From 282c42da3cc8f6383e8029843c8105ba038a0004 Mon Sep 17 00:00:00 2001 From: greg Date: Fri, 4 Jan 2019 22:58:25 -0800 Subject: [PATCH] Adding Node intermediate type to AST --- schala-lang/language/src/ast.rs | 13 +++- schala-lang/language/src/parsing.rs | 83 +++++++++++++----------- schala-lang/language/src/reduced_ast.rs | 20 +++--- schala-lang/language/src/symbol_table.rs | 1 + schala-lang/language/src/typechecking.rs | 2 +- 5 files changed, 69 insertions(+), 50 deletions(-) diff --git a/schala-lang/language/src/ast.rs b/schala-lang/language/src/ast.rs index eae5a98..660cbf8 100644 --- a/schala-lang/language/src/ast.rs +++ b/schala-lang/language/src/ast.rs @@ -4,22 +4,29 @@ use std::convert::From; use source_map::{SourceMap}; use builtin::{BinOp, PrefixOp}; +#[derive(Clone, Debug, PartialEq)] pub struct Node { n: T, meta: Meta } impl Node { - fn node(&self) -> &T { + pub fn new(n: T) -> Node { + Node { n, meta: Meta::default() } + } + + pub fn node(&self) -> &T { &self.n } } +//TODO this PartialEq is here to make tests work - find a way to make it not necessary +#[derive(Clone, Debug, Default, PartialEq)] struct Meta { } #[derive(Debug, PartialEq)] -pub struct AST(pub Vec); +pub struct AST(pub Vec>); #[derive(Debug, PartialEq, Clone)] pub enum Statement { @@ -27,7 +34,7 @@ pub enum Statement { Declaration(Declaration), } -pub type Block = Vec; +pub type Block = Vec>; pub type ParamName = Rc; pub type InterfaceName = Rc; //should be a singleton I think?? pub type FormalParam = (ParamName, Option); diff --git a/schala-lang/language/src/parsing.rs b/schala-lang/language/src/parsing.rs index 4f200af..98d76fb 100644 --- a/schala-lang/language/src/parsing.rs +++ b/schala-lang/language/src/parsing.rs @@ -304,7 +304,9 @@ impl Parser { self.next(); continue; }, - _ => statements.push(self.statement()?), + _ => statements.push( + Node::new(self.statement()?) + ), } } Ok(AST(statements)) @@ -428,8 +430,9 @@ impl Parser { } #[recursive_descent_method] - fn nonempty_func_body(&mut self) -> ParseResult> { - Ok(delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict)) + fn nonempty_func_body(&mut self) -> ParseResult>> { + let statements = delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict); + Ok(statements.into_iter().map(|s| Node::new(s)).collect()) } #[recursive_descent_method] @@ -908,7 +911,8 @@ impl Parser { #[recursive_descent_method] fn block(&mut self) -> ParseResult { - Ok(delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict)) + let block = delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict); + Ok(block.into_iter().map(|s| { Node::new(s) }).collect()) } #[recursive_descent_method] @@ -917,7 +921,7 @@ impl Parser { LCurlyBrace => self.block(), _ => { let expr = self.expression()?; - Ok(vec![Statement::ExpressionStatement(expr)]) + Ok(vec![Node::new(Statement::ExpressionStatement(expr))]) } } } @@ -976,7 +980,7 @@ impl Parser { Ok(match self.peek() { LCurlyBrace => { let statements = delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict); - StatementBlock(statements) + StatementBlock(statements.into_iter().map(|s| Node::new(s)).collect()) }, Keyword(Kw::Return) => { self.next(); @@ -1115,7 +1119,7 @@ mod parse_tests { use super::tokenize; use super::ParseResult; use builtin::{PrefixOp, BinOp}; - use ast::{AST, Expression, Statement, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody}; + use ast::{AST, Node, Expression, Statement, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody}; use super::Statement::*; use super::Declaration::*; use super::Signature; @@ -1171,14 +1175,14 @@ mod parse_tests { ($op:expr, $lhs:expr) => { PrefixExp(PrefixOp::from_sigil($op), bx!(Expression($lhs, None))) } } macro_rules! exst { - ($expr_type:expr) => { Statement::ExpressionStatement(Expression($expr_type, None)) }; - ($expr_type:expr, $type_anno:expr) => { Statement::ExpressionStatement(Expression($expr_type, Some($type_anno))) }; - ($op:expr, $lhs:expr, $rhs:expr) => { Statement::ExpressionStatement(ex!(binexp!($op, $lhs, $rhs))) }; + ($expr_type:expr) => { Node::new(Statement::ExpressionStatement(Expression($expr_type, None))) }; + ($expr_type:expr, $type_anno:expr) => { Node::new(Statement::ExpressionStatement(Expression($expr_type, Some($type_anno)))) }; + ($op:expr, $lhs:expr, $rhs:expr) => { Node::new(Statement::ExpressionStatement(ex!(binexp!($op, $lhs, $rhs)))) }; (s $statement_text:expr) => { { let tokens: Vec<::tokenizing::Token> = tokenize($statement_text); let mut parser = super::Parser::new(tokens); - parser.statement().unwrap() + Node::new(parser.statement().unwrap()) } } } @@ -1274,7 +1278,7 @@ mod parse_tests { #[test] fn parsing_functions() { - parse_test!("fn oi()", AST(vec![Declaration(FuncSig(Signature { name: rc!(oi), operator: false, params: vec![], type_anno: None }))])); + parse_test!("fn oi()", AST(vec![Node::new(Declaration(FuncSig(Signature { name: rc!(oi), operator: false, params: vec![], type_anno: None })))])); parse_test!("oi()", AST(vec![exst!(Call { f: bx!(ex!(val!("oi"))), arguments: vec![] })])); parse_test!("oi(a, 2 + 2)", AST(vec![exst!(Call { f: bx!(ex!(val!("oi"))), @@ -1282,27 +1286,27 @@ mod parse_tests { })])); parse_error!("a(b,,c)"); - parse_test!("fn a(b, c: Int): Int", AST(vec![Declaration( + parse_test!("fn a(b, c: Int): Int", AST(vec![Node::new(Declaration( FuncSig(Signature { name: rc!(a), operator: false, params: vec![ (rc!(b), None), (rc!(c), Some(ty!("Int"))) - ], type_anno: Some(ty!("Int")) }))])); + ], type_anno: Some(ty!("Int")) })))])); - parse_test!("fn a(x) { x() }", AST(vec![Declaration( + parse_test!("fn a(x) { x() }", AST(vec![Node::new(Declaration( FuncDecl(Signature { name: rc!(a), operator: false, params: vec![(rc!(x),None)], type_anno: None }, - vec![exst!(Call { f: bx!(ex!(val!("x"))), arguments: vec![] })]))])); - parse_test!("fn a(x) {\n x() }", AST(vec![Declaration( + vec![exst!(Call { f: bx!(ex!(val!("x"))), arguments: vec![] })])))])); + parse_test!("fn a(x) {\n x() }", AST(vec![Node::new(Declaration( FuncDecl(Signature { name: rc!(a), operator: false, params: vec![(rc!(x),None)], type_anno: None }, - vec![exst!(Call { f: bx!(ex!(val!("x"))), arguments: vec![] })]))])); + vec![exst!(Call { f: bx!(ex!(val!("x"))), arguments: vec![] })])))])); let multiline = r#" fn a(x) { x() } "#; - parse_test!(multiline, AST(vec![Declaration( + parse_test!(multiline, AST(vec![Node::new(Declaration( FuncDecl(Signature { name: rc!(a), operator: false, params: vec![(rc!(x),None)], type_anno: None }, - vec![exst!(Call { f: bx!(ex!(val!("x"))), arguments: vec![] })]))])); + vec![exst!(Call { f: bx!(ex!(val!("x"))), arguments: vec![] })])))])); let multiline2 = r#" fn a(x) { @@ -1310,9 +1314,9 @@ fn a(x) { } "#; - parse_test!(multiline2, AST(vec![Declaration( + parse_test!(multiline2, AST(vec![Node::new(Declaration( FuncDecl(Signature { name: rc!(a), operator: false, params: vec![(rc!(x),None)], type_anno: None }, - vec![exst!(s "x()")]))])); + vec![exst!(s "x()")])))])); } #[test] @@ -1328,11 +1332,11 @@ fn a(x) { #[test] fn parsing_types() { - parse_test!("type Yolo = Yolo", AST(vec![Declaration(TypeDecl { name: tys!("Yolo"), body: TypeBody(vec![UnitStruct(rc!(Yolo))]), mutable: false} )])); - parse_test!("type mut Yolo = Yolo", AST(vec![Declaration(TypeDecl { name: tys!("Yolo"), body: TypeBody(vec![UnitStruct(rc!(Yolo))]), mutable: true} )])); - parse_test!("type alias Sex = Drugs", AST(vec![Declaration(TypeAlias(rc!(Sex), rc!(Drugs)))])); + parse_test!("type Yolo = Yolo", AST(vec![Node::new(Declaration(TypeDecl { name: tys!("Yolo"), body: TypeBody(vec![UnitStruct(rc!(Yolo))]), mutable: false} ))])); + parse_test!("type mut Yolo = Yolo", AST(vec![Node::new(Declaration(TypeDecl { name: tys!("Yolo"), body: TypeBody(vec![UnitStruct(rc!(Yolo))]), mutable: true} ))])); + parse_test!("type alias Sex = Drugs", AST(vec![Node::new(Declaration(TypeAlias(rc!(Sex), rc!(Drugs))))])); parse_test!("type Sanchez = Miguel | Alejandro(Int, Option) | Esperanza { a: Int, b: String }", - AST(vec![Declaration(TypeDecl{ + AST(vec![Node::new(Declaration(TypeDecl{ name: tys!("Sanchez"), body: TypeBody(vec![ UnitStruct(rc!(Miguel)), @@ -1346,21 +1350,21 @@ fn a(x) { ]) ]), mutable: false - })])); + }))])); parse_test!("type Jorge = Diego | Kike(a)", AST(vec![ - Declaration(TypeDecl{ + Node::new(Declaration(TypeDecl{ name: TypeSingletonName { name: rc!(Jorge), params: vec![Singleton(TypeSingletonName { name: rc!(a), params: vec![] })] }, body: TypeBody(vec![UnitStruct(rc!(Diego)), TupleStruct(rc!(Kike), vec![Singleton(TypeSingletonName { name: rc!(a), params: vec![] })])]), mutable: false } - )])); + ))])); } #[test] fn parsing_bindings() { - parse_test!("let mut a = 10", AST(vec![Declaration(Binding { name: rc!(a), constant: false, expr: ex!(NatLiteral(10)) } )])); - parse_test!("let a = 2 + 2", AST(vec![Declaration(Binding { name: rc!(a), constant: true, expr: ex!(binexp!("+", NatLiteral(2), NatLiteral(2))) }) ])); + parse_test!("let mut a = 10", AST(vec![Node::new(Declaration(Binding { name: rc!(a), constant: false, expr: ex!(NatLiteral(10)) } ))])); + parse_test!("let a = 2 + 2", AST(vec![Node::new(Declaration(Binding { name: rc!(a), constant: true, expr: ex!(binexp!("+", NatLiteral(2), NatLiteral(2))) }) )])); } #[test] @@ -1434,50 +1438,53 @@ fn a(x) { #[test] fn parsing_interfaces() { parse_test!("interface Unglueable { fn unglue(a: Glue); fn mar(): Glue }", AST(vec![ - Declaration(Interface { + Node::new(Declaration(Interface { name: rc!(Unglueable), signatures: vec![ Signature { name: rc!(unglue), operator: false, params: vec![(rc!(a), Some(Singleton(TypeSingletonName { name: rc!(Glue), params: vec![] })))], type_anno: None }, Signature { name: rc!(mar), operator: false, params: vec![], type_anno: Some(Singleton(TypeSingletonName { name: rc!(Glue), params: vec![] })) }, ] - }) + })) ])); } #[test] fn parsing_impls() { parse_test!("impl Heh { fn yolo(); fn swagg(); }", AST(vec![ + Node::new( Declaration(Impl { type_name: ty!("Heh"), interface_name: None, block: vec![ FuncSig(Signature { name: rc!(yolo), operator: false, params: vec![], type_anno: None }), FuncSig(Signature { name: rc!(swagg), operator: false, params: vec![], type_anno: None }) - ] })])); + ] }))])); parse_test!("impl Mondai for Lollerino { fn yolo(); fn swagg(); }", AST(vec![ - Declaration(Impl { + Node::new(Declaration(Impl { type_name: ty!("Lollerino"), interface_name: Some(rc!(Mondai)), block: vec![ FuncSig(Signature { name: rc!(yolo), operator: false, params: vec![], type_anno: None}), FuncSig(Signature { name: rc!(swagg), operator: false, params: vec![], type_anno: None }) - ] })])); + ] }))])); parse_test!("impl Option { fn oi() }", AST(vec![ + Node::new( Declaration(Impl { type_name: Singleton(TypeSingletonName { name: rc!(Option), params: vec![ty!("WTFMate")]}), interface_name: None, block: vec![ FuncSig(Signature { name: rc!(oi), operator: false, params: vec![], type_anno: None }), ] - })])); + }))])); } #[test] fn parsing_type_annotations() { parse_test!("let a = b : Int", AST(vec![ + Node::new( Declaration(Binding { name: rc!(a), constant: true, expr: - Expression(val!("b"), Some(ty!("Int"))) })])); + Expression(val!("b"), Some(ty!("Int"))) }))])); parse_test!("a : Int", AST(vec![ exst!(val!("a"), ty!("Int")) diff --git a/schala-lang/language/src/reduced_ast.rs b/schala-lang/language/src/reduced_ast.rs index 5491c2e..44324ac 100644 --- a/schala-lang/language/src/reduced_ast.rs +++ b/schala-lang/language/src/reduced_ast.rs @@ -98,7 +98,7 @@ impl AST { pub fn reduce(&self, symbol_table: &SymbolTable) -> ReducedAST { let mut output = vec![]; for statement in self.0.iter() { - output.push(statement.reduce(symbol_table)); + output.push(statement.node().reduce(symbol_table)); } ReducedAST(output) } @@ -114,6 +114,10 @@ impl Statement { } } +fn reduce_block(block: &Block, symbol_table: &SymbolTable) -> Vec { + block.iter().map(|stmt| stmt.node().reduce(symbol_table)).collect() +} + impl Expression { fn reduce(&self, symbol_table: &SymbolTable) -> Expr { use ast::ExpressionType::*; @@ -154,7 +158,7 @@ fn reduce_lambda(params: &Vec, body: &Block, symbol_table: &SymbolT Expr::Func(Func::UserDefined { name: None, params: params.iter().map(|param| param.0.clone()).collect(), - body: body.iter().map(|stmt| stmt.reduce(symbol_table)).collect(), + body: reduce_block(body, symbol_table), }) } @@ -165,18 +169,18 @@ fn reduce_if_expression(discriminator: &Discriminator, body: &IfExpressionBody, }); match *body { IfExpressionBody::SimpleConditional(ref then_clause, ref else_clause) => { - let then_clause = then_clause.iter().map(|expr| expr.reduce(symbol_table)).collect(); + let then_clause = reduce_block(then_clause, symbol_table); let else_clause = match else_clause { None => vec![], - Some(stmts) => stmts.iter().map(|expr| expr.reduce(symbol_table)).collect(), + Some(stmts) => reduce_block(stmts, symbol_table), }; Expr::Conditional { cond, then_clause, else_clause } }, IfExpressionBody::SimplePatternMatch(ref pat, ref then_clause, ref else_clause) => { - let then_clause = then_clause.iter().map(|expr| expr.reduce(symbol_table)).collect(); + let then_clause = reduce_block(then_clause, symbol_table); let else_clause = match else_clause { None => vec![], - Some(stmts) => stmts.iter().map(|expr| expr.reduce(symbol_table)).collect(), + Some(stmts) => reduce_block(stmts, symbol_table), }; let alternatives = vec![ @@ -200,7 +204,7 @@ fn reduce_if_expression(discriminator: &Discriminator, body: &IfExpressionBody, for arm in guard_arms { match arm.guard { Guard::Pat(ref p) => { - let item = arm.body.iter().map(|expr| expr.reduce(symbol_table)).collect(); + let item = reduce_block(&arm.body, symbol_table); let alt = p.to_alternative(item, symbol_table); alternatives.push(alt); }, @@ -360,7 +364,7 @@ impl Declaration { func: Func::UserDefined { name: Some(name.clone()), params: params.iter().map(|param| param.0.clone()).collect(), - body: statements.iter().map(|stmt| stmt.reduce(symbol_table)).collect(), + body: reduce_block(&statements, symbol_table), } }, TypeDecl { .. } => Stmt::Noop, diff --git a/schala-lang/language/src/symbol_table.rs b/schala-lang/language/src/symbol_table.rs index ab3976b..7f2cedc 100644 --- a/schala-lang/language/src/symbol_table.rs +++ b/schala-lang/language/src/symbol_table.rs @@ -62,6 +62,7 @@ impl SymbolTable { use self::ast::{Statement, TypeIdentifier, Variant, TypeSingletonName, TypeBody}; use self::ast::Declaration::*; for statement in ast.0.iter() { + let statement = statement.node(); if let Statement::Declaration(decl) = statement { match decl { FuncSig(signature) | FuncDecl(signature, _) => { diff --git a/schala-lang/language/src/typechecking.rs b/schala-lang/language/src/typechecking.rs index 437622f..3e48c23 100644 --- a/schala-lang/language/src/typechecking.rs +++ b/schala-lang/language/src/typechecking.rs @@ -208,7 +208,7 @@ impl<'a> TypeContext<'a> { fn infer_block(&mut self, block: &Block) -> InferResult> { let mut output = Type::Const(TConst::Unit); for statement in block.iter() { - output = self.infer_statement(statement)?; + output = self.infer_statement(statement.node())?; } Ok(output) }