2019-08-12 11:53:17 -07:00
//! # Reduced AST
//! The reduced AST is a minimal AST designed to be built from the full AST after all possible
//! static checks have been done. Consequently, the AST reduction phase does very little error
//! checking itself - any errors should ideally be caught either by an earlier phase, or are
//! runtime errors that the evaluator should handle. That said, becuase it does do table lookups
//! that can in principle fail [especially at the moment with most static analysis not yet complete],
//! there is an Expr variant `ReductionError` to handle these cases.
//!
//! A design decision to make - should the ReducedAST types contain all information about
//! type/layout necessary for the evaluator to work? If so, then the evaluator should not
//! have access to the symbol table at all and ReducedAST should carry that information. If not,
//! then ReducedAST shouldn't be duplicating information that can be queried at runtime from the
//! symbol table. But I think the former might make sense since ultimately the bytecode will be
//! built from the ReducedAST.
2018-05-09 02:27:57 -07:00
use std ::rc ::Rc ;
2019-08-12 14:10:07 -07:00
use std ::str ::FromStr ;
2018-05-09 02:02:17 -07:00
2019-01-07 13:00:37 -08:00
use crate ::ast ::* ;
use crate ::symbol_table ::{ Symbol , SymbolSpec , SymbolTable } ;
2019-08-15 06:28:40 -07:00
use crate ::builtin ::Builtin ;
2018-05-09 02:27:57 -07:00
2018-05-09 02:49:49 -07:00
#[ derive(Debug) ]
2018-05-09 02:27:57 -07:00
pub struct ReducedAST ( pub Vec < Stmt > ) ;
2018-05-11 17:24:11 -07:00
#[ derive(Debug, Clone) ]
2018-05-09 02:27:57 -07:00
pub enum Stmt {
2018-05-13 17:24:21 -07:00
PreBinding {
name : Rc < String > ,
func : Func ,
} ,
2018-05-09 02:27:57 -07:00
Binding {
name : Rc < String > ,
2018-05-11 02:24:38 -07:00
constant : bool ,
2018-05-09 02:27:57 -07:00
expr : Expr ,
} ,
Expr ( Expr ) ,
2018-05-13 17:24:21 -07:00
Noop ,
2018-05-09 02:27:57 -07:00
}
2018-05-11 17:24:11 -07:00
#[ derive(Debug, Clone) ]
2018-05-09 02:27:57 -07:00
pub enum Expr {
2018-05-12 00:59:50 -07:00
Unit ,
2018-05-09 03:04:01 -07:00
Lit ( Lit ) ,
2018-05-12 12:56:39 -07:00
Tuple ( Vec < Expr > ) ,
2018-05-09 02:27:57 -07:00
Func ( Func ) ,
2019-08-30 19:10:16 -07:00
Sym ( Rc < String > ) ,
2018-08-05 19:14:02 -07:00
Constructor {
2018-08-05 14:23:08 -07:00
type_name : Rc < String > ,
2018-08-05 17:15:58 -07:00
name : Rc < String > ,
2018-08-05 14:23:08 -07:00
tag : usize ,
2019-08-12 10:59:04 -07:00
arity : usize , // n.b. arity here is always the value from the symbol table - if it doesn't match what it's being called with, that's an eval error, eval will handle it
2018-08-05 14:23:08 -07:00
} ,
2018-05-09 02:27:57 -07:00
Call {
2018-05-11 23:34:26 -07:00
f : Box < Expr > ,
2018-05-09 02:27:57 -07:00
args : Vec < Expr > ,
} ,
2018-05-12 03:51:42 -07:00
Assign {
val : Box < Expr > ,
expr : Box < Expr > ,
} ,
2018-05-12 13:51:12 -07:00
Conditional {
cond : Box < Expr > ,
then_clause : Vec < Stmt > ,
else_clause : Vec < Stmt > ,
} ,
2018-10-29 01:50:43 -07:00
ConditionalTargetSigilValue ,
2018-08-14 12:37:18 -07:00
CaseMatch {
2018-07-24 03:12:00 -07:00
cond : Box < Expr > ,
2018-08-05 14:23:08 -07:00
alternatives : Vec < Alternative >
2018-07-24 03:12:00 -07:00
} ,
2019-08-12 11:40:16 -07:00
UnimplementedSigilValue ,
ReductionError ( String ) ,
2018-05-09 02:27:57 -07:00
}
2018-11-05 03:41:03 -08:00
pub type BoundVars = Vec < Option < Rc < String > > > ; //remember that order matters here
2018-08-05 14:23:08 -07:00
#[ derive(Debug, Clone) ]
pub struct Alternative {
2019-07-30 01:33:09 -07:00
pub matchable : Subpattern ,
2018-08-14 21:17:43 -07:00
pub item : Vec < Stmt > ,
2018-08-05 14:23:08 -07:00
}
2018-10-30 18:39:25 -07:00
#[ derive(Debug, Clone) ]
pub struct Subpattern {
pub tag : Option < usize > ,
2018-10-30 18:46:06 -07:00
pub subpatterns : Vec < Option < Subpattern > > ,
2018-11-05 03:41:03 -08:00
pub bound_vars : BoundVars ,
2018-10-30 18:39:25 -07:00
pub guard : Option < Expr > ,
}
2018-05-11 17:24:11 -07:00
#[ derive(Debug, Clone) ]
2018-05-09 02:27:57 -07:00
pub enum Lit {
2018-05-11 00:38:40 -07:00
Nat ( u64 ) ,
Int ( i64 ) ,
2018-05-09 17:02:10 -07:00
Float ( f64 ) ,
2018-05-09 02:27:57 -07:00
Bool ( bool ) ,
StringLit ( Rc < String > ) ,
}
2018-05-11 17:24:11 -07:00
#[ derive(Debug, Clone) ]
2018-05-11 00:38:40 -07:00
pub enum Func {
2019-08-12 14:10:07 -07:00
BuiltIn ( Builtin ) ,
2018-05-11 00:38:40 -07:00
UserDefined {
2018-05-11 23:23:54 -07:00
name : Option < Rc < String > > ,
2018-05-11 00:38:40 -07:00
params : Vec < Rc < String > > ,
body : Vec < Stmt > ,
}
2018-05-09 02:27:57 -07:00
}
2018-05-10 23:41:51 -07:00
impl AST {
2018-06-12 02:56:28 -07:00
pub fn reduce ( & self , symbol_table : & SymbolTable ) -> ReducedAST {
2018-05-10 23:41:51 -07:00
let mut output = vec! [ ] ;
for statement in self . 0. iter ( ) {
2019-01-04 22:58:25 -08:00
output . push ( statement . node ( ) . reduce ( symbol_table ) ) ;
2018-05-09 02:49:49 -07:00
}
2018-05-11 00:45:32 -07:00
ReducedAST ( output )
2018-05-09 02:49:49 -07:00
}
}
2018-05-09 02:27:57 -07:00
2018-05-11 22:44:21 -07:00
impl Statement {
2018-06-12 02:56:28 -07:00
fn reduce ( & self , symbol_table : & SymbolTable ) -> Stmt {
2019-01-07 13:00:37 -08:00
use crate ::ast ::Statement ::* ;
2018-05-11 22:44:21 -07:00
match self {
2019-01-05 15:47:44 -08:00
ExpressionStatement ( expr ) = > Stmt ::Expr ( expr . node ( ) . reduce ( symbol_table ) ) ,
2018-06-12 02:56:28 -07:00
Declaration ( decl ) = > decl . reduce ( symbol_table ) ,
2018-05-11 22:44:21 -07:00
}
}
}
2019-01-04 22:58:25 -08:00
fn reduce_block ( block : & Block , symbol_table : & SymbolTable ) -> Vec < Stmt > {
block . iter ( ) . map ( | stmt | stmt . node ( ) . reduce ( symbol_table ) ) . collect ( )
}
2019-06-12 03:28:46 -07:00
impl InvocationArgument {
fn reduce ( & self , symbol_table : & SymbolTable ) -> Expr {
use crate ::ast ::InvocationArgument ::* ;
match self {
Positional ( ex ) = > ex . reduce ( symbol_table ) ,
Keyword { .. } = > Expr ::UnimplementedSigilValue ,
Ignored = > Expr ::UnimplementedSigilValue ,
}
}
}
2018-05-10 23:41:51 -07:00
impl Expression {
2018-06-12 02:56:28 -07:00
fn reduce ( & self , symbol_table : & SymbolTable ) -> Expr {
2019-02-21 01:26:51 -08:00
use crate ::ast ::ExpressionKind ::* ;
2019-07-10 18:52:25 -07:00
let ref input = self . kind ;
2018-05-11 00:45:32 -07:00
match input {
2018-05-12 01:44:03 -07:00
NatLiteral ( n ) = > Expr ::Lit ( Lit ::Nat ( * n ) ) ,
2018-05-11 23:26:02 -07:00
FloatLiteral ( f ) = > Expr ::Lit ( Lit ::Float ( * f ) ) ,
StringLiteral ( s ) = > Expr ::Lit ( Lit ::StringLit ( s . clone ( ) ) ) ,
BoolLiteral ( b ) = > Expr ::Lit ( Lit ::Bool ( * b ) ) ,
2018-06-12 02:56:28 -07:00
BinExp ( binop , lhs , rhs ) = > binop . reduce ( symbol_table , lhs , rhs ) ,
PrefixExp ( op , arg ) = > op . reduce ( symbol_table , arg ) ,
2018-08-07 17:09:53 -07:00
Value ( name ) = > match symbol_table . lookup_by_name ( name ) {
Some ( Symbol { spec : SymbolSpec ::DataConstructor { index , type_args , type_name } , .. } ) = > Expr ::Constructor {
type_name : type_name . clone ( ) ,
name : name . clone ( ) ,
tag : index . clone ( ) ,
arity : type_args . len ( ) ,
} ,
2019-08-30 19:10:16 -07:00
_ = > Expr ::Sym ( name . clone ( ) ) ,
2018-06-12 03:02:50 -07:00
} ,
2019-06-16 00:21:39 -07:00
Call { f , arguments } = > reduce_call_expression ( f , arguments , symbol_table ) ,
2019-01-05 16:06:55 -08:00
TupleLiteral ( exprs ) = > Expr ::Tuple ( exprs . iter ( ) . map ( | e | e . node ( ) . reduce ( symbol_table ) ) . collect ( ) ) ,
2018-07-24 03:12:00 -07:00
IfExpression { discriminator , body } = > reduce_if_expression ( discriminator , body , symbol_table ) ,
2018-11-05 21:13:31 -08:00
Lambda { params , body , .. } = > reduce_lambda ( params , body , symbol_table ) ,
2019-08-12 10:59:04 -07:00
NamedStruct { name , fields } = > reduce_named_struct ( name , fields , symbol_table ) ,
2018-11-05 21:13:31 -08:00
Index { .. } = > Expr ::UnimplementedSigilValue ,
WhileExpression { .. } = > Expr ::UnimplementedSigilValue ,
ForExpression { .. } = > Expr ::UnimplementedSigilValue ,
ListLiteral { .. } = > Expr ::UnimplementedSigilValue ,
2018-05-11 00:45:32 -07:00
}
2018-05-10 23:41:51 -07:00
}
2018-05-09 02:49:49 -07:00
}
2018-05-10 23:41:51 -07:00
2018-11-05 21:13:31 -08:00
fn reduce_lambda ( params : & Vec < FormalParam > , body : & Block , symbol_table : & SymbolTable ) -> Expr {
2018-11-06 01:19:16 -08:00
Expr ::Func ( Func ::UserDefined {
name : None ,
2019-06-16 14:56:52 -07:00
params : params . iter ( ) . map ( | param | param . name . clone ( ) ) . collect ( ) ,
2019-01-04 22:58:25 -08:00
body : reduce_block ( body , symbol_table ) ,
2018-11-06 01:19:16 -08:00
} )
2018-11-05 21:13:31 -08:00
}
2019-08-12 10:59:04 -07:00
fn reduce_named_struct ( name : & Rc < String > , fields : & Vec < ( Rc < String > , Meta < Expression > ) > , symbol_table : & SymbolTable ) -> Expr {
2019-08-12 12:46:18 -07:00
let ( type_name , index , members_from_table ) = match symbol_table . lookup_by_name ( name ) {
Some ( Symbol { spec : SymbolSpec ::RecordConstructor { members , type_name , index } , .. } ) = > ( type_name . clone ( ) , index , members ) ,
2019-08-12 11:40:16 -07:00
_ = > return Expr ::ReductionError ( " Not a record constructor " . to_string ( ) ) ,
2019-08-12 10:59:04 -07:00
} ;
2019-08-12 12:46:18 -07:00
let arity = members_from_table . len ( ) ;
let mut args : Vec < ( Rc < String > , Expr ) > = fields . iter ( )
. map ( | ( name , expr ) | ( name . clone ( ) , expr . node ( ) . 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 , } ;
2019-08-12 10:59:04 -07:00
Expr ::Call { f , args }
2019-08-05 03:35:10 -07:00
}
2019-06-16 00:21:39 -07:00
fn reduce_call_expression ( func : & Meta < Expression > , arguments : & Vec < Meta < InvocationArgument > > , symbol_table : & SymbolTable ) -> Expr {
Expr ::Call {
f : Box ::new ( func . node ( ) . reduce ( symbol_table ) ) ,
args : arguments . iter ( ) . map ( | arg | arg . node ( ) . reduce ( symbol_table ) ) . collect ( ) ,
}
}
2018-07-24 03:12:00 -07:00
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 ) ,
2018-10-20 00:55:37 -07:00
Discriminator ::BinOp ( ref _expr , ref _binop ) = > panic! ( " Can't yet handle binop discriminators " )
2018-07-24 03:12:00 -07:00
} ) ;
match * body {
IfExpressionBody ::SimpleConditional ( ref then_clause , ref else_clause ) = > {
2019-01-04 22:58:25 -08:00
let then_clause = reduce_block ( then_clause , symbol_table ) ;
2018-07-24 03:12:00 -07:00
let else_clause = match else_clause {
None = > vec! [ ] ,
2019-01-04 22:58:25 -08:00
Some ( stmts ) = > reduce_block ( stmts , symbol_table ) ,
2018-07-24 03:12:00 -07:00
} ;
Expr ::Conditional { cond , then_clause , else_clause }
} ,
IfExpressionBody ::SimplePatternMatch ( ref pat , ref then_clause , ref else_clause ) = > {
2019-01-04 22:58:25 -08:00
let then_clause = reduce_block ( then_clause , symbol_table ) ;
2018-07-24 03:12:00 -07:00
let else_clause = match else_clause {
None = > vec! [ ] ,
2019-01-04 22:58:25 -08:00
Some ( stmts ) = > reduce_block ( stmts , symbol_table ) ,
2018-07-24 03:12:00 -07:00
} ;
2018-08-13 23:28:03 -07:00
2018-08-05 18:01:42 -07:00
let alternatives = vec! [
2018-10-29 01:50:43 -07:00
pat . to_alternative ( then_clause , symbol_table ) ,
2018-11-03 12:53:09 -07:00
Alternative {
2019-07-30 01:33:09 -07:00
matchable : Subpattern {
tag : None ,
subpatterns : vec ! [ ] ,
bound_vars : vec ! [ ] ,
guard : None ,
} ,
2018-11-03 12:53:09 -07:00
item : else_clause
} ,
2018-08-05 18:01:42 -07:00
] ;
2018-08-14 12:37:18 -07:00
Expr ::CaseMatch {
2018-08-05 18:01:42 -07:00
cond ,
alternatives ,
2018-07-25 03:05:40 -07:00
}
2018-07-24 03:12:00 -07:00
} ,
2018-08-15 09:34:00 -07:00
IfExpressionBody ::GuardList ( ref guard_arms ) = > {
2018-10-19 11:02:10 -07:00
let mut alternatives = vec! [ ] ;
for arm in guard_arms {
match arm . guard {
Guard ::Pat ( ref p ) = > {
2019-01-04 22:58:25 -08:00
let item = reduce_block ( & arm . body , symbol_table ) ;
2018-10-29 01:50:43 -07:00
let alt = p . to_alternative ( item , symbol_table ) ;
2018-10-19 11:02:10 -07:00
alternatives . push ( alt ) ;
} ,
Guard ::HalfExpr ( HalfExpr { op : _ , expr : _ } ) = > {
return Expr ::UnimplementedSigilValue
}
2018-08-24 16:04:18 -07:00
}
2018-10-19 11:02:10 -07:00
}
2018-08-15 18:32:44 -07:00
Expr ::CaseMatch { cond , alternatives }
2018-08-15 09:34:00 -07:00
}
2018-07-24 03:12:00 -07:00
}
}
2018-10-19 17:27:06 -07:00
/* ig var pat
* x is SomeBigOldEnum ( _ , x , Some ( t ) )
* /
2018-11-03 12:53:09 -07:00
fn handle_symbol ( symbol : Option < & Symbol > , inner_patterns : & Vec < Pattern > , symbol_table : & SymbolTable ) -> Subpattern {
2018-10-30 18:53:34 -07:00
use self ::Pattern ::* ;
2018-10-30 23:36:55 -07:00
let tag = symbol . map ( | symbol | match symbol . spec {
2018-10-30 18:53:34 -07:00
SymbolSpec ::DataConstructor { index , .. } = > index . clone ( ) ,
_ = > panic! ( " Symbol is not a data constructor - this should've been caught in type-checking " ) ,
2018-10-30 23:36:55 -07:00
} ) ;
2018-11-03 12:53:09 -07:00
let bound_vars = inner_patterns . iter ( ) . map ( | p | match p {
2018-10-30 18:53:34 -07:00
Literal ( PatternLiteral ::VarPattern ( var ) ) = > Some ( var . clone ( ) ) ,
_ = > None ,
} ) . collect ( ) ;
2018-07-24 03:12:00 -07:00
2018-11-03 12:53:09 -07:00
let subpatterns = inner_patterns . iter ( ) . map ( | p | match p {
Ignored = > None ,
Literal ( PatternLiteral ::VarPattern ( _ ) ) = > None ,
Literal ( other ) = > Some ( other . to_subpattern ( symbol_table ) ) ,
tp @ TuplePattern ( _ ) = > Some ( tp . to_subpattern ( symbol_table ) ) ,
ts @ TupleStruct ( _ , _ ) = > Some ( ts . to_subpattern ( symbol_table ) ) ,
Record ( .. ) = > unimplemented! ( ) ,
} ) . collect ( ) ;
let guard = None ;
2018-10-30 18:53:34 -07:00
/*
let guard_equality_exprs : Vec < Expr > = subpatterns . iter ( ) . map ( | p | match p {
Literal ( lit ) = > match lit {
_ = > unimplemented! ( )
} ,
_ = > unimplemented! ( )
} ) . collect ( ) ;
* /
2018-10-15 19:54:17 -07:00
2018-10-30 18:53:34 -07:00
Subpattern {
2018-10-30 23:36:55 -07:00
tag ,
2018-10-30 18:53:34 -07:00
subpatterns ,
guard ,
bound_vars ,
}
}
2018-10-15 19:54:17 -07:00
2018-10-30 18:53:34 -07:00
impl Pattern {
fn to_alternative ( & self , item : Vec < Stmt > , symbol_table : & SymbolTable ) -> Alternative {
2018-11-03 12:53:09 -07:00
let s = self . to_subpattern ( symbol_table ) ;
Alternative {
2019-07-30 01:33:09 -07:00
matchable : Subpattern {
tag : s . tag ,
subpatterns : s . subpatterns ,
bound_vars : s . bound_vars ,
guard : s . guard ,
} ,
2018-11-03 12:53:09 -07:00
item
}
}
fn to_subpattern ( & self , symbol_table : & SymbolTable ) -> Subpattern {
2018-10-30 18:53:34 -07:00
use self ::Pattern ::* ;
2018-08-24 16:04:18 -07:00
match self {
2018-11-03 12:53:09 -07:00
TupleStruct ( name , inner_patterns ) = > {
2018-10-15 19:54:17 -07:00
let symbol = symbol_table . lookup_by_name ( name ) . expect ( & format! ( " Symbol {} not found " , name ) ) ;
2018-11-03 12:53:09 -07:00
handle_symbol ( Some ( symbol ) , inner_patterns , symbol_table )
2018-08-24 16:04:18 -07:00
} ,
2018-11-03 12:53:09 -07:00
TuplePattern ( inner_patterns ) = > handle_symbol ( None , inner_patterns , symbol_table ) ,
2018-08-24 16:04:18 -07:00
Record ( _name , _pairs ) = > {
unimplemented! ( )
} ,
2018-11-03 12:53:09 -07:00
Ignored = > Subpattern { tag : None , subpatterns : vec ! [ ] , guard : None , bound_vars : vec ! [ ] } ,
Literal ( lit ) = > lit . to_subpattern ( symbol_table ) ,
2018-10-30 18:53:34 -07:00
}
}
}
impl PatternLiteral {
fn to_subpattern ( & self , symbol_table : & SymbolTable ) -> Subpattern {
use self ::PatternLiteral ::* ;
match self {
NumPattern { neg , num } = > {
let comparison = Expr ::Lit ( match ( neg , num ) {
2019-02-21 01:26:51 -08:00
( false , ExpressionKind ::NatLiteral ( n ) ) = > Lit ::Nat ( * n ) ,
( false , ExpressionKind ::FloatLiteral ( f ) ) = > Lit ::Float ( * f ) ,
( true , ExpressionKind ::NatLiteral ( n ) ) = > Lit ::Int ( - 1 * ( * n as i64 ) ) ,
( true , ExpressionKind ::FloatLiteral ( f ) ) = > Lit ::Float ( - 1.0 * f ) ,
2018-10-30 18:53:34 -07:00
_ = > panic! ( " This should never happen " )
} ) ;
let guard = Some ( Expr ::Call {
2019-08-12 14:10:07 -07:00
f : Box ::new ( Expr ::Func ( Func ::BuiltIn ( Builtin ::Equality ) ) ) ,
2018-10-30 18:53:34 -07:00
args : vec ! [ comparison , Expr ::ConditionalTargetSigilValue ] ,
} ) ;
Subpattern {
tag : None ,
subpatterns : vec ! [ ] ,
guard ,
bound_vars : vec ! [ ] ,
}
} ,
2018-10-31 01:45:16 -07:00
StringPattern ( s ) = > {
let guard = Some ( Expr ::Call {
2019-08-12 14:10:07 -07:00
f : Box ::new ( Expr ::Func ( Func ::BuiltIn ( Builtin ::Equality ) ) ) ,
2018-10-31 01:45:16 -07:00
args : vec ! [ Expr ::Lit ( Lit ::StringLit ( s . clone ( ) ) ) , Expr ::ConditionalTargetSigilValue ]
} ) ;
Subpattern {
tag : None ,
subpatterns : vec ! [ ] ,
guard ,
bound_vars : vec ! [ ] ,
}
} ,
2018-10-30 18:53:34 -07:00
BoolPattern ( b ) = > {
let guard = Some ( if * b {
Expr ::ConditionalTargetSigilValue
} else {
Expr ::Call {
2019-08-12 14:10:07 -07:00
f : Box ::new ( Expr ::Func ( Func ::BuiltIn ( Builtin ::BooleanNot ) ) ) ,
2018-10-30 18:53:34 -07:00
args : vec ! [ Expr ::ConditionalTargetSigilValue ]
2018-10-15 19:54:17 -07:00
}
2018-10-30 18:53:34 -07:00
} ) ;
Subpattern {
tag : None ,
subpatterns : vec ! [ ] ,
guard ,
bound_vars : vec ! [ ] ,
2018-10-15 19:54:17 -07:00
}
2018-08-24 16:04:18 -07:00
} ,
2018-10-30 18:53:34 -07:00
VarPattern ( var ) = > match symbol_table . lookup_by_name ( var ) {
2018-11-03 12:53:09 -07:00
Some ( symbol ) = > handle_symbol ( Some ( symbol ) , & vec! [ ] , symbol_table ) ,
2018-10-30 18:53:34 -07:00
None = > Subpattern {
tag : None ,
subpatterns : vec ! [ ] ,
guard : None ,
bound_vars : vec ! [ Some ( var . clone ( ) ) ] ,
}
}
2018-08-24 16:04:18 -07:00
}
}
}
2018-05-10 23:41:51 -07:00
impl Declaration {
2018-06-12 02:56:28 -07:00
fn reduce ( & self , symbol_table : & SymbolTable ) -> Stmt {
2018-05-11 02:24:38 -07:00
use self ::Declaration ::* ;
match self {
2019-02-21 19:07:07 -08:00
Binding { name , constant , expr , .. } = > Stmt ::Binding { name : name . clone ( ) , constant : * constant , expr : expr . node ( ) . reduce ( symbol_table ) } ,
2018-05-13 17:24:21 -07:00
FuncDecl ( Signature { name , params , .. } , statements ) = > Stmt ::PreBinding {
2018-05-11 22:44:21 -07:00
name : name . clone ( ) ,
2018-05-13 17:24:21 -07:00
func : Func ::UserDefined {
name : Some ( name . clone ( ) ) ,
2019-06-16 14:56:52 -07:00
params : params . iter ( ) . map ( | param | param . name . clone ( ) ) . collect ( ) ,
2019-01-04 22:58:25 -08:00
body : reduce_block ( & statements , symbol_table ) ,
2018-05-13 17:24:21 -07:00
}
2018-05-11 22:44:21 -07:00
} ,
2018-07-12 02:07:52 -07:00
TypeDecl { .. } = > Stmt ::Noop ,
2018-07-18 16:01:59 -07:00
TypeAlias ( _ , _ ) = > Stmt ::Noop ,
Interface { .. } = > Stmt ::Noop ,
Impl { .. } = > Stmt ::Expr ( Expr ::UnimplementedSigilValue ) ,
2018-05-11 02:24:38 -07:00
_ = > Stmt ::Expr ( Expr ::UnimplementedSigilValue )
}
2018-05-10 23:41:51 -07:00
}
2018-05-09 02:27:57 -07:00
}
2018-05-09 17:02:10 -07:00
2018-05-10 23:41:51 -07:00
impl BinOp {
2019-02-21 01:49:15 -08:00
fn reduce ( & self , symbol_table : & SymbolTable , lhs : & Box < Meta < Expression > > , rhs : & Box < Meta < Expression > > ) -> Expr {
2019-08-12 14:10:07 -07:00
let operation = Builtin ::from_str ( self . sigil ( ) ) . ok ( ) ;
match operation {
Some ( Builtin ::Assignment ) = > Expr ::Assign {
2019-01-05 15:54:03 -08:00
val : Box ::new ( lhs . node ( ) . reduce ( symbol_table ) ) ,
expr : Box ::new ( rhs . node ( ) . reduce ( symbol_table ) ) ,
2019-08-12 14:10:07 -07:00
} ,
Some ( op ) = > {
let f = Box ::new ( Expr ::Func ( Func ::BuiltIn ( op ) ) ) ;
Expr ::Call { f , args : vec ! [ lhs . node ( ) . reduce ( symbol_table ) , rhs . node ( ) . reduce ( symbol_table ) ] }
} ,
None = > {
//TODO handle a user-defined operation
Expr ::UnimplementedSigilValue
2018-05-12 03:51:42 -07:00
}
}
2018-05-10 23:41:51 -07:00
}
2018-05-09 17:02:10 -07:00
}
2018-05-10 23:41:51 -07:00
impl PrefixOp {
2019-02-21 01:49:15 -08:00
fn reduce ( & self , symbol_table : & SymbolTable , arg : & Box < Meta < Expression > > ) -> Expr {
2019-08-14 07:31:59 -07:00
match self . builtin {
2019-08-12 14:10:07 -07:00
Some ( op ) = > {
let f = Box ::new ( Expr ::Func ( Func ::BuiltIn ( op ) ) ) ;
Expr ::Call { f , args : vec ! [ arg . node ( ) . reduce ( symbol_table ) ] }
} ,
2019-08-14 07:54:39 -07:00
None = > { //TODO need this for custom prefix ops
2019-08-12 14:10:07 -07:00
Expr ::UnimplementedSigilValue
}
}
2018-05-10 23:41:51 -07:00
}
2018-05-09 17:02:10 -07:00
}