Compare commits

..

No commits in common. "734a00ea92e596716f0e5d38b42205c9e40bd2b1" and "f656d0d4d4e14748915807c3b329b507cb69bcc6" have entirely different histories.

20 changed files with 998 additions and 1273 deletions

View File

@ -135,7 +135,6 @@ fn generate_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
use std::rc::Rc; use std::rc::Rc;
use std::cell::RefCell; use std::cell::RefCell;
use crate::name_analysis::symbol::*; use crate::name_analysis::symbol::*;
use crate::type_analysis::kinds::*;
#(#types)* #(#types)*
}; };

View File

@ -1,12 +1,7 @@
use crate::asm::{ use crate::asm::{AsmBinaryOperator, AsmFunction, AsmInstruction, AsmOperand, ControlUnit, ControlUnitId, VirtualRegisterId};
AsmBinaryOperator, AsmFunction, AsmInstruction, AsmOperand, ControlUnit, ControlUnitId, use crate::ir::{IrAssign, IrBinaryOperation, IrBinaryOperator, IrCall, IrCallType, IrExpression, IrFunction, IrLiteral, IrReturn, IrStatement};
VirtualRegisterId,
};
use crate::ir::{
IrAssign, IrBinaryOperation, IrBinaryOperator, IrCall, IrCallType, IrExpression, IrFunction,
IrLiteral, IrReturn, IrStatement,
};
use std::collections::HashMap; use std::collections::HashMap;
use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
struct AssemblyContext { struct AssemblyContext {
@ -86,7 +81,7 @@ pub fn assemble_ir_function(ir_function: &IrFunction) -> AsmFunction {
assemble_ir_statement(statement, &mut context); assemble_ir_statement(statement, &mut context);
} }
AsmFunction::new(ir_function.fqn().into(), context.into_control_units()) AsmFunction::new(ir_function.name().into(), context.into_control_units())
} }
fn assemble_ir_statement(ir_statement: &IrStatement, context: &mut AssemblyContext) { fn assemble_ir_statement(ir_statement: &IrStatement, context: &mut AssemblyContext) {
@ -118,6 +113,9 @@ fn assemble_ir_assign(ir_assign: &IrAssign, context: &mut AssemblyContext) {
let virtual_register_id = context.get_virtual_register(ir_variable.name()); let virtual_register_id = context.get_virtual_register(ir_variable.name());
AsmOperand::VirtualRegister(virtual_register_id) AsmOperand::VirtualRegister(virtual_register_id)
} }
IrExpression::ConstRef(ir_const_ref) => AsmOperand::Constant {
name: ir_const_ref.name_owned(),
},
IrExpression::Literal(ir_literal) => ir_literal_to_asm_operand(ir_literal), IrExpression::Literal(ir_literal) => ir_literal_to_asm_operand(ir_literal),
}; };
let destination = context.next_virtual_register(ir_assign.lhs().name()); let destination = context.next_virtual_register(ir_assign.lhs().name());
@ -146,7 +144,6 @@ fn ir_literal_to_asm_operand(ir_literal: &IrLiteral) -> AsmOperand {
IrLiteral::Boolean(b) => AsmOperand::Boolean(*b), IrLiteral::Boolean(b) => AsmOperand::Boolean(*b),
IrLiteral::Float(f) => AsmOperand::Float(*f), IrLiteral::Float(f) => AsmOperand::Float(*f),
IrLiteral::Double(d) => AsmOperand::Double(*d), IrLiteral::Double(d) => AsmOperand::Double(*d),
IrLiteral::String(s) => AsmOperand::String(s.clone()),
} }
} }
@ -162,6 +159,13 @@ fn assemble_ir_call(ir_call: &IrCall, context: &mut AssemblyContext) {
source: AsmOperand::VirtualRegister(variable_register_id), source: AsmOperand::VirtualRegister(variable_register_id),
}) })
} }
IrExpression::ConstRef(ir_const_ref) => context
.current_control_unit_mut()
.append_instruction(AsmInstruction::Push {
source: AsmOperand::Constant {
name: ir_const_ref.name_owned(),
},
}),
IrExpression::Literal(ir_literal) => context IrExpression::Literal(ir_literal) => context
.current_control_unit_mut() .current_control_unit_mut()
.append_instruction(AsmInstruction::Push { .append_instruction(AsmInstruction::Push {
@ -185,60 +189,72 @@ fn assemble_ir_call(ir_call: &IrCall, context: &mut AssemblyContext) {
fqn: ir_call.function_name_owned(), fqn: ir_call.function_name_owned(),
}) })
} }
IrCallType::PlatformStatic => {}
IrCallType::PlatformObject => {}
} }
} }
fn assemble_ir_return(ir_return: &IrReturn, context: &mut AssemblyContext) { fn assemble_ir_return(ir_return: &IrReturn, context: &mut AssemblyContext) {
let operand = ir_return.expression().map(|expression| { let operand = match ir_return.expression() {
match expression { IrExpression::Variable(ir_variable) => {
IrExpression::Variable(ir_variable) => { let variable_virtual_register_id = context.get_virtual_register(ir_variable.name());
let variable_virtual_register_id = context.get_virtual_register(ir_variable.name()); AsmOperand::VirtualRegister(variable_virtual_register_id)
AsmOperand::VirtualRegister(variable_virtual_register_id)
}
IrExpression::Literal(ir_literal) => ir_literal_to_asm_operand(ir_literal),
} }
}); IrExpression::ConstRef(ir_const_ref) => AsmOperand::Constant {
name: ir_const_ref.name_owned(),
},
IrExpression::Literal(ir_literal) => ir_literal_to_asm_operand(ir_literal),
};
context context
.current_control_unit_mut() .current_control_unit_mut()
.append_instruction(AsmInstruction::Return { operand }); .append_instruction(AsmInstruction::Return { operand });
} }
fn assemble_ir_binary_operation( fn assemble_ir_binary_operation(ir_binary_operation: &IrBinaryOperation, context: &mut AssemblyContext) {
ir_binary_operation: &IrBinaryOperation,
context: &mut AssemblyContext,
) {
let left = match ir_binary_operation.left() { let left = match ir_binary_operation.left() {
IrExpression::Variable(ir_variable) => { IrExpression::Variable(ir_variable) => {
AsmOperand::VirtualRegister(context.get_virtual_register(ir_variable.name())) AsmOperand::VirtualRegister(context.get_virtual_register(ir_variable.name()))
} }
IrExpression::Literal(ir_literal) => ir_literal_to_asm_operand(ir_literal), IrExpression::ConstRef(ir_const_ref) => {
unreachable!("Cannot assemble binary operation with a lhs IrConstRef")
}
IrExpression::Literal(ir_literal) => {
ir_literal_to_asm_operand(ir_literal)
}
}; };
let right = match ir_binary_operation.right() { let right = match ir_binary_operation.right() {
IrExpression::Variable(ir_variable) => { IrExpression::Variable(ir_variable) => {
AsmOperand::VirtualRegister(context.get_virtual_register(ir_variable.name())) AsmOperand::VirtualRegister(context.get_virtual_register(ir_variable.name()))
},
IrExpression::ConstRef(ir_const_ref) => {
unreachable!("Cannot assemble binary operation with a rhs IrConstRef")
}
IrExpression::Literal(ir_literal) => {
ir_literal_to_asm_operand(ir_literal)
} }
IrExpression::Literal(ir_literal) => ir_literal_to_asm_operand(ir_literal),
}; };
let destination = context.next_virtual_register(ir_binary_operation.destination().name()); let destination = context.next_virtual_register(ir_binary_operation.destination().name());
let operator = match ir_binary_operation.operator() { let operator = match ir_binary_operation.operator() {
IrBinaryOperator::Add => AsmBinaryOperator::Add, IrBinaryOperator::Add => {
IrBinaryOperator::Subtract => AsmBinaryOperator::Subtract, AsmBinaryOperator::Add
IrBinaryOperator::Multiply => AsmBinaryOperator::Multiply, }
IrBinaryOperator::Divide => AsmBinaryOperator::Divide, IrBinaryOperator::Subtract => {
AsmBinaryOperator::Subtract
}
IrBinaryOperator::Multiply => {
AsmBinaryOperator::Multiply
}
IrBinaryOperator::Divide => {
AsmBinaryOperator::Divide
}
IrBinaryOperator::Exponent => { IrBinaryOperator::Exponent => {
todo!() todo!()
} }
}; };
let instruction = AsmInstruction::BinaryOperation { let instruction = AsmInstruction::BinaryOperation {
destination, destination,
left, left,
right, right,
operator, operator
}; };
context context.current_control_unit_mut().append_instruction(instruction);
.current_control_unit_mut() }
.append_instruction(instruction);
}

View File

