diff --git a/schala-lang/language/src/ast.rs b/schala-lang/language/src/ast.rs index 7805147..af660d9 100644 --- a/schala-lang/language/src/ast.rs +++ b/schala-lang/language/src/ast.rs @@ -50,8 +50,13 @@ pub struct AST { } #[derive(Debug, PartialEq, Clone)] -pub enum Statement { - ExpressionStatement(Meta), +pub struct Statement { + pub kind: StatementKind, +} + +#[derive(Debug, PartialEq, Clone)] +pub enum StatementKind { + Expression(Meta), Declaration(Declaration), //TODO Declaration should also be Meta-wrapped; only Expression and Declaration are Meta-wrapped maybe? } diff --git a/schala-lang/language/src/parsing.rs b/schala-lang/language/src/parsing.rs index 38351ca..e601ac3 100644 --- a/schala-lang/language/src/parsing.rs +++ b/schala-lang/language/src/parsing.rs @@ -341,14 +341,15 @@ impl Parser { #[recursive_descent_method] fn statement(&mut self) -> ParseResult { //TODO handle error recovery here - match self.token_handler.peek().get_kind() { - Keyword(Type) => self.type_declaration().map(|decl| { Statement::Declaration(decl) }), - Keyword(Func)=> self.func_declaration().map(|func| { Statement::Declaration(func) }), - Keyword(Let) => self.binding_declaration().map(|decl| Statement::Declaration(decl)), - Keyword(Interface) => self.interface_declaration().map(|decl| Statement::Declaration(decl)), - Keyword(Impl) => self.impl_declaration().map(|decl| Statement::Declaration(decl)), - _ => self.expression().map(|expr| { Statement::ExpressionStatement(expr.into()) } ), - } + let kind = match self.token_handler.peek().get_kind() { + Keyword(Type) => self.type_declaration().map(|decl| { StatementKind::Declaration(decl) }), + Keyword(Func)=> self.func_declaration().map(|func| { StatementKind::Declaration(func) }), + Keyword(Let) => self.binding_declaration().map(|decl| StatementKind::Declaration(decl)), + Keyword(Interface) => self.interface_declaration().map(|decl| StatementKind::Declaration(decl)), + Keyword(Impl) => self.impl_declaration().map(|decl| StatementKind::Declaration(decl)), + _ => self.expression().map(|expr| { StatementKind::Expression(expr.into()) } ), + }?; + Ok(Statement { kind }) } #[recursive_descent_method] @@ -1060,7 +1061,8 @@ impl Parser { LCurlyBrace => self.block(), _ => { let expr = self.expression()?; - Ok(vec![Meta::new(Statement::ExpressionStatement(expr.into()))]) + let s = Statement { kind: StatementKind::Expression(expr.into()) }; + Ok(vec![Meta::new(s)]) } } } diff --git a/schala-lang/language/src/parsing/test.rs b/schala-lang/language/src/parsing/test.rs index a0d9305..376ce55 100644 --- a/schala-lang/language/src/parsing/test.rs +++ b/schala-lang/language/src/parsing/test.rs @@ -4,8 +4,7 @@ use std::str::FromStr; use super::tokenize; use super::ParseResult; -use crate::ast::{AST, Meta, Expression, Statement, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody, InvocationArgument, FormalParam, PrefixOp, BinOp, QualifiedName}; -use super::Statement::*; +use crate::ast::{AST, Meta, Expression, Statement, StatementKind, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody, InvocationArgument, FormalParam, PrefixOp, BinOp, QualifiedName}; use super::Declaration::*; use super::Signature; use super::TypeIdentifier::*; @@ -39,6 +38,12 @@ macro_rules! tys { ($name:expr) => { TypeSingletonName { name: Rc::new($name.to_string()), params: vec![] } }; } +macro_rules! decl { + ($expr_type:expr) => { + Statement { kind: StatementKind::Declaration($expr_type) } + }; +} + macro_rules! ex { ($expr_type:expr) => { Expression::new($expr_type) }; (m $expr_type:expr) => { Meta::new(Expression::new($expr_type)) }; @@ -63,9 +68,11 @@ macro_rules! prefexp { ($op:expr, $lhs:expr) => { PrefixExp(PrefixOp::from_str($op).unwrap(), bx!(Expression::new($lhs).into())) } } macro_rules! exst { - ($expr_type:expr) => { Meta::new(Statement::ExpressionStatement(Expression::new($expr_type).into())) }; - ($expr_type:expr, $type_anno:expr) => { Meta::new(Statement::ExpressionStatement(Expression::with_anno($expr_type, $type_anno).into())) }; - ($op:expr, $lhs:expr, $rhs:expr) => { Meta::new(Statement::ExpressionStatement(ex!(binexp!($op, $lhs, $rhs)))) }; + ($expr_type:expr) => { Meta::new(Statement { kind: StatementKind::Expression(Expression::new($expr_type).into())}) }; + ($expr_type:expr, $type_anno:expr) => { Meta::new(Statement { kind: StatementKind::Expression(Expression::with_anno($expr_type, $type_anno).into())}) }; + ($op:expr, $lhs:expr, $rhs:expr) => { Meta::new( + Statement { kind: StatementKind::Expression(ex!(binexp!($op, $lhs, $rhs)))} + )}; (s $statement_text:expr) => { { let tokens: Vec = tokenize($statement_text); @@ -168,7 +175,7 @@ fn parsing_identifiers() { fn qualified_identifiers() { parse_test_wrap_ast! { "let q_q = Yolo::Swaggins", - Meta::new(Declaration(Binding { name: rc!(q_q), constant: true, type_anno: None, + Meta::new(decl!(Binding { name: rc!(q_q), constant: true, type_anno: None, expr: Meta::new(Expression::new(Value(Meta::new(QualifiedName(vec![rc!(Yolo), rc!(Swaggins)]))))), })) } @@ -203,7 +210,7 @@ fn parsing_complicated_operators() { #[test] fn parsing_functions() { - parse_test_wrap_ast!("fn oi()", Meta::new(Declaration(FuncSig(Signature { name: rc!(oi), operator: false, params: vec![], type_anno: None })))); + parse_test_wrap_ast!("fn oi()", Meta::new(decl!(FuncSig(Signature { name: rc!(oi), operator: false, params: vec![], type_anno: None })))); parse_test_wrap_ast!("oi()", exst!(Call { f: bx!(ex!(m val!("oi"))), arguments: vec![] })); parse_test_wrap_ast!("oi(a, 2 + 2)", exst!(Call { f: bx!(ex!(m val!("oi"))), @@ -211,17 +218,17 @@ fn parsing_functions() { })); parse_error!("a(b,,c)"); - parse_test_wrap_ast!("fn a(b, c: Int): Int", Meta::new(Declaration( + parse_test_wrap_ast!("fn a(b, c: Int): Int", Meta::new(decl!( FuncSig(Signature { name: rc!(a), operator: false, params: vec![ FormalParam { name: rc!(b), anno: None, default: None }, FormalParam { name: rc!(c), anno: Some(ty!("Int")), default: None } ], type_anno: Some(ty!("Int")) })))); - parse_test_wrap_ast!("fn a(x) { x() }", Meta::new(Declaration( + parse_test_wrap_ast!("fn a(x) { x() }", Meta::new(decl!( FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), anno: None, default: None }], type_anno: None }, vec![exst!(Call { f: bx!(ex!(m val!("x"))), arguments: vec![] })])))); - parse_test_wrap_ast!("fn a(x) {\n x() }", Meta::new(Declaration( + parse_test_wrap_ast!("fn a(x) {\n x() }", Meta::new(decl!( FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), anno: None, default: None }], type_anno: None }, vec![exst!(Call { f: bx!(ex!(m val!("x"))), arguments: vec![] })])))); @@ -230,7 +237,7 @@ fn a(x) { x() } "#; - parse_test_wrap_ast!(multiline, Meta::new(Declaration( + parse_test_wrap_ast!(multiline, Meta::new(decl!( FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), default: None, anno: None }], type_anno: None }, vec![exst!(Call { f: bx!(ex!(m val!("x"))), arguments: vec![] })])))); let multiline2 = r#" @@ -240,7 +247,7 @@ x() } "#; - parse_test_wrap_ast!(multiline2, Meta::new(Declaration( + parse_test_wrap_ast!(multiline2, Meta::new(decl!( FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), default: None, anno: None }], type_anno: None }, vec![exst!(s "x()")])))); } @@ -249,7 +256,7 @@ x() fn functions_with_default_args() { parse_test_wrap_ast! { "fn func(x: Int, y: Int = 4) { }", - Meta::new(Declaration( + Meta::new(decl!( FuncDecl(Signature { name: rc!(func), operator: false, type_anno: None, params: vec![ FormalParam { name: rc!(x), default: None, anno: Some(ty!("Int")) }, FormalParam { name: rc!(y), default: Some(Meta::new(ex!(s "4"))), anno: Some(ty!("Int")) } @@ -271,11 +278,11 @@ fn parsing_strings() { #[test] fn parsing_types() { - parse_test_wrap_ast!("type Yolo = Yolo", Meta::new(Declaration(TypeDecl { name: tys!("Yolo"), body: TypeBody(vec![UnitStruct(rc!(Yolo))]), mutable: false} ))); - parse_test_wrap_ast!("type mut Yolo = Yolo", Meta::new(Declaration(TypeDecl { name: tys!("Yolo"), body: TypeBody(vec![UnitStruct(rc!(Yolo))]), mutable: true} ))); - parse_test_wrap_ast!("type alias Sex = Drugs", Meta::new(Declaration(TypeAlias(rc!(Sex), rc!(Drugs))))); + parse_test_wrap_ast!("type Yolo = Yolo", Meta::new(decl!(TypeDecl { name: tys!("Yolo"), body: TypeBody(vec![UnitStruct(rc!(Yolo))]), mutable: false} ))); + parse_test_wrap_ast!("type mut Yolo = Yolo", Meta::new(decl!(TypeDecl { name: tys!("Yolo"), body: TypeBody(vec![UnitStruct(rc!(Yolo))]), mutable: true} ))); + parse_test_wrap_ast!("type alias Sex = Drugs", Meta::new(decl!(TypeAlias(rc!(Sex), rc!(Drugs))))); parse_test_wrap_ast!("type Sanchez = Miguel | Alejandro(Int, Option) | Esperanza { a: Int, b: String }", - Meta::new(Declaration(TypeDecl { + Meta::new(decl!(TypeDecl { name: tys!("Sanchez"), body: TypeBody(vec![ UnitStruct(rc!(Miguel)), @@ -296,7 +303,7 @@ fn parsing_types() { parse_test_wrap_ast! { "type Jorge = Diego | Kike(a)", - Meta::new(Declaration(TypeDecl{ + Meta::new(decl!(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 @@ -307,9 +314,9 @@ fn parsing_types() { #[test] fn parsing_bindings() { - parse_test_wrap_ast!("let mut a = 10", Meta::new(Declaration(Binding { name: rc!(a), constant: false, type_anno: None, expr: ex!(m NatLiteral(10)) } ))); - parse_test_wrap_ast!("let a = 2 + 2", Meta::new(Declaration(Binding { name: rc!(a), constant: true, type_anno: None, expr: ex!(m binexp!("+", NatLiteral(2), NatLiteral(2))) }) )); - parse_test_wrap_ast!("let a: Nat = 2 + 2", Meta::new(Declaration( + parse_test_wrap_ast!("let mut a = 10", Meta::new(decl!(Binding { name: rc!(a), constant: false, type_anno: None, expr: ex!(m NatLiteral(10)) } ))); + parse_test_wrap_ast!("let a = 2 + 2", Meta::new(decl!(Binding { name: rc!(a), constant: true, type_anno: None, expr: ex!(m binexp!("+", NatLiteral(2), NatLiteral(2))) }) )); + parse_test_wrap_ast!("let a: Nat = 2 + 2", Meta::new(decl!( Binding { name: rc!(a), constant: true, type_anno: Some(Singleton(TypeSingletonName { name: rc!(Nat), params: vec![] })), expr: Meta::new(ex!(binexp!("+", NatLiteral(2), NatLiteral(2)))) } ))); @@ -365,7 +372,7 @@ fn parsing_block_expressions() { c }"#, AST(vec![exst!(IfExpression(bx!(ex!(BoolLiteral(true))), - vec![Declaration(Binding { name: rc!(a), constant: true, expr: ex!(NatLiteral(10)) }), + vec![decl!(Binding { name: rc!(a), constant: true, expr: ex!(NatLiteral(10)) }), exst!(val!(rc!(b)))], Some(vec![exst!(val!(rc!(c)))])))]) ); @@ -386,7 +393,7 @@ fn parsing_block_expressions() { #[test] fn parsing_interfaces() { parse_test_wrap_ast!("interface Unglueable { fn unglue(a: Glue); fn mar(): Glue }", - Meta::new(Declaration(Interface { + Meta::new(decl!(Interface { name: rc!(Unglueable), signatures: vec![ Signature { @@ -407,7 +414,7 @@ fn parsing_interfaces() { fn parsing_impls() { parse_test_wrap_ast!("impl Heh { fn yolo(); fn swagg(); }", Meta::new( - Declaration(Impl { + decl!(Impl { type_name: ty!("Heh"), interface_name: None, block: vec![ @@ -416,7 +423,7 @@ fn parsing_impls() { ] }))); parse_test_wrap_ast!("impl Mondai for Lollerino { fn yolo(); fn swagg(); }", - Meta::new(Declaration(Impl { + Meta::new(decl!(Impl { type_name: ty!("Lollerino"), interface_name: Some(TypeSingletonName { name: rc!(Mondai), params: vec![] }), block: vec![ @@ -425,7 +432,7 @@ fn parsing_impls() { ] }))); parse_test_wrap_ast!("impl Hella for (Alpha, Omega) { }", - Meta::new(Declaration(Impl { + Meta::new(decl!(Impl { type_name: Tuple(vec![ty!("Alpha"), ty!("Omega")]), interface_name: Some(TypeSingletonName { name: rc!(Hella), params: vec![ty!("T")] }), block: vec![] @@ -434,7 +441,7 @@ fn parsing_impls() { parse_test_wrap_ast!("impl Option { fn oi() }", Meta::new( - Declaration(Impl { + decl!(Impl { type_name: Singleton(TypeSingletonName { name: rc!(Option), params: vec![ty!("WTFMate")]}), interface_name: None, block: vec![ @@ -447,7 +454,7 @@ fn parsing_impls() { fn parsing_type_annotations() { parse_test_wrap_ast!("let a = b : Int", Meta::new( - Declaration(Binding { name: rc!(a), constant: true, type_anno: None, expr: + decl!(Binding { name: rc!(a), constant: true, type_anno: None, expr: ex!(m val!("b"), ty!("Int")) }))); parse_test_wrap_ast!("a : Int", diff --git a/schala-lang/language/src/reduced_ast.rs b/schala-lang/language/src/reduced_ast.rs index 5a91ade..16fef7c 100644 --- a/schala-lang/language/src/reduced_ast.rs +++ b/schala-lang/language/src/reduced_ast.rs @@ -126,10 +126,9 @@ impl<'a> Reducer<'a> { } fn statement(&mut self, stmt: &Meta) -> Stmt { - use crate::ast::Statement::*; - match stmt.node() { - ExpressionStatement(expr) => Stmt::Expr(self.expression(expr)), - Declaration(decl) => self.declaration(decl), + match &stmt.node().kind { + StatementKind::Expression(expr) => Stmt::Expr(self.expression(&expr)), + StatementKind::Declaration(decl) => self.declaration(&decl), } } diff --git a/schala-lang/language/src/scope_resolution.rs b/schala-lang/language/src/scope_resolution.rs index 7ad9bc6..4043c37 100644 --- a/schala-lang/language/src/scope_resolution.rs +++ b/schala-lang/language/src/scope_resolution.rs @@ -11,9 +11,9 @@ impl<'a> ScopeResolver<'a> { } pub fn resolve(&mut self, ast: &mut AST) -> Result<(), String> { for statement in ast.statements.iter_mut() { - match statement.mut_node() { - Statement::Declaration(ref mut decl) => self.decl(decl), - Statement::ExpressionStatement(ref mut expr) => self.expr(expr), + match statement.mut_node().kind { + StatementKind::Declaration(ref mut decl) => self.decl(decl), + StatementKind::Expression(ref mut expr) => self.expr(expr), }?; } Ok(()) @@ -29,9 +29,9 @@ impl<'a> ScopeResolver<'a> { } fn block(&mut self, block: &mut Block) -> Result<(), String> { for statement in block.iter_mut() { - match statement.mut_node() { - Statement::Declaration(ref mut decl) => self.decl(decl), - Statement::ExpressionStatement(ref mut expr) => self.expr(expr), + match statement.mut_node().kind { + StatementKind::Declaration(ref mut decl) => self.decl(decl), + StatementKind::Expression(ref mut expr) => self.expr(expr), }?; } Ok(()) diff --git a/schala-lang/language/src/symbol_table.rs b/schala-lang/language/src/symbol_table.rs index 2186332..3c61723 100644 --- a/schala-lang/language/src/symbol_table.rs +++ b/schala-lang/language/src/symbol_table.rs @@ -5,7 +5,7 @@ use std::fmt; use std::fmt::Write; use crate::ast; -use crate::ast::{Meta, TypeBody, TypeSingletonName, Signature, Statement}; +use crate::ast::{Meta, TypeBody, TypeSingletonName, Signature, Statement, StatementKind}; use crate::typechecking::TypeName; type LineNumber = u32; @@ -175,7 +175,7 @@ impl SymbolTable { for meta in statements.iter() { let statement = meta.node(); - if let Statement::Declaration(decl) = statement { + if let Statement { kind: StatementKind::Declaration(decl), .. } = statement { match decl { FuncSig(ref signature) => { insert_and_check_duplicate_symbol(&mut seen_identifiers, &signature.name)?; diff --git a/schala-lang/language/src/typechecking.rs b/schala-lang/language/src/typechecking.rs index ca005b8..220adbd 100644 --- a/schala-lang/language/src/typechecking.rs +++ b/schala-lang/language/src/typechecking.rs @@ -271,9 +271,9 @@ impl<'a> TypeContext<'a> { } fn statement(&mut self, statement: &Statement) -> InferResult { - match statement { - Statement::ExpressionStatement(e) => self.expr(e.node()), - Statement::Declaration(decl) => self.decl(decl), + match &statement.kind { + StatementKind::Expression(e) => self.expr(e.node()), + StatementKind::Declaration(decl) => self.decl(&decl), } }