add import statement
ltcc: map all outputted bytecode such that absolute addresses become relative to the file typing: rename scope to super_scope
This commit is contained in:
parent
a948b53d9a
commit
4bc7fd1788
6 changed files with 122 additions and 46 deletions
|
@ -7,4 +7,5 @@ edition = "2021"
|
||||||
laddertypes = { path = "../../lib-laddertypes", features = ["pretty"] }
|
laddertypes = { path = "../../lib-laddertypes", features = ["pretty"] }
|
||||||
tisc = { path = "../../lib-tisc" }
|
tisc = { path = "../../lib-tisc" }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
iterate-text = "0.0.1"
|
||||||
tiny-ansi = "0.1.0"
|
tiny-ansi = "0.1.0"
|
||||||
|
|
|
@ -12,6 +12,9 @@ use {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Statement {
|
pub enum Statement {
|
||||||
|
Import {
|
||||||
|
path: String,
|
||||||
|
},
|
||||||
Assignment {
|
Assignment {
|
||||||
name_region: InputRegionTag,
|
name_region: InputRegionTag,
|
||||||
var_id: String,
|
var_id: String,
|
||||||
|
|
|
@ -225,6 +225,28 @@ where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
|
||||||
val_expr,
|
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" => {
|
"return" => {
|
||||||
tokens.next();
|
tokens.next();
|
||||||
let expr = parse_expr(super_scope, tokens)?;
|
let expr = parse_expr(super_scope, tokens)?;
|
||||||
|
|
|
@ -85,6 +85,8 @@ impl ProcedureCompiler {
|
||||||
|
|
||||||
pub fn compile_statement(mut self, statement: &Statement) -> Self {
|
pub fn compile_statement(mut self, statement: &Statement) -> Self {
|
||||||
match statement {
|
match statement {
|
||||||
|
Statement::Import { path } => {
|
||||||
|
}
|
||||||
Statement::Assignment { name_region, var_id, val_expr } => {
|
Statement::Assignment { name_region, var_id, val_expr } => {
|
||||||
self = self.compile_expr(val_expr, true);
|
self = self.compile_expr(val_expr, true);
|
||||||
|
|
||||||
|
|
|
@ -38,24 +38,24 @@ impl LTExpr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn infer_type(&self, scope: &Arc<RwLock<Scope>>) -> TypeTag
|
pub fn infer_type(&self, super_scope: &Arc<RwLock<Scope>>) -> TypeTag
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
LTExpr::WordLiteral{ region, val } => {
|
LTExpr::WordLiteral{ region, val } => {
|
||||||
Ok(scope.write().unwrap().parse(
|
Ok(super_scope.write().unwrap().parse(
|
||||||
"ℤ_2^64 ~ machine.UInt64 ~ machine.Word"
|
"machine.Int64 ~ machine.Word"
|
||||||
).unwrap())
|
).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
LTExpr::StringLiteral{ region, value } => {
|
LTExpr::StringLiteral{ region, value } => {
|
||||||
Ok(scope.write().unwrap().parse(
|
Ok(super_scope.write().unwrap().parse(
|
||||||
"<Seq Char ~ Unicode ~ ℤ_2^32 ~ ℤ_2^64 ~ machine.UInt64>
|
"<Seq Char ~ Unicode ~ ℤ_2^32 ~ ℤ_2^64 ~ machine.UInt64>
|
||||||
~ <TermArray 0 machine.UInt64 ~ machine.Word>"
|
~ <TermArray 0 machine.UInt64 ~ machine.Word>"
|
||||||
).unwrap())
|
).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
LTExpr::Symbol { region, typ, symbol } => {
|
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) {
|
if let Some(sdef) = s.get(symbol) {
|
||||||
Ok(sdef.get_type(&mut *s))
|
Ok(sdef.get_type(&mut *s))
|
||||||
} else {
|
} else {
|
||||||
|
@ -65,7 +65,7 @@ impl LTExpr {
|
||||||
}
|
}
|
||||||
|
|
||||||
LTExpr::Ascend { region, typ, expr } => {
|
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();
|
let sub_type = typ.clone();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -89,7 +89,7 @@ impl LTExpr {
|
||||||
}
|
}
|
||||||
|
|
||||||
LTExpr::Descend { region, typ, expr } => {
|
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();
|
let super_type = typ.clone();
|
||||||
|
|
||||||
if let Ok(i) = expr_type.is_syntactic_subtype_of(&super_type) {
|
if let Ok(i) = expr_type.is_syntactic_subtype_of(&super_type) {
|
||||||
|
@ -127,11 +127,11 @@ impl LTExpr {
|
||||||
}
|
}
|
||||||
|
|
||||||
LTExpr::Application{ region, typ, head, body } => {
|
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 args = body.into_iter();
|
||||||
|
|
||||||
let mut result_type = head_type;
|
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();
|
let mut errors = Vec::new();
|
||||||
|
|
||||||
|
@ -141,10 +141,10 @@ impl LTExpr {
|
||||||
for (argi, expected_arg_type) in f_types.iter().enumerate() {
|
for (argi, expected_arg_type) in f_types.iter().enumerate() {
|
||||||
if let Some(arg) = args.next() {
|
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
|
// 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() {
|
if ! received_arg_type.is_syntactic_subtype_of(&expected_arg_type).is_ok() {
|
||||||
errors.push(TypeError{
|
errors.push(TypeError{
|
||||||
region: arg.get_region(),
|
region: arg.get_region(),
|
||||||
|
@ -166,7 +166,7 @@ impl LTExpr {
|
||||||
|
|
||||||
return
|
return
|
||||||
if errors.len() == 0 {
|
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)
|
Ok(result_type)
|
||||||
} else {
|
} else {
|
||||||
Err(errors)
|
Err(errors)
|
||||||
|
@ -183,7 +183,7 @@ impl LTExpr {
|
||||||
}
|
}
|
||||||
|
|
||||||
if errors.len() == 0 {
|
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)
|
Ok(result_type)
|
||||||
} else {
|
} else {
|
||||||
Err(errors)
|
Err(errors)
|
||||||
|
@ -191,13 +191,13 @@ impl LTExpr {
|
||||||
}
|
}
|
||||||
|
|
||||||
LTExpr::Branch { region, condition, if_expr, else_expr } => {
|
LTExpr::Branch { region, condition, if_expr, else_expr } => {
|
||||||
let received_cond_type = condition.infer_type(scope)?;
|
let received_cond_type = condition.infer_type(super_scope)?;
|
||||||
let expected_cond_type = scope.write().unwrap().parse("Bool ~ machine.Word").unwrap();
|
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() {
|
if received_cond_type.is_syntactic_subtype_of(&expected_cond_type).is_ok() {
|
||||||
|
|
||||||
let if_expr_type = if_expr.infer_type(scope)?;
|
let if_expr_type = if_expr.infer_type(super_scope)?;
|
||||||
let else_expr_type = else_expr.infer_type(scope)?;
|
let else_expr_type = else_expr.infer_type(super_scope)?;
|
||||||
|
|
||||||
if if_expr_type.is_syntactic_subtype_of(&else_expr_type).is_ok() {
|
if if_expr_type.is_syntactic_subtype_of(&else_expr_type).is_ok() {
|
||||||
Ok(else_expr_type)
|
Ok(else_expr_type)
|
||||||
|
@ -223,14 +223,14 @@ impl LTExpr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LTExpr::WhileLoop { region, condition, body } => {
|
LTExpr::WhileLoop { region, condition, body } => {
|
||||||
let received_cond_type = condition.infer_type(scope)?;
|
let received_cond_type = condition.infer_type(super_scope)?;
|
||||||
let expected_cond_type = scope.write().unwrap().parse("Bool ~ machine.Word").unwrap();
|
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() {
|
if received_cond_type.is_syntactic_subtype_of(&expected_cond_type).is_ok() {
|
||||||
let body_type = body.infer_type(scope)?;
|
let body_type = body.infer_type(super_scope)?;
|
||||||
let body_type = body_type.sugar(&mut scope.clone());
|
let body_type = body_type.sugar(&mut super_scope.clone());
|
||||||
let loop_type = laddertypes::SugaredTypeTerm::Seq(vec![ body_type ]);
|
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 {
|
} else {
|
||||||
return Err(vec![ TypeError{
|
return Err(vec![ TypeError{
|
||||||
region: condition.get_region(),
|
region: condition.get_region(),
|
||||||
|
@ -250,7 +250,6 @@ impl LTExpr {
|
||||||
LTExpr::ExportBlock{ region:_, scope:_, statements:_ } => true,
|
LTExpr::ExportBlock{ region:_, scope:_, statements:_ } => true,
|
||||||
_ => false
|
_ => false
|
||||||
};
|
};
|
||||||
eprintln!(" .. in block (export={}) ", enable_export);
|
|
||||||
|
|
||||||
for s in statements {
|
for s in statements {
|
||||||
match s.infer_type(scope, enable_export) {
|
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(
|
Ok(
|
||||||
if types.len() == 1 { types.pop().unwrap() }
|
if types.len() == 1 { types.pop().unwrap() }
|
||||||
else { laddertypes::SugaredTypeTerm::Struct(types) }
|
else { laddertypes::SugaredTypeTerm::Struct(types) }
|
||||||
|
@ -279,6 +283,45 @@ impl LTExpr {
|
||||||
impl Statement {
|
impl Statement {
|
||||||
pub fn infer_type(&self, scope: &Arc<RwLock<Scope>>, enable_export: bool) -> Result< Option<laddertypes::SugaredTypeTerm> , Vec<TypeError> > {
|
pub fn infer_type(&self, scope: &Arc<RwLock<Scope>>, enable_export: bool) -> Result< Option<laddertypes::SugaredTypeTerm> , Vec<TypeError> > {
|
||||||
match self {
|
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 } => {
|
Statement::LetAssign{ name_region, typ, var_id, val_expr } => {
|
||||||
let typ = val_expr.infer_type( scope )?;
|
let typ = val_expr.infer_type( scope )?;
|
||||||
|
|
||||||
|
@ -304,7 +347,6 @@ impl Statement {
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let id = scope.write().unwrap().declare_var(var_id.clone(), typ);
|
let id = scope.write().unwrap().declare_var(var_id.clone(), typ);
|
||||||
eprintln!("TYPING declare var ({}) = {}, export ={}", var_id, id, enable_export);
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -314,8 +356,8 @@ impl Statement {
|
||||||
let t = expr.infer_type(scope)?;
|
let t = expr.infer_type(scope)?;
|
||||||
|
|
||||||
let symb = expr.export_symbols();
|
let symb = expr.export_symbols();
|
||||||
eprintln!("expr statement: import symbols from expr {:?}", symb);
|
// eprintln!("expr statement: import symbols from expr {:?}", symb);
|
||||||
scope.write().unwrap().import( symb );
|
// scope.write().unwrap().import( symb );
|
||||||
|
|
||||||
if t != laddertypes::TypeTerm::App(vec![]) {
|
if t != laddertypes::TypeTerm::App(vec![]) {
|
||||||
let st = t.sugar(&mut scope.clone());
|
let st = t.sugar(&mut scope.clone());
|
||||||
|
|
|
@ -54,12 +54,11 @@ fn main() {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|(symbol, def)| match def {
|
.filter_map(|(symbol, def)| match def {
|
||||||
ltcore::symbols::SymbolDef::StaticRef { typ, link_addr, export } => {
|
ltcore::symbols::SymbolDef::StaticRef { typ, link_addr, export } => {
|
||||||
eprintln!("runtime export static REF {}", export);
|
|
||||||
if export {
|
if export {
|
||||||
if let Some(addr)= link_addr {
|
if let Some(addr)= runtime_linker.get_link_addr(&symbol) {
|
||||||
Some((symbol, addr))
|
Some((symbol, addr))
|
||||||
} else {
|
} else {
|
||||||
Some((symbol.clone(), runtime_linker.get_link_addr(&symbol).unwrap_or(-1)))
|
None
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -168,18 +167,6 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln!("{} {}\n{}", "Compiled".green(), path.bold(), "---------------".green());
|
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
|
/* link assembly-program to symbols
|
||||||
*/
|
*/
|
||||||
|
@ -212,10 +199,10 @@ fn main() {
|
||||||
.filter_map(|(symbol, def)| match def {
|
.filter_map(|(symbol, def)| match def {
|
||||||
ltcore::symbols::SymbolDef::StaticRef { typ, link_addr, export } => {
|
ltcore::symbols::SymbolDef::StaticRef { typ, link_addr, export } => {
|
||||||
if export {
|
if export {
|
||||||
if let Some(addr)= link_addr {
|
if let Some(addr) = linker.get_link_addr(&symbol) {
|
||||||
Some((symbol.clone(), addr))
|
Some((symbol.clone(), addr))
|
||||||
} else {
|
} else {
|
||||||
Some((symbol.clone(), linker.get_link_addr(&symbol).unwrap_or(-1)))
|
None
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -229,9 +216,12 @@ fn main() {
|
||||||
Some(( symbol, w ))
|
Some(( symbol, w ))
|
||||||
}
|
}
|
||||||
tisc::LinkAddr::Relative{ symbol: b, offset } => {
|
tisc::LinkAddr::Relative{ symbol: b, offset } => {
|
||||||
let addr = linker.get_link_addr(&b).unwrap_or(-1);
|
if let Some(addr) = linker.get_link_addr(&b) {
|
||||||
// eprintln!("relative symbol {} -> {}({})+{}", symbol, b, addr, offset);
|
// eprintln!("relative symbol {} -> {}({})+{}", symbol, b, addr, offset);
|
||||||
Some((symbol, addr + offset ))
|
Some((symbol, addr + offset ))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -243,6 +233,22 @@ fn main() {
|
||||||
.collect(),
|
.collect(),
|
||||||
|
|
||||||
code: linker.link_partial().expect("Link error:")
|
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(
|
let mut output = std::io::BufWriter::new(
|
||||||
|
|
Loading…
Reference in a new issue