make let
a statement & support parsing for let
This commit is contained in:
parent
d7c06d423e
commit
e23d8257d0
5 changed files with 77 additions and 95 deletions
17
src/expr.rs
17
src/expr.rs
|
@ -12,6 +12,10 @@ pub enum Statement {
|
||||||
var_id: String,
|
var_id: String,
|
||||||
val_expr: LTExpr
|
val_expr: LTExpr
|
||||||
},
|
},
|
||||||
|
LetAssign {
|
||||||
|
var_id: String,
|
||||||
|
val_expr: LTExpr,
|
||||||
|
},
|
||||||
WhileLoop {
|
WhileLoop {
|
||||||
condition: LTExpr,
|
condition: LTExpr,
|
||||||
body: Vec<Statement>
|
body: Vec<Statement>
|
||||||
|
@ -39,11 +43,6 @@ pub enum LTExpr {
|
||||||
arg_type: Option< laddertypes::TypeTerm >,
|
arg_type: Option< laddertypes::TypeTerm >,
|
||||||
val_expr: Box<LTExpr>
|
val_expr: Box<LTExpr>
|
||||||
},
|
},
|
||||||
Let {
|
|
||||||
name: String,
|
|
||||||
val: Box<LTExpr>,
|
|
||||||
body: Box<LTExpr>
|
|
||||||
},
|
|
||||||
Branch {
|
Branch {
|
||||||
condition: Box<LTExpr>,
|
condition: Box<LTExpr>,
|
||||||
if_expr: Box<LTExpr>,
|
if_expr: Box<LTExpr>,
|
||||||
|
@ -77,14 +76,6 @@ impl LTExpr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn let_expr(name: &str, val: LTExpr, body: LTExpr) -> Self {
|
|
||||||
LTExpr::Let {
|
|
||||||
name: String::from(name),
|
|
||||||
val: Box::new(val),
|
|
||||||
body: Box::new(body)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn application(head: LTExpr, body: Vec<LTExpr>) -> Self {
|
pub fn application(head: LTExpr, body: Vec<LTExpr>) -> Self {
|
||||||
LTExpr::Application {
|
LTExpr::Application {
|
||||||
head: Box::new( head ),
|
head: Box::new( head ),
|
||||||
|
|
|
@ -10,6 +10,8 @@ pub enum LTIRToken {
|
||||||
// TripleQuote(String),
|
// TripleQuote(String),
|
||||||
|
|
||||||
Lambda,
|
Lambda,
|
||||||
|
AssignType,
|
||||||
|
AssignValue,
|
||||||
|
|
||||||
ExprOpen,
|
ExprOpen,
|
||||||
ExprClose,
|
ExprClose,
|
||||||
|
@ -83,11 +85,13 @@ where It: Iterator<Item = char>
|
||||||
// determine token type
|
// determine token type
|
||||||
LexerState::Any => {
|
LexerState::Any => {
|
||||||
match c {
|
match c {
|
||||||
|
'λ' => { self.chars.next(); return Some(Ok(LTIRToken::Lambda)); },
|
||||||
'(' => { self.chars.next(); return Some(Ok(LTIRToken::ExprOpen)); },
|
'(' => { self.chars.next(); return Some(Ok(LTIRToken::ExprOpen)); },
|
||||||
')' => { self.chars.next(); return Some(Ok(LTIRToken::ExprClose)); },
|
')' => { self.chars.next(); return Some(Ok(LTIRToken::ExprClose)); },
|
||||||
'{' => { self.chars.next(); return Some(Ok(LTIRToken::BlockOpen)); },
|
'{' => { self.chars.next(); return Some(Ok(LTIRToken::BlockOpen)); },
|
||||||
'}' => { self.chars.next(); return Some(Ok(LTIRToken::BlockClose)); },
|
'}' => { self.chars.next(); return Some(Ok(LTIRToken::BlockClose)); },
|
||||||
'λ' => { self.chars.next(); return Some(Ok(LTIRToken::Lambda)); },
|
':' => { self.chars.next(); return Some(Ok(LTIRToken::AssignType)); },
|
||||||
|
'=' => { self.chars.next(); return Some(Ok(LTIRToken::AssignValue)); },
|
||||||
';' => { self.chars.next(); return Some(Ok(LTIRToken::StatementSep)); },
|
';' => { self.chars.next(); return Some(Ok(LTIRToken::StatementSep)); },
|
||||||
'\'' => { self.chars.next(); state = LexerState::Char(None); },
|
'\'' => { self.chars.next(); state = LexerState::Char(None); },
|
||||||
c => {
|
c => {
|
||||||
|
|
108
src/main.rs
108
src/main.rs
|
@ -50,6 +50,15 @@ fn main() {
|
||||||
~<NullTerminatedSeq machine::Word>"
|
~<NullTerminatedSeq machine::Word>"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
main_scope.write().unwrap()
|
||||||
|
.declare_static_parse(
|
||||||
|
"pfxstr",
|
||||||
|
"<Seq Char
|
||||||
|
~Ascii
|
||||||
|
~machine::Word>
|
||||||
|
~<LengthPrefixedSeq machine::Word>"
|
||||||
|
);
|
||||||
|
|
||||||
main_scope.write().unwrap()
|
main_scope.write().unwrap()
|
||||||
.declare_proc_parse(
|
.declare_proc_parse(
|
||||||
"print-nullterm",
|
"print-nullterm",
|
||||||
|
@ -61,31 +70,6 @@ fn main() {
|
||||||
],
|
],
|
||||||
vec![]);
|
vec![]);
|
||||||
|
|
||||||
/* link assembly-program to symbol
|
|
||||||
*/
|
|
||||||
linker.add_procedure(
|
|
||||||
"main",
|
|
||||||
compile(&main_scope, "{
|
|
||||||
print-nullterm hello-string;
|
|
||||||
}"));
|
|
||||||
|
|
||||||
linker.add_static("hello-string",
|
|
||||||
"Hallo Welt!\n\0"
|
|
||||||
.chars()
|
|
||||||
.map(|c| (c as u8) as tisc::VM_Word)
|
|
||||||
.collect());
|
|
||||||
|
|
||||||
linker.add_procedure(
|
|
||||||
"print-nullterm",
|
|
||||||
compile(&main_scope,
|
|
||||||
"λ str {
|
|
||||||
while (@ str) {
|
|
||||||
emit (@ str);
|
|
||||||
! str (i+ str 1);
|
|
||||||
}
|
|
||||||
}")
|
|
||||||
);
|
|
||||||
|
|
||||||
main_scope.write().unwrap().declare_proc_parse(
|
main_scope.write().unwrap().declare_proc_parse(
|
||||||
"print-lenprefix",
|
"print-lenprefix",
|
||||||
vec![],
|
vec![],
|
||||||
|
@ -95,53 +79,45 @@ fn main() {
|
||||||
~machine::Word"
|
~machine::Word"
|
||||||
],
|
],
|
||||||
vec![]);
|
vec![]);
|
||||||
/*
|
|
||||||
linker.add_procedure(
|
|
||||||
"print-lenprefix",
|
|
||||||
compile(&main_scope,
|
/* link assembly-program to symbols
|
||||||
|
*/
|
||||||
|
linker.add_procedure("main", compile(&main_scope,
|
||||||
|
"{
|
||||||
|
print-lenprefix pfxstr;
|
||||||
|
}"));
|
||||||
|
|
||||||
|
linker.add_static("hello-string",
|
||||||
|
"Hallo Welt!\n\0"
|
||||||
|
.chars()
|
||||||
|
.map(|c| (c as u8) as tisc::VM_Word)
|
||||||
|
.collect());
|
||||||
|
|
||||||
|
linker.add_static("pfxstr",
|
||||||
|
vec![ 4, 'a' as tisc::VM_Word, 'b' as tisc::VM_Word, 'c' as tisc::VM_Word, 'd' as tisc::VM_Word ]
|
||||||
|
);
|
||||||
|
|
||||||
|
linker.add_procedure("print-nullterm", compile(&main_scope,
|
||||||
"λ str {
|
"λ str {
|
||||||
let len = (@ str);
|
while (@ str) {
|
||||||
! str = (i+ str 1);
|
emit (@ str);
|
||||||
let end = (i+ str len);
|
! str (i+ str 1);
|
||||||
|
}
|
||||||
|
}"));
|
||||||
|
|
||||||
|
linker.add_procedure("print-lenprefix", compile(&main_scope,
|
||||||
|
"λ str {
|
||||||
|
let len = @ str;
|
||||||
|
! str (i+ str 1);
|
||||||
|
let end = i+ str len;
|
||||||
while (i- str end) {
|
while (i- str end) {
|
||||||
emit (@ str);
|
emit (@ str);
|
||||||
! str (i+ str 1);
|
! str (i+ str 1);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
)
|
));
|
||||||
);
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
tisc::Assembler::new()
|
|
||||||
// calculate stop address
|
|
||||||
.inst( tisc::VM_Instruction::Dup )
|
|
||||||
.inst( tisc::VM_Instruction::Dup )
|
|
||||||
.inst( tisc::VM_Instruction::Fetch )
|
|
||||||
.lit(1)
|
|
||||||
.inst( tisc::VM_Instruction::Add )
|
|
||||||
.inst( tisc::VM_Instruction::Add )
|
|
||||||
.inst( tisc::VM_Instruction::Swap )
|
|
||||||
|
|
||||||
// emit until address == start address
|
|
||||||
.while_loop(
|
|
||||||
tisc::Assembler::new()
|
|
||||||
.lit( 2 )
|
|
||||||
.inst( tisc::VM_Instruction::Pick )
|
|
||||||
.lit( 2 )
|
|
||||||
.inst( tisc::VM_Instruction::Pick )
|
|
||||||
.call("i-"),
|
|
||||||
|
|
||||||
tisc::Assembler::new()
|
|
||||||
.inst( tisc::VM_Instruction::Dup )
|
|
||||||
.inst( tisc::VM_Instruction::Fetch )
|
|
||||||
.inst( tisc::VM_Instruction::Emit )
|
|
||||||
.lit( 1 )
|
|
||||||
.inst( tisc::VM_Instruction::Add )
|
|
||||||
)
|
|
||||||
.inst( tisc::VM_Instruction::Drop )
|
|
||||||
.inst( tisc::VM_Instruction::Drop )
|
|
||||||
.build()
|
|
||||||
*/
|
|
||||||
|
|
||||||
let main_addr = linker.get_link_addr(&"main".into()).expect("'main' not linked");
|
let main_addr = linker.get_link_addr(&"main".into()).expect("'main' not linked");
|
||||||
vm.load( linker.link_total().expect("could not link") );
|
vm.load( linker.link_total().expect("could not link") );
|
||||||
|
|
|
@ -66,6 +66,18 @@ where It: Iterator<Item = char>
|
||||||
val_expr
|
val_expr
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
"let" => {
|
||||||
|
tokens.next();
|
||||||
|
let name = parse_symbol(tokens)?;
|
||||||
|
let _ = parse_expect(tokens, LTIRToken::AssignValue);
|
||||||
|
let val_expr = parse_expr(tokens)?;
|
||||||
|
let _ = parse_expect(tokens, LTIRToken::StatementSep)?;
|
||||||
|
|
||||||
|
Ok(Statement::LetAssign {
|
||||||
|
var_id: name,
|
||||||
|
val_expr
|
||||||
|
})
|
||||||
|
}
|
||||||
"while" => {
|
"while" => {
|
||||||
tokens.next();
|
tokens.next();
|
||||||
let _ = parse_expect(tokens, LTIRToken::ExprOpen)?;
|
let _ = parse_expect(tokens, LTIRToken::ExprOpen)?;
|
||||||
|
|
|
@ -67,6 +67,20 @@ impl ProcedureCompiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Statement::LetAssign{ var_id, val_expr } => {
|
||||||
|
self.symbols.write().unwrap()
|
||||||
|
.declare_var(
|
||||||
|
var_id.clone(),
|
||||||
|
laddertypes::TypeTerm::unit()
|
||||||
|
);
|
||||||
|
|
||||||
|
self = self.compile_statement(
|
||||||
|
&Statement::Assignment {
|
||||||
|
var_id: var_id.clone(),
|
||||||
|
val_expr: val_expr.clone()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
Statement::WhileLoop { condition, body } => {
|
Statement::WhileLoop { condition, body } => {
|
||||||
let asm = self.asm;
|
let asm = self.asm;
|
||||||
|
|
||||||
|
@ -122,21 +136,6 @@ impl ProcedureCompiler {
|
||||||
}
|
}
|
||||||
self = self.compile(head);
|
self = self.compile(head);
|
||||||
},
|
},
|
||||||
LTExpr::Let { name, val, body } => {
|
|
||||||
self.symbols.write().unwrap()
|
|
||||||
.declare_var(
|
|
||||||
name.clone(),
|
|
||||||
laddertypes::TypeTerm::unit()
|
|
||||||
);
|
|
||||||
|
|
||||||
self = self.compile_statement(
|
|
||||||
&Statement::Assignment {
|
|
||||||
var_id: name.clone(),
|
|
||||||
val_expr: val.deref().clone()
|
|
||||||
}
|
|
||||||
);
|
|
||||||
self = self.compile(&body.deref().clone());
|
|
||||||
},
|
|
||||||
LTExpr::Abstraction { arg_id: arg_name, arg_type, val_expr } => {
|
LTExpr::Abstraction { arg_id: arg_name, arg_type, val_expr } => {
|
||||||
let id = self.symbols
|
let id = self.symbols
|
||||||
.write().unwrap()
|
.write().unwrap()
|
||||||
|
|
Loading…
Reference in a new issue