@ -79,14 +79,8 @@ pub enum AsmInstruction {
InvokeObject { InvokeObject {
fqn: Rc<str>, fqn: Rc<str>,
}, },
InvokePlatformStatic {
fqn: Rc<str>,
},
InvokePlatformObject {
fqn: Rc<str>,
},
Return { Return {
operand: Option<AsmOperand>, operand: AsmOperand,
}, },
BinaryOperation { BinaryOperation {
destination: VirtualRegisterId, destination: VirtualRegisterId,
@ -126,18 +120,8 @@ impl Display for AsmInstruction {
AsmInstruction::InvokeObject { fqn } => { AsmInstruction::InvokeObject { fqn } => {
write!(f, "invoke_object {}", fqn) write!(f, "invoke_object {}", fqn)
} }
AsmInstruction::InvokePlatformStatic { fqn } => {
write!(f, "invoke_platform_static {}", fqn)
}
AsmInstruction::InvokePlatformObject { fqn } => {
write!(f, "invoke_platform_object {}", fqn)
}
AsmInstruction::Return { operand } => { AsmInstruction::Return { operand } => {
write!(f, "return")?; write!(f, "return {}", operand)
if let Some(operand) = operand {
write!(f, " {}", operand)?;
}
Ok(())
} }
AsmInstruction::BinaryOperation { AsmInstruction::BinaryOperation {
destination, destination,
@ -167,7 +151,7 @@ pub enum AsmOperand {
Float(f32), Float(f32),
Double(f64), Double(f64),
Boolean(bool), Boolean(bool),
String(Rc<str>), Constant { name: Rc<str> },
VirtualRegister(VirtualRegisterId), VirtualRegister(VirtualRegisterId),
} }
@ -219,8 +203,8 @@ impl Display for AsmOperand {
AsmOperand::Boolean(b) => { AsmOperand::Boolean(b) => {
write!(f, "{}", b) write!(f, "{}", b)
} }
AsmOperand::String(s) => { AsmOperand::Constant { name } => {
write!(f, "{}", s) write!(f, "<{}>", name)
} }
AsmOperand::VirtualRegister(id) => { AsmOperand::VirtualRegister(id) => {
write!(f, "vr{}", id) write!(f, "vr{}", id)

View File

@ -30,81 +30,6 @@ pub mod node {
} }
} }
} }
impl Expression {
pub fn analyzed_kind(&self) -> Kind {
match self {
Expression::Ternary(ternary_expression) => {
todo!()
}
Expression::Or(or_expression) => {todo!()}
Expression::And(and_expression) => {
todo!()
}
Expression::Comparison(comparison_expression) => {
todo!()
}
Expression::Shift(shift_expression) => {
todo!()
}
Expression::Additive(additive_expression) => {
todo!()
}
Expression::Multiplicative(multiplicative_expression) => {
todo!()
}
Expression::Prefix(prefix_expression) => {
todo!()
}
Expression::Suffix(suffix_expression) => {
todo!()
}
Expression::Literal(literal) => {
literal.analyzed_kind()
}
Expression::Identifier(identifier) => {
identifier.analyzed_kind().expect("IdentifierExpression's analyzed_kind not set.").clone()
}
Expression::Fqn(fqn) => {
todo!()
}
Expression::Closure(closure) => {
todo!()
}
Expression::List(list_expression) => {
todo!()
}
}
}
}
impl Literal {
pub fn analyzed_kind(&self) -> Kind {
match self {
Literal::IntLiteral(_) => {
Kind::Primitive(PrimitiveKind::Int.into())
}
Literal::LongLiteral(_) => {
Kind::Primitive(PrimitiveKind::Long.into())
}
Literal::DoubleLiteral(_) => {
Kind::Primitive(PrimitiveKind::Double.into())
}
Literal::SingleQuoteString(_) => {
Kind::Primitive(PrimitiveKind::String.into())
}
Literal::DString(_) => {
todo!()
}
Literal::BacktickString(_) => {
todo!()
}
Literal::BooleanLiteral(_) => {
Kind::Primitive(PrimitiveKind::Boolean.into())
}
}
}
}
impl Default for Parameters { impl Default for Parameters {
fn default() -> Self { fn default() -> Self {

View File

@ -3,25 +3,22 @@ use deimos::asm::assemble_ir::assemble_ir_function;
use deimos::ast::node::CompilationUnit; use deimos::ast::node::CompilationUnit;
use deimos::ir::lower_ast::lower_compilation_unit; use deimos::ir::lower_ast::lower_compilation_unit;
use deimos::ir::Ir; use deimos::ir::Ir;
use deimos::type_analysis::analyze_types; use deimos::util::indent_writer::IndentWriter;
use std::path::PathBuf; use std::path::PathBuf;
pub fn compile_to_ir( pub fn compile_to_ir(
paths: &[PathBuf], paths: &[PathBuf],
) -> Result<Vec<CompilationUnit>, Box<dyn std::error::Error>> { ) -> Result<Vec<CompilationUnit>, Box<dyn std::error::Error>> {
let mut compilation_units = name_analysis(&paths)?; let compilation_units = name_analysis(&paths)?;
let type_diagnostics = analyze_types(&mut compilation_units);
if !type_diagnostics.is_empty() {
eprintln!("There were type diagnostics")
}
for compilation_unit in &compilation_units { for compilation_unit in &compilation_units {
let cu_irs = lower_compilation_unit(compilation_unit); let cu_irs = lower_compilation_unit(compilation_unit);
let mut out = String::new();
let mut indent_writer = IndentWriter::new(0, " ", &mut out);
for ir in &cu_irs { for ir in &cu_irs {
println!("{}", ir) ir.pretty_print(&mut indent_writer)?;
} }
println!("{}", &out);
for ir in &cu_irs { for ir in &cu_irs {
match ir { match ir {

View File

@ -1,139 +1,119 @@
use crate::ast::node::{ use crate::ast::node::{AdditiveExpression, AdditiveOperator, Call, Closure, CompilationUnit, Expression, ExpressionList, ExpressionStatement, Function, FunctionBlockBody, FunctionBody, Identifier, Literal, ModuleLevelDeclaration, Statement, SuffixExpression, SuffixOperator, VariableDeclaration};
AdditiveExpression, AdditiveOperator, Call, CompilationUnit, Expression, ExpressionStatement,
Function, FunctionBlockBody, FunctionBody, FunctionEqualsBody, Literal, Module,
ModuleLevelDeclaration, Statement, SuffixExpression, SuffixOperator, VariableDeclaration,
};
use crate::ir::{ use crate::ir::{
Ir, IrAssign, IrBinaryOperation, IrBinaryOperator, IrExpression, IrFunction, IrKind, IrLiteral, Ir, IrAssign, IrBinaryOperation, IrBinaryOperator, IrCall, IrCallType, IrConst, IrExpression,
IrPrimitiveKind, IrReturn, IrStatement, IrStructKind, IrVariable, IrFunction, IrKind, IrLiteral, IrPrimitiveKind, IrStatement, IrVariable,
};
use crate::name_analysis::symbol::{
ExpressibleSymbol, ParameterSymbol, PrimitiveTypeSymbol, TypeSymbol,
}; };
use crate::name_analysis::symbol::{ClassSymbol, ParameterSymbol, PrimitiveTypeSymbol, TypeSymbol};
use std::cell::RefCell; use std::cell::RefCell;
use std::ops::Deref; use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
use crate::type_analysis::kinds::Kind; use crate::ir::IrStatement::BinaryOperation;
struct CuContext {
irs: Vec<Ir>,
}
impl CuContext {
pub fn new() -> Self {
Self { irs: vec![] }
}
pub fn push_ir(&mut self, ir: Ir) {
self.irs.push(ir);
}
pub fn into_irs(self) -> Vec<Ir> {
self.irs
}
}
pub fn lower_compilation_unit(compilation_unit: &CompilationUnit) -> Vec<Ir> { pub fn lower_compilation_unit(compilation_unit: &CompilationUnit) -> Vec<Ir> {
let mut context = CuContext::new(); let mut result: Vec<Ir> = vec![];
for declaration in compilation_unit.module_level_declarations() { for declaration in compilation_unit.module_level_declarations() {
lower_module_level_declaration(declaration, &mut context); result.append(&mut lower_module_level_declaration(declaration));
} }
context.into_irs() result
} }
fn lower_module_level_declaration( fn lower_module_level_declaration(declaration: &ModuleLevelDeclaration) -> Vec<Ir> {
module_level_declaration: &ModuleLevelDeclaration, match declaration {
cu_context: &mut CuContext, ModuleLevelDeclaration::Module(module) => {
) { todo!()
match module_level_declaration { }
ModuleLevelDeclaration::Module(module) => lower_module(module, cu_context),
ModuleLevelDeclaration::Interface(interface) => { ModuleLevelDeclaration::Interface(interface) => {
todo!() todo!()
} }
ModuleLevelDeclaration::Class(class) => { ModuleLevelDeclaration::Class(class) => {
todo!() todo!()
} }
ModuleLevelDeclaration::Function(function) => lower_function(function, cu_context), ModuleLevelDeclaration::Function(function) => lower_function(function),
ModuleLevelDeclaration::PlatformFunction(platform_function) => { ModuleLevelDeclaration::PlatformFunction(platform_function) => {
todo!() todo!()
} }
} }
} }
fn lower_module(module: &Module, cu_context: &mut CuContext) { pub struct LocalsTable {
for declaration in module.declarations() { t_count: usize,
lower_module_level_declaration(declaration, cu_context); stack_slot_count: usize,
} stack_slots: HashMap<IrVariable, usize>,
} }
struct FnContext { impl LocalsTable {
t_var_count: usize, pub fn new() -> Self {
statements: Vec<IrStatement>,
return_type: Option<TypeSymbol>,
}
impl FnContext {
pub fn new(return_type: Option<TypeSymbol>) -> Self {
Self { Self {
t_var_count: 0, t_count: 0,
statements: vec![], stack_slot_count: 0,
return_type, stack_slots: HashMap::new(),
} }
} }
pub fn next_t_var(&mut self) -> String { pub fn next_t_var(&mut self) -> IrVariable {
let t_var = format!("__t{}", self.t_var_count); let t_num = self.t_count;
self.t_var_count += 1; self.t_count += 1;
let t_name = format!("__t{}", t_num);
let t_var = IrVariable::new(&t_name);
self.register_stack_local(&t_var);
t_var t_var
} }
pub fn push_statement(&mut self, statement: IrStatement) { pub fn register_stack_local(&mut self, ir_variable: &IrVariable) {
self.statements.push(statement); let stack_slot = self.stack_slot_count;
self.stack_slot_count += 1;
self.stack_slots.insert(ir_variable.clone(), stack_slot);
} }
pub fn into_statements(self) -> Vec<IrStatement> { pub fn get_stack_slot(&self, ir_variable: &IrVariable) -> usize {
self.statements *self.stack_slots.get(ir_variable).unwrap()
}
pub fn return_type(&self) -> Option<&TypeSymbol> {
self.return_type.as_ref()
} }
} }
fn lower_function(function: &Function, cu_context: &mut CuContext) { fn lower_function(function: &Function) -> Vec<Ir> {
let function_symbol = function.function_symbol().unwrap().borrow(); let function_symbol = function.function_symbol().unwrap().borrow();
let fqn = function_symbol.fqn_formatted(); let name = function_symbol.fqn_parts_owned().join("::");
let parameters = parameter_symbols_to_ir_kinds(function_symbol.parameter_symbols()); let parameters = lower_parameter_symbols(function_symbol.parameter_symbols());
let return_type = type_symbol_to_ir_kind(function_symbol.return_type().unwrap()); let return_type = lower_type_symbol(function_symbol.return_type().unwrap());
let mut fn_context = FnContext::new(function_symbol.return_type_owned()); let mut locals_table = LocalsTable::new();
lower_function_body(function.function_body(), &mut fn_context); let (statements, consts) = lower_function_body(function.function_body(), &mut locals_table);
let ir_function = IrFunction::new(
&fqn, let mut result: Vec<Ir> = vec![];
function_symbol.is_public(), result.push(Ir::Function(Box::new(IrFunction::new(
name,
parameters, parameters,
return_type, Box::new(return_type),
fn_context.into_statements(), statements,
Box::new(locals_table),
))));
result.append(
&mut consts
.into_iter()
.map(|constant| Ir::Const(Box::new(constant)))
.collect(),
); );
cu_context.push_ir(Ir::Function(ir_function.into())); result
} }
fn parameter_symbols_to_ir_kinds( fn lower_parameter_symbols(parameter_symbols: &[Rc<RefCell<ParameterSymbol>>]) -> Vec<IrKind> {
parameter_symbols: &[Rc<RefCell<ParameterSymbol>>],
) -> Vec<IrKind> {
parameter_symbols parameter_symbols
.iter() .iter()
.map(|parameter_symbol_rc| parameter_symbol_rc.borrow()) .map(|parameter_symbol_rc| parameter_symbol_rc.borrow())
.map(|parameter_symbol_ref| { .map(|parameter_symbol| lower_type_symbol(parameter_symbol.type_symbol().unwrap()))
type_symbol_to_ir_kind(parameter_symbol_ref.type_symbol().unwrap())
})
.collect() .collect()
} }
fn type_symbol_to_ir_kind(type_symbol: &TypeSymbol) -> IrKind { fn lower_type_symbol(type_symbol: &TypeSymbol) -> IrKind {
match type_symbol { match type_symbol {
TypeSymbol::Primitive(primitive_type_symbol) => { TypeSymbol::Primitive(primitive_type_symbol) => {
primitive_type_symbol_to_ir_kind(primitive_type_symbol) lower_primitive_type_symbol(primitive_type_symbol)
}
TypeSymbol::Class(class_type_symbol) => {
todo!()
} }
TypeSymbol::Class(class_symbol) => class_symbol_to_ir_kind(class_symbol.borrow().deref()),
TypeSymbol::Interface(interface_type_symbol) => { TypeSymbol::Interface(interface_type_symbol) => {
todo!() todo!()
} }
@ -143,7 +123,7 @@ fn type_symbol_to_ir_kind(type_symbol: &TypeSymbol) -> IrKind {
} }
} }
fn primitive_type_symbol_to_ir_kind(primitive_type_symbol: &PrimitiveTypeSymbol) -> IrKind { fn lower_primitive_type_symbol(primitive_type_symbol: &PrimitiveTypeSymbol) -> IrKind {
IrKind::Primitive(Box::new(match primitive_type_symbol { IrKind::Primitive(Box::new(match primitive_type_symbol {
PrimitiveTypeSymbol::Byte => IrPrimitiveKind::I8, PrimitiveTypeSymbol::Byte => IrPrimitiveKind::I8,
PrimitiveTypeSymbol::Char => IrPrimitiveKind::I8, PrimitiveTypeSymbol::Char => IrPrimitiveKind::I8,
@ -154,54 +134,59 @@ fn primitive_type_symbol_to_ir_kind(primitive_type_symbol: &PrimitiveTypeSymbol)
PrimitiveTypeSymbol::Double => IrPrimitiveKind::Double, PrimitiveTypeSymbol::Double => IrPrimitiveKind::Double,
PrimitiveTypeSymbol::Boolean => IrPrimitiveKind::Boolean, PrimitiveTypeSymbol::Boolean => IrPrimitiveKind::Boolean,
PrimitiveTypeSymbol::String => IrPrimitiveKind::String, PrimitiveTypeSymbol::String => IrPrimitiveKind::String,
PrimitiveTypeSymbol::TypedArray { inner_type } => IrPrimitiveKind::Array(Box::new( PrimitiveTypeSymbol::TypedArray { inner_type } => {
type_symbol_to_ir_kind(inner_type.as_ref().unwrap()), IrPrimitiveKind::Array(Box::new(lower_type_symbol(inner_type.as_ref().unwrap())))
)), }
PrimitiveTypeSymbol::Any => IrPrimitiveKind::Any, PrimitiveTypeSymbol::Any => {
todo!()
}
PrimitiveTypeSymbol::Void => IrPrimitiveKind::Void, PrimitiveTypeSymbol::Void => IrPrimitiveKind::Void,
})) }))
} }
fn class_symbol_to_ir_kind(class_type_symbol: &ClassSymbol) -> IrKind { fn lower_function_body(
let struct_kind = IrStructKind::new(&class_type_symbol.fqn_formatted()); function_body: &FunctionBody,
IrKind::Struct(struct_kind.into()) locals_table: &mut LocalsTable,
} ) -> (Vec<IrStatement>, Vec<IrConst>) {
fn lower_function_body(function_body: &FunctionBody, fn_context: &mut FnContext) {
match function_body { match function_body {
FunctionBody::FunctionAliasBody(alias_body) => { FunctionBody::FunctionAliasBody(alias_body) => {
todo!() todo!()
} }
FunctionBody::FunctionEqualsBody(equals_body) => { FunctionBody::FunctionEqualsBody(equals_body) => {
lower_function_equals_body(equals_body, fn_context); todo!()
} }
FunctionBody::FunctionBlockBody(block_body) => { FunctionBody::FunctionBlockBody(block_body) => {
lower_function_block_body(block_body, fn_context); lower_function_block_body(block_body, locals_table)
} }
} }
} }
fn lower_function_equals_body(body: &FunctionEqualsBody, fn_context: &mut FnContext) { fn lower_function_block_body(
todo!() body: &FunctionBlockBody,
} locals_table: &mut LocalsTable,
) -> (Vec<IrStatement>, Vec<IrConst>) {
fn lower_function_block_body(body: &FunctionBlockBody, fn_context: &mut FnContext) { let mut statements: Vec<IrStatement> = vec![];
let statement_count = body.statements().count(); let mut consts: Vec<IrConst> = vec![];
for (i, statement) in body.statements().enumerate() { for statement in body.statements() {
lower_statement(statement, fn_context, i == statement_count - 1); statements.append(&mut lower_statement(statement, &mut consts, locals_table));
} }
(statements, consts)
} }
fn lower_statement(statement: &Statement, fn_context: &mut FnContext, is_last: bool) { fn lower_statement(
statement: &Statement,
consts_pool: &mut Vec<IrConst>,
locals_table: &mut LocalsTable,
) -> Vec<IrStatement> {
match statement { match statement {
Statement::VariableDeclaration(variable_declaration) => { Statement::VariableDeclaration(variable_declaration) => {
lower_variable_declaration(variable_declaration, fn_context) lower_variable_declaration(variable_declaration, consts_pool, locals_table)
} }
Statement::AssignmentStatement(assignment_statement) => { Statement::AssignmentStatement(assignment_statement) => {
todo!() todo!()
} }
Statement::ExpressionStatement(expression_statement) => { Statement::ExpressionStatement(expression_statement) => {
lower_expression_statement(expression_statement, fn_context, is_last) lower_expression_statement(expression_statement, consts_pool, locals_table)
} }
Statement::UseStatement(use_statement) => { Statement::UseStatement(use_statement) => {
todo!() todo!()
@ -220,49 +205,192 @@ fn lower_statement(statement: &Statement, fn_context: &mut FnContext, is_last: b
fn lower_variable_declaration( fn lower_variable_declaration(
variable_declaration: &VariableDeclaration, variable_declaration: &VariableDeclaration,
fn_context: &mut FnContext, consts_pool: &mut Vec<IrConst>,
) { locals_table: &mut LocalsTable,
let initializer = match variable_declaration.expression() { ) -> Vec<IrStatement> {
Expression::Literal(literal) => literal_to_ir_expression(literal), let mut result: Vec<IrStatement> = vec![];
Expression::Identifier(identifier_expression) => IrExpression::Variable( let expression_t_var = lower_expression(
IrVariable::new(identifier_expression.identifier().name()).into(), variable_declaration.expression().unwrap(),
), &mut result,
Expression::Fqn(fqn) => { consts_pool,
todo!("Fqn as expressions") locals_table,
} );
_ => expression_to_ir_expression(variable_declaration.expression(), fn_context), let target = IrVariable::new(variable_declaration.identifier().name());
}; locals_table.register_stack_local(&target);
let assign_stmt = IrAssign::new(
let result_variable = IrVariable::new(variable_declaration.identifier().name()); Box::new(target),
let ir_assign = IrAssign::new(result_variable, initializer); Box::new(IrExpression::Variable(Box::new(expression_t_var))),
fn_context.push_statement(IrStatement::Assign(ir_assign.into())); );
result.push(IrStatement::Assign(assign_stmt));
result
} }
fn literal_to_ir_expression(literal: &Literal) -> IrExpression { fn lower_expression_statement(
match literal { expression_statement: &ExpressionStatement,
Literal::IntLiteral(i) => IrExpression::Literal(IrLiteral::I32(*i).into()), consts_pool: &mut Vec<IrConst>,
Literal::LongLiteral(l) => IrExpression::Literal(IrLiteral::I64(*l).into()), locals_table: &mut LocalsTable,
Literal::DoubleLiteral(d) => IrExpression::Literal(IrLiteral::Double(*d).into()), ) -> Vec<IrStatement> {
Literal::SingleQuoteString(s) => { let mut result: Vec<IrStatement> = vec![];
IrExpression::Literal(IrLiteral::String(Rc::from(s.as_ref())).into()) lower_expression(
} expression_statement.expression(),
Literal::DString(d_string) => todo!(), &mut result,
Literal::BacktickString(backtick_string) => { consts_pool,
locals_table,
);
result
}
fn lower_expression(
expression: &Expression,
target: &mut Vec<IrStatement>,
consts_pool: &mut Vec<IrConst>,
locals_table: &mut LocalsTable,
) -> IrVariable {
match expression {
Expression::Ternary(ternary) => {
todo!()
}
Expression::Or(or) => {
todo!()
}
Expression::And(and) => {
todo!()
}
Expression::Comparison(comparison) => {
todo!()
}
Expression::Shift(shift) => {
todo!()
}
Expression::Additive(additive) => {
lower_additive_expression(additive, target, consts_pool, locals_table)
}
Expression::Multiplicative(multiplicative) => {
todo!()
}
Expression::Prefix(prefix) => {
todo!()
}
Expression::Suffix(suffix) => {
lower_suffix_expression(suffix, target, consts_pool, locals_table)
}
Expression::Literal(literal) => lower_literal(literal, target, consts_pool, locals_table),
Expression::Identifier(identifier_expression) => lower_identifier(
identifier_expression.identifier(),
target,
consts_pool,
locals_table,
),
Expression::Fqn(fqn) => {
todo!()
}
Expression::Closure(closure) => {
todo!()
}
Expression::List(list) => {
todo!() todo!()
} }
Literal::BooleanLiteral(b) => IrExpression::Literal(IrLiteral::Boolean(*b).into()),
} }
} }
fn expression_to_ir_expression( fn lower_suffix_expression(
expression: &Expression, suffix_expression: &SuffixExpression,
fn_context: &mut FnContext, target: &mut Vec<IrStatement>,
) -> IrExpression { consts_pool: &mut Vec<IrConst>,
IrExpression::Variable(expression_into_ir_variable(expression, fn_context).into()) locals_table: &mut LocalsTable,
) -> IrVariable {
let receiver_variable = lower_expression(
suffix_expression.expression(),
target,
consts_pool,
locals_table,
);
match suffix_expression.operator() {
SuffixOperator::PlusPlus => {
let result_var = locals_table.next_t_var();
let operation = IrBinaryOperation::new(
result_var.clone(),
IrExpression::Variable(receiver_variable.into()),
IrExpression::Literal(IrLiteral::I32(1).into()),
IrBinaryOperator::Add,
);
target.push(IrStatement::BinaryOperation(operation));
result_var
}
SuffixOperator::MinusMinus => {
let result_var = locals_table.next_t_var();
let operation = IrBinaryOperation::new(
result_var.clone(),
IrExpression::Variable(receiver_variable.into()),
IrExpression::Literal(IrLiteral::I32(1).into()),
IrBinaryOperator::Subtract,
);
target.push(IrStatement::BinaryOperation(operation));
result_var
}
SuffixOperator::ObjectIndex(object_index) => {
todo!()
}
SuffixOperator::Call(call) => lower_call(
call,
suffix_expression.expression(),
target,
consts_pool,
locals_table,
),
SuffixOperator::ObjectProperty(object_property) => {
todo!()
}
}
} }
fn expression_into_ir_variable(expression: &Expression, fn_context: &mut FnContext) -> IrVariable { fn lower_literal(
match expression { literal: &Literal,
statements: &mut Vec<IrStatement>,
consts_pool: &mut Vec<IrConst>,
locals_table: &mut LocalsTable,
) -> IrVariable {
match literal {
Literal::IntLiteral(int_literal) => {
let t_var = locals_table.next_t_var();
let assign_stmt = IrAssign::new(
Box::new(t_var.clone()),
Box::new(IrExpression::Literal(Box::new(IrLiteral::I32(
*int_literal,
)))),
);
statements.push(IrStatement::Assign(assign_stmt));
t_var
}
Literal::LongLiteral(long_literal) => {
todo!()
}
Literal::DoubleLiteral(double_literal) => {
todo!()
}
Literal::SingleQuoteString(sq_string) => {
todo!()
}
Literal::DString(d_string) => {
todo!()
}
Literal::BacktickString(b_string) => {
todo!()
}
Literal::BooleanLiteral(boolean_literal) => {
todo!()
}
}
}
fn lower_call(
call: &Call,
receiver: &Expression,
target: &mut Vec<IrStatement>,
consts_pool: &mut Vec<IrConst>,
locals_table: &mut LocalsTable,
) -> IrVariable {
let fqn = match receiver {
Expression::Ternary(_) => { Expression::Ternary(_) => {
todo!() todo!()
} }
@ -278,8 +406,8 @@ fn expression_into_ir_variable(expression: &Expression, fn_context: &mut FnConte
Expression::Shift(_) => { Expression::Shift(_) => {
todo!() todo!()
} }
Expression::Additive(additive_expression) => { Expression::Additive(_) => {
additive_expression_into_ir_variable(additive_expression, fn_context) todo!()
} }
Expression::Multiplicative(_) => { Expression::Multiplicative(_) => {
todo!() todo!()
@ -287,22 +415,33 @@ fn expression_into_ir_variable(expression: &Expression, fn_context: &mut FnConte
Expression::Prefix(_) => { Expression::Prefix(_) => {
todo!() todo!()
} }
Expression::Suffix(suffix_expression) => { Expression::Suffix(_) => {
suffix_expression_into_ir_variable(suffix_expression, fn_context) todo!()
} }
Expression::Literal(literal) => { Expression::Literal(_) => {
let literal_as_ir_expression = literal_to_ir_expression(literal); todo!()
let t_var_name = fn_context.next_t_var();
let t_var_ir_variable = IrVariable::new(&t_var_name);
let ir_assign = IrAssign::new(t_var_ir_variable.clone(), literal_as_ir_expression);
fn_context.push_statement(IrStatement::Assign(ir_assign.into()));
t_var_ir_variable
} }
Expression::Identifier(identifier_expression) => { Expression::Identifier(identifier_expression) => {
IrVariable::new(identifier_expression.identifier().name()) match identifier_expression.expressible_symbol().unwrap() {
ExpressibleSymbol::Class(class_symbol) => {
todo!()
}
ExpressibleSymbol::Function(function_symbol) => {
function_symbol.borrow().fqn_formatted()
}
ExpressibleSymbol::ClassMember(class_member_symbol) => {
todo!()
}
ExpressibleSymbol::Parameter(parameter_symbol) => {
todo!()
}
ExpressibleSymbol::Variable(variable_symbol) => {
todo!()
}
}
} }
Expression::Fqn(_) => { Expression::Fqn(fqn) => {
todo!("Fqn as expression") todo!()
} }
Expression::Closure(_) => { Expression::Closure(_) => {
todo!() todo!()
@ -310,134 +449,221 @@ fn expression_into_ir_variable(expression: &Expression, fn_context: &mut FnConte
Expression::List(_) => { Expression::List(_) => {
todo!() todo!()
} }
}
}
fn additive_expression_into_ir_variable(
additive_expression: &AdditiveExpression,
fn_context: &mut FnContext,
) -> IrVariable {
let left = expression_to_ir_expression(additive_expression.left(), fn_context);
let right = expression_to_ir_expression(additive_expression.rhs().expression(), fn_context);
let operator = match additive_expression.rhs().operator() {
AdditiveOperator::Add => IrBinaryOperator::Add,
AdditiveOperator::Subtract => IrBinaryOperator::Subtract,
}; };
let result_variable_name = fn_context.next_t_var(); let declared_type = match receiver {
let result_ir_variable = IrVariable::new(&result_variable_name); Expression::Ternary(_) => {
let add_op = IrBinaryOperation::new(result_ir_variable.clone(), left, right, operator);
fn_context.push_statement(IrStatement::BinaryOperation(add_op.into()));
result_ir_variable
}
fn suffix_expression_into_ir_variable(
suffix_expression: &SuffixExpression,
fn_context: &mut FnContext,
) -> IrVariable {
match suffix_expression.operator() {
SuffixOperator::PlusPlus => {
let result_variable_name = fn_context.next_t_var();
let result_ir_variable = IrVariable::new(&result_variable_name);
let plus_plus_op = IrBinaryOperation::new(
result_ir_variable.clone(),
expression_to_ir_expression(suffix_expression.expression(), fn_context),
IrExpression::Literal(IrLiteral::I32(1).into()),
IrBinaryOperator::Add,
);
fn_context.push_statement(IrStatement::BinaryOperation(plus_plus_op.into()));
result_ir_variable
}
SuffixOperator::MinusMinus => {
let result_variable_name = fn_context.next_t_var();
let result_ir_variable = IrVariable::new(&result_variable_name);
let plus_plus_op = IrBinaryOperation::new(
result_ir_variable.clone(),
expression_to_ir_expression(suffix_expression.expression(), fn_context),
IrExpression::Literal(IrLiteral::I32(1).into()),
IrBinaryOperator::Subtract, // n.b.
);
fn_context.push_statement(IrStatement::BinaryOperation(plus_plus_op.into()));
result_ir_variable
}
SuffixOperator::ObjectIndex(object_index) => {
todo!("Object indexing")
}
SuffixOperator::Call(call) => {
todo!() todo!()
} }
SuffixOperator::ObjectProperty(object_property) => { Expression::Or(_) => {
todo!() todo!()
} }
} Expression::And(_) => {
} todo!()
}
fn lower_expression_statement( Expression::Comparison(_) => {
expression_statement: &ExpressionStatement, todo!()
fn_context: &mut FnContext, }
is_last: bool, Expression::Shift(_) => {
) { todo!()
let is_void_return = if let Some(return_type_symbol) = fn_context.return_type() { }
match return_type_symbol { Expression::Additive(_) => {
TypeSymbol::Primitive(primitive_type_symbol) => match primitive_type_symbol { todo!()
PrimitiveTypeSymbol::Void => true, }
_ => false, Expression::Multiplicative(_) => {
}, todo!()
_ => false, }
Expression::Prefix(_) => {
todo!()
}
Expression::Suffix(_) => {
todo!()
}
Expression::Literal(_) => {
todo!()
}
Expression::Identifier(identifier_expression) => {
match identifier_expression.expressible_symbol().unwrap() {
ExpressibleSymbol::Class(_) => {
todo!()
}
ExpressibleSymbol::Function(function_symbol) => {
match function_symbol.borrow().return_type().expect(&format!(
"Expected return type for fn {}",
function_symbol.borrow().fqn_formatted()
)) {
TypeSymbol::Primitive(primitive_type_symbol) => match primitive_type_symbol
{
PrimitiveTypeSymbol::Byte => {
IrKind::Primitive(IrPrimitiveKind::I8.into())
}
PrimitiveTypeSymbol::Char => {
todo!()
}
PrimitiveTypeSymbol::Short => {
IrKind::Primitive(IrPrimitiveKind::I16.into())
}
PrimitiveTypeSymbol::Int => {
IrKind::Primitive(IrPrimitiveKind::I32.into())
}
PrimitiveTypeSymbol::Long => {
IrKind::Primitive(IrPrimitiveKind::I64.into())
}
PrimitiveTypeSymbol::Float => {
IrKind::Primitive(IrPrimitiveKind::Float.into())
}
PrimitiveTypeSymbol::Double => {
IrKind::Primitive(IrPrimitiveKind::Double.into())
}
PrimitiveTypeSymbol::Boolean => {
IrKind::Primitive(IrPrimitiveKind::Boolean.into())
}
PrimitiveTypeSymbol::String => {
IrKind::Primitive(IrPrimitiveKind::String.into())
}
PrimitiveTypeSymbol::TypedArray { inner_type } => {
todo!()
}
PrimitiveTypeSymbol::Any => {
IrKind::Primitive(IrPrimitiveKind::Any.into())
}
PrimitiveTypeSymbol::Void => {
IrKind::Primitive(IrPrimitiveKind::Void.into())
}
},
TypeSymbol::Class(class_symbol) => {
todo!()
}
TypeSymbol::Interface(interface_symbol) => {
todo!()
}
TypeSymbol::Generic(generic_symbol) => {
todo!()
}
}
}
ExpressibleSymbol::ClassMember(_) => {
todo!()
}
ExpressibleSymbol::Parameter(_) => {
todo!()
}
ExpressibleSymbol::Variable(_) => {
todo!()
}
}
}
Expression::Fqn(_) => {
todo!()
}
Expression::Closure(_) => {
todo!()
}
Expression::List(_) => {
todo!()
} }
} else {
false
}; };
if is_last && !is_void_return { let arg_vars = match call {
let return_statement = IrReturn::new(Some(expression_to_ir_expression( Call::ParenthesesCall(p_call) => {
expression_statement.expression(), let mut arg_vars: Vec<IrVariable> = vec![];
fn_context, if let Some(expression_list) = p_call.expression_list() {
))); arg_vars.append(&mut lower_expression_list(
fn_context.push_statement(IrStatement::Return(return_statement.into())); expression_list,
} else { target,
lower_side_effect_expression(expression_statement.expression(), fn_context); consts_pool,
} locals_table,
));
}
if let Some(closure) = p_call.closure() {
arg_vars.push(lower_closure(closure, target, consts_pool, locals_table));
}
arg_vars
}
Call::ClosureOnlyCall(c_call) => {
vec![lower_closure(
c_call.closure(),
target,
consts_pool,
locals_table,
)]
}
};
let arg_expressions = arg_vars
.iter()
.map(|ir_variable| IrExpression::Variable(ir_variable.clone().into()))
.collect::<Vec<_>>();
let result_var = locals_table.next_t_var();
let call = IrCall::new(
result_var.name(),
declared_type.into(),
&fqn,
IrCallType::Static,
arg_expressions,
);
target.push(IrStatement::Call(call));
result_var
} }
fn lower_side_effect_expression(expression: &Expression, fn_context: &mut FnContext) { fn lower_expression_list(
match expression { expression_list: &ExpressionList,
Expression::Suffix(suffix_expression) => { target: &mut Vec<IrStatement>,
lower_side_effect_suffix_expression(suffix_expression, fn_context); consts_pool: &mut Vec<IrConst>,
} locals_table: &mut LocalsTable,
_ => { ) -> Vec<IrVariable> {
todo!("Anything other than a suffix expression for side-effects should be eliminated as dead code.") let mut results: Vec<IrVariable> = vec![];
} for expression in expression_list.expressions() {
results.push(lower_expression(
expression,
target,
consts_pool,
locals_table,
));
} }
results
} }
fn lower_side_effect_suffix_expression( fn lower_closure(
suffix_expression: &SuffixExpression, closure: &Closure,
fn_context: &mut FnContext, target: &mut Vec<IrStatement>,
) { consts_pool: &mut Vec<IrConst>,
match suffix_expression.operator() { locals_table: &mut LocalsTable,
SuffixOperator::PlusPlus => { ) -> IrVariable {
todo!() todo!()
}
SuffixOperator::MinusMinus => {
todo!()
}
SuffixOperator::ObjectIndex(object_index) => {
todo!()
}
SuffixOperator::Call(call) => {
call_to_ir_expression(call, suffix_expression.expression(), fn_context);
}
SuffixOperator::ObjectProperty(object_property) => {
todo!()
}
}
} }
fn call_to_ir_expression( fn lower_identifier(
call: &Call, identifier: &Identifier,
receiver: &Expression, target: &mut Vec<IrStatement>,
fn_context: &mut FnContext, consts_pool: &mut Vec<IrConst>,
) -> IrExpression { locals_table: &mut LocalsTable,
let function_kind = receiver.analyzed_kind().expect_function(); ) -> IrVariable {
todo!("Rework AST nodes so that Call and children have a better api") IrVariable::new(identifier.name())
}
fn lower_additive_expression(
additive: &AdditiveExpression,
target: &mut Vec<IrStatement>,
consts_pool: &mut Vec<IrConst>,
locals_table: &mut LocalsTable,
) -> IrVariable {
let left_var = lower_expression(additive.left(), target, consts_pool, locals_table);
let right_var = lower_expression(additive.rhs().expression(), target, consts_pool, locals_table);
let destination = locals_table.next_t_var();
let operator = match additive.rhs().operator() {
AdditiveOperator::Add => {
IrBinaryOperator::Add
}
AdditiveOperator::Subtract => {
IrBinaryOperator::Subtract
}
};
let operation = IrBinaryOperation::new(
destination.clone(),
IrExpression::Variable(left_var.into()),
IrExpression::Variable(right_var.into()),
operator
);
target.push(IrStatement::BinaryOperation(operation));
destination
} }

134
src/ir/lower_ir.rs Normal file
View File

@ -0,0 +1,134 @@
use crate::ir::lower_ast::LocalsTable;
use crate::ir::{IrAllocable, IrAllocate, IrAssign, IrCall, IrExpression, IrFunction, IrLiteral, IrReturn, IrStatement};
use crate::vm::instruction::{Immediate, Instruction, Location};
use std::ops::Deref;
use std::rc::Rc;
pub fn lower_ir_function(ir_function: &IrFunction) -> Vec<Instruction> {
let mut instructions: Vec<Instruction> = vec![];
for statement in ir_function.statements() {
instructions.append(&mut lower_ir_statement(
statement,
ir_function.locals_table(),
));
}
instructions
}
fn lower_ir_statement(ir_statement: &IrStatement, locals_table: &LocalsTable) -> Vec<Instruction> {
match ir_statement {
IrStatement::Allocate(allocate) => lower_ir_allocate(allocate),
IrStatement::Call(call) => lower_ir_call(call, locals_table),
IrStatement::Return(ir_return) => lower_return(ir_return, locals_table),
IrStatement::Assign(assign) => {
lower_ir_assign(assign, locals_table)
}
IrStatement::MakeClosure(make_closure) => {
todo!()
}
IrStatement::BinaryOperation(binary_operation) => {
todo!()
}
}
}
fn lower_ir_allocate(ir_allocate: &IrAllocate) -> Vec<Instruction> {
let allocate_instruction = match ir_allocate.kind_to_alloc() {
IrAllocable::Struct(struct_kind) => Instruction::AllocateObject {
implementation_name: Rc::new(struct_kind.name().to_string()),
destination_register: 0,
},
IrAllocable::Array(array_kind) => {
todo!()
}
};
let push_instruction = Instruction::Push { source_register: 0 };
vec![allocate_instruction, push_instruction]
}
fn lower_ir_call(ir_call: &IrCall, locals_table: &LocalsTable) -> Vec<Instruction> {
let mut instructions: Vec<Instruction> = vec![];
// push args
for argument in ir_call.arguments() {
lower_ir_expression(argument, &mut instructions, locals_table);
}
instructions
}
fn lower_ir_expression(
ir_expression: &IrExpression,
instructions: &mut Vec<Instruction>,
locals_table: &LocalsTable,
) {
match ir_expression {
IrExpression::Variable(variable) => instructions.append(&mut vec![
Instruction::Copy {
source: Location::FramePointer {
offset: locals_table.get_stack_slot(variable) as isize,
},
destination: Location::Register(0),
},
Instruction::Push { source_register: 0 },
]),
IrExpression::ConstRef(const_ref) => {
todo!()
}
IrExpression::Literal(literal) => {
let immediate = match literal.deref() {
IrLiteral::I8(v) => Immediate::I8(*v),
IrLiteral::I16(v) => Immediate::I16(*v),
IrLiteral::I32(v) => Immediate::I32(*v),
IrLiteral::I64(v) => Immediate::I64(*v),
IrLiteral::I128(v) => Immediate::I128(*v),
IrLiteral::ISize(v) => Immediate::ISize(*v),
IrLiteral::U8(v) => Immediate::U8(*v),
IrLiteral::U16(v) => Immediate::U16(*v),
IrLiteral::U32(v) => Immediate::U32(*v),
IrLiteral::U64(v) => Immediate::U64(*v),
IrLiteral::U128(v) => Immediate::U128(*v),
IrLiteral::USize(v) => Immediate::USize(*v),
IrLiteral::Boolean(v) => Immediate::Boolean(*v),
IrLiteral::Float(v) => Immediate::Float(*v),
IrLiteral::Double(v) => Immediate::Double(*v),
};
instructions.append(&mut vec![
Instruction::MoveImmediate {
destination_register: 0,
immediate,
},
Instruction::Push { source_register: 0 },
])
}
}
}
fn lower_return(ir_return: &IrReturn, locals_table: &LocalsTable) -> Vec<Instruction> {
let mut instructions: Vec<Instruction> = vec![];
lower_ir_expression(ir_return.expression(), &mut instructions, locals_table);
instructions.append(&mut vec![
Instruction::Pop {
destination_register: Some(0),
},
Instruction::PopFrame,
Instruction::Push { source_register: 0 },
Instruction::Return,
]);
instructions
}
fn lower_ir_assign(ir_assign: &IrAssign, locals_table: &LocalsTable) -> Vec<Instruction> {
let mut instructions: Vec<Instruction> = vec![];
lower_ir_expression(ir_assign.rhs(), &mut instructions, locals_table);
instructions.append(&mut vec![
Instruction::Pop {
destination_register: Some(0),
},
Instruction::Copy {
source: Location::Register(0),
destination: Location::FramePointer {
offset: locals_table.get_stack_slot(ir_assign.lhs()) as isize,
}
}
]);
instructions
}

View File

@ -1,123 +1,72 @@
use crate::ir::lower_ast::LocalsTable;
use crate::util::indent_writer::IndentWriter;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::rc::Rc; use std::rc::Rc;
pub mod lower_ast; pub mod lower_ast;
pub mod lower_ir;
pub enum Ir { pub enum Ir {
Struct(Box<IrStruct>), Struct(Box<IrStruct>),
Function(Box<IrFunction>), Function(Box<IrFunction>),
PlatformFunction(Box<IrPlatformFunction>), PlatformFunction(Box<IrPlatformFunction>),
Const(Box<IrConst>),
} }
impl Display for Ir { impl Ir {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
writeln!( match self {
f, Ir::Struct(ir_struct) => ir_struct.pretty_print(writer),
"{}\n", Ir::Function(ir_function) => ir_function.pretty_print(writer),
match self { Ir::PlatformFunction(ir_platform_function) => ir_platform_function.pretty_print(writer),
Ir::Struct(ir_struct) => { Ir::Const(ir_const) => ir_const.pretty_print(writer),
format!("{}", ir_struct) }
}
Ir::Function(ir_function) => {
format!("{}", ir_function)
}
Ir::PlatformFunction(ir_platform_function) => {
format!("{}", ir_platform_function)
}
}
)
} }
} }
pub struct IrStruct { pub struct IrStruct {
name: Rc<str>, name: String,
is_public: bool, is_public: bool,
members: Vec<IrStructMember>, members: Vec<IrStructMember>,
} }
impl IrStruct { impl IrStruct {
pub fn new(name: &str, is_public: bool, members: Vec<IrStructMember>) -> Self { fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
Self {
name: name.into(),
is_public,
members,
}
}
pub fn name(&self) -> &str {
&self.name
}
pub fn name_owned(&self) -> Rc<str> {
self.name.clone()
}
pub fn is_public(&self) -> bool {
self.is_public
}
pub fn members(&self) -> &[IrStructMember] {
&self.members
}
}
impl Display for IrStruct {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
if self.is_public { if self.is_public {
write!(f, "pub ")?; writer.writeln(&format!("pub struct {} {{", self.name))?;
} else {
writer.writeln(&format!("struct {} {{", self.name))?;
} }
writeln!(f, "struct {} {{", self.name)?; writer.increase_indent();
for member in &self.members { for member in &self.members {
writeln!(f, " {}", member)?; member.pretty_print(writer)?;
writer.write("\n")?;
} }
writeln!(f, "}}")?; writer.decrease_indent();
writer.writeln("}")?;
Ok(()) Ok(())
} }
} }
pub struct IrStructMember { pub struct IrStructMember {
name: Rc<str>, name: String,
kind: Box<IrKind>, kind: Box<IrKind>,
is_public: bool, is_public: bool,
is_mut: bool, is_mut: bool,
} }
impl IrStructMember { impl IrStructMember {
pub fn new(name: &str, kind: IrKind, is_public: bool, is_mut: bool) -> Self { fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
Self {
name: name.into(),
kind: kind.into(),
is_public,
is_mut,
}
}
pub fn name(&self) -> &str {
&self.name
}
pub fn name_owned(&self) -> Rc<str> {
self.name.clone()
}
pub fn kind(&self) -> &IrKind {
&self.kind
}
pub fn is_public(&self) -> bool {
self.is_public
}
}
impl Display for IrStructMember {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
if self.is_public { if self.is_public {
write!(f, "pub ")?; writer.write("pub ")?;
} }
if self.is_mut { if self.is_mut {
write!(f, "mut ")?; writer.write("mut ")?;
} }
write!(f, "{}: {}", self.name, self.kind) writer.write(&self.name)?;
writer.write(": ")?;
self.kind.pretty_print(writer)?;
Ok(())
} }
} }
@ -126,15 +75,11 @@ pub enum IrKind {
Struct(Box<IrStructKind>), Struct(Box<IrStructKind>),
} }
impl Display for IrKind { impl IrKind {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
match self { match self {
IrKind::Primitive(ir_primitive_kind) => { IrKind::Primitive(primitive) => primitive.pretty_print(writer),
write!(f, "{}", ir_primitive_kind) IrKind::Struct(struct_kind) => struct_kind.pretty_print(writer),
}
IrKind::Struct(ir_struct_kind) => {
write!(f, "{}", ir_struct_kind)
}
} }
} }
} }
@ -158,115 +103,99 @@ pub enum IrPrimitiveKind {
Array(Box<IrKind>), Array(Box<IrKind>),
String, String,
Closure(Box<IrClosureKind>), Closure(Box<IrClosureKind>),
Ref(Box<IrKind>),
Any, Any,
Void, Void,
} }
impl Display for IrPrimitiveKind { impl IrPrimitiveKind {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
let s = match self { match self {
IrPrimitiveKind::I8 => "i8", IrPrimitiveKind::I8 => writer.write("i8"),
IrPrimitiveKind::I16 => "i16", IrPrimitiveKind::I16 => writer.write("i16"),
IrPrimitiveKind::I32 => "i32", IrPrimitiveKind::I32 => writer.write("i32"),
IrPrimitiveKind::I64 => "i64", IrPrimitiveKind::I64 => writer.write("i64"),
IrPrimitiveKind::I128 => "i128", IrPrimitiveKind::I128 => writer.write("i128"),
IrPrimitiveKind::ISize => "isize", IrPrimitiveKind::ISize => writer.write("isize"),
IrPrimitiveKind::U8 => "u8", IrPrimitiveKind::U8 => writer.write("u8"),
IrPrimitiveKind::U16 => "u16", IrPrimitiveKind::U16 => writer.write("u16"),
IrPrimitiveKind::U32 => "u32", IrPrimitiveKind::U32 => writer.write("u32"),
IrPrimitiveKind::U64 => "u64", IrPrimitiveKind::U64 => writer.write("u64"),
IrPrimitiveKind::U128 => "u128", IrPrimitiveKind::U128 => writer.write("u128"),
IrPrimitiveKind::USize => "usize", IrPrimitiveKind::USize => writer.write("usize"),
IrPrimitiveKind::Float => "f32", IrPrimitiveKind::Float => writer.write("f32"),
IrPrimitiveKind::Double => "f64", IrPrimitiveKind::Double => writer.write("f64"),
IrPrimitiveKind::Boolean => "Boolean", IrPrimitiveKind::Boolean => writer.write("boolean"),
IrPrimitiveKind::Array(inner_kind) => &format!("Array<{}>", inner_kind), IrPrimitiveKind::Array(kind) => {
IrPrimitiveKind::String => "String", writer.write("Array<")?;
IrPrimitiveKind::Closure(ir_closure_kind) => &format!("{}", ir_closure_kind), kind.pretty_print(writer)?;
IrPrimitiveKind::Any => "Any", writer.write(">")?;
IrPrimitiveKind::Void => "Void", Ok(())
}; }
write!(f, "{}", s) IrPrimitiveKind::String => writer.write("String"),
IrPrimitiveKind::Closure(closure_kind) => writer.write("Closure"),
IrPrimitiveKind::Ref(ref_kind) => {
todo!()
}
IrPrimitiveKind::Any => writer.write("Any"),
IrPrimitiveKind::Void => writer.write("Void"),
}
} }
} }
pub struct IrStructKind { pub struct IrStructKind {
name: Rc<str>, name: String,
} }
impl IrStructKind { impl IrStructKind {
pub fn new(name: &str) -> Self { pub fn new(name: &str) -> Self {
Self { name: name.into() } Self {
name: name.to_string(),
}
} }
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
&self.name &self.name
} }
pub fn name_owned(&self) -> Rc<str> { pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
self.name.clone() writer.write(&self.name)
}
}
impl Display for IrStructKind {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name)
} }
} }
pub struct IrClosureKind { pub struct IrClosureKind {
captures_struct_name: Rc<str>, captures_struct_name: String,
parameters: Vec<IrKind>, parameters: Vec<IrKind>,
return_type: Box<IrKind>, return_type: Box<IrKind>,
} }
impl Display for IrClosureKind {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Closure |{}| ({}) -> {}",
self.captures_struct_name,
self.parameters
.iter()
.map(|ir_kind| format!("{}", ir_kind))
.collect::<Vec<_>>()
.join(", "),
self.return_type
)
}
}
pub struct IrFunction { pub struct IrFunction {
fqn: Rc<str>, name: String,
is_public: bool,
parameters: Vec<IrKind>, parameters: Vec<IrKind>,
return_type: Box<IrKind>, return_type: Box<IrKind>,
statements: Vec<IrStatement>, statements: Vec<IrStatement>,
locals_table: Box<LocalsTable>,
} }
impl IrFunction { impl IrFunction {
pub fn new( pub fn new(
fqn: &str, name: String,
is_public: bool,
parameters: Vec<IrKind>, parameters: Vec<IrKind>,
return_type: IrKind, return_type: Box<IrKind>,
statements: Vec<IrStatement>, statements: Vec<IrStatement>,
locals_table: Box<LocalsTable>,
) -> Self { ) -> Self {
Self { Self {
fqn: fqn.into(), name,
is_public,
parameters, parameters,
return_type: return_type.into(), return_type,
statements, statements,
locals_table,
} }
} }
pub fn fqn(&self) -> &str { pub fn name(&self) -> &str {
&self.fqn &self.name
}
pub fn fqn_owned(&self) -> Rc<str> {
self.fqn.clone()
} }
pub fn parameters(&self) -> &[IrKind] { pub fn parameters(&self) -> &[IrKind] {
@ -280,93 +209,76 @@ impl IrFunction {
pub fn statements(&self) -> &[IrStatement] { pub fn statements(&self) -> &[IrStatement] {
&self.statements &self.statements
} }
}
impl Display for IrFunction { pub fn locals_table(&self) -> &LocalsTable {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { &self.locals_table
if self.is_public { }
write!(f, "pub ")?;
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
writer.write("fn ")?;
writer.write(&self.name)?;
writer.write("(")?;
for (i, parameter) in self.parameters.iter().enumerate() {
parameter.pretty_print(writer)?;
if i != self.parameters.len() - 1 {
writer.write(", ")?;
}
} }
writeln!( writer.write(") -> ")?;
f, self.return_type.pretty_print(writer)?;
"fn {}({}) -> {} {{", writer.write(" {\n")?;
self.fqn, writer.increase_indent();
self.parameters
.iter()
.map(|ir_kind| format!("{}", ir_kind))
.collect::<Vec<_>>()
.join(", "),
self.return_type
)?;
for statement in &self.statements { for statement in &self.statements {
writeln!(f, " {}", statement)?; statement.pretty_print(writer)?;
} }
writeln!(f, "}}")?; writer.decrease_indent();
Ok(()) writer.writeln("}")
} }
} }
pub struct IrPlatformFunction { pub struct IrPlatformFunction {
fqn: Rc<str>, name: String,
is_public: bool,
parameters: Vec<IrKind>, parameters: Vec<IrKind>,
return_type: Box<IrKind>, return_type: Box<IrKind>,
} }
impl Display for IrPlatformFunction { impl IrPlatformFunction {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
if self.is_public { writer.write("platform fn ")?;
write!(f, "pub ")?; writer.write(&self.name)?;
writer.write("(")?;
for (i, parameter) in self.parameters.iter().enumerate() {
parameter.pretty_print(writer)?;
if i != self.parameters.len() - 1 {
writer.write(", ")?;
}
} }
writeln!( writer.write(") -> ")?;
f, self.return_type.pretty_print(writer)?;
"platform fn {}({}) -> {}", writer.write("\n")?;
self.fqn, Ok(())
self.parameters
.iter()
.map(|ir_kind| format!("{}", ir_kind))
.collect::<Vec<_>>()
.join(", "),
self.return_type
)
} }
} }
pub enum IrStatement { pub enum IrStatement {
Allocate(Box<IrAllocate>), Allocate(IrAllocate),
Call(Box<IrCall>), Call(IrCall),
Return(Box<IrReturn>), Return(IrReturn),
Assign(Box<IrAssign>), Assign(IrAssign),
MakeClosure(Box<IrMakeClosure>), MakeClosure(IrMakeClosure),
BinaryOperation(Box<IrBinaryOperation>), BinaryOperation(IrBinaryOperation),
} }
impl Display for IrStatement { impl IrStatement {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
write!( match self {
f, IrStatement::Allocate(allocate) => allocate.pretty_print(writer),
"{}", IrStatement::Call(call) => call.pretty_print(writer),
match self { IrStatement::Return(ir_return) => ir_return.pretty_print(writer),
IrStatement::Allocate(ir_allocate) => { IrStatement::Assign(assign) => assign.pretty_print(writer),
format!("{}", ir_allocate) IrStatement::MakeClosure(make_closure) => make_closure.pretty_print(writer),
} IrStatement::BinaryOperation(binary_operation) => binary_operation.pretty_print(writer),
IrStatement::Call(ir_call) => { }
format!("{}", ir_call)
}
IrStatement::Return(ir_return) => {
format!("{}", ir_return)
}
IrStatement::Assign(ir_assign) => {
format!("{}", ir_assign)
}
IrStatement::MakeClosure(ir_make_closure) => {
format!("{}", ir_make_closure)
}
IrStatement::BinaryOperation(ir_binary_operation) => {
format!("{}", ir_binary_operation)
}
}
)
} }
} }
@ -375,15 +287,11 @@ pub enum IrAllocable {
Array(Box<IrArrayKind>), Array(Box<IrArrayKind>),
} }
impl Display for IrAllocable { impl IrAllocable {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
match self { match self {
IrAllocable::Struct(ir_struct_kind) => { IrAllocable::Struct(struct_kind) => struct_kind.pretty_print(writer),
write!(f, "{}(", ir_struct_kind) IrAllocable::Array(array_kind) => array_kind.pretty_print(writer),
}
IrAllocable::Array(ir_array_kind) => {
write!(f, "{}(", ir_array_kind)
}
} }
} }
} }
@ -393,15 +301,11 @@ pub enum IrArrayKind {
DynamicSize(Box<IrDynamicArrayKind>), DynamicSize(Box<IrDynamicArrayKind>),
} }
impl Display for IrArrayKind { impl IrArrayKind {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
match self { match self {
IrArrayKind::StaticSize(ir_static_array_kind) => { IrArrayKind::StaticSize(static_array_kind) => static_array_kind.pretty_print(writer),
write!(f, "{}", ir_static_array_kind) IrArrayKind::DynamicSize(dynamic_array_kind) => dynamic_array_kind.pretty_print(writer),
}
IrArrayKind::DynamicSize(ir_dynamic_array_kind) => {
write!(f, "{}", ir_dynamic_array_kind)
}
} }
} }
} }
@ -411,9 +315,12 @@ pub struct IrStaticArrayKind {
size: usize, size: usize,
} }
impl Display for IrStaticArrayKind { impl IrStaticArrayKind {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
write!(f, "Array<{}>[{}]", self.inner_kind, self.size) writer.write("[")?;
self.inner_kind.pretty_print(writer)?;
writer.write(&format!("; {}]", self.size))?;
Ok(())
} }
} }
@ -422,33 +329,26 @@ pub struct IrDynamicArrayKind {
size_expr: Box<IrExpression>, size_expr: Box<IrExpression>,
} }
impl Display for IrDynamicArrayKind { impl IrDynamicArrayKind {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
write!(f, "Array<{}>", self.inner_kind) writer.write("[")?;
self.inner_kind.pretty_print(writer)?;
writer.write("; ")?;
self.size_expr.pretty_print(writer)?;
writer.write("]")?;
Ok(())
} }
} }
pub struct IrAllocate { pub struct IrAllocate {
result_variable: Rc<str>, name: String,
declared_kind: Box<IrAllocable>, declared_kind: Box<IrAllocable>,
kind_to_alloc: Box<IrAllocable>, kind_to_alloc: Box<IrAllocable>,
} }
impl IrAllocate { impl IrAllocate {
pub fn new( pub fn name(&self) -> &str {
result_variable: &str, &self.name
declared_kind: IrAllocable,
kind_to_alloc: IrAllocable,
) -> Self {
Self {
result_variable: result_variable.into(),
declared_kind: declared_kind.into(),
kind_to_alloc: kind_to_alloc.into(),
}
}
pub fn result_variable(&self) -> &str {
&self.result_variable
} }
pub fn declared_kind(&self) -> &IrAllocable { pub fn declared_kind(&self) -> &IrAllocable {
@ -458,15 +358,13 @@ impl IrAllocate {
pub fn kind_to_alloc(&self) -> &IrAllocable { pub fn kind_to_alloc(&self) -> &IrAllocable {
&self.kind_to_alloc &self.kind_to_alloc
} }
}
impl Display for IrAllocate { pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { writer.write_indented(&format!("let {}: ", self.name))?;
write!( self.declared_kind.pretty_print(writer)?;
f, writer.write(" = alloc")?;
"{}: {} = alloc {}", self.kind_to_alloc.pretty_print(writer)?;
self.result_variable, self.declared_kind, self.kind_to_alloc Ok(())
)
} }
} }
@ -507,15 +405,16 @@ impl IrBinaryOperation {
pub fn operator(&self) -> &IrBinaryOperator { pub fn operator(&self) -> &IrBinaryOperator {
&self.operator &self.operator
} }
}
impl Display for IrBinaryOperation { pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { writer.write_indented("")?;
write!( self.destination.pretty_print(writer)?;
f, writer.write(" = ")?;
"{} = {} {} {}", self.left.pretty_print(writer)?;
self.destination, self.left, self.operator, self.right writer.write(&format!(" {} ", self.operator))?;
) self.right.pretty_print(writer)?;
writer.writeln("")?;
Ok(())
} }
} }
@ -549,46 +448,83 @@ impl Display for IrBinaryOperator {
} }
} }
pub enum IrConst {
String(IrStringConst),
StringArray(IrStringArrayConst),
}
impl IrConst {
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
todo!()
}
}
pub struct IrStringConst {
name: String,
value: String,
}
pub struct IrStringArrayConst {
name: String,
value: Vec<String>,
}
pub enum IrExpression { pub enum IrExpression {
Variable(Box<IrVariable>), Variable(Box<IrVariable>),
ConstRef(Box<IrConstRef>),
Literal(Box<IrLiteral>), Literal(Box<IrLiteral>),
} }
impl Display for IrExpression { impl IrExpression {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
write!( match self {
f, IrExpression::Variable(variable) => variable.pretty_print(writer),
"{}", IrExpression::ConstRef(const_ref) => const_ref.pretty_print(writer),
match self { IrExpression::Literal(literal) => literal.pretty_print(writer),
IrExpression::Variable(ir_variable) => { }
format!("{}", ir_variable)
}
IrExpression::Literal(ir_literal) => {
format!("{}", ir_literal)
}
}
)
} }
} }
#[derive(Clone, Hash, Eq, PartialEq)] #[derive(Clone, Hash, Eq, PartialEq)]
pub struct IrVariable { pub struct IrVariable {
name: Rc<str>, name: String,
} }
impl IrVariable { impl IrVariable {
pub fn new(name: &str) -> Self { pub fn new(name: &str) -> Self {
Self { name: name.into() } Self {
name: name.to_string(),
}
} }
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
&self.name &self.name
} }
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
writer.write(&self.name)
}
} }
impl Display for IrVariable { pub struct IrConstRef {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { name: Rc<str>,
write!(f, "{}", self.name) }
impl IrConstRef {
pub fn new(name: Rc<str>) -> Self {
Self { name }
}
pub fn name(&self) -> &str {
&self.name
}
pub fn name_owned(&self) -> Rc<str> {
self.name.clone()
}
pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
writer.write(&self.name)
} }
} }
@ -608,63 +544,57 @@ pub enum IrLiteral {
Boolean(bool), Boolean(bool),
Float(f32), Float(f32),
Double(f64), Double(f64),
String(Rc<str>),
} }
impl Display for IrLiteral { impl IrLiteral {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
write!( match self {
f, IrLiteral::I8(v) => writer.write(&format!("{}", v)),
"{}", IrLiteral::I16(v) => writer.write(&format!("{}", v)),
match self { IrLiteral::I32(v) => writer.write(&format!("{}", v)),
IrLiteral::I8(i) => format!("{}", *i), IrLiteral::I64(v) => writer.write(&format!("{}", v)),
IrLiteral::I16(i) => format!("{}", *i), IrLiteral::I128(v) => writer.write(&format!("{}", v)),
IrLiteral::I32(i) => format!("{}", *i), IrLiteral::ISize(v) => writer.write(&format!("{}", v)),
IrLiteral::I64(i) => format!("{}", *i), IrLiteral::U8(v) => writer.write(&format!("{}", v)),
IrLiteral::I128(i) => format!("{}", *i), IrLiteral::U16(v) => writer.write(&format!("{}", v)),
IrLiteral::ISize(i) => format!("{}", *i), IrLiteral::U32(v) => writer.write(&format!("{}", v)),
IrLiteral::U8(u) => format!("{}", *u), IrLiteral::U64(v) => writer.write(&format!("{}", v)),
IrLiteral::U16(u) => format!("{}", *u), IrLiteral::U128(v) => writer.write(&format!("{}", v)),
IrLiteral::U32(u) => format!("{}", *u), IrLiteral::USize(v) => writer.write(&format!("{}", v)),
IrLiteral::U64(u) => format!("{}", *u), IrLiteral::Boolean(v) => writer.write(&format!("{}", v)),
IrLiteral::U128(u) => format!("{}", *u), IrLiteral::Float(v) => writer.write(&format!("{}", v)),
IrLiteral::USize(u) => format!("{}", *u), IrLiteral::Double(v) => writer.write(&format!("{}", v)),
IrLiteral::Boolean(b) => format!("{}", *b), }
IrLiteral::Float(float) => format!("{}", *float),
IrLiteral::Double(double) => format!("{}", *double),
IrLiteral::String(s) => format!("{}", s),
}
)
} }
} }
pub struct IrCall { pub struct IrCall {
result_variable: Option<Rc<str>>, result_name: String,
declared_type: Box<IrKind>, declared_type: Box<IrKind>,
function_fqn: Rc<str>, fqn: Rc<str>,
call_type: IrCallType, call_type: IrCallType,
arguments: Vec<IrExpression>, arguments: Vec<IrExpression>,
} }
impl IrCall { impl IrCall {
pub fn new( pub fn new(
result_variable: Option<&str>, result_name: &str,
declared_type: IrKind, declared_type: Box<IrKind>,
fqn: &str, fqn: &str,
call_type: IrCallType, call_type: IrCallType,
arguments: Vec<IrExpression>, arguments: Vec<IrExpression>,
) -> Self { ) -> Self {
Self { Self {
result_variable: result_variable.map(Rc::from), result_name: result_name.to_string(),
declared_type: declared_type.into(), declared_type,
function_fqn: fqn.into(), fqn: fqn.into(),
call_type, call_type,
arguments, arguments,
} }
} }
pub fn result_variable(&self) -> Option<&str> { pub fn result_name(&self) -> &str {
self.result_variable.as_ref().map(Rc::as_ref) &self.result_name
} }
pub fn declared_type(&self) -> &IrKind { pub fn declared_type(&self) -> &IrKind {
@ -672,11 +602,11 @@ impl IrCall {
} }
pub fn function_name(&self) -> &str { pub fn function_name(&self) -> &str {
&self.function_fqn &self.fqn
} }
pub fn function_name_owned(&self) -> Rc<str> { pub fn function_name_owned(&self) -> Rc<str> {
self.function_fqn.clone() self.fqn.clone()
} }
pub fn call_type(&self) -> &IrCallType { pub fn call_type(&self) -> &IrCallType {
@ -686,51 +616,25 @@ impl IrCall {
pub fn arguments(&self) -> &[IrExpression] { pub fn arguments(&self) -> &[IrExpression] {
&self.arguments &self.arguments
} }
}
impl Display for IrCall { pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { writer.write_indented(&format!("{}: ", self.result_name))?;
if let Some(result_variable) = &self.result_variable { self.declared_type.pretty_print(writer)?;
write!(f, "{}: {} = ", result_variable, self.declared_type)?; writer.write(&format!(" = call {}(", self.fqn))?;
for (i, argument) in self.arguments.iter().enumerate() {
argument.pretty_print(writer)?;
if i != self.arguments.len() - 1 {
writer.write(", ")?;
}
} }
write!( writer.write(")\n")?;
f, Ok(())
"{} {}({})",
self.call_type,
self.function_fqn,
self.arguments
.iter()
.map(|ir_expression| ir_expression.to_string())
.collect::<Vec<_>>()
.join(", ")
)
} }
} }
pub enum IrCallType { pub enum IrCallType {
Static, Static,
Object, Object,
PlatformStatic,
PlatformObject,
}
impl Display for IrCallType {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
IrCallType::Static => {
write!(f, "call_static")
}
IrCallType::Object => {
write!(f, "call_object")
}
IrCallType::PlatformStatic => {
write!(f, "call_platform_static")
}
IrCallType::PlatformObject => {
write!(f, "call_platform_object")
}
}
}
} }
pub struct IrAssign { pub struct IrAssign {
@ -739,11 +643,8 @@ pub struct IrAssign {
} }
impl IrAssign { impl IrAssign {
pub fn new(lhs: IrVariable, rhs: IrExpression) -> Self { pub fn new(lhs: Box<IrVariable>, rhs: Box<IrExpression>) -> Self {
Self { Self { lhs, rhs }
lhs: lhs.into(),
rhs: rhs.into(),
}
} }
pub fn lhs(&self) -> &IrVariable { pub fn lhs(&self) -> &IrVariable {
@ -753,36 +654,34 @@ impl IrAssign {
pub fn rhs(&self) -> &IrExpression { pub fn rhs(&self) -> &IrExpression {
&self.rhs &self.rhs
} }
}
impl Display for IrAssign { pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { writer.write_indented("")?;
write!(f, "{} = {}", self.lhs, self.rhs) self.lhs.pretty_print(writer)?;
writer.write(" = ")?;
self.rhs.pretty_print(writer)?;
writer.write("\n")?;
Ok(())
} }
} }
pub struct IrReturn { pub struct IrReturn {
expression: Option<Box<IrExpression>>, expression: Box<IrExpression>,
} }
impl IrReturn { impl IrReturn {
pub fn new(expression: Option<IrExpression>) -> Self { pub fn new(expression: Box<IrExpression>) -> Self {
Self { Self { expression }
expression: expression.map(Box::new),
}
} }
pub fn expression(&self) -> Option<&IrExpression> { pub fn expression(&self) -> &IrExpression {
self.expression.as_ref().map(Box::as_ref) &self.expression
} }
}
impl Display for IrReturn { pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { writer.write_indented("return ")?;
write!(f, "return")?; self.expression.pretty_print(writer)?;
if let Some(expression) = &self.expression { writer.write("\n")?;
write!(f, " {}", expression)?;
}
Ok(()) Ok(())
} }
} }
@ -791,13 +690,13 @@ pub struct IrMakeClosure {
captures_kind: Option<Box<IrStructKind>>, captures_kind: Option<Box<IrStructKind>>,
parameters: Vec<IrKind>, parameters: Vec<IrKind>,
return_type: Box<IrKind>, return_type: Box<IrKind>,
result_variable: Rc<str>, name: String,
function_fqn: Rc<str>, fn_name: String,
captures_variable: Box<IrVariable>, captures_variable: Box<IrVariable>,
} }
impl Display for IrMakeClosure { impl IrMakeClosure {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result {
todo!() todo!()
} }
} }

View File

@ -1,6 +1,6 @@
#![feature(new_range_api)] #![feature(new_range_api)]
#![feature(unsize)]
#![feature(coerce_unsized)] #![feature(coerce_unsized)]
#![feature(unsize)]
#![allow(warnings)] #![allow(warnings)]
extern crate core; extern crate core;
@ -13,6 +13,5 @@ pub mod name_analysis;
pub mod object_file; pub mod object_file;
pub mod parser; pub mod parser;
pub mod std_core; pub mod std_core;
pub mod type_analysis;
pub mod util; pub mod util;
pub mod vm; pub mod vm;

View File

@ -529,7 +529,9 @@ fn na_p2_variable_declaration(
} }
// initializer // initializer
na_p2_expression(variable_declaration.expression_mut(), symbol_table, diagnostics); if let Some(expression) = variable_declaration.expression_mut() {
na_p2_expression(expression, symbol_table, diagnostics);
}
} }
fn na_p2_assignment_statement( fn na_p2_assignment_statement(

View File

@ -24,10 +24,6 @@ impl ClassSymbol {
} }
} }
pub fn fqn_formatted(&self) -> String {
self.fqn_parts.join("::")
}
pub fn declared_name(&self) -> &str { pub fn declared_name(&self) -> &str {
self.fqn_parts.last().unwrap() self.fqn_parts.last().unwrap()
} }

