Compare commits

...
Sign in to create a new pull request.

9 commits
dev ... dev2

Author SHA1 Message Date
12c0a008df
wip 2024-12-24 12:51:36 +01:00
4bc7fd1788
add import statement
ltcc: map all outputted bytecode such that absolute addresses become relative to the file

typing: rename scope to super_scope
2024-10-21 12:00:13 +02:00
a948b53d9a
ltvm: remove unneccesary symbol table
(handled in linker now)
2024-10-21 11:52:01 +02:00
45869fdd30
fixup symbol export 2024-10-21 00:20:55 +02:00
489d9886e3
remove oldmain.rs 2024-10-18 22:05:10 +02:00
b268544955
ltcc: output separate runtime.lt.o to avoid duplication when loading multiple object files in ltvm 2024-10-18 21:24:10 +02:00
388454e083
add ltobjdump 2024-10-18 21:23:30 +02:00
6b577e91f8
fix compilation: insert procedures at front, ltvm: use 0 as default entrypoint 2024-10-18 21:22:56 +02:00
5c2a610d31
ltcc: exit with error code when typecheck or compilation fails 2024-10-18 21:13:44 +02:00
28 changed files with 646 additions and 753 deletions

View file

@ -2,5 +2,6 @@
members = [ members = [
"lib-ltcore", "lib-ltcore",
"ltcc", "ltcc",
"ltvm" "ltvm",
"ltobjdump",
] ]

View file

@ -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"

View file

@ -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,

View file

@ -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)?;

View file

