add export block and ability to load multiple files
This commit is contained in:
parent
f06bf14b52
commit
8d19767c98
13 changed files with 439 additions and 245 deletions
|
@ -60,6 +60,9 @@ pub enum LTExpr {
|
|||
Block {
|
||||
statements: Vec<Statement>,
|
||||
},
|
||||
ExportBlock {
|
||||
statements: Vec<Statement>,
|
||||
}
|
||||
}
|
||||
|
||||
impl LTExpr {
|
||||
|
|
89
src/main.rs
89
src/main.rs
|
@ -76,8 +76,10 @@ fn print_diagnostic(
|
|||
}
|
||||
|
||||
/* TODO:
|
||||
* - export / import , load multiple files
|
||||
* - Compiler error reporting
|
||||
* - parse float literals
|
||||
* - return type annotation
|
||||
* - write to address resulting from expression
|
||||
* - sized objects
|
||||
* - Typecheck for LTExpr::Application
|
||||
|
@ -96,8 +98,17 @@ fn main() {
|
|||
/* open source file
|
||||
*/
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
let path = &args[1];
|
||||
let iter_chars = iterate_text::file::characters::IterateFileCharacters::new(path);
|
||||
|
||||
if args.len() < 2 {
|
||||
eprintln!("{}", "No source files specified.".red());
|
||||
return;
|
||||
}
|
||||
|
||||
let mut args_iter = args.into_iter();
|
||||
args_iter.next();
|
||||
|
||||
for path in args_iter {
|
||||
let iter_chars = iterate_text::file::characters::IterateFileCharacters::new(path.clone());
|
||||
|
||||
/* compile source file
|
||||
*/
|
||||
|
@ -108,40 +119,54 @@ fn main() {
|
|||
})
|
||||
.peekable();
|
||||
|
||||
match parser::parse_expr( &typectx, &mut program_tokens ) {
|
||||
Ok( ast ) => {
|
||||
let bytecode = ProcedureCompiler::new(&main_scope)
|
||||
.compile( &ast )
|
||||
.into_asm(&"main".into());
|
||||
match parser::parse_expr( &typectx, &mut program_tokens ) {
|
||||
Ok( ast ) => {
|
||||
let (exports, bytecode) = ProcedureCompiler::new(&main_scope)
|
||||
.compile(&ast)
|
||||
.into_asm(&path);
|
||||
|
||||
eprintln!("{}", "Compiled successfully.\n======================\n".green());
|
||||
eprintln!("{} {}", "Compiled".green(), path.bold());
|
||||
for (name, def) in exports.iter() {
|
||||
eprintln!("export {}: {:?}", name.yellow().bold(), def);
|
||||
}
|
||||
|
||||
/* link assembly-program to symbols
|
||||
*/
|
||||
linker.add_procedure("main", bytecode);
|
||||
main_scope.write().unwrap().import(
|
||||
exports
|
||||
);
|
||||
|
||||
/* load & run compiled bytecode
|
||||
*/
|
||||
let main_addr = linker
|
||||
.get_link_addr(&"main".into())
|
||||
.expect("'main' not linked");
|
||||
|
||||
vm.load(linker.link_total().expect("could not link"));
|
||||
vm.execute(main_addr);
|
||||
|
||||
eprintln!(
|
||||
"\n====\nVM execution finished\ndatastack = {:?}\n====",
|
||||
vm.data_stack
|
||||
);
|
||||
/* link assembly-program to symbols
|
||||
*/
|
||||
linker.add_procedure(path.as_str(), bytecode);
|
||||
}
|
||||
Err( (region, parse_error) ) => {
|
||||
print_diagnostic(
|
||||
path.as_str(),
|
||||
region,
|
||||
format!("{:?}", parse_error)
|
||||
);
|
||||
|
||||
eprintln!("=======\nParse Error: Abort\n");
|
||||
}
|
||||
}
|
||||
Err( (region, parse_error) ) => {
|
||||
print_diagnostic(
|
||||
path,
|
||||
region,
|
||||
format!("{:?}", parse_error)
|
||||
);
|
||||
|
||||
eprintln!("=======\nerror: Parse Error\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* load & run compiled bytecode
|
||||
*/
|
||||
let main_addr = linker
|
||||
.get_link_addr(&"main.lt".into())
|
||||
.expect("'main.lt' not found");
|
||||
|
||||
let bytecode = linker.link_total().expect("Link error:");
|
||||
|
||||
eprintln!("{} ({} bytes)", "Linked bytecode.".green(), bytecode.len());
|
||||
eprintln!("================\n");
|
||||
|
||||
vm.load(bytecode);
|
||||
vm.execute(main_addr);
|
||||
|
||||
eprintln!(
|
||||
"\n================\nVM execution finished\ndatastack = {:?}\n====",
|
||||
vm.data_stack
|
||||
);
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ impl VariableBinding {
|
|||
.flatten()
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* parse a symbol binding of the form
|
||||
|
@ -364,7 +364,14 @@ where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
|
|||
if_expr: Box::new(if_expr),
|
||||
else_expr: Box::new(else_expr),
|
||||
});
|
||||
}
|
||||
},
|
||||
"export" => {
|
||||
tokens.next();
|
||||
let block = parse_statement_block(typectx, tokens)?;
|
||||
children.push(LTExpr::ExportBlock {
|
||||
statements: block
|
||||
});
|
||||
},
|
||||
name => {
|
||||
children.push(parse_atom(tokens)?);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use {
|
|||
};
|
||||
|
||||
pub struct ProcedureCompiler {
|
||||
symbols: Arc<RwLock<Scope>>,
|
||||
pub symbols: Arc<RwLock<Scope>>,
|
||||
asm: tisc::Assembler,
|
||||
linker: tisc::Linker,
|
||||
result_size: usize,
|
||||
|
@ -27,8 +27,17 @@ impl ProcedureCompiler {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn into_asm(mut self, proc_symbol: &String) -> Vec<tisc::assembler::AssemblyWord> {
|
||||
let data_frame_size = self.symbols.read().unwrap().get_frame_size() as i64;
|
||||
pub fn into_asm(mut self, proc_symbol: &String) -> (Vec<(String, SymbolDef)>, Vec<tisc::assembler::AssemblyWord>) {
|
||||
let mut symbols =
|
||||
Arc::try_unwrap(self.symbols).ok().unwrap()
|
||||
.into_inner().unwrap();
|
||||
|
||||
symbols.update_link_addresses(
|
||||
proc_symbol,
|
||||
&self.linker
|
||||
);
|
||||
|
||||
let data_frame_size = symbols.get_frame_size() as i64;
|
||||
|
||||
let body = self.asm.build();
|
||||
self.linker.add_procedure("__procedure_body__", body);
|
||||
|
@ -36,6 +45,7 @@ impl ProcedureCompiler {
|
|||
.linker
|
||||
.get_link_addr(&"__procedure_body__".into())
|
||||
.unwrap();
|
||||
|
||||
let subroutines = self
|
||||
.linker
|
||||
.link_relative(&"__subroutines__".into())
|
||||
|
@ -58,21 +68,37 @@ impl ProcedureCompiler {
|
|||
superlink.add_procedure("", entry.build());
|
||||
superlink.add_procedure("__subroutines__", subroutines);
|
||||
|
||||
let bytecode = superlink.link_relative(proc_symbol).expect("link error");
|
||||
/*
|
||||
eprintln!("\n\n{}:", proc_symbol);
|
||||
for (i,w) in tisc::assembler::disassemble(&bytecode).iter().enumerate() {
|
||||
eprintln!("{}:\t\t{}", i, w);
|
||||
symbols.update_link_addresses(
|
||||
&proc_symbol,
|
||||
&superlink
|
||||
);
|
||||
|
||||
let mut symbol_exports = symbols.export();
|
||||
let subroutines_addr = superlink.get_link_addr(&"__subroutines__".into()).unwrap();
|
||||
for (name, def) in symbol_exports.iter_mut() {
|
||||
match def {
|
||||
SymbolDef::Procedure{ in_types:_, out_types:_, link_addr, export:_ } => {
|
||||
match link_addr {
|
||||
LinkAddr::Relative{ symbol, offset } => {
|
||||
*offset += subroutines_addr;
|
||||
}
|
||||
LinkAddr::Absolute(addr) => {
|
||||
*addr += subroutines_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
bytecode
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
let bytecode = superlink.link_relative(proc_symbol).expect("link error");
|
||||
(symbol_exports, bytecode)
|
||||
}
|
||||
|
||||
pub fn verify(&self) {
|
||||
// todo
|
||||
}
|
||||
|
||||
pub fn compile_statement(mut self, statement: &Statement) -> Self {
|
||||
pub fn compile_statement(mut self, statement: &Statement, enable_export: bool) -> Self {
|
||||
match statement {
|
||||
Statement::Assignment { var_id, val_expr } => {
|
||||
self = self.compile(val_expr);
|
||||
|
@ -91,6 +117,7 @@ impl ProcedureCompiler {
|
|||
in_types,
|
||||
out_types,
|
||||
link_addr,
|
||||
export
|
||||
}) => {
|
||||
self.asm = self
|
||||
.asm
|
||||
|
@ -111,12 +138,23 @@ impl ProcedureCompiler {
|
|||
self.symbols
|
||||
.write()
|
||||
.unwrap()
|
||||
.declare_proc(var_id.clone(), vec![], vec![]);
|
||||
let lambda_procedure = ProcedureCompiler::new(&self.symbols)
|
||||
.declare_proc(var_id.clone(), vec![], vec![], enable_export);
|
||||
|
||||
let (exports, lambda_procedure) = ProcedureCompiler::new(&self.symbols)
|
||||
.compile(val_expr)
|
||||
.into_asm(var_id);
|
||||
|
||||
self.linker.add_procedure(var_id, lambda_procedure);
|
||||
|
||||
let offset = self.linker.get_link_addr(var_id).unwrap();
|
||||
|
||||
if enable_export {
|
||||
for (name, def) in exports.iter() {
|
||||
eprintln!("Procedure compiler: export {}", name);
|
||||
}
|
||||
|
||||
self.symbols.write().unwrap().import( exports );
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
self.symbols
|
||||
|
@ -126,7 +164,7 @@ impl ProcedureCompiler {
|
|||
self = self.compile_statement(&Statement::Assignment {
|
||||
var_id: var_id.clone(),
|
||||
val_expr: val_expr.clone(),
|
||||
});
|
||||
}, false);
|
||||
}
|
||||
},
|
||||
Statement::WhileLoop { condition, body } => {
|
||||
|
@ -138,7 +176,7 @@ impl ProcedureCompiler {
|
|||
|
||||
self.asm = tisc::Assembler::new();
|
||||
for statement in body.into_iter() {
|
||||
self = self.compile_statement(statement);
|
||||
self = self.compile_statement(statement, false);
|
||||
}
|
||||
let body_asm = self.asm;
|
||||
|
||||
|
@ -168,8 +206,9 @@ impl ProcedureCompiler {
|
|||
in_types,
|
||||
out_types,
|
||||
link_addr,
|
||||
export
|
||||
}) => {
|
||||
self.asm = self.asm.call(symbol.as_str());
|
||||
self.asm = self.asm.call_symbol(link_addr);
|
||||
}
|
||||
None => {
|
||||
eprintln!("undefined symbol '{}'!", symbol);
|
||||
|
@ -218,7 +257,12 @@ impl ProcedureCompiler {
|
|||
}
|
||||
LTExpr::Block { statements } => {
|
||||
for s in statements.iter() {
|
||||
self = self.compile_statement(s);
|
||||
self = self.compile_statement(s, false);
|
||||
}
|
||||
}
|
||||
LTExpr::ExportBlock{ statements } => {
|
||||
for s in statements.iter() {
|
||||
self = self.compile_statement(s, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use {
|
|||
collections::HashMap,
|
||||
sync::{Arc, RwLock},
|
||||
},
|
||||
tisc::linker::LinkAddr,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -19,7 +20,8 @@ pub enum SymbolDef {
|
|||
Procedure {
|
||||
in_types: Vec<laddertypes::TypeTerm>,
|
||||
out_types: Vec<laddertypes::TypeTerm>,
|
||||
link_addr: Option<tisc::VM_Word>,
|
||||
link_addr: LinkAddr,
|
||||
export: bool
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -35,6 +37,7 @@ impl SymbolDef {
|
|||
in_types,
|
||||
out_types,
|
||||
link_addr: _,
|
||||
export: _,
|
||||
} => laddertypes::TypeTerm::App(vec![
|
||||
typectx
|
||||
.write()
|
||||
|
@ -94,6 +97,24 @@ impl Scope {
|
|||
Arc::new(RwLock::new(s))
|
||||
}
|
||||
|
||||
pub fn export(self) -> Vec<(String, SymbolDef)> {
|
||||
self.symbols
|
||||
.into_iter()
|
||||
.filter(|(name, def)|
|
||||
match def {
|
||||
SymbolDef::Procedure { in_types:_, out_types:_, link_addr:_, export } => *export,
|
||||
_ => false
|
||||
}
|
||||
)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn import(&mut self, symbol_imports: Vec<(String, SymbolDef)>) {
|
||||
for (name, def) in symbol_imports {
|
||||
self.symbols.insert( name, def );
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_frame_size(&self) -> usize {
|
||||
self.frame_size
|
||||
}
|
||||
|
@ -116,20 +137,35 @@ impl Scope {
|
|||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
pub fn get_link_addr(&self, name: &str) -> Option<tisc::VM_Word> {
|
||||
match self.get(name) {
|
||||
Some(SymbolDef::Procedure{ in_types:_, out_types:_, link_addr }) => {
|
||||
link_addr
|
||||
|
||||
/// takes the link-addresses from a Linker
|
||||
/// and updates the symbol table to relative addresses
|
||||
/// based on the next super-label
|
||||
pub fn update_link_addresses(
|
||||
&mut self,
|
||||
base_symbol: &String,
|
||||
linker: &tisc::Linker
|
||||
) {
|
||||
for (name, def) in self.symbols.iter_mut() {
|
||||
if let Some(offset) = linker.get_link_addr( name ) {
|
||||
match def {
|
||||
SymbolDef::Procedure {
|
||||
in_types:_,out_types:_,
|
||||
link_addr,
|
||||
export:_
|
||||
} => {
|
||||
*link_addr = LinkAddr::Relative{
|
||||
symbol: base_symbol.clone(),
|
||||
offset
|
||||
};
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
Some(SymbolDef::StaticRef { typ:_, link_addr }) => {
|
||||
link_addr
|
||||
}
|
||||
Some(SymbolDef::FrameRef { typ:_, stack_ref:_ }) => None,
|
||||
None => None
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//<><><><><><>
|
||||
|
||||
pub fn declare_proc_parse(
|
||||
|
@ -165,6 +201,7 @@ impl Scope {
|
|||
.expect("parse typeterm")
|
||||
})
|
||||
.collect(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -173,13 +210,15 @@ impl Scope {
|
|||
name: String,
|
||||
in_types: Vec<laddertypes::TypeTerm>,
|
||||
out_types: Vec<laddertypes::TypeTerm>,
|
||||
export: bool
|
||||
) {
|
||||
self.symbols.insert(
|
||||
name,
|
||||
name.clone(),
|
||||
SymbolDef::Procedure {
|
||||
link_addr: None, //LinkAddr::Relative{ name, offset: 0 },
|
||||
link_addr: LinkAddr::Relative{ symbol: name, offset: 0 },
|
||||
in_types,
|
||||
out_types,
|
||||
export
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue