Pattern-matching in reduced AST

This commit is contained in:
greg 2018-07-24 03:12:00 -07:00
parent 75bf4b5697
commit a2b1b0f953
2 changed files with 33 additions and 27 deletions

View File

@ -3,7 +3,7 @@
Schala is a Rust framework written to make it easy to Schala is a Rust framework written to make it easy to
create and experiment with toy programming languages. It provides create and experiment with toy programming languages. It provides
a common REPL, and a trait `ProgrammingLanguage` with provisions a common REPL, and a trait `ProgrammingLanguage` with provisions
for tokenizing text, parsing tokens, evaluating an abstract syntax tree, for tokenizing text, parsing tokens, evaluating an abstract syntax tree,
and other tasks that are common to all programming languages. and other tasks that are common to all programming languages.

View File

@ -1,6 +1,6 @@
use std::rc::Rc; use std::rc::Rc;
use ast::{AST, Statement, Expression, Declaration, Discriminator, IfExpressionBody}; use ast::{AST, Statement, Expression, Declaration, Discriminator, IfExpressionBody, Pattern};
use symbol_table::{Symbol, SymbolSpec, SymbolTable}; use symbol_table::{Symbol, SymbolSpec, SymbolTable};
use builtin::{BinOp, PrefixOp}; use builtin::{BinOp, PrefixOp};
@ -45,6 +45,10 @@ pub enum Expr {
then_clause: Vec<Stmt>, then_clause: Vec<Stmt>,
else_clause: Vec<Stmt>, else_clause: Vec<Stmt>,
}, },
Match {
cond: Box<Expr>,
arms: Vec<(Pattern, Vec<Stmt>)>
},
UnimplementedSigilValue UnimplementedSigilValue
} }
@ -112,36 +116,38 @@ impl Expression {
args: arguments.iter().map(|arg| arg.reduce(symbol_table)).collect(), args: arguments.iter().map(|arg| arg.reduce(symbol_table)).collect(),
}, },
TupleLiteral(exprs) => Expr::Tuple(exprs.iter().map(|e| e.reduce(symbol_table)).collect()), TupleLiteral(exprs) => Expr::Tuple(exprs.iter().map(|e| e.reduce(symbol_table)).collect()),
IfExpression { discriminator, body } => { IfExpression { discriminator, body } => reduce_if_expression(discriminator, body, symbol_table),
let cond = Box::new(match **discriminator {
Discriminator::Simple(ref expr) => expr.reduce(symbol_table),
_ => panic!(),
});
match **body {
IfExpressionBody::SimpleConditional(ref then_clause, ref else_clause) => {
let then_clause = then_clause.iter().map(|expr| expr.reduce(symbol_table)).collect();
let else_clause = match else_clause {
None => vec![],
Some(stmts) => stmts.iter().map(|expr| expr.reduce(symbol_table)).collect(),
};
Expr::Conditional { cond, then_clause, 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 else_clause = match else_clause {
None => vec![],
Some(stmts) => stmts.iter().map(|expr| expr.reduce(symbol_table)).collect(),
};
Expr::Conditional { cond, then_clause, else_clause }
},
_ => panic!(),
}
},
_ => Expr::UnimplementedSigilValue, _ => Expr::UnimplementedSigilValue,
} }
} }
} }
fn reduce_if_expression(discriminator: &Discriminator, body: &IfExpressionBody, symbol_table: &SymbolTable) -> Expr {
let cond = Box::new(match *discriminator {
Discriminator::Simple(ref expr) => expr.reduce(symbol_table),
_ => panic!(),
});
match *body {
IfExpressionBody::SimpleConditional(ref then_clause, ref else_clause) => {
let then_clause = then_clause.iter().map(|expr| expr.reduce(symbol_table)).collect();
let else_clause = match else_clause {
None => vec![],
Some(stmts) => stmts.iter().map(|expr| expr.reduce(symbol_table)).collect(),
};
Expr::Conditional { cond, then_clause, 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 else_clause = match else_clause {
None => vec![],
Some(stmts) => stmts.iter().map(|expr| expr.reduce(symbol_table)).collect(),
};
Expr::Conditional { cond, then_clause, else_clause }
},
_ => panic!(),
}
}
impl Declaration { impl Declaration {
fn reduce(&self, symbol_table: &SymbolTable) -> Stmt { fn reduce(&self, symbol_table: &SymbolTable) -> Stmt {
use self::Declaration::*; use self::Declaration::*;