View File

@ -86,10 +86,6 @@ impl FunctionSymbol {
pub fn return_type(&self) -> Option<&TypeSymbol> { pub fn return_type(&self) -> Option<&TypeSymbol> {
self.return_type.as_ref() self.return_type.as_ref()
} }
pub fn return_type_owned(&self) -> Option<TypeSymbol> {
self.return_type.clone()
}
pub fn set_return_type(&mut self, type_symbol: TypeSymbol) { pub fn set_return_type(&mut self, type_symbol: TypeSymbol) {
self.return_type = Some(type_symbol); self.return_type = Some(type_symbol);

View File

@ -2,13 +2,12 @@ use crate::name_analysis::symbol::source_definition::SourceDefinition;
use crate::name_analysis::symbol::Symbol; use crate::name_analysis::symbol::Symbol;
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::rc::Rc; use std::rc::Rc;
use crate::type_analysis::kinds::Kind;
#[derive(Clone)]
pub struct VariableSymbol { pub struct VariableSymbol {
declared_name: Rc<str>, declared_name: Rc<str>,
is_mutable: bool, is_mutable: bool,
source_definition: Option<SourceDefinition>, source_definition: Option<SourceDefinition>,
analyzed_kind: Option<Kind>,
} }
impl VariableSymbol { impl VariableSymbol {
@ -21,7 +20,6 @@ impl VariableSymbol {
declared_name: Rc::from(declared_name), declared_name: Rc::from(declared_name),
is_mutable, is_mutable,
source_definition, source_definition,
analyzed_kind: None,
} }
} }
@ -36,14 +34,6 @@ impl VariableSymbol {
pub fn is_mutable(&self) -> bool { pub fn is_mutable(&self) -> bool {
self.is_mutable self.is_mutable
} }
pub fn set_analyzed_kind(&mut self, analyzed_kind: Kind) {
self.analyzed_kind = Some(analyzed_kind);
}
pub fn analyzed_kind(&self) -> Option<&Kind> {
self.analyzed_kind.as_ref()
}
} }
impl Symbol for VariableSymbol { impl Symbol for VariableSymbol {

View File

@ -37,9 +37,6 @@ $defs:
- $ref: "#/$defs/PolymorphicTypeDefinition" - $ref: "#/$defs/PolymorphicTypeDefinition"
- $ref: "#/$defs/PolymorphicEnumLoopBuildDefinition" - $ref: "#/$defs/PolymorphicEnumLoopBuildDefinition"
- $ref: "#/$defs/PolymorphicPassThroughDefinition" - $ref: "#/$defs/PolymorphicPassThroughDefinition"
- $ref: "#/$defs/PolymorphicTreeEnumDefinition"
- $ref: "#/$defs/PolymorphicLeafEnumDefinition"
- $ref: "#/$defs/PolymorphicEnumInnerBuildDefinition"
# Struct # Struct
StructNodeDefinition: StructNodeDefinition:
@ -609,89 +606,4 @@ $defs:
- kind - kind
- with - with
required: required:
- node_production - node_production
# Polymorphic Tree Enum
PolymorphicTreeEnumDefinition:
type: object
additionalProperties: false
properties:
polymorphic_tree_enum:
type: object
additionalProperties: false
properties:
kind:
type: string
rules:
type: array
items:
type: string
required:
- kind
- rules
required:
- polymorphic_tree_enum
# Polymorphic Leaf Enum
PolymorphicLeafEnumDefinition:
type: object
additionalProperties: false
properties:
polymorphic_leaf_enum:
type: object
additionalProperties: false
properties:
kind:
type: string
rules:
type: array
items:
type: string
required:
- kind
- rules
required:
- polymorphic_leaf_enum
# Polymorphic Enum Inner Build
PolymorphicEnumInnerBuildDefinition:
type: object
additionalProperties: false
properties:
polymorphic_enum_inner_build:
type: object
additionalProperties: false
properties:
members:
type: array
items:
$ref: "#/$defs/PolymorphicEnumInnerBuildMember"
rules:
type: array
items:
type: string
required:
- members
- rules
required:
- polymorphic_enum_inner_build
PolymorphicEnumInnerBuildMember:
type: object
oneOf:
- type: string
- $ref: "#/$defs/PolymorphicEnumInnerBuildAdvancedMember"
PolymorphicEnumInnerBuildAdvancedMember:
type: object
patternProperties:
"^([A-Z][a-z]*)*$":
type: object
additionalProperties: false
properties:
kind:
type: string
required:
- kind
minProperties: 1
maxProperties: 1

View File

@ -694,7 +694,9 @@ VariableDeclaration:
- type_use: - type_use:
member: member:
optional: true optional: true
- expression - expression:
member:
optional: true
fields: fields:
- variable_symbol: - variable_symbol:
kind: VariableSymbol kind: VariableSymbol
@ -1224,8 +1226,6 @@ IdentifierExpression:
fields: fields:
- expressible_symbol: - expressible_symbol:
kind: ExpressibleSymbol kind: ExpressibleSymbol
- analyzed_kind:
kind: Kind
ListExpression: ListExpression:
struct: struct:
children: children:

View File

@ -1,27 +0,0 @@
use std::fmt::Display;
use std::rc::Rc;
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct ClassKind {
fqn: Rc<str>
}
impl ClassKind {
pub fn new(fqn: &str) -> Self {
Self { fqn: fqn.into() }
}
pub fn fqn(&self) -> &str {
&self.fqn
}
pub fn fqn_owned(&self) -> Rc<str> {
self.fqn.clone()
}
}
impl Display for ClassKind {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "{}", self.fqn)
}
}

View File

@ -1,27 +0,0 @@
use std::fmt::{Display, Formatter};
use std::rc::Rc;
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct FunctionKind {
fqn: Rc<str>,
}
impl FunctionKind {
pub fn new(fqn: &str) -> Self {
Self { fqn: fqn.into() }
}
pub fn fqn(&self) -> &str {
&self.fqn
}
pub fn fqn_owned(&self) -> Rc<str> {
self.fqn.clone()
}
}
impl Display for FunctionKind {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.fqn)
}
}

