Finish conversion of AST Reducer

This commit is contained in:
greg 2019-09-11 01:27:52 -07:00
parent 25f51a314d
commit a85d3c46bd
1 changed files with 168 additions and 178 deletions

View File

@ -120,58 +120,46 @@ impl<'a> Reducer<'a> {
fn ast(&mut self, input: &AST) -> ReducedAST {
let mut output = vec![];
for statement in input.0.iter() {
output.push(statement.reduce(self.symbol_table));
output.push(self.statement(statement));
}
ReducedAST(output)
}
/*
fn meta_statement(&mut self, stmt: &Meta<Statement>) -> Stmt {
}
*/
}
impl Meta<Statement> {
fn reduce(&self, symbol_table: &SymbolTable) -> Stmt {
fn statement(&mut self, stmt: &Meta<Statement>) -> Stmt {
use crate::ast::Statement::*;
match self.node() {
ExpressionStatement(expr) => Stmt::Expr(expr.reduce(symbol_table)),
Declaration(decl) => decl.reduce(symbol_table),
match stmt.node() {
ExpressionStatement(expr) => Stmt::Expr(self.expression(expr)),
Declaration(decl) => self.declaration(decl),
}
}
}
fn reduce_block(block: &Block, symbol_table: &SymbolTable) -> Vec<Stmt> {
block.iter().map(|stmt| stmt.reduce(symbol_table)).collect()
}
fn block(&mut self, block: &Block) -> Vec<Stmt> {
block.iter().map(|stmt| self.statement(stmt)).collect()
}
impl InvocationArgument {
fn reduce(&self, symbol_table: &SymbolTable) -> Expr {
fn invocation_argument(&mut self, invoc: &InvocationArgument) -> Expr {
use crate::ast::InvocationArgument::*;
match self {
Positional(ex) => ex.reduce(symbol_table),
match invoc {
Positional(ex) => self.expression(ex),
Keyword { .. } => Expr::UnimplementedSigilValue,
Ignored => Expr::UnimplementedSigilValue,
}
}
}
impl Meta<Expression> {
fn reduce(&self, symbol_table: &SymbolTable) -> Expr {
fn expression(&mut self, expr: &Meta<Expression>) -> Expr {
use crate::ast::ExpressionKind::*;
let ref node = self.node();
let symbol_table = self.symbol_table;
let ref node = expr.node();
let ref input = node.kind;
match input {
NatLiteral(n) => Expr::Lit(Lit::Nat(*n)),
FloatLiteral(f) => Expr::Lit(Lit::Float(*f)),
StringLiteral(s) => Expr::Lit(Lit::StringLit(s.clone())),
BoolLiteral(b) => Expr::Lit(Lit::Bool(*b)),
BinExp(binop, lhs, rhs) => binop.reduce(symbol_table, lhs, rhs),
PrefixExp(op, arg) => op.reduce(symbol_table, arg),
BinExp(binop, lhs, rhs) => self.binop(binop, lhs, rhs),
PrefixExp(op, arg) => self.prefix(op, arg),
Value(qualified_name) => {
let ref sym_name = match self.fqsn {
let ref sym_name = match expr.fqsn {
Some(ref fqsn) => fqsn,
None => return Expr::ReductionError(format!("FQSN lookup for Value {:?} failed", qualified_name)),
};
@ -188,118 +176,175 @@ impl Meta<Expression> {
_ => Expr::Sym(name.clone()),
}
},
Call { f, arguments } => reduce_call_expression(f, arguments, symbol_table),
TupleLiteral(exprs) => Expr::Tuple(exprs.iter().map(|e| e.reduce(symbol_table)).collect()),
IfExpression { discriminator, body } => reduce_if_expression(discriminator, body, symbol_table),
Lambda { params, body, .. } => reduce_lambda(params, body, symbol_table),
NamedStruct { name, fields } => reduce_named_struct(self.fqsn.as_ref(), name.node(), fields, symbol_table),
Call { f, arguments } => self.reduce_call_expression(f, arguments),
TupleLiteral(exprs) => Expr::Tuple(exprs.iter().map(|e| self.expression(e)).collect()),
IfExpression { discriminator, body } => self.reduce_if_expression(discriminator, body),
Lambda { params, body, .. } => self.reduce_lambda(params, body),
NamedStruct { name, fields } => self.reduce_named_struct(expr.fqsn.as_ref(), name.node(), fields),
Index { .. } => Expr::UnimplementedSigilValue,
WhileExpression { .. } => Expr::UnimplementedSigilValue,
ForExpression { .. } => Expr::UnimplementedSigilValue,
ListLiteral { .. } => Expr::UnimplementedSigilValue,
}
}
}
fn reduce_lambda(params: &Vec<FormalParam>, body: &Block, symbol_table: &SymbolTable) -> Expr {
Expr::Func(Func::UserDefined {
name: None,
params: params.iter().map(|param| param.name.clone()).collect(),
body: reduce_block(body, symbol_table),
})
}
fn reduce_named_struct(fqsn: Option<&FullyQualifiedSymbolName>, _name: &QualifiedName, fields: &Vec<(Rc<String>, Meta<Expression>)>, symbol_table: &SymbolTable) -> Expr {
let sym_name = match fqsn {
Some(fqsn) => fqsn,
None => return Expr::ReductionError(format!("FQSN lookup for value B failed")),
};
let FullyQualifiedSymbolName(ref v) = sym_name;
let ref name = v.last().unwrap().name;
let (type_name, index, members_from_table) = match symbol_table.lookup_by_fqsn(&sym_name) {
Some(Symbol { spec: SymbolSpec::RecordConstructor { members, type_name, index }, .. }) => (type_name.clone(), index, members),
_ => return Expr::ReductionError("Not a record constructor".to_string()),
};
let arity = members_from_table.len();
let mut args: Vec<(Rc<String>, Expr)> = fields.iter()
.map(|(name, expr)| (name.clone(), expr.reduce(symbol_table)))
.collect();
args.as_mut_slice()
.sort_unstable_by(|(name1, _), (name2, _)| name1.cmp(name2)); //arbitrary - sorting by alphabetical order
let args = args.into_iter().map(|(_, expr)| expr).collect();
//TODO make sure this sorting actually works
let f = box Expr::Constructor { type_name, name: name.clone(), tag: *index, arity, };
Expr::Call { f, args }
}
fn reduce_call_expression(func: &Meta<Expression>, arguments: &Vec<InvocationArgument>, symbol_table: &SymbolTable) -> Expr {
Expr::Call {
f: Box::new(func.reduce(symbol_table)),
args: arguments.iter().map(|arg| arg.reduce(symbol_table)).collect(),
fn reduce_lambda(&mut self, params: &Vec<FormalParam>, body: &Block) -> Expr {
Expr::Func(Func::UserDefined {
name: None,
params: params.iter().map(|param| param.name.clone()).collect(),
body: self.block(body),
})
}
}
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),
Discriminator::BinOp(ref _expr, ref _binop) => panic!("Can't yet handle binop discriminators")
});
match *body {
IfExpressionBody::SimpleConditional(ref then_clause, ref else_clause) => {
let then_clause = reduce_block(then_clause, symbol_table);
let else_clause = match else_clause {
None => vec![],
Some(stmts) => reduce_block(stmts, symbol_table),
};
Expr::Conditional { cond, then_clause, else_clause }
},
IfExpressionBody::SimplePatternMatch(ref pat, ref then_clause, ref else_clause) => {
let then_clause = reduce_block(then_clause, symbol_table);
let else_clause = match else_clause {
None => vec![],
Some(stmts) => reduce_block(stmts, symbol_table),
};
fn reduce_named_struct(&mut self, fqsn: Option<&FullyQualifiedSymbolName>, _name: &QualifiedName, fields: &Vec<(Rc<String>, Meta<Expression>)>) -> Expr {
let symbol_table = self.symbol_table;
let sym_name = match fqsn {
Some(fqsn) => fqsn,
None => return Expr::ReductionError(format!("FQSN lookup for value B failed")),
};
let FullyQualifiedSymbolName(ref v) = sym_name;
let ref name = v.last().unwrap().name;
let (type_name, index, members_from_table) = match symbol_table.lookup_by_fqsn(&sym_name) {
Some(Symbol { spec: SymbolSpec::RecordConstructor { members, type_name, index }, .. }) => (type_name.clone(), index, members),
_ => return Expr::ReductionError("Not a record constructor".to_string()),
};
let arity = members_from_table.len();
let alternatives = vec![
pat.to_alternative(then_clause, symbol_table),
Alternative {
matchable: Subpattern {
tag: None,
subpatterns: vec![],
bound_vars: vec![],
guard: None,
let mut args: Vec<(Rc<String>, Expr)> = fields.iter()
.map(|(name, expr)| (name.clone(), self.expression(expr)))
.collect();
args.as_mut_slice()
.sort_unstable_by(|(name1, _), (name2, _)| name1.cmp(name2)); //arbitrary - sorting by alphabetical order
let args = args.into_iter().map(|(_, expr)| expr).collect();
//TODO make sure this sorting actually works
let f = box Expr::Constructor { type_name, name: name.clone(), tag: *index, arity, };
Expr::Call { f, args }
}
fn reduce_call_expression(&mut self, func: &Meta<Expression>, arguments: &Vec<InvocationArgument>) -> Expr {
Expr::Call {
f: Box::new(self.expression(func)),
args: arguments.iter().map(|arg| self.invocation_argument(arg)).collect(),
}
}
fn reduce_if_expression(&mut self, discriminator: &Discriminator, body: &IfExpressionBody) -> Expr {
let symbol_table = self.symbol_table;
let cond = Box::new(match *discriminator {
Discriminator::Simple(ref expr) => self.expression(expr),
Discriminator::BinOp(ref _expr, ref _binop) => panic!("Can't yet handle binop discriminators")
});
match *body {
IfExpressionBody::SimpleConditional(ref then_clause, ref else_clause) => {
let then_clause = self.block(then_clause);
let else_clause = match else_clause {
None => vec![],
Some(stmts) => self.block(stmts),
};
Expr::Conditional { cond, then_clause, else_clause }
},
IfExpressionBody::SimplePatternMatch(ref pat, ref then_clause, ref else_clause) => {
let then_clause = self.block(then_clause);
let else_clause = match else_clause {
None => vec![],
Some(stmts) => self.block(stmts),
};
let alternatives = vec![
pat.to_alternative(then_clause, symbol_table),
Alternative {
matchable: Subpattern {
tag: None,
subpatterns: vec![],
bound_vars: vec![],
guard: None,
},
item: else_clause
},
item: else_clause
},
];
];
Expr::CaseMatch {
cond,
alternatives,
}
},
IfExpressionBody::GuardList(ref guard_arms) => {
let mut alternatives = vec![];
for arm in guard_arms {
match arm.guard {
Guard::Pat(ref p) => {
let item = reduce_block(&arm.body, symbol_table);
let alt = p.to_alternative(item, symbol_table);
alternatives.push(alt);
},
Guard::HalfExpr(HalfExpr { op: _, expr: _ }) => {
return Expr::UnimplementedSigilValue
Expr::CaseMatch {
cond,
alternatives,
}
},
IfExpressionBody::GuardList(ref guard_arms) => {
let mut alternatives = vec![];
for arm in guard_arms {
match arm.guard {
Guard::Pat(ref p) => {
let item = self.block(&arm.body);
let alt = p.to_alternative(item, symbol_table);
alternatives.push(alt);
},
Guard::HalfExpr(HalfExpr { op: _, expr: _ }) => {
return Expr::UnimplementedSigilValue
}
}
}
Expr::CaseMatch { cond, alternatives }
}
Expr::CaseMatch { cond, alternatives }
}
}
fn binop(&mut self, binop: &BinOp, lhs: &Box<Meta<Expression>>, rhs: &Box<Meta<Expression>>) -> Expr {
let operation = Builtin::from_str(binop.sigil()).ok();
match operation {
Some(Builtin::Assignment) => Expr::Assign {
val: Box::new(self.expression(&*lhs)),
expr: Box::new(self.expression(&*rhs)),
},
Some(op) => {
let f = Box::new(Expr::Func(Func::BuiltIn(op)));
Expr::Call { f, args: vec![self.expression(&*lhs), self.expression(&*rhs)] }
},
None => {
//TODO handle a user-defined operation
Expr::UnimplementedSigilValue
}
}
}
fn prefix(&mut self, prefix: &PrefixOp, arg: &Box<Meta<Expression>>) -> Expr {
match prefix.builtin {
Some(op) => {
let f = Box::new(Expr::Func(Func::BuiltIn(op)));
Expr::Call { f, args: vec![self.expression(arg)] }
},
None => { //TODO need this for custom prefix ops
Expr::UnimplementedSigilValue
}
}
}
fn declaration(&mut self, declaration: &Declaration) -> Stmt {
use self::Declaration::*;
match declaration {
Binding {name, constant, expr, .. } => Stmt::Binding { name: name.clone(), constant: *constant, expr: self.expression(expr) },
FuncDecl(Signature { name, params, .. }, statements) => Stmt::PreBinding {
name: name.clone(),
func: Func::UserDefined {
name: Some(name.clone()),
params: params.iter().map(|param| param.name.clone()).collect(),
body: self.block(&statements),
}
},
TypeDecl { .. } => Stmt::Noop,
TypeAlias(_, _) => Stmt::Noop,
Interface { .. } => Stmt::Noop,
Impl { .. } => Stmt::Expr(Expr::UnimplementedSigilValue),
_ => Stmt::Expr(Expr::UnimplementedSigilValue)
}
}
}
/* ig var pat
* x is SomeBigOldEnum(_, x, Some(t))
*/
@ -465,60 +510,5 @@ impl PatternLiteral {
},
}
}
}
impl Declaration {
fn reduce(&self, symbol_table: &SymbolTable) -> Stmt {
use self::Declaration::*;
match self {
Binding {name, constant, expr, .. } => Stmt::Binding { name: name.clone(), constant: *constant, expr: expr.reduce(symbol_table) },
FuncDecl(Signature { name, params, .. }, statements) => Stmt::PreBinding {
name: name.clone(),
func: Func::UserDefined {
name: Some(name.clone()),
params: params.iter().map(|param| param.name.clone()).collect(),
body: reduce_block(&statements, symbol_table),
}
},
TypeDecl { .. } => Stmt::Noop,
TypeAlias(_, _) => Stmt::Noop,
Interface { .. } => Stmt::Noop,
Impl { .. } => Stmt::Expr(Expr::UnimplementedSigilValue),
_ => Stmt::Expr(Expr::UnimplementedSigilValue)
}
}
}
impl BinOp {
fn reduce(&self, symbol_table: &SymbolTable, lhs: &Box<Meta<Expression>>, rhs: &Box<Meta<Expression>>) -> Expr {
let operation = Builtin::from_str(self.sigil()).ok();
match operation {
Some(Builtin::Assignment) => Expr::Assign {
val: Box::new(lhs.reduce(symbol_table)),
expr: Box::new(rhs.reduce(symbol_table)),
},
Some(op) => {
let f = Box::new(Expr::Func(Func::BuiltIn(op)));
Expr::Call { f, args: vec![lhs.reduce(symbol_table), rhs.reduce(symbol_table)]}
},
None => {
//TODO handle a user-defined operation
Expr::UnimplementedSigilValue
}
}
}
}
impl PrefixOp {
fn reduce(&self, symbol_table: &SymbolTable, arg: &Box<Meta<Expression>>) -> Expr {
match self.builtin {
Some(op) => {
let f = Box::new(Expr::Func(Func::BuiltIn(op)));
Expr::Call { f, args: vec![arg.reduce(symbol_table)]}
},
None => { //TODO need this for custom prefix ops
Expr::UnimplementedSigilValue
}
}
}
}