Move AST into its own module

This commit is contained in:
greg 2018-06-04 19:25:40 -07:00
parent d0a0cc8209
commit f98d8e2bb0
6 changed files with 163 additions and 154 deletions

132
schala-lang/src/ast.rs Normal file
View File

@ -0,0 +1,132 @@
use std::rc::Rc;
use builtin::{BinOp, PrefixOp};
#[derive(Debug, PartialEq)]
pub struct AST(pub Vec<Statement>);
#[derive(Debug, PartialEq, Clone)]
pub enum Statement {
ExpressionStatement(Expression),
Declaration(Declaration),
}
pub type Block = Vec<Statement>;
pub type ParamName = Rc<String>;
pub type InterfaceName = Rc<String>; //should be a singleton I think??
pub type FormalParam = (ParamName, Option<TypeName>);
#[derive(Debug, PartialEq, Clone)]
pub enum Declaration {
FuncSig(Signature),
FuncDecl(Signature, Block),
TypeDecl(TypeSingletonName, TypeBody), //should have TypeSingletonName in it
TypeAlias(Rc<String>, Rc<String>), //should have TypeSingletonName in it, or maybe just String, not sure
Binding {
name: Rc<String>,
constant: bool,
expr: Expression,
},
Impl {
type_name: TypeName,
interface_name: Option<InterfaceName>,
block: Vec<Declaration>,
},
Interface {
name: Rc<String>,
signatures: Vec<Signature>
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct Signature {
pub name: Rc<String>,
pub params: Vec<FormalParam>,
pub type_anno: Option<TypeName>,
}
#[derive(Debug, PartialEq, Clone)]
pub struct TypeBody(pub Vec<Variant>);
#[derive(Debug, PartialEq, Clone)]
pub enum Variant {
UnitStruct(Rc<String>),
TupleStruct(Rc<String>, Vec<TypeName>),
Record(Rc<String>, Vec<(Rc<String>, TypeName)>),
}
#[derive(Debug, PartialEq, Clone)]
pub struct Expression(pub ExpressionType, pub Option<TypeName>);
#[derive(Debug, PartialEq, Clone)]
pub enum TypeName {
Tuple(Vec<TypeName>),
Singleton(TypeSingletonName)
}
#[derive(Debug, PartialEq, Clone)]
pub struct TypeSingletonName {
pub name: Rc<String>,
pub params: Vec<TypeName>,
}
#[derive(Debug, PartialEq, Clone)]
pub enum ExpressionType {
NatLiteral(u64),
FloatLiteral(f64),
StringLiteral(Rc<String>),
BoolLiteral(bool),
BinExp(BinOp, Box<Expression>, Box<Expression>),
PrefixExp(PrefixOp, Box<Expression>),
TupleLiteral(Vec<Expression>),
Value(Rc<String>),
NamedStruct {
name: Rc<String>,
fields: Vec<(Rc<String>, Expression)>,
},
Call {
f: Box<Expression>,
arguments: Vec<Expression>,
},
Index {
indexee: Box<Expression>,
indexers: Vec<Expression>,
},
IfExpression(Box<Expression>, Block, Option<Block>),
MatchExpression(Box<Expression>, Vec<MatchArm>),
WhileExpression {
condition: Option<Box<Expression>>,
body: Block,
},
ForExpression {
enumerators: Vec<Enumerator>,
body: Box<ForBody>,
},
Lambda {
params: Vec<FormalParam>,
body: Block,
},
ListLiteral(Vec<Expression>),
}
#[derive(Debug, PartialEq, Clone)]
pub struct Enumerator {
pub id: Rc<String>,
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<String>);

View File

@ -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<tokenizing::Token>, comp: Option<&mut UnfinishedComputation>) -> Result<parsing::AST, String> {
fn parsing(_handle: &mut Schala, input: Vec<tokenizing::Token>, comp: Option<&mut UnfinishedComputation>) -> Result<ast::AST, String> {
let (ast, trace) = parsing::parse(input);
comp.map(|comp| {
@ -85,7 +86,7 @@ fn parsing(_handle: &mut Schala, input: Vec<tokenizing::Token>, comp: Option<&mu
ast.map_err(|err| err.msg)
}
fn symbol_table(handle: &mut Schala, input: parsing::AST, comp: Option<&mut UnfinishedComputation>) -> Result<parsing::AST, String> {
fn symbol_table(handle: &mut Schala, input: ast::AST, comp: Option<&mut UnfinishedComputation>) -> Result<ast::AST, String> {
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<parsing::AST, String> {
fn typechecking(handle: &mut Schala, input: ast::AST, comp: Option<&mut UnfinishedComputation>) -> Result<ast::AST, String> {
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<reduced_ast::ReducedAST, String> {
fn ast_reducing(_handle: &mut Schala, input: ast::AST, comp: Option<&mut UnfinishedComputation>) -> Result<reduced_ast::ReducedAST, String> {
let output = input.reduce();
comp.map(|comp| comp.add_artifact(TraceArtifact::new("ast_reducing", format!("{:?}", output))));
Ok(output)

View File

@ -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<Statement>);
#[derive(Debug, PartialEq, Clone)]
pub enum Statement {
ExpressionStatement(Expression),
Declaration(Declaration),
}
type Block = Vec<Statement>;
type ParamName = Rc<String>;
type InterfaceName = Rc<String>; //should be a singleton I think??
type FormalParam = (ParamName, Option<TypeName>);
#[derive(Debug, PartialEq, Clone)]
pub enum Declaration {
FuncSig(Signature),
FuncDecl(Signature, Block),
TypeDecl(TypeSingletonName, TypeBody), //should have TypeSingletonName in it
TypeAlias(Rc<String>, Rc<String>), //should have TypeSingletonName in it, or maybe just String, not sure
Binding {
name: Rc<String>,
constant: bool,
expr: Expression,
},
Impl {
type_name: TypeName,
interface_name: Option<InterfaceName>,
block: Vec<Declaration>,
},
Interface {
name: Rc<String>,
signatures: Vec<Signature>
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct Signature {
pub name: Rc<String>,
pub params: Vec<FormalParam>,
pub type_anno: Option<TypeName>,
}
#[derive(Debug, PartialEq, Clone)]
pub struct TypeBody(pub Vec<Variant>);
#[derive(Debug, PartialEq, Clone)]
pub enum Variant {
UnitStruct(Rc<String>),
TupleStruct(Rc<String>, Vec<TypeName>),
Record(Rc<String>, Vec<(Rc<String>, TypeName)>),
}
#[derive(Debug, PartialEq, Clone)]
pub struct Expression(pub ExpressionType, pub Option<TypeName>);
#[derive(Debug, PartialEq, Clone)]
pub enum TypeName {
Tuple(Vec<TypeName>),
Singleton(TypeSingletonName)
}
#[derive(Debug, PartialEq, Clone)]
pub struct TypeSingletonName {
pub name: Rc<String>,
pub params: Vec<TypeName>,
}
#[derive(Debug, PartialEq, Clone)]
pub enum ExpressionType {
NatLiteral(u64),
FloatLiteral(f64),
StringLiteral(Rc<String>),
BoolLiteral(bool),
BinExp(BinOp, Box<Expression>, Box<Expression>),
PrefixExp(PrefixOp, Box<Expression>),
TupleLiteral(Vec<Expression>),
Value(Rc<String>),
NamedStruct {
name: Rc<String>,
fields: Vec<(Rc<String>, Expression)>,
},
Call {
f: Box<Expression>,
arguments: Vec<Expression>,
},
Index {
indexee: Box<Expression>,
indexers: Vec<Expression>,
},
IfExpression(Box<Expression>, Block, Option<Block>),
MatchExpression(Box<Expression>, Vec<MatchArm>),
WhileExpression {
condition: Option<Box<Expression>>,
body: Block,
},
ForExpression {
enumerators: Vec<Enumerator>,
body: Box<ForBody>,
},
Lambda {
params: Vec<FormalParam>,
body: Block,
},
ListLiteral(Vec<Expression>),
}
#[derive(Debug, PartialEq, Clone)]
pub struct Enumerator {
id: Rc<String>,
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<String>);
macro_rules! parse_method {
($name:ident(&mut $self:ident) -> $type:ty $body:block) => {

View File

@ -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 {

View File

@ -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 {

View File

@ -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<String, String> {
pub fn type_check_ast(&mut self, input: &ast::AST) -> Result<String, String> {
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<parsing::Statement>) -> TypeResult<Type> {
fn infer_block(&mut self, block: &Vec<ast::Statement>) -> TypeResult<Type> {
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<Type> {
fn infer_statement(&mut self, statement: &ast::Statement) -> TypeResult<Type> {
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<Type> {
use parsing::Declaration::*;
fn infer_decl(&mut self, decl: &ast::Declaration) -> TypeResult<Type> {
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<Type> {
fn infer_expr(&mut self, expr: &ast::Expression) -> TypeResult<Type> {
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<Type> {
fn infer_exprtype(&mut self, expr: &ast::ExpressionType) -> TypeResult<Type> {
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));
}
*/
}