Line | Branch | Exec | Source |
---|---|---|---|
1 | #include "gwion_util.h" | ||
2 | #include "gwion_ast.h" | ||
3 | #include "gwion_env.h" | ||
4 | #include "vm.h" | ||
5 | #include "instr.h" | ||
6 | #include "gwion.h" | ||
7 | #include "object.h" | ||
8 | #include "emit.h" | ||
9 | #include "traverse.h" | ||
10 | #include "parse.h" | ||
11 | #include "operator.h" | ||
12 | #include "import.h" | ||
13 | #include "array.h" | ||
14 | |||
15 | ✗ | OP_CHECK(opck_basic_cast) { | |
16 | ✗ | const Exp_Cast *cast = (Exp_Cast *)data; | |
17 | ✗ | return isa(cast->exp->type, exp_self(cast)->type) > 0 | |
18 | ✗ | ? exp_self(cast)->type | |
19 | ✗ | : env->gwion->type[et_error]; | |
20 | } | ||
21 | |||
22 | 3 | OP_CHECK(opck_similar_cast) { | |
23 | 3 | const Exp_Cast *cast = (Exp_Cast *)data; | |
24 | 3 | return exp_self(cast)->type; | |
25 | } | ||
26 | |||
27 | 3 | OP_CHECK(opck_usr_implicit) { | |
28 | 3 | struct Implicit *imp = (struct Implicit *)data; | |
29 | /* | ||
30 | // in use for refinement types | ||
31 | const Value v = nspc_lookup_value1(imp->t->info->owner, | ||
32 | insert_symbol("@implicit")); if(v) { Func f = v->d.func_ref; while(f) { | ||
33 | if(f->def->base->ret_type == imp->t) | ||
34 | break; | ||
35 | f = f->next; | ||
36 | } | ||
37 | if(f) { | ||
38 | // TODO: add call exp | ||
39 | struct Exp_ call = { .exp_type=ae_exp_call, | ||
40 | .d={.exp_call={.args=imp->e}}, .pos=imp->e->pos, .type=f->value_ref->type }; | ||
41 | struct Op_Import opi = { .op=insert_symbol("@func_check"), | ||
42 | .rhs=f->value_ref->type, .pos=imp->e->pos, .data=(uintptr_t)&call }; | ||
43 | CHECK_NN(op_check(env, &opi)); | ||
44 | } | ||
45 | } | ||
46 | */ | ||
47 | 3 | return imp->t; | |
48 | } | ||
49 | |||
50 | //#include "emit.h" | ||
51 | // contracts only | ||
52 | ✗ | OP_EMIT(opem_contract_similar) { | |
53 | ✗ | const Exp_Cast *cast = (Exp_Cast *)data; | |
54 | ✗ | const Env env = emit->env; | |
55 | ✗ | struct Implicit imp = { .t=exp_self(cast)->type, .e=cast->exp}; | |
56 | ✗ | struct Op_Import opi = { | |
57 | ✗ | .op = insert_symbol("@implicit"), .lhs = cast->exp->type, .rhs = exp_self(cast)->type, .data=(m_uint)&imp }; | |
58 | ✗ | return op_emit(emit, &opi); | |
59 | } | ||
60 | |||
61 | 185 | OP_CHECK(opck_const_rhs) { | |
62 | 185 | const Exp_Binary *bin = (Exp_Binary *)data; | |
63 | 185 | const m_str access = exp_access(bin->rhs); | |
64 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 176 times.
|
185 | if (access) |
65 | 9 | ERR_N(bin->rhs->pos, | |
66 | _("cannot assign '%s' on types '%s' and '%s'.\n" | ||
67 | " ... (reason: --- right-side operand is %s.)"), | ||
68 | s_name(bin->op), bin->lhs->type->name, bin->rhs->type->name, access); | ||
69 | 176 | return bin->rhs->type; | |
70 | } | ||
71 | |||
72 | 180 | OP_CHECK(opck_rassign) { | |
73 | 180 | const Exp_Binary *bin = (Exp_Binary *)data; | |
74 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 172 times.
|
180 | if (opck_const_rhs(env, data) == env->gwion->type[et_error]) |
75 | 8 | return env->gwion->type[et_error]; | |
76 | 172 | exp_setvar(bin->rhs, 1); | |
77 | 172 | return bin->rhs->type; | |
78 | } | ||
79 | |||
80 | 29 | OP_CHECK(opck_unary_meta) { | |
81 | 29 | const Exp_Unary *unary = (Exp_Unary *)data; | |
82 | 29 | exp_setmeta(exp_self(unary), 1); | |
83 | 29 | return unary->exp->type; | |
84 | } | ||
85 | |||
86 | 1 | OP_CHECK(opck_unary_meta2) { | |
87 | 1 | const Exp_Unary *unary = (Exp_Unary *)data; | |
88 | 1 | exp_setmeta(exp_self(unary), 1); | |
89 | 1 | return env->gwion->type[et_bool]; | |
90 | } | ||
91 | |||
92 | 10 | OP_CHECK(opck_unary) { | |
93 | 10 | const Exp_Unary *unary = (Exp_Unary *)data; | |
94 | 10 | const m_str access = exp_access(unary->exp); | |
95 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
|
10 | if (access) |
96 | 1 | ERR_N(unary->exp->pos, | |
97 | _("unary operator '%s' cannot be used on %s data-types."), | ||
98 | s_name(unary->op), access); | ||
99 | 9 | exp_setvar(unary->exp, 1); | |
100 | 9 | exp_setmeta(exp_self(unary), 1); | |
101 | 9 | return unary->exp->type; | |
102 | } | ||
103 | |||
104 | 30 | OP_CHECK(opck_post) { | |
105 | 30 | const Exp_Postfix *post = (Exp_Postfix *)data; | |
106 | 30 | const m_str access = exp_access(post->exp); | |
107 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 29 times.
|
30 | if (access) |
108 | 1 | ERR_N(post->exp->pos, | |
109 | _("post operator '%s' cannot be used on %s data-type."), | ||
110 | s_name(post->op), access); | ||
111 | 29 | exp_setvar(post->exp, 1); | |
112 | 29 | exp_setmeta(exp_self(post), 1); | |
113 | 29 | return post->exp->type; | |
114 | } | ||
115 | |||
116 | ANN Type check_td(const Env env, Type_Decl *td); | ||
117 | |||
118 | 38 | OP_CHECK(opck_new) { | |
119 | 38 | Exp_Unary *unary = (Exp_Unary *)data; | |
120 | 38 | const Array_Sub array = unary->ctor.td->array; | |
121 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 37 times.
|
38 | DECL_ON(const Type, t, = known_type(env, unary->ctor.td)); |
122 |
3/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
37 | if(array && !unary->ctor.exp) { |
123 | 3 | const Type base = array_base(t); | |
124 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | if(GET_FLAG(base, abstract)) |
125 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | CHECK_BN(abstract_array(env, array)); |
126 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if(GET_FLAG(base, abstract)) |
127 | ✗ | CHECK_BN(check_array_instance(env, unary->ctor.td, unary->ctor.exp)); | |
128 | } | ||
129 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
|
36 | CHECK_BN(ensure_traverse(env, t)); |
130 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 35 times.
|
36 | if (type_ref(t)) |
131 | 1 | ERR_N(unary->ctor.td->pos, _("can't use 'new' on ref type '%s'\n"), t->name); | |
132 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 33 times.
|
35 | if (tflag(t, tflag_infer)) |
133 | 2 | ERR_N(unary->ctor.td->pos, _("can't use 'new' on '%s'\n"), | |
134 | t->name); | ||
135 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 31 times.
|
33 | if (array) { |
136 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | CHECK_BN(check_subscripts(env, array, 1)); |
137 | } | ||
138 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 15 times.
|
33 | if(unary->ctor.exp) { |
139 | 18 | const Exp self = exp_self(unary); | |
140 | 18 | const Exp args = cpy_exp(env->gwion->mp, unary->ctor.exp); | |
141 | 18 | const Exp base = new_exp_unary2(env->gwion->mp, unary->op, unary->ctor.td, unary->ctor.exp, self->pos); | |
142 | 18 | base->type = t; | |
143 | 18 | const Exp func = new_exp_dot(env->gwion->mp, base, insert_symbol("new"), self->pos); | |
144 | 18 | self->d.exp_call.func = func; | |
145 | 18 | self->d.exp_call.args = args; | |
146 | 18 | self->d.exp_call.tmpl = NULL; | |
147 | 18 | self->exp_type = ae_exp_call; | |
148 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 13 times.
|
18 | CHECK_BN(traverse_exp(env, self)); |
149 | 13 | return self->type; | |
150 | } | ||
151 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
15 | if (GET_FLAG(t, abstract) && |
152 | ✗ | (!array || (array->exp && exp_is_zero(array->exp)))) | |
153 | 1 | ERR_N(unary->ctor.td->pos, _("can't use 'new' on abstract type '%s'\n"), | |
154 | t->name); | ||
155 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 13 times.
|
14 | if (isa(t, env->gwion->type[et_object]) < 0) |
156 | 1 | ERR_N(exp_self(unary)->pos, _("can't use 'new' on non-object types...\n")); | |
157 | 13 | return t; | |
158 | } | ||
159 | |||
160 | 17 | OP_EMIT(opem_new) { | |
161 | 17 | const Exp_Unary *unary = (Exp_Unary *)data; | |
162 |
1/2✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
|
17 | if(!tflag(exp_self(unary)->type, tflag_struct)) |
163 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
|
17 | CHECK_BB(emit_instantiate_object(emit, exp_self(unary)->type, |
164 | unary->ctor.td->array, 0)); | ||
165 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 8 times.
|
17 | if(!unary->ctor.exp) |
166 | 9 | emit_local_exp(emit, exp_self(unary)); | |
167 | 17 | return GW_OK; | |
168 | } | ||
169 |