View File

@ -1,40 +0,0 @@
pub use crate::type_analysis::kinds::class_kind::ClassKind;
pub use crate::type_analysis::kinds::function_kind::FunctionKind;
pub use crate::type_analysis::kinds::primitive_kind::PrimitiveKind;
use std::fmt::Display;
pub mod class_kind;
pub mod function_kind;
pub mod primitive_kind;
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum Kind {
Primitive(Box<PrimitiveKind>),
Class(Box<ClassKind>),
Function(Box<FunctionKind>),
}
impl Kind {
pub fn expect_function(&self) -> &FunctionKind {
match self {
Kind::Function(function_kind) => function_kind,
_ => panic!("Expected FunctionKind, found {:?}", self),
}
}
}
impl Display for Kind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Kind::Primitive(primitive_kind) => {
write!(f, "{}", primitive_kind)
}
Kind::Class(class_kind) => {
write!(f, "{}", class_kind)
}
Kind::Function(function_kind) => {
write!(f, "{}", function_kind)
}
}
}
}

View File

@ -1,24 +0,0 @@
use std::fmt::Display;
use crate::type_analysis::kinds::Kind;
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum PrimitiveKind {
Byte,
Char,
Short,
Int,
Long,
Float,
Double,
Boolean,
String,
Array { inner_type: Kind },
Any,
Void,
}
impl Display for PrimitiveKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}