@ -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: &LTExpr) -> Self { pub fn compile_expr(mut self, expr: &LTExpr, 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,11 +232,11 @@ 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;
@ -249,22 +244,22 @@ impl ProcedureCompiler {
} }
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

View file

@ -13,8 +13,8 @@ pub fn init_runtime(linker: &mut Linker) -> Arc<RwLock<Scope>> {
symbols.write().unwrap().declare_proc_parse( symbols.write().unwrap().declare_proc_parse(
"dup", "dup",
vec!["T"], vec!["T"],
vec!["T~machine.Word"], vec!["machine.Word"],
vec!["T~machine.Word", "T~machine.Word"], vec!["machine.Word", "machine.Word"],
); );
/* drop topmost element /* drop topmost element
@ -30,7 +30,7 @@ pub fn init_runtime(linker: &mut Linker) -> Arc<RwLock<Scope>> {
symbols.write().unwrap().declare_proc_parse( symbols.write().unwrap().declare_proc_parse(
"emit", "emit",
vec![], vec![],
vec!["Char~Unicode~_2^32~_2^64~machine.UInt64~machine.Word"], vec!["Char~Unicode~_2^32~machine.Int64~machine.Word"],
vec![], vec![],
); );
symbols.write().unwrap().declare_proc_parse( symbols.write().unwrap().declare_proc_parse(
@ -53,49 +53,54 @@ pub fn init_runtime(linker: &mut Linker) -> Arc<RwLock<Scope>> {
symbols.write().unwrap().declare_proc_parse( symbols.write().unwrap().declare_proc_parse(
"i+", "i+",
vec![], vec![],
vec![ vec!["machine.Int64","machine.Int64"],
"_2^64~machine.UInt64~machine.Word", vec!["machine.Int64"],
"_2^64~machine.UInt64~machine.Word", );
], symbols.write().unwrap().declare_proc_parse(
vec!["_2^64~machine.UInt64~machine.Word"], "u+",
vec![],
vec!["machine.UInt64","machine.UInt64"],
vec!["machine.UInt64"],
); );
symbols.write().unwrap().declare_proc_parse( symbols.write().unwrap().declare_proc_parse(
"i-", "i-",
vec![], vec![],
vec![ vec!["machine.Int64","machine.Int64"],
"_2^64~machine.UInt64~machine.Word", vec!["machine.Int64"],
"_2^64~machine.UInt64~machine.Word", );
], symbols.write().unwrap().declare_proc_parse(
vec!["_2^64~machine::UInt64~machine.Word"], "u-",
vec![],
vec!["machine.UInt64","machine.UInt64"],
vec!["machine.UInt64"],
); );
symbols.write().unwrap().declare_proc_parse( symbols.write().unwrap().declare_proc_parse(
"i*", "i*",
vec![], vec![],
vec![ vec![
"_2^64~machine.UInt64~machine.Word", "machine.Int64~machine.Word",
"_2^64~machine.UInt64~machine.Word", "machine.Int64~machine.Word",
], ],
vec!["_2^64~machine.UInt64~machine.Word"], vec!["machine.Int64~machine.Word"],
); );
symbols.write().unwrap().declare_proc_parse( symbols.write().unwrap().declare_proc_parse(
"i/", "i/",
vec![], vec![],
vec![ vec![
"_2^64~machine.UInt64~machine.Word", "machine.Int64~machine.Word",
"_2^64~machine.UInt64~machine.Word", "machine.Int64~machine.Word",
], ],
vec!["_2^64~machine.UInt64~machine.Word"], vec!["machine.Int64~machine.Word"],
); );
symbols.write().unwrap().declare_proc_parse( symbols.write().unwrap().declare_proc_parse(
"i%", "i%",
vec![], vec![],
vec![ vec![
"_2^64~machine.UInt64~machine.Word", "machine.Int64~machine.Word",
"_2^64~machine.UInt64~machine.Word", "machine.Int64~machine.Word",
], ],
vec!["_2^64~machine.UInt64~machine.Word"], vec!["machine.Int64~machine.Word"],
); );
symbols.write().unwrap().declare_proc_parse( symbols.write().unwrap().declare_proc_parse(
"f+", "f+",
vec![], vec![],
@ -146,6 +151,9 @@ pub fn init_runtime(linker: &mut Linker) -> Arc<RwLock<Scope>> {
vec!["~machine.f64~machine.Word"], vec!["~machine.f64~machine.Word"],
); );
linker.add_procedure("u+", tisc::Assembler::new().inst(tisc::VM_Instruction::IntAdd).build());
linker.add_procedure("u-", tisc::Assembler::new().inst(tisc::VM_Instruction::IntSub).build());
linker.add_procedure("i+", tisc::Assembler::new().inst(tisc::VM_Instruction::IntAdd).build()); linker.add_procedure("i+", tisc::Assembler::new().inst(tisc::VM_Instruction::IntAdd).build());
linker.add_procedure("i-", tisc::Assembler::new().inst(tisc::VM_Instruction::IntSub).build()); linker.add_procedure("i-", tisc::Assembler::new().inst(tisc::VM_Instruction::IntSub).build());
linker.add_procedure("i*", tisc::Assembler::new().inst(tisc::VM_Instruction::IntMul).build()); linker.add_procedure("i*", tisc::Assembler::new().inst(tisc::VM_Instruction::IntMul).build());
@ -162,7 +170,7 @@ pub fn init_runtime(linker: &mut Linker) -> Arc<RwLock<Scope>> {
symbols.write().unwrap().declare_proc_parse( symbols.write().unwrap().declare_proc_parse(
"bit-neg", "bit-neg",
vec![], vec!["machine.Word", "machine.Word"], vec!["machine.Word"], vec![], vec!["machine.Word"], vec!["machine.Word"],
); );
symbols.write().unwrap().declare_proc_parse( symbols.write().unwrap().declare_proc_parse(
"bit-and", "bit-and",
@ -176,7 +184,7 @@ pub fn init_runtime(linker: &mut Linker) -> Arc<RwLock<Scope>> {
"bit-xor", "bit-xor",
vec![], vec!["machine.Word", "machine.Word"], vec!["machine.Word"], vec![], vec!["machine.Word", "machine.Word"], vec!["machine.Word"],
); );
symbols.write().unwrap().declare_proc_parse( symbols.write().unwrap().declare_proc_parse(
"bit-shl", "bit-shl",
vec![], vec!["machine.Word", "machine.Word"], vec!["machine.Word"], vec![], vec!["machine.Word", "machine.Word"], vec!["machine.Word"],
); );
@ -217,12 +225,11 @@ pub fn init_runtime(linker: &mut Linker) -> Arc<RwLock<Scope>> {
linker.add_procedure("!", tisc::Assembler::new().inst(tisc::VM_Instruction::Store).build()); linker.add_procedure("!", tisc::Assembler::new().inst(tisc::VM_Instruction::Store).build());
let section_id = linker.add_static("data-frame-ptr", vec![0x1000]);
symbols.write().unwrap().declare_static_parse( symbols.write().unwrap().declare_static_parse(
"data-frame-ptr", "data-frame-ptr",
"<MutRef <Seq machine.Word>>~machine.Address~machine.Word", "<MutRef <Seq machine.Word>>~machine.Address~machine.Word",
); );
linker.add_static("data-frame-ptr", vec![0x1000]);
symbols.write().unwrap().declare_proc_parse( symbols.write().unwrap().declare_proc_parse(
"data-frame-set", "data-frame-set",

View file

@ -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,16 @@ 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) {
self.symbols.insert( self.symbols.insert(
name, name,
SymbolDef::StaticRef { SymbolDef::StaticRef {
typ, typ,
link_addr: None, link_addr: None,
export
}, },
); );
} }

View file

@ -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))
@ -316,4 +384,3 @@ impl Statement {
} }
} }
} }

View file

@ -1,4 +1,5 @@
export { export {
/*
let angle-normalize = let angle-normalize =
λ a : Angle λ a : Angle
~ Degree ~ Degree
@ -16,4 +17,5 @@ export {
~ ~
~ machine.Float64 ~ machine.Float64
↦ f/ a 360 ; ↦ f/ a 360 ;
*/
} }

