void test_if_elif_else()
{
    Branch branch;

    branch.compile("if true { a = 1 } elif true { a = 2 } else { a = 3 } a=a");
    evaluate_branch(&branch);

    test_assert(branch.contains("a"));
    test_equals(branch["a"]->asInt(), 1);

    branch.compile(
        "if false { b = 'apple' } elif false { b = 'orange' } else { b = 'pineapple' } b=b");
    evaluate_branch(&branch);
    test_assert(branch.contains("b"));
    test_assert(branch["b"]->asString() == "pineapple");

    // try one without 'else'
    branch.clear();
    branch.compile("c = 0");
    branch.compile("if false { c = 7 } elif true { c = 8 }; c=c");
    evaluate_branch(&branch);
    test_assert(branch.contains("c"));
    test_assert(branch["c"]->asInt() == 8);

    // try with some more complex conditions
    branch.clear();
    branch.compile("x = 5");
    branch.compile("if x > 6 { compare = 1 } elif x < 6 { compare = -1 } else { compare = 0}");
    branch.compile("compare=compare");
    evaluate_branch(&branch);

    test_assert(branch.contains("compare"));
    test_assert(branch["compare"]->asInt() == -1);
}
void test_state_simple()
{
    Branch branch;
    Stack context;

    // Simple test, condition never changes
    Term* block = branch.compile("if true { state i = 0; i += 1 }");
    evaluate_branch(&context, &branch);

    caValue *i = context.state.getField("_if_block")->getIndex(0)->getField("i");
    test_assert(i != NULL);
    test_assert(as_int(i) == 1);
    evaluate_branch(&context, &branch);
    i = context.state.getField("_if_block")->getIndex(0)->getField("i");
    test_assert(as_int(i) == 2);
    evaluate_branch(&context, &branch);
    i = context.state.getField("_if_block")->getIndex(0)->getField("i");
    test_assert(as_int(i) == 3);

    // Same test with elif
    branch.clear();
    block = branch.compile("if false {} elif true { state i = 0; i += 1 }");
    evaluate_branch(&context, &branch);
    i = context.state.getField("_if_block")->getIndex(1)->getField("i");
    test_assert(as_int(i) == 1);
    evaluate_branch(&context, &branch);
    i = context.state.getField("_if_block")->getIndex(1)->getField("i");
    test_assert(as_int(i) == 2);
    evaluate_branch(&context, &branch);
    i = context.state.getField("_if_block")->getIndex(1)->getField("i");
    test_assert(as_int(i) == 3);

    // Same test with else
    branch.clear();

    Stack context2;
    block = branch.compile("if false {} else { state i = 0; i += 1 }");
    evaluate_branch(&context2, &branch);
    i = context2.state.getField("_if_block")->getIndex(1)->getField("i");
    test_assert(as_int(i) == 1);
    evaluate_branch(&context2, &branch);
    i = context2.state.getField("_if_block")->getIndex(1)->getField("i");
    test_assert(as_int(i) == 2);
    evaluate_branch(&context2, &branch);
    i = context2.state.getField("_if_block")->getIndex(1)->getField("i");
    test_assert(as_int(i) == 3);
}
void generate_source_for_function_calls() {
    Branch branch;

    Term* a = create_int(&branch, 5, "a");
    Term* b = create_int(&branch, 9, "b");
    Term* c = apply(&branch, "add", TermList(a,b));

    test_assert(should_print_term_source_line(a));
    test_assert(should_print_term_source_line(b));
    test_assert(should_print_term_source_line(c));
    test_equals(get_branch_source_text(&branch), "a = 5\nb = 9\nadd(a, b)");

    // Same test with anonymous values
    branch.clear();
    Term* d = create_int(&branch, 3);
    Term* e = create_int(&branch, 4);
    /*Term* f =*/ apply(&branch, "add", TermList(d,e));

    /*
    TODO, fix this
    test_assert(!should_print_term_source_line(d));
    test_assert(!should_print_term_source_line(e));
    test_assert(should_print_term_source_line(f));
    test_equals(get_branch_source_text(branch), "add(3, 4)");
    
    // Do a test where some calls are parser-created, and then user-created calls
    // are added.
    branch.clear();
    branch.compile("a = 1");
    branch.compile("b = 2");
    a = create_int(branch, 3, "c");
    b = create_int(branch, 4, "d");
    apply(branch, "add", TermList(a,b));

    test_equals(get_branch_source_text(branch), "a = 1\nb = 2\nc = 3\nd = 4\nadd(c, d)");
    */
}
void test_execution()
{
    Branch branch;

    internal_debug_function::spy_clear();

    // Start off with some simple expressions
    branch.compile("if true { test_spy('Success 1') }");
    branch.compile("if false { test_spy('Fail') }");
    branch.compile("if (1 + 2) > 1 { test_spy('Success 2') }");
    branch.compile("if (1 + 2) < 1 { test_spy('Fail') }");
    evaluate_branch(&branch);
    test_assert(&branch);
    test_equals(internal_debug_function::spy_results(), "['Success 1', 'Success 2']");
    
    // Use 'else'
    branch.clear();
    internal_debug_function::spy_clear();
    branch.compile("if true { test_spy('Success 1') } else { test_spy('Fail') }");
    branch.compile("if false { test_spy('Fail') } else { test_spy('Success 2') }");
    branch.compile("if true { test_spy('Success 3-1') test_spy('Success 3-2') test_spy('Success 3-3') } "
                "else { test_spy('Fail') }");
    branch.compile("if false { test_spy('Fail') test_spy('Fail 2') } "
                "else { test_spy('Success 4-1') test_spy('Success 4-2') test_spy('Success 4-3') }");
    evaluate_branch(&branch);
    test_assert(&branch);
    test_equals(internal_debug_function::spy_results(),
            "['Success 1', 'Success 2', 'Success 3-1', 'Success 3-2', 'Success 3-3', "
            "'Success 4-1', 'Success 4-2', 'Success 4-3']");

    // Do some nested blocks

    branch.clear();
    internal_debug_function::spy_clear();
    branch.compile("if true { if false { test_spy('Error!') } else { test_spy('Nested 1') } } "
                "else { test_spy('Error!') }");
    evaluate_branch(&branch);
    test_assert(&branch);
    test_equals(internal_debug_function::spy_results(), "['Nested 1']");

    branch.clear();
    internal_debug_function::spy_clear();
    branch.compile("if false { test_spy('Error!') } else { if false { test_spy('Error!') } "
                "else { test_spy('Nested 2') } }");
    evaluate_branch(&branch);
    test_assert(&branch);
    test_equals(internal_debug_function::spy_results(), "['Nested 2']");
    
    branch.clear();
    internal_debug_function::spy_clear();
    branch.compile("if false { test_spy('Error!') }"
                "else { if true { test_spy('Nested 3') } else { test_spy('Error!') } }");
    evaluate_branch(&branch);
    test_assert(&branch);
    test_equals(internal_debug_function::spy_results(), "['Nested 3']");

    branch.clear();
    internal_debug_function::spy_clear();
    branch.compile("if true { if false { test_spy('Error!') } else { test_spy('Nested 4') } } "
                "else { test_spy('Error!') }");
    evaluate_branch(&branch);
    test_assert(&branch);
    test_equals(internal_debug_function::spy_results(), "['Nested 4']");

    branch.clear();
    internal_debug_function::spy_clear();
    branch.compile(
    "if (false)\n"
    "  test_spy('Error!')\n"
    "else\n"
    "  if (true)\n"
    "    if (false)\n"
    "      test_spy('Error!')\n"
    "    else\n"
    "      if (false)\n"
    "        test_spy('Error!')\n"
    "      else\n"
    "         if (true)\n"
    "           test_spy('Nested 5')\n"
    "         else\n"
    "           test_spy('Error!')\n"
    "           test_spy('Error!')\n"
            );
    evaluate_branch(&branch);
    test_assert(&branch);
    test_equals(internal_debug_function::spy_results(), "['Nested 5']");
}