]> Nishi Git Mirror - gwion.git/commitdiff
:art: Make Vararg a better type
authorJérémie Astor <astor.jeremie@wanadoo.fr>
Sun, 8 Mar 2020 22:57:37 +0000 (23:57 +0100)
committerJérémie Astor <astor.jeremie@wanadoo.fr>
Sun, 8 Mar 2020 22:57:37 +0000 (23:57 +0100)
src/emit/emit.c
src/env/tupleform.c [new file with mode: 0644]
src/lib/object.c
src/lib/vararg.c
src/parse/check.c
src/vm/vm.c

index 67e22ceec8b288ff1b73335123a575fcde7511cd..f528699cf1aaa2d4b5dcfa31856972042c8e824a 100644 (file)
@@ -1649,6 +1649,7 @@ ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def fdef) {
     if(!GET_FLAG(fdef->base->func, empty))
       ERR_B(fdef->pos, _("invalid variadic use"))
   }
+  vector_pop(&emit->info->variadic);
   return GW_OK;
 }
 
diff --git a/src/env/tupleform.c b/src/env/tupleform.c
new file mode 100644 (file)
index 0000000..f14fec2
--- /dev/null
@@ -0,0 +1,50 @@
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "vm.h"
+#include "instr.h"
+#include "object.h"
+#include "emit.h"
+#include "vm.h"
+#include "gwion.h"
+#include "operator.h"
+#include "import.h"
+#include "gwi.h"
+#include "traverse.h"
+#include "object.h"
+#include "parse.h"
+#include "tuple.h"
+#include "array.h"
+
+ANN void tuple_info(const Env env, Type_Decl *base, const Var_Decl var) {
+  const Value v = var->value;
+  const m_uint offset = vector_back(&env->class_def->e->tuple->offset);
+  vector_add(&env->class_def->e->tuple->types, (vtype)v->type);
+  vector_add(&env->class_def->e->tuple->offset, offset + v->type->size);
+  Type_Decl *td = cpy_type_decl(env->gwion->mp, base);
+  if(var->array)
+    td->array = cpy_array_sub(env->gwion->mp, var->array);
+  if(env->class_def->e->tuple->list) {
+    Type_List tl = env->class_def->e->tuple->list;
+    while(tl->next)
+      tl = tl->next;
+    tl->next = new_type_list(env->gwion->mp, td, NULL);
+  } else
+    env->class_def->e->tuple->list = new_type_list(env->gwion->mp, td, NULL);
+}
+
+ANN TupleForm new_tupleform(MemPool p) {
+  TupleForm tuple = mp_malloc(p, TupleForm);
+  vector_init(&tuple->types);
+  vector_init(&tuple->offset);
+  vector_add(&tuple->offset, 0);
+  tuple->list = NULL;
+  return tuple;
+}
+
+ANN void free_tupleform(MemPool p, const TupleForm tuple) {
+  vector_release(&tuple->types);
+  vector_release(&tuple->offset);
+  if(tuple->list)
+    free_type_list(p, tuple->list);
+}
index ffd8539b211704c0553c09ba06ddbb4dc5818f2e..116b24076ab1f5bded7aba0c83b2484d211fa403 100644 (file)
@@ -277,9 +277,41 @@ ANN static inline void emit_member(const Emitter emit, const Value v, const uint
   instr->m_val2 = size;
 }
 
+ANN m_bool not_from_owner_class(const Env env, const Type t, const Value v, const loc_t pos);
 OP_CHECK(opck_object_dot) {
   const Exp_Dot *member = (Exp_Dot*)data;
-  const Value value = find_value(actual_type(env->gwion, member->t_base), member->xid);
+  const m_str str = s_name(member->xid);
+  const m_bool base_static = is_class(env->gwion, member->t_base);
+  const Type the_base = base_static ? member->t_base->e->d.base_type : member->t_base;
+  if(!the_base->nspc)
+    ERR_O(member->base->pos,
+          _("type '%s' does not have members - invalid use in dot expression of %s"),
+          the_base->name, str)
+  if(member->xid ==  insert_symbol(env->gwion->st, "this") && base_static)
+    ERR_O(exp_self(member)->pos,
+          _("keyword 'this' must be associated with object instance..."))
+  const Value value = find_value(the_base, member->xid);
+  if(!value) {
+    env_err(env, exp_self(member)->pos,
+          _("class '%s' has no member '%s'"), the_base->name, str);
+    if(member->t_base->nspc)
+      did_you_mean_type(the_base, str);
+    return NULL;
+  }
+  CHECK_BO(not_from_owner_class(env, the_base, value, exp_self(member)->pos))
+  if(!env->class_def || isa(env->class_def, value->from->owner_class) < 0) {
+    if(GET_FLAG(value, private))
+      ERR_O(exp_self(member)->pos,
+          _("can't access private '%s' outside of class..."), value->name)
+    else if(GET_FLAG(value, protect))
+      exp_self(member)->meta = ae_meta_protect;
+  }
+  if(base_static && GET_FLAG(value, member))
+    ERR_O(exp_self(member)->pos,
+          _("cannot access member '%s.%s' without object instance..."),
+          the_base->name, str)
+  if(GET_FLAG(value, const) || GET_FLAG(value, enum))
+    exp_self(member)->meta = ae_meta_value;
   return value->type;
 }
 
