2019-06-16 14:59:11 -07:00
#![ cfg(test) ]
2021-10-19 22:24:27 -07:00
#![ allow(clippy::upper_case_acronyms) ]
2021-10-19 22:29:41 -07:00
#![ allow(clippy::vec_init_then_push) ]
2021-10-31 02:05:39 -07:00
//use test_case::test_case;
2021-11-02 21:03:48 -07:00
use std ::{ fmt ::Write , rc ::Rc } ;
2021-10-19 22:24:27 -07:00
2021-10-30 20:27:16 -07:00
use pretty_assertions ::assert_eq ;
2019-08-14 07:25:45 -07:00
2021-11-14 04:35:04 -08:00
use super ::Parser ;
2021-11-14 03:18:05 -08:00
use crate ::{ ast ::* , parsing ::Location } ;
2021-10-31 02:05:39 -07:00
fn rc ( s : & str ) -> Rc < String > {
Rc ::new ( s . to_owned ( ) )
}
fn bx < T > ( item : T ) -> Box < T > {
Box ::new ( item )
}
2019-06-16 14:59:11 -07:00
2021-11-21 01:02:59 -08:00
fn strlit ( s : & str ) -> ExpressionKind {
ExpressionKind ::StringLiteral { s : Rc ::new ( s . to_string ( ) ) , prefix : None }
}
2021-12-07 02:39:01 -08:00
fn stmt < K > ( kind : K ) -> Statement < K > {
2021-10-31 02:05:39 -07:00
Statement { location : Location ::default ( ) , id : ItemId ::default ( ) , kind }
2021-10-14 06:18:17 -07:00
}
2021-12-07 02:39:01 -08:00
fn exst ( kind : ExpressionKind ) -> Statement < StatementKind > {
2021-10-31 02:05:39 -07:00
Statement {
location : Location ::default ( ) ,
id : ItemId ::default ( ) ,
kind : StatementKind ::Expression ( expr ( kind ) ) ,
}
2021-10-14 17:42:04 -07:00
}
2021-12-07 02:39:01 -08:00
fn decl ( declaration : Declaration ) -> Statement < StatementKind > {
2021-10-31 02:05:39 -07:00
Statement {
location : Location ::default ( ) ,
id : ItemId ::default ( ) ,
kind : StatementKind ::Declaration ( declaration ) ,
}
2019-06-16 14:59:11 -07:00
}
2021-10-31 02:05:39 -07:00
2021-12-07 02:39:01 -08:00
fn fn_decl ( sig : Signature , stmts : Block ) -> Statement < StatementKind > {
2021-10-31 02:05:39 -07:00
Statement {
kind : StatementKind ::Declaration ( Declaration ::FuncDecl ( sig , stmts ) ) ,
location : Default ::default ( ) ,
id : Default ::default ( ) ,
}
2019-06-16 14:59:11 -07:00
}
2021-10-31 02:05:39 -07:00
fn expr_anno ( kind : ExpressionKind , anno : TypeIdentifier ) -> Expression {
Expression { id : ItemId ::default ( ) , kind , type_anno : Some ( anno ) }
}
fn expr ( kind : ExpressionKind ) -> Expression {
Expression { id : ItemId ::default ( ) , kind , type_anno : None }
}
fn binop ( sigil : & str , lhs : Expression , rhs : Expression ) -> Expression {
Expression {
id : Default ::default ( ) ,
type_anno : None ,
kind : ExpressionKind ::BinExp ( BinOp ::from_sigil ( sigil ) , Box ::new ( lhs ) , Box ::new ( rhs ) ) ,
}
}
fn prefixop ( sigil : & str , exp : Expression ) -> Expression {
Expression {
id : Default ::default ( ) ,
type_anno : None ,
kind : ExpressionKind ::PrefixExp ( PrefixOp ::from_sigil ( sigil ) , Box ::new ( exp ) ) ,
}
}
macro_rules ! qn {
( $( $component :ident ) , * ) = > {
2019-09-19 01:34:21 -07:00
{
2021-10-31 02:05:39 -07:00
let mut components = vec! [ ] ;
$(
components . push ( rc ( stringify! ( $component ) ) ) ;
) *
QualifiedName { components , id : Default ::default ( ) }
2019-09-19 01:34:21 -07:00
}
} ;
}
2021-10-31 02:05:39 -07:00
fn ty_simple ( name : & str ) -> TypeIdentifier {
TypeIdentifier ::Singleton ( TypeSingletonName { name : rc ( name ) , params : vec ! [ ] } )
2019-06-16 14:59:11 -07:00
}
2021-10-31 02:05:39 -07:00
2021-11-19 09:59:08 -08:00
macro_rules ! assert_ast {
2021-11-18 15:17:47 -08:00
( $input :expr , $statements :expr ) = > {
let mut parser = Parser ::new ( ) ;
let ast = parser . parse_comb ( $input ) ;
2021-11-20 11:04:56 -08:00
let ast2 = parser . parse_peg ( $input ) ;
2021-11-18 15:17:47 -08:00
let expected = AST { id : Default ::default ( ) , statements : $statements . into ( ) } ;
2021-11-20 11:04:56 -08:00
let ast = match ast {
Err ( err ) = > {
println! ( " Parse error: {} " , err . msg ) ;
panic! ( ) ;
2021-11-20 22:55:11 -08:00
}
2021-11-20 11:04:56 -08:00
Ok ( ast ) = > ast ,
} ;
assert_eq! ( ast , ast2 . unwrap ( ) ) ;
assert_eq! ( ast , expected ) ;
2021-11-07 03:13:35 -08:00
} ;
}
2021-11-19 23:04:00 -08:00
macro_rules ! assert_fail {
( $input :expr ) = > {
let mut parser = Parser ::new ( ) ;
2021-11-20 22:55:11 -08:00
let _err = parser . parse_comb ( $input ) . unwrap_err ( ) ;
2021-11-19 23:04:00 -08:00
} ;
2021-11-19 09:59:08 -08:00
( $input :expr , $failure :expr ) = > {
let mut parser = Parser ::new ( ) ;
let err = parser . parse_comb ( $input ) . unwrap_err ( ) ;
2021-11-19 20:43:37 -08:00
println! ( " assert_fail: {} " , err . msg ) ;
2021-11-19 09:59:08 -08:00
assert_eq! ( err . msg , $failure ) ;
} ;
}
2021-11-19 01:35:25 -08:00
macro_rules ! assert_expr {
2021-11-17 16:53:03 -08:00
( $input :expr , $correct :expr ) = > {
let mut parser = Parser ::new ( ) ;
2021-11-19 00:40:10 -08:00
let expr = parser . expression_comb ( $input . trim_start ( ) ) ;
2021-11-20 11:04:56 -08:00
let expr2 = parser . expression ( $input . trim_start ( ) ) ;
let expr = match expr {
Err ( err ) = > {
println! ( " Expression parse error: {} " , err . msg ) ;
panic! ( ) ;
2021-11-20 22:55:11 -08:00
}
2021-11-20 11:04:56 -08:00
Ok ( expr ) = > expr ,
} ;
assert_eq! ( expr , expr2 . unwrap ( ) ) ;
assert_eq! ( expr , $correct ) ;
2021-11-04 21:11:19 -07:00
} ;
2021-11-03 20:31:46 -07:00
}
2021-11-20 00:03:05 -08:00
macro_rules ! assert_fail_expr {
( $input :expr , $failure :expr ) = > {
let mut parser = Parser ::new ( ) ;
let _err = parser . expression_comb ( $input ) . unwrap_err ( ) ;
//TODO make real tests for failures
//assert_eq!(err.to_string(), $failure);
} ;
}
2021-11-20 23:00:19 -08:00
macro_rules ! assert_block {
( $input :expr , $correct :expr ) = > {
let mut parser = Parser ::new ( ) ;
let block = parser . block_comb ( $input ) ;
let block2 = parser . block ( $input ) ;
let block = match block {
Err ( err ) = > {
println! ( " Expression parse error: {} " , err . msg ) ;
panic! ( ) ;
}
Ok ( item ) = > item ,
} ;
assert_eq! ( block , block2 . unwrap ( ) ) ;
assert_eq! ( block , $correct ) ;
} ;
}
2021-10-31 02:05:39 -07:00
#[ test ]
fn basic_literals ( ) {
use ExpressionKind ::* ;
2021-11-19 01:35:25 -08:00
assert_expr! ( " .2 " , expr ( FloatLiteral ( 0.2 ) ) ) ;
assert_expr! ( " 8.1 " , expr ( FloatLiteral ( 8.1 ) ) ) ;
assert_expr! ( " 0b010 " , expr ( NatLiteral ( 2 ) ) ) ;
assert_expr! ( " 0b0_1_0 " , expr ( NatLiteral ( 2 ) ) ) ;
assert_expr! ( " 0xff " , expr ( NatLiteral ( 255 ) ) ) ;
assert_expr! ( " 0x032f " , expr ( NatLiteral ( 815 ) ) ) ;
2021-11-20 02:33:09 -08:00
assert_expr! ( " 0xf_f " , expr ( NatLiteral ( 255 ) ) ) ;
2021-11-19 01:35:25 -08:00
assert_expr! ( " false " , expr ( BoolLiteral ( false ) ) ) ;
assert_expr! ( " true " , expr ( BoolLiteral ( true ) ) ) ;
2021-11-13 13:45:52 -08:00
}
#[ test ]
fn string_literals ( ) {
use ExpressionKind ::* ;
2021-11-21 01:02:59 -08:00
assert_expr! ( r # """"# , expr ( strlit ( " " ) ) ) ;
assert_expr! ( r # ""hello""# , expr ( strlit ( " hello " ) ) ) ;
assert_expr! (
r # "b"some bytestring""# ,
expr ( StringLiteral { s : rc ( " some bytestring " ) , prefix : Some ( rc ( " b " ) ) } )
) ;
2021-11-21 01:54:34 -08:00
assert_expr! ( r # ""Do \n \" escapes work\t""# , expr ( strlit ( " Do \n \" escapes work \t " ) ) ) ;
2021-11-21 02:11:20 -08:00
assert_expr! ( r # ""Georgian letter jani \u{10ef}""# , expr ( strlit ( " Georgian letter jani ჯ " ) ) ) ;
2021-10-31 02:05:39 -07:00
}
#[ test ]
fn list_literals ( ) {
use ExpressionKind ::* ;
2021-11-19 01:35:25 -08:00
assert_expr! ( " [] " , expr ( ListLiteral ( vec! [ ] ) ) ) ;
assert_expr! ( " [1,2] " , expr ( ListLiteral ( vec! [ expr ( NatLiteral ( 1 ) ) , expr ( NatLiteral ( 2 ) ) , ] ) ) ) ;
assert_expr! ( " [1, /*no*/2] " , expr ( ListLiteral ( vec! [ expr ( NatLiteral ( 1 ) ) , expr ( NatLiteral ( 2 ) ) , ] ) ) ) ;
2021-11-13 01:42:49 -08:00
assert_fail_expr! ( " [1,,2] " , " some failure " ) ;
2021-10-31 02:05:39 -07:00
}
#[ test ]
fn binexps ( ) {
use ExpressionKind ::* ;
use StatementKind ::Expression ;
2021-11-19 01:35:25 -08:00
assert_expr! ( " 0xf_f+1 " , binop ( " + " , expr ( NatLiteral ( 255 ) ) , expr ( NatLiteral ( 1 ) ) ) ) ;
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-11-04 21:11:19 -07:00
" 3; 4; 4.3 " ,
vec! [
stmt ( Expression ( expr ( NatLiteral ( 3 ) ) ) ) ,
stmt ( Expression ( expr ( NatLiteral ( 4 ) ) ) ) ,
stmt ( Expression ( expr ( FloatLiteral ( 4.3 ) ) ) ) ,
]
2021-10-31 02:05:39 -07:00
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" 1 + 2 * 3 " ,
binop ( " + " , expr ( NatLiteral ( 1 ) ) , binop ( " * " , expr ( NatLiteral ( 2 ) ) , expr ( NatLiteral ( 3 ) ) ) )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" 1 * 2 + 3 " ,
binop ( " + " , binop ( " * " , expr ( NatLiteral ( 1 ) ) , expr ( NatLiteral ( 2 ) ) ) , expr ( NatLiteral ( 3 ) ) )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! ( " 1 && 2 " , binop ( " && " , expr ( NatLiteral ( 1 ) ) , expr ( NatLiteral ( 2 ) ) ) ) ;
assert_expr! (
2021-10-31 02:05:39 -07:00
" 1 + 2 * 3 + 4 " ,
binop (
" + " ,
binop ( " + " , expr ( NatLiteral ( 1 ) ) , binop ( " * " , expr ( NatLiteral ( 2 ) ) , expr ( NatLiteral ( 3 ) ) ) ) ,
expr ( NatLiteral ( 4 ) )
)
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" (1 + 2) * 3 " ,
binop ( " * " , binop ( " + " , expr ( NatLiteral ( 1 ) ) , expr ( NatLiteral ( 2 ) ) ) , expr ( NatLiteral ( 3 ) ) )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! ( " .1 + .2 " , binop ( " + " , expr ( FloatLiteral ( 0.1 ) ) , expr ( FloatLiteral ( 0.2 ) ) ) ) ;
assert_expr! ( " 1 / 2. " , binop ( " / " , expr ( NatLiteral ( 1 ) ) , expr ( FloatLiteral ( 2. ) ) ) ) ;
2021-10-31 02:05:39 -07:00
}
#[ test ]
fn prefix_exps ( ) {
use ExpressionKind ::* ;
2021-11-19 01:35:25 -08:00
assert_expr! ( " -3 " , prefixop ( " - " , expr ( NatLiteral ( 3 ) ) ) ) ;
assert_expr! ( " -0.2 " , prefixop ( " - " , expr ( FloatLiteral ( 0.2 ) ) ) ) ;
assert_expr! ( " !3 " , prefixop ( " ! " , expr ( NatLiteral ( 3 ) ) ) ) ;
assert_expr! ( " !t " , prefixop ( " ! " , expr ( Value ( qn! ( t ) ) ) ) ) ;
assert_expr! ( " a <- -b " , binop ( " <- " , expr ( Value ( qn! ( a ) ) ) , prefixop ( " - " , expr ( Value ( qn! ( b ) ) ) ) ) ) ;
assert_expr! ( " a <--b " , binop ( " <-- " , expr ( Value ( qn! ( a ) ) ) , expr ( Value ( qn! ( b ) ) ) ) ) ;
2021-10-31 02:05:39 -07:00
}
#[ test ]
fn operators ( ) {
use ExpressionKind ::* ;
2021-11-19 01:35:25 -08:00
assert_expr! ( " a <- 1 " , binop ( " <- " , expr ( Value ( qn! ( a ) ) ) , expr ( NatLiteral ( 1 ) ) ) ) ;
assert_expr! ( " a || 1 " , binop ( " || " , expr ( Value ( qn! ( a ) ) ) , expr ( NatLiteral ( 1 ) ) ) ) ;
assert_expr! ( " a <> 1 " , binop ( " <> " , expr ( Value ( qn! ( a ) ) ) , expr ( NatLiteral ( 1 ) ) ) ) ;
2021-10-31 02:05:39 -07:00
}
#[ test ]
fn accessors ( ) {
use ExpressionKind ::* ;
2021-11-19 01:35:25 -08:00
assert_expr! ( " a.b " , expr ( Access { name : rc ( " b " ) , expr : bx ( expr ( Value ( qn! ( a ) ) ) ) } ) ) ;
assert_expr! (
2021-10-31 02:05:39 -07:00
" a.b.c " ,
expr ( Access {
name : rc ( " c " ) ,
expr : bx ( expr ( Access { name : rc ( " b " ) , expr : bx ( expr ( Value ( qn! ( a ) ) ) ) } ) )
} )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" a.b.c(3) " ,
expr ( Call {
f : bx ( expr ( Access {
name : rc ( " c " ) ,
expr : bx ( expr ( Access { name : rc ( " b " ) , expr : bx ( expr ( Value ( qn! ( a ) ) ) ) } ) )
} ) ) ,
arguments : vec ! [ InvocationArgument ::Positional ( expr ( NatLiteral ( 3 ) ) ) ] ,
} )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" a.b().c " ,
expr ( Access {
name : rc ( " c " ) ,
expr : bx ( expr ( Call {
f : bx ( expr ( Access { name : rc ( " b " ) , expr : bx ( expr ( Value ( qn! ( a ) ) ) ) } ) ) ,
arguments : vec ! [ ]
} ) )
} )
) ;
}
#[ test ]
fn tuples ( ) {
use ExpressionKind ::* ;
2021-11-19 01:35:25 -08:00
assert_expr! ( " () " , expr ( TupleLiteral ( vec! [ ] ) ) ) ;
2021-11-21 01:02:59 -08:00
assert_expr! ( r # "("hella", 34)"# , expr ( TupleLiteral ( vec! [ expr ( strlit ( " hella " ) ) , expr ( NatLiteral ( 34 ) ) ] ) ) ) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
r # "(1+2, "slough")"# ,
expr ( TupleLiteral ( vec! [
binop ( " + " , expr ( NatLiteral ( 1 ) ) , expr ( NatLiteral ( 2 ) ) ) ,
2021-11-21 01:02:59 -08:00
expr ( strlit ( " slough " ) ) ,
2021-10-31 02:05:39 -07:00
] ) )
) ;
}
#[ test ]
fn identifiers ( ) {
use ExpressionKind ::* ;
2021-11-19 01:35:25 -08:00
assert_expr! ( " a " , expr ( Value ( qn! ( a ) ) ) ) ;
assert_expr! ( " some_value " , expr ( Value ( qn! ( some_value ) ) ) ) ;
assert_expr! ( " alpha::beta::gamma " , expr ( Value ( qn! ( alpha , beta , gamma ) ) ) ) ;
assert_expr! ( " a + b " , binop ( " + " , expr ( Value ( qn! ( a ) ) ) , expr ( Value ( qn! ( b ) ) ) ) ) ;
assert_expr! ( " None " , expr ( Value ( qn! ( None ) ) ) ) ;
assert_expr! (
2021-10-31 02:05:39 -07:00
" thing::item::call() " ,
expr ( Call { f : bx ( expr ( Value ( qn! ( thing , item , call ) ) ) ) , arguments : vec ! [ ] } )
) ;
}
#[ test ]
fn named_struct ( ) {
use ExpressionKind ::* ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" Pandas { a: x + y } " ,
expr ( NamedStruct {
name : qn ! ( Pandas ) ,
fields : vec ! [ ( rc ( " a " ) , binop ( " + " , expr ( Value ( qn! ( x ) ) ) , expr ( Value ( qn! ( y ) ) ) ) ) ]
} )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" Trousers { a:1, b:800 } " ,
expr ( NamedStruct {
name : qn ! ( Trousers ) ,
fields : vec ! [ ( rc ( " a " ) , expr ( NatLiteral ( 1 ) ) ) , ( rc ( " b " ) , expr ( NatLiteral ( 800 ) ) ) ]
} )
) ;
}
#[ test ]
fn index ( ) {
use ExpressionKind ::* ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-11-04 22:31:29 -07:00
" armok[b,c] " ,
2021-10-31 02:05:39 -07:00
expr ( Index {
2021-11-04 22:31:29 -07:00
indexee : bx ( expr ( Value ( qn! ( armok ) ) ) ) ,
2021-10-31 02:05:39 -07:00
indexers : vec ! [ expr ( Value ( qn! ( b ) ) ) , expr ( Value ( qn! ( c ) ) ) ]
} )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-11-04 22:31:29 -07:00
" a[b,c][1] " ,
expr ( Index {
indexee : bx ( expr ( Index {
indexee : bx ( expr ( Value ( qn! ( a ) ) ) ) ,
indexers : vec ! [ expr ( Value ( qn! ( b ) ) ) , expr ( Value ( qn! ( c ) ) ) ]
} ) ) ,
indexers : vec ! [ expr ( NatLiteral ( 1 ) ) ]
} )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" perspicacity()[a] " ,
expr ( Index {
indexee : bx ( expr ( Call { f : bx ( expr ( Value ( qn! ( perspicacity ) ) ) ) , arguments : vec ! [ ] } ) ) ,
indexers : vec ! [ expr ( Value ( qn! ( a ) ) ) ]
} )
) ;
let a = expr ( Call { f : bx ( expr ( Value ( qn! ( a ) ) ) ) , arguments : vec ! [ ] } ) ;
let b = expr ( Index { indexee : bx ( a ) , indexers : vec ! [ expr ( Value ( qn! ( b ) ) ) ] } ) ;
let c = expr ( Call { f : bx ( b ) , arguments : vec ! [ ] } ) ;
let d = expr ( Index { indexee : bx ( c ) , indexers : vec ! [ expr ( Value ( qn! ( d ) ) ) ] } ) ;
2021-11-19 01:35:25 -08:00
assert_expr! ( " a()[b]()[d] " , d ) ;
2021-10-31 02:05:39 -07:00
2021-11-13 01:42:49 -08:00
assert_fail_expr! ( " a[] " , " Empty index expressions are not allowed " ) ;
2021-10-31 02:05:39 -07:00
}
#[ test ]
fn while_expression ( ) {
use ExpressionKind ::* ;
2021-11-18 21:02:33 -08:00
// assert_expr_comb!("while { }", expr(WhileExpression { condition: None, body: Block::default() }));
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" while a == b { } " ,
expr ( WhileExpression {
condition : Some ( bx ( binop ( " == " , expr ( Value ( qn! ( a ) ) ) , expr ( Value ( qn! ( b ) ) ) ) ) ) ,
body : Block ::default ( )
} )
) ;
}
#[ test ]
fn for_expression ( ) {
use ExpressionKind ::* ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" for { a <- garodzny::maybeValue } return 1 " ,
expr ( ForExpression {
2021-11-22 01:59:05 -08:00
enumerators : vec ! [ Enumerator {
identifier : rc ( " a " ) ,
assignment : false ,
generator : expr ( Value ( qn! ( garodzny , maybeValue ) ) )
} ] ,
2021-10-31 02:05:39 -07:00
body : bx ( ForBody ::MonadicReturn ( expr ( NatLiteral ( 1 ) ) ) )
} )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-11-06 20:33:33 -07:00
" for n <- someRange { f(n) ; } " ,
2021-10-31 02:05:39 -07:00
expr ( ForExpression {
2021-11-22 01:59:05 -08:00
enumerators : vec ! [ Enumerator {
identifier : rc ( " n " ) ,
assignment : false ,
generator : expr ( Value ( qn! ( someRange ) ) )
} ] ,
2021-10-31 02:05:39 -07:00
body : bx ( ForBody ::StatementBlock (
vec! [ stmt ( StatementKind ::Expression ( expr ( Call {
f : bx ( expr ( Value ( qn! ( f ) ) ) ) ,
arguments : vec ! [ InvocationArgument ::Positional ( expr ( Value ( qn! ( n ) ) ) ) ] ,
} ) ) ) , ]
. into ( )
) ) ,
} )
) ;
}
#[ test ]
fn lambda_expressions ( ) {
use ExpressionKind ::* ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
r # "\(x) { x + 1}"# ,
expr ( Lambda {
params : vec ! [ FormalParam { name : rc ! ( x ) , anno : None , default : None } ] ,
type_anno : None ,
body :
vec! [ stmt ( StatementKind ::Expression ( binop ( " + " , expr ( Value ( qn! ( x ) ) ) , expr ( NatLiteral ( 1 ) ) ) ) ) , ]
. into ( )
} )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
r # "\ (x: Int, y) { a;b;c;}"# ,
expr ( Lambda {
params : vec ! [
FormalParam { name : rc ! ( x ) , anno : Some ( ty_simple ( " Int " ) ) , default : None } ,
FormalParam { name : rc ! ( y ) , anno : None , default : None } ,
] ,
type_anno : None ,
body : vec ! [
stmt ( StatementKind ::Expression ( expr ( Value ( qn! ( a ) ) ) ) ) ,
stmt ( StatementKind ::Expression ( expr ( Value ( qn! ( b ) ) ) ) ) ,
stmt ( StatementKind ::Expression ( expr ( Value ( qn! ( c ) ) ) ) ) ,
]
. into ( )
} )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
r # "\(x){y}(1)"# ,
expr ( Call {
f : bx ( expr ( Lambda {
params : vec ! [ FormalParam { name : rc ! ( x ) , anno : None , default : None } , ] ,
type_anno : None ,
body : vec ! [ stmt ( StatementKind ::Expression ( expr ( Value ( qn! ( y ) ) ) ) ) , ] . into ( )
} ) ) ,
arguments : vec ! [ InvocationArgument ::Positional ( expr ( NatLiteral ( 1 ) ) ) ] ,
} )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
r # "\(x: Int): String { "q" }"# ,
expr ( Lambda {
params : vec ! [ FormalParam { name : rc ! ( x ) , anno : Some ( ty_simple ( " Int " ) ) , default : None } , ] ,
type_anno : Some ( TypeIdentifier ::Singleton ( TypeSingletonName {
name : rc ( " String " ) ,
params : vec ! [ ]
} ) ) ,
2021-11-21 01:02:59 -08:00
body : vec ! [ stmt ( StatementKind ::Expression ( expr ( strlit ( " q " ) ) ) ) , ] . into ( )
2021-10-31 02:05:39 -07:00
} )
) ;
}
#[ test ]
fn single_param_lambda ( ) {
use ExpressionKind ::* ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
r # "\x { x + 10 }"# ,
expr ( Lambda {
params : vec ! [ FormalParam { name : rc ! ( x ) , anno : None , default : None } , ] ,
type_anno : None ,
body : vec ! [ stmt ( StatementKind ::Expression ( binop (
" + " ,
expr ( Value ( qn! ( x ) ) ) ,
expr ( NatLiteral ( 10 ) )
) ) ) ]
. into ( )
} )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
r # "\x: Int { x + 10 }"# ,
expr ( Lambda {
params : vec ! [ FormalParam { name : rc ! ( x ) , anno : Some ( ty_simple ( " Int " ) ) , default : None } , ] ,
type_anno : None ,
body : vec ! [ stmt ( StatementKind ::Expression ( binop (
" + " ,
expr ( Value ( qn! ( x ) ) ) ,
expr ( NatLiteral ( 10 ) )
) ) ) ]
. into ( )
} )
) ;
}
#[ test ]
fn complex_lambdas ( ) {
use ExpressionKind ::* ;
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-11-21 02:23:50 -08:00
r #" fn wahoo() { let a = 10; \ (x) { x + a } }
2021-10-31 02:05:39 -07:00
wahoo ( ) ( 3 ) " #,
vec! [
fn_decl ( Signature { name : rc ( " wahoo " ) , operator : false , type_anno : None , params : vec ! [ ] } ,
vec! [
decl ( Declaration ::Binding {
name : rc ( " a " ) ,
constant : true ,
type_anno : None ,
expr : expr ( NatLiteral ( 10 ) )
} ) ,
stmt ( StatementKind ::Expression ( expr ( Lambda {
params : vec ! [
FormalParam { name : rc ( " x " ) , default : None , anno : None }
] ,
type_anno : None ,
body : vec ! [
stmt ( StatementKind ::Expression ( binop ( " + " , expr ( Value ( qn! ( x ) ) ) , expr ( Value ( qn! ( a ) ) ) ) ) ) ,
] . into ( )
} ) ) ) ,
] . into ( ) ) ,
stmt ( StatementKind ::Expression ( expr ( Call {
f : bx ( expr ( Call {
f : bx ( expr ( Value ( qn! ( wahoo ) ) ) ) ,
arguments : vec ! [ ] } ) ) ,
arguments : vec ! [
InvocationArgument ::Positional ( expr ( NatLiteral ( 3 ) ) )
]
} ) ) )
]
} ;
}
#[ test ]
fn reserved_words ( ) {
2021-11-21 01:02:59 -08:00
//TODO assert a good error message for this
assert_fail! ( " module::item::call() " ) ;
2021-11-19 18:15:02 -08:00
assert_expr! ( " modulek::item " , expr ( ExpressionKind ::Value ( qn! ( modulek , item ) ) ) ) ;
2021-10-31 02:05:39 -07:00
}
#[ test ]
fn type_annotations ( ) {
use ExpressionKind ::* ;
use TypeIdentifier ::* ;
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-10-31 02:05:39 -07:00
" let a = b : Int " ,
vec! [ decl ( Declaration ::Binding {
name : rc ( " a " ) ,
constant : true ,
type_anno : None ,
expr : expr_anno ( Value ( qn! ( b ) ) , Singleton ( TypeSingletonName { name : rc ( " Int " ) , params : vec ! [ ] } ) ) ,
} ) ]
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" a: Int " ,
expr_anno ( Value ( qn! ( a ) ) , Singleton ( TypeSingletonName { name : rc ( " Int " ) , params : vec ! [ ] } ) )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" a: Option<Int> " ,
expr_anno (
Value ( qn! ( a ) ) ,
Singleton ( TypeSingletonName {
name : rc ( " Option " ) ,
params : vec ! [ Singleton ( TypeSingletonName { name : rc ( " Int " ) , params : vec ! [ ] } ) ]
} )
)
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" a: KoreanBBQSpecifier<Kimchi, Option<Bulgogi> > " ,
expr_anno (
Value ( qn! ( a ) ) ,
Singleton ( TypeSingletonName {
name : rc ( " KoreanBBQSpecifier " ) ,
params : vec ! [
Singleton ( TypeSingletonName { name : rc ( " Kimchi " ) , params : vec ! [ ] } ) ,
Singleton ( TypeSingletonName {
name : rc ( " Option " ) ,
params : vec ! [ Singleton ( TypeSingletonName { name : rc ( " Bulgogi " ) , params : vec ! [ ] } ) ]
} )
]
} )
)
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" a: (Int, Yolo<a>) " ,
expr_anno (
Value ( qn! ( a ) ) ,
Tuple ( vec! [
Singleton ( TypeSingletonName { name : rc ( " Int " ) , params : vec ! [ ] } ) ,
Singleton ( TypeSingletonName {
name : rc ( " Yolo " ) ,
params : vec ! [ Singleton ( TypeSingletonName { name : rc ( " a " ) , params : vec ! [ ] } ) ]
} ) ,
] ) ,
)
) ;
}
#[ test ]
fn type_declarations ( ) {
use Declaration ::TypeDecl ;
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:05:39 -07:00
" type Alpha = Alpha " , vec! [
decl ( TypeDecl {
name : TypeSingletonName { name : rc ( " Alpha " ) , params : vec ! [ ] } ,
mutable : false ,
2021-10-31 02:30:38 -07:00
body : TypeBody ::Variants ( vec! [
2021-10-31 02:05:39 -07:00
Variant {
id : Default ::default ( ) ,
name : rc ( " Alpha " ) ,
kind : VariantKind ::UnitStruct
}
] )
} )
]
} ;
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-10-31 02:05:39 -07:00
" type mut Kuah = Kuah " ,
decl ( TypeDecl {
name : TypeSingletonName { name : rc ( " Kuah " ) , params : vec ! [ ] } ,
mutable : true ,
2021-10-31 02:30:38 -07:00
body : TypeBody ::Variants ( vec! [ Variant {
2021-10-31 02:05:39 -07:00
id : Default ::default ( ) ,
name : rc ( " Kuah " ) ,
kind : VariantKind ::UnitStruct
} ] )
} )
) ;
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:30:38 -07:00
" type Alpha = Alpha { a: Int, b: Int } " ,
vec! [ decl ( TypeDecl {
name : TypeSingletonName { name : rc ( " Alpha " ) , params : vec ! [ ] } ,
mutable : false ,
body : TypeBody ::Variants ( vec! [
Variant {
id : Default ::default ( ) ,
name : rc ( " Alpha " ) ,
kind : VariantKind ::Record ( vec! [
( rc ( " a " ) , ty_simple ( " Int " ) ) ,
( rc ( " b " ) , ty_simple ( " Int " ) )
] )
}
] )
} ) ]
} ;
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:30:38 -07:00
" type Alpha = { a: Int, b: Int } " ,
vec! [ decl ( TypeDecl {
name : TypeSingletonName { name : rc ( " Alpha " ) , params : vec ! [ ] } ,
mutable : false ,
2021-11-18 18:24:06 -08:00
body : TypeBody ::ImmediateRecord { id : Default ::default ( ) , fields : vec ! [
2021-10-31 02:30:38 -07:00
( rc ( " a " ) , ty_simple ( " Int " ) ) ,
( rc ( " b " ) , ty_simple ( " Int " ) )
2021-11-18 18:24:06 -08:00
] }
2021-10-31 02:30:38 -07:00
} ) ]
} ;
2021-10-31 02:05:39 -07:00
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-10-31 02:05:39 -07:00
" type Option<T> = None | Some(T) " ,
vec! [ decl ( TypeDecl {
name : TypeSingletonName {
name : rc ( " Option " ) ,
params : vec ! [ TypeIdentifier ::Singleton ( TypeSingletonName { name : rc ( " T " ) , params : vec ! [ ] } ) ]
} ,
mutable : false ,
2021-10-31 02:30:38 -07:00
body : TypeBody ::Variants ( vec! [
2021-10-31 02:05:39 -07:00
Variant { id : Default ::default ( ) , name : rc ( " None " ) , kind : VariantKind ::UnitStruct } ,
Variant {
id : Default ::default ( ) ,
name : rc ( " Some " ) ,
kind : VariantKind ::TupleStruct ( vec! [ TypeIdentifier ::Singleton ( TypeSingletonName {
name : rc ( " T " ) ,
params : vec ! [ ]
} ) ] )
} ,
] )
} ) ]
) ;
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-10-31 02:05:39 -07:00
" type alias Alpha = Beta " ,
decl ( Declaration ::TypeAlias { alias : rc ( " Alpha " ) , original : rc ( " Beta " ) } )
) ;
2021-11-19 09:59:08 -08:00
assert_ast! ( " type Complex<T, U> = Unit | Record { field: AnotherType<Bool>, field2: (Nat, Int), field3: T } | Tuple(Int, (String, T)) " ,
2021-10-31 02:05:39 -07:00
decl ( TypeDecl {
name : TypeSingletonName { name : rc ( " Complex " ) , params : vec ! [
TypeIdentifier ::Singleton ( TypeSingletonName { name : rc ( " T " ) , params : vec ! [ ] } ) ,
TypeIdentifier ::Singleton ( TypeSingletonName { name : rc ( " U " ) , params : vec ! [ ] } ) ,
] } ,
mutable : false ,
2021-10-31 02:30:38 -07:00
body : TypeBody ::Variants ( vec! [
2021-10-31 02:05:39 -07:00
Variant { id : Default ::default ( ) , name : rc ( " Unit " ) , kind : VariantKind ::UnitStruct } ,
Variant { id : Default ::default ( ) , name : rc ( " Record " ) , kind : VariantKind ::Record (
vec! [
( rc ( " field " ) , TypeIdentifier ::Singleton ( TypeSingletonName { name : rc ( " AnotherType " ) , params : vec ! [ TypeIdentifier ::Singleton ( TypeSingletonName { name : rc ( " Bool " ) , params : vec ! [ ] } ) ] } ) ) ,
( rc ( " field2 " ) , TypeIdentifier ::Tuple ( vec! [
TypeIdentifier ::Singleton ( TypeSingletonName { name : rc ( " Nat " ) , params : vec ! [ ] } ) ,
TypeIdentifier ::Singleton ( TypeSingletonName { name : rc ( " Int " ) , params : vec ! [ ] } ) ,
]
) ) ,
( rc ( " field3 " ) , TypeIdentifier ::Singleton ( TypeSingletonName { name : rc ( " T " ) , params : vec ! [ ] } ) ) ,
]
) } ,
Variant { id : Default ::default ( ) , name : rc ( " Tuple " ) , kind : VariantKind ::TupleStruct (
vec! [
TypeIdentifier ::Singleton ( TypeSingletonName { name : rc ( " Int " ) , params : vec ! [ ] } ) ,
TypeIdentifier ::Tuple ( vec! [
TypeIdentifier ::Singleton ( TypeSingletonName { name : rc ( " String " ) , params : vec ! [ ] } ) ,
TypeIdentifier ::Singleton ( TypeSingletonName { name : rc ( " T " ) , params : vec ! [ ] } ) ,
] )
]
) } ,
] ) ,
} ) ) ;
2019-06-16 14:59:11 -07:00
}
2021-10-31 02:05:39 -07:00
#[ test ]
fn declarations ( ) {
use ExpressionKind ::* ;
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-10-31 02:05:39 -07:00
" let q_q = Yolo::Swaggins " ,
vec! [ decl ( Declaration ::Binding {
name : rc ( " q_q " ) ,
constant : true ,
type_anno : None ,
expr : expr ( Value ( qn! ( Yolo , Swaggins ) ) )
} ) ]
) ;
}
#[ test ]
fn bindings ( ) {
use ExpressionKind ::* ;
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-10-31 02:05:39 -07:00
" let mut a = 10 " ,
vec! [ decl ( Declaration ::Binding {
name : rc ( " a " ) ,
constant : false ,
type_anno : None ,
expr : expr ( NatLiteral ( 10 ) ) ,
} ) ]
) ;
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-10-31 02:05:39 -07:00
" let a = 2 + a " ,
vec! [ stmt ( StatementKind ::Declaration ( Declaration ::Binding {
name : rc ( " a " ) ,
constant : true ,
type_anno : None ,
expr : binop ( " + " , expr ( NatLiteral ( 2 ) ) , expr ( Value ( qn! ( a ) ) ) ) ,
} ) ) ]
) ;
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-10-31 02:05:39 -07:00
" let a: Nat = 2 " ,
vec! [ stmt ( StatementKind ::Declaration ( Declaration ::Binding {
name : rc ( " a " ) ,
constant : true ,
type_anno : Some ( TypeIdentifier ::Singleton ( TypeSingletonName { name : rc ( " Nat " ) , params : vec ! [ ] } ) ) ,
expr : expr ( NatLiteral ( 2 ) ) ,
} ) ) ]
) ;
}
#[ test ]
fn functions ( ) {
use ExpressionKind ::* ;
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-10-31 02:05:39 -07:00
" fn oi() " ,
vec! [ stmt ( StatementKind ::Declaration ( Declaration ::FuncSig ( Signature {
name : rc ( " oi " ) ,
operator : false ,
params : vec ! [ ] ,
type_anno : None
} ) ) ) ]
) ;
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-10-31 02:05:39 -07:00
" oi() " ,
vec! [ stmt ( StatementKind ::Expression ( expr ( Call { f : bx ( expr ( Value ( qn! ( oi ) ) ) ) , arguments : vec ! [ ] } ) ) ) ]
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" oi(a, 2+2) " ,
expr ( Call {
f : bx ( expr ( Value ( qn! ( oi ) ) ) ) ,
arguments : vec ! [
InvocationArgument ::Positional ( expr ( Value ( qn! ( a ) ) ) ) ,
InvocationArgument ::Positional ( binop ( " + " , expr ( NatLiteral ( 2 ) ) , expr ( NatLiteral ( 2 ) ) ) ) ,
]
} )
) ;
2021-11-20 19:42:50 -08:00
let err_msg = " 0: at line 1, in Alpha: \n a(b,,c) \n ^ \n \n 1: at line 1, in Alt: \n a(b,,c) \n ^ \n \n 2: at line 1, in token: \n a(b,,c) \n ^ \n \n 3: at line 1, in identifier-expr: \n a(b,,c) \n ^ \n \n 4: at line 1, in Alt: \n a(b,,c) \n ^ \n \n 5: at line 1, in primary-expr: \n a(b,,c) \n ^ \n \n 6: at line 1, in extended-expr: \n a(b,,c) \n ^ \n \n 7: at line 1, in prefix-expr: \n a(b,,c) \n ^ \n \n 8: at line 1, in expression-kind: \n a(b,,c) \n ^ \n \n 9: at line 1, in Alt: \n a(b,,c) \n ^ \n \n 10: at line 1, in invocation-argument: \n a(b,,c) \n ^ \n \n 11: at line 1, in call-part: \n a(b,,c) \n ^ \n \n 12: at line 1, in extended-expr: \n a(b,,c) \n ^ \n \n 13: at line 1, in prefix-expr: \n a(b,,c) \n ^ \n \n 14: at line 1, in expression-kind: \n a(b,,c) \n ^ \n \n 15: at line 1, in Parsing-statement: \n a(b,,c) \n ^ \n \n 16: at line 1, in AST: \n a(b,,c) \n ^ \n \n " ;
2021-11-19 23:04:00 -08:00
assert_fail! ( " a(b,,c) " , err_msg ) ;
2021-10-31 02:05:39 -07:00
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-10-31 02:05:39 -07:00
" fn a(b, c: Int): Int " ,
vec! [ stmt ( StatementKind ::Declaration ( Declaration ::FuncSig ( Signature {
name : rc ( " a " ) ,
operator : false ,
params : vec ! [
FormalParam { name : rc ( " b " ) , default : None , anno : None } ,
FormalParam {
name : rc ( " c " ) ,
default : None ,
anno : Some ( TypeIdentifier ::Singleton ( TypeSingletonName {
name : rc ( " Int " ) ,
params : vec ! [ ]
} ) ) ,
} ,
] ,
type_anno : Some ( TypeIdentifier ::Singleton ( TypeSingletonName { name : rc ( " Int " ) , params : vec ! [ ] } ) ) ,
} ) ) ) ]
) ;
2021-11-11 23:41:51 -08:00
let source = r #"
fn some_function ( ) {
} " #;
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-11-12 01:13:13 -08:00
source ,
vec! [ fn_decl (
Signature { name : rc ( " some_function " ) , operator : false , type_anno : None , params : vec ! [ ] } ,
2021-11-11 23:41:51 -08:00
vec! [ ] . into ( )
2021-11-12 01:13:13 -08:00
) ]
) ;
2021-10-31 02:05:39 -07:00
}
2021-11-20 23:56:53 -08:00
#[ test ]
fn custom_operator ( ) {
let source = " fn (!!)(lhs,rhs) " ;
assert_ast! (
source ,
vec! [ stmt ( StatementKind ::Declaration ( Declaration ::FuncSig ( Signature {
name : rc ( " !! " ) ,
operator : true ,
params : vec ! [
FormalParam { name : rc ( " lhs " ) , default : None , anno : None } ,
FormalParam { name : rc ( " rhs " ) , default : None , anno : None } ,
] ,
type_anno : None
} ) ) ) ]
) ;
}
2021-11-02 21:03:48 -07:00
#[ test ]
fn max_function_params ( ) {
let mut buf = " fn longfunc( " . to_string ( ) ;
2021-11-21 03:00:19 -08:00
for n in 0 .. 255 {
2021-11-02 21:03:48 -07:00
write! ( buf , " a{}, " , n ) . unwrap ( ) ;
}
2021-11-21 03:00:19 -08:00
write! ( buf , " a256 " ) . unwrap ( ) ;
2021-11-02 21:03:48 -07:00
write! ( buf , " ) {{ return 20 }} " ) . unwrap ( ) ;
2021-11-19 23:04:00 -08:00
//TODO need to create a good, custom error message for this case
2021-11-21 03:00:19 -08:00
//assert_fail!(&buf, "A function cannot have more than 255 arguments");
2021-11-19 23:04:00 -08:00
assert_fail! ( & buf ) ;
2021-11-22 00:14:21 -08:00
let mut buf = r # "\("# . to_string ( ) ;
for n in 0 .. 255 {
write! ( buf , " a{}, " , n ) . unwrap ( ) ;
}
write! ( buf , " a256 " ) . unwrap ( ) ;
write! ( buf , " ) {{ return 10 }} " ) . unwrap ( ) ;
assert_fail! ( & buf ) ;
2021-11-02 21:03:48 -07:00
}
2021-10-31 02:05:39 -07:00
#[ test ]
fn functions_with_different_whitespace ( ) {
use ExpressionKind ::* ;
let a = " fn a(x) { x() } " ;
let b = " fn a(x) { \n x() } " ;
let c = r #"
fn a ( x ) {
x ( )
}
" #;
for item in [ a , b , c ] . iter ( ) {
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-10-31 02:05:39 -07:00
item ,
vec! [ fn_decl (
Signature {
name : rc ( " a " ) ,
operator : false ,
type_anno : None ,
params : vec ! [ FormalParam { name : rc ( " x " ) , default : None , anno : None } ]
} ,
vec! [ stmt ( StatementKind ::Expression ( expr ( Call {
f : bx ( expr ( Value ( qn! ( x ) ) ) ) ,
arguments : vec ! [ ] ,
} ) ) ) ]
. into ( )
) ]
) ;
2019-06-16 14:59:11 -07:00
}
}
2021-10-31 02:05:39 -07:00
#[ test ]
fn functions_with_default_args ( ) {
use ExpressionKind ::* ;
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-10-31 02:05:39 -07:00
" fn func(x: Int, y: Int = 4) { } " ,
vec! [ fn_decl (
Signature {
name : rc ( " func " ) ,
operator : false ,
type_anno : None ,
params : vec ! [
FormalParam { name : rc ( " x " ) , anno : Some ( ty_simple ( " Int " ) ) , default : None } ,
FormalParam {
name : rc ( " y " ) ,
anno : Some ( ty_simple ( " Int " ) ) ,
default : Some ( expr ( NatLiteral ( 4 ) ) )
} ,
] ,
} ,
vec! [ ] . into ( )
) ]
) ;
}
#[ test ]
fn interface ( ) {
let glue = TypeIdentifier ::Singleton ( TypeSingletonName { name : rc ( " Glue " ) , params : vec ! [ ] } ) ;
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-10-31 02:05:39 -07:00
" interface Unglueable { fn unglue(a: Glue); fn mar(): Glue } " ,
vec! [ decl ( Declaration ::Interface {
name : rc ( " Unglueable " ) ,
signatures : vec ! [
Signature {
name : rc ( " unglue " ) ,
operator : false ,
params : vec ! [ FormalParam { name : rc ( " a " ) , default : None , anno : Some ( glue . clone ( ) ) } , ] ,
type_anno : None ,
} ,
Signature { name : rc ( " mar " ) , operator : false , params : vec ! [ ] , type_anno : Some ( glue ) } ,
] ,
} ) ]
) ;
}
2019-06-16 14:59:11 -07:00
#[ test ]
2021-10-31 02:05:39 -07:00
fn impls ( ) {
2021-11-11 22:00:04 -08:00
use Declaration ::{ FuncDecl , Impl } ;
let block = vec! [
2021-12-07 02:39:01 -08:00
stmt ( FuncDecl (
2021-11-12 01:13:13 -08:00
Signature { name : rc ( " yolo " ) , operator : false , params : vec ! [ ] , type_anno : None } ,
vec! [ ] . into ( ) ,
2021-12-07 02:39:01 -08:00
) ) ,
stmt ( FuncDecl (
2021-11-12 01:13:13 -08:00
Signature { name : rc ( " swagg " ) , operator : false , params : vec ! [ ] , type_anno : None } ,
vec! [ ] . into ( ) ,
2021-12-07 02:39:01 -08:00
) ) ,
2021-11-11 22:00:04 -08:00
] ;
2021-10-31 02:05:39 -07:00
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-11-11 22:00:04 -08:00
" impl Heh { fn yolo() { }; fn swagg() { } } " ,
2021-11-12 01:13:13 -08:00
vec! [ decl ( Impl { type_name : ty_simple ( " Heh " ) , interface_name : None , block : block . clone ( ) } ) ]
2021-10-31 02:05:39 -07:00
) ;
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-11-21 02:23:50 -08:00
" impl Heh<X> { fn yolo() { }; fn swagg() { }; } " ,
2021-10-31 02:05:39 -07:00
vec! [ decl ( Impl {
type_name : TypeIdentifier ::Singleton ( TypeSingletonName {
name : rc ( " Heh " ) ,
params : vec ! [ ty_simple ( " X " ) ]
} ) ,
interface_name : None ,
2021-11-11 22:00:04 -08:00
block : block . clone ( ) ,
2021-10-31 02:05:39 -07:00
} ) ]
) ;
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-11-11 22:00:04 -08:00
" impl Heh for Saraz { fn yolo() {}; fn swagg() {} } " ,
2021-10-31 02:05:39 -07:00
vec! [ decl ( Impl {
type_name : ty_simple ( " Saraz " ) ,
interface_name : Some ( TypeSingletonName { name : rc ( " Heh " ) , params : vec ! [ ] } ) ,
2021-11-11 22:00:04 -08:00
block : block . clone ( ) ,
2021-10-31 02:05:39 -07:00
} ) ]
) ;
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-10-31 02:05:39 -07:00
" impl Heh<T> for (Int, Codepoint) {} " ,
vec! [ decl ( Impl {
type_name : TypeIdentifier ::Tuple ( vec! [ ty_simple ( " Int " ) , ty_simple ( " Codepoint " ) ] ) ,
interface_name : Some ( TypeSingletonName { name : rc ( " Heh " ) , params : vec ! [ ty_simple ( " T " ) ] } ) ,
block : vec ! [ ]
} ) ]
) ;
}
#[ test ]
fn annotations ( ) {
use ExpressionKind ::* ;
2021-11-02 16:56:12 -07:00
let func = decl ( Declaration ::FuncDecl (
2021-11-02 14:40:28 -07:00
Signature { name : rc ( " some_function " ) , operator : false , params : vec ! [ ] , type_anno : None } ,
vec! [ ] . into ( ) ,
2021-11-02 16:56:12 -07:00
) ) ;
2021-11-02 14:40:28 -07:00
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:05:39 -07:00
r #"
@ test_annotation
fn some_function ( ) {
} " #,
vec! [ decl ( Declaration ::Annotation {
name : rc ( " test_annotation " ) ,
2021-11-02 14:40:28 -07:00
arguments : vec ! [ ] ,
inner : bx ( func . clone ( ) ) ,
2019-10-10 18:17:59 -07:00
} ) ,
2021-10-31 02:05:39 -07:00
]
} ;
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:05:39 -07:00
r #"
@ test_annotation ( some , value )
2021-11-02 14:40:28 -07:00
@ another_annotation
2021-10-31 02:05:39 -07:00
fn some_function ( ) {
2019-06-16 14:59:11 -07:00
2021-10-31 02:05:39 -07:00
} " #,
vec! [ decl ( Declaration ::Annotation {
name : rc ( " test_annotation " ) ,
2021-11-02 14:40:28 -07:00
arguments : vec ! [ expr ( Value ( qn! ( some ) ) ) , expr ( Value ( qn! ( value ) ) ) ] ,
2021-11-02 16:56:12 -07:00
inner : bx ( decl ( Declaration ::Annotation {
2021-11-02 14:40:28 -07:00
name : rc ( " another_annotation " ) , arguments : vec ! [ ] , inner : bx ( func )
2021-11-02 16:56:12 -07:00
} ) )
2019-10-10 18:17:59 -07:00
} ) ,
2021-10-31 02:05:39 -07:00
]
} ;
}
#[ test ]
fn modules ( ) {
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:05:39 -07:00
r #"
module ephraim {
let mut a = 10
fn nah ( ) { 33 }
}
" #,
2021-11-02 18:34:15 -07:00
vec! [ stmt ( StatementKind ::Declaration ( Declaration ::Module {
2021-10-31 02:05:39 -07:00
name : rc ( " ephraim " ) ,
2021-11-02 18:34:15 -07:00
items : vec ! [
2021-10-31 02:05:39 -07:00
decl ( Declaration ::Binding {
name : rc ( " a " ) , constant : false , type_anno : None ,
expr : expr ( ExpressionKind ::NatLiteral ( 10 ) )
} ) ,
fn_decl ( Signature { name : rc ( " nah " ) , operator : false , params : vec ! [ ] , type_anno : None } ,
vec! [ stmt ( StatementKind ::Expression ( expr ( ExpressionKind ::NatLiteral ( 33 ) ) ) ) ] . into ( ) ) ,
] . into ( )
} ) ) ]
} ;
}
2019-06-16 14:59:11 -07:00
2021-10-31 02:05:39 -07:00
#[ test ]
fn imports ( ) {
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:05:39 -07:00
" import harbinger::draughts::Norgleheim " ,
vec! [ stmt ( StatementKind ::Import ( ImportSpecifier {
id : ItemId ::default ( ) ,
path_components : vec ! [ rc ( " harbinger " ) , rc ( " draughts " ) , rc ( " Norgleheim " ) ] ,
imported_names : ImportedNames ::LastOfPath
} ) ) ]
} ;
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:05:39 -07:00
" import harbinger::draughts::{Norgleheim, Xraksenlaigar} " ,
vec! [ stmt ( StatementKind ::Import ( ImportSpecifier {
id : ItemId ::default ( ) ,
path_components : vec ! [ rc ( " harbinger " ) , rc ( " draughts " ) ] ,
imported_names : ImportedNames ::List ( vec! [
rc ( " Norgleheim " ) , rc ( " Xraksenlaigar " ) ] )
} ) ) ]
} ;
2021-11-21 02:30:45 -08:00
assert_fail! ( " import bespouri::{} " ) ;
2021-10-31 02:05:39 -07:00
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:05:39 -07:00
" import bespouri::* " ,
vec! [ stmt ( StatementKind ::Import ( ImportSpecifier {
id : Default ::default ( ) ,
path_components : vec ! [ rc ( " bespouri " ) ] ,
imported_names : ImportedNames ::All ,
} ) ) ]
} ;
}
#[ test ]
fn if_exprs ( ) {
use ExpressionKind ::* ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" if a() then { tuah(); } " ,
expr ( IfExpression {
discriminator : Some ( bx ( expr ( Call { f : bx ( expr ( Value ( qn! ( a ) ) ) ) , arguments : vec ! [ ] } ) ) ) ,
body : bx ( IfExpressionBody ::SimpleConditional {
then_case : vec ! [ exst ( Call { f : bx ( expr ( Value ( qn! ( tuah ) ) ) ) , arguments : vec ! [ ] } ) ] . into ( ) ,
else_case : None ,
} )
} )
) ;
2021-11-19 00:40:10 -08:00
//TODO add tests for named expressions
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" if a then b else c " ,
expr ( IfExpression {
discriminator : Some ( bx ( expr ( Value ( qn! ( a ) ) ) ) ) ,
body : bx ( IfExpressionBody ::SimpleConditional {
then_case : vec ! [ exst ( Value ( qn! ( b ) ) ) ] . into ( ) ,
else_case : Some ( vec! [ exst ( Value ( qn! ( c ) ) ) ] . into ( ) ) ,
} )
} )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-11-19 00:40:10 -08:00
r #" if true then {
2021-10-31 02:05:39 -07:00
let a = 10
2019-06-16 14:59:11 -07:00
b
} else {
c
} " #,
2021-10-31 02:05:39 -07:00
expr ( IfExpression {
discriminator : Some ( bx ( expr ( BoolLiteral ( true ) ) ) ) ,
body : bx ( IfExpressionBody ::SimpleConditional {
then_case : vec ! [
decl ( Declaration ::Binding {
name : rc ( " a " ) ,
constant : true ,
type_anno : None ,
expr : expr ( NatLiteral ( 10 ) )
} ) ,
exst ( Value ( qn! ( b ) ) ) ,
]
. into ( ) ,
else_case : Some ( vec! [ exst ( Value ( qn! ( c ) ) ) , ] . into ( ) )
} )
} )
) ;
}
2019-06-16 14:59:11 -07:00
2021-10-31 02:05:39 -07:00
#[ test ]
fn pattern_matching ( ) {
use ExpressionKind ::* ;
2019-06-16 14:59:11 -07:00
2021-10-31 02:05:39 -07:00
for item in [ " if x is Some(a) then { 4 } else { 9 } " , " if x is Some(a) then 4 else 9 " ] {
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
item ,
expr ( IfExpression {
discriminator : Some ( bx ( expr ( Value ( qn! ( x ) ) ) ) ) ,
body : bx ( IfExpressionBody ::SimplePatternMatch {
pattern : Pattern ::TupleStruct ( qn! ( Some ) , vec! [ Pattern ::VarOrName ( qn! ( a ) ) ] ) ,
then_case : vec ! [ exst ( NatLiteral ( 4 ) ) ] . into ( ) ,
else_case : Some ( vec! [ exst ( NatLiteral ( 9 ) ) ] . into ( ) ) ,
} )
} )
) ;
}
2019-06-16 14:59:11 -07:00
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" if x is Something { a, b: x } then { 4 } else { 9 } " ,
expr ( IfExpression {
discriminator : Some ( bx ( expr ( Value ( qn! ( x ) ) ) ) ) ,
body : bx ( IfExpressionBody ::SimplePatternMatch {
pattern : Pattern ::Record (
qn! ( Something ) ,
2021-11-01 13:46:38 -07:00
vec! [ ( rc ( " a " ) , Pattern ::VarOrName ( qn! ( a ) ) ) , ( rc ( " b " ) , Pattern ::VarOrName ( qn! ( x ) ) ) ]
2021-10-31 02:05:39 -07:00
) ,
then_case : vec ! [ exst ( NatLiteral ( 4 ) ) ] . into ( ) ,
else_case : Some ( vec! [ exst ( NatLiteral ( 9 ) ) ] . into ( ) ) ,
} )
} )
) ;
2019-06-16 14:59:11 -07:00
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" if x is -1 then 1 else 2 " ,
expr ( IfExpression {
discriminator : Some ( bx ( expr ( Value ( qn! ( x ) ) ) ) ) ,
body : bx ( IfExpressionBody ::SimplePatternMatch {
pattern : Pattern ::Literal ( PatternLiteral ::NumPattern { neg : true , num : NatLiteral ( 1 ) } ) ,
then_case : vec ! [ exst ( NatLiteral ( 1 ) ) ] . into ( ) ,
else_case : Some ( vec! [ exst ( NatLiteral ( 2 ) ) ] . into ( ) ) ,
} )
} )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
" if x is true then 1 else 2 " ,
expr ( IfExpression {
discriminator : Some ( bx ( expr ( Value ( qn! ( x ) ) ) ) ) ,
body : bx ( IfExpressionBody ::SimplePatternMatch {
pattern : Pattern ::Literal ( PatternLiteral ::BoolPattern ( true ) ) ,
then_case : vec ! [ exst ( NatLiteral ( 1 ) ) ] . into ( ) ,
else_case : Some ( vec! [ exst ( NatLiteral ( 2 ) ) ] . into ( ) ) ,
} )
} )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-11-11 22:24:35 -08:00
" if x { is 1 then 5; else 20 } " ,
2021-10-31 02:05:39 -07:00
expr ( IfExpression {
discriminator : Some ( bx ( expr ( Value ( qn! ( x ) ) ) ) ) ,
body : bx ( IfExpressionBody ::CondList ( vec! [
ConditionArm {
condition : Condition ::Pattern ( Pattern ::Literal ( PatternLiteral ::NumPattern {
neg : false ,
num : NatLiteral ( 1 )
} ) ) ,
guard : None ,
body : vec ! [ exst ( NatLiteral ( 5 ) ) ] . into ( ) ,
} ,
ConditionArm {
condition : Condition ::Else ,
guard : None ,
body : vec ! [ exst ( NatLiteral ( 20 ) ) ] . into ( ) ,
} ,
] ) )
} )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! (
2021-10-31 02:05:39 -07:00
r # "if x is "gnosticism" then 1 else 2"# ,
expr ( IfExpression {
discriminator : Some ( bx ( expr ( Value ( qn! ( x ) ) ) ) ) ,
body : bx ( IfExpressionBody ::SimplePatternMatch {
pattern : Pattern ::Literal ( PatternLiteral ::StringPattern ( rc ( " gnosticism " ) ) ) ,
then_case : vec ! [ exst ( NatLiteral ( 1 ) ) ] . into ( ) ,
else_case : Some ( vec! [ exst ( NatLiteral ( 2 ) ) ] . into ( ) ) ,
} )
} )
) ;
2021-11-19 01:35:25 -08:00
assert_expr! {
2021-10-31 02:05:39 -07:00
r #"
if ( 45 , " panda " , false , 2.2 ) {
2021-11-11 22:24:35 -08:00
is ( 49 , " pablo " , _ , 28.4 ) then " no "
2021-10-31 02:05:39 -07:00
is ( _ , " panda " , _ , - 2.2 ) then " yes "
is _ then " maybe "
} " #,
expr (
IfExpression {
discriminator : Some ( bx ( expr ( TupleLiteral ( vec! [
2021-11-21 01:02:59 -08:00
expr ( NatLiteral ( 45 ) ) , expr ( strlit ( " panda " ) ) , expr ( BoolLiteral ( false ) ) , expr ( FloatLiteral ( 2.2 ) )
2021-10-31 02:05:39 -07:00
] ) ) ) ) ,
body : bx ( IfExpressionBody ::CondList ( vec! [
ConditionArm {
condition : Condition ::Pattern ( Pattern ::TuplePattern (
vec! [
Pattern ::Literal ( PatternLiteral ::NumPattern { neg : false , num : NatLiteral ( 49 ) } ) ,
Pattern ::Literal ( PatternLiteral ::StringPattern ( rc ( " pablo " ) ) ) ,
Pattern ::Ignored ,
Pattern ::Literal ( PatternLiteral ::NumPattern { neg : false , num : FloatLiteral ( 28.4 ) } ) ,
]
) ) ,
guard : None ,
2021-11-21 01:02:59 -08:00
body : vec ! [ stmt ( StatementKind ::Expression ( expr ( strlit ( " no " ) ) ) ) ] . into ( ) ,
2021-10-31 02:05:39 -07:00
} ,
ConditionArm {
condition : Condition ::Pattern ( Pattern ::TuplePattern (
vec! [
Pattern ::Ignored ,
Pattern ::Literal ( PatternLiteral ::StringPattern ( rc! ( panda ) ) ) ,
Pattern ::Ignored ,
Pattern ::Literal ( PatternLiteral ::NumPattern { neg : true , num : FloatLiteral ( 2.2 ) } ) ,
]
) ) ,
guard : None ,
2021-11-21 01:02:59 -08:00
body : vec ! [ stmt ( StatementKind ::Expression ( expr ( strlit ( " yes " ) ) ) ) ] . into ( ) ,
2021-10-31 02:05:39 -07:00
} ,
ConditionArm {
condition : Condition ::Pattern ( Pattern ::Ignored ) ,
guard : None ,
2021-11-21 01:02:59 -08:00
body : vec ! [ exst ( strlit ( " maybe " ) ) ] . into ( ) ,
2021-10-31 02:05:39 -07:00
} ,
] ) )
}
)
} ;
2021-10-26 00:39:24 -07:00
}
2021-11-01 00:14:15 -07:00
#[ test ]
fn flow_control ( ) {
use ExpressionKind ::* ;
2021-11-19 01:01:26 -08:00
// This is an incorrect program, but should parse correctly.
2021-11-01 00:14:15 -07:00
let source = r #"
fn test ( ) {
let a = 10 ;
break ;
continue ;
return ;
return 10 ;
} " #;
2021-11-19 09:59:08 -08:00
assert_ast! (
2021-11-01 00:14:15 -07:00
source ,
vec! [ fn_decl (
Signature { name : rc ( " test " ) , operator : false , type_anno : None , params : vec ! [ ] } ,
vec! [
decl ( Declaration ::Binding {
name : rc ( " a " ) ,
constant : true ,
type_anno : None ,
expr : expr ( NatLiteral ( 10 ) )
} ) ,
stmt ( StatementKind ::Flow ( FlowControl ::Break ) ) ,
stmt ( StatementKind ::Flow ( FlowControl ::Continue ) ) ,
stmt ( StatementKind ::Flow ( FlowControl ::Return ( None ) ) ) ,
stmt ( StatementKind ::Flow ( FlowControl ::Return ( Some ( expr ( NatLiteral ( 10 ) ) ) ) ) ) ,
]
. into ( )
) ]
) ;
}
2021-11-06 20:33:33 -07:00
#[ test ]
fn blocks ( ) {
use ExpressionKind ::* ;
let cases = [ " { a } " , " { a; } " , " {a} " , " { a \n } " , " { a \n \n } " , " { a; \n \n ; } " ] ;
for case in cases . iter ( ) {
2021-11-20 23:00:19 -08:00
assert_block! ( case , vec! [ exst ( Value ( qn! ( a ) ) ) ] . into ( ) ) ;
2021-11-06 20:33:33 -07:00
}
2021-11-14 00:34:21 -08:00
let source = r #" {
fn quah ( ) {
fn foo ( ) { }
}
} " #;
2021-11-20 23:00:19 -08:00
assert_block! (
source ,
2021-11-14 00:34:21 -08:00
vec! [ decl ( Declaration ::FuncDecl (
Signature { name : rc ( " quah " ) , operator : false , params : vec ! [ ] , type_anno : None } ,
vec! [ decl ( Declaration ::FuncDecl (
Signature { name : rc ( " foo " ) , operator : false , params : vec ! [ ] , type_anno : None } ,
vec! [ ] . into ( ) ,
) ) ]
. into ( )
) ) ]
. into ( )
) ;
2021-11-18 01:37:05 -08:00
2021-11-20 23:00:19 -08:00
assert_block! ( " {} " , vec! [ ] . into ( ) ) ;
2021-11-18 01:37:05 -08:00
let source = r #" {
//hella
4_5 //bog
11 ; /* chutney */ 0xf
} " #;
2021-11-22 01:52:08 -08:00
assert_block! (
source ,
2021-11-18 01:37:05 -08:00
vec! [
Statement {
id : Default ::default ( ) ,
location : Default ::default ( ) ,
kind : StatementKind ::Expression ( Expression ::new (
Default ::default ( ) ,
ExpressionKind ::NatLiteral ( 45 )
) )
} ,
Statement {
id : Default ::default ( ) ,
location : Default ::default ( ) ,
kind : StatementKind ::Expression ( Expression ::new (
Default ::default ( ) ,
ExpressionKind ::NatLiteral ( 11 )
) )
} ,
Statement {
id : Default ::default ( ) ,
location : Default ::default ( ) ,
kind : StatementKind ::Expression ( Expression ::new (
Default ::default ( ) ,
ExpressionKind ::NatLiteral ( 15 )
) )
} ,
]
. into ( )
) ;
2021-11-06 20:33:33 -07:00
}
2021-11-13 01:41:17 -08:00
#[ test ]
fn comments ( ) {
use ExpressionKind ::* ;
let source = " 1 + /* hella /* bro */ */ 2 " ;
2021-11-20 22:55:11 -08:00
assert_expr! ( source , binop ( " + " , expr ( NatLiteral ( 1 ) ) , expr ( NatLiteral ( 2 ) ) ) ) ;
2021-11-13 01:41:17 -08:00
//TODO make sure this error message makes sense
let source = " 1 + /* hella /* bro */ 2 " ;
2021-11-20 22:55:11 -08:00
assert_fail_expr! ( source , " foo " ) ;
2021-11-13 01:41:17 -08:00
2021-11-20 02:03:28 -08:00
let source = " 1 + /* hella */ bro */ 2 " ;
assert_fail_expr! ( source , binop ( " + " , expr ( NatLiteral ( 1 ) ) , expr ( NatLiteral ( 2 ) ) ) ) ;
2021-11-13 13:18:02 -08:00
let source = " 5//no man \n " ;
2021-11-20 22:55:11 -08:00
assert_ast! ( source , vec! [ exst ( NatLiteral ( 5 ) ) ] ) ;
2021-11-19 09:59:08 -08:00
let source = " /*yolo*/ barnaby " ;
2021-11-20 22:55:11 -08:00
assert_ast! ( source , exst ( ExpressionKind ::Value ( qn! ( barnaby ) ) ) ) ;
2021-11-13 01:41:17 -08:00
}
2021-11-13 13:45:52 -08:00
//TODO support backtick operators like this
/*
#[ test ]
fn backtick_operators ( ) {
let output = token_kinds ( " 1 `plus` 2 " ) ;
assert_eq! ( output , vec! [ digit! ( " 1 " ) , op! ( " plus " ) , digit! ( " 2 " ) ] ) ;
}
* /