]> Nishi Git Mirror - gwion.git/commitdiff
:art: Unpack as a type
authorJérémie Astor <astor.jeremie@wanadoo.fr>
Fri, 6 Mar 2020 02:06:35 +0000 (03:06 +0100)
committerJérémie Astor <astor.jeremie@wanadoo.fr>
Fri, 6 Mar 2020 02:06:35 +0000 (03:06 +0100)
src/emit/emit.c
src/lib/tuple.c
src/lib/vec.c
src/parse/check.c
src/parse/scan1.c
tests/error/unused_unpack.gw
tests/match/tuple.gw
tests/tuple/tuple_skip.gw
tests/tuple/tuple_unpack_already_declared.gw

index 126bde8cd73519abdad78e1e2c3d0989f2c39c89..289e9751d82f0669fca7be50e97dc352c18c225d 100644 (file)
@@ -795,11 +795,11 @@ ANN static m_bool emit_exp_call(const Emitter emit, const Exp_Call* exp_call) {
   }
   if(exp_call->args)
     CHECK_BB(emit_exp(emit, exp_call->args, 1))
-    struct Op_Import opi = { .op=insert_symbol("@ctor"), .lhs=exp_call->func->type->e->d.base_type, .data=(uintptr_t)exp_call, .pos=exp_self(exp_call)->pos };
-    CHECK_OB(op_emit(emit, &opi))
-    const Exp e = exp_self(exp_call);
-    if(e->emit_var)
-      emit_vec_addr(emit, e->type->size);
+  struct Op_Import opi = { .op=insert_symbol("@ctor"), .lhs=exp_call->func->type->e->d.base_type, .data=(uintptr_t)exp_call, .pos=exp_self(exp_call)->pos };
+  CHECK_OB(op_emit(emit, &opi))
+  const Exp e = exp_self(exp_call);
+  if(e->emit_var)
+    emit_vec_addr(emit, e->type->size);
   return GW_OK;
 }
 
@@ -1250,7 +1250,7 @@ DECL_EXP_FUNC(emit, m_bool, Emitter)
 
 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))
