"Fossies" - the Fresh Open Source Software Archive

Member "ponyc-0.33.0/test/libponyc/literal_inference.cc" (1 Nov 2019, 21394 Bytes) of package /linux/misc/ponyc-0.33.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #include <gtest/gtest.h>
    2 #include "util.h"
    3 
    4 // Literal type inference and limit checks.
    5 
    6 #define TEST_ERROR(src) DO(test_error(src, "expr"))
    7 #define TEST_COMPILE(src) DO(test_compile(src, "expr"))
    8 
    9 #define TEST_ERRORS_1(src, err1) \
   10   { const char* errs[] = {err1, NULL}; \
   11     DO(test_expected_errors(src, "expr", errs)); }
   12 
   13 class LiteralTest : public PassTest
   14 {
   15   protected:
   16     void check_type_for_assign(const char* type_name, token_id tk_type, const char* var, const char* src)
   17     {
   18       TEST_COMPILE(src);
   19 
   20       ast_t* x_type = type_of(var);      // Find type of x
   21       ast_t* x = ast_parent(x_type);     // Declaration of foo is parent of type
   22       ast_t* assign = ast_parent(x);     // Assignment is the parent of declaration of x
   23       ast_t* three = ast_child(assign);  // Literal is the first child of the assignment
   24       ast_t* type = ast_type(three);     // Finally we get to the type of the literal
   25 
   26       ASSERT_ID(tk_type, type);
   27 
   28       switch(tk_type) {
   29         case TK_NOMINAL:
   30           ASSERT_STREQ(type_name, ast_name(ast_childidx(type, 1)));  // Child index 1 of a nominal is the type name
   31           break;
   32         case TK_TYPEPARAMREF:
   33           ASSERT_STREQ(type_name, ast_name(ast_childidx(type, 0)));  // Child index 0 of a type param is the type name
   34           break;
   35         default:
   36           FAIL(); // Unexpected tk_type
   37       }
   38     }
   39 
   40     void check_type(const char* type_name, token_id tk_type, ast_t* ast)
   41     {
   42       ast_t* type = ast_type(ast);
   43       ASSERT_ID(tk_type, type);
   44 
   45       switch(tk_type)
   46       {
   47         case TK_NOMINAL:
   48           ASSERT_STREQ(type_name, ast_name(ast_childidx(type, 1)));  // Child index 1 of a nominal is the type name
   49           break;
   50         case TK_TYPEPARAMREF:
   51           ASSERT_STREQ(type_name, ast_name(ast_childidx(type, 0)));  // Child index 0 of a type param is the type name
   52           break;
   53         default:
   54           FAIL(); // Unexpected tk_type
   55       }
   56     }
   57 
   58     void check_trivial(const char* type_name, const char* value) {
   59       const char* src =
   60         "class Foo\n"
   61         "  fun f() =>\n"
   62         "    let x: ";
   63 
   64       std::string str(src);
   65       str.append(type_name).append(" = ").append(value);
   66 
   67       DO(check_type_for_assign(type_name, TK_NOMINAL, "x", str.c_str()));
   68     }
   69 
   70 
   71     void check_trivial_fail(const char* type_name, const char* value) {
   72       const char* src =
   73         "class Foo\n"
   74         "  fun f() =>\n"
   75         "    let x: ";
   76 
   77       std::string str(src);
   78       str.append(type_name).append(" = ").append(value);
   79 
   80       TEST_ERROR(str.c_str());
   81     }
   82 };
   83 
   84 
   85 // First the limitations.
   86 
   87 TEST_F(LiteralTest, CantInfer_Op_IsLiterals)
   88 {
   89   const char* src =
   90     "class Foo\n"
   91     "  new create() =>\n"
   92     "    2 is 3";
   93 
   94   // Fails because type of literals cannot be determined. See #369.
   95   TEST_ERROR(src);
   96 }
   97 
   98 
   99 TEST_F(LiteralTest, CantInfer_Op_IsntLiterals)
  100 {
  101   const char* src =
  102     "class Foo\n"
  103     "  new create() =>\n"
  104     "    2 isnt 2";
  105 
  106   // Fails because type of literals cannot be determined. See #369.
  107   TEST_ERROR(src);
  108 }
  109 
  110 
  111 TEST_F(LiteralTest, CantInfer_Op_ExprIsLiteral)
  112 {
  113   const char* src =
  114     "class Foo\n"
  115     "  new create() =>\n"
  116     "    (1 + 2) is 3";
  117 
  118   // Fails because type of literals cannot be determined. See #369.
  119   TEST_ERROR(src);
  120 }
  121 
  122 
  123 TEST_F(LiteralTest, CantInfer_Op_IntAndFloat )
  124 {
  125   const char* src =
  126     "class Foo10b\n"
  127     "  fun test(): I32 => 7 and 16.0\n";
  128 
  129   TEST_ERROR(src);
  130 }
  131 
  132 
  133 TEST_F(LiteralTest, CantInfer_Op_FloatAndInt )
  134 {
  135   const char* src =
  136     "class Foo11b\n"
  137     "  fun test(): I32 => 7.0 and 16\n";
  138 
  139   TEST_ERROR(src);
  140 }
  141 
  142 
  143 TEST_F(LiteralTest, CantInfer_Op_FloatAndIntReturningFloat )
  144 {
  145   const char* src =
  146     "class Foo12b\n"
  147     "  fun test(): F32 => 7.0 and 16\n";
  148 
  149   TEST_ERROR(src);
  150 }
  151 
  152 
  153 TEST_F(LiteralTest, CantInfer_Op_IntAndFloatReturningFloat )
  154 {
  155   const char* src =
  156     "class Foo13b\n"
  157     "  fun test(): F32 => 7 and 16.0\n";
  158 
  159   TEST_ERROR(src);
  160 }
  161 
  162 
  163 TEST_F(LiteralTest, CantInfer_Op_EqualsLiterals )
  164 {
  165   const char* src =
  166     "class Foo14b\n"
  167     "  fun test(): Bool => 34 == 79\n";
  168 
  169   TEST_ERROR(src);
  170 }
  171 
  172 
  173 TEST_F(LiteralTest, CantInfer_Let_FloatLiteralFromIntType)
  174 {
  175   DO(check_trivial_fail("U8",   "3.0"));
  176   DO(check_trivial_fail("U16",  "3.0"));
  177   DO(check_trivial_fail("U32",  "3.0"));
  178   DO(check_trivial_fail("U64",  "3.0"));
  179   DO(check_trivial_fail("U128", "3.0"));
  180 
  181   DO(check_trivial_fail("I8",   "3.0"));
  182   DO(check_trivial_fail("I16",  "3.0"));
  183   DO(check_trivial_fail("I32",  "3.0"));
  184   DO(check_trivial_fail("I64",  "3.0"));
  185   DO(check_trivial_fail("I128", "3.0"));
  186 }
  187 
  188 
  189 TEST_F(LiteralTest, CantInfer_Let_NonNumericType)
  190 {
  191   DO(check_trivial_fail("String", "3"));
  192   DO(check_trivial_fail("String", "3.0"));
  193 
  194   DO(check_trivial_fail("Bool", "3"));
  195   DO(check_trivial_fail("Bool", "3.0"));
  196 }
  197 
  198 
  199 TEST_F(LiteralTest, CantInfer_Let_NoType)
  200 {
  201   const char* src =
  202     "class Foo\n"
  203     "  new create() =>\n"
  204     "    let x = 17";
  205 
  206   TEST_ERROR(src);
  207 }
  208 
  209 
  210 TEST_F(LiteralTest, CantInfer_Let_AmbiguousUnion1)
  211 {
  212   const char* src =
  213     "class Foo\n"
  214     "  new create() =>\n"
  215     "    let x: (U8 | U32) = 17";
  216 
  217   TEST_ERROR(src);
  218 }
  219 
  220 
  221 TEST_F(LiteralTest, CantInfer_Let_AmbiguousUnion2)
  222 {
  223   const char* src =
  224     "class Foo\n"
  225     "  new create() =>\n"
  226     "    let x: (U8 | F32) = 17";  // could be either U8 or F32
  227 
  228   TEST_ERROR(src);
  229 }
  230 
  231 TEST_F(LiteralTest, CantInfer_Let_EmptyIntersection)
  232 {
  233   const char* src =
  234     "class Foo\n"
  235     "  new create() =>\n"
  236     "    let x: (U8 & U32) = 17\n";
  237 
  238   TEST_ERROR(src);
  239 }
  240 
  241 
  242 TEST_F(LiteralTest, CantInfer_Let_InsufficientlySpecifiedGeneric)
  243 {
  244   const char* src =
  245     "class Foo[A]\n"
  246     "  new create() =>\n"
  247     "    let x: A = 17";
  248 
  249   TEST_ERRORS_1(src, "could not infer literal type, no valid types found");
  250 }
  251 
  252 TEST_F(LiteralTest, CantInfer_DefaultArg_InsufficientlySpecifiedGeneric)
  253 {
  254   const char* src =
  255     "class Foo[A]\n"
  256     "  new create(field: A = 0) =>\n"
  257     "    None\n"
  258     "\n"
  259     "class Bar\n"
  260     "  new create() =>\n"
  261     "    let foo = Foo[U16]()";
  262 
  263   TEST_ERRORS_1(src, "could not infer literal type, no valid types found");
  264 }
  265 
  266 
  267 TEST_F(LiteralTest, CantInfer_Parameter_AmbiguousUnion)
  268 {
  269   const char* src =
  270     "class Foo3\n"
  271     "  fun run() => test(8)\n"
  272     "  fun test(a: (U8|U32)) => true\n";
  273 
  274   TEST_ERROR(src);
  275 }
  276 
  277 
  278 TEST_F(LiteralTest, CantInfer_Return_InvalidUnion )
  279 {
  280   const char* src =
  281     "class Foo4\n"
  282     "  fun test(): ( Bool | String ) => 2\n";
  283 
  284   TEST_ERROR(src);
  285 }
  286 
  287 
  288 TEST_F(LiteralTest, Array_UnambiguousUnion )
  289 {
  290   const char* src =
  291     "class Foo5a\n"
  292     "  fun run() => test([8])\n"
  293     "  fun test(a: Array[ (String | I32) ] ): Bool => true\n";
  294 
  295   TEST_COMPILE(src);
  296 }
  297 
  298 
  299 TEST_F(LiteralTest, CantInfer_Match_LiteralMatchValue )
  300 {
  301   const char* src =
  302     "class Foo10c\n"
  303     "  fun test(): Bool => \n"
  304     "    match 8\n"
  305     "    | I16 => true\n"
  306     "    end\n";
  307 
  308   TEST_ERROR(src);
  309 }
  310 
  311 
  312 TEST_F(LiteralTest, CantInfer_Match_InvalidElse)
  313 {
  314   const char* src =
  315     "class Foo11c\n"
  316     "  fun test(q: Bool): I16 => \n"
  317     "    match q\n"
  318     "    | true => 1\n"
  319     "    | false => 1\n"
  320     "    else\n"
  321     "      7.0\n"
  322     "    end\n";
  323 
  324   TEST_ERROR(src);
  325 }
  326 
  327 
  328 TEST_F(LiteralTest, CantInfer_Literal_Unused)
  329 {
  330   const char* src =
  331     "class Foo12c\n"
  332     "  fun test(q: Bool): F64 ? => 79; error\n";
  333 
  334   TEST_ERROR(src);
  335 }
  336 
  337 
  338 TEST_F(LiteralTest, CantInfer_While_InvalidReturnValue)
  339 {
  340   const char* src =
  341     "class Foo13c\n"
  342     "  fun test(): String =>\n"
  343     "    while true do\n"
  344     "      72\n"
  345     "    else\n"
  346     "      ""\n"
  347     "    end\n";
  348 
  349   TEST_ERROR(src);
  350 }
  351 
  352 
  353 TEST_F(LiteralTest, CantInfer_While_InvalidElseValue )
  354 {
  355   const char* src =
  356     "class Foo14c\n"
  357     "  fun test(): String =>\n"
  358     "    while true do\n"
  359     "      ""\n"
  360     "    else\n"
  361     "      63\n"
  362     "    end\n";
  363 
  364   TEST_ERROR(src);
  365 }
  366 
  367 
  368 
  369 
  370 // Happy paths
  371 
  372 TEST_F(LiteralTest, Let_AllNumericTypes)
  373 {
  374   DO(check_trivial("U8",   "3"));
  375   DO(check_trivial("U16",  "3"));
  376   DO(check_trivial("U32",  "3"));
  377   DO(check_trivial("U64",  "3"));
  378   DO(check_trivial("U128", "3"));
  379 
  380   DO(check_trivial("I8",   "3"));
  381   DO(check_trivial("I16",  "3"));
  382   DO(check_trivial("I32",  "3"));
  383   DO(check_trivial("I64",  "3"));
  384   DO(check_trivial("I128", "3"));
  385 
  386   DO(check_trivial("F32",  "3"));
  387   DO(check_trivial("F64",  "3"));
  388 
  389   DO(check_trivial("F32",  "3.0"));
  390   DO(check_trivial("F64",  "3.0"));
  391 }
  392 
  393 
  394 TEST_F(LiteralTest, Let_UnambiguousUnion)
  395 {
  396   const char* src =
  397     "class Foo\n"
  398     "  fun f() =>\n"
  399     "    let x: (U8 | String) = 3";
  400 
  401   TEST_COMPILE(src);
  402 
  403   DO(check_type("U8", TK_NOMINAL, numeric_literal(3)));
  404 }
  405 
  406 
  407 // TEST_F(LiteralTest, LetUnambiguousUnionBecauseFloatingLiteral)   -- FIXME currently fails
  408 // {
  409 //   const char* src =
  410 //     "class Foo\n"
  411 //     "  fun f() =>\n"
  412 //     "    let x: (U128 | F64) = 36000.0";  // .0 forces this to be F64
  413 
  414 //   DO(check_type_for_assign("F64", TK_NOMINAL, "x", src));
  415 // }
  416 
  417 
  418 TEST_F(LiteralTest, Let_UnionSameType)
  419 {
  420   const char* src =
  421     "class Foo\n"
  422     "  fun f() =>\n"
  423     "    let x: (U8 | U8) = 3";
  424 
  425   TEST_COMPILE(src);
  426 
  427   DO(check_type("U8", TK_NOMINAL, numeric_literal(3)));
  428 }
  429 
  430 
  431 TEST_F(LiteralTest, Let_SufficientlySpecifiedGeneric)
  432 {
  433   const char* src =
  434     "class Foo[A: U8]\n"
  435     "  new create() =>\n"
  436     "    let x: A = 17";
  437 
  438   TEST_COMPILE(src);
  439 
  440   DO(check_type("A", TK_TYPEPARAMREF, numeric_literal(17)));
  441 }
  442 
  443 
  444 TEST_F(LiteralTest, Let_Tuple)
  445 {
  446   const char* src =
  447     "class Foo\n"
  448     "  new create() =>\n"
  449     "    (let x: U8, let y: U32) = (8, 32)";
  450 
  451   TEST_COMPILE(src);
  452 
  453   DO(check_type("U8",  TK_NOMINAL, numeric_literal(8)));
  454   DO(check_type("U32", TK_NOMINAL, numeric_literal(32)));
  455 }
  456 
  457 
  458 TEST_F(LiteralTest, Let_NestedTuple)
  459 {
  460   const char* src =
  461     "class Foo\n"
  462     "  new create() =>\n"
  463     "    ((let w: U8, let x: U16), (let y: U32, let z: U64)) = ((2, 3), (4, 5))";
  464 
  465   TEST_COMPILE(src);
  466 
  467   DO(check_type("U8",  TK_NOMINAL, numeric_literal(2)));
  468   DO(check_type("U16", TK_NOMINAL, numeric_literal(3)));
  469   DO(check_type("U32", TK_NOMINAL, numeric_literal(4)));
  470   DO(check_type("U64", TK_NOMINAL, numeric_literal(5)));
  471 }
  472 
  473 
  474 TEST_F(LiteralTest, Let_TupleOfGeneric)
  475 {
  476   const char* src =
  477     "class Foo[A: U8, B: U32]\n"
  478     "  new create() =>\n"
  479     "    (let x: A, let y: A) = (16, 32)";
  480 
  481   TEST_COMPILE(src);
  482 
  483   DO(check_type("A", TK_TYPEPARAMREF, numeric_literal(16)));
  484   DO(check_type("A", TK_TYPEPARAMREF, numeric_literal(32)));
  485 }
  486 
  487 
  488 TEST_F(LiteralTest, Let_TupleOfGenericOfGeneric)
  489 {
  490   const char* src =
  491     "class Foo[A: U8, B: U32]\n"
  492     "  new create() =>\n"
  493     "    (let x: A, let y: B) = (16, 32)";
  494 
  495   TEST_COMPILE(src);
  496 
  497   DO(check_type("A", TK_TYPEPARAMREF, numeric_literal(16)));
  498   DO(check_type("B", TK_TYPEPARAMREF, numeric_literal(32)));
  499 }
  500 
  501 
  502 TEST_F(LiteralTest, Let_GenericSubtype)
  503 {
  504   const char* src =
  505     " class Foo[A: U8, B: A]\n"
  506     "  new create() =>\n"
  507     "    let x: B = 17";
  508 
  509   TEST_COMPILE(src);
  510 
  511   DO(check_type("B", TK_TYPEPARAMREF, numeric_literal(17)));
  512 }
  513 
  514 
  515 TEST_F(LiteralTest, Parameter_Simple)
  516 {
  517   const char* src =
  518     "class Foo1\n"
  519     "  fun run() => test(128)\n"
  520     "  fun test(a: U128) => true\n";
  521 
  522   TEST_COMPILE(src);
  523 
  524   DO(check_type("U128", TK_NOMINAL, numeric_literal(128)));
  525 }
  526 
  527 
  528 TEST_F(LiteralTest, Parameter_SecondParameter)
  529 {
  530   const char* src =
  531     "class Foo1a\n"
  532     "  fun run() => test(\"\", 128)\n"
  533     "  fun test(a: String, b: U128) => true\n";
  534 
  535   TEST_COMPILE(src);
  536 
  537   DO(check_type("U128",  TK_NOMINAL, numeric_literal(128)));
  538 }
  539 
  540 
  541 TEST_F(LiteralTest, Parameter_Tuple)
  542 {
  543   const char* src =
  544     "class Foo2\n"
  545     "  fun run() => test((8, 32))\n"
  546     "  fun test(a: (U8, U32)) => true\n";
  547 
  548   TEST_COMPILE(src);
  549 
  550   DO(check_type("U8",  TK_NOMINAL, numeric_literal(8)));
  551   DO(check_type("U32", TK_NOMINAL, numeric_literal(32)));
  552 }
  553 
  554 
  555 TEST_F(LiteralTest, Parameter_NestedTuple)
  556 {
  557   const char* src =
  558     "class Foo2a\n"
  559     "  fun run() => test((8, (\"\", 32)))\n"
  560     "  fun test(a: (U8, (String, U32)) ) => true\n";
  561 
  562   TEST_COMPILE(src);
  563 
  564   DO(check_type("U8",  TK_NOMINAL, numeric_literal(8)));
  565   DO(check_type("U32", TK_NOMINAL, numeric_literal(32)));
  566 }
  567 
  568 
  569 TEST_F(LiteralTest, Parameter_Union)
  570 {
  571   const char* src =
  572     "class Foo4\n"
  573     "  fun run() => test(64)\n"
  574     "  fun test(a: (Bool | U64 | String) ) => true\n";
  575 
  576   TEST_COMPILE(src);
  577 
  578   DO(check_type("U64",  TK_NOMINAL, numeric_literal(64)));
  579 }
  580 
  581 
  582 TEST_F(LiteralTest, Parameter_TupleOfUnions)
  583 {
  584   const char* src =
  585     "class Foo7\n"
  586     "  fun run() => test((8, 32))\n"
  587     "  fun test(a: ((U8 | String), (Bool | U32)) ) => true\n";
  588 
  589   TEST_COMPILE(src);
  590 
  591   DO(check_type("U8",  TK_NOMINAL, numeric_literal(8)));
  592   DO(check_type("U32", TK_NOMINAL, numeric_literal(32)));
  593 }
  594 
  595 
  596 TEST_F(LiteralTest, Parameter_Generic)
  597 {
  598   const char* src =
  599     "class Foo5[A : U8]\n"
  600     "  fun run() => test(8)\n"
  601     "  fun test(a: A) => true\n";
  602 
  603   TEST_COMPILE(src);
  604 
  605   DO(check_type("A",  TK_TYPEPARAMREF, numeric_literal(8)));
  606 }
  607 
  608 
  609 TEST_F(LiteralTest, Parameter_TupleOfUnionOfGeneric)
  610 {
  611   const char* src =
  612     "class Foo7a[A : U32]\n"
  613     "  fun run() => test((79, 1032))\n"
  614     "  fun test(a: (U8, (String | A)) ) => true\n";
  615 
  616   TEST_COMPILE(src);
  617 
  618   DO(check_type("U8", TK_NOMINAL, numeric_literal(79)));
  619   DO(check_type("A",  TK_TYPEPARAMREF, numeric_literal(1032)));
  620 }
  621 
  622 
  623 TEST_F(LiteralTest, Parameter_GenericSubtype)
  624 {
  625   const char* src =
  626     "class Foo6[A : U8, B: A]\n"
  627     "  fun run() => test(8)\n"
  628     "  fun test(a: B) => true\n";
  629 
  630   TEST_COMPILE(src);
  631 
  632   DO(check_type("B", TK_TYPEPARAMREF, numeric_literal(8)));
  633 }
  634 
  635 
  636 TEST_F(LiteralTest, Return_Simple)
  637 {
  638   const char* src =
  639     "class Foo1\n"
  640     "  fun test(): U128 => 17\n";
  641 
  642   TEST_COMPILE(src);
  643 
  644   DO(check_type("U128", TK_NOMINAL, numeric_literal(17)));
  645 }
  646 
  647 
  648 TEST_F(LiteralTest, Return_TupleOfUnionOfGeneric)
  649 {
  650   const char* src =
  651     "class Foo2[A]\n"
  652     "  fun test(): (String, (U8|A)) => (\"\", 2)\n";
  653 
  654   TEST_COMPILE(src);
  655 
  656   DO(check_type("U8", TK_NOMINAL, numeric_literal(2)));
  657 }
  658 
  659 
  660 TEST_F(LiteralTest, Return_UnionOfTuple)
  661 {
  662   const char* src =
  663     "class Foo3\n"
  664     "  fun test(): ( (String, U32) | (U16, String) ) => (\"\", 2)\n";
  665 
  666   TEST_COMPILE(src);
  667 
  668   DO(check_type("U32", TK_NOMINAL, numeric_literal(2)));
  669 }
  670 
  671 
  672 TEST_F(LiteralTest, UseReturn_Simple)
  673 {
  674   const char* src =
  675     "class Foo10\n"
  676     "  fun run() => 8 * test()\n"
  677     "  fun test(): U8 => 2\n";
  678 
  679   TEST_COMPILE(src);
  680 
  681   DO(check_type("U8", TK_NOMINAL, numeric_literal(8)));
  682 }
  683 
  684 
  685 TEST_F(LiteralTest, UseReturn_Tuple)
  686 {
  687   const char* src =
  688     "class Foo11\n"
  689     "  fun run() => 8 * test()._2\n"
  690     "  fun test(): (String, I16) => (\"\", 16)\n";
  691 
  692   TEST_COMPILE(src);
  693 
  694   DO(check_type("I16", TK_NOMINAL, numeric_literal(8)));
  695 }
  696 
  697 
  698 TEST_F(LiteralTest, Type_Simple)
  699 {
  700   const char* src =
  701     "type T is ( (String, U32) | (U16, String) )\n"
  702     "\n"
  703     "class Foo1t\n"
  704     "  fun test(): T => (\"\", 2)\n";
  705 
  706   TEST_COMPILE(src);
  707 
  708   DO(check_type("U32", TK_NOMINAL, numeric_literal(2)));
  709 }
  710 
  711 
  712 TEST_F(LiteralTest, Array_Simple)
  713 {
  714   const char* src =
  715     "class Foo1a\n"
  716     "  fun test(): Array[U8] => [8]\n";
  717 
  718   TEST_COMPILE(src);
  719 
  720   DO(check_type("U8", TK_NOMINAL, numeric_literal(8)));
  721 }
  722 
  723 
  724 TEST_F(LiteralTest, Array_Parameter)
  725 {
  726   const char* src =
  727     "class Foo2a\n"
  728     "  fun run() => test([8])\n"
  729     "  fun test(a: Array[I32]): Bool => true\n";
  730 
  731   TEST_COMPILE(src);
  732 
  733   DO(check_type("I32", TK_NOMINAL, numeric_literal(8)));
  734 }
  735 
  736 
  737 TEST_F(LiteralTest, Array_ParameterOfUnionOfArray)
  738 {
  739   const char* src =
  740     "class Foo3a\n"
  741     "  fun run() => test([8])\n"
  742     "  fun test(a: (Array[String] | Array[I32]) ): Bool => true\n";
  743 
  744   TEST_COMPILE(src);
  745 
  746   DO(check_type("I32", TK_NOMINAL, numeric_literal(8)));
  747 }
  748 
  749 
  750 TEST_F(LiteralTest, Array_ParameterOfArrayOfUnion)
  751 {
  752   const char* src =
  753     "class Foo4a\n"
  754     "  fun run() => test([8; \"\"])\n"
  755     "  fun test(a: Array[ (String | I32) ] ): Bool => true\n";
  756 
  757   TEST_COMPILE(src);
  758 
  759   DO(check_type("I32", TK_NOMINAL, numeric_literal(8)));
  760 }
  761 
  762 
  763 TEST_F(LiteralTest, Op_MulLiterals)
  764 {
  765   const char* src =
  766     "class Foo1b\n"
  767     "  fun test(): I64 => 64 * 79\n";
  768 
  769   TEST_COMPILE(src);
  770 
  771   DO(check_type("I64", TK_NOMINAL, numeric_literal(64)));
  772   DO(check_type("I64", TK_NOMINAL, numeric_literal(79)));
  773 }
  774 
  775 
  776 TEST_F(LiteralTest, Op_XorLiterals)
  777 {
  778   const char* src =
  779     "class Foo2b\n"
  780     "  fun test(): I64 => 64 xor 79\n";
  781 
  782   TEST_COMPILE(src);
  783 
  784   DO(check_type("I64", TK_NOMINAL, numeric_literal(64)));
  785   DO(check_type("I64", TK_NOMINAL, numeric_literal(79)));
  786 }
  787 
  788 
  789 TEST_F(LiteralTest, Op_VarOrLiteral)
  790 {
  791   const char* src =
  792     "class Foo2ba\n"
  793     "  fun test(y: I64): I64 => y or 79\n";
  794 
  795   TEST_COMPILE(src);
  796 
  797   DO(check_type("I64", TK_NOMINAL, numeric_literal(79)));
  798 }
  799 
  800 
  801 TEST_F(LiteralTest, Op_VarEqualsLiteral)
  802 {
  803   const char* src =
  804     "class Foo4b\n"
  805     "  fun test(y: I32): Bool => y == 79\n";
  806 
  807   TEST_COMPILE(src);
  808 
  809   DO(check_type("I32", TK_NOMINAL, numeric_literal(79)));
  810 }
  811 
  812 
  813 TEST_F(LiteralTest, Op_LiteralEqualsVar)
  814 {
  815   const char* src =
  816     "class Foo5b\n"
  817     "  fun test(y: I32): Bool => 79 == y\n";
  818 
  819   TEST_COMPILE(src);
  820 
  821   DO(check_type("I32", TK_NOMINAL, numeric_literal(79)));
  822 }
  823 
  824 
  825 TEST_F(LiteralTest, Op_ParameterOfTupleOfAnd)
  826 {
  827   const char* src =
  828     "class Foo3b\n"
  829     "  fun run() => test((\"\", 64 and 79))\n"
  830     "  fun test(a: (String, I64)) : Bool => true\n";
  831 
  832   TEST_COMPILE(src);
  833 
  834   DO(check_type("I64", TK_NOMINAL, numeric_literal(64)));
  835   DO(check_type("I64", TK_NOMINAL, numeric_literal(79)));
  836 }
  837 
  838 
  839 TEST_F(LiteralTest, If_Simple)
  840 {
  841   const char* src =
  842    "class Foo1c\n"
  843     "  fun test(): USize => if true then 79 elseif false then 234 else 123 end\n";
  844 
  845   TEST_COMPILE(src);
  846 
  847   DO(check_type("USize", TK_NOMINAL, numeric_literal(79)));
  848   DO(check_type("USize", TK_NOMINAL, numeric_literal(234)));
  849   DO(check_type("USize", TK_NOMINAL, numeric_literal(123)));
  850 }
  851 
  852 
  853 TEST_F(LiteralTest, Match_ResultInt)
  854 {
  855   const char* src =
  856     "class Foo2c\n"
  857     "  fun test(q: Bool): I16 => \n"
  858     "    match q\n"
  859     "    | true => 1\n"
  860     "    | false => 11\n"
  861     "    else\n"
  862     "      7\n"
  863     "    end\n";
  864 
  865   TEST_COMPILE(src);
  866 
  867   DO(check_type("I16", TK_NOMINAL, numeric_literal(1)));
  868   DO(check_type("I16", TK_NOMINAL, numeric_literal(11)));
  869   DO(check_type("I16", TK_NOMINAL, numeric_literal(7)));
  870 }
  871 
  872 
  873 TEST_F(LiteralTest, Match_ResultFloat)
  874 {
  875   const char* src =
  876     "class Foo3c\n"
  877     "  fun test(q: Bool): F64 => \n"
  878     "    match q\n"
  879     "    | true => 1\n"
  880     "    | false => 11\n"
  881     "    else\n"
  882     "      7\n"
  883     "    end\n";
  884 
  885   TEST_COMPILE(src);
  886 
  887   DO(check_type("F64", TK_NOMINAL, numeric_literal(1)));
  888   DO(check_type("F64", TK_NOMINAL, numeric_literal(11)));
  889   DO(check_type("F64", TK_NOMINAL, numeric_literal(7)));
  890 }
  891 
  892 
  893 TEST_F(LiteralTest, Match_PatternTuple)
  894 {
  895   const char* src =
  896     "class Foo4c\n"
  897     "  fun test(q: (U16, F32)): Bool => \n"
  898     "    match q\n"
  899     "    | (16, 17) => true\n"
  900     "    | (32, 33) => false\n"
  901     "    else\n"
  902     "      false\n"
  903     "    end\n";
  904 
  905   TEST_COMPILE(src);
  906 
  907   DO(check_type("U16", TK_NOMINAL, numeric_literal(16)));
  908   DO(check_type("U16", TK_NOMINAL, numeric_literal(32)));
  909   DO(check_type("F32", TK_NOMINAL, numeric_literal(17)));
  910   DO(check_type("F32", TK_NOMINAL, numeric_literal(33)));
  911 }
  912 
  913 
  914 TEST_F(LiteralTest, Try_ErrorBodyElseLiteral)
  915 {
  916   const char* src =
  917     "class Foo5c\n"
  918     "  fun test(): F64 => try error else 73 end\n";
  919 
  920   TEST_COMPILE(src);
  921 
  922   DO(check_type("F64", TK_NOMINAL, numeric_literal(73)));
  923 }
  924 
  925 
  926 TEST_F(LiteralTest, Try_ExpressionBody)
  927 {
  928   const char* src =
  929     "class Foo6c\n"
  930     "  fun run() => test(true)\n"
  931     "  fun test(q: Bool): F64 => try if q then 166 else error end else 73 end\n";
  932 
  933   TEST_COMPILE(src);
  934 
  935   DO(check_type("F64", TK_NOMINAL, numeric_literal(166)));
  936   DO(check_type("F64", TK_NOMINAL, numeric_literal(73)));
  937 }
  938 
  939 
  940 TEST_F(LiteralTest, While_TupleResultBreakHasValue)
  941 {
  942   const char* src =
  943     "class Foo7c\n"
  944     "  fun test(): (U128, Bool) =>\n"
  945     "    while true do\n"
  946     "      if false then\n"
  947     "        (72 * 16, true)\n"
  948     "      else\n"
  949     "        break (14, true)\n"
  950     "      end\n"
  951     "    else\n"
  952     "      (63 / 12, false)\n"
  953     "    end\n";
  954 
  955   TEST_COMPILE(src);
  956 
  957   DO(check_type("U128", TK_NOMINAL, numeric_literal(72)));
  958   DO(check_type("U128", TK_NOMINAL, numeric_literal(16)));
  959   DO(check_type("U128", TK_NOMINAL, numeric_literal(14)));
  960   DO(check_type("U128", TK_NOMINAL, numeric_literal(63)));
  961   DO(check_type("U128", TK_NOMINAL, numeric_literal(12)));
  962 }
  963 
  964 
  965 TEST_F(LiteralTest, While_TupleResultBreakHasNoValue)
  966 {
  967   const char* src =
  968     "class Foo8c\n"
  969     "  fun test(): (None | (U128, Bool)) =>\n"
  970     "    while true do\n"
  971     "      if false then\n"
  972     "        (72 * 16, true)\n"
  973     "      else\n"
  974     "        break\n"
  975     "      end\n"
  976     "    else\n"
  977     "      (63 / 12, false)\n"
  978     "    end\n";
  979 
  980   TEST_COMPILE(src);
  981 
  982   DO(check_type("U128", TK_NOMINAL, numeric_literal(72)));
  983   DO(check_type("U128", TK_NOMINAL, numeric_literal(16)));
  984   DO(check_type("U128", TK_NOMINAL, numeric_literal(63)));
  985   DO(check_type("U128", TK_NOMINAL, numeric_literal(12)));
  986 }
  987 
  988 
  989 TEST_F(LiteralTest, For_Simple)
  990 {
  991   const char* src =
  992     "class Foo9c\n"
  993     "  fun test(q: Array[String], r: Bool): U64 =>\n"
  994     "    for x in q.values() do\n"
  995     "      if r then 3 else 4 end\n"
  996     "    else\n"
  997     "      0\n"
  998     "    end\n";
  999 
 1000   TEST_COMPILE(src);
 1001 
 1002   DO(check_type("U64", TK_NOMINAL, numeric_literal(3)));
 1003   DO(check_type("U64", TK_NOMINAL, numeric_literal(4)));
 1004   DO(check_type("U64", TK_NOMINAL, numeric_literal(0)));
 1005 }