diff --git a/lib-ltcore/src/procedure_compiler.rs b/lib-ltcore/src/procedure_compiler.rs index ee5b848..644151a 100644 --- a/lib-ltcore/src/procedure_compiler.rs +++ b/lib-ltcore/src/procedure_compiler.rs @@ -20,7 +20,12 @@ pub struct ProcedureCompiler { proc_symbol: String, scope: Arc>, asm: tisc::Assembler, - subroutines: Vec, + subroutine_count: u32, + frame_size: u32, + + in_types: Vec< laddertypes::TypeTerm >, + out_types: Vec< laddertypes::TypeTerm >, + pub linker: tisc::Linker, pub diagnostics: Vec<( InputRegionTag, String )> } @@ -30,48 +35,36 @@ impl ProcedureCompiler { ProcedureCompiler { proc_symbol, scope, - subroutines: Vec::new(), + subroutine_count: 0, + frame_size: 0, + in_types: vec![], + out_types: vec![], asm: tisc::Assembler::new(), linker: tisc::Linker::new(), diagnostics: Vec::new() } } -/* - pub fn export_symbols(&self) -> Vec<(String, SymbolDef)> { - let mut scope = self.scope.write().unwrap(); - scope.update_link_addresses(&self.proc_symbol, &self.linker); - scope.export() + + pub fn make_subroutine_symbol(&mut self) -> String { + let id = self.subroutine_count; + self.subroutine_count += 1; + format!("__{}_sub_{}__", self.proc_symbol, id) } -*/ - pub fn get_bytecode(mut self, ret: bool) -> ( + + pub fn get_bytecode(mut self) -> ( Vec<(String, SymbolDef)>, Vec ) { - let frame_size = self.scope.read().unwrap().get_frame_size(); - if frame_size > 0 { + if self.frame_size > 0 { let alloc_asm = tisc::Assembler::new() - .lit(frame_size as tisc::VM_Word).call("data-frame-alloc"); + .lit(self.frame_size as tisc::VM_Word).call("data-frame-alloc"); let drop_asm = tisc::Assembler::new() - .lit(frame_size as tisc::VM_Word).call("data-frame-drop"); + .lit(self.frame_size as tisc::VM_Word).call("data-frame-drop"); self.asm = alloc_asm.join( self.asm ).join( drop_asm ); } - let main_section = self.asm.build(); - - //self.linker.add_procedure( &self.proc_symbol, main_section ); - // ^--- this would insert the asm section at the end, - // we however need it an the beginning of the bytecode - - // insert section at front - self.linker.next_addr += main_section.len() as i64; - for (name,section) in self.linker.symbols.iter_mut() { - section.addr += main_section.len() as i64; - } - self.linker.symbols.insert( - self.proc_symbol.clone(), - tisc::linker::Section { addr: 0, data: main_section } - ); + self.linker.add_procedure_front( &self.proc_symbol, self.asm.build() ); // replace all symbol definitions from subroutines // with relative LinkAddr`s @@ -80,16 +73,21 @@ impl ProcedureCompiler { &self.linker ); + let code = + self.linker.link_relative(&self.proc_symbol).expect("link error"); + + let mut export_symbols = self.scope.read().unwrap().export(); + //eprintln!("proc compiler export = {:?}\ncode= {:?}", export_symbols, code); ( - self.scope.read().unwrap().export(), - self.linker.link_relative( &self.proc_symbol ).expect("link error") + export_symbols, + code ) } pub fn compile_statement(mut self, statement: &Statement, enable_export: bool) -> Self { match statement { Statement::Assignment { name_region, var_id, val_expr } => { - self = self.compile_expr(val_expr); + self = self.compile_expr(val_expr, true); match self.scope.read().unwrap().get(var_id) { Some(SymbolDef::FrameRef { typ, stack_ref }) => { @@ -127,35 +125,20 @@ impl ProcedureCompiler { } => { let val_type = self.scope.read().unwrap() .get(var_id).unwrap() - .get_type(&mut self.scope.clone()); - let val_type = val_type.sugar(&mut self.scope.clone()); + .get_type(&mut self.scope.clone()) + .sugar(&mut self.scope.clone()); + match val_type { laddertypes::SugaredTypeTerm::Func(mut f_types) => { - let mut c = ProcedureCompiler::new( - var_id.clone(), - self.scope.clone() - ); - c = c.compile_expr( val_expr ); + let mut c = + ProcedureCompiler::new( + var_id.clone(), self.scope.clone() + ).compile_expr( val_expr, true ); + self.diagnostics.append(&mut c.diagnostics); - let (symbols,code) = c.get_bytecode( true ); - eprintln!("LET assign compiled {}", var_id); - for (i,l) in tisc::assembler::disassemble( &code ).iter().enumerate() { - eprintln!("{}+{} ... {}", var_id, i, l); - } + let (symbols,code) = c.get_bytecode(); self.linker.add_procedure(var_id, code); - - /* - let out_types = vec![ f_types.pop().unwrap().desugar(&mut self.scope.clone()) ]; - let in_types = f_types.into_iter().map(|t| t.desugar(&mut self.scope.clone())).collect(); - - self.scope.write().unwrap().declare_proc( - var_id.clone(), - in_types, - out_types, - true - ); - */ } _ => { @@ -164,20 +147,27 @@ impl ProcedureCompiler { var_id: var_id.clone(), val_expr: val_expr.clone(), }, false); + + self.frame_size += 1; } } } Statement::Expr(expr) => { - self = self.compile_expr(expr); + self = self.compile_expr(expr, true); } Statement::Return(expr) => { - self = self.compile_expr(expr); + self = self.compile_expr(expr, true); } } self } - pub fn compile_expr(mut self, expr: <Expr) -> Self { + pub fn compile_expr(mut self, expr: <Expr, call: bool) -> Self { + /* + self.out_types.push( + expr.infer_type( &self.scope ).expect("type error") + ); + */ match expr { LTExpr::Symbol { region, typ, symbol } => match self.scope.read().unwrap().get(symbol) { Some(SymbolDef::FrameRef { typ, stack_ref }) => { @@ -192,7 +182,11 @@ impl ProcedureCompiler { link_addr, export }) => { - self.asm = self.asm.call_symbol(link_addr); + if call { + self.asm = self.asm.call_symbol(link_addr); + } else { + self.asm = self.asm.ref_symbol( link_addr ); + } } None => { self.diagnostics.push( @@ -210,10 +204,10 @@ impl ProcedureCompiler { self.asm = self.asm.lit(*val); } LTExpr::Ascend { region, typ, expr } => { - self = self.compile_expr(expr); + self = self.compile_expr(expr, call); } LTExpr::Descend { region, typ, expr } => { - self = self.compile_expr(expr); + self = self.compile_expr(expr, call); } LTExpr::Branch { region, @@ -221,14 +215,14 @@ impl ProcedureCompiler { if_expr, else_expr, } => { - self = self.compile_expr(condition); + self = self.compile_expr(condition, true); let asm = self.asm; self.asm = tisc::Assembler::new(); - self = self.compile_expr(if_expr); + self = self.compile_expr(if_expr, true); let if_asm = self.asm; self.asm = tisc::Assembler::new(); - self = self.compile_expr(else_expr); + self = self.compile_expr(else_expr, true); let else_asm = self.asm; self.asm = asm; self.asm = self.asm.branch(if_asm, else_asm); @@ -237,34 +231,34 @@ impl ProcedureCompiler { let asm = self.asm; self.asm = tisc::Assembler::new(); - self = self.compile_expr(condition); + self = self.compile_expr(condition, true); let cond_asm = self.asm; self.asm = tisc::Assembler::new(); - self = self.compile_expr(body); + self = self.compile_expr(body, true); let body_asm = self.asm; self.asm = asm; self.asm = self.asm.while_loop(cond_asm, body_asm); } - LTExpr::Application { region, typ, head, body } => { + LTExpr::Application { region, typ, head, body } => { for arg in body.iter().rev() { - self = self.compile_expr(arg); + self = self.compile_expr(arg, false); } - self = self.compile_expr(head); + self = self.compile_expr(head, true); } LTExpr::Abstraction { region, scope, args, body } => { - let mut abs_compiler = ProcedureCompiler::new("__abs__".into(), scope.clone()); + let abs_symbol = self.make_subroutine_symbol(); + let mut abs_compiler = ProcedureCompiler::new(abs_symbol.clone(), scope.clone()); for (region, arg_name, arg_type) in args.iter() { match scope.read().unwrap().get(arg_name) { Some(SymbolDef::FrameRef{ typ, stack_ref }) => { - eprintln!("Arg {} stack ref = {}", arg_name, stack_ref); - // TODO: aknowledge actual size of arguments // let arg_size = typ.get_size() let arg_size = 1; + abs_compiler.frame_size += 1; for i in 0..arg_size { abs_compiler.asm = abs_compiler.asm .lit(stack_ref + i) @@ -280,48 +274,22 @@ impl ProcedureCompiler { } } - abs_compiler = abs_compiler.compile_expr( body ); - let (abs_symbols, mut abs_code) = abs_compiler.get_bytecode( false ); - - for (s,def) in abs_symbols.iter() { - eprintln!("{} = {:?}", s, def); - } - for (i, l) in tisc::assembler::disassemble(&abs_code).into_iter().enumerate() { - eprintln!("__abs__+{} .. {}", i, l); - } - - self.asm.words.append( &mut abs_code ); -/* - self.linker.add_procedure( - "__abs__".into(), - abs_code - );*/ + abs_compiler = abs_compiler.compile_expr( body, true ); + let (abs_export_symbols, mut abs_code) = abs_compiler.get_bytecode(); + self.scope.write().unwrap().import( abs_export_symbols ); + self.linker.add_procedure( &abs_symbol, abs_code ); + self.asm = self.asm.call( &abs_symbol ); } LTExpr::Block { region, scope, statements } => { - let mut block_compiler = ProcedureCompiler::new( - "__block__".into(), - scope.clone() - ); - + let block_symbol = self.make_subroutine_symbol(); + let mut block_compiler = ProcedureCompiler::new( block_symbol.clone(), scope.clone() ); for stmnt in statements.iter() { block_compiler = block_compiler.compile_statement( stmnt, true ); } - - let (block_symbols, mut block_code) = block_compiler.get_bytecode( true ); - - eprintln!("BLOCK compiler:"); - for (s,def) in block_symbols.iter() { - eprintln!("{} = {:?}", s, def); - } - for (i,l) in tisc::assembler::disassemble( &block_code ).into_iter().enumerate() { - eprintln!("block+{} .. {}", i, l); - } - - self.linker. - self.scope.write().unwrap().import( - block_symbols - ); - self.asm.words.append(&mut block_code); + let (block_export_symbols, mut block_code) = block_compiler.get_bytecode(); + self.scope.write().unwrap().import( block_export_symbols ); + self.linker.add_procedure( &block_symbol, block_code.clone() ); + self.asm = self.asm.call( &block_symbol ); } LTExpr::ExportBlock{ region, scope, statements } => { } diff --git a/lib-ltcore/src/symbols.rs b/lib-ltcore/src/symbols.rs index a44a2e5..f9b3d91 100644 --- a/lib-ltcore/src/symbols.rs +++ b/lib-ltcore/src/symbols.rs @@ -207,25 +207,39 @@ impl Scope { linker: &tisc::Linker ) { for (name, def) in self.symbols.iter_mut() { - if let Some(offset) = linker.get_link_addr( name ) { - match def { - SymbolDef::Procedure { - in_types:_,out_types:_, - link_addr, - export:_ - } => { + match def { + SymbolDef::Procedure { + in_types:_, + out_types:_, + link_addr, + export:_ + } => { + if let Some(offset) = linker.get_link_addr( name ) { + eprintln!("update link addr {} @ {} + {}", name, base_symbol, offset); + *link_addr = LinkAddr::Relative{ symbol: base_symbol.clone(), offset }; - }, - _ => {} + } else { + match link_addr { + LinkAddr::Relative{ symbol, offset } => { + if let Some(base_symb_offset) = linker.get_link_addr( &symbol ) { + *symbol = base_symbol.clone(); + *offset += base_symb_offset; + } + }, + _ => {} + } + } + } + _ => { + // TODO: what about StaticRef?? } } } } - //<><><><><><> pub fn declare_proc_parse( @@ -258,7 +272,7 @@ impl Scope { } }) .collect(), - false + true ); } diff --git a/ltcc/src/main.rs b/ltcc/src/main.rs index f07337a..813134b 100644 --- a/ltcc/src/main.rs +++ b/ltcc/src/main.rs @@ -77,9 +77,9 @@ fn main() { } } - compiler = compiler.compile_expr(&ast); + compiler = compiler.compile_expr(&ast, true); let diagnostics = compiler.diagnostics.clone(); - let (exports, proc_code) = compiler.get_bytecode(false); + let (exports, proc_code) = compiler.get_bytecode(); for (region, message) in diagnostics { crate::diagnostic::print_diagnostic( @@ -89,8 +89,7 @@ fn main() { ); } - - eprintln!("{} {}", "Compiled".green(), path.bold()); + eprintln!("{} {}\n{}", "Compiled".green(), path.bold(), "---------------".green()); for (name, def) in exports.iter() { eprintln!("export {}:", name.yellow().bold()); let mut t = def.get_type(&mut main_scope); @@ -106,11 +105,12 @@ fn main() { /* link assembly-program to symbols */ - eprintln!("generated bytecode ({})", proc_code.len() ); - for (i,l) in tisc::assembler::disassemble(&proc_code).iter().enumerate() { - eprintln!("{} .... {}", i,l); - } - linker.add_procedure(path.as_str(), proc_code); + linker.add_procedure_front(path.as_str(), proc_code); + + main_scope.write().unwrap().update_link_addresses( + &path, + &linker + ); } Err( (region, parse_error) ) => { crate::diagnostic::print_diagnostic( @@ -125,6 +125,7 @@ fn main() { } } + eprintln!("write output file {}", args.output); let obj_file = tisc::linker::ObjectFile { symbols: Arc::into_inner(main_scope).unwrap().into_inner().unwrap() @@ -135,12 +136,12 @@ fn main() { if export { match link_addr { tisc::LinkAddr::Absolute(w) => { - eprintln!("add symbol {} -> {}", symbol, w); + // eprintln!("add symbol {} -> {}", symbol, w); Some(( symbol, w )) } tisc::LinkAddr::Relative{ symbol: b, offset } => { let addr = linker.get_link_addr(&b).unwrap_or(-1); - eprintln!("relative symbol {} -> {}({})+{}", symbol, b, addr, offset); + // eprintln!("relative symbol {} -> {}({})+{}", symbol, b, addr, offset); Some((symbol, addr + offset )) } } diff --git a/ltvm/src/main.rs b/ltvm/src/main.rs index 38e9704..6ba4a91 100644 --- a/ltvm/src/main.rs +++ b/ltvm/src/main.rs @@ -32,13 +32,21 @@ fn main() { std::fs::File::open(source_path).expect("Failed to open file") ); - linker.import( source_path, bincode::deserialize_from( input ).expect("") ); + let obj_file : tisc::linker::ObjectFile = bincode::deserialize_from( input ).expect(""); + + for (name, addr) in obj_file.symbols.iter() { + symbols.insert( + name.clone(), + tisc::LinkAddr::Relative{ + symbol: source_path.clone(), + offset: *addr + } + ); + } + linker.import( source_path, obj_file ); } let entry_addr = linker.get_link_addr(&args.entry).unwrap_or(0); - /* - .expect(&format!("cant find entry symbol '{}'", args.entry)); - */ let bytecode = linker.link_total().expect("Link error:"); eprintln!("{} ({} bytes)", "Loaded bytecode.".green(), bytecode.len());