31
lt-stdlib/bool.lt Normal file
View file

@ -0,0 +1,31 @@
/*
*
*/
export {
let bool-norm =
λ { x: Bool ~ machine.Word; }
↦ if(x) {
(1 des machine.Word) as Bool;
} else {
(0 des machine.Word) as Bool;
};
let bool-neg =
λ { x: Bool ~ machine.Word; }
↦ (bit-and (bit-neg (bool-norm x)) 1) as Bool;
let bool-or =
λ { a: Bool ~ machine.Word;
b: Bool ~ machine.Word; }
↦ (bit-or a b) as Bool ~ machine.Word;
let bool-and =
λ{ a: Bool ~ machine.Word;
b: Bool ~ machine.Word; }
↦ (bit-and (bool-norm a) (bool-norm b)) as Bool ~ machine.Word;
let bool-xor =
λ{ a: Bool ~ machine.Word;
b: Bool ~ machine.Word; }
↦ (bit-xor (bool-norm a) (bool-norm b)) as Bool ~ machine.Word;
}

View file

@ -1,63 +0,0 @@
export {
/* todo: allow machine.UInt8 in the VM
*/
let morph-rgb-to-hsv = λ{
{
red: _[0,1] ~ _256 ~ machine.UInt64;
green: _[0,1] ~ _256 ~ machine.UInt64;
blue: _[0,1] ~ _256 ~ machine.UInt64;
} : <Color sRGB>
~ RGB
~ <Vec3 _[0,1] ~ _256 ~ machine.UInt64>;
}
/*
-> <Color sRGB>
~ HSV
~ {
hue: Angle ~ Degrees ~ _0,360 ~ _360 ~ machine.UInt64 ;
sat: _[0,1] ~ _256 ~ machine.UInt64;
val: _[0,1] ~ _256 ~ machine.UInt64;
}
~ <Vec3 machine.UInt64>
*/
↦ {
let channel_max = int-max (int-max red green) blue;
let channel_min = int-min (int-min red green) blue;
let channel_delta = i- channel_max channel_min;
/* value */
channel_max;
/* saturation */
i/ (i* 255 channel_delta) channel_max;
/* hue */
i% (i/ (i* 60
if( int-eq channel_max red ) { i+ (i* 0 255) (i- green blue); }
else {
if( int-eq channel_max green ) { i+ (i* 2 255) (i- blue red); }
else { i+ (i* 4 255) (i- red green); };
}
)
channel_delta
)
360;
};
/*
let get-srgb-luminance =
-> _[0,1] ~ machine.Float64
λ{r:,g:,b:} : <Color sRGB> ~ RGB ~ <Vec3 _[0,1] ~ machine.Float64>
{
machine.Float64.mul red 0.22248840;
machine.Float64.mul green 0.71690369;
machine.Float64.mul blue 0.06060791;
machine.Float64.add;
machine.Float64.add;
// add (add (mul r 0.2) (mul g 0.7)) (mul b 0.6)
};
*/
}

