diff --git a/src/lexer.rs b/src/lexer.rs index 2941c6a..c8cfa86 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -143,7 +143,7 @@ where It: Iterator if c.is_whitespace() || *c == '(' || *c == ')' || *c == '{' || *c == '}' - || *c == ';' + || *c == ';' || *c == '=' || *c == ':' { // finish the current token diff --git a/src/main.rs b/src/main.rs index 0b3dba9..db260a8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,7 @@ use crate::{ procedure_compiler::ProcedureCompiler }; -fn compile(scope: &Arc>, source: &str) -> Vec< tisc::assembler::AssemblyWord > { +fn compile(scope: &Arc>, name: &str, source: &str) -> Vec< tisc::assembler::AssemblyWord > { ProcedureCompiler::new(scope) .compile( &parser::parse_expr( @@ -26,8 +26,7 @@ fn compile(scope: &Arc>, source: &str) -> Vec< tisc::assembler::As ).peekable() ).expect("syntax error") ) - .into_asm() - .build() + .into_asm(&name.into()) } fn main() { @@ -59,34 +58,38 @@ fn main() { ~" ); - main_scope.write().unwrap() - .declare_proc_parse( - "print-nullterm", - vec![], - vec![ - "~> - ~machine::Address - ~machine::Word" - ], - vec![]); - - main_scope.write().unwrap().declare_proc_parse( - "print-lenprefix", - vec![], - vec![ - "~> - ~machine::Address - ~machine::Word" - ], - vec![]); - - - /* link assembly-program to symbols */ linker.add_procedure("main", compile(&main_scope, + "main", "{ - print-lenprefix pfxstr; + let print-nullterm = λstr { + while (@ str) { + emit (@ str); + ! str (i+ str 1); + } + }; + + let print-lenprefix = λstr { + let len = (@ str); + ! str (i+ str 1); + let end = (i+ str len); + while (i- str end) { + emit (@ str); + ! str (i+ str 1); + } + }; + + let hello = λ _ { + print-nullterm hello-string; + print-lenprefix pfxstr; + }; + let isquare = λx (i* x x); + + hello 'X'; + emit '\n'; + emit (i+ '0' (isquare 3)); + emit '\n'; }")); linker.add_static("hello-string", @@ -96,29 +99,9 @@ fn main() { .collect()); linker.add_static("pfxstr", - vec![ 4, 'a' as tisc::VM_Word, 'b' as tisc::VM_Word, 'c' as tisc::VM_Word, 'd' as tisc::VM_Word ] + vec![ 3, 'a' as tisc::VM_Word, 'b' as tisc::VM_Word, 'c' as tisc::VM_Word, 'd' as tisc::VM_Word ] ); - linker.add_procedure("print-nullterm", compile(&main_scope, - "λ str { - while (@ str) { - emit (@ str); - ! str (i+ str 1); - } - }")); - - linker.add_procedure("print-lenprefix", compile(&main_scope, - "λ str { - let len = @ str; - ! str (i+ str 1); - let end = i+ str len; - while (i- str end) { - emit (@ str); - ! str (i+ str 1); - } - }" - )); - let main_addr = linker.get_link_addr(&"main".into()).expect("'main' not linked"); vm.load( linker.link_total().expect("could not link") ); vm.execute( main_addr ); diff --git a/src/parser.rs b/src/parser.rs index 5a81a07..d80724c 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -57,6 +57,7 @@ where It: Iterator match sym.as_str() { "!" => { tokens.next(); + // todo accept address-expression instead of symbol let name = parse_symbol(tokens)?; let val_expr = parse_expr(tokens)?; let _ = parse_expect(tokens, LTIRToken::StatementSep)?; diff --git a/src/procedure_compiler.rs b/src/procedure_compiler.rs index 7d69841..b7a23a4 100644 --- a/src/procedure_compiler.rs +++ b/src/procedure_compiler.rs @@ -4,6 +4,10 @@ use { sync::{Arc, RwLock}, ops::Deref, }, + tisc::{ + assembler::AssemblyWord, + linker::LinkAddr + }, crate::{ expr::{LTExpr, Statement}, symbols::{Scope, SymbolDef} @@ -27,14 +31,41 @@ impl ProcedureCompiler { } } - pub fn into_asm(self) -> tisc::Assembler { + pub fn into_asm(mut self, proc_symbol: &String) -> Vec< tisc::assembler::AssemblyWord > { let data_frame_size = self.symbols.read().unwrap().get_frame_size() as i64; - tisc::Assembler::new() - .lit(data_frame_size) - .call("data-frame-alloc") - .join(self.asm) - .lit(data_frame_size) - .call("data-frame-drop") + + let body = self.asm.build(); + self.linker.add_procedure("__procedure_body__", body); + let body_addr = self.linker.get_link_addr(&"__procedure_body__".into()).unwrap(); + let subroutines = self.linker.link_relative(&"__subroutines__".into()).expect("link error"); + + let mut entry = tisc::Assembler::new(); + if data_frame_size > 0 { + entry = entry + .lit(data_frame_size) + .call("data-frame-alloc"); + } + entry = entry + .call_symbol( LinkAddr::Relative{ symbol: "__subroutines__".into(), offset: body_addr }); + + if data_frame_size > 0 { + entry = entry + .lit(data_frame_size) + .call("data-frame-drop"); + } + + let mut superlink = tisc::Linker::new(); + superlink.add_procedure("", entry.build()); + superlink.add_procedure("__subroutines__", subroutines); + + let bytecode = superlink.link_relative(proc_symbol).expect("link error"); +/* + eprintln!("\n\n{}:", proc_symbol); + for (i,w) in tisc::assembler::disassemble(&bytecode).iter().enumerate() { + eprintln!("{}:\t\t{}", i, w); + } +*/ + bytecode } pub fn verify(&self) { @@ -68,18 +99,37 @@ impl ProcedureCompiler { } } Statement::LetAssign{ var_id, val_expr } => { - self.symbols.write().unwrap() - .declare_var( - var_id.clone(), - laddertypes::TypeTerm::unit() - ); + match val_expr { + LTExpr::Abstraction { arg_id:_, arg_type:_, val_expr:_ } => { + self.symbols.write().unwrap() + .declare_proc( + var_id.clone(), + vec![],vec![] + ); + let lambda_procedure = + ProcedureCompiler::new(&self.symbols) + .compile( val_expr ) + .into_asm( var_id ); - self = self.compile_statement( - &Statement::Assignment { - var_id: var_id.clone(), - val_expr: val_expr.clone() + self.linker.add_procedure( + var_id, + lambda_procedure + ); } - ); + _ => { + self.symbols.write().unwrap() + .declare_var( + var_id.clone(), + laddertypes::TypeTerm::unit() + ); + self = self.compile_statement( + &Statement::Assignment { + var_id: var_id.clone(), + val_expr: val_expr.clone() + } + ); + } + } } Statement::WhileLoop { condition, body } => { let asm = self.asm; @@ -126,7 +176,7 @@ impl ProcedureCompiler { eprintln!("undefined symbol '{}'!", symbol); } } - }, + } LTExpr::Literal { typ, val } => { self.asm = self.asm.lit( *val ); } @@ -135,7 +185,7 @@ impl ProcedureCompiler { self = self.compile(arg); } self = self.compile(head); - }, + } LTExpr::Abstraction { arg_id: arg_name, arg_type, val_expr } => { let id = self.symbols .write().unwrap() @@ -148,7 +198,7 @@ impl ProcedureCompiler { .call("data-frame-set"); self = self.compile(val_expr); - }, + } LTExpr::Branch { condition, if_expr, else_expr } => { self = self.compile(condition); diff --git a/src/runtime.rs b/src/runtime.rs index fe43f21..0bf2cce 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -193,37 +193,6 @@ pub fn init_runtime(linker: &mut Linker) -> Arc> { .build() ); - - /* - * let isquare = λx.(i* x x); - */ - symbols.write().unwrap().declare_proc_parse( - "isquare", - vec![], - vec![ "ℤ_2^64~machine::UInt64~machine::Word" ], - vec![ "ℤ_2^64~machine::UInt64~machine::Word" ]); - - linker.add_procedure( - "isquare", - ProcedureCompiler::new(&symbols) - .compile( - <Expr::abstraction( - "x", - "ℤ_2^64~machine::UInt64~machine::Word", - - LTExpr::application( - LTExpr::symbol("i*"), - vec![ - LTExpr::symbol("x"), - LTExpr::symbol("x") - ] - ) - ) - ) - .into_asm() - .build() - ); - symbols.write().unwrap().declare_static_parse( "data-frame-ptr", ">~machine::Address~machine::Word"