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