]> Nishi Git Mirror - gwion.git/commitdiff
:art: Vararg uses cast
authorJérémie Astor <astor.jeremie@wanadoo.fr>
Sat, 7 Mar 2020 16:03:40 +0000 (17:03 +0100)
committerJérémie Astor <astor.jeremie@wanadoo.fr>
Sat, 7 Mar 2020 16:37:22 +0000 (17:37 +0100)
19 files changed:
examples/template_vararg.gw
examples/vararg.gw
include/emit.h
include/instr.h
include/vararg.h
src/emit/emit.c
src/lib/array.c
src/lib/engine.c
src/lib/object.c
src/lib/tuple.c
src/lib/vararg.c
src/parse/check.c
src/parse/operator.c
tests/error/vararg_after.gw
tests/error/vararg_before.gw
tests/error/vararg_invalid_acces.gw
tests/new/typedef_func_class_variadic.gw
tests/tree/empty_vararg.gw
tests/tree/varobject_assign.gw

index 83dd8a7607ef30b88980c5a26e5d3bc3d971e33c..564d0b80b039b7397ee54bbab200e60b28dca4e9 100644 (file)
@@ -1,6 +1,6 @@
 fun void test<~A~>(...) {
   vararg.start;
-  <<< vararg.i >>>;
+  <<< vararg $ int >>>;
   vararg.end;
 }
 test<~int~>(1, 2);
index a5b017e7f9ecacc2f93024fb6b3ffa472d88be15..0270e4f91d116ea3c4b1c9a19ace63ed42c0dda7 100644 (file)
@@ -3,19 +3,19 @@ fun void test(...) {
   vararg.start;
 
        if(i == 0)
-               <<< vararg.i >>>;
+               <<< vararg $ int >>>;
        else if(i == 1)
-               <<< vararg.f >>>;
+               <<< vararg $ float >>>;
        else if(i == 2)
-               <<< vararg.c >>>;
+               <<< vararg $ complex >>>;
        else if(i == 3)
-               <<< vararg.p >>>;
+               <<< vararg $ polar >>>;
        else if(i == 4)
-               <<< vararg.v3 >>>;
+               <<< vararg $ Vec3 >>>;
        else if(i == 5)
-               <<< vararg.v4 >>>;
+               <<< vararg $ Vec4 >>>;
        else if(i == 6)
-               <<< vararg.o >>>;
+               <<< vararg $ Object >>>;
        i++;
   vararg.end;
 }
index 8c7012149b663d057b438feb7d87ee8ed556ebac..8a8cb71eec1d55054b02e2b364883c2c45d41f9d 100644 (file)
@@ -47,4 +47,9 @@ ANN2(1,2) m_bool emit_instantiate_object(const Emitter, const Type, const Array_
 ANN m_uint emit_code_offset(const Emitter emit);
 ANN m_uint emit_local(const Emitter emit, const m_uint size, const m_bool is_obj);
 ANN Instr emit_exp_spork(const Emitter, const Exp_Unary*);
+ANN m_bool emit_exp(const Emitter, const Exp, const m_bool add_ref);
+ANN static inline void emit_except(const Emitter emit, const Type t) {
+  emit_add_instr(emit, !GET_FLAG(t, nonnull) ? GWOP_EXCEPT : SetObj);
+}
+
 #endif
index 9a545cbe797851197496548ad4f1551f58990386..2565644b5c211e66f45e61a84e0f61a36803f831 100644 (file)
@@ -50,7 +50,6 @@ INSTR(ArrayAlloc);
 INSTR(VarargIni);
 INSTR(VarargTop);
 INSTR(VarargEnd);
-INSTR(VarargMember);
 
 INSTR(VecCpy);
 INSTR(VecMember);
index ed207e29eb168835727a6b47e8eebf25041f126a..f94f649f64ca9ce2d678260fdca14c6daf8af3cf 100644 (file)
@@ -2,6 +2,7 @@
 #define __VARARG
 struct Vararg_ {
   m_uint* k;      // sizes
+  Type* t;      // types
   m_bit* d;  // d(ata)
   m_uint o, i, s; // o(ffset), i(ndex), s(ize)
 };
index 66018eccdaa0214109e2255eaf09e1bbcc8d651e..97312a7d16f372a9a72259aa051fdf90bf2caf59 100644 (file)
@@ -85,7 +85,7 @@ ANN static m_int frame_pop(Frame* frame) {
   return l->is_obj ? (m_int)l->offset : frame_pop(frame);
 }
 
-ANN static m_bool emit_exp(const Emitter emit, Exp exp, const m_bool add_ref);
+ANN /*static */m_bool emit_exp(const Emitter emit, Exp exp, const m_bool add_ref);
 ANN static m_bool emit_stmt(const Emitter emit, const Stmt stmt, const m_bool pop);
 ANN static m_bool emit_stmt_list(const Emitter emit, Stmt_List list);
 ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member);