View file

@ -1,10 +0,0 @@
export {
let complex-magnitude = λ{
{ re: , im: }
:
~ Cartesian
~ <Vec2 ~ machine.Float64>
} -> ↦ {
}
}

View file

@ -3,25 +3,27 @@
*/ */
export { export {
import "int.lt";
/* Euclidean Algorithm to calculate greatest common divisor /* Euclidean Algorithm to calculate greatest common divisor
*/ */
let gcd = λ{ let gcd = λ{
a : ~ machine.Int64; a : machine.Int64 ~ machine.Word;
b : ~ machine.Int64; b :machine.Int64 ~ machine.Word;
} ↦ { } ↦ {
while( b ) { while( int-gt b 0 ) {
let tmp = i% a b; let tmp = i% a b;
! a b; ! a b;
! b tmp; ! b tmp;
} };
a; a;
}; };
/* least common multiple /* least common multiple
*/ */
let lcm = λ{ let lcm = λ{
a : ~ machine.Int64; a : machine.Int64 ~ machine.Word;
b : ~ machine.Int64; b : machine.Int64 ~ machine.Word;
} ↦ i* (int-abs a) (i/ (int-abs b) (gcd a b)); } ↦ i* (int-abs a) (i/ (int-abs b) (gcd a b));
}; };

View file

@ -1,61 +0,0 @@
export {
/* Platform Specific Types */
type machine.Float16 = IEEE-754.half ~ <machine.Bits 16>;
type machine.Float32 = IEEE-754.single ~ <machine.Bits 32>;
type machine.Float64 = IEEE-754.double ~ <machine.Bits 64>;
overload + = λ{
a: ~ machine.Float16 ;
b: ~ machine.Float16 ;
} -> ~ machine.Float16 ↦ {
machine.Float16.add a b;
};
overload * = λ{
a: ~ machine.Float16 ;
b: ~ machine.Float16 ;
} -> ~ machine.Float16 ↦ {
machine.Float16.mul a b;
};
let Sign = enum { Positive; Negative; };
let Sign.Positive : <machine.Bits 1> = 0;
let Sign.Negative : <machine.Bits 1> = 1;
let softfloat16-mul = λ{
{
a.sign: Sign
~ <machine.Bits 1>
;
a.exponent: _[-14,15]
~ <BiasedInt -14>
~ _32
~ <PosInt 2 BigEndian>
~ <Seq <Digit 2>~Bit >
~ <machine.Bits 5>
;
a.significand: _2048
~ <PosInt 2 BigEndian>
~ <Seq <Digit2> ~ Bit>
~ <machine.Bits 11>
;
} :
~ IEEE-754.Half
~ <machine.Bits 16>
;
{
b.sign: <machine.Bits 1>;
} : ~ IEEE-754.Half ~ <machine.Bits 16> ;
} -> result: ~ IEEE~754.Half ~ <machine.Bits 16> ↦ {
/* 1. unify */
/* 2. add exponent */
+ a.exponent b.exponent;
/* 3. normaize */
result.sign = bit-xor a.sign b.sign ;
}
}

View file

