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 ::* ;
2019-09-10 03:40:41 -07:00
use crate ::symbol_table ::{ Symbol , SymbolSpec , SymbolTable , FullyQualifiedSymbolName } ;
2019-08-15 06:28:40 -07:00
use crate ::builtin ::Builtin ;
2019-10-10 17:06:41 -07:00
use crate ::util ::deref_optional_box ;
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
}
2019-09-10 09:27:33 -07:00
pub fn reduce ( ast : & AST , symbol_table : & SymbolTable ) -> ReducedAST {
let mut reducer = Reducer { symbol_table } ;
reducer . ast ( ast )
}
struct Reducer < ' a > {
symbol_table : & ' a SymbolTable
}
impl < ' a > Reducer < ' a > {
2019-09-11 19:06:00 -07:00
fn ast ( & mut self , ast : & AST ) -> ReducedAST {
2018-05-10 23:41:51 -07:00
let mut output = vec! [ ] ;
2019-09-11 19:06:00 -07:00
for statement in ast . statements . iter ( ) {
2019-09-11 01:27:52 -07:00
output . push ( self . statement ( statement ) ) ;
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
}
2019-09-10 09:27:33 -07:00
2019-09-20 02:21:39 -07:00
fn statement ( & mut self , stmt : & Statement ) -> Stmt {
match & stmt . kind {
2019-09-17 02:25:11 -07:00
StatementKind ::Expression ( expr ) = > Stmt ::Expr ( self . expression ( & expr ) ) ,
StatementKind ::Declaration ( decl ) = > self . declaration ( & decl ) ,
2019-09-21 02:30:28 -07:00
StatementKind ::Import ( _ ) = > Stmt ::Noop ,
2019-10-22 03:15:14 -07:00
StatementKind ::Module ( modspec ) = > {
for statement in modspec . contents . iter ( ) {
self . statement ( & statement ) ;
}
Stmt ::Noop
}
2018-05-11 22:44:21 -07:00
}
}
2019-09-11 01:27:52 -07:00
fn block ( & mut self , block : & Block ) -> Vec < Stmt > {
block . iter ( ) . map ( | stmt | self . statement ( stmt ) ) . collect ( )
}
2019-01-04 22:58:25 -08:00
2019-09-11 01:27:52 -07:00
fn invocation_argument ( & mut self , invoc : & InvocationArgument ) -> Expr {
2019-06-12 03:28:46 -07:00
use crate ::ast ::InvocationArgument ::* ;
2019-09-11 01:27:52 -07:00
match invoc {
Positional ( ex ) = > self . expression ( ex ) ,
2019-06-12 03:28:46 -07:00
Keyword { .. } = > Expr ::UnimplementedSigilValue ,
Ignored = > Expr ::UnimplementedSigilValue ,
}
}
2019-09-20 02:21:39 -07:00
fn expression ( & mut self , expr : & Expression ) -> Expr {
2019-02-21 01:26:51 -08:00
use crate ::ast ::ExpressionKind ::* ;
2019-09-11 01:27:52 -07:00
let symbol_table = self . symbol_table ;
2019-09-20 02:21:39 -07:00
let ref input = expr . 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 ) ) ,
2019-09-11 01:27:52 -07:00
BinExp ( binop , lhs , rhs ) = > self . binop ( binop , lhs , rhs ) ,
PrefixExp ( op , arg ) = > self . prefix ( op , arg ) ,
2019-08-31 23:39:01 -07:00
Value ( qualified_name ) = > {
2019-09-20 01:57:48 -07:00
let ref id = qualified_name . id ;
2019-09-19 03:34:09 -07:00
let ref sym_name = match symbol_table . get_fqsn_from_id ( id ) {
Some ( fqsn ) = > fqsn ,
2019-09-10 03:31:23 -07:00
None = > return Expr ::ReductionError ( format! ( " FQSN lookup for Value {:?} failed " , qualified_name ) ) ,
2019-09-03 03:20:17 -07:00
} ;
2019-09-10 03:33:28 -07:00
//TODO this probably needs to change
2019-08-31 23:39:01 -07:00
let FullyQualifiedSymbolName ( ref v ) = sym_name ;
let name = v . last ( ) . unwrap ( ) . name . clone ( ) ;
match symbol_table . lookup_by_fqsn ( & sym_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 ( ) ,
} ,
_ = > Expr ::Sym ( name . clone ( ) ) ,
}
2018-06-12 03:02:50 -07:00
} ,
2019-09-11 01:27:52 -07:00
Call { f , arguments } = > self . reduce_call_expression ( f , arguments ) ,
TupleLiteral ( exprs ) = > Expr ::Tuple ( exprs . iter ( ) . map ( | e | self . expression ( e ) ) . collect ( ) ) ,
2019-10-10 17:06:41 -07:00
IfExpression { discriminator , body } = > self . reduce_if_expression ( deref_optional_box ( discriminator ) , body ) ,
2019-09-11 01:27:52 -07:00
Lambda { params , body , .. } = > self . reduce_lambda ( params , body ) ,
2019-09-20 02:21:39 -07:00
NamedStruct { name , fields } = > self . reduce_named_struct ( name , fields ) ,
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
}
2019-09-11 01:27:52 -07:00
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 ) ,
} )
}
2018-11-05 21:13:31 -08:00
2019-09-20 02:21:39 -07:00
fn reduce_named_struct ( & mut self , name : & QualifiedName , fields : & Vec < ( Rc < String > , Expression ) > ) -> Expr {
2019-09-11 01:27:52 -07:00
let symbol_table = self . symbol_table ;
2019-09-19 18:38:15 -07:00
let ref sym_name = match symbol_table . get_fqsn_from_id ( & name . id ) {
2019-09-11 01:27:52 -07:00
Some ( fqsn ) = > fqsn ,
2019-09-19 18:38:15 -07:00
None = > return Expr ::ReductionError ( format! ( " FQSN lookup for name {:?} failed " , name ) ) ,
2019-09-11 01:27:52 -07:00
} ;
2019-09-19 18:38:15 -07:00
2019-09-11 01:27:52 -07:00
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 ( ) , 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 }
}
2019-08-05 03:35:10 -07:00
2019-09-20 02:21:39 -07:00
fn reduce_call_expression ( & mut self , func : & Expression , arguments : & Vec < InvocationArgument > ) -> Expr {
2019-09-11 01:27:52 -07:00
Expr ::Call {
f : Box ::new ( self . expression ( func ) ) ,
args : arguments . iter ( ) . map ( | arg | self . invocation_argument ( arg ) ) . collect ( ) ,
}
2019-06-16 00:21:39 -07:00
}
2019-10-10 17:06:41 -07:00
fn reduce_if_expression ( & mut self , discriminator : Option < & Expression > , body : & IfExpressionBody ) -> Expr {
2019-09-11 01:27:52 -07:00
let symbol_table = self . symbol_table ;
2019-10-10 17:06:41 -07:00
let cond = Box ::new ( match discriminator {
Some ( expr ) = > self . expression ( expr ) ,
2019-10-10 17:50:20 -07:00
None = > return Expr ::ReductionError ( format! ( " blank cond if-expr not supported " ) ) ,
2019-09-11 01:27:52 -07:00
} ) ;
2019-10-10 17:06:41 -07:00
2019-10-10 17:50:20 -07:00
match body {
2019-10-10 17:06:41 -07:00
IfExpressionBody ::SimpleConditional { then_case , else_case } = > {
2019-10-10 17:50:20 -07:00
let then_clause = self . block ( & then_case ) ;
let else_clause = match else_case . as_ref ( ) {
2019-09-11 01:27:52 -07:00
None = > vec! [ ] ,
2019-10-10 17:50:20 -07:00
Some ( stmts ) = > self . block ( & stmts ) ,
2019-09-11 01:27:52 -07:00
} ;
Expr ::Conditional { cond , then_clause , else_clause }
} ,
2019-10-10 17:50:20 -07:00
IfExpressionBody ::SimplePatternMatch { pattern , then_case , else_case } = > {
let then_clause = self . block ( & then_case ) ;
let else_clause = match else_case . as_ref ( ) {
2019-09-11 01:27:52 -07:00
None = > vec! [ ] ,
2019-10-10 17:50:20 -07:00
Some ( stmts ) = > self . block ( & stmts ) ,
2019-09-11 01:27:52 -07:00
} ;
2018-08-05 18:01:42 -07:00
2019-09-11 01:27:52 -07:00
let alternatives = vec! [
2019-10-10 17:50:20 -07:00
pattern . to_alternative ( then_clause , symbol_table ) ,
2019-09-11 01:27:52 -07:00
Alternative {
matchable : Subpattern {
tag : None ,
subpatterns : vec ! [ ] ,
bound_vars : vec ! [ ] ,
guard : None ,
} ,
item : else_clause
2018-10-19 11:02:10 -07:00
} ,
2019-09-11 01:27:52 -07:00
] ;
Expr ::CaseMatch {
cond ,
alternatives ,
}
} ,
2019-10-10 17:50:20 -07:00
IfExpressionBody ::CondList ( ref condition_arms ) = > {
2019-09-11 01:27:52 -07:00
let mut alternatives = vec! [ ] ;
2019-10-10 17:50:20 -07:00
for arm in condition_arms {
match arm . condition {
Condition ::Expression ( ref _expr ) = > {
return Expr ::UnimplementedSigilValue
2019-10-09 01:50:32 -07:00
} ,
2019-10-10 17:50:20 -07:00
Condition ::Pattern ( ref p ) = > {
2019-09-11 01:27:52 -07:00
let item = self . block ( & arm . body ) ;
let alt = p . to_alternative ( item , symbol_table ) ;
alternatives . push ( alt ) ;
} ,
2019-10-10 17:50:20 -07:00
Condition ::TruncatedOp ( _ , _ ) = > {
return Expr ::UnimplementedSigilValue
} ,
Condition ::Else = > {
2019-09-11 01:27:52 -07:00
return Expr ::UnimplementedSigilValue
}
2018-10-19 11:02:10 -07:00
}
2018-08-24 16:04:18 -07:00
}
2019-09-11 01:27:52 -07:00
Expr ::CaseMatch { cond , alternatives }
2018-10-19 11:02:10 -07:00
}
2019-09-11 01:27:52 -07:00
}
}
2019-09-20 02:21:39 -07:00
fn binop ( & mut self , binop : & BinOp , lhs : & Box < Expression > , rhs : & Box < Expression > ) -> Expr {
2019-09-11 01:27:52 -07:00
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
}
}
}
2019-09-20 02:21:39 -07:00
fn prefix ( & mut self , prefix : & PrefixOp , arg : & Box < Expression > ) -> Expr {
2019-09-11 01:27:52 -07:00
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 ,
2019-09-28 02:42:18 -07:00
TypeAlias { .. } = > Stmt ::Noop ,
2019-09-11 01:27:52 -07:00
Interface { .. } = > Stmt ::Noop ,
Impl { .. } = > Stmt ::Expr ( Expr ::UnimplementedSigilValue ) ,
_ = > Stmt ::Expr ( Expr ::UnimplementedSigilValue )
2018-08-15 09:34:00 -07:00
}
2018-07-24 03:12:00 -07:00
}
}
2019-09-11 01:27:52 -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 {
2019-09-20 02:03:10 -07:00
VarOrName ( qualified_name ) = > {
2019-09-20 01:08:00 -07:00
let fqsn = symbol_table . get_fqsn_from_id ( & qualified_name . id ) ;
let symbol_exists = fqsn . and_then ( | fqsn | symbol_table . lookup_by_fqsn ( & fqsn ) ) . is_some ( ) ;
2019-09-08 17:01:07 -07:00
if symbol_exists {
None
} else {
2019-09-20 01:08:00 -07:00
let QualifiedName { components , .. } = qualified_name ;
2019-09-19 01:34:21 -07:00
if components . len ( ) = = 1 {
Some ( components [ 0 ] . clone ( ) )
2019-09-08 17:01:07 -07:00
} else {
panic! ( " Bad variable name in pattern " ) ;
}
}
2019-09-06 02:23:04 -07:00
} ,
2018-10-30 18:53:34 -07:00
_ = > 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 ,
2019-09-06 02:23:04 -07:00
VarOrName ( _ ) = > None ,
2018-11-03 12:53:09 -07:00
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 {
2019-09-20 02:03:10 -07:00
TupleStruct ( QualifiedName { components , id } , inner_patterns ) = > {
2019-09-20 01:44:20 -07:00
let fqsn = symbol_table . get_fqsn_from_id ( & id ) ;
match fqsn . and_then ( | fqsn | symbol_table . lookup_by_fqsn ( & fqsn ) ) {
2019-09-10 03:31:23 -07:00
Some ( symbol ) = > handle_symbol ( Some ( symbol ) , inner_patterns , symbol_table ) ,
None = > {
2019-09-19 01:34:21 -07:00
panic! ( " Symbol {:?} not found " , components ) ;
2019-09-10 03:31:23 -07:00
}
}
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 ) ,
2019-09-20 02:03:10 -07:00
VarOrName ( QualifiedName { components , id } ) = > {
2019-09-10 03:31:23 -07:00
// if fqsn is Some, treat this as a symbol pattern. If it's None, treat it
// as a variable.
2019-09-20 01:44:20 -07:00
let fqsn = symbol_table . get_fqsn_from_id ( & id ) ;
match fqsn . and_then ( | fqsn | symbol_table . lookup_by_fqsn ( & fqsn ) ) {
2019-09-06 02:23:04 -07:00
Some ( symbol ) = > handle_symbol ( Some ( symbol ) , & vec! [ ] , symbol_table ) ,
2019-09-10 03:31:23 -07:00
None = > {
2019-09-19 01:34:21 -07:00
let name = if components . len ( ) = = 1 {
components [ 0 ] . clone ( )
2019-09-10 03:31:23 -07:00
} else {
panic! ( " check this line of code yo " ) ;
} ;
Subpattern {
tag : None ,
subpatterns : vec ! [ ] ,
guard : None ,
bound_vars : vec ! [ Some ( name . clone ( ) ) ] ,
}
2019-09-06 02:23:04 -07:00
}
}
} ,
2018-10-30 18:53:34 -07:00
}
}
}
impl PatternLiteral {
2019-09-10 03:40:41 -07:00
fn to_subpattern ( & self , _symbol_table : & SymbolTable ) -> Subpattern {
2018-10-30 18:53:34 -07:00
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-05-09 17:02:10 -07:00
}