+   CHECK_BB(emit_exp_func[exp->exp_type](emit, &exp->d))
    if(ref && isa(exp->type, emit->gwion->type[et_object]) > 0) {
       const Instr instr = emit_add_instr(emit, RegAddRef);
       instr->m_val = exp->emit_var;
index b7d2402d63b1895616f6337ea9d0fd2112c1c614..fe0eb5d6306b7e49cd32b683fa8df457c94b4692 100644 (file)
@@ -34,7 +34,6 @@ struct UnpackInfo_ {
 static INSTR(TupleUnpack) {
   const M_Object o = *(M_Object*)(shred->reg - SZ_INT);
   struct UnpackInfo_ *info = (struct UnpackInfo_*)instr->m_val;
-//  memcpy(shred->mem + info->mem_offset, o->data + shred->info->vm->gwion->type[et_tuple]->nspc->info->offset + info->obj_offset, info->size);
   memcpy(shred->mem + info->mem_offset, o->data + info->obj_offset, info->size);
 }
 
@@ -358,7 +357,8 @@ static OP_CHECK(opck_tuple) {
 static OP_CHECK(tuple_ck) {
   const Exp_Call *call = (Exp_Call*)data;
   const Exp exp = call->args;
-  CHECK_OO(check_exp(env, exp))
+  if(exp)
+    CHECK_OO(check_exp(env, exp))
   struct Vector_ v;
   vector_init(&v);
   Exp e = exp;
@@ -376,6 +376,83 @@ static OP_EMIT(tuple_em) {
   return instr;
 }
 
+static OP_CHECK(unpack_ck) {
+  const Exp_Call *call = (Exp_Call*)data;
+  const Symbol decl = insert_symbol("auto");
+  const Symbol skip = insert_symbol("_");
+  Exp e = call->args;
+const Value v = nspc_lookup_value1(env->global_nspc, insert_symbol("false"));
+  while(e) {
+    if(e->exp_type != ae_exp_primary || e->d.prim.prim_type != ae_prim_id)
+      ERR_O(e->pos, _("invalid expression for unpack"))
+    if(e->d.prim.d.var != skip) {
+      const Symbol var = e->d.prim.d.var;
+      memset(&e->d, 0, sizeof(union exp_data));
+e->type = env->gwion->type[et_auto];
+e->d.exp_decl.type = env->gwion->type[et_auto];
+      e->exp_type = ae_exp_decl;
+      e->d.exp_decl.td = new_type_decl(env->gwion->mp, new_id_list(env->gwion->mp, decl, loc_cpy(env->gwion->mp, e->pos)));
+      e->d.exp_decl.list = new_var_decl_list(env->gwion->mp,
+        new_var_decl(env->gwion->mp, var, NULL, loc_cpy(env->gwion->mp, e->pos)), NULL);
+e->d.exp_decl.list->self->value = v;
+    } else {
+      e->d.prim.prim_type = ae_prim_nil;
+      e->type = env->gwion->type[et_null];
+    }
+    e = e->next;
+  }
+  exp_self(call)->meta = ae_meta_var;
+  return call->func->type->e->d.base_type;
+}
+
+static OP_EMIT(unpack_em) {
+  const Exp_Call *call = (Exp_Call*)data;
+  if(exp_self(call)->meta == ae_meta_value)
+    return (Instr)GW_OK;
+  env_err(emit->env, exp_self(call)->pos, _("unused Tuple unpack"));
+  return NULL;
+}
+
+static OP_CHECK(opck_at_unpack) {
+  const Exp_Binary *bin = (Exp_Binary*)data;
+  Exp e = bin->rhs->d.exp_call.args;
+  int i = 0;
+  while(e) {
+    if(e->exp_type == ae_exp_decl) {
+      DECL_OO(const Type, t, = (Type)VPTR(&bin->lhs->type->e->tuple->types, i))
+      e->d.exp_decl.td->xid->xid = insert_symbol(t->name);
+      const Exp next = e->next;
+      e->d.exp_decl.type = NULL;
+      e->next = NULL;
+      const m_bool ret = traverse_exp(env, e);
+      e->next = next;
+      CHECK_BO(ret)
+      bin->rhs->meta = ae_meta_value;
+    }
+    ++i;
+    e = e->next;
+  }
+  return bin->lhs->type;
+}
+
+static OP_EMIT(opem_at_unpack) {
+  const Exp_Binary *bin = (Exp_Binary*)data;
+  if(bin->rhs->d.exp_call.args) {
+    const Type t_null = emit->gwion->type[et_null];
+    Exp e = bin->rhs->d.exp_call.args;
+    m_uint sz = 0;
+    do if(e->type != t_null)
+      sz += e->type->size;
+    while((e = e->next));
+    const Instr pop = emit_add_instr(emit, RegPop);
+    pop->m_val = sz;
+    const Vector v = &bin->lhs->type->e->tuple->types;
+    struct TupleEmit te = { .e=bin->rhs->d.exp_call.args, .v=v };
+    emit_unpack_instr(emit, &te);
+  }
+  return (Instr)GW_OK;
+}
+
 GWION_IMPORT(tuple) {
   const Type t_tuple = gwi_mk_type(gwi, "Tuple", SZ_INT, "Object");
   gwi_add_type(gwi, t_tuple);
@@ -412,5 +489,28 @@ GWION_IMPORT(tuple) {
 //  GWI_BB(gwi_oper_emi(gwi, opem_at_tuple))
   GWI_BB(gwi_oper_end(gwi, "@array", NULL))
   gwi_register_freearg(gwi, TupleUnpack, freearg_tuple_at);
+
+  const Type t_unpack = gwi_mk_type(gwi, "Unpack", SZ_INT, "Tuple");
+  gwi_add_type(gwi, t_unpack);
+  SET_FLAG(t_unpack, checked | ae_flag_scan2 | ae_flag_check | ae_flag_emit);
+  SET_FLAG(t_unpack, abstract | ae_flag_template);
+  GWI_BB(gwi_oper_ini(gwi, "Unpack", NULL, NULL))
+  GWI_BB(gwi_oper_add(gwi, unpack_ck))
+  GWI_BB(gwi_oper_emi(gwi, unpack_em))
+  GWI_BB(gwi_oper_end(gwi, "@ctor", NULL))
+  GWI_BB(gwi_oper_ini(gwi, "Object", "Unpack", NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_at_unpack))
+  GWI_BB(gwi_oper_emi(gwi, opem_at_unpack))
+  GWI_BB(gwi_oper_end(gwi, "@=>", NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_at_unpack))
+  GWI_BB(gwi_oper_emi(gwi, opem_at_unpack))
+  GWI_BB(gwi_oper_end(gwi, "==", NULL))
+  GWI_BB(gwi_oper_ini(gwi, "Tuple", "Unpack", NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_at_unpack))
+  GWI_BB(gwi_oper_emi(gwi, opem_at_unpack))
+  GWI_BB(gwi_oper_end(gwi, "@=>", NULL))
+  GWI_BB(gwi_oper_add(gwi, opck_at_unpack))
+  GWI_BB(gwi_oper_emi(gwi, opem_at_unpack))
+  GWI_BB(gwi_oper_end(gwi, "==", NULL))
   return GW_OK;
 }
index aaa92d889fb6f91ec57be6e0da9bdc272b8559ec..2c6b2e90b21d78ed89d50cf179f821d0c9725e30 100644 (file)
@@ -6,6 +6,8 @@
 #include "object.h"
 #include "gwion.h"
 #include "operator.h"
+#include "traverse.h"
+#include "parse.h"
 #include "import.h"
 #include "driver.h"
 #include "gwi.h"
@@ -166,6 +168,8 @@ EQUALITY_OPER(vec3, SZ_VEC3);
 OP_CHECK(vecx_ck) {
   Exp_Call *call = (Exp_Call*)data;
   Exp e = call->args, last = NULL;
+  if(call->args)
+    CHECK_ON(check_exp(env, call->args))
   size_t i = 0;
   const Type t_float = env->gwion->type[et_float];
   while(e) {
index ef9868eac55fbeb22a980f1137e36fd780b0cc57..001794f9ab094c2c22306669edcca8b0e9c517da 100644 (file)
@@ -715,10 +715,11 @@ ANN static Type check_lambda_call(const Env env, const Exp_Call *exp) {
 ANN Type check_exp_call1(const Env env, const Exp_Call *exp) {
   CHECK_OO(check_exp(env, exp->func))
   if(isa(exp->func->type, env->gwion->type[et_function]) < 0) {
+    // use func flag?
     if(isa(exp->func->type, env->gwion->type[et_class]) < 0)
       ERR_O(exp->func->pos, _("function call using a non-function value"))
-    if(exp->args)
-      CHECK_OO(check_exp(env, exp->args))
+//    if(exp->args)
+//      CHECK_OO(check_exp(env, exp->args))
     struct Op_Import opi = { .op=insert_symbol("@ctor"), .lhs=exp->func->type->e->d.base_type, .data=(uintptr_t)exp, .pos=exp_self(exp)->pos };
     const Type t = op_check(env, &opi);
     exp_self(exp)->nspc = t ? t->e->owner : NULL;
index 8916cce048b226ac6a82b4462a7fca052deb8d80..4fc66782741af4c8ed5d9cbd959721d9bea25f78 100644 (file)
@@ -137,8 +137,6 @@ ANN static inline m_bool scan1_prim(const Env env, const Exp_Primary* prim) {
     return scan1_exp(env, prim->d.array->exp);
   if(prim->prim_type == ae_prim_range)
     return scan1_range(env, prim->d.range);
-//  if(prim->prim_type == ae_prim_unpack)
-//    return scan1_exp(env, prim->d.tuple.exp);
   return GW_OK;
 }
 
index 5f161d80dd7d97509a06a2219cbfe3f5d485d34a..e6e759624899d3091b3ace5bd7ac464f2c37735d 100644 (file)
@@ -1,2 +1,2 @@
 #! [contains] unused Tuple unpack
->(a,b);
+Unpack(a,b);
index 90dbff2a497b0b98666b4720b3d0f242e6575bea..9c595568d6fbd34207626a8693129366fb5d2e75 100644 (file)
@@ -8,5 +8,5 @@ C charles;
 21 => charles.age;
 
 match charles {
-  case >(name, age): <<< name , " is ", age, " years old." >>>;
+  case Unpack(name, age): <<< name , " is ", age, " years old." >>>;
 }
index cd289269c224eab4a1fbd3828ec1640e47d0958b..bad9d2a25319139a3024a69042b27d98e74c8dd8 100644 (file)
@@ -1,2 +1,2 @@
-Tuple(1, 2, 3) @=> >(b, _, c);
+Tuple(1, 2, 3) @=> Unpack(b, _, c);
 <<< c >>>;
index 20178d9641dbdb9718e8af02544afeeadbaea9f7..16336f580d551595c1d5cd42558603e3a35f8dd9 100644 (file)
@@ -1,3 +1,3 @@
 #! [contains] already been defined in the same scope
 int i;
-Tuple(12) @=> >(i);
+Tuple(12) @=> Unpack(i);