@ -1,138 +0,0 @@
/* C++ */
template <typename T>
struct Sample {
T value;
};
template<> struct Sample< uint8_t > {
constexpr uint8_t min = std::numeric_limits<uint8_t>::min();
constexpr uint8_t max = std::numeric_limits<uint8_t>::max();
};
template<> struct Sample< uint16_t > {
constexpr uint16_t min = std::numeric_limits<uint16_t>::min();
constexpr uint16_t max = std::numeric_limits<uint16_t>::max();
};
template<> struct Sample< uint32_t > {
constexpr uint32_t min = std::numeric_limits<uint32_t>::min();
constexpr uint32_t max = std::numeric_limits<uint32_t>::max();
};
template<> struct Sample< float > {
constexpr float min = 0.0;
constexpr float max = 1.0;
};
template<> struct Sample< double > {
constexpr double min = 0.0;
constexpr double max = 1.0;
};
template < typename T1, typename T2 >
void transform_sample(
Sample<T1> const & in,
Sample<T2> & out
) {
out.value = static_cast<T1>( in.value * static_cast<T1>(Sample<T2>::max) ) / Sample<T1>::min;
}
/* LT IR */
@isomorphism
transform_sample <F: f32 | f64>
:: Sample ~ < 0,1> ~ f64
-> Sample ~ < 0,1> ~ _2^256 ~ u8
transform_sample f = floor( f * 256.0 ) as _2^256 ~ u8
@isomorphism
transform_sample :: Sample ~ < 0,1> ~ _2^256 ~ u8
-> Sample ~ < 0,1> ~ f64
transform_sample i = (i as ~f64) / 256.0
transform_sample <T1 T2> :: Sample~~T1 -> ~T2
transform_sample v
void main() {
// read Audio streams
for( unsigned i = 0; i < )
}
/* LT IR */
type Color~RGB = { r|red: _0,1; g|green: _0,1; b|blue: _0,1; }
type Color~HSL = { h|hue: _0,1; s|saturation: _0,1; l|lightness: _0,1; }
validate <> :: f64 -> {}
validate x = {}
morph :: Color~RGB -> Color~HSL
morph (r,g,b) = {
let h = .. TODO ..
...
(h,s,l)
}
morph :: _0,1 ~ f64 -> _0,1 ~ _256
morph x = (x * 256.0) % 256
morph :: _0,1 ~ _256 -> _0,1 ~ f64
morph x = (x as f64 / 256.0)
infix * :: ~f64 -> ~f64 -> ~f64
infix * a b = f64.mul a b
clamp :: -> -> ->
clamp minVal maxVal x = if x < minVal { minVal }
else if x > maxVal { maxVal }
else { x }
saturate :: -> Color~HSL -> Color~HSL
saturate f {h,s,l} = { h, clamp(f*s, 0.0, 1.0), l }
saturate_image :: -> [Color~HSL] -> [Color~HSL]
saturate_image f pixels = map saturate pixels
{
let width : = 4;
let height : = 2;
let pixels
: [
[
[ Color
~RGB
~[ _0,1
~_256
~<PosInt 16 BE>
~[<Digit 16>~Char]
; 3]
; width]
~<SepSeq Char ",[ ]*">~<Wrapped Char "[" "]">~[Char]
; height]
~<SepSeq Char ",[ ]*">~<Wrapped Char "[" "]">~[Char]
= [
[000000, 001122, 22ff33, ffe384],
[ff3344, abcdef, ffeebb, 44bb22]
];
pixels = saturate_image 0.3 pixels
let packed_buf = array_layout_rot
<
[[Color~RGB~[_0,1; 3]; width]; height],
[[Color; width]; height]; 3]
>
pixels;
}
brighten_image :: -> -> [Color] [[ Color~RGB~[~f64; 3]; width]; height] )

View file

