diff --git a/schala-lang/language/src/reduced_ast.rs b/schala-lang/language/src/reduced_ast.rs index fbc23d0..a75c20c 100644 --- a/schala-lang/language/src/reduced_ast.rs +++ b/schala-lang/language/src/reduced_ast.rs @@ -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) -> Stmt { - - } - */ -} - -impl Meta { - fn reduce(&self, symbol_table: &SymbolTable) -> Stmt { + fn statement(&mut self, stmt: &Meta) -> 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 { - block.iter().map(|stmt| stmt.reduce(symbol_table)).collect() -} + fn block(&mut self, block: &Block) -> Vec { + 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 { - fn reduce(&self, symbol_table: &SymbolTable) -> Expr { + fn expression(&mut self, expr: &Meta) -> 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 { _ => 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, 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, Meta)>, 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, 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, arguments: &Vec, 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, 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, Meta)>) -> 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, 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, arguments: &Vec) -> 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>, rhs: &Box>) -> 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>) -> 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>, rhs: &Box>) -> 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>) -> 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 - } - } - } }