diff --git a/src/expr.rs b/src/expr.rs index 592d938..e75811d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -13,6 +13,7 @@ pub enum Statement { val_expr: LTExpr }, LetAssign { + typ: Option, var_id: String, val_expr: LTExpr, }, @@ -24,22 +25,34 @@ pub enum Statement { Expr(LTExpr) } +#[derive(Clone, Debug)] +pub enum TypeError { + ParseError(laddertypes::parser::ParseError), + Mismatch { + expected: laddertypes::TypeTerm, + received: laddertypes::TypeTerm + } +} + +pub type TypeTag = Result< laddertypes::TypeTerm, TypeError >; + #[derive(Clone, Debug)] pub enum LTExpr { Literal { - typ: Option< laddertypes::TypeTerm >, + typ: Option, val: tisc::VM_Word }, Symbol { - typ: Option< laddertypes::TypeTerm >, + typ: Option, symbol: String, }, Application { + typ: Option, head: Box, body: Vec }, Abstraction { - args: Vec<(String, Option)>, + args: Vec<(String, Option)>, body: Box }, Branch { @@ -67,18 +80,19 @@ impl LTExpr { } } - pub fn abstraction(args: Vec<(&str, &str)>, val_expr: LTExpr) -> LTExpr { + pub fn abstraction(args: Vec<(&str, &str)>, body: LTExpr) -> LTExpr { LTExpr::Abstraction { args: args.into_iter().map(|(arg_name, arg_type)| ( arg_name.into(), None ) //typectx.write().unwrap().parse(t).expect("parse typeterm") ).collect(), - body: Box::new(val_expr) + body: Box::new(body) } } pub fn application(head: LTExpr, body: Vec) -> Self { LTExpr::Application { + typ: None, head: Box::new( head ), body: body } diff --git a/src/lexer.rs b/src/lexer.rs index c8cfa86..07e1699 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -10,7 +10,8 @@ pub enum LTIRToken { // TripleQuote(String), Lambda, - AssignType, + LambdaBody, + AssignType( String ), AssignValue, ExprOpen, @@ -30,6 +31,7 @@ pub enum LexError { #[derive(PartialEq, Eq, Clone, Debug)] pub enum LexerState { Any, + TypeTerm( String ), Sym( String ), Num( i64 ), Char( Option ) @@ -39,6 +41,7 @@ impl LexerState { fn into_token(self) -> Option< LTIRToken > { match self { LexerState::Any => None, + LexerState::TypeTerm(s) => Some(LTIRToken::AssignType(s)), LexerState::Sym(s) => Some(LTIRToken::Symbol(s)), LexerState::Num(n) => Some(LTIRToken::Num(n)), LexerState::Char(c) => Some(LTIRToken::Char(c?)) @@ -86,11 +89,15 @@ where It: Iterator LexerState::Any => { match c { 'λ' => { self.chars.next(); return Some(Ok(LTIRToken::Lambda)); }, + '.' => { self.chars.next(); return Some(Ok(LTIRToken::LambdaBody)); }, '(' => { self.chars.next(); return Some(Ok(LTIRToken::ExprOpen)); }, ')' => { self.chars.next(); return Some(Ok(LTIRToken::ExprClose)); }, '{' => { self.chars.next(); return Some(Ok(LTIRToken::BlockOpen)); }, '}' => { self.chars.next(); return Some(Ok(LTIRToken::BlockClose)); }, - ':' => { self.chars.next(); return Some(Ok(LTIRToken::AssignType)); }, + ':' => { + self.chars.next(); + state = LexerState::TypeTerm(String::new()); + }, '=' => { self.chars.next(); return Some(Ok(LTIRToken::AssignValue)); }, ';' => { self.chars.next(); return Some(Ok(LTIRToken::StatementSep)); }, '\'' => { self.chars.next(); state = LexerState::Char(None); }, @@ -138,12 +145,25 @@ where It: Iterator } } + LexerState::TypeTerm(s) => { + if *c == '=' || *c == '.' { + if let Some(token) = state.clone().into_token() { + return Some(Ok(token)) + } + } else { + if let Some(c) = self.chars.next() { + s.push(c); + } + } + } + _ => { if c.is_whitespace() || *c == '(' || *c == ')' || *c == '{' || *c == '}' - || *c == ';' || *c == '=' || *c == ':' + || *c == ';' || *c == '=' + || *c == ':' || *c == '.' { // finish the current token @@ -183,4 +203,25 @@ where It: Iterator } } +mod tests { + #[test] + fn test_lexer() { + let mut lexer = crate::lexer::LTIRLexer::from( + "let var1:ℕ=123; + let square =λx.* x x; + + let sqrt = λx:ℝ~machine::Float64~machine::Word.(f64-sqrt x); + let magnitude = + λx:ℝ + .λy:ℝ + .sqrt (+ (* x x) (* y y)); + ".chars() + ); + + for token in lexer { + eprintln!("token = {:?}", token); + } + } +} + diff --git a/src/main.rs b/src/main.rs index 07b62a9..12c3fc9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,6 +21,7 @@ fn compile(scope: &Arc>, name: &str, source: &str) -> Vec< tisc::a ProcedureCompiler::new(scope) .compile( &parser::parse_expr( + &scope.read().unwrap().typectx, &mut lexer::LTIRLexer::from( source.chars().peekable() ).peekable() @@ -63,40 +64,81 @@ fn main() { linker.add_procedure("main", compile(&main_scope, "main", "{ - let print-nullterm = λstr { - while (@ str) { - emit (@ str); - ! str (i+ str 1); - } - }; + let print-nullterm = + λ str : > + ~ > + ~ machine::Address + ~ machine::Word + . + { + while (@ str) { + emit (@ str); + ! str (i+ str 1); + } + }; - let print-lenprefix = λstr { + let print-len = + λ len : ℤ_2^64 + ~ machine::UInt64 + ~ machine::Word + . + λ str : > + ~ > + ~ machine::Address + ~ machine::Word + . + { + let end = (i+ str len); + while (i- str end) { + emit (@ str); + ! str (i+ str 1); + } + }; + + let print-lenprefix = + λ str : > + ~ > + ~ + > + >> + ~ machine::Address + ~ machine::Word + . + { let len = (@ str); ! str (i+ str 1); - let end = (i+ str len); - while (i- str end) { - emit (@ str); - ! str (i+ str 1); - } + print-len len str; }; - let hello = λ{ + let hello = λ.{ print-nullterm hello-string; print-lenprefix pfxstr; + + let isquare = λx:ℤ. i* x x; + let imagnitude2 = λx:ℤ.λy:ℤ. i+ (isquare x) (isquare y); + let factorial = λn:ℤ. + if( n ){ i* n (factorial (i- n 1)); } + else { 1; }; + + factorial 20; + + if ( i- (imagnitude2 10 20) 500 ) { + emit '?'; + } else { + emit '!'; + }; + + emit '\n'; + emit (i+ '0' (isquare 3)); + emit '\n'; }; hello; - - let isquare = λx (i* x x); - let magnitude2 = λx y { - i+ (isquare x) (isquare y); - }; - magnitude2 8 16; - - emit '\n'; - emit (i+ '0' (isquare 3)); - emit '\n'; - }")); + }" + )); linker.add_static("hello-string", "Hallo Welt!\n\0" diff --git a/src/parser.rs b/src/parser.rs index 6a4f48b..921a745 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,8 +1,11 @@ use { - std::iter::Peekable, + std::{ + iter::Peekable, + sync::{Arc, RwLock} + }, crate::{ lexer::{LTIRLexer, LTIRToken, LexError}, - expr::{LTExpr, Statement} + expr::{LTExpr, Statement, TypeTag, TypeError} } }; @@ -46,7 +49,34 @@ where It: Iterator } } +pub fn parse_type_tag( + typectx: &Arc>, + tokens: &mut Peekable> +) -> Option +where It: Iterator +{ + if let Some(peektok) = tokens.peek().clone() { + match peektok.clone() { + Ok(LTIRToken::AssignType(typeterm_str)) => { + tokens.next(); + match typectx.write().unwrap().parse(typeterm_str.as_str()) { + Ok(typeterm) => { + Some(Ok(typeterm)) + } + Err(parse_error) => { + Some(Err(TypeError::ParseError(parse_error))) + } + } + } + _ => None + } + } else { + None + } +} + pub fn parse_statement( + typectx: &Arc>, tokens: &mut Peekable> ) -> Result< crate::expr::Statement, ParseError > where It: Iterator @@ -59,7 +89,7 @@ where It: Iterator tokens.next(); // todo accept address-expression instead of symbol let name = parse_symbol(tokens)?; - let val_expr = parse_expr(tokens)?; + let val_expr = parse_expr(typectx, tokens)?; let _ = parse_expect(tokens, LTIRToken::StatementSep)?; Ok(Statement::Assignment { @@ -70,11 +100,13 @@ where It: Iterator "let" => { tokens.next(); let name = parse_symbol(tokens)?; + let typ = parse_type_tag(typectx, tokens); let _ = parse_expect(tokens, LTIRToken::AssignValue); - let val_expr = parse_expr(tokens)?; + let val_expr = parse_expr(typectx, tokens)?; let _ = parse_expect(tokens, LTIRToken::StatementSep)?; - + Ok(Statement::LetAssign { + typ, var_id: name, val_expr }) @@ -82,28 +114,28 @@ where It: Iterator "while" => { tokens.next(); let _ = parse_expect(tokens, LTIRToken::ExprOpen)?; - let cond = parse_expr(tokens)?; + let cond = parse_expr(typectx, tokens)?; let _ = parse_expect(tokens, LTIRToken::ExprClose)?; Ok(Statement::WhileLoop { condition: cond, - body: parse_block(tokens)? + body: parse_block(typectx, tokens)? }) } "return" => { tokens.next(); - let expr = parse_expr(tokens)?; + let expr = parse_expr(typectx, tokens)?; let _ = parse_expect(tokens, LTIRToken::StatementSep)?; - Ok(Statement::Return(parse_expr(tokens)?)) + Ok(Statement::Return(parse_expr(typectx, tokens)?)) } _ => { - let expr = parse_expr(tokens)?; + let expr = parse_expr(typectx, tokens)?; let _ = parse_expect(tokens, LTIRToken::StatementSep)?; Ok(Statement::Expr(expr)) } } } Ok(_) => { - let expr = parse_expr(tokens)?; + let expr = parse_expr(typectx, tokens)?; let _ = parse_expect(tokens, LTIRToken::StatementSep)?; Ok(Statement::Expr(expr)) }, @@ -115,6 +147,7 @@ where It: Iterator } pub fn parse_block( + typectx: &Arc>, tokens: &mut Peekable> ) -> Result< Vec, ParseError > where It: Iterator @@ -128,7 +161,7 @@ where It: Iterator tokens.next(); return Ok(statements) } - Ok(_) => { statements.push( parse_statement(tokens)? ); } + Ok(_) => { statements.push( parse_statement(typectx, tokens)? ); } Err(err) => { return Err(ParseError::LexError(err.clone())); } } } @@ -164,6 +197,7 @@ where It: Iterator } pub fn parse_expr( + typectx: &Arc>, tokens: &mut Peekable> ) -> Result< crate::expr::LTExpr, ParseError > where It: Iterator @@ -178,9 +212,14 @@ where It: Iterator let mut args = Vec::new(); while let Some(Ok(LTIRToken::Symbol(_))) = tokens.peek() { - args.push((parse_symbol(tokens)?, None)); + args.push(( + parse_symbol(tokens)?, + parse_type_tag(typectx, tokens) + )); } - let body = parse_expr(tokens)?; + + let _ = parse_expect(tokens, LTIRToken::LambdaBody); + let body = parse_expr(typectx, tokens)?; return Ok(LTExpr::Abstraction{ args, @@ -200,11 +239,13 @@ where It: Iterator } _ => {} } - children.push(parse_expr(tokens)?); + children.push(parse_expr(typectx, tokens)?); } }, Ok(LTIRToken::ExprClose) => { break; } - Ok(LTIRToken::BlockOpen) => { children.push( LTExpr::block(parse_block(tokens)?)); } + Ok(LTIRToken::BlockOpen) => { + children.push( LTExpr::block(parse_block(typectx, tokens)?)); + } Ok(LTIRToken::BlockClose) => { break; } Ok(LTIRToken::StatementSep) => { break; } Ok(LTIRToken::Symbol(name)) => { @@ -212,16 +253,16 @@ where It: Iterator "if" => { tokens.next(); let _ = parse_expect(tokens, LTIRToken::ExprOpen)?; - let cond = parse_expr(tokens)?; + let cond = parse_expr(typectx, tokens)?; let _ = parse_expect(tokens, LTIRToken::ExprClose)?; - let if_expr = LTExpr::block(parse_block(tokens)?); + let if_expr = LTExpr::block(parse_block(typectx, tokens)?); let mut else_expr = LTExpr::block(vec![]); if let Some(peektok) = tokens.peek() { if let Ok(LTIRToken::Symbol(name)) = peektok { if name == "else" { tokens.next(); - else_expr = parse_expr(tokens)?; + else_expr = parse_expr(typectx, tokens)?; } } } @@ -245,6 +286,7 @@ where It: Iterator if children.len() > 0 { let head = children.remove(0); Ok(LTExpr::Application { + typ: None, head: Box::new(head), body: children }) diff --git a/src/procedure_compiler.rs b/src/procedure_compiler.rs index a361146..00f44f4 100644 --- a/src/procedure_compiler.rs +++ b/src/procedure_compiler.rs @@ -98,7 +98,7 @@ impl ProcedureCompiler { } } } - Statement::LetAssign{ var_id, val_expr } => { + Statement::LetAssign{ typ, var_id, val_expr } => { match val_expr { LTExpr::Abstraction { args:_, body:_ } => { self.symbols.write().unwrap() @@ -180,7 +180,7 @@ impl ProcedureCompiler { LTExpr::Literal { typ, val } => { self.asm = self.asm.lit( *val ); } - LTExpr::Application { head, body } => { + LTExpr::Application { typ, head, body } => { for arg in body.iter().rev() { self = self.compile(arg); } @@ -188,16 +188,19 @@ impl ProcedureCompiler { } LTExpr::Abstraction { args, body } => { for (arg_name, arg_type) in args.iter() { - let id = self.symbols - .write().unwrap() - .declare_var( - arg_name.clone(), - arg_type.clone().unwrap_or( - laddertypes::TypeTerm::unit()) - ); - self.asm = self.asm - .lit( id ) - .call("data-frame-set"); + if let Some(Ok(typeterm)) = arg_type { + let id = self.symbols + .write().unwrap() + .declare_var( + arg_name.clone(), + typeterm.clone() + ); + self.asm = self.asm + .lit( id ) + .call("data-frame-set"); + } else { + eprintln!("invalid type {:?} for argument {}", arg_type, arg_name); + } } self = self.compile(body); } diff --git a/src/runtime.rs b/src/runtime.rs index 0bf2cce..3554ecd 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -89,6 +89,7 @@ pub fn init_runtime(linker: &mut Linker) -> Arc> { linker.add_procedure( "i-", tisc::Assembler::new() + .inst(tisc::VM_Instruction::Swap) .inst(tisc::VM_Instruction::BitwiseNot) .lit(1) .inst(tisc::VM_Instruction::Add) @@ -174,6 +175,7 @@ pub fn init_runtime(linker: &mut Linker) -> Arc> { .lit( 1 ) // [ a sum b -- a sum (b-1) ] + .inst( tisc::VM_Instruction::Swap ) .call( "i-" ) // [ a sum b -- a b sum ] @@ -245,7 +247,6 @@ pub fn init_runtime(linker: &mut Linker) -> Arc> { tisc::Assembler::new() .static_ref("data-frame-ptr") .inst( tisc::VM_Instruction::Fetch ) - .inst( tisc::VM_Instruction::Swap ) .call("i-") .static_ref("data-frame-ptr") .inst( tisc::VM_Instruction::Store )