@ -1,18 +1,95 @@
/* Two's complement Signed Integers /* Two's complement Signed Integers
*/ */
export { export {
let int-sign = λx:~machine.Int64 ↦ bit-and (bit-shr x 63) 1; import "./lt-stdlib/bool.lt";
let int-neg = λx:~machine.Int64 ↦ i+ (bit-neg x) 1;
let int-abs = λx:~machine.Int64 ↦ if( int-sign x ) { int-neg x; } else { x; };
let int-lt = λ{ a:~machine.Int64; b:~machine.Int64; } ↦ int-sign (i- a b);
let int-gt = λ{ a:~machine.Int64; b:~machine.Int64; } ↦ int-sign (i- b a);
let int-eq = λ{ a:~machine.Int64; b:~machine.Int64; } ↦ if (bit-xor a b) { 0; } else { 1; };
let int-lte = λ{ a:~machine.Int64; b:~machine.Int64; } ↦ bit-or (int-lt a b) (int-eq a b);
let int-gte = λ{ a:~machine.Int64; b:~machine.Int64; } ↦ bit-or (int-gt a b) (int-eq a b);
let int-min = λ{ a:~machine.Int64; b:~machine.Int64; } ↦ if( int-lt a b ) { a; } else { b; };
let int-max = λ{ a:~machine.Int64; b:~machine.Int64; } ↦ if( int-gt a b ) { a; } else { b; };
};
let int-sign =
λ x: machine.Int64~machine.Word
↦ (bit-and (bit-shr (x des machine.Word) 63) 1) as Bool;
let int-neg =
λ x: machine.Int64~machine.Word
↦ i+ ((bit-neg x) as machine.Int64) 1;
let int-abs =
λ x: machine.Int64~machine.Word
↦ if( int-sign x ) { int-neg x; } else { x; };
let int-lt =
λ{ a: machine.Int64~machine.Word;
b: machine.Int64~machine.Word; }
↦ int-sign (i- a b);
let int-gt =
λ{ a: machine.Int64~machine.Word;
b: machine.Int64~machine.Word; }
↦ int-sign (i- b a);
let int-neq =
λ{ a: machine.Int64~machine.Word;
b: machine.Int64~machine.Word; }
↦ (bit-xor a b) as Bool;
let int-eq =
λ{ a: machine.Int64~machine.Word;
b: machine.Int64~machine.Word; }
↦ bool-neg (int-neq a b);
let int-lte =
λ{ a: machine.Int64~machine.Word;
b: machine.Int64~machine.Word; }
↦ bool-or (int-lt a b) (int-eq a b);
let int-gte =
λ{ a: machine.Int64~machine.Word;
b: machine.Int64~machine.Word; }
↦ bool-or (int-gt a b) (int-eq a b);
let int-min =
λ{ a: machine.Int64~machine.Word;
b: machine.Int64~machine.Word; }
↦ if (int-lt a b) { a; } else { b; };
let int-max =
λ{ a:machine.Int64~machine.Word;
b:machine.Int64~machine.Word; }
↦ if (int-gt a b) { a; } else { b; };
/*
type machine.UInt64 = <UnsignedBinaryInt 64> ~ machine.Word;
impl _2^64 for machine.UInt64 {
let + = machine.UInt64.add;
let - = machine.UInt64.sub;
let * = machine.UInt64.mul;
let / = machine.UInt64.div;
let % = machine.UInt64.rem;
};
type machine.Int64 = <TwosComplementInt 64> ~ machine.Word;
let machine.Int64.add =
λ{ a: machine.Int64;
b: machine.Int64; }
↦ ((u+ ((a des machine.Word) as machine.UInt64)
((b des machine.Word) as machine.UInt64))
des machine.Word) as machine.Int64;
type =~ <PosInt 2^64 BigEndian> ~ <Seq <Digit 2^64>~_2^64~machine.UInt64>;
impl < -2^63-1 +2^63> for <TwosComplementInt 64> {
let + = machine.Int64.add;
let - = machine.Int64.sub;
let * = machine.Int64.mul;
let / = machine.Int64.div;
let % = machine.Int64.rem;
};
*/
/*
let int-onescomplement-neg =
λ x : < -2^63 +2^63> ~ <OnesComplementInt 64> ~ machine.Word
↦ (bit-neg x) as < -2^63 +2^63> ~ <OnesComplementInt 64>;
let int-twoscomplement-neg =
λ x : < -2^63-1 +2^63> ~ <TwosComplementInt 64> ~ machine.Word
↦ (i+ 1 ((bit-neg x) as machine.Int64)) as < -2^63-1 +2^63>;
*/
};

11
lt-stdlib/makefile Normal file
View file

@ -0,0 +1,11 @@
TARGETS=$(shell find -name '*.lt' | sed -E 's~\.lt~\.o~')
all: $(TARGETS)
%.o: %.lt
ltcc $< -o target/$@
clean:
cd target && rm $(TARGETS)

View file

