Compare commits
8 commits
Author | SHA1 | Date | |
---|---|---|---|
4bc7fd1788 | |||
a948b53d9a | |||
45869fdd30 | |||
489d9886e3 | |||
b268544955 | |||
388454e083 | |||
6b577e91f8 | |||
5c2a610d31 |
12 changed files with 429 additions and 222 deletions
|
@ -2,5 +2,6 @@
|
||||||
members = [
|
members = [
|
||||||
"lib-ltcore",
|
"lib-ltcore",
|
||||||
"ltcc",
|
"ltcc",
|
||||||
"ltvm"
|
"ltvm",
|
||||||
|
"ltobjdump",
|
||||||
]
|
]
|
||||||
|
|
|
@ -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)?;
|
||||||
|
|
|
@ -20,7 +20,12 @@ pub struct ProcedureCompiler {
|
||||||
proc_symbol: String,
|
proc_symbol: String,
|
||||||
scope: Arc<RwLock<Scope>>,
|
scope: Arc<RwLock<Scope>>,
|
||||||
asm: tisc::Assembler,
|
asm: tisc::Assembler,
|
||||||
subroutines: Vec<tisc::assembler::AssemblyWord>,
|
subroutine_count: u32,
|
||||||
|
frame_size: u32,
|
||||||
|
|
||||||
|
in_types: Vec< laddertypes::TypeTerm >,
|
||||||
|
out_types: Vec< laddertypes::TypeTerm >,
|
||||||
|
|
||||||
pub linker: tisc::Linker,
|
pub linker: tisc::Linker,
|
||||||
pub diagnostics: Vec<( InputRegionTag, String )>
|
pub diagnostics: Vec<( InputRegionTag, String )>
|
||||||
}
|
}
|
||||||
|
@ -30,48 +35,36 @@ impl ProcedureCompiler {
|
||||||
ProcedureCompiler {
|
ProcedureCompiler {
|
||||||
proc_symbol,
|
proc_symbol,
|
||||||
scope,
|
scope,
|
||||||
subroutines: Vec::new(),
|
subroutine_count: 0,
|
||||||
|
frame_size: 0,
|
||||||
|
in_types: vec![],
|
||||||
|
out_types: vec![],
|
||||||
asm: tisc::Assembler::new(),
|
asm: tisc::Assembler::new(),
|
||||||
linker: tisc::Linker::new(),
|
linker: tisc::Linker::new(),
|
||||||
diagnostics: Vec::new()
|
diagnostics: Vec::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
pub fn export_symbols(&self) -> Vec<(String, SymbolDef)> {
|
pub fn make_subroutine_symbol(&mut self) -> String {
|
||||||
let mut scope = self.scope.write().unwrap();
|
let id = self.subroutine_count;
|
||||||
scope.update_link_addresses(&self.proc_symbol, &self.linker);
|
self.subroutine_count += 1;
|
||||||
scope.export()
|
format!("__{}_sub_{}__", self.proc_symbol, id)
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
pub fn get_bytecode(mut self, ret: bool) -> (
|
pub fn get_bytecode(mut self) -> (
|
||||||
Vec<(String, SymbolDef)>,
|
Vec<(String, SymbolDef)>,
|
||||||
Vec<tisc::assembler::AssemblyWord>
|
Vec<tisc::assembler::AssemblyWord>
|
||||||
) {
|
) {
|
||||||
let frame_size = self.scope.read().unwrap().get_frame_size();
|
if self.frame_size > 0 {
|
||||||
if frame_size > 0 {
|
|
||||||
let alloc_asm = tisc::Assembler::new()
|
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()
|
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 );
|
self.asm = alloc_asm.join( self.asm ).join( drop_asm );
|
||||||
}
|
}
|
||||||
|
|
||||||
let main_section = self.asm.build();
|
self.linker.add_procedure_front( &self.proc_symbol, 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 }
|
|
||||||
);
|
|
||||||
|
|
||||||
// replace all symbol definitions from subroutines
|
// replace all symbol definitions from subroutines
|
||||||
// with relative LinkAddr`s
|
// with relative LinkAddr`s
|
||||||
|
@ -80,22 +73,28 @@ impl ProcedureCompiler {
|
||||||
&self.linker
|
&self.linker
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let code =
|
||||||
|
self.linker.link_relative(&self.proc_symbol).expect("link error");
|
||||||
|
|
||||||
|
let mut export_symbols = self.scope.read().unwrap().export();
|
||||||
(
|
(
|
||||||
self.scope.read().unwrap().export(),
|
export_symbols,
|
||||||
self.linker.link_relative( &self.proc_symbol ).expect("link error")
|
code
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_statement(mut self, statement: &Statement, enable_export: bool) -> 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);
|
self = self.compile_expr(val_expr, true);
|
||||||
|
|
||||||
match self.scope.read().unwrap().get(var_id) {
|
match self.scope.read().unwrap().get(var_id) {
|
||||||
Some(SymbolDef::FrameRef { typ, stack_ref }) => {
|
Some(SymbolDef::FrameRef { typ, stack_ref }) => {
|
||||||
self.asm = self.asm.lit(stack_ref).call("data-frame-set");
|
self.asm = self.asm.lit(stack_ref).call("data-frame-set");
|
||||||
}
|
}
|
||||||
Some(SymbolDef::StaticRef { typ, link_addr }) => {
|
Some(SymbolDef::StaticRef { typ, link_addr, export }) => {
|
||||||
self.asm = self
|
self.asm = self
|
||||||
.asm
|
.asm
|
||||||
.static_ref(var_id.as_str())
|
.static_ref(var_id.as_str())
|
||||||
|
@ -127,35 +126,20 @@ impl ProcedureCompiler {
|
||||||
} => {
|
} => {
|
||||||
let val_type = self.scope.read().unwrap()
|
let val_type = self.scope.read().unwrap()
|
||||||
.get(var_id).unwrap()
|
.get(var_id).unwrap()
|
||||||
.get_type(&mut self.scope.clone());
|
.get_type(&mut self.scope.clone())
|
||||||
let val_type = val_type.sugar(&mut self.scope.clone());
|
.sugar(&mut self.scope.clone());
|
||||||
|
|
||||||
match val_type {
|
match val_type {
|
||||||
laddertypes::SugaredTypeTerm::Func(mut f_types) => {
|
laddertypes::SugaredTypeTerm::Func(mut f_types) => {
|
||||||
let mut c = ProcedureCompiler::new(
|
let mut c =
|
||||||
var_id.clone(),
|
ProcedureCompiler::new(
|
||||||
self.scope.clone()
|
var_id.clone(), self.scope.clone()
|
||||||
);
|
).compile_expr( val_expr, true );
|
||||||
c = c.compile_expr( val_expr );
|
|
||||||
self.diagnostics.append(&mut c.diagnostics);
|
self.diagnostics.append(&mut c.diagnostics);
|
||||||
|
|
||||||
let (symbols,code) = c.get_bytecode( true );
|
let (symbols,code) = c.get_bytecode();
|
||||||
eprintln!("LET assign compiled {}", var_id);
|
|
||||||
for (i,l) in tisc::assembler::disassemble( &code ).iter().enumerate() {
|
|
||||||
eprintln!("{}+{} ... {}", var_id, i, l);
|
|
||||||
}
|
|
||||||
self.linker.add_procedure(var_id, code);
|
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
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -163,27 +147,34 @@ impl ProcedureCompiler {
|
||||||
name_region: *name_region,
|
name_region: *name_region,
|
||||||
var_id: var_id.clone(),
|
var_id: var_id.clone(),
|
||||||
val_expr: val_expr.clone(),
|
val_expr: val_expr.clone(),
|
||||||
}, false);
|
});
|
||||||
|
|
||||||
|
self.frame_size += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Statement::Expr(expr) => {
|
Statement::Expr(expr) => {
|
||||||
self = self.compile_expr(expr);
|
self = self.compile_expr(expr, true);
|
||||||
}
|
}
|
||||||
Statement::Return(expr) => {
|
Statement::Return(expr) => {
|
||||||
self = self.compile_expr(expr);
|
self = self.compile_expr(expr, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self
|
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 {
|
match expr {
|
||||||
LTExpr::Symbol { region, typ, symbol } => match self.scope.read().unwrap().get(symbol) {
|
LTExpr::Symbol { region, typ, symbol } => match self.scope.read().unwrap().get(symbol) {
|
||||||
Some(SymbolDef::FrameRef { typ, stack_ref }) => {
|
Some(SymbolDef::FrameRef { typ, stack_ref }) => {
|
||||||
self.asm = self.asm.lit(stack_ref).call("data-frame-get");
|
self.asm = self.asm.lit(stack_ref).call("data-frame-get");
|
||||||
}
|
}
|
||||||
Some(SymbolDef::StaticRef { typ, link_addr }) => {
|
Some(SymbolDef::StaticRef { typ, link_addr, export }) => {
|
||||||
self.asm = self.asm.static_ref(symbol.as_str());
|
self.asm = self.asm.static_ref(symbol.as_str());
|
||||||
}
|
}
|
||||||
Some(SymbolDef::Procedure {
|
Some(SymbolDef::Procedure {
|
||||||
|
@ -192,7 +183,11 @@ impl ProcedureCompiler {
|
||||||
link_addr,
|
link_addr,
|
||||||
export
|
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 => {
|
None => {
|
||||||
self.diagnostics.push(
|
self.diagnostics.push(
|
||||||
|
@ -210,10 +205,10 @@ impl ProcedureCompiler {
|
||||||
self.asm = self.asm.lit(*val);
|
self.asm = self.asm.lit(*val);
|
||||||
}
|
}
|
||||||
LTExpr::Ascend { region, typ, expr } => {
|
LTExpr::Ascend { region, typ, expr } => {
|
||||||
self = self.compile_expr(expr);
|
self = self.compile_expr(expr, call);
|
||||||
}
|
}
|
||||||
LTExpr::Descend { region, typ, expr } => {
|
LTExpr::Descend { region, typ, expr } => {
|
||||||
self = self.compile_expr(expr);
|
self = self.compile_expr(expr, call);
|
||||||
}
|
}
|
||||||
LTExpr::Branch {
|
LTExpr::Branch {
|
||||||
region,
|
region,
|
||||||
|
@ -221,14 +216,14 @@ impl ProcedureCompiler {
|
||||||
if_expr,
|
if_expr,
|
||||||
else_expr,
|
else_expr,
|
||||||
} => {
|
} => {
|
||||||
self = self.compile_expr(condition);
|
self = self.compile_expr(condition, true);
|
||||||
|
|
||||||
let asm = self.asm;
|
let asm = self.asm;
|
||||||
self.asm = tisc::Assembler::new();
|
self.asm = tisc::Assembler::new();
|
||||||
self = self.compile_expr(if_expr);
|
self = self.compile_expr(if_expr, true);
|
||||||
let if_asm = self.asm;
|
let if_asm = self.asm;
|
||||||
self.asm = tisc::Assembler::new();
|
self.asm = tisc::Assembler::new();
|
||||||
self = self.compile_expr(else_expr);
|
self = self.compile_expr(else_expr, true);
|
||||||
let else_asm = self.asm;
|
let else_asm = self.asm;
|
||||||
self.asm = asm;
|
self.asm = asm;
|
||||||
self.asm = self.asm.branch(if_asm, else_asm);
|
self.asm = self.asm.branch(if_asm, else_asm);
|
||||||
|
@ -237,34 +232,34 @@ impl ProcedureCompiler {
|
||||||
let asm = self.asm;
|
let asm = self.asm;
|
||||||
|
|
||||||
self.asm = tisc::Assembler::new();
|
self.asm = tisc::Assembler::new();
|
||||||
self = self.compile_expr(condition);
|
self = self.compile_expr(condition, true);
|
||||||
let cond_asm = self.asm;
|
let cond_asm = self.asm;
|
||||||
|
|
||||||
self.asm = tisc::Assembler::new();
|
self.asm = tisc::Assembler::new();
|
||||||
self = self.compile_expr(body);
|
self = self.compile_expr(body, true);
|
||||||
let body_asm = self.asm;
|
let body_asm = self.asm;
|
||||||
|
|
||||||
self.asm = asm;
|
self.asm = asm;
|
||||||
self.asm = self.asm.while_loop(cond_asm, body_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() {
|
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 } => {
|
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() {
|
for (region, arg_name, arg_type) in args.iter() {
|
||||||
match scope.read().unwrap().get(arg_name) {
|
match scope.read().unwrap().get(arg_name) {
|
||||||
Some(SymbolDef::FrameRef{ typ, stack_ref }) => {
|
Some(SymbolDef::FrameRef{ typ, stack_ref }) => {
|
||||||
eprintln!("Arg {} stack ref = {}", arg_name, stack_ref);
|
|
||||||
|
|
||||||
// TODO: aknowledge actual size of arguments
|
// TODO: aknowledge actual size of arguments
|
||||||
// let arg_size = typ.get_size()
|
// let arg_size = typ.get_size()
|
||||||
let arg_size = 1;
|
let arg_size = 1;
|
||||||
|
|
||||||
|
abs_compiler.frame_size += 1;
|
||||||
for i in 0..arg_size {
|
for i in 0..arg_size {
|
||||||
abs_compiler.asm = abs_compiler.asm
|
abs_compiler.asm = abs_compiler.asm
|
||||||
.lit(stack_ref + i)
|
.lit(stack_ref + i)
|
||||||
|
@ -280,50 +275,23 @@ impl ProcedureCompiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abs_compiler = abs_compiler.compile_expr( body );
|
abs_compiler = abs_compiler.compile_expr( body, true );
|
||||||
let (abs_symbols, mut abs_code) = abs_compiler.get_bytecode( false );
|
let (abs_export_symbols, mut abs_code) = abs_compiler.get_bytecode();
|
||||||
|
self.scope.write().unwrap().import( abs_export_symbols );
|
||||||
for (s,def) in abs_symbols.iter() {
|
self.linker.add_procedure( &abs_symbol, abs_code );
|
||||||
eprintln!("{} = {:?}", s, def);
|
self.asm = self.asm.call( &abs_symbol );
|
||||||
}
|
|
||||||
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
|
|
||||||
);*/
|
|
||||||
}
|
}
|
||||||
LTExpr::Block { region, scope, statements } => {
|
LTExpr::ExportBlock{ region, scope, statements }
|
||||||
let mut block_compiler = ProcedureCompiler::new(
|
| LTExpr::Block { region, scope, statements } => {
|
||||||
"__block__".into(),
|
let block_symbol = self.make_subroutine_symbol();
|
||||||
scope.clone()
|
let mut block_compiler = ProcedureCompiler::new( block_symbol.clone(), scope.clone() );
|
||||||
);
|
|
||||||
|
|
||||||
for stmnt in statements.iter() {
|
for stmnt in statements.iter() {
|
||||||
block_compiler = block_compiler.compile_statement( stmnt, true );
|
block_compiler = block_compiler.compile_statement( stmnt );
|
||||||
}
|
}
|
||||||
|
let (block_export_symbols, mut block_code) = block_compiler.get_bytecode();
|
||||||
let (block_symbols, mut block_code) = block_compiler.get_bytecode( true );
|
self.scope.write().unwrap().import( block_export_symbols );
|
||||||
|
self.linker.add_procedure( &block_symbol, block_code.clone() );
|
||||||
eprintln!("BLOCK compiler:");
|
self.asm = self.asm.call( &block_symbol );
|
||||||
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);
|
|
||||||
}
|
|
||||||
LTExpr::ExportBlock{ region, scope, statements } => {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
|
|
|
@ -20,6 +20,7 @@ pub enum SymbolDef {
|
||||||
StaticRef {
|
StaticRef {
|
||||||
typ: laddertypes::TypeTerm,
|
typ: laddertypes::TypeTerm,
|
||||||
link_addr: Option<tisc::VM_Word>,
|
link_addr: Option<tisc::VM_Word>,
|
||||||
|
export: bool
|
||||||
},
|
},
|
||||||
Procedure {
|
Procedure {
|
||||||
in_types: Vec<laddertypes::TypeTerm>,
|
in_types: Vec<laddertypes::TypeTerm>,
|
||||||
|
@ -36,7 +37,7 @@ impl SymbolDef {
|
||||||
) -> laddertypes::TypeTerm {
|
) -> laddertypes::TypeTerm {
|
||||||
match self {
|
match self {
|
||||||
SymbolDef::FrameRef { typ, stack_ref: _ } => typ.clone(),
|
SymbolDef::FrameRef { typ, stack_ref: _ } => typ.clone(),
|
||||||
SymbolDef::StaticRef { typ, link_addr: _ } => typ.clone(),
|
SymbolDef::StaticRef { typ, link_addr: _, export: _ } => typ.clone(),
|
||||||
SymbolDef::Procedure {
|
SymbolDef::Procedure {
|
||||||
in_types,
|
in_types,
|
||||||
out_types,
|
out_types,
|
||||||
|
@ -153,6 +154,7 @@ impl Scope {
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(name, def)|
|
.filter(|(name, def)|
|
||||||
match def {
|
match def {
|
||||||
|
SymbolDef::StaticRef { typ:_, link_addr:_, export } => *export,
|
||||||
SymbolDef::Procedure { in_types:_, out_types:_, link_addr:_, export } => *export,
|
SymbolDef::Procedure { in_types:_, out_types:_, link_addr:_, export } => *export,
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
|
@ -207,25 +209,38 @@ impl Scope {
|
||||||
linker: &tisc::Linker
|
linker: &tisc::Linker
|
||||||
) {
|
) {
|
||||||
for (name, def) in self.symbols.iter_mut() {
|
for (name, def) in self.symbols.iter_mut() {
|
||||||
if let Some(offset) = linker.get_link_addr( name ) {
|
match def {
|
||||||
match def {
|
SymbolDef::Procedure {
|
||||||
SymbolDef::Procedure {
|
in_types:_,
|
||||||
in_types:_,out_types:_,
|
out_types:_,
|
||||||
link_addr,
|
link_addr,
|
||||||
export:_
|
export:_
|
||||||
} => {
|
} => {
|
||||||
|
if let Some(offset) = linker.get_link_addr( name ) {
|
||||||
|
// eprintln!("update link addr {} @ {} + {}", name, base_symbol, offset);
|
||||||
*link_addr = LinkAddr::Relative{
|
*link_addr = LinkAddr::Relative{
|
||||||
symbol: base_symbol.clone(),
|
symbol: base_symbol.clone(),
|
||||||
offset
|
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(
|
pub fn declare_proc_parse(
|
||||||
|
@ -258,7 +273,7 @@ impl Scope {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
false
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,15 +320,17 @@ impl Scope {
|
||||||
let typ = self
|
let typ = self
|
||||||
.parse(typ)
|
.parse(typ)
|
||||||
.expect("parse typeterm");
|
.expect("parse typeterm");
|
||||||
self.declare_static(String::from(name), typ);
|
self.declare_static(String::from(name), typ, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn declare_static(&mut self, name: String, typ: laddertypes::TypeTerm) {
|
pub fn declare_static(&mut self, name: String, typ: laddertypes::TypeTerm, export: bool) {
|
||||||
|
eprintln!("add {} export {}", name, export);
|
||||||
self.symbols.insert(
|
self.symbols.insert(
|
||||||
name,
|
name,
|
||||||
SymbolDef::StaticRef {
|
SymbolDef::StaticRef {
|
||||||
typ,
|
typ,
|
||||||
link_addr: None,
|
link_addr: None,
|
||||||
|
export
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,24 +23,39 @@ impl LTExpr {
|
||||||
Err(TypeError::Todo)
|
Err(TypeError::Todo)
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
pub fn infer_type(&self, scope: &Arc<RwLock<Scope>>) -> TypeTag
|
pub fn export_symbols(&self) -> Vec< (String, SymbolDef) > {
|
||||||
|
match self {
|
||||||
|
LTExpr::Block{ region, scope, statements }
|
||||||
|
| LTExpr::ExportBlock{
|
||||||
|
region,
|
||||||
|
scope,
|
||||||
|
statements
|
||||||
|
} => {
|
||||||
|
scope.read().unwrap().export()
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
@ -50,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();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -74,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) {
|
||||||
|
@ -112,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();
|
||||||
|
|
||||||
|
@ -126,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(),
|
||||||
|
@ -151,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)
|
||||||
|
@ -168,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)
|
||||||
|
@ -176,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)
|
||||||
|
@ -208,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(),
|
||||||
|
@ -230,8 +245,14 @@ impl LTExpr {
|
||||||
LTExpr::Block{ region, scope, statements } => {
|
LTExpr::Block{ region, scope, statements } => {
|
||||||
let mut types = Vec::new();
|
let mut types = Vec::new();
|
||||||
|
|
||||||
|
let enable_export =
|
||||||
|
match self {
|
||||||
|
LTExpr::ExportBlock{ region:_, scope:_, statements:_ } => true,
|
||||||
|
_ => false
|
||||||
|
};
|
||||||
|
|
||||||
for s in statements {
|
for s in statements {
|
||||||
match s.infer_type(scope) {
|
match s.infer_type(scope, enable_export) {
|
||||||
Ok(Some(t)) => {
|
Ok(Some(t)) => {
|
||||||
if !t.is_empty() {
|
if !t.is_empty() {
|
||||||
types.insert(0, t);
|
types.insert(0, t);
|
||||||
|
@ -244,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) }
|
||||||
|
@ -255,8 +281,47 @@ impl LTExpr {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Statement {
|
impl Statement {
|
||||||
pub fn infer_type(&self, scope: &Arc<RwLock<Scope>>) -> 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 )?;
|
||||||
|
|
||||||
|
@ -271,18 +336,17 @@ impl Statement {
|
||||||
let in_types = args.into_iter().map(|t| t.desugar(&mut scope.clone())).collect();
|
let in_types = args.into_iter().map(|t| t.desugar(&mut scope.clone())).collect();
|
||||||
|
|
||||||
scope.write().unwrap()
|
scope.write().unwrap()
|
||||||
.declare_proc(
|
.declare_proc(
|
||||||
var_id.clone(),
|
var_id.clone(),
|
||||||
in_types,
|
in_types,
|
||||||
out_types,
|
out_types,
|
||||||
true
|
enable_export
|
||||||
);
|
);
|
||||||
|
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
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 = {}", id);
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -291,6 +355,10 @@ impl Statement {
|
||||||
Statement::Expr(expr) => {
|
Statement::Expr(expr) => {
|
||||||
let t = expr.infer_type(scope)?;
|
let t = expr.infer_type(scope)?;
|
||||||
|
|
||||||
|
let symb = expr.export_symbols();
|
||||||
|
// eprintln!("expr statement: import symbols from expr {:?}", 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());
|
||||||
Ok(Some(st))
|
Ok(Some(st))
|
||||||
|
|
151
ltcc/src/main.rs
151
ltcc/src/main.rs
|
@ -17,6 +17,19 @@ use {
|
||||||
|
|
||||||
mod diagnostic;
|
mod diagnostic;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO:
|
||||||
|
* - import function symbols (use / import statement)
|
||||||
|
* - parse float literals
|
||||||
|
* - return type annotation
|
||||||
|
* - write to address resulting from expression
|
||||||
|
* - sized objects
|
||||||
|
* - typecheck stack
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(version, about, long_about = None)]
|
#[command(version, about, long_about = None)]
|
||||||
struct Args {
|
struct Args {
|
||||||
|
@ -32,7 +45,71 @@ fn main() {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
let mut linker = tisc::Linker::new();
|
let mut linker = tisc::Linker::new();
|
||||||
let root_scope = ltcore::runtime::init_runtime(&mut linker);
|
let mut runtime_linker = tisc::Linker::new();
|
||||||
|
|
||||||
|
let root_scope = ltcore::runtime::init_runtime(&mut runtime_linker);
|
||||||
|
let runtime_obj_file = tisc::linker::ObjectFile {
|
||||||
|
symbols: root_scope.read().unwrap().clone()
|
||||||
|
.export()
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|(symbol, def)| match def {
|
||||||
|
ltcore::symbols::SymbolDef::StaticRef { typ, link_addr, export } => {
|
||||||
|
if export {
|
||||||
|
if let Some(addr)= runtime_linker.get_link_addr(&symbol) {
|
||||||
|
Some((symbol, addr))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ltcore::symbols::SymbolDef::Procedure { in_types:_, out_types:_, link_addr, export } => {
|
||||||
|
if true {
|
||||||
|
match link_addr {
|
||||||
|
tisc::LinkAddr::Absolute(w) => {
|
||||||
|
// eprintln!("add symbol {} -> {}", symbol, w);
|
||||||
|
Some(( symbol, w ))
|
||||||
|
}
|
||||||
|
tisc::LinkAddr::Relative{ symbol: b, offset } => {
|
||||||
|
let addr = runtime_linker.get_link_addr(&b).unwrap_or(-1);
|
||||||
|
// eprintln!("relative symbol {} -> {}({})+{}", symbol, b, addr, offset);
|
||||||
|
Some((symbol, addr + offset))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => None
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
|
||||||
|
code: runtime_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: "runtime.lt.o".into(),
|
||||||
|
offset: a
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
w => w
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
let mut runtime_output = std::io::BufWriter::new(
|
||||||
|
std::fs::File::create("runtime.lt.o").expect("Failed to open file")
|
||||||
|
);
|
||||||
|
bincode::serialize_into( runtime_output, &runtime_obj_file );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let mut main_scope = Scope::with_parent(&root_scope);
|
let mut main_scope = Scope::with_parent(&root_scope);
|
||||||
|
|
||||||
for path in args.sources {
|
for path in args.sources {
|
||||||
|
@ -73,13 +150,13 @@ fn main() {
|
||||||
|
|
||||||
eprintln!("----------------------------------");
|
eprintln!("----------------------------------");
|
||||||
eprintln!("{} ({} errors)", "Typecheck failed".bright_red().bold(), type_errs.len());
|
eprintln!("{} ({} errors)", "Typecheck failed".bright_red().bold(), type_errs.len());
|
||||||
return;
|
std::process::exit(-2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compiler = compiler.compile_expr(&ast);
|
compiler = compiler.compile_expr(&ast, true);
|
||||||
let diagnostics = compiler.diagnostics.clone();
|
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 {
|
for (region, message) in diagnostics {
|
||||||
crate::diagnostic::print_diagnostic(
|
crate::diagnostic::print_diagnostic(
|
||||||
|
@ -89,28 +166,16 @@ fn main() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eprintln!("{} {}\n{}", "Compiled".green(), path.bold(), "---------------".green());
|
||||||
eprintln!("{} {}", "Compiled".green(), path.bold());
|
|
||||||
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
|
||||||
*/
|
*/
|
||||||
eprintln!("generated bytecode ({})", proc_code.len() );
|
linker.add_procedure_front(path.as_str(), proc_code);
|
||||||
for (i,l) in tisc::assembler::disassemble(&proc_code).iter().enumerate() {
|
|
||||||
eprintln!("{} .... {}", i,l);
|
main_scope.write().unwrap().update_link_addresses(
|
||||||
}
|
&path,
|
||||||
linker.add_procedure(path.as_str(), proc_code);
|
&linker
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Err( (region, parse_error) ) => {
|
Err( (region, parse_error) ) => {
|
||||||
crate::diagnostic::print_diagnostic(
|
crate::diagnostic::print_diagnostic(
|
||||||
|
@ -120,27 +185,43 @@ fn main() {
|
||||||
);
|
);
|
||||||
|
|
||||||
eprintln!("=======\nParse Error: Abort\n");
|
eprintln!("=======\nParse Error: Abort\n");
|
||||||
|
std::process::exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
eprintln!("write output file {}", args.output);
|
eprintln!("write output file {}", args.output);
|
||||||
let obj_file = tisc::linker::ObjectFile {
|
let obj_file = tisc::linker::ObjectFile {
|
||||||
symbols: Arc::into_inner(main_scope).unwrap().into_inner().unwrap()
|
symbols: Arc::into_inner(main_scope).unwrap().into_inner().unwrap()
|
||||||
.export()
|
.export()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|(symbol, def)| match def {
|
.filter_map(|(symbol, def)| match def {
|
||||||
|
ltcore::symbols::SymbolDef::StaticRef { typ, link_addr, export } => {
|
||||||
|
if export {
|
||||||
|
if let Some(addr) = linker.get_link_addr(&symbol) {
|
||||||
|
Some((symbol.clone(), addr))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
ltcore::symbols::SymbolDef::Procedure { in_types:_, out_types:_, link_addr, export } => {
|
ltcore::symbols::SymbolDef::Procedure { in_types:_, out_types:_, link_addr, export } => {
|
||||||
if export {
|
if export {
|
||||||
match link_addr {
|
match link_addr {
|
||||||
tisc::LinkAddr::Absolute(w) => {
|
tisc::LinkAddr::Absolute(w) => {
|
||||||
eprintln!("add symbol {} -> {}", symbol, w);
|
// eprintln!("add symbol {} -> {}", symbol, w);
|
||||||
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 {
|
||||||
|
@ -152,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(
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
use {
|
|
||||||
std::collections::HashMap,
|
|
||||||
std::sync::{Arc, RwLock},
|
|
||||||
std::{boxed::Box, ops::Deref},
|
|
||||||
tiny_ansi::TinyAnsi
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
lexer::InputRegionTag,
|
|
||||||
expr::{LTExpr, Statement},
|
|
||||||
procedure_compiler::ProcedureCompiler,
|
|
||||||
symbols::Scope,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* TODO:
|
|
||||||
* - import function symbols
|
|
||||||
* - Compiler error reporting
|
|
||||||
* - parse float literals
|
|
||||||
* - return type annotation
|
|
||||||
* - write to address resulting from expression
|
|
||||||
* - sized objects
|
|
||||||
* - Typecheck for LTExpr::Application
|
|
||||||
* - typecheck & inference for rest
|
|
||||||
*/
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
// create virtual machine with 4096 words of memory
|
|
||||||
let mut vm = tisc::VM::new(0x1000);
|
|
||||||
|
|
||||||
}
|
|
14
ltobjdump/Cargo.toml
Normal file
14
ltobjdump/Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "ltobjdump"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
laddertypes = { path = "../../lib-laddertypes" }
|
||||||
|
ltcore = { path = "../lib-ltcore" }
|
||||||
|
tisc = { path = "../../lib-tisc" }
|
||||||
|
clap = { version = "4.5.15", features = ["derive"] }
|
||||||
|
tiny-ansi = "0.1.0"
|
||||||
|
iterate-text = "0.0.1"
|
||||||
|
bincode = "1.3.3"
|
||||||
|
|
50
ltobjdump/src/main.rs
Normal file
50
ltobjdump/src/main.rs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
use {
|
||||||
|
std::io::Read,
|
||||||
|
clap::Parser,
|
||||||
|
tiny_ansi::TinyAnsi,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
#[command(version, about, long_about = None)]
|
||||||
|
struct Args {
|
||||||
|
/// source files
|
||||||
|
sources: Vec< String >,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args = Args::parse();
|
||||||
|
|
||||||
|
for source_path in args.sources.iter() {
|
||||||
|
let mut input = std::io::BufReader::new(
|
||||||
|
std::fs::File::open(source_path).expect("Failed to open file")
|
||||||
|
);
|
||||||
|
|
||||||
|
let obj_file : tisc::linker::ObjectFile
|
||||||
|
= bincode::deserialize_from( input ).expect("");
|
||||||
|
|
||||||
|
println!("{}\n{}", source_path.bold().yellow(), "------------".green());
|
||||||
|
println!("{}", "Symbols".bold().white());
|
||||||
|
|
||||||
|
for (name, addr) in obj_file.symbols.iter() {
|
||||||
|
println!("{} @ {}", name.bold().yellow(), format!("{:#010x}", addr).blue());
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{}\n{}", "------------".green(),
|
||||||
|
"Code".bold().white());
|
||||||
|
|
||||||
|
for (i,l) in tisc::assembler::disassemble( &obj_file.code )
|
||||||
|
.into_iter().enumerate()
|
||||||
|
{
|
||||||
|
for (name, addr) in obj_file.symbols.iter() {
|
||||||
|
if *addr == i as tisc::VM_Word {
|
||||||
|
println!("{}:", name.bold().yellow());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{} {}", format!("{:#06x}",i).blue(), l.green());
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{}\n", "============".green());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,20 +25,16 @@ fn main() {
|
||||||
let mut vm = tisc::VM::new( args.memsize );
|
let mut vm = tisc::VM::new( args.memsize );
|
||||||
let mut linker = tisc::Linker::new();
|
let mut linker = tisc::Linker::new();
|
||||||
|
|
||||||
let mut symbols = std::collections::HashMap::<String, tisc::LinkAddr>::new();
|
|
||||||
|
|
||||||
for source_path in args.sources.iter() {
|
for source_path in args.sources.iter() {
|
||||||
let mut input = std::io::BufReader::new(
|
let mut input = std::io::BufReader::new(
|
||||||
std::fs::File::open(source_path).expect("Failed to open file")
|
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("");
|
||||||
|
linker.import( source_path, obj_file );
|
||||||
}
|
}
|
||||||
|
|
||||||
let entry_addr = linker.get_link_addr(&args.entry).unwrap_or(0);
|
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:");
|
let bytecode = linker.link_total().expect("Link error:");
|
||||||
|
|
||||||
eprintln!("{} ({} bytes)", "Loaded bytecode.".green(), bytecode.len());
|
eprintln!("{} ({} bytes)", "Loaded bytecode.".green(), bytecode.len());
|
||||||
|
|
Loading…
Reference in a new issue