diff options
author | David Li <li.davidm96@gmail.com> | 2017-11-05 21:12:44 -0500 |
---|---|---|
committer | David Li <li.davidm96@gmail.com> | 2017-11-05 21:12:44 -0500 |
commit | e5c6400f75029124474ee989388bf2c0abdc7e0a (patch) | |
tree | c713adc4c05559bb082375218a9eca9badffc531 | |
parent | 44570e6b300961cdcf080b82e7cc1d89fc553b0a (diff) |
Parse type and variable declarations
-rw-r--r-- | src/ast.rs | 73 | ||||
-rw-r--r-- | src/semantic/translate.rs | 25 | ||||
-rw-r--r-- | src/taiga.lalrpop | 34 |
3 files changed, 105 insertions, 27 deletions
@@ -1,3 +1,5 @@ +use std::ops::Deref; + #[derive(Debug)] pub struct WithLocation<T> { pub value: T, @@ -35,6 +37,14 @@ impl<T> WithLocation<T> { } } +impl<T> Deref for WithLocation<T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.value + } +} + #[derive(Debug)] pub struct Program(pub Box<WithLocation<Expression>>); @@ -64,7 +74,7 @@ pub enum BinOp { #[derive(Debug)] pub enum Expression { - Let(Vec<WithLocation<VarDec>>, Box<WithLocation<Expression>>), + Let(Vec<WithLocation<Declaration>>, Box<WithLocation<Expression>>), UnaryOp(UnaryOp, Box<WithLocation<Expression>>), BinOp(BinOp, Box<WithLocation<Expression>>, Box<WithLocation<Expression>>), Number(u64), @@ -74,19 +84,62 @@ pub enum Expression { } #[derive(Debug)] -pub struct VarDec { +pub struct RecordField { + name: WithLocation<String>, + ty: WithLocation<String>, +} + +impl RecordField { + pub fn new(name: WithLocation<String>, ty: WithLocation<String>) -> RecordField { + RecordField { name, ty } + } +} + +#[derive(Debug)] +pub enum Ty { + Name(String), + Array(Box<Ty>), + Record(Vec<WithLocation<RecordField>>), +} + +#[derive(Debug)] +pub struct Declaration { pub name: WithLocation<String>, - pub type_: Option<String>, - pub value: Box<WithLocation<Expression>>, + pub declaration: DeclarationBody, +} + +#[derive(Debug)] +pub enum DeclarationBody { + Var { + ty: Option<WithLocation<Ty>>, + value: Box<WithLocation<Expression>>, + }, + Ty { + ty: WithLocation<Ty>, + }, + Fun { + ty: Box<WithLocation<Ty>>, + }, } -impl VarDec { - pub fn new(name: WithLocation<String>, type_: Option<String>, - value: Box<WithLocation<Expression>>) -> VarDec { - VarDec { +impl Declaration { + pub fn new_var(name: WithLocation<String>, type_: Option<WithLocation<Ty>>, + value: Box<WithLocation<Expression>>) -> Declaration { + Declaration { name: name, - type_: type_, - value: value, + declaration: DeclarationBody::Var { + ty: type_, + value: value, + } + } + } + + pub fn new_ty(name: WithLocation<String>, type_: WithLocation<Ty>) -> Declaration { + Declaration { + name: name, + declaration: DeclarationBody::Ty { + ty: type_, + } } } } diff --git a/src/semantic/translate.rs b/src/semantic/translate.rs index 9da6411..cf1dcf8 100644 --- a/src/semantic/translate.rs +++ b/src/semantic/translate.rs @@ -31,18 +31,19 @@ fn trans_exp<'a>(venv: &mut TypeEnvironment<'a>, exp: &WithLocation<ast::Express match &exp.value { &Let(ref decls, ref body) => { - let mut new_env = TypeEnvironment::new(None); - for decl in decls.iter() { - let decl_ty = trans_exp(venv, &*decl.value.value)?; - if let Some(_) = decl.value.type_ { - return err!(decl, TypeError::Unimplemented); - } - else { - new_env.add_binding(decl.value.name.value.clone(), decl_ty); - } - } - new_env.set_parent(venv); - trans_exp(&mut new_env, &*body) + err!(exp, TypeError::Unimplemented) + // let mut new_env = TypeEnvironment::new(None); + // for decl in decls.iter() { + // let decl_ty = trans_exp(venv, &*decl.value.value)?; + // if let Some(_) = decl.value.type_ { + // return err!(decl, TypeError::Unimplemented); + // } + // else { + // new_env.add_binding(decl.name.clone(), decl_ty); + // } + // } + // new_env.set_parent(venv); + // trans_exp(&mut new_env, &*body) }, &UnaryOp(ref op, ref operand) => { use ast::UnaryOp::*; diff --git a/src/taiga.lalrpop b/src/taiga.lalrpop index 851cb24..aa5e50e 100644 --- a/src/taiga.lalrpop +++ b/src/taiga.lalrpop @@ -7,17 +7,39 @@ pub Program: ast::Program = { Expression => ast::Program(<>), }; -VarDec: Box<WithLocation<ast::VarDec>> = +RecordFields: Vec<WithLocation<ast::RecordField>> = { + <l: @L> <n:Name> ":" <v:Name> <r: @R> "," <rest: RecordFields> => { + let mut rest = rest; + rest.push(WithLocation::new(ast::RecordField::new(n, v), l, r)); + rest + }, + <l: @L> <n:Name> ":" <v:Name> <r: @R> "," => vec![WithLocation::new(ast::RecordField::new(n, v), l, r)], + <l: @L> <n:Name> ":" <v:Name> <r: @R> => vec![WithLocation::new(ast::RecordField::new(n, v), l, r)], + "" => vec![], +}; + +Ty: WithLocation<ast::Ty> = { + <Name> => <>.map(|v| ast::Ty::Name(v)), + "array" "of" <Name> => <>.map(|v| ast::Ty::Array(Box::new(ast::Ty::Name(v)))), + <l: @L> "{" <v: RecordFields> "}" <r: @R> => WithLocation::new(ast::Ty::Record(v), l, r), +}; + +Declaration: Box<WithLocation<ast::Declaration>> = { + <l: @L> "var" <name: Name> ":" <ty: Ty> "=" <exp: Expression> <r: @R> => + Box::new(WithLocation::new(ast::Declaration::new_var(name, Some(ty), exp), l, r)), <l: @L> "var" <name: Name> "=" <exp: Expression> <r: @R> => - Box::new(WithLocation::new(ast::VarDec::new(name, None, exp), l, r)); + Box::new(WithLocation::new(ast::Declaration::new_var(name, None, exp), l, r)), + <l: @L> "type" <name: Name> "=" <ty: Ty> <r: @R> => + Box::new(WithLocation::new(ast::Declaration::new_ty(name, ty), l, r)), +}; -DeclarationsList: Vec<WithLocation<ast::VarDec>> = { - <h: DeclarationsList> <t: VarDec> => { +DeclarationsList: Vec<WithLocation<ast::Declaration>> = { + <h: DeclarationsList> <t: Declaration> => { let mut h = h; h.push(*t); h }, - <VarDec> => vec![*<>], + <Declaration> => vec![*<>], }; Expression: Box<ast::WithLocation<ast::Expression>> = { @@ -121,6 +143,8 @@ match { "let", "in", "end", + "type", + "function", } else { r"[[:alpha:]_][[:alpha:]_0-9]*", |