use crate::{ codegen::{expr::*, stmt::*, CodeGenContext}, toplevel::{DefinitionId, TopLevelDef}, typecheck::typedef::{FunSignature, Type}, }; use inkwell::values::{BasicValueEnum, PointerValue}; use nac3parser::ast::{Expr, Stmt, StrRef}; pub trait CodeGenerator { /// Return the module name for the code generator. fn get_name(&self) -> &str; /// Generate function call and returns the function return value. /// - obj: Optional object for method call. /// - fun: Function signature and definition ID. /// - params: Function parameters. Note that this does not include the object even if the /// function is a class method. fn gen_call<'ctx, 'a>( &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, obj: Option<(Type, BasicValueEnum<'ctx>)>, fun: (&FunSignature, DefinitionId), params: Vec<(Option, BasicValueEnum<'ctx>)>, ) -> Option> { gen_call(self, ctx, obj, fun, params) } /// Generate object constructor and returns the constructed object. /// - signature: Function signature of the contructor. /// - def: Class definition for the constructor class. /// - params: Function parameters. fn gen_constructor<'ctx, 'a>( &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, signature: &FunSignature, def: &TopLevelDef, params: Vec<(Option, BasicValueEnum<'ctx>)>, ) -> BasicValueEnum<'ctx> { gen_constructor(self, ctx, signature, def, params) } /// Generate a function instance. /// - obj: Optional object for method call. /// - fun: Function signature, definition ID and the substitution key. /// - params: Function parameters. Note that this does not include the object even if the /// function is a class method. /// Note that this function should check if the function is generated in another thread (due to /// possible race condition), see the default implementation for an example. fn gen_func_instance<'ctx, 'a>( &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, obj: Option<(Type, BasicValueEnum<'ctx>)>, fun: (&FunSignature, &mut TopLevelDef, String), ) -> String { gen_func_instance(ctx, obj, fun) } /// Generate the code for an expression. fn gen_expr<'ctx, 'a>( &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, expr: &Expr>, ) -> Option> { gen_expr(self, ctx, expr) } /// Allocate memory for a variable and return a pointer pointing to it. /// The default implementation places the allocations at the start of the function. fn gen_var_alloc<'ctx, 'a>( &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, ty: Type, ) -> PointerValue<'ctx> { gen_var(ctx, ty) } /// Return a pointer pointing to the target of the expression. fn gen_store_target<'ctx, 'a>( &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, pattern: &Expr>, ) -> PointerValue<'ctx> { gen_store_target(self, ctx, pattern) } /// Generate code for an assignment expression. fn gen_assign<'ctx, 'a>( &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, target: &Expr>, value: BasicValueEnum<'ctx>, ) { gen_assign(self, ctx, target, value) } /// Generate code for a while expression. /// Return true if the while loop must early return fn gen_while<'ctx, 'a>( &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, stmt: &Stmt>, ) -> bool { gen_while(self, ctx, stmt); false } /// Generate code for a while expression. /// Return true if the while loop must early return fn gen_for<'ctx, 'a>( &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, stmt: &Stmt>, ) -> bool { gen_for(self, ctx, stmt); false } /// Generate code for an if expression. /// Return true if the statement must early return fn gen_if<'ctx, 'a>( &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, stmt: &Stmt>, ) -> bool { gen_if(self, ctx, stmt) } fn gen_with<'ctx, 'a>( &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, stmt: &Stmt>, ) -> bool { gen_with(self, ctx, stmt) } /// Generate code for a statement /// Return true if the statement must early return fn gen_stmt<'ctx, 'a>( &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, stmt: &Stmt>, ) -> bool { gen_stmt(self, ctx, stmt) } } pub struct DefaultCodeGenerator { name: String, } impl DefaultCodeGenerator { pub fn new(name: String) -> DefaultCodeGenerator { DefaultCodeGenerator { name } } } impl CodeGenerator for DefaultCodeGenerator { fn get_name(&self) -> &str { &self.name } }