#!/usr/bin/env qore
# -*- mode: qore; indent-tabs-mode: nil -*-

%new-style
%enable-all-warnings
%require-types
%strict-args
%no-child-restrictions

# we will test invalid operations
%disable-warning invalid-operation

%requires ../../../../qlib/QUnit.qm

%exec-class TypeTest

class Test {
    public {
        auto a;
    }
}

public hashdecl MyHash {
    int x = 1;
}

const Test = (
    "a": {
        "a": 1,
    },
);

int sub rt(reference<list<string>> r) {
    return 1;
}

const TestList = (1, 2, 3);

class Issue3887_Base { abstract int test(softlist<auto> l); }
class Issue3887_Child inherits Issue3887_Base { int test(softlist l) { return 1; } }

class TypeTest inherits QUnit::Test {
    constructor() : QUnit::Test("TypeTest", "1.0") {
        addTestCase("issue 4133 complex types", \issue4133());
        addTestCase("issue 3887", \issue3887());
        addTestCase("hashdecl types", \hashdeclTypeTest());
        addTestCase("<string>::toBinary()", \stringToBinary());
        addTestCase("issue 3448", \issue3448());
        addTestCase("issue 3438", \issue3438());
        addTestCase("issue 3429", \issue3429());
        addTestCase("issue 3404", \issue3404());
        addTestCase("issue 3278", \issue3278());
        addTestCase("issue 3210", \issue3210());
        addTestCase("issue 3157", \issue3157());
        addTestCase("issue 2980", \issue2980());
        addTestCase("issue 2877", \issue2877());
        addTestCase("issue 2869", \issue2869());
        addTestCase("issue 2791", \issue2791());
        addTestCase("issue 2767", \issue2767());
        addTestCase("complex assignments", \testComplexAssignments());
        addTestCase("auto", \testComplexAutoTypes());
        addTestCase("complex type compat", \testComplexTypesCompat());
        addTestCase("types", \testTypes());
        addTestCase("issue 2651", \issue2651());
        addTestCase("issue 2647", \issue2647());

        set_return_value(main());
    }

    issue4133() {
        {
           *hash<string, softlist<auto>> h = {"a": 1};
           assertEq((1,), h.a);
        }
        {
           *hash<string, softlist<auto>> h += {"a": 1};
           assertEq((1,), h.a);
        }
        {
           *hash<string, softlist<auto>> h;
           map h = {"a": 1}, 1;
           assertEq((1,), h.a);
        }
        {
           *hash<string, softlist<auto>> h;
           map h += {"a": 1}, 1;
           assertEq((1,), h.a);
        }
    }

    issue3887() {
        assertEq(1, (new Issue3887_Child()).test());
    }

    hashdeclTypeTest() {
        # issue #3882
        hash<DateTimeInfo> h = now().info(){"month", "day"};
        assertEq("hash<DateTimeInfo>", h.fullType());

        hash<DateTimeInfo> h0 = h + now().info(){"month",};
        assertEq("hash<DateTimeInfo>", h0.fullType());
    }

    stringToBinary() {
        assertEq(<68656c6c6f>, "hello".toBinary());
    }

    issue3448() {
        {
            Program p(PO_NEW_STYLE);
            p.parse("softlist<auto> l0 = (1,); list<int> l1 = l0; remove l1;", "issue-3448");
        }
        {
            Program p(PO_NEW_STYLE);
            p.parse("hash<auto> h0 = {'a': 1,}; hash<string, int> h1 = h0; remove h1;", "issue-3448");
        }
        assertTrue(True);
    }

    issue3438() {
        hash<string, string> h = {"a": (*softint x = 1).toString()};
        delete x;
        assertEq("hash<string, string>", h.fullType());
    }