@ -1,63 +0,0 @@
/* Positional Integer
*/
export {
let fmt-uint-radix = λ{
radix : ~ _2^64 ~ machine.UInt64;
x : ~ _2^64 ~ machine.UInt64;
} ↦ {
if( x ) {
while( x ) {
let digit = (i% x radix);
if( int-lt digit 10 ) {
i+ '0' digit;
} else {
i+ (i- 'a' 10) digit;
};
! x (i/ x radix);
}
} else {
'0';
};
};
let uint-machine-to-posint =
λ{
radix: ~ _2^64 ~ machine.UInt64;
value: ~ _2^64 ~ machine.UInt64;
}
/*
::>
~ <PosInt radix BigEndian>
~ <Seq <Digit radix>
~ _radix
~ _2^64
~ machine.UInt64>
~ <LengthPrefixedArray machine.UInt64>
*/
↦ {
let len = 0;
while( value ) {
/* push digit to sequence on stack */
i% value radix;
! value (i/ value radix);
! len (i+ len 1);
}
/* push length of sequence to stack */
len;
};
let fmt-int-radix = λ{
radix: ~ _2^64 ~ machine.UInt64;
x : ~ machine.Int64;
} ↦ {
fmt-uint-radix radix (int-abs x);
if( int-sign x ) { '-'; };
};
let fmt-uint = λx: ↦ fmt-uint-radix 10 x;
let fmt-int = λx: ↦ fmt-int-radix 10 x;
}

View file

