Adding Node intermediate type to AST

This commit is contained in:
greg 2019-01-04 22:58:25 -08:00
parent 87e68988c8
commit 282c42da3c
5 changed files with 69 additions and 50 deletions

View File

@ -4,22 +4,29 @@ use std::convert::From;
use source_map::{SourceMap}; use source_map::{SourceMap};
use builtin::{BinOp, PrefixOp}; use builtin::{BinOp, PrefixOp};
#[derive(Clone, Debug, PartialEq)]
pub struct Node<T> { pub struct Node<T> {
n: T, n: T,
meta: Meta meta: Meta
} }
impl<T> Node<T> { impl<T> Node<T> {
fn node(&self) -> &T { pub fn new(n: T) -> Node<T> {
Node { n, meta: Meta::default() }
}
pub fn node(&self) -> &T {
&self.n &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 { struct Meta {
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct AST(pub Vec<Statement>); pub struct AST(pub Vec<Node<Statement>>);
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum Statement { pub enum Statement {
@ -27,7 +34,7 @@ pub enum Statement {
Declaration(Declaration), Declaration(Declaration),
} }
pub type Block = Vec<Statement>; pub type Block = Vec<Node<Statement>>;
pub type ParamName = Rc<String>; pub type ParamName = Rc<String>;
pub type InterfaceName = Rc<String>; //should be a singleton I think?? pub type InterfaceName = Rc<String>; //should be a singleton I think??
pub type FormalParam = (ParamName, Option<TypeIdentifier>); pub type FormalParam = (ParamName, Option<TypeIdentifier>);

View File

@ -304,7 +304,9 @@ impl Parser {
self.next(); self.next();
continue; continue;
}, },
_ => statements.push(self.statement()?), _ => statements.push(
Node::new(self.statement()?)
),
} }
} }
Ok(AST(statements)) Ok(AST(statements))
@ -428,8 +430,9 @@ impl Parser {
} }
#[recursive_descent_method] #[recursive_descent_method]
fn nonempty_func_body(&mut self) -> ParseResult<Vec<Statement>> { fn nonempty_func_body(&mut self) -> ParseResult<Vec<Node<Statement>>> {
Ok(delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict)) let statements = delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict);
Ok(statements.into_iter().map(|s| Node::new(s)).collect())
} }
#[recursive_descent_method] #[recursive_descent_method]
@ -908,7 +911,8 @@ impl Parser {
#[recursive_descent_method] #[recursive_descent_method]
fn block(&mut self) -> ParseResult<Block> { fn block(&mut self) -> ParseResult<Block> {
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] #[recursive_descent_method]
@ -917,7 +921,7 @@ impl Parser {
LCurlyBrace => self.block(), LCurlyBrace => self.block(),
_ => { _ => {
let expr = self.expression()?; 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() { Ok(match self.peek() {
LCurlyBrace => { LCurlyBrace => {
let statements = delimited!(self, LCurlyBrace, statement, Newline | Semicolon, RCurlyBrace, nonstrict); 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) => { Keyword(Kw::Return) => {
self.next(); self.next();
@ -1115,7 +1119,7 @@ mod parse_tests {
use super::tokenize; use super::tokenize;
use super::ParseResult; use super::ParseResult;
use builtin::{PrefixOp, BinOp}; 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::Statement::*;
use super::Declaration::*; use super::Declaration::*;
use super::Signature; use super::Signature;
@ -1171,14 +1175,14 @@ mod parse_tests {
($op:expr, $lhs:expr) => { PrefixExp(PrefixOp::from_sigil($op), bx!(Expression($lhs, None))) } ($op:expr, $lhs:expr) => { PrefixExp(PrefixOp::from_sigil($op), bx!(Expression($lhs, None))) }
} }
macro_rules! exst { macro_rules! exst {
($expr_type:expr) => { Statement::ExpressionStatement(Expression($expr_type, None)) }; ($expr_type:expr) => { Node::new(Statement::ExpressionStatement(Expression($expr_type, None))) };
($expr_type:expr, $type_anno:expr) => { Statement::ExpressionStatement(Expression($expr_type, Some($type_anno))) }; ($expr_type:expr, $type_anno:expr) => { Node::new(Statement::ExpressionStatement(Expression($expr_type, Some($type_anno)))) };
($op:expr, $lhs:expr, $rhs:expr) => { Statement::ExpressionStatement(ex!(binexp!($op, $lhs, $rhs))) }; ($op:expr, $lhs:expr, $rhs:expr) => { Node::new(Statement::ExpressionStatement(ex!(binexp!($op, $lhs, $rhs)))) };
(s $statement_text:expr) => { (s $statement_text:expr) => {
{ {
let tokens: Vec<::tokenizing::Token> = tokenize($statement_text); let tokens: Vec<::tokenizing::Token> = tokenize($statement_text);
let mut parser = super::Parser::new(tokens); let mut parser = super::Parser::new(tokens);
parser.statement().unwrap() Node::new(parser.statement().unwrap())
} }
} }
} }
@ -1274,7 +1278,7 @@ mod parse_tests {
#[test] #[test]
fn parsing_functions() { 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()", AST(vec![exst!(Call { f: bx!(ex!(val!("oi"))), arguments: vec![] })]));
parse_test!("oi(a, 2 + 2)", AST(vec![exst!(Call parse_test!("oi(a, 2 + 2)", AST(vec![exst!(Call
{ f: bx!(ex!(val!("oi"))), { f: bx!(ex!(val!("oi"))),
@ -1282,27 +1286,27 @@ mod parse_tests {
})])); })]));
parse_error!("a(b,,c)"); 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![ FuncSig(Signature { name: rc!(a), operator: false, params: vec![
(rc!(b), None), (rc!(c), Some(ty!("Int"))) (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 }, 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![] })])))]));
parse_test!("fn a(x) {\n x() }", AST(vec![Declaration( 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 }, 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#" let multiline = r#"
fn a(x) { fn a(x) {
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 }, 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#" let multiline2 = r#"
fn a(x) { 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 }, FuncDecl(Signature { name: rc!(a), operator: false, params: vec![(rc!(x),None)], type_anno: None },
vec![exst!(s "x()")]))])); vec![exst!(s "x()")])))]));
} }
#[test] #[test]
@ -1328,11 +1332,11 @@ fn a(x) {
#[test] #[test]
fn parsing_types() { 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 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![Declaration(TypeDecl { name: tys!("Yolo"), body: TypeBody(vec![UnitStruct(rc!(Yolo))]), mutable: true} )])); 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![Declaration(TypeAlias(rc!(Sex), rc!(Drugs)))])); parse_test!("type alias Sex = Drugs", AST(vec![Node::new(Declaration(TypeAlias(rc!(Sex), rc!(Drugs))))]));
parse_test!("type Sanchez = Miguel | Alejandro(Int, Option<a>) | Esperanza { a: Int, b: String }", parse_test!("type Sanchez = Miguel | Alejandro(Int, Option<a>) | Esperanza { a: Int, b: String }",
AST(vec![Declaration(TypeDecl{ AST(vec![Node::new(Declaration(TypeDecl{
name: tys!("Sanchez"), name: tys!("Sanchez"),
body: TypeBody(vec![ body: TypeBody(vec![
UnitStruct(rc!(Miguel)), UnitStruct(rc!(Miguel)),
@ -1346,21 +1350,21 @@ fn a(x) {
]) ])
]), ]),
mutable: false mutable: false
})])); }))]));
parse_test!("type Jorge<a> = Diego | Kike(a)", AST(vec![ parse_test!("type Jorge<a> = 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![] })] }, 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![] })])]), body: TypeBody(vec![UnitStruct(rc!(Diego)), TupleStruct(rc!(Kike), vec![Singleton(TypeSingletonName { name: rc!(a), params: vec![] })])]),
mutable: false mutable: false
} }
)])); ))]));
} }
#[test] #[test]
fn parsing_bindings() { 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 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![Declaration(Binding { name: rc!(a), constant: true, expr: ex!(binexp!("+", NatLiteral(2), NatLiteral(2))) }) ])); 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] #[test]
@ -1434,50 +1438,53 @@ fn a(x) {
#[test] #[test]
fn parsing_interfaces() { fn parsing_interfaces() {
parse_test!("interface Unglueable { fn unglue(a: Glue); fn mar(): Glue }", AST(vec![ parse_test!("interface Unglueable { fn unglue(a: Glue); fn mar(): Glue }", AST(vec![
Declaration(Interface { Node::new(Declaration(Interface {
name: rc!(Unglueable), name: rc!(Unglueable),
signatures: vec![ 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!(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![] })) }, Signature { name: rc!(mar), operator: false, params: vec![], type_anno: Some(Singleton(TypeSingletonName { name: rc!(Glue), params: vec![] })) },
] ]
}) }))
])); ]));
} }
#[test] #[test]
fn parsing_impls() { fn parsing_impls() {
parse_test!("impl Heh { fn yolo(); fn swagg(); }", AST(vec![ parse_test!("impl Heh { fn yolo(); fn swagg(); }", AST(vec![
Node::new(
Declaration(Impl { Declaration(Impl {
type_name: ty!("Heh"), type_name: ty!("Heh"),
interface_name: None, interface_name: None,
block: vec![ block: vec![
FuncSig(Signature { name: rc!(yolo), operator: false, params: vec![], type_anno: None }), FuncSig(Signature { name: rc!(yolo), operator: false, params: vec![], type_anno: None }),
FuncSig(Signature { name: rc!(swagg), 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![ parse_test!("impl Mondai for Lollerino { fn yolo(); fn swagg(); }", AST(vec![
Declaration(Impl { Node::new(Declaration(Impl {
type_name: ty!("Lollerino"), type_name: ty!("Lollerino"),
interface_name: Some(rc!(Mondai)), interface_name: Some(rc!(Mondai)),
block: vec![ block: vec![
FuncSig(Signature { name: rc!(yolo), operator: false, params: vec![], type_anno: None}), FuncSig(Signature { name: rc!(yolo), operator: false, params: vec![], type_anno: None}),
FuncSig(Signature { name: rc!(swagg), operator: false, params: vec![], type_anno: None }) FuncSig(Signature { name: rc!(swagg), operator: false, params: vec![], type_anno: None })
] })])); ] }))]));
parse_test!("impl Option<WTFMate> { fn oi() }", AST(vec![ parse_test!("impl Option<WTFMate> { fn oi() }", AST(vec![
Node::new(
Declaration(Impl { Declaration(Impl {
type_name: Singleton(TypeSingletonName { name: rc!(Option), params: vec![ty!("WTFMate")]}), type_name: Singleton(TypeSingletonName { name: rc!(Option), params: vec![ty!("WTFMate")]}),
interface_name: None, interface_name: None,
block: vec![ block: vec![
FuncSig(Signature { name: rc!(oi), operator: false, params: vec![], type_anno: None }), FuncSig(Signature { name: rc!(oi), operator: false, params: vec![], type_anno: None }),
] ]
})])); }))]));
} }
#[test] #[test]
fn parsing_type_annotations() { fn parsing_type_annotations() {
parse_test!("let a = b : Int", AST(vec![ parse_test!("let a = b : Int", AST(vec![
Node::new(
Declaration(Binding { name: rc!(a), constant: true, expr: 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![ parse_test!("a : Int", AST(vec![
exst!(val!("a"), ty!("Int")) exst!(val!("a"), ty!("Int"))

View File

@ -98,7 +98,7 @@ impl AST {
pub fn reduce(&self, symbol_table: &SymbolTable) -> ReducedAST { pub fn reduce(&self, symbol_table: &SymbolTable) -> ReducedAST {
let mut output = vec![]; let mut output = vec![];
for statement in self.0.iter() { for statement in self.0.iter() {
output.push(statement.reduce(symbol_table)); output.push(statement.node().reduce(symbol_table));
} }
ReducedAST(output) ReducedAST(output)
} }
@ -114,6 +114,10 @@ impl Statement {
} }
} }
fn reduce_block(block: &Block, symbol_table: &SymbolTable) -> Vec<Stmt> {
block.iter().map(|stmt| stmt.node().reduce(symbol_table)).collect()
}
impl Expression { impl Expression {
fn reduce(&self, symbol_table: &SymbolTable) -> Expr { fn reduce(&self, symbol_table: &SymbolTable) -> Expr {
use ast::ExpressionType::*; use ast::ExpressionType::*;
@ -154,7 +158,7 @@ fn reduce_lambda(params: &Vec<FormalParam>, body: &Block, symbol_table: &SymbolT
Expr::Func(Func::UserDefined { Expr::Func(Func::UserDefined {
name: None, name: None,
params: params.iter().map(|param| param.0.clone()).collect(), 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 { match *body {
IfExpressionBody::SimpleConditional(ref then_clause, ref else_clause) => { 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 { let else_clause = match else_clause {
None => vec![], 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 } Expr::Conditional { cond, then_clause, else_clause }
}, },
IfExpressionBody::SimplePatternMatch(ref pat, ref then_clause, ref 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 { let else_clause = match else_clause {
None => vec![], None => vec![],
Some(stmts) => stmts.iter().map(|expr| expr.reduce(symbol_table)).collect(), Some(stmts) => reduce_block(stmts, symbol_table),
}; };
let alternatives = vec![ let alternatives = vec![
@ -200,7 +204,7 @@ fn reduce_if_expression(discriminator: &Discriminator, body: &IfExpressionBody,
for arm in guard_arms { for arm in guard_arms {
match arm.guard { match arm.guard {
Guard::Pat(ref p) => { 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); let alt = p.to_alternative(item, symbol_table);
alternatives.push(alt); alternatives.push(alt);
}, },
@ -360,7 +364,7 @@ impl Declaration {
func: Func::UserDefined { func: Func::UserDefined {
name: Some(name.clone()), name: Some(name.clone()),
params: params.iter().map(|param| param.0.clone()).collect(), 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, TypeDecl { .. } => Stmt::Noop,

View File

@ -62,6 +62,7 @@ impl SymbolTable {
use self::ast::{Statement, TypeIdentifier, Variant, TypeSingletonName, TypeBody}; use self::ast::{Statement, TypeIdentifier, Variant, TypeSingletonName, TypeBody};
use self::ast::Declaration::*; use self::ast::Declaration::*;
for statement in ast.0.iter() { for statement in ast.0.iter() {
let statement = statement.node();
if let Statement::Declaration(decl) = statement { if let Statement::Declaration(decl) = statement {
match decl { match decl {
FuncSig(signature) | FuncDecl(signature, _) => { FuncSig(signature) | FuncDecl(signature, _) => {

View File

@ -208,7 +208,7 @@ impl<'a> TypeContext<'a> {
fn infer_block(&mut self, block: &Block) -> InferResult<Type<UVar>> { fn infer_block(&mut self, block: &Block) -> InferResult<Type<UVar>> {
let mut output = Type::Const(TConst::Unit); let mut output = Type::Const(TConst::Unit);
for statement in block.iter() { for statement in block.iter() {
output = self.infer_statement(statement)?; output = self.infer_statement(statement.node())?;
} }
Ok(output) Ok(output)
} }