@@ -750,7 +750,7 @@ ANN static m_uint vararg_size(const Exp_Call* exp_call, const Vector kinds) {
   while(e) {
     if(!l) {
       size += e->type->size;
-      vector_add(kinds, e->type->size);
+      vector_add(kinds, (vtype)e->type); // ->size
     } else
       l = l->next;
     e = e->next;
@@ -854,12 +854,10 @@ ANN static m_bool emit_exp_post(const Emitter emit, const Exp_Postfix* post) {
   return op_emit_bool(emit, &opi);
 }
 
-ANN static m_bool is_special(const Emitter emit, const Type t) {
-  if(isa(t, emit->gwion->type[et_complex]) > 0 || isa(t, emit->gwion->type[et_polar]) > 0 ||
-     isa(t, emit->gwion->type[et_vec3])    > 0 || isa(t, emit->gwion->type[et_vec4])  > 0 ||
-     isa(t, emit->gwion->type[et_vararg])  > 0)
-    return GW_OK;
-  return GW_ERROR;
+ANN static inline m_bool is_special(const Emitter emit, const Type t) {
+  return isa(t, emit->gwion->type[et_object]) < 0 &&
+         isa(t, emit->gwion->type[et_class]) < 0  ?
+    GW_OK : GW_ERROR;
 }
 
 ANN static inline m_bool traverse_emit_func_def(const Emitter emit, const Func_Def fdef) {
@@ -1242,7 +1240,7 @@ ANN static m_bool emit_exp_interp(const Emitter emit, const Exp_Interp *exp) {
 
 DECL_EXP_FUNC(emit, m_bool, Emitter)
 
-ANN2(1) static m_bool emit_exp(const Emitter emit, Exp exp, const m_bool ref) {
+ANN2(1) /*static */m_bool emit_exp(const Emitter emit, Exp exp, const m_bool ref) {
   do {
    CHECK_BB(emit_exp_func[exp->exp_type](emit, &exp->d))
    if(ref && isa(exp->type, emit->gwion->type[et_object]) > 0) {
@@ -1716,6 +1714,7 @@ ANN static m_bool emit_vararg_start(const Emitter emit, const m_uint offset) {
   vector_set(&emit->info->variadic, vector_size(&emit->info->variadic) -1, (vtype)instr);
   return GW_OK;
 }
+
 ANN static inline Instr get_variadic(const Emitter emit) {
   return (Instr)vector_back(&emit->info->variadic);
 }
@@ -1749,14 +1748,8 @@ ANN static m_bool emit_vararg(const Emitter emit, const Exp_Dot* member) {
     emit_vararg_end(emit, offset);
     return GW_OK;
   }
-  if(!get_variadic(emit))
-      ERR_B(exp_self(member)->pos, _("vararg.%s used before vararg.start"), s_name(member->xid))
-  if(GET_FLAG(emit->env->func, empty))
-    ERR_B(exp_self(member)->pos, _("vararg.%s used after vararg.end"), s_name(member->xid))
-  const Instr instr = emit_add_instr(emit, VarargMember);
-  instr->m_val = offset;
-  instr->m_val2 = exp_self(member)->type->size;
-  return GW_OK;
+// should not be reached now
+  return GW_ERROR;
 }
 
 ANN static m_bool emit_exp_dot_special(const Emitter emit, const Exp_Dot* member) {
@@ -1805,12 +1798,10 @@ ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member) {
     return emit_exp_dot_special(emit, member);
   const Value value = find_value(actual_type(emit->gwion, member->t_base), member->xid);
   if(!is_class(emit->gwion, member->t_base) && (GET_FLAG(value, member) ||
-(isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 && !is_fptr(emit->gwion, exp_self(member)->type)))
-) {
+       (isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 &&
+       !is_fptr(emit->gwion, exp_self(member)->type)))) {
     CHECK_BB(emit_exp(emit, member->base, 0))
-    emit_add_instr(emit, GWOP_EXCEPT);
-
-//    emit_except(emit, member->t_base);
+    emit_except(emit, member->t_base);
   }
   if(isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 && !is_fptr(emit->gwion, exp_self(member)->type))
     return emit_member_func(emit, member);
index 11b751efb882ab3d5d0b3a86dc0306f2ba004b25..5f9a9157c055ea1effbf8882372c3e969c339933 100644 (file)
@@ -14,6 +14,7 @@
 #include "traverse.h"
 #include "parse.h"
 #include "gwi.h"
+#include "emit.h"
 
 struct M_Vector_ {
   m_bit* ptr;
index bcd5ca0a896fa659ebb5fcb1b001c8a1699ebf35..5cef63a1250267e6694b972d9b1e4341d461ba43 100644 (file)
@@ -76,8 +76,6 @@ ANN static m_bool import_core_libs(const Gwi gwi) {
   const Type t_void  = gwi_mk_type(gwi, "void", 0, NULL);
   GWI_BB(gwi_gack(gwi, t_void, gack_void))
   GWI_BB(gwi_set_global_type(gwi, t_void, et_void))
-  const Type t_null  = gwi_mk_type(gwi, "@null",  SZ_INT, NULL);
-  GWI_BB(gwi_set_global_type(gwi, t_null, et_null))
   const Type t_function = gwi_mk_type(gwi, "@function", SZ_INT, NULL);
   GWI_BB(gwi_gack(gwi, t_function, gack_function))
   GWI_BB(gwi_set_global_type(gwi, t_function, et_function))
index 5c3cebf813d6de505f4558eceed3b075e1deebd6..b94a6536fa79bd630b1c7046e10964ab03b2618a 100644 (file)
@@ -236,13 +236,15 @@ static OP_CHECK(opck_object_scan) {
 }
 
 GWION_IMPORT(object) {
-const Type t_object  = gwi_mk_type(gwi, "Object", SZ_INT, NULL);
-gwi_add_type(gwi, t_object);
+  const Type t_object  = gwi_mk_type(gwi, "Object", SZ_INT, NULL);
+  gwi_add_type(gwi, t_object);
   GWI_BB(gwi_gack(gwi, t_object, gack_object))
-//assert(GET_FLAG(t_object, checked));
   SET_FLAG(t_object, checked); // should be set by gwi_add_type
   gwi->gwion->type[et_object] = t_object;
 
+  const Type t_null  = gwi_mk_type(gwi, "@null",  SZ_INT, "Object");
+  gwi->gwion->type[et_null] = t_null;
+  GWI_BB(gwi_set_global_type(gwi, t_null, et_null))
   GWI_BB(gwi_oper_cond(gwi, "Object", BranchEqInt, BranchNeqInt))
   GWI_BB(gwi_oper_ini(gwi, "@null", "Object", "Object"))
   GWI_BB(gwi_oper_add(gwi, at_object))
@@ -269,6 +271,9 @@ gwi_add_type(gwi, t_object);
   GWI_BB(gwi_oper_add(gwi, opck_implicit_null2obj))
   GWI_BB(gwi_oper_end(gwi, "@implicit", NULL))
   GWI_BB(gwi_oper_ini(gwi, "Object", "@null", "int"))
+//  GWI_BB(gwi_oper_add(gwi, opck_object_cast))
+//  GWI_BB(gwi_oper_emi(gwi, opem_object_cast))
+//  GWI_BB(gwi_oper_end(gwi, "$", NULL))
   GWI_BB(gwi_oper_end(gwi, "==", EqObject))
   GWI_BB(gwi_oper_end(gwi, "!=", NeqObject))
   GWI_BB(gwi_oper_ini(gwi, NULL, "Object", "bool"))
index ca97a433abfe45d40a0e81d0205d517dfde436d3..8dd269aee1d2b40c15be1691383e417dff489083 100644 (file)
@@ -14,6 +14,7 @@
 #include "object.h"
 #include "parse.h"
 #include "tuple.h"
+#include "array.h"
 
 struct TupleEmit {
   Exp e;
index 69621f9bdf75ab80704e5460c8ceba77be6573e9..129fa43b8dfd680e82fbad12fd5e6e8c21ac7bd7 100644 (file)
 #include "specialid.h"
 #include "traverse.h"
 #include "parse.h"
+#include "gack.h"
 
 void free_vararg(MemPool p, struct Vararg_* arg) {
   xfree(arg->d);
   xfree(arg->k);
+  xfree(arg->t);
   mp_free(p, Vararg, arg);
 }
 
@@ -38,8 +40,12 @@ INSTR(VarargIni) {
   const Vector kinds = (Vector)instr->m_val2;
   arg->s = vector_size(kinds);
   arg->k = (m_uint*)xmalloc(arg->s * SZ_INT);
-  for(m_uint i = 0; i < arg->s; ++i)
-     *(m_uint*)(arg->k + i) = vector_at(kinds, i);
+  arg->t = (Type*)xmalloc(arg->s * SZ_INT);
+  for(m_uint i = 0; i < arg->s; ++i) {
+    const Type t = (Type)vector_at(kinds, i);
+    *(Type*)(arg->t + i) = t;
+    *(m_uint*)(arg->k + i) = t->size;
+  }
   *(struct Vararg_**)REG(-SZ_INT) = arg;
 }
 
@@ -53,15 +59,48 @@ INSTR(VarargEnd) {
     free_vararg(shred->info->mp, arg);
 }
 
-INSTR(VarargMember) {
+static OP_CHECK(opck_vararg_cast) {
+  const Exp_Cast* cast = (Exp_Cast*)data;
+  const Type t = known_type(env, cast->td);
+//puts(t->name);
+  return t;
+}
+
+static INSTR(VarargCast) {
   struct Vararg_* arg = *(struct Vararg_**)MEM(instr->m_val);
-  if(instr->m_val2 != arg->k[arg->i]) { // TODO: differnciate object and primitives
-    free_vararg(shred->info->mp, arg);
-    Except(shred, "InvalidVariadicAccess");
+  const Type t = (Type)instr->m_val2;
+  if(isa(arg->t[arg->i], t) < 0){
+         free_vararg(shred->info->mp, arg);
+         Except(shred, "InvalidVariadicAccess");
   }
-  for(m_uint i = 0; i < instr->m_val2; i += SZ_INT)
-    *(m_uint*)REG(i) = *(m_uint*)(arg->d + arg->o + i);
-  PUSH_REG(shred, instr->m_val2);
+//  POP_REG(shred, SZ_INT);
+  for(m_uint i = 0; i < t->size; i += SZ_INT)
+    *(m_uint*)REG(i - SZ_INT) = *(m_uint*)(arg->d + arg->o + i);
+  PUSH_REG(shred, t->size - SZ_INT);
+}
+
+ANN static inline Instr get_variadic(const Emitter emit) {
+  return (Instr)vector_back(&emit->info->variadic);
+}
+
+ANN m_bool variadic_check(const Emitter emit, const loc_t pos) {
+  const Env env = emit->env;
+  if(!get_variadic(emit))
+      ERR_B(pos, _("vararg.xxx used before vararg.start"))
+  if(GET_FLAG(emit->env->func, empty))
+    ERR_B(pos, _("vararg.xxx used after vararg.end"))
+  return GW_OK;
+}
+
+static OP_EMIT(opem_vararg_cast) {
+  const Exp_Cast* cast = (Exp_Cast*)data;
+  CHECK_BO(variadic_check(emit, cast->exp->pos))
+  const Instr instr = emit_add_instr(emit, VarargCast);
+  const Instr variadic = (Instr)vector_back(&emit->info->variadic);
+  instr->m_val = variadic->m_val;
+  const Type t = known_type(emit->env, cast->td);
+  instr->m_val2 = (m_uint)t;
+  return instr;
 }
 
 static OP_CHECK(at_varobj) {
@@ -85,26 +124,22 @@ static ID_CHECK(idck_vararg) {
   ERR_O(exp_self(prim)->pos, _("'vararg' must be used inside variadic function"))
 }
 
+static GACK(gack_vararg) {
+  INTERP_PRINTF("%p\n", *(M_Object*)VALUE);
+}
+
 GWION_IMPORT(vararg) {
   const Type t_varobj  = gwi_mk_type(gwi, "VarObject", SZ_INT, "Object");
   SET_FLAG(t_varobj, abstract);
   const Type t_varloop = gwi_mk_type(gwi, "@VarLoop",  SZ_INT, NULL);
   GWI_BB(gwi_add_type(gwi,  t_varobj))
   GWI_BB(gwi_set_global_type(gwi, t_varloop, et_varloop))
-  const Type t_vararg  = gwi_class_ini(gwi, "@Vararg", NULL);
+  const Type t_vararg  = gwi_class_spe(gwi, "@Vararg", 0);
+  gwi_gack(gwi, t_vararg, gack_vararg);
   gwi->gwion->type[et_vararg] = t_vararg; // use func
   GWI_BB(gwi_union_ini(gwi, NULL, NULL))
   GWI_BB(gwi_union_add(gwi, "@VarLoop",  "start"))
   GWI_BB(gwi_union_add(gwi, "@VarLoop",  "end"))
-  GWI_BB(gwi_union_add(gwi, "int",       "i"))
-  GWI_BB(gwi_union_add(gwi, "float",     "f"))
-  GWI_BB(gwi_union_add(gwi, "time",      "t"))
-  GWI_BB(gwi_union_add(gwi, "dur",       "d"))
-  GWI_BB(gwi_union_add(gwi, "complex",   "c"))
-  GWI_BB(gwi_union_add(gwi, "polar",     "p"))
-  GWI_BB(gwi_union_add(gwi, "Vec3",      "v3"))
-  GWI_BB(gwi_union_add(gwi, "Vec4",      "v4"))
-  GWI_BB(gwi_union_add(gwi, "VarObject", "o"))
   GWI_OB(gwi_union_end(gwi, ae_flag_const))
   GWI_BB(gwi_class_end(gwi))
   GWI_BB(gwi_oper_ini(gwi, "VarObject", "Object", NULL))
@@ -113,6 +148,10 @@ GWION_IMPORT(vararg) {
   GWI_BB(gwi_oper_ini(gwi, "Object", "VarObject", NULL))
   GWI_BB(gwi_oper_add(gwi, at_varobj))
   GWI_BB(gwi_oper_end(gwi, "@=>", VarargAssign))
+  GWI_BB(gwi_oper_ini(gwi, "@Vararg", (m_str)OP_ANY_TYPE, NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_vararg_cast))
+  GWI_BB(gwi_oper_emi(gwi, opem_vararg_cast))
+  GWI_BB(gwi_oper_end(gwi, "$", VarargCast))
   gwi_register_freearg(gwi, VarargIni, freearg_vararg);
   struct SpecialId_ spid = { .type=t_vararg, .exec=RegPushImm, .is_const=1, .ck=idck_vararg};
   gwi_specialid(gwi, "vararg", &spid);
index 5f67e708b2942e583c3a4c6b1fe886f1d2551be6..567a98b62f9921a51653ace36977b06e6e1f1675 100644 (file)
@@ -33,7 +33,6 @@ ANN /*static inline */m_bool check_implicit(const Env env, const Exp e, const Ty
   return check_internal(env, sym, e, t);
 }
 
-
 ANN m_bool check_subscripts(Env env, const Array_Sub array) {
   CHECK_OB(check_exp(env, array->exp))
   m_uint depth = 0;
index e83958997b6f803cf89b2eff85dfc7eaa20a57c1..0f8e3240c7d24f213949953ace4a581cdc5f4d03 100644 (file)
@@ -8,6 +8,8 @@
 #include "instr.h"
 #include "emit.h"
 #include "operator.h"
+#include "object.h"
+#include "array.h"
 
 typedef Type (*f_type)(const Env env, const Exp exp);
 
index c9dec0cc69f8a5d0adb2d4b2754ece2e8cd7e817..93375f6d183a636794b9d96149cb222c00def36c 100644 (file)
@@ -2,5 +2,5 @@
 fun void test(...) {
   vararg.start;
   vararg.end;
-  vararg.i;
+  vararg $ int;
 }
index ee2680b712784c286793c72fcd2523889d26aa9d..9159d48002e3d9ed5210712dd14acd140aaa7de5 100644 (file)
@@ -1,4 +1,4 @@
 #! [contains] used before
 fun void test(...) {
-  vararg.i;
+  vararg $ int;
 }
index 4467d961703a108016f24ca2abcecb3a34d82731..ad3a91b03ed2a3e4d6bd261e622e1ad40e7c6288 100644 (file)
@@ -1,7 +1,7 @@
 #! [contains] InvalidVariadicAccess
 fun void test(...) {
   vararg.start;
-  <<<vararg.i>>>;
+  <<<vararg $ int >>>;
   vararg.end;
 }
 Vec3(1.3) => test;
index 914c46d2d939aea08727da69c7014bbae965c801..e84007303bb00113cc4ee2248b6e743341234f43 100644 (file)
@@ -6,7 +6,7 @@ class C {
   fun void test(...) {
     <<< this, " ", __func__ >>>;
     vararg.start;
-    <<< vararg.i >>>;
+    <<< vararg $ int >>>;
     vararg.end;
   }
 
index fa873c549a75cfc964ba869310c2db6b27761d07..bc944a4d49bb0e03e137dff9d757f05a439494ff 100644 (file)
@@ -1,7 +1,7 @@
 fun int test(...){
   vararg.start;
-  <<< "test" >>>; 
-  <<< vararg.i >>>;
+  <<< "test" >>>;
+  <<< vararg $ int >>>;
   vararg.end;
   return 1;
 }
index 87a2f858293a45295ec18d5e7235e8fa850d99cd..23a891ca9fb12a7633c74714caa80df2d655f725 100644 (file)
@@ -1,6 +1,6 @@
 fun void test(...) {
        Object o;
        vararg.start;
-       vararg.o @=> o;
+       vararg $ Object @=> o;
        vararg.end;
 }