@ -1,19 +1,30 @@
export { export {
import "int.lt";
import "euclidean.lt";
/* Implementation of Rational Numbers /* Implementation of Rational Numbers
*/ */
let ratio-sign = λ{
p: machine.Int64 ~ machine.Word;
q: machine.Int64 ~ machine.Word;
}
↦ bool-xor (int-sign p) (int-sign q);
let ratio-scale = λ{ let ratio-scale = λ{
{p:; q:;} : ~ <Ratio ~machine.UInt64> ; {
n : ~ machine.UInt64 ; p: machine.Int64~machine.Word;
q: machine.Int64~machine.Word;
} : ~ <Ratio machine.Int64~machine.Word>;
n : machine.Int64 ~machine.Word;
} ↦ { } ↦ {
i* q n; i* q n;
i* p n; i* p n;
}; };
let ratio-normalize = λ{ let ratio-normalize = λ{
p: ~machine.Int64; p: machine.Int64 ~ machine.Word;
q: ~machine.Int64; q: machine.Int64 ~ machine.Word;
} : ~ <Ratio ~machine.Int64> } : ~ <Ratio machine.Int64 ~ machine.Word>
↦ { ↦ {
let s = gcd p q; let s = gcd p q;
i/ q s; i/ q s;
@ -21,8 +32,14 @@ export {
}; };
let ratio-add = λ{ let ratio-add = λ{
{ap:; aq:;}: ~ <Ratio ~ _2^64 ~ machine.UInt64> ; {
{bp:; bq:;}: ~ <Ratio ~ _2^64 ~ machine.UInt64> ; ap:machine.Int64~machine.Word;
aq:machine.Int64~machine.Word;
}: ~ <Ratio machine.Int64 ~ machine.Word> ;
{
bp:machine.Int64~machine.Word;
bq:machine.Int64~machine.Word;
}: ~ <Ratio machine.Int64 ~ machine.Word> ;
} ↦ { } ↦ {
let l = lcm aq bq; let l = lcm aq bq;
let a = i/ l aq; let a = i/ l aq;
@ -33,13 +50,20 @@ export {
}; };
let ratio-mul = λ{ let ratio-mul = λ{
{ap:; aq:;}: ~ <Ratio ~ _2^64 ~ machine.Int64> ; {
{bp:; bq:;}: ~ <Ratio ~ _2^64 ~ machine.Int64> ; ap:machine.Int64~machine.Word;
aq:machine.Int64~machine.Word;
}: ~ <Ratio machine.Int64 ~ machine.Word> ;
{
bp:machine.Int64~machine.Word;
bq:machine.Int64~machine.Word;
}: ~ <Ratio machine.Int64 ~ machine.Word> ;
} ↦ ratio-normalize (i* ap bp) (i* aq bq); } ↦ ratio-normalize (i* ap bp) (i* aq bq);
/*
let fmt-ratio = λ{ p:; q:; }: ~<Ratio > ↦ { let fmt-ratio = λ{ p:; q:; }: ~<Ratio > ↦ {
fmt-int q;':';fmt-int p; fmt-int q;':';fmt-int p;
}; };
*/
} }

View file

@ -1,6 +1,8 @@
export { export {
/* output nullterminated string directly from datastack /* output nullterminated string directly from datastack
*/ */
/*
let print-nullterm = let print-nullterm =
λ{} : < Seq Char~Ascii~machine.Word > λ{} : < Seq Char~Ascii~machine.Word >
~ < NullTerminatedArray machine.Word > ~ < NullTerminatedArray machine.Word >
@ -8,5 +10,6 @@ export {
while(dup) { emit; } while(dup) { emit; }
drop; drop;
}; };
*/
} }

View file

@ -1,41 +0,0 @@
#complexity O(n)
let strlen-nullterm =
λ str : &[Char~Ascii~machine::Word]
~ &<NullTerminatedSeq machine::Word>
~ machine::Address
~ machine::Word
->
~ _2^64
~ machine::UInt64
~ machine::Word
{
let mut len = 0;
while ( @str ) {
! len (i+ len 1);
! str (i+ str 1);
}
len;
};
#complexity O(1)
let strlen-lenprefix =
λ str : &[Char~Ascii~machine::Word]
~ &<LenPrefixArray machine::Word>
~ &{
len : _2^64
~ machine::UInt64
~ machine::Word,
data : [machine::Word]
}
~ machine::Address
~ machine::Word
->
~ _2^64
~ machine::UInt64
~ machine::Word
{
str.len
};

View file

@ -1,70 +0,0 @@
type Vec = ΛT ↦ Struct {
len : _2^64 ~ machine.UInt64 ~ machine.Word ;
capacity : _2^64 ~ machine.UInt64 ~ machine.Word ;
data : <RefMut T> ~ machine.Address ~ machine.UInt64 ~ machine.Word ;
};
let yellow:Color~RGB~Vec3i = {
0;
220;
220;
};
let fn = λx::{
3;
};
let swap = λ{x;y;}:{T;T;} ↦ :{x;y;}
let n :
~_2^64
~machine.UInt64
~machine.Word
=
~<PosInt 16 BigEndian>
~<Seq <Digit 16>
~ Char >
: CF03;
λ{} -> {x y} : <Vec2 >
↦ {
10;
5;
}
let Vec.new = ΛT ↦ λ{} ↦ self:<Vec T>{
let sizeofT = 1;
!self <Vec T>{
};
!self.len 0;
!self.capacity 10;
!self.data malloc (i* self.capacity sizeofT);
};
let Vec.drop = ΛT ↦ λself:<Vec T> ↦ {
mfree self.data;
};
let vec-get =
Λ T
↦ λ vec: <Vec T>
↦ λ idx: _2^64 ~ machine.UInt64 ~ machine.Word
↦ T {
if( int-lt idx vec.len ) {
let j = 0;
let sizeofT = 1; /* todo: <sizeof T> */
while( int-lt j sizeofT ) {
@ (i+ vec.data
(i+ (i* idx sizeofT) j));
! j (i+ j 1);
};
} else {
print-nullterm 'o''u''t'' ''o''f'' ''b''o''u''n''d''s''\n''\0'
};
};

View file

@ -1,23 +0,0 @@
export {
/* Vec3i
*/
let vec3i-add = λ{
{ ax:_2^64; ay:_2^64; az:_2^64; } : <Vec3 _2^64~machine.Int64>;
{ bx:_2^64; by:_2^64; bz:_2^64; } : <Vec3 _2^64~machine.Int64>;
} ↦ {
i+ az bz;
i+ ay by;
i+ ax bx;
};
let fmt-vec3i =
λ{ x:_2^64; y:_2^64; z:_2^64; } : <Vec3 _2^64~machine.Int64>
↦ {
'}';
fmt-int z; '='; 'z'; ' '; ';';
fmt-int y; '='; 'y'; ' '; ';';
fmt-int x; '='; 'x'; '{';
};
}

View file

@ -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(

View file

@ -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
View 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
View 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());
obj_file.symbols.sort_by(|(n0,a0), (n1,a1)| a0.cmp(a1));
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());
}
}

View file

@ -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());