deimos-lang/src/ir/lower_ast.rs

670 lines
21 KiB
Rust

use crate::ast::node::{AdditiveExpression, AdditiveOperator, Call, Closure, CompilationUnit, Expression, ExpressionList, ExpressionStatement, Function, FunctionBlockBody, FunctionBody, Identifier, Literal, ModuleLevelDeclaration, Statement, SuffixExpression, SuffixOperator, VariableDeclaration};
use crate::ir::{
Ir, IrAssign, IrBinaryOperation, IrBinaryOperator, IrCall, IrCallType, IrConst, IrExpression,
IrFunction, IrKind, IrLiteral, IrPrimitiveKind, IrStatement, IrVariable,
};
use crate::name_analysis::symbol::{
ExpressibleSymbol, ParameterSymbol, PrimitiveTypeSymbol, TypeSymbol,
};
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use crate::ir::IrStatement::BinaryOperation;
pub fn lower_compilation_unit(compilation_unit: &CompilationUnit) -> Vec<Ir> {
let mut result: Vec<Ir> = vec![];
for declaration in compilation_unit.module_level_declarations() {
result.append(&mut lower_module_level_declaration(declaration));
}
result
}
fn lower_module_level_declaration(declaration: &ModuleLevelDeclaration) -> Vec<Ir> {
match declaration {
ModuleLevelDeclaration::Module(module) => {
todo!()
}
ModuleLevelDeclaration::Interface(interface) => {
todo!()
}
ModuleLevelDeclaration::Class(class) => {
todo!()
}
ModuleLevelDeclaration::Function(function) => lower_function(function),
ModuleLevelDeclaration::PlatformFunction(platform_function) => {
todo!()
}
}
}
pub struct LocalsTable {
t_count: usize,
stack_slot_count: usize,
stack_slots: HashMap<IrVariable, usize>,
}
impl LocalsTable {
pub fn new() -> Self {
Self {
t_count: 0,
stack_slot_count: 0,
stack_slots: HashMap::new(),
}
}
pub fn next_t_var(&mut self) -> IrVariable {
let t_num = self.t_count;
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
}
pub fn register_stack_local(&mut self, ir_variable: &IrVariable) {
let stack_slot = self.stack_slot_count;
self.stack_slot_count += 1;
self.stack_slots.insert(ir_variable.clone(), stack_slot);
}
pub fn get_stack_slot(&self, ir_variable: &IrVariable) -> usize {
*self.stack_slots.get(ir_variable).unwrap()
}
}
fn lower_function(function: &Function) -> Vec<Ir> {
let function_symbol = function.function_symbol().unwrap().borrow();
let name = function_symbol.fqn_parts_owned().join("::");
let parameters = lower_parameter_symbols(function_symbol.parameter_symbols());
let return_type = lower_type_symbol(function_symbol.return_type().unwrap());
let mut locals_table = LocalsTable::new();
let (statements, consts) = lower_function_body(function.function_body(), &mut locals_table);
let mut result: Vec<Ir> = vec![];
result.push(Ir::Function(Box::new(IrFunction::new(
name,
parameters,
Box::new(return_type),
statements,
Box::new(locals_table),
))));
result.append(
&mut consts
.into_iter()
.map(|constant| Ir::Const(Box::new(constant)))
.collect(),
);
result
}
fn lower_parameter_symbols(parameter_symbols: &[Rc<RefCell<ParameterSymbol>>]) -> Vec<IrKind> {
parameter_symbols
.iter()
.map(|parameter_symbol_rc| parameter_symbol_rc.borrow())
.map(|parameter_symbol| lower_type_symbol(parameter_symbol.type_symbol().unwrap()))
.collect()
}
fn lower_type_symbol(type_symbol: &TypeSymbol) -> IrKind {
match type_symbol {
TypeSymbol::Primitive(primitive_type_symbol) => {
lower_primitive_type_symbol(primitive_type_symbol)
}
TypeSymbol::Class(class_type_symbol) => {
todo!()
}
TypeSymbol::Interface(interface_type_symbol) => {
todo!()
}
TypeSymbol::Generic(generic_type_symbol) => {
todo!()
}
}
}
fn lower_primitive_type_symbol(primitive_type_symbol: &PrimitiveTypeSymbol) -> IrKind {
IrKind::Primitive(Box::new(match primitive_type_symbol {
PrimitiveTypeSymbol::Byte => IrPrimitiveKind::I8,
PrimitiveTypeSymbol::Char => IrPrimitiveKind::I8,
PrimitiveTypeSymbol::Short => IrPrimitiveKind::I16,
PrimitiveTypeSymbol::Int => IrPrimitiveKind::I32,
PrimitiveTypeSymbol::Long => IrPrimitiveKind::I64,
PrimitiveTypeSymbol::Float => IrPrimitiveKind::Float,
PrimitiveTypeSymbol::Double => IrPrimitiveKind::Double,
PrimitiveTypeSymbol::Boolean => IrPrimitiveKind::Boolean,
PrimitiveTypeSymbol::String => IrPrimitiveKind::String,
PrimitiveTypeSymbol::TypedArray { inner_type } => {
IrPrimitiveKind::Array(Box::new(lower_type_symbol(inner_type.as_ref().unwrap())))
}
PrimitiveTypeSymbol::Any => {
todo!()
}
PrimitiveTypeSymbol::Void => IrPrimitiveKind::Void,
}))
}
fn lower_function_body(
function_body: &FunctionBody,
locals_table: &mut LocalsTable,
) -> (Vec<IrStatement>, Vec<IrConst>) {
match function_body {
FunctionBody::FunctionAliasBody(alias_body) => {
todo!()
}
FunctionBody::FunctionEqualsBody(equals_body) => {
todo!()
}
FunctionBody::FunctionBlockBody(block_body) => {
lower_function_block_body(block_body, locals_table)
}
}
}
fn lower_function_block_body(
body: &FunctionBlockBody,
locals_table: &mut LocalsTable,
) -> (Vec<IrStatement>, Vec<IrConst>) {
let mut statements: Vec<IrStatement> = vec![];
let mut consts: Vec<IrConst> = vec![];
for statement in body.statements() {
statements.append(&mut lower_statement(statement, &mut consts, locals_table));
}
(statements, consts)
}
fn lower_statement(
statement: &Statement,
consts_pool: &mut Vec<IrConst>,
locals_table: &mut LocalsTable,
) -> Vec<IrStatement> {
match statement {
Statement::VariableDeclaration(variable_declaration) => {
lower_variable_declaration(variable_declaration, consts_pool, locals_table)
}
Statement::AssignmentStatement(assignment_statement) => {
todo!()
}
Statement::ExpressionStatement(expression_statement) => {
lower_expression_statement(expression_statement, consts_pool, locals_table)
}
Statement::UseStatement(use_statement) => {
todo!()
}
Statement::IfStatement(if_statement) => {
todo!()
}
Statement::WhileStatement(while_statement) => {
todo!()
}
Statement::ForStatement(for_statement) => {
todo!()
}
}
}
fn lower_variable_declaration(
variable_declaration: &VariableDeclaration,
consts_pool: &mut Vec<IrConst>,
locals_table: &mut LocalsTable,
) -> Vec<IrStatement> {
let mut result: Vec<IrStatement> = vec![];
let expression_t_var = lower_expression(
variable_declaration.expression().unwrap(),
&mut result,
consts_pool,
locals_table,
);
let target = IrVariable::new(variable_declaration.identifier().name());
locals_table.register_stack_local(&target);
let assign_stmt = IrAssign::new(
Box::new(target),
Box::new(IrExpression::Variable(Box::new(expression_t_var))),
);
result.push(IrStatement::Assign(assign_stmt));
result
}
fn lower_expression_statement(
expression_statement: &ExpressionStatement,
consts_pool: &mut Vec<IrConst>,
locals_table: &mut LocalsTable,
) -> Vec<IrStatement> {
let mut result: Vec<IrStatement> = vec![];
lower_expression(
expression_statement.expression(),
&mut result,
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!()
}
}
}
fn lower_suffix_expression(
suffix_expression: &SuffixExpression,
target: &mut Vec<IrStatement>,
consts_pool: &mut Vec<IrConst>,
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 lower_literal(
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(_) => {
todo!()
}
Expression::Or(_) => {
todo!()
}
Expression::And(_) => {
todo!()
}
Expression::Comparison(_) => {
todo!()
}
Expression::Shift(_) => {
todo!()
}
Expression::Additive(_) => {
todo!()
}
Expression::Multiplicative(_) => {
todo!()
}
Expression::Prefix(_) => {
todo!()
}
Expression::Suffix(_) => {
todo!()
}
Expression::Literal(_) => {
todo!()
}
Expression::Identifier(identifier_expression) => {
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(fqn) => {
todo!()
}
Expression::Closure(_) => {
todo!()
}
Expression::List(_) => {
todo!()
}
};
let declared_type = match receiver {
Expression::Ternary(_) => {
todo!()
}
Expression::Or(_) => {
todo!()
}
Expression::And(_) => {
todo!()
}
Expression::Comparison(_) => {
todo!()
}
Expression::Shift(_) => {
todo!()
}
Expression::Additive(_) => {
todo!()
}
Expression::Multiplicative(_) => {
todo!()
}
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!()
}
};
let arg_vars = match call {
Call::ParenthesesCall(p_call) => {
let mut arg_vars: Vec<IrVariable> = vec![];
if let Some(expression_list) = p_call.expression_list() {
arg_vars.append(&mut lower_expression_list(
expression_list,
target,
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_expression_list(
expression_list: &ExpressionList,
target: &mut Vec<IrStatement>,
consts_pool: &mut Vec<IrConst>,
locals_table: &mut LocalsTable,
) -> Vec<IrVariable> {
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_closure(
closure: &Closure,
target: &mut Vec<IrStatement>,
consts_pool: &mut Vec<IrConst>,
locals_table: &mut LocalsTable,
) -> IrVariable {
todo!()
}
fn lower_identifier(
identifier: &Identifier,
target: &mut Vec<IrStatement>,
consts_pool: &mut Vec<IrConst>,
locals_table: &mut LocalsTable,
) -> IrVariable {
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
}