index e8b76e47ba59ec0117f80378583a37539285a74b..046ed3246b2312cf13d885e068f84afdee0f0458 100644 (file)
 
 void free_vararg(MemPool p, struct Vararg_* arg) {
   xfree(arg->d);
-  xfree(arg->k);
   xfree(arg->t);
   mp_free(p, Vararg, arg);
 }
 
-INSTR(VarargTop) {
-  struct Vararg_* arg = *(struct Vararg_**)MEM(instr->m_val);
-  if(arg) {
-    assert(arg->d);
-    PUSH_REG(shred, SZ_INT)
-  } else
-    shred->pc = instr->m_val2 + 1;
-}
-
 INSTR(VarargIni) {
   struct Vararg_* arg = mp_calloc(shred->info->mp, Vararg);
   POP_REG(shred, instr->m_val - SZ_INT)
@@ -39,22 +29,19 @@ INSTR(VarargIni) {
     *(m_uint*)(arg->d + i) = *(m_uint*)(shred->reg - SZ_INT + i);
   const Vector kinds = (Vector)instr->m_val2;
   arg->s = vector_size(kinds);
-  arg->k = (m_uint*)xmalloc(arg->s * SZ_INT);
   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;
 }
 
-INSTR(VarargEnd) {
-  struct Vararg_* arg = *(struct Vararg_**)MEM(instr->m_val);
-  PUSH_REG(shred, SZ_INT);
-  arg->o += arg->k[arg->i];
+static INSTR(VarargEnd) {
+  struct Vararg_* arg = *(struct Vararg_**)REG(0);
+  arg->o += arg->t[arg->i]->size;
   if(++arg->i < arg->s)
-    shred->pc = instr->m_val2;
+    shred->pc = instr->m_val;
   else
     free_vararg(shred->info->mp, arg);
 }
@@ -65,15 +52,14 @@ static OP_CHECK(opck_vararg_cast) {
 }
 
 static INSTR(VarargCast) {
-  struct Vararg_* arg = *(struct Vararg_**)MEM(instr->m_val);
+  struct Vararg_* arg = *(struct Vararg_**)REG(-SZ_INT);
   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 < 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);
+    *(m_uint*)REG(i - SZ_INT*2) = *(m_uint*)(arg->d + arg->o + i);
 }
 
 ANN static inline Instr get_variadic(const Emitter emit) {
@@ -92,9 +78,12 @@ ANN m_bool variadic_check(const Emitter emit, const loc_t pos) {
 static OP_EMIT(opem_vararg_cast) {
   const Exp_Cast* cast = (Exp_Cast*)data;
   CHECK_BO(variadic_check(emit, cast->exp->pos))
+  CHECK_BO(emit_exp(emit, cast->exp, 0))
   const Instr instr = emit_add_instr(emit, VarargCast);
   instr->m_val = get_variadic(emit)->m_val;
   instr->m_val2 = (m_uint)exp_self(cast)->type;
+  const Instr pop = emit_add_instr(emit, RegPush);
+  pop->m_val = exp_self(cast)->type->size - SZ_INT *2;
   return instr;
 }
 
@@ -109,47 +98,56 @@ static ID_CHECK(idck_vararg) {
   ERR_O(exp_self(prim)->pos, _("'vararg' must be used inside variadic function"))
 }
 
+static ID_EMIT(idem_vararg) {
+  const Instr instr = emit_add_instr(emit, RegPushMem);
+  instr->m_val = emit->code->stack_depth - SZ_INT;
+  return instr;
+}
+
 static GACK(gack_vararg) {
-  INTERP_PRINTF("%p\n", *(M_Object*)VALUE);
+  INTERP_PRINTF("%p", *(M_Object*)VALUE);
 }
 
 ANN static inline m_uint emit_code_size(const Emitter emit) {
   return vector_size(&emit->code->instr);
 }
 ANN static m_bool emit_vararg_start(const Emitter emit, const m_uint offset) {
-  const Instr instr = emit_add_instr(emit, VarargTop);
-  instr->m_val = offset;
-  instr->m_val2 = emit_code_size(emit);
+  const Instr instr = emit_add_instr(emit, BranchEqInt);
+  instr->m_val = emit_code_size(emit);
   vector_set(&emit->info->variadic, vector_size(&emit->info->variadic) -1, (vtype)instr);
   return GW_OK;
 }
 
 ANN static void emit_vararg_end(const Emitter emit, const m_uint offset) {
+  const Instr pop = emit_add_instr(emit, RegPop);
+  pop->m_val = SZ_INT;
   const Instr instr = emit_add_instr(emit, VarargEnd),
     variadic = get_variadic(emit);
-  instr->m_val = offset;
-  instr->m_val2 = variadic->m_val2;
-  variadic->m_val2 = emit_code_size(emit);
+  instr->m_val = variadic->m_val;
+  variadic->m_val = emit_code_size(emit);
   SET_FLAG(emit->env->func, empty);// mark vararg func as complete
 }
 
+static OP_CHECK(opck_vararg_dot) {
+  const Exp_Dot *member = (Exp_Dot*)data;
+  const m_str str = s_name(member->xid);
+  if(!strcmp(str, "start") || !strcmp(str, "end"))
+    return env->gwion->type[et_varloop];
+  ERR_O(exp_self(member)->pos, _("'%s' is not a vararg keyword."), str)
+}
+
 static OP_EMIT(opem_vararg_dot) {
   const Env env = emit->env;
   const Exp_Dot *member = (Exp_Dot*)data;
-  m_uint offset = emit->env->class_def ? SZ_INT : 0;
-  Arg_List l = emit->env->func->def->base->args;
   const m_str str = s_name(member->xid);
-  while(l) {
-    offset += l->type->size;
-    l = l->next;
-  }
-  if(!strcmp(str, "start")) {
+  const m_uint offset = emit->code->stack_depth - SZ_INT;
+  CHECK_BO(emit_exp(emit, member->base, 0))
+  if(str[0] == 's') {
     if(get_variadic(emit))
       ERR_O(exp_self(member)->pos, _("vararg.start already used"))
     emit_vararg_start(emit, offset);
     return (Instr)GW_OK;
   }
-  assert(!strcmp(str, "end"));
   if(!get_variadic(emit))
     ERR_O(exp_self(member)->pos, _("vararg.start not used before vararg.end"))
   emit_vararg_end(emit, offset);
@@ -158,25 +156,21 @@ static OP_EMIT(opem_vararg_dot) {
 OP_CHECK(opck_object_dot);
 
 GWION_IMPORT(vararg) {
-  const Type t_varloop = gwi_mk_type(gwi, "@VarLoop",  SZ_INT, NULL);
+  const Type t_varloop = gwi_mk_type(gwi, "@VarLoop", 0, NULL);
   GWI_BB(gwi_set_global_type(gwi, t_varloop, et_varloop))
-  const Type t_vararg  = gwi_class_spe(gwi, "@Vararg", 0);
+  const Type t_vararg  = gwi_mk_type(gwi, "@Vararg", SZ_INT, NULL);
   gwi_gack(gwi, t_vararg, gack_vararg);
-  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_OB(gwi_union_end(gwi, ae_flag_const))
-  GWI_BB(gwi_class_end(gwi))
+//  gwi_gack(gwi, t_varloop, gack_vararg);// ????
+  GWI_BB(gwi_add_type(gwi, t_vararg))
   GWI_BB(gwi_oper_ini(gwi, "@Vararg", (m_str)OP_ANY_TYPE, NULL))
-  GWI_BB(gwi_oper_add(gwi, opck_object_dot))
+  GWI_BB(gwi_oper_add(gwi, opck_vararg_dot))
   GWI_BB(gwi_oper_emi(gwi, opem_vararg_dot))
   GWI_BB(gwi_oper_end(gwi, "@dot", NULL))
-  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_BB(gwi_oper_end(gwi, "$", NULL))
   gwi_register_freearg(gwi, VarargIni, freearg_vararg);
-  struct SpecialId_ spid = { .type=t_vararg, .exec=RegPushImm, .is_const=1, .ck=idck_vararg};
+  struct SpecialId_ spid = { .type=t_vararg, .is_const=1, .ck=idck_vararg, .em=idem_vararg};
   gwi_specialid(gwi, "vararg", &spid);
   return GW_OK;
 }
index 73819a0ad099d8018e482f882c33ec5f2d728f46..133f8364d9d12961737e1475ea0bb6d544770734 100644 (file)
@@ -232,7 +232,7 @@ ANN static Type check_prim_range(const Env env, Range **data) {
   return op_check(env, &opi);
 }
 
-ANN static inline m_bool not_from_owner_class(const Env env, const Type t,
+ANN m_bool not_from_owner_class(const Env env, const Type t,
       const Value v, const loc_t pos) {
   if(!v->from->owner_class || isa(t, v->from->owner_class) < 0) {
     ERR_B(pos,
@@ -265,9 +265,8 @@ ANN static Value check_non_res_value(const Env env, const Symbol *data) {
 
 ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data);
 
-ANN static Type check_dot(const Env env, const Value v, const Exp_Dot *member) {
-  struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base,
-         .rhs=v->type, .data=(uintptr_t)member, .pos=exp_self(member)->pos };
+ANN static Type check_dot(const Env env, const Exp_Dot *member) {
+  struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base, .data=(uintptr_t)member, .pos=exp_self(member)->pos };
   return op_check(env, &opi);
 }
 
@@ -288,7 +287,7 @@ ANN static Type prim_id_non_res(const Env env, const Symbol *data) {
     prim_exp(data)->meta = ae_meta_value;
   if(v->from->owner_class) {
     const Exp exp  = symbol_owned_exp(env->gwion, data);
-    const Type ret = check_dot(env, v, &exp->d.exp_dot);
+    const Type ret = check_dot(env, &exp->d.exp_dot);
     prim_exp(data)->nspc = exp->nspc;
     free_exp(env->gwion->mp, exp);
     CHECK_OO(ret);
@@ -850,42 +849,8 @@ ANN static Type check_exp_if(const Env env, const Exp_If* exp_if) {
 }
 
 ANN static Type check_exp_dot(const Env env, Exp_Dot* member) {
-  const m_str str = s_name(member->xid);
   CHECK_OO((member->t_base = check_exp(env, member->base)))
-  const m_bool base_static = is_class(env->gwion, member->t_base);
-  const Type the_base = base_static ? member->t_base->e->d.base_type : member->t_base;
-  if(!the_base->nspc)
-    ERR_O(member->base->pos,
-          _("type '%s' does not have members - invalid use in dot expression of %s"),
-          the_base->name, str)
-  if(member->xid ==  insert_symbol("this") && base_static)
-    ERR_O(exp_self(member)->pos,
-          _("keyword 'this' must be associated with object instance..."))
-  const Value value = find_value(the_base, member->xid);
-  if(!value) {
-    env_err(env, exp_self(member)->pos,
-          _("class '%s' has no member '%s'"), the_base->name, str);
-    if(member->t_base->nspc)
-      did_you_mean_type(the_base, str);
-    return NULL;
-  }
-  CHECK_BO(not_from_owner_class(env, the_base, value, exp_self(member)->pos))
-  if(!env->class_def || isa(env->class_def, value->from->owner_class) < 0) {
-    if(GET_FLAG(value, private))
-      ERR_O(exp_self(member)->pos,
-          _("can't access private '%s' outside of class..."), value->name)
-    else if(GET_FLAG(value, protect))
-      exp_self(member)->meta = ae_meta_protect;
-  }
-  if(base_static && GET_FLAG(value, member))
-    ERR_O(exp_self(member)->pos,
-          _("cannot access member '%s.%s' without object instance..."),
-          the_base->name, str)
-  if(GET_FLAG(value, const) || GET_FLAG(value, enum))
-    exp_self(member)->meta = ae_meta_value;
-//  prim_self(member)->value = value;
-  CHECK_OO(check_dot(env, value, member))
-  return value->type;
+  return check_dot(env, member);
 }
 
 ANN m_bool check_type_def(const Env env, const Type_Def tdef) {
index 1c8af73e6a2da71fcb7ae391f3d957f78a3b9b6f..deef382dfd181145b42e4ee29c395574c1c44cfc 100644 (file)
@@ -382,20 +382,20 @@ regpushaddr:
   reg += SZ_INT;
   DISPATCH()
 regpushmem:
-  *(m_uint*)reg = *(m_uint*)(mem + VAL);
+  *(m_uint*)reg = *(m_uint*)(mem + (m_int)VAL);
   reg += SZ_INT;
   DISPATCH();
 regpushmemfloat:
-  *(m_float*)reg = *(m_float*)(mem + VAL);
+  *(m_float*)reg = *(m_float*)(mem + (m_int)VAL);
   reg += SZ_FLOAT;
   DISPATCH();
 regpushmemother:
   for(m_uint i = 0; i <= VAL2; i+= SZ_INT)
-    *(m_uint*)(reg+i) = *(m_uint*)((m_bit*)(mem + VAL) + i);
+    *(m_uint*)(reg+i) = *(m_uint*)((m_bit*)(mem + (m_int)VAL) + i);
   reg += VAL2;
   DISPATCH();
 regpushmemaddr:
-  *(m_bit**)reg = &*(m_bit*)(mem + VAL);
+  *(m_bit**)reg = &*(m_bit*)(mem + (m_int)VAL);
   reg += SZ_INT;
   DISPATCH()
 pushnow: