From 4bc7fd17888ea179482781fe2cc95056fac9c27c Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Mon, 21 Oct 2024 12:00:13 +0200 Subject: [PATCH] add import statement ltcc: map all outputted bytecode such that absolute addresses become relative to the file typing: rename scope to super_scope --- lib-ltcore/Cargo.toml | 1 + lib-ltcore/src/expr.rs | 3 + lib-ltcore/src/parser.rs | 22 +++++++ lib-ltcore/src/procedure_compiler.rs | 2 + lib-ltcore/src/typing.rs | 94 ++++++++++++++++++++-------- ltcc/src/main.rs | 46 ++++++++------ 6 files changed, 122 insertions(+), 46 deletions(-) diff --git a/lib-ltcore/Cargo.toml b/lib-ltcore/Cargo.toml index 6ed8c37..40d872b 100644 --- a/lib-ltcore/Cargo.toml +++ b/lib-ltcore/Cargo.toml @@ -7,4 +7,5 @@ edition = "2021" laddertypes = { path = "../../lib-laddertypes", features = ["pretty"] } tisc = { path = "../../lib-tisc" } serde = { version = "1.0", features = ["derive"] } +iterate-text = "0.0.1" tiny-ansi = "0.1.0" diff --git a/lib-ltcore/src/expr.rs b/lib-ltcore/src/expr.rs index 37b3f96..b9fec02 100644 --- a/lib-ltcore/src/expr.rs +++ b/lib-ltcore/src/expr.rs @@ -12,6 +12,9 @@ use { #[derive(Clone, Debug)] pub enum Statement { + Import { + path: String, + }, Assignment { name_region: InputRegionTag, var_id: String, diff --git a/lib-ltcore/src/parser.rs b/lib-ltcore/src/parser.rs index 249695d..b3f7fe6 100644 --- a/lib-ltcore/src/parser.rs +++ b/lib-ltcore/src/parser.rs @@ -225,6 +225,28 @@ where It: Iterator)> val_expr, }) } + "import" => { + let region = region.clone(); + tokens.next(); + + let tok = tokens.next(); + if let Some((path_region, path_token)) = tok { + match path_token { + Ok(LTIRToken::DoubleQuote(path_str)) => { + let _ = parse_expect(tokens, LTIRToken::StatementSep)?; + + Ok(Statement::Import { + path: path_str + }) + } + _ => { + Err((path_region, ParseError::UnexpectedToken)) + } + } + } else { + Err((region, ParseError::UnexpectedEnd)) + } + } "return" => { tokens.next(); let expr = parse_expr(super_scope, tokens)?; diff --git a/lib-ltcore/src/procedure_compiler.rs b/lib-ltcore/src/procedure_compiler.rs index f8f9791..1d4f16e 100644 --- a/lib-ltcore/src/procedure_compiler.rs +++ b/lib-ltcore/src/procedure_compiler.rs @@ -85,6 +85,8 @@ impl ProcedureCompiler { pub fn compile_statement(mut self, statement: &Statement) -> Self { match statement { + Statement::Import { path } => { + } Statement::Assignment { name_region, var_id, val_expr } => { self = self.compile_expr(val_expr, true); diff --git a/lib-ltcore/src/typing.rs b/lib-ltcore/src/typing.rs index 3ca4b57..2a7b24a 100644 --- a/lib-ltcore/src/typing.rs +++ b/lib-ltcore/src/typing.rs @@ -38,24 +38,24 @@ impl LTExpr { } } - pub fn infer_type(&self, scope: &Arc>) -> TypeTag + pub fn infer_type(&self, super_scope: &Arc>) -> TypeTag { match self { LTExpr::WordLiteral{ region, val } => { - Ok(scope.write().unwrap().parse( - "ℤ_2^64 ~ machine.UInt64 ~ machine.Word" + Ok(super_scope.write().unwrap().parse( + "machine.Int64 ~ machine.Word" ).unwrap()) } LTExpr::StringLiteral{ region, value } => { - Ok(scope.write().unwrap().parse( + Ok(super_scope.write().unwrap().parse( " ~ " ).unwrap()) } LTExpr::Symbol { region, typ, symbol } => { - let mut s = scope.write().unwrap(); + let mut s = super_scope.write().unwrap(); if let Some(sdef) = s.get(symbol) { Ok(sdef.get_type(&mut *s)) } else { @@ -65,7 +65,7 @@ impl LTExpr { } LTExpr::Ascend { region, typ, expr } => { - let expr_type = expr.infer_type( scope )?; + let expr_type = expr.infer_type( super_scope )?; let sub_type = typ.clone(); /* @@ -89,7 +89,7 @@ impl LTExpr { } LTExpr::Descend { region, typ, expr } => { - let expr_type = expr.infer_type(scope)?; + let expr_type = expr.infer_type(super_scope)?; let super_type = typ.clone(); if let Ok(i) = expr_type.is_syntactic_subtype_of(&super_type) { @@ -127,11 +127,11 @@ impl LTExpr { } LTExpr::Application{ region, typ, head, body } => { - let mut head_type = head.infer_type(scope)?; + let mut head_type = head.infer_type(super_scope)?; let mut args = body.into_iter(); let mut result_type = head_type; - let mut sugared_result_type = result_type.sugar(&mut *scope.write().unwrap()); + let mut sugared_result_type = result_type.sugar(&mut *super_scope.write().unwrap()); let mut errors = Vec::new(); @@ -141,10 +141,10 @@ impl LTExpr { for (argi, expected_arg_type) in f_types.iter().enumerate() { if let Some(arg) = args.next() { - let expected_arg_type = expected_arg_type.clone().desugar(&mut *scope.write().unwrap()); + let expected_arg_type = expected_arg_type.clone().desugar(&mut *super_scope.write().unwrap()); // check subtype - let received_arg_type = arg.infer_type(scope)?; + let received_arg_type = arg.infer_type(super_scope)?; if ! received_arg_type.is_syntactic_subtype_of(&expected_arg_type).is_ok() { errors.push(TypeError{ region: arg.get_region(), @@ -166,7 +166,7 @@ impl LTExpr { return if errors.len() == 0 { - result_type = sugared_result_type.desugar(&mut *scope.write().unwrap()); + result_type = sugared_result_type.desugar(&mut *super_scope.write().unwrap()); Ok(result_type) } else { Err(errors) @@ -183,7 +183,7 @@ impl LTExpr { } if errors.len() == 0 { - result_type = sugared_result_type.desugar(&mut *scope.write().unwrap()); + result_type = sugared_result_type.desugar(&mut *super_scope.write().unwrap()); Ok(result_type) } else { Err(errors) @@ -191,13 +191,13 @@ impl LTExpr { } LTExpr::Branch { region, condition, if_expr, else_expr } => { - let received_cond_type = condition.infer_type(scope)?; - let expected_cond_type = scope.write().unwrap().parse("Bool ~ machine.Word").unwrap(); + let received_cond_type = condition.infer_type(super_scope)?; + let expected_cond_type = super_scope.write().unwrap().parse("Bool ~ machine.Word").unwrap(); if received_cond_type.is_syntactic_subtype_of(&expected_cond_type).is_ok() { - let if_expr_type = if_expr.infer_type(scope)?; - let else_expr_type = else_expr.infer_type(scope)?; + let if_expr_type = if_expr.infer_type(super_scope)?; + let else_expr_type = else_expr.infer_type(super_scope)?; if if_expr_type.is_syntactic_subtype_of(&else_expr_type).is_ok() { Ok(else_expr_type) @@ -223,14 +223,14 @@ impl LTExpr { } } LTExpr::WhileLoop { region, condition, body } => { - let received_cond_type = condition.infer_type(scope)?; - let expected_cond_type = scope.write().unwrap().parse("Bool ~ machine.Word").unwrap(); + let received_cond_type = condition.infer_type(super_scope)?; + let expected_cond_type = super_scope.write().unwrap().parse("Bool ~ machine.Word").unwrap(); if received_cond_type.is_syntactic_subtype_of(&expected_cond_type).is_ok() { - let body_type = body.infer_type(scope)?; - let body_type = body_type.sugar(&mut scope.clone()); + let body_type = body.infer_type(super_scope)?; + let body_type = body_type.sugar(&mut super_scope.clone()); let loop_type = laddertypes::SugaredTypeTerm::Seq(vec![ body_type ]); - Ok(loop_type.desugar(&mut scope.clone())) + Ok(loop_type.desugar(&mut super_scope.clone())) } else { return Err(vec![ TypeError{ region: condition.get_region(), @@ -250,7 +250,6 @@ impl LTExpr { LTExpr::ExportBlock{ region:_, scope:_, statements:_ } => true, _ => false }; - eprintln!(" .. in block (export={}) ", enable_export); for s in statements { match s.infer_type(scope, enable_export) { @@ -266,6 +265,11 @@ impl LTExpr { } } + let export = scope.read().unwrap().export(); + super_scope.write().unwrap().import( + export + ); + Ok( if types.len() == 1 { types.pop().unwrap() } else { laddertypes::SugaredTypeTerm::Struct(types) } @@ -279,6 +283,45 @@ impl LTExpr { impl Statement { pub fn infer_type(&self, scope: &Arc>, enable_export: bool) -> Result< Option , Vec > { match self { + Statement::Import { path } => { + /* + * 1. load file + * 2. parse + * 3. infer types + * 3. import symbols + */ + let iter_chars = iterate_text::file::characters::IterateFileCharacters::new(path.clone()); + + /* compile source file + */ + let mut lexer = crate::lexer::LTIRLexer::from( iter_chars.peekable() ); + let mut program_tokens = + lexer + .filter(|tok| match tok { + (_, Ok(crate::lexer::LTIRToken::Comment(_))) => false, + _ => true + }) + .peekable(); + + let mut scope = scope.clone(); + match crate::parser::parse_expr( &mut scope, &mut program_tokens ) { + Ok( mut ast ) => { + + match ast.infer_type(&scope) { + Ok(mut t) => { + } + + Err(type_err) =>{ + eprintln!("In {} : Type Error", path); + } + } + } + Err( parse_err ) => { + eprintln!("In {} : Parse Error", path); + } + } + Ok(None) + } Statement::LetAssign{ name_region, typ, var_id, val_expr } => { let typ = val_expr.infer_type( scope )?; @@ -304,7 +347,6 @@ impl Statement { } _ => { let id = scope.write().unwrap().declare_var(var_id.clone(), typ); - eprintln!("TYPING declare var ({}) = {}, export ={}", var_id, id, enable_export); Ok(None) } } @@ -314,8 +356,8 @@ impl Statement { let t = expr.infer_type(scope)?; let symb = expr.export_symbols(); - eprintln!("expr statement: import symbols from expr {:?}", symb); - scope.write().unwrap().import( symb ); +// eprintln!("expr statement: import symbols from expr {:?}", symb); +// scope.write().unwrap().import( symb ); if t != laddertypes::TypeTerm::App(vec![]) { let st = t.sugar(&mut scope.clone()); diff --git a/ltcc/src/main.rs b/ltcc/src/main.rs index 2bb49bd..c8d9bc3 100644 --- a/ltcc/src/main.rs +++ b/ltcc/src/main.rs @@ -54,12 +54,11 @@ fn main() { .into_iter() .filter_map(|(symbol, def)| match def { ltcore::symbols::SymbolDef::StaticRef { typ, link_addr, export } => { - eprintln!("runtime export static REF {}", export); if export { - if let Some(addr)= link_addr { + if let Some(addr)= runtime_linker.get_link_addr(&symbol) { Some((symbol, addr)) } else { - Some((symbol.clone(), runtime_linker.get_link_addr(&symbol).unwrap_or(-1))) + None } } else { None @@ -168,18 +167,6 @@ fn main() { } 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); - t = t.normalize(); - t = t.param_normalize(); - let mut tc = main_scope.clone(); - eprintln!( "{}", t.sugar(&mut tc).pretty(&tc,0) ); - } - - main_scope.write().unwrap().import( - exports - ); /* link assembly-program to symbols */ @@ -212,10 +199,10 @@ fn main() { .filter_map(|(symbol, def)| match def { ltcore::symbols::SymbolDef::StaticRef { typ, link_addr, export } => { if export { - if let Some(addr)= link_addr { + if let Some(addr) = linker.get_link_addr(&symbol) { Some((symbol.clone(), addr)) } else { - Some((symbol.clone(), linker.get_link_addr(&symbol).unwrap_or(-1))) + None } } else { None @@ -229,9 +216,12 @@ fn main() { 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); - Some((symbol, addr + offset )) + if let Some(addr) = linker.get_link_addr(&b) { + // eprintln!("relative symbol {} -> {}({})+{}", symbol, b, addr, offset); + Some((symbol, addr + offset )) + } else { + None + } } } } else { @@ -243,6 +233,22 @@ fn main() { .collect(), code: linker.link_partial().expect("Link error:") + .into_iter() + .map(|w| match w { + tisc::assembler::AssemblyWord::Symbol( + tisc::LinkAddr::Absolute(a) + ) => { + tisc::assembler::AssemblyWord::Symbol( + tisc::LinkAddr::Relative{ + symbol: args.output.clone().into(), + offset: a + } + ) + }, + + w => w + }) + .collect() }; let mut output = std::io::BufWriter::new(