View File

@ -1,232 +0,0 @@
pub mod kinds;
use crate::ast::node::{
AdditiveExpression, CompilationUnit, Expression, ExpressionStatement, Function,
FunctionBlockBody, FunctionBody, IdentifierExpression, ModuleLevelDeclaration, Statement,
VariableDeclaration,
};
use crate::diagnostic::DmDiagnostic;
use crate::name_analysis::symbol::ExpressibleSymbol;
use crate::type_analysis::kinds::class_kind::ClassKind;
use crate::type_analysis::kinds::function_kind::FunctionKind;
use crate::type_analysis::kinds::Kind;
use codespan_reporting::files::Files;
pub fn analyze_types(compilation_units: &mut [CompilationUnit]) -> Vec<DmDiagnostic> {
let mut diagnostics: Vec<DmDiagnostic> = vec![];
for compilation_unit in compilation_units {
ta_compilation_unit(compilation_unit, &mut diagnostics);
}
diagnostics
}
fn ta_compilation_unit(
compilation_unit: &mut CompilationUnit,
diagnostics: &mut Vec<DmDiagnostic>,
) {
for module_level_declaration in compilation_unit.module_level_declarations_mut() {
ta_module_level_declaration(module_level_declaration, diagnostics);
}
}
fn ta_module_level_declaration(
module_level_declaration: &mut ModuleLevelDeclaration,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match module_level_declaration {
ModuleLevelDeclaration::Module(module) => {
todo!()
}
ModuleLevelDeclaration::Interface(interface) => {
todo!()
}
ModuleLevelDeclaration::Class(class) => {
todo!()
}
ModuleLevelDeclaration::Function(function) => {
ta_function(function, diagnostics);
}
ModuleLevelDeclaration::PlatformFunction(platform_function) => {
todo!()
}
}
}
fn ta_function(function: &mut Function, diagnostics: &mut Vec<DmDiagnostic>) {
ta_function_body(function.function_body_mut(), diagnostics);
}
fn ta_function_body(function_body: &mut FunctionBody, diagnostics: &mut Vec<DmDiagnostic>) {
match function_body {
FunctionBody::FunctionAliasBody(function_alias_body) => {
todo!()
}
FunctionBody::FunctionEqualsBody(function_equals_body) => {
todo!()
}
FunctionBody::FunctionBlockBody(function_block_body) => {
ta_function_block_body(function_block_body, diagnostics);
}
}
}
fn ta_function_block_body(
function_block_body: &mut FunctionBlockBody,
diagnostics: &mut Vec<DmDiagnostic>,
) {
for statement in function_block_body.statements_mut() {
ta_statement(statement, diagnostics);
}
}
fn ta_statement(statement: &mut Statement, diagnostics: &mut Vec<DmDiagnostic>) {
match statement {
Statement::VariableDeclaration(variable_declaration) => {
ta_variable_declaration(variable_declaration, diagnostics);
}
Statement::AssignmentStatement(assignment_statement) => {
todo!()
}
Statement::ExpressionStatement(expression_statement) => {
ta_expression_statement(expression_statement, diagnostics);
}
Statement::UseStatement(use_statement) => {
todo!()
}
Statement::IfStatement(if_statement) => {
todo!()
}
Statement::WhileStatement(while_statement) => {
todo!()
}
Statement::ForStatement(for_statement) => {
todo!()
}
}
}
fn ta_variable_declaration(
variable_declaration: &mut VariableDeclaration,
diagnostics: &mut Vec<DmDiagnostic>,
) {
// compute type of initializer
ta_expression(variable_declaration.expression_mut(), diagnostics);
// get type of initializer, and check against to declared type (if present)
// todo
// set type of variable's symbol to analyzed type (initializer type or declared type)
let variable_kind = if let Some(declared_type) = variable_declaration.type_use() {
todo!("declared types on variable declarations")
} else {
variable_declaration.expression().analyzed_kind().clone()
};
variable_declaration
.variable_symbol_mut()
.expect("VariableDeclaration's variable_symbol not set.")
.borrow_mut()
.set_analyzed_kind(variable_kind)
}
fn ta_expression_statement(
expression_statement: &mut ExpressionStatement,
diagnostics: &mut Vec<DmDiagnostic>,
) {
ta_expression(expression_statement.expression_mut(), diagnostics);
}
fn ta_expression(expression: &mut Expression, diagnostics: &mut Vec<DmDiagnostic>) {
match expression {
Expression::Ternary(ternary_expression) => {
todo!()
}
Expression::Or(or_expression) => {
todo!()
}
Expression::And(and_expression) => {
todo!()
}
Expression::Comparison(comparison_expression) => {
todo!()
}
Expression::Shift(shift_expression) => {
todo!()
}
Expression::Additive(additive_expression) => {
ta_additive_expression(additive_expression, diagnostics);
}
Expression::Multiplicative(multiplicative_expression) => {
todo!()
}
Expression::Prefix(prefix_expression) => {
todo!()
}
Expression::Suffix(suffix_expression) => {
todo!()
}
Expression::Literal(literal) => {
// no-op
}
Expression::Identifier(identifier_expression) => {
ta_identifier_expression(identifier_expression);
}
Expression::Fqn(fqn) => {
todo!()
}
Expression::Closure(closure) => {
todo!()
}
Expression::List(list_expression) => {
todo!()
}
}
}
fn ta_additive_expression(
additive_expression: &mut AdditiveExpression,
diagnostics: &mut Vec<DmDiagnostic>,
) {
ta_expression(additive_expression.left_mut(), diagnostics);
ta_expression(additive_expression.rhs_mut().expression_mut(), diagnostics);
let left_kind = additive_expression.left().analyzed_kind();
let right_kind = additive_expression.rhs().expression().analyzed_kind();
if left_kind != right_kind {
diagnostics.push(DmDiagnostic::error().with_message(&format!(
"Incompatible types for additive expression: {} vs. {}",
left_kind, right_kind
)));
todo!("Error file_id and range; set Error type on additive expression")
} else {
todo!("set analyzed type for additive expression")
}
}
fn ta_identifier_expression(identifier_expression: &mut IdentifierExpression) {
let expressible_symbol = identifier_expression
.expressible_symbol()
.expect("IdentifierExpression's expressible_symbol must be set before type analysis.");
let kind = match expressible_symbol {
ExpressibleSymbol::Class(class_symbol) => {
let class_kind = ClassKind::new(&class_symbol.borrow().fqn_formatted());
Kind::Class(class_kind.into())
}
ExpressibleSymbol::Function(function_symbol) => {
let function_kind = FunctionKind::new(&function_symbol.borrow().fqn_formatted());
Kind::Function(function_kind.into())
}
ExpressibleSymbol::ClassMember(class_member_symbol) => {
todo!()
}
ExpressibleSymbol::Parameter(parameter_symbol) => {
todo!()
}
ExpressibleSymbol::Variable(variable_symbol) => variable_symbol
.borrow()
.analyzed_kind()
.expect("VariableSymbol's analyzed_kind not set.")
.clone(),
};
identifier_expression.set_analyzed_kind(kind);
}