    issue3429() {
        hash<auto> h = {
            "a": <StatInfo>{"size": 1},
            "b": {"a": "string"},
            "c": {"a": 1},
        };

        assertEq("hash<StatInfo>", h.a.fullType());
        assertEq("hash<auto>", ({"a": 1} + {"b": "2"}).fullType());
        assertEq("list<auto>", ((1,) + ("2",)).fullType());
        assertEq("list<auto>", ((1,) + "2").fullType());
        assertEq("list<auto>", (1 + ("2",)).fullType());

        assertEq("hash<string, *int>", ({"a": 1} + {"b": NOTHING}).fullType());
        assertEq("list<*int>", ((1,) + (NOTHING,)).fullType());

        assertEq("hash<auto>", (<StatInfo>{} + {"a": 1}).fullType());
        assertEq("hash<auto>", ({"a": 1} + <StatInfo>{}).fullType());

        # test the hash map operator
        assertEq("hash<string, hash<StatInfo>>", (map {$1.key: $1.value}, {"a": <StatInfo>{}}.pairIterator()).fullType());
        assertEq("hash<string, hash<StatInfo>>", (map {$1.key: $1.value}, {"a": <StatInfo>{}}.pairIterator(), True).fullType());
        assertEq("hash<string, hash<StatInfo>>", (map {$#.toString(): $1}, <StatInfo>{}).fullType());
        assertEq("hash<string, hash<StatInfo>>", (map {$#.toString(): $1}, (<StatInfo>{},)).fullType());
        assertEq("hash<string, hash<StatInfo>>", (map {$#.toString(): $1}, <StatInfo>{}, True).fullType());
        assertEq("hash<string, hash<StatInfo>>", (map {$#.toString(): $1}, (<StatInfo>{},), True).fullType());

        assertEq("hash<StatInfo>", (map {$1.key: $1.value}, {"a": <StatInfo>{}}.pairIterator()).a.fullType());
        assertEq("hash<StatInfo>", (map {$1.key: $1.value}, {"a": <StatInfo>{}}.pairIterator(), True).a.fullType());

        {
            hash h0;
            h0.a.b = <StatInfo>{};
            assertEq("hash", h0.a.b.fullType());
        }

        {
            list<hash<StatInfo>> l = map $1, (<StatInfo>{},);
            assertEq("hash<StatInfo>", l[0].fullType());
            assertEq("list<hash<StatInfo>>", l.fullType());
        }

        {
            list<hash<StatInfo>> l = map $1, (<StatInfo>{},), True;
            assertEq("hash<StatInfo>", l[0].fullType());
            assertEq("list<hash<StatInfo>>", l.fullType());
        }
    }

    issue3404() {
        {
            Program p(PO_NEW_STYLE | PO_REQUIRE_TYPES | PO_STRICT_ARGS);
            assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("*hash<string, bool> h0; hash h1; h0 = h1;", ""));
        }

        {
            Program p(PO_NEW_STYLE | PO_REQUIRE_TYPES);
            assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("*hash<string, bool> h0; hash h1; h0 = h1;", ""));
        }

        {
            Program p(PO_NEW_STYLE);
            assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("*hash<string, bool> h0; hash h1; h0 = h1;", ""));
        }

        # make sure complex type assignments work when expected
        {
            hash<string, bool> h1();
            hash<string, bool> h2();
            hash<string, bool> h3 = h1 + h2;
            assertEq("hash<string, bool>", h3.fullType());
        }

        {
            hash<auto> h1 = {"a": True};
            hash<auto> h2 = {"b": True};
            hash<string, bool> h3 = h1 + h2;
            assertEq("hash<string, bool>", h3.fullType());
        }

        {
            list<int> l1();
            list<int> l2();
            list<int> l3 = l1 + l2;
            assertEq("list<int>", l3.fullType());
        }

        {
            list<auto> l1(1);
            list<auto> l2(2);
            list<int> l3 = l1 + l2;
            assertEq("list<int>", l3.fullType());
        }

        {
            hash h;
            *list<string> l = keys h;
            assertEq("nothing", l.fullType());
            l = keys {};
            assertEq("list<string>", l.fullType());
        }
    }

    issue3278() {
        auto x = ();
        {
            hash h = map {$1: True}, x;
            assertEq({}, h);
            assertEq("hash", h.fullType());
        }
        {
            hash<auto> h = map {$1: True}, x;
            assertEq({}, h);
            assertEq("hash<string, bool>", h.fullType());
        }
        {
            hash<string, bool> h = map {$1: True}, x;
            assertEq({}, h);
            assertEq("hash<string, bool>", h.fullType());
        }
        {
            *hash<string, int> x0 = {};
            assertEq("hash<string, int>", x0.fullType());
            hash<string, int> v = x0;
            assertEq({}, v);
            assertEq("hash<string, int>", v.fullType());
        }
        {
            *list<int> x0 = ();
            assertEq("list<int>", x0.fullType());
            list<int> v = x0;
            assertEq((), v);
            assertEq("list<int>", v.fullType());
        }
        {
            *softlist<int> x0 = ();
            assertEq("list<int>", x0.fullType());
            softlist<int> v = x0;
            assertEq((), v);
            assertEq("list<int>", v.fullType());
        }
        {
            hash<auto> h;
            h += {"a": 1};
            h += {"b": (2,)};
            assertEq("hash<auto>", h.fullType());
        }
        {
            *hash<auto> h;
            h += {"a": 1};
            h += {"b": (2,)};
            assertEq("hash<auto>", h.fullType());
        }
    }

    issue3210() {
        {
            Program p(PO_NEW_STYLE);
            p.parse("sub test() { list<string> l0; softlist<string> l1; l1 += l0; }", "");
            assertThrows("RUNTIME-TYPE-ERROR", "list element assignment.*list<string>", \p.callFunction(), "test");
        }
        {
            Program p(PO_NEW_STYLE);
            p.parse("sub test() { softlist<string> l(); auto x = 1; l = x; }", "");
            assertThrows("RUNTIME-TYPE-ERROR", "list<string>", \p.callFunction(), "test");
        }
    }

    issue3157() {
        timeout t = 3s;
        t -= 1s;
        assertEq(2000, t);

        assertEq(NT_DATE, (t - 1s).typeCode());
        assertEq(NT_DATE, (10s - t).typeCode());
        assertEq(NT_DATE, (t + 1s).typeCode());
        assertEq(NT_DATE, (10s + t).typeCode());

        t = 3s;
        t = t - 1s;
        assertEq(2000, t);

        t = 3s;
        t = 1s - t;
        assertEq(-2000, t);

        t = 3s;
        t += 1s;
        assertEq(4000, t);

        t = 3s;
        t = t + 1s;
        assertEq(4000, t);

        t = 3s;
        t = 1s + t;
        assertEq(4000, t);

        t = 3000;
        t -= 1s;
        assertEq(2000, t);

        t = 3000;
        t = t - 1s;
        assertEq(2000, t);

        t = 3000;
        t = 1s - t;
        assertEq(-2000, t);

        t = 3000;
        t += 1s;
        assertEq(4000, t);

        t = 3000;
        t = t + 1s;
        assertEq(4000, t);

        t = 3000;
        t = 1s + t;
        assertEq(4000, t);
    }

    issue2980() {
        softlist<auto> l = new hash<StatInfo>();
        assertEq("hash<StatInfo>", l[0].fullType());
    }

    issue2877() {
        hash<auto> h = {
            "a": 1,
            "b": 2,
        };

        assertEq("hash<string, int>", h.fullType());
        assertEq("list<int>", h.values().fullType());
        assertEq("list<int>", hash_values(h).fullType());
    }

    issue2869() {
        hash h = {};
        h += {"a": {"x": 1}};
        assertEq(Type::Hash, h.a.fullType());
    }

    issue2791() {
        {
            Test t();
            t.a = {"a": "two"};
            hash h = t{"a",};
            assertEq(Type::Hash, h.a.fullType());
        }
        {
            hash<auto> h1 = {
                "a": {"a": "a"},
            };
            hash h = h1{"a",};
            assertEq(Type::Hash, h.a.fullType());
        }
        {
            hash h;
            h.a = hash<MyHash>{};
            # ensure types are stripped on assignment with internal values of untyped hashes
            assertEq(Type::Hash, h.a.fullType());
        }
        {
            hash h = {
                "a": {"a": 1},
                "b": 1,
            };
            h.a = hash<MyHash>{};
            # ensure types are stripped on assignment with internal values of untyped hashes
            # also with type folding
            assertEq(Type::Hash, h.a.fullType());
        }
        {
            auto h = {
                "a": {"a": 1},
                "b": {"a": "1"},
            };
            # ensure consistent type folding
            assertEq("hash<string, hash<auto>>", h.fullType());
            assertEq("hash<string, int>", h.a.fullType());
        }
        {
            auto h = {
                "a": {"a": 1},
            } + {
                "b": {"a": "1"},
            };
            # ensure consistent type folding
            assertEq("hash<string, hash<auto>>", h.fullType());
            assertEq("hash<string, int>", h.a.fullType());
            h.a.b = 2;
        }
        {
            any h;
            h.a = hash<MyHash>{};
            # ensure types are stripped on assignment with internal values of untyped hashes
            assertEq(Type::Hash, h.a.fullType());
        }
        {
            hash<auto> h;
            h.a = hash<MyHash>{};
            assertEq("hash<MyHash>", h.a.fullType());
        }
        {
            auto h = {"a": {"a": 2}} + {"b": {"a": "1"}};
            assertEq("hash<string, int>", h.a.fullType());
            assertEq("hash<string, string>", h.b.fullType());
            assertEq("hash<string, hash<auto>>", h.fullType());
        }
        {
            list<auto> l = ({"a": "a"}, );
            list l1 = l[0..];
            assertEq("list<hash<string, string>>", l.fullType());
            assertEq("hash<string, string>", l[0].fullType());
            assertEq(Type::Hash, l1[0].fullType());
            l1 = extract l, 0;
            assertEq(Type::Hash, l1[0].fullType());
        }
        {
            list l;
            l += hash<MyHash>{};
            # ensure types are stripped on assignment with internal values of untyped lists
            assertEq(Type::Hash, l[0].fullType());
        }
        {
            list l = ({"a": 1}, 1);
            # ensure types are stripped on assignment with internal values of untyped hashes
            # also with type folding
            assertEq(Type::Hash, l[0].fullType());
        }
        {
            any l;
            l[0] = hash<MyHash>{};
            # ensure types are stripped on assignment with internal values of untyped lists
            assertEq(Type::Hash, l[0].fullType());
        }
        {
            list<auto> l;
            l += hash<MyHash>{};
            assertEq("hash<MyHash>", l[0].fullType());
        }
        {
            list l;
            l += hash<MyHash>{};
            # ensure types are stripped on assignment with internal values of untyped lists
            assertEq(Type::Hash, l[0].fullType());
        }
        {
            auto l = (1, 2,) + ("3",);
            assertEq("list<auto>", l.fullType());
        }
        {
            auto l = (1, 2,) + "3";
            assertEq("list<auto>", l.fullType());
        }
        {
            auto l = ("3",) + (1, 2,);
            assertEq("list<auto>", l.fullType());
        }
        {
            auto l = "3" + (1, 2,);
            assertEq("list<auto>", l.fullType());
        }
    }

    issue2767() {
        {
            hash<auto> h;
            h.a = 1;
            assertEq("hash<auto>", h.fullType());
            h.b.a = 1;
            assertEq("hash<auto>", h.b.fullType());
        }

        {
            list<auto> l;
            l[0] = 1;
            assertEq("list<auto>", l.fullType());
            l[1][0] = 1;
            assertEq("list<auto>", l[1].fullType());
        }
    }

    testComplexAssignments() {
        {
            # issue #2652: implicit creation of an lvalue with a complex type
            *hash<string, bool> h;
            h.a = True;
            assertEq("hash<string, bool>", h.fullType());
        }
        {
            # issue #2652: implicit creation of an lvalue with a complex type
            hash<string, bool> h;
            h.a = True;
            assertEq("hash<string, bool>", h.fullType());
        }
        {
            # issue #2652: implicit creation of an lvalue with a complex type
            *list<bool> l;
            l[0] = True;
            assertEq("list<bool>", l.fullType());
        }
        {
            # issue #2652: implicit creation of an lvalue with a complex type
            list<bool> l;
            l[0] = True;
            assertEq("list<bool>", l.fullType());
        }
        {
            # issue #2652: implicit creation of an lvalue with a complex type
            *softlist<bool> l;
            l[0] = True;
            assertEq("list<bool>", l.fullType());
        }
        {
            # issue #2652: implicit creation of an lvalue with a complex type
            softlist<bool> l;
            l[0] = True;
            assertEq("list<bool>", l.fullType());
        }

        hash h = (
            "a": ("a": 1),
        );

        hash val;
        h += (
            "a": val,
        );
        assertEq("hash<string, nothing>", ("a": val).fullType());
        list l = ();
        l += (val,);
        assertEq("list<hash<string, nothing>>", (("a": val),).fullType());

        any anyval = ("a": 1);
        h = ("a": anyval);
        assertEq(Type::Hash, h.fullType());

        assertEq("hash<string, hash<string, int>>", Test.fullType());
        *string cmd = Test.a.b;
        assertEq(NOTHING, cmd);
        any nval = "a";
        cmd = Test{nval}.b;
        assertEq(NOTHING, cmd);

        assertEq("list<int>", TestList.fullType());
        cmd = TestList[4];
        assertEq(NOTHING, cmd);
        nval = 4;
        cmd = TestList[nval];
        assertEq(NOTHING, cmd);

        {
            list l1;
            reference<list<string>> r = \l1;
            assertEq(l1, r);
        }

        {
            code c = int sub (reference<list<string>> r) {
                return 1;
            };
            list l1;
            assertEq(1, rt(\l1));
            assertEq(1, c(\l1));
        }
    }

    testComplexAutoTypes() {
        {
            any a = (1, 2);
            assertEq("list", a.fullType());
            code c = any sub (any a) { return a; };
            assertEq("list", c(a).fullType());
            c = auto sub (any a) { return a; };
            assertEq("list", c(a).fullType());
            c = any sub (auto a) { return a; };
            assertEq("list", c(a).fullType());
        }
        {
            auto a = (1, 2);
            assertEq("list<int>", a.fullType());
            code c = auto sub (auto a) { return a; };
            assertEq("list<int>", c(a).fullType());
        }

        list<auto> l0 = ("str0", "str1");
        assertEq("list<string>", l0.fullType());
        softlist<auto> l1 = ("str0", "str1");
        assertEq("list<string>", l1.fullType());
        *list<auto> l2 = ("str0", "str1");
        assertEq("list<string>", l2.fullType());
        *softlist<auto> l3 = ("str0", "str1");
        assertEq("list<string>", l3.fullType());

        hash<auto> h0 = ("a": 1, "b": 2);
        assertEq("hash<string, int>", h0.fullType());
        hash<string, auto> h1 = ("a": 1, "b": 2);
        assertEq("hash<string, int>", h1.fullType());
        hash<auto> h2 = new hash<MyHash>();
        assertEq("hash<MyHash>", h2.fullType());

        # reference<auto> == reference<any>
        reference<auto> r = \h0;
        assertEq("hash<string, int>", r.fullType());

        {
            hash h = {};
            *hash h9 = ("a": ());
            h += ("a": ("a": ("a": 1), "b": h9));
            assertEq("hash", h.fullType());
            assertEq("hash", h.a.b.fullType());
        }

        {
            list<auto> l();
            assertEq("list<auto>", l.fullType());
            l += new hash<MyHash>();
            assertEq("hash<MyHash>", l[0].fullType());
            l[0] = new hash<MyHash>();
            assertEq("hash<MyHash>", l[0].fullType());

            hash<auto> h();
            assertEq("hash<auto>", h.fullType());
            h += ("a": new hash<MyHash>());
            assertEq("hash<MyHash>", h.a.fullType());
            h.a = new hash<MyHash>();
            assertEq("hash<MyHash>", h.a.fullType());
        }
    }

    testComplexTypesCompat() {
        {
            Program p(PO_NEW_STYLE);
            p.parse("sub t() {\n#hash<string, int> h0();\n#hash<MyHash> h1();\n#list<int> l0();\n}\n", "");
        }

        {
            hash<MyHash> h();
            assertEq(True, h.complexType());
            assertEq(1, h.x);
            # assigning to an untyped variable strips the type information for backwards-compatibility
            any h0 = h;
            assertEq(1, h0.x);
            assertEq(False, h0.complexType());
            h0.a = 2;
            assertEq(2, h0.a);
            assertThrows("INVALID-MEMBER", sub () { reference r = \h; r.a = "a"; });
            # verify that a failed reference assignment does not strip complex type information from the lvalue
            hash ih = testAnyArg(h);
            assertEq(True, ih.complex);
            assertEq("hash<MyHash>", ih.type);
        }

        {
            hash<string, int> h();
            assertEq(True, h.complexType());
            # assigning to an untyped variable strips the type information for backwards-compatibility
            any h0 = h;
            assertEq(False, h0.complexType());
            h0.a = "a";
            assertEq("a", h0.a);
            assertThrows("RUNTIME-TYPE-ERROR", sub () { reference r = \h; r.a = "a"; });
            # verify that a failed reference assignment does not strip complex type information from the lvalue
            hash ih = testAnyArg(h);
            assertEq(True, ih.complex);
            assertEq("hash<string, int>", ih.type);
        }

        {
            list<int> l();
            assertEq(True, l.complexType());
            # assigning to an untyped variable strips the type information for backwards-compatibility
            any l0 = l;
            assertEq(False, l0.complexType());
            l0 += "a";
            assertEq("a", l0[0]);
            assertThrows("RUNTIME-TYPE-ERROR", sub () { reference r = \l; r += "a"; });
            # verify that a failed reference assignment does not strip complex type information from the lvalue
            hash ih = testAnyArg(l);
            assertEq(True, ih.complex);
            assertEq("list<int>", ih.type);
        }

        {
            softlist<int> l();
            assertEq(True, l.complexType());
            # assigning to an untyped variable strips the type information for backwards-compatibility
            any l0 = l;
            assertEq(False, l0.complexType());
            l0 += "a";
            assertEq("a", l0[0]);
            assertThrows("RUNTIME-TYPE-ERROR", sub () { reference r = \l; r += "a"; });
            # verify that a failed reference assignment does not strip complex type information from the lvalue
            hash ih = testAnyArg(l);
            assertEq(True, ih.complex);
            assertEq("softlist<int>", ih.type);
        }

        {
            softlist<softint> l = "1";
            assertEq(1, l[0]);
            assertEq(True, l.complexType());
            # assigning to an untyped variable strips the type information for backwards-compatibility
            any l0 = l;
            assertEq(False, l0.complexType());
            l0 += "a";
            assertEq("a", l0[1]);
            hash<auto> ih = testAnyArg(l);
            assertEq(True, ih.complex);
            assertEq("list<softint>", ih.type);
            l += "2";
            assertEq(2, l[1]);
        }

        {
            Program p(PO_NEW_STYLE);
            assertThrows("PARSE-EXCEPTION", "unknown member", \p.parse(), ("sub t() {hash<MyHash> h(); h.a = 2;}", ""));
        }

        {
            Program p(PO_NEW_STYLE);
            assertThrows("PARSE-TYPE-ERROR", "lvalue for assignment", \p.parse(), ("sub t() {hash<string, int> h(); h.a = 'a';}", ""));
        }

        {
            Program p(PO_NEW_STYLE);
            assertThrows("PARSE-TYPE-ERROR", "lvalue for assignment", \p.parse(), ("sub t() {list<int> l(); l[0] = 'a';}", ""));
        }

        {
            Program p(PO_NEW_STYLE);
            assertThrows("PARSE-TYPE-ERROR", "cannot append", \p.parse(), ("sub t() {list<int> l(); l += 'a';}", ""));
        }
    }

    testTypes() {
        {
            hash<StatInfo> h0({"size": 1});
            hash<auto> h1 = hash(h0);
            assertEq(Type::Hash, h1.fullType());
            assertEq(1, h1.size);
            h1.newkey = 2;
            assertEq(2, h1.newkey);
        }
        {
            int i = 1;
            assertEq(1, i);
            assertEq(True, i instanceof int);
            assertEq(True, i instanceof softint);
            assertEq(True, i instanceof *softint);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { int i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { int i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { int i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { int i = \"\"; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { int i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { int i = NULL; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { int i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { int i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { int i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { int i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { int i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { int i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { int i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NULL; int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            float i = 1.0;
            assertEq(1.0, i);
            i = 1;
            assertEq(1.0, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { float i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { float i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { float i = \"\"; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { float i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { float i = NULL; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { float i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { float i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { float i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { float i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { float i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { float i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { float i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NULL; float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            number i = 1n;
            assertEq(1n, i);
            i = 1.0;
            assertEq(1n, i);
            i = 1;
            assertEq(1n, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { number i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { number i = \"\"; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { number i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { number i = NULL; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { number i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { number i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { number i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { number i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { number i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { number i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { number i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NULL; number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            string i = "1";
            assertEq("1", i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { string i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { string i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { string i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { string i = True; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { string i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { string i = NULL; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { string i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { string i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { string i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { string i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { string i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { string i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { string i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NULL; string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            bool i = True;
            assertEq(True, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { bool i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { bool i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { bool i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { bool i = \"\"; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { bool i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { bool i = NULL; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { bool i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { bool i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { bool i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { bool i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { bool i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { bool i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { bool i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NULL; bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            date i = 2017-07-10;
            assertEq(2017-07-10, i);
            i = 1s;
            assertEq(1s, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { date i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { date i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { date i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { date i = \"\"; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { date i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { date i = NULL; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { date i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { date i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { date i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { date i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { date i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { date i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { date i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NULL; date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            binary i = <ab>;
            assertEq(<ab>, i);

            {
                hexbinary b = "ab";
                assertEq(<ab>, b);
                assertThrows("PARSE-HEX-ERROR", sub () { hexbinary x = "gi"; remove x; });
            }

            {
                base64binary b = "qw==";
                assertEq(<ab>, b);
                assertThrows("BASE64-PARSE-ERROR", sub () { base64binary x = "gi"; remove x; });
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { binary i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { binary i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { binary i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { binary i = \"\"; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { binary i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { binary i = NULL; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { binary i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { binary i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { binary i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { binary i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { binary i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { binary i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NULL; binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            hash i = {};
            assertEq({}, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { hash i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { hash i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { hash i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { hash i = \"\"; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { hash i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { hash i = NULL; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { hash i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { hash i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { hash i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { hash i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { hash i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { hash i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { hash i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NULL; hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            {
                hash<string, softint> h(("a": "23"));
                assertEq(23, h.a);
                assertEq(Type::Hash, h.type());

                h = cast<hash<string, softint>>(new hash<string, int>(("b": 2, "c": 3)));
                assertEq(2, h.b);
                assertEq(3, h.c);

                h.d = "50";
                assertEq(50, h.d);
            }

            {
                # make sure map operators return the correct parse- and runtime types
                hash<string, int> h = map {$1: 1}, "a";
                assertEq(1, h.a);

                # make sure parse hashes return the correct parse- and runtime types
                h = ("a": 1);
                assertEq(1, h.a);
                int i = 0;
                h = ("a": i);
                assertEq(0, h.a);
            }

            {
                # make sure that a runtime assignment from a typed hash to an untyped hash results in an untyped hash assignment
                hash h = new hash<string, int>(("a": 1));
                h.b = "str";
                assertEq("str", h.b);
            }

            {
                hash<string, int> h1;
                hash<string, int> h2;
                map h1.$1 = 1, "a";
                h2 = h1;

                hash h3 = cast<hash>(h2);
                h3.b = "string";
                assertEq("string", h3.b);
            }

            {
                hash<string, hash> h = (("a": ("a": "a")));
                assertEq("a", h.a.a);
            }

            {
                hash<string, softint> h();
                h = new hash<string, int>(('b': 2, 'c': 3));
                assertEq(2, h.b);
            }

            {
                hash<string, softint> h = ("a": "2");
                assertEq(2, h.a);
                assertEq(True, h instanceof hash<string, softint>);
            }

            {
                # cast to hash from a non-hash must fail at parse time
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-EXCEPTION", \p.parse(), ("sub t() { any h = cast<hash>(1); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", "complex", \p.parse(), ("sub t() { hash<int, int> h(); }", ""));
            }
        }

        {
            list i = ();
            assertEq((), i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { list i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { list i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { list i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { list i = \"\"; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { list i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { list i = NULL; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { list i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { list i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { list i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { list i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { list i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { list i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { list i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NULL; list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            {
                list<softint> l("1", "2");
                assertEq("list<softint>", l.fullType());
                assertEq((1, 2), l);
                assertEq(Type::List, l.type());

                l = new list<int>(2, 3);
                assertEq("list<softint>", l.fullType());
                assertEq(2, l[0]);
                assertEq(3, l[1]);

                l[3] = "50";
                assertEq(50, l[3]);

                l += "20";
                assertEq(20, l[4]);

                l += ("5", 4.1);
                assertEq(5, l[5]);
                assertEq(4, l[6]);
            }

            {
                # make sure map operators return the correct parse- and runtime types
                list<int> l = map 1, ("a",);
                assertEq(1, l[0]);

                # make sure parse hashes return the correct parse- and runtime types
                l = (1,);
                assertEq(1, l[0]);
                int i = 0;
                l[0] = (i,)[0];
                assertEq(0, l[0]);
            }

            {
                # make sure that a runtime assignment from a typed list to an untyped list results in an untyped list assignment
                list l = new list<int>(1);
                l[1] = "str";
                assertEq("str", l[1]);
            }

            {
                list<int> l1;
                list<int> l2;
                map l1 += 1, "a";
                l2 = l1;

                list l3 = cast<list>(l2);
                l3 += "string";
                assertEq("string", l3[1]);
            }

            {
                list<list> l = ((1, 2), ("a", "b"));
                assertEq(1, l[0][0]);
                assertEq("a", l[1][0]);
            }

            {
                list<softint> l();
                l = new list<int>(2, 3);
                assertEq(2, l[0]);
            }

            {
                list<softint> l = ("2",);
                assertEq(2, l[0]);
                assertEq(True, l instanceof list<softint>);
            }

            {
                any l = list(new list<int>(1));
                l += "2";
                assertEq("2", l[1]);
            }

            {
                # cast to list from a non-list must fail at parse time
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-EXCEPTION", \p.parse(), ("sub t() { any l = cast<list>(1); }", ""));
            }
        }

        {
            Mutex m();
            object i = m;
            assertEq(m, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { object i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { object i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { object i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { object i = \"\"; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { object i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { object i = NULL; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { object i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { object i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { object i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { object i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { object i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { object i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { object i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NULL; object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            timeout i = 1970-01-01;
            assertEq(0, i);
            i = 1;
            assertEq(1, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { timeout i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { timeout i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { timeout i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { timeout i = \"\"; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { timeout i = NULL; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { timeout i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { timeout i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { timeout i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { timeout i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { timeout i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { timeout i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { timeout i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NULL; timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            data i = "";
            assertEq("", i);
            i = <ab>;
            assertEq(<ab>, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { data i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { data i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { data i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { data i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { data i = NULL; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { data i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { data i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { data i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { data i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { data i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { data i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NULL; data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            null i = NULL;
            assertEq(NULL, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            nothing i = NOTHING;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { nothing i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { nothing i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { nothing i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { nothing i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { nothing i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { nothing i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { nothing i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { nothing i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { nothing i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { nothing i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { nothing i = NULL; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; nothing i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; nothing i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; nothing i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); nothing i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; nothing i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; nothing i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; nothing i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); nothing i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); nothing i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); nothing i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NULL; nothing i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            *int i = 1;
            assertEq(1, i);
            i = NOTHING;
            assertEq(NOTHING, i);
            i = NULL;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *int i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *int i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *int i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *int i = \"\"; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *int i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *int i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *int i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *int i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *int i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *int i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *int i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; *int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; *int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; *int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; *int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); *int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; *int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); *int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); *int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; *int i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            *float i = 1.0;
            assertEq(1.0, i);
            i = 1;
            assertEq(1.0, i);
            i = NOTHING;
            assertEq(NOTHING, i);
            i = NULL;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *float i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *float i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *float i = \"\"; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *float i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *float i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *float i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *float i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *float i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *float i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *float i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; *float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; *float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; *float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); *float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; *float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); *float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); *float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; *float i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            *number i = 1n;
            assertEq(1n, i);
            i = 1.0;
            assertEq(1n, i);
            i = 1;
            assertEq(1n, i);
            i = NOTHING;
            assertEq(NOTHING, i);
            i = NULL;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *number i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *number i = \"\"; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *number i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *number i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *number i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *number i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *number i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *number i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *number i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; *number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; *number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); *number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; *number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); *number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); *number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; *number i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            *string i = "1";
            assertEq("1", i);
            i = NOTHING;
            assertEq(NOTHING, i);
            i = NULL;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *string i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *string i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *string i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *string i = True; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *string i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *string i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *string i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *string i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *string i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *string i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *string i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; *string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; *string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; *string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; *string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); *string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; *string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); *string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); *string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; *string i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            *bool i = True;
            assertEq(True, i);
            i = NOTHING;
            assertEq(NOTHING, i);
            i = NULL;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *bool i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *bool i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *bool i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *bool i = \"\"; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *bool i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *bool i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *bool i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *bool i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *bool i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *bool i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *bool i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; *bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; *bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; *bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; *bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); *bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; *bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); *bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); *bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; *bool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

        }

        {
            *date i = 2017-07-10;
            assertEq(2017-07-10, i);
            i = 1s;
            assertEq(1s, i);
            i = NOTHING;
            assertEq(NOTHING, i);
            i = NULL;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *date i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *date i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *date i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *date i = \"\"; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *date i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *date i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *date i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *date i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *date i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *date i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *date i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; *date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; *date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; *date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; *date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; *date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; *date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); *date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); *date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; *date i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

        }

        {
            *binary i = <ab>;
            assertEq(<ab>, i);
            i = NOTHING;
            assertEq(NOTHING, i);
            i = NULL;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *binary i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *binary i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *binary i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *binary i = \"\"; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *binary i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *binary i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *binary i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *binary i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *binary i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *binary i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; *binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; *binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; *binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; *binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; *binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; *binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); *binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); *binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); *binary i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            *hash i = {};
            assertEq({}, i);
            i = NOTHING;
            assertEq(NOTHING, i);
            i = NULL;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *hash i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *hash i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *hash i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *hash i = \"\"; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *hash i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *hash i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *hash i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *hash i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *hash i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *hash i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *hash i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; *hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; *hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; *hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; *hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; *hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; *hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); *hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); *hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); *hash i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            *list i = ();
            assertEq((), i);
            i = NOTHING;
            assertEq(NOTHING, i);
            i = NULL;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *list i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *list i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *list i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *list i = \"\"; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *list i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *list i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *list i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *list i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *list i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *list i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *list i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; *list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; *list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; *list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; *list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; *list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; *list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; *list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); *list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); *list i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            Mutex m();
            *object i = m;
            assertEq(m, i);
            i = NOTHING;
            assertEq(NOTHING, i);
            i = NULL;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *object i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *object i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *object i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *object i = \"\"; }", ""));
            }

            # issue #2001
            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *object i = 2017-07-10; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *object i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *object i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *object i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *object i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *object i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *object i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; *object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; *object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; *object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; *object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; *object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; *object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; *object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); *object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); *object i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            *timeout i = 1970-01-01;
            assertEq(0, i);
            i = 1;
            assertEq(1, i);
            i = NOTHING;
            assertEq(NOTHING, i);
            i = NULL;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *timeout i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *timeout i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *timeout i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *timeout i = \"\"; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *timeout i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *timeout i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *timeout i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *timeout i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *timeout i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *timeout i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; *timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; *timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \"\"; *timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; *timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; *timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; *timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); *timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); *timeout i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            *data i = "";
            assertEq("", i);
            i = <ab>;
            assertEq(<ab>, i);
            i = NOTHING;
            assertEq(NOTHING, i);
            i = NULL;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *data i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *data i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *data i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *data i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *data i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *data i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *data i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *data i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *data i = \\i; }", ""));
            }

            # issue #2002
            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; *data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; *data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; *data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); *data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; *data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; *data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); *data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); *data i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            *null i = NULL;
            assertEq(NULL, i);
            i = NOTHING;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { null i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1.0; null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1n; null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = 1; null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = True; null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = now(); null i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            softint i = 1;
            assertEq(1, i);
            i = 1.0;
            assertEq(1, i);
            i = 1.9;
            assertEq(1, i);
            i = 1.9n;
            assertEq(1, i);
            i = "1.9";
            assertEq(1, i);
            i = 1s + 590ms;
            assertEq(1, i);
            i = True;
            assertEq(1, i);
            i = False;
            assertEq(0, i);
            i = NULL;
            assertEq(0, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softint i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softint i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softint i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softint i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softint i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softint i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softint i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; softint i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); softint i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); softint i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); softint i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; softint i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; softint i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; softint i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            softfloat i = 1;
            assertEq(1.0, i);
            i = 1.0n;
            assertEq(1.0, i);
            i = 1.9n;
            assertEq(1.9, i);
            i = "1.9";
            assertEq(1.9, i);
            i = 1s + 590ms;
            assertEq(1.0, i);
            i = True;
            assertEq(1.0, i);
            i = False;
            assertEq(0.0, i);
            i = NULL;
            assertEq(0.0, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softfloat i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softfloat i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softfloat i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softfloat i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softfloat i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softfloat i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softfloat i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; softfloat i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); softfloat i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); softfloat i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); softfloat i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; softfloat i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; softfloat i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; softfloat i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            softnumber i = 1;
            assertEq(1n, i);
            i = 1.0;
            assertEq(1n, i);
            i = 1.5;
            assertEq(1.5n, i);
            i = 1;
            assertEq(1n, i);
            i = "1.9";
            assertEq(1.9n, i);
            i = 1s + 590ms;
            assertEq(1n, i);
            i = True;
            assertEq(1n, i);
            i = False;
            assertEq(0n, i);
            i = NULL;
            assertEq(0n, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softnumber i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softnumber i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softnumber i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softnumber i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softnumber i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softnumber i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softnumber i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; softnumber i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); softnumber i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); softnumber i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); softnumber i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; softnumber i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; softnumber i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; softnumber i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            softbinary b = "1";
            assertEq(<31>, b);
            b = NULL;
            assertEq(binary(), b);
            b = <3132>;
            assertEq(<3132>, b);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softbinary b = 1; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softbinary b = 1.0; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softbinary b = 1n; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softbinary b = True; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softbinary b = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softbinary b = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softbinary b = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softbinary b = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softbinary b = \\b; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softbinary b = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { auto x = 1; softbinary b = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { auto x = 1.0; softbinary b = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { auto x = 1n; softbinary b = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { auto x = True; softbinary b = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { auto x = {}; softbinary b = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { auto x = (); softbinary b = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { auto x = new Mutex(); softbinary b = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { auto x = \\printf(); softbinary b = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { auto x1; any x = \\x1; softbinary b = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { auto x = NOTHING; softbinary b = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            softbool i = 1;
            assertEq(True, i);
            i = 1.0;
            assertEq(True, i);
            i = 1.9;
            assertEq(True, i);
            i = 1.9n;
            assertEq(True, i);
            i = "1.9";
            assertEq(True, i);
            i = 1s + 590ms;
            assertEq(True, i);
            i = True;
            assertEq(True, i);
            i = False;
            assertEq(False, i);
            i = NULL;
            assertEq(False, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softbool i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softbool i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softbool i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softbool i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softbool i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softbool i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softbool i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; softbool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); softbool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); softbool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); softbool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; softbool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; softbool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; softbool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            softstring i = 1;
            assertEq("1", i);
            i = 1.0;
            assertEq("1.0", i);
            i = 1.9;
            assertEq("1.9", i);
            i = 1.9n;
            assertEq("1.9", i);
            i = "1.9";
            assertEq("1.9", i);
            i = 1s + 590ms;
            assertEq("00000000000001", i);
            i = True;
            assertEq("1", i);
            i = False;
            assertEq("0", i);
            i = NULL;
            assertEq("", i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softstring i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softstring i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softstring i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softstring i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softstring i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softstring i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softstring i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; softstring i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); softstring i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); softstring i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); softstring i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; softstring i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; softstring i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; softstring i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            softdate i = 1;
            assertEq(1970-01-01T00:00:01, i);
            i = 1.0;
            assertEq(1970-01-01T00:00:01, i);
            i = 1.9;
            assertEq(1970-01-01T00:00:01, i);
            i = 1.5n;
            assertEq(1970-01-01T00:00:01.5, i);
            i = "2017-07-10";
            assertEq(2017-07-10, i);
            i = 1s + 590ms;
            assertEq(1s + 590ms, i);
            i = True;
            assertEq(1970-01-01T00:00:01, i);
            i = False;
            assertEq(1970-01-01, i);
            i = NULL;
            assertEq(1970-01-01, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softdate i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softdate i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softdate i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softdate i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softdate i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softdate i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { softdate i = NOTHING; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; softdate i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); softdate i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); softdate i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); softdate i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x1; any x = \\x1; softdate i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; softdate i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = NOTHING; softdate i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            softlist i = 1;
            assertEq((1,), i);
            i = 1.0;
            assertEq((1.0,), i);
            i = 1n;
            assertEq((1n,), i);
            i = 1s;
            assertEq((1s,), i);
            i = True;
            assertEq((True,), i);
            i = "hi";
            assertEq(("hi",), i);
            i = ();
            assertEq((), i);
            i = {};
            assertEq(({},), i);
            Mutex m();
            i = m;
            assertEq((m,), i);
            i = \printf();
            assertEq((\printf(),), i);
            i = <ab>;
            assertEq((<ab>,), i);
            i = NULL;
            assertEq((NULL,), i);
            i = NOTHING;
            assertEq((), i);
        }

        {
            *softint i = 1;
            assertEq(1, i);
            i = 1.0;
            assertEq(1, i);
            i = 1.9;
            assertEq(1, i);
            i = 1.9n;
            assertEq(1, i);
            i = "1.9";
            assertEq(1, i);
            i = 1s + 590ms;
            assertEq(1, i);
            i = True;
            assertEq(1, i);
            i = False;
            assertEq(0, i);
            i = NULL;
            assertEq(NOTHING, i);
            i = NOTHING;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softint i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softint i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softint i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softint i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softint i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softint i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; *softint i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); *softint i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); *softint i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *softint i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; *softint i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            *softfloat i = 1;
            assertEq(1.0, i);
            i = 1.0n;
            assertEq(1.0, i);
            i = 1.9n;
            assertEq(1.9, i);
            i = "1.9";
            assertEq(1.9, i);
            i = 1s + 590ms;
            assertEq(1.0, i);
            i = True;
            assertEq(1.0, i);
            i = False;
            assertEq(0.0, i);
            i = NULL;
            assertEq(NOTHING, i);
            i = NOTHING;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softfloat i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softfloat i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softfloat i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softfloat i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softfloat i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softfloat i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; *softfloat i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); *softfloat i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); *softfloat i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *softfloat i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; *softfloat i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            *softnumber i = 1;
            assertEq(1n, i);
            i = 1.0;
            assertEq(1n, i);
            i = 1.5;
            assertEq(1.5n, i);
            i = 1;
            assertEq(1n, i);
            i = "1.9";
            assertEq(1.9n, i);
            i = 1s + 590ms;
            assertEq(1n, i);
            i = True;
            assertEq(1n, i);
            i = False;
            assertEq(0n, i);
            i = NULL;
            assertEq(NOTHING, i);
            i = NOTHING;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softnumber i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softnumber i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softnumber i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softnumber i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softnumber i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softnumber i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; *softnumber i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); *softnumber i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); *softnumber i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *softnumber i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; *softnumber i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            *softbool i = 1;
            assertEq(True, i);
            i = 1.0;
            assertEq(True, i);
            i = 1.9;
            assertEq(True, i);
            i = 1.9n;
            assertEq(True, i);
            i = "1.9";
            assertEq(True, i);
            i = 1s + 590ms;
            assertEq(True, i);
            i = True;
            assertEq(True, i);
            i = False;
            assertEq(False, i);
            i = NULL;
            assertEq(NOTHING, i);
            i = NOTHING;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softbool i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softbool i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softbool i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softbool i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softbool i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softbool i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; *softbool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); *softbool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); *softbool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *softbool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; *softbool i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            *softstring i = 1;
            assertEq("1", i);
            i = 1.0;
            assertEq("1.0", i);
            i = 1.9;
            assertEq("1.9", i);
            i = 1.9n;
            assertEq("1.9", i);
            i = "1.9";
            assertEq("1.9", i);
            i = 1s + 590ms;
            assertEq("00000000000001", i);
            i = True;
            assertEq("1", i);
            i = False;
            assertEq("0", i);
            i = NULL;
            assertEq(NOTHING, i);
            i = NOTHING;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softstring i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softstring i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softstring i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softstring i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softstring i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softstring i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; *softstring i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); *softstring i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); *softstring i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *softstring i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; *softstring i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            *softdate i = 1;
            assertEq(1970-01-01T00:00:01, i);
            i = 1.0;
            assertEq(1970-01-01T00:00:01, i);
            i = 1.9;
            assertEq(1970-01-01T00:00:01, i);
            i = 1.5n;
            assertEq(1970-01-01T00:00:01.5, i);
            i = "2017-07-10";
            assertEq(2017-07-10, i);
            i = 1s + 590ms;
            assertEq(1s + 590ms, i);
            i = True;
            assertEq(1970-01-01T00:00:01, i);
            i = False;
            assertEq(1970-01-01, i);
            i = NULL;
            assertEq(NOTHING, i);
            i = NOTHING;
            assertEq(NOTHING, i);

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softdate i = {}; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softdate i = (); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softdate i = new Mutex(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softdate i = \\printf(); }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softdate i = \\i; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                assertThrows("PARSE-TYPE-ERROR", \p.parse(), ("sub t() { *softdate i = <ab>; }", ""));
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = {}; *softdate i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = (); *softdate i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = new Mutex(); *softdate i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = \\printf(); *softdate i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }

            {
                Program p(PO_NEW_STYLE);
                p.parse("sub t() { any x = <ab>; *softdate i = x; }", "");
                assertThrows("RUNTIME-TYPE-ERROR", \p.callFunction(), "t");
            }
        }

        {
            *softlist i = 1;
            assertEq((1,), i);
            i = 1.0;
            assertEq((1.0,), i);
            i = 1n;
            assertEq((1n,), i);
            i = 1s;
            assertEq((1s,), i);
            i = True;
            assertEq((True,), i);
            i = "hi";
            assertEq(("hi",), i);
            i = ();
            assertEq((), i);
            i = {};
            assertEq(({},), i);
            Mutex m();
            i = m;
            assertEq((m,), i);
            i = \printf();
            assertEq((\printf(),), i);
            i = <ab>;
            assertEq((<ab>,), i);
            i = NULL;
            assertEq(NOTHING, i);
            i = NOTHING;
            assertEq(NOTHING, i);
        }
    }

    issue2651() {
        assertEq("hash<string, bool>", (map {$1: True}, keys {}).fullType());
        assertEq("hash<string, bool>", (map {$1: True}, keys {"a": 1}).fullType());
        assertEq("hash<string, bool>", (map {$1: True}, NOTHING.iterator()).fullType());
        assertEq(Type::NothingType, (map {$1: True}, NOTHING).fullType());
        assertEq("list<string>", (keys {}).fullType());
        assertEq("list<bool>", (map True, keys {}).fullType());
        assertEq("list<bool>", (map True, keys {"a": 1}).fullType());
        assertEq("list<bool>", (map True, NOTHING.iterator()).fullType());
        assertEq(Type::NothingType, (map True, NOTHING).fullType());
    }

    issue2647() {
        # test runtime type folding
        {
            auto x = {};
            hash<string, bool> h = x;
            assertEq("hash<auto>", x.fullType());
            assertEq("hash<string, bool>", h.fullType());
        }
        # test parse and runtime type folding
        {
            hash<string, bool> h = {};
            assertEq("hash<string, bool>", h.fullType());
            code test = hash<string, bool> sub () {
                return {};
            };
            assertEq("hash<string, bool>", test().fullType());
        }
        # test runtime type folding
        {
            auto x = ();
            list<bool> l = x;
            assertEq("list<auto>", x.fullType());
            assertEq("list<bool>", l.fullType());
        }
        # test parse and runtime type folding
        {
            list<bool> l = ();
            assertEq("list<bool>", l.fullType());
            code test = list<bool> sub () {
                return ();
            };
            assertEq("list<bool>", test().fullType());
        }
    }

    static hash testAnyArg(auto v) {
        return {
            "type": v.fullType(),
            "complex": v.complexType(),
        };
    }
}
