diff --git a/schala-lang/src/ast.rs b/schala-lang/src/ast.rs new file mode 100644 index 0000000..95f5cfb --- /dev/null +++ b/schala-lang/src/ast.rs @@ -0,0 +1,132 @@ +use std::rc::Rc; + +use builtin::{BinOp, PrefixOp}; + +#[derive(Debug, PartialEq)] +pub struct AST(pub Vec); + +#[derive(Debug, PartialEq, Clone)] +pub enum Statement { + ExpressionStatement(Expression), + Declaration(Declaration), +} + +pub type Block = Vec; + +pub type ParamName = Rc; +pub type InterfaceName = Rc; //should be a singleton I think?? +pub type FormalParam = (ParamName, Option); + +#[derive(Debug, PartialEq, Clone)] +pub enum Declaration { + FuncSig(Signature), + FuncDecl(Signature, Block), + TypeDecl(TypeSingletonName, TypeBody), //should have TypeSingletonName in it + TypeAlias(Rc, Rc), //should have TypeSingletonName in it, or maybe just String, not sure + Binding { + name: Rc, + constant: bool, + expr: Expression, + }, + Impl { + type_name: TypeName, + interface_name: Option, + block: Vec, + }, + Interface { + name: Rc, + signatures: Vec + } +} + +#[derive(Debug, PartialEq, Clone)] +pub struct Signature { + pub name: Rc, + pub params: Vec, + pub type_anno: Option, +} + +#[derive(Debug, PartialEq, Clone)] +pub struct TypeBody(pub Vec); + +#[derive(Debug, PartialEq, Clone)] +pub enum Variant { + UnitStruct(Rc), + TupleStruct(Rc, Vec), + Record(Rc, Vec<(Rc, TypeName)>), +} + +#[derive(Debug, PartialEq, Clone)] +pub struct Expression(pub ExpressionType, pub Option); + +#[derive(Debug, PartialEq, Clone)] +pub enum TypeName { + Tuple(Vec), + Singleton(TypeSingletonName) +} + +#[derive(Debug, PartialEq, Clone)] +pub struct TypeSingletonName { + pub name: Rc, + pub params: Vec, +} + +#[derive(Debug, PartialEq, Clone)] +pub enum ExpressionType { + NatLiteral(u64), + FloatLiteral(f64), + StringLiteral(Rc), + BoolLiteral(bool), + BinExp(BinOp, Box, Box), + PrefixExp(PrefixOp, Box), + TupleLiteral(Vec), + Value(Rc), + NamedStruct { + name: Rc, + fields: Vec<(Rc, Expression)>, + }, + Call { + f: Box, + arguments: Vec, + }, + Index { + indexee: Box, + indexers: Vec, + }, + IfExpression(Box, Block, Option), + MatchExpression(Box, Vec), + WhileExpression { + condition: Option>, + body: Block, + }, + ForExpression { + enumerators: Vec, + body: Box, + }, + Lambda { + params: Vec, + body: Block, + }, + ListLiteral(Vec), +} + +#[derive(Debug, PartialEq, Clone)] +pub struct Enumerator { + pub id: Rc, + pub generator: Expression, +} + +#[derive(Debug, PartialEq, Clone)] +pub enum ForBody { + MonadicReturn(Expression), + StatementBlock(Block), +} + +#[derive(Debug, PartialEq, Clone)] +pub struct MatchArm { + pub pat: Pattern, + pub expr: Expression, +} + +#[derive(Debug, PartialEq, Clone)] +pub struct Pattern(pub Rc); diff --git a/schala-lang/src/lib.rs b/schala-lang/src/lib.rs index 7da7aeb..23f47fd 100644 --- a/schala-lang/src/lib.rs +++ b/schala-lang/src/lib.rs @@ -23,6 +23,7 @@ macro_rules! bx { mod util; mod builtin; mod tokenizing; +mod ast; mod parsing; mod symbol_table; mod typechecking; @@ -74,7 +75,7 @@ fn tokenizing(_handle: &mut Schala, input: &str, comp: Option<&mut UnfinishedCom } } -fn parsing(_handle: &mut Schala, input: Vec, comp: Option<&mut UnfinishedComputation>) -> Result { +fn parsing(_handle: &mut Schala, input: Vec, comp: Option<&mut UnfinishedComputation>) -> Result { let (ast, trace) = parsing::parse(input); comp.map(|comp| { @@ -85,7 +86,7 @@ fn parsing(_handle: &mut Schala, input: Vec, comp: Option<&mu ast.map_err(|err| err.msg) } -fn symbol_table(handle: &mut Schala, input: parsing::AST, comp: Option<&mut UnfinishedComputation>) -> Result { +fn symbol_table(handle: &mut Schala, input: ast::AST, comp: Option<&mut UnfinishedComputation>) -> Result { let add = handle.symbol_table.borrow_mut().add_top_level_symbols(&input); match add { Ok(()) => { @@ -97,7 +98,7 @@ fn symbol_table(handle: &mut Schala, input: parsing::AST, comp: Option<&mut Unfi } } -fn typechecking(handle: &mut Schala, input: parsing::AST, comp: Option<&mut UnfinishedComputation>) -> Result { +fn typechecking(handle: &mut Schala, input: ast::AST, comp: Option<&mut UnfinishedComputation>) -> Result { match handle.type_context.type_check_ast(&input) { Ok(ty) => { comp.map(|c| { @@ -116,7 +117,7 @@ fn typechecking(handle: &mut Schala, input: parsing::AST, comp: Option<&mut Unfi } } -fn ast_reducing(_handle: &mut Schala, input: parsing::AST, comp: Option<&mut UnfinishedComputation>) -> Result { +fn ast_reducing(_handle: &mut Schala, input: ast::AST, comp: Option<&mut UnfinishedComputation>) -> Result { let output = input.reduce(); comp.map(|comp| comp.add_artifact(TraceArtifact::new("ast_reducing", format!("{:?}", output)))); Ok(output) diff --git a/schala-lang/src/parsing.rs b/schala-lang/src/parsing.rs index f775c9a..6957249 100644 --- a/schala-lang/src/parsing.rs +++ b/schala-lang/src/parsing.rs @@ -6,6 +6,8 @@ use tokenizing::*; use tokenizing::Kw::*; use tokenizing::TokenType::*; +use ast::*; + use builtin::{BinOp, PrefixOp}; /* Schala EBNF Grammar */ @@ -173,134 +175,6 @@ macro_rules! expect { } } -#[derive(Debug, PartialEq)] -pub struct AST(pub Vec); - -#[derive(Debug, PartialEq, Clone)] -pub enum Statement { - ExpressionStatement(Expression), - Declaration(Declaration), -} - -type Block = Vec; - -type ParamName = Rc; -type InterfaceName = Rc; //should be a singleton I think?? -type FormalParam = (ParamName, Option); - -#[derive(Debug, PartialEq, Clone)] -pub enum Declaration { - FuncSig(Signature), - FuncDecl(Signature, Block), - TypeDecl(TypeSingletonName, TypeBody), //should have TypeSingletonName in it - TypeAlias(Rc, Rc), //should have TypeSingletonName in it, or maybe just String, not sure - Binding { - name: Rc, - constant: bool, - expr: Expression, - }, - Impl { - type_name: TypeName, - interface_name: Option, - block: Vec, - }, - Interface { - name: Rc, - signatures: Vec - } -} - -#[derive(Debug, PartialEq, Clone)] -pub struct Signature { - pub name: Rc, - pub params: Vec, - pub type_anno: Option, -} - -#[derive(Debug, PartialEq, Clone)] -pub struct TypeBody(pub Vec); - -#[derive(Debug, PartialEq, Clone)] -pub enum Variant { - UnitStruct(Rc), - TupleStruct(Rc, Vec), - Record(Rc, Vec<(Rc, TypeName)>), -} - -#[derive(Debug, PartialEq, Clone)] -pub struct Expression(pub ExpressionType, pub Option); - -#[derive(Debug, PartialEq, Clone)] -pub enum TypeName { - Tuple(Vec), - Singleton(TypeSingletonName) -} - -#[derive(Debug, PartialEq, Clone)] -pub struct TypeSingletonName { - pub name: Rc, - pub params: Vec, -} - -#[derive(Debug, PartialEq, Clone)] -pub enum ExpressionType { - NatLiteral(u64), - FloatLiteral(f64), - StringLiteral(Rc), - BoolLiteral(bool), - BinExp(BinOp, Box, Box), - PrefixExp(PrefixOp, Box), - TupleLiteral(Vec), - Value(Rc), - NamedStruct { - name: Rc, - fields: Vec<(Rc, Expression)>, - }, - Call { - f: Box, - arguments: Vec, - }, - Index { - indexee: Box, - indexers: Vec, - }, - IfExpression(Box, Block, Option), - MatchExpression(Box, Vec), - WhileExpression { - condition: Option>, - body: Block, - }, - ForExpression { - enumerators: Vec, - body: Box, - }, - Lambda { - params: Vec, - body: Block, - }, - ListLiteral(Vec), -} - -#[derive(Debug, PartialEq, Clone)] -pub struct Enumerator { - id: Rc, - generator: Expression, -} - -#[derive(Debug, PartialEq, Clone)] -pub enum ForBody { - MonadicReturn(Expression), - StatementBlock(Block), -} - -#[derive(Debug, PartialEq, Clone)] -pub struct MatchArm { - pat: Pattern, - expr: Expression, -} - -#[derive(Debug, PartialEq, Clone)] -pub struct Pattern(Rc); macro_rules! parse_method { ($name:ident(&mut $self:ident) -> $type:ty $body:block) => { diff --git a/schala-lang/src/reduced_ast.rs b/schala-lang/src/reduced_ast.rs index 51795ce..2b5aca3 100644 --- a/schala-lang/src/reduced_ast.rs +++ b/schala-lang/src/reduced_ast.rs @@ -1,6 +1,6 @@ use std::rc::Rc; -use parsing::{AST, Statement, Expression, Declaration}; +use ast::{AST, Statement, Expression, Declaration}; use builtin::{BinOp, PrefixOp}; #[derive(Debug)] @@ -76,7 +76,7 @@ impl AST { impl Statement { fn reduce(&self) -> Stmt { - use parsing::Statement::*; + use ast::Statement::*; match self { ExpressionStatement(expr) => Stmt::Expr(expr.reduce()), Declaration(decl) => decl.reduce(), @@ -86,7 +86,7 @@ impl Statement { impl Expression { fn reduce(&self) -> Expr { - use parsing::ExpressionType::*; + use ast::ExpressionType::*; let ref input = self.0; match input { NatLiteral(n) => Expr::Lit(Lit::Nat(*n)), @@ -117,7 +117,7 @@ impl Expression { impl Declaration { fn reduce(&self) -> Stmt { use self::Declaration::*; - use ::parsing::Signature; + use ::ast::Signature; match self { Binding {name, constant, expr } => Stmt::Binding { name: name.clone(), constant: *constant, expr: expr.reduce() }, FuncDecl(Signature { name, params, .. }, statements) => Stmt::PreBinding { diff --git a/schala-lang/src/symbol_table.rs b/schala-lang/src/symbol_table.rs index bbbccd6..431f351 100644 --- a/schala-lang/src/symbol_table.rs +++ b/schala-lang/src/symbol_table.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use std::fmt; use std::fmt::Write; -use parsing; +use ast; use typechecking::TypeName; //cf. p. 150 or so of Language Implementation Patterns @@ -51,9 +51,9 @@ impl fmt::Display for SymbolSpec { impl SymbolTable { /* note: this adds names for *forward reference* but doesn't actually create any types. solve that problem * later */ - pub fn add_top_level_symbols(&mut self, ast: &parsing::AST) -> Result<(), String> { - use self::parsing::{Statement, TypeName, Variant, TypeSingletonName, TypeBody}; - use self::parsing::Declaration::*; + pub fn add_top_level_symbols(&mut self, ast: &ast::AST) -> Result<(), String> { + use self::ast::{Statement, TypeName, Variant, TypeSingletonName, TypeBody}; + use self::ast::Declaration::*; for statement in ast.0.iter() { if let Statement::Declaration(decl) = statement { match decl { diff --git a/schala-lang/src/typechecking.rs b/schala-lang/src/typechecking.rs index 24022d4..ac246ff 100644 --- a/schala-lang/src/typechecking.rs +++ b/schala-lang/src/typechecking.rs @@ -9,7 +9,7 @@ use std::iter::Iterator; use itertools::Itertools; */ -use parsing; +use ast; use util::StateStack; use symbol_table::{SymbolSpec, Symbol, SymbolTable}; @@ -98,7 +98,7 @@ impl<'a> TypeContext<'a> { output } - pub fn type_check_ast(&mut self, input: &parsing::AST) -> Result { + pub fn type_check_ast(&mut self, input: &ast::AST) -> Result { let ref symbol_table = self.symbol_table_handle.borrow(); self.global_env.populate_from_symbols(symbol_table); let output = self.global_env.infer_block(&input.0)?; @@ -118,21 +118,21 @@ impl TypeEnv { ty } } - fn infer_block(&mut self, block: &Vec) -> TypeResult { + fn infer_block(&mut self, block: &Vec) -> TypeResult { let mut output = Type::Const(TConst::Unit); for statement in block { output = self.infer_statement(statement)?; } Ok(output) } - fn infer_statement(&mut self, statement: &parsing::Statement) -> TypeResult { + fn infer_statement(&mut self, statement: &ast::Statement) -> TypeResult { match statement { - parsing::Statement::ExpressionStatement(expr) => self.infer_expr(expr), - parsing::Statement::Declaration(decl) => self.infer_decl(decl) + ast::Statement::ExpressionStatement(expr) => self.infer_expr(expr), + ast::Statement::Declaration(decl) => self.infer_decl(decl) } } - fn infer_decl(&mut self, decl: &parsing::Declaration) -> TypeResult { - use parsing::Declaration::*; + fn infer_decl(&mut self, decl: &ast::Declaration) -> TypeResult { + use ast::Declaration::*; match decl { Binding { name, expr, .. } => { let ty = self.infer_expr(expr)?; @@ -143,20 +143,20 @@ impl TypeEnv { } Ok(Type::Const(TConst::Unit)) } - fn infer_expr(&mut self, expr: &parsing::Expression) -> TypeResult { + fn infer_expr(&mut self, expr: &ast::Expression) -> TypeResult { match expr { - parsing::Expression(expr, Some(anno)) => { + ast::Expression(expr, Some(anno)) => { self.infer_exprtype(expr) }, - parsing::Expression(expr, None) => { + ast::Expression(expr, None) => { self.infer_exprtype(expr) } } } - fn infer_exprtype(&mut self, expr: &parsing::ExpressionType) -> TypeResult { + fn infer_exprtype(&mut self, expr: &ast::ExpressionType) -> TypeResult { use self::TConst::*; - use parsing::ExpressionType::*; + use ast::ExpressionType::*; Ok(match expr { NatLiteral(_) => Type::Const(Nat), StringLiteral(_) => Type::Const(StringT), @@ -465,6 +465,7 @@ impl TypeContext { #[cfg(test)] mod tests { + /* use super::{Type, TConst, TypeContext}; use super::Type::*; use super::TConst::*; @@ -473,7 +474,7 @@ mod tests { ($input:expr, $correct:expr) => { { let mut tc = TypeContext::new(); - let ast = ::parsing::parse(::tokenizing::tokenize($input)).0.unwrap() ; + let ast = ::ast::parse(::tokenizing::tokenize($input)).0.unwrap() ; //tc.add_symbols(&ast); assert_eq!($correct, tc.infer_block(&ast.0).unwrap()) } @@ -485,4 +486,5 @@ mod tests { type_test!("30", Const(Nat)); //type_test!("fn x(a: Int): Bool {}; x(1)", TConst(Boolean)); } + */ }