]> Nishi Git Mirror - gwion.git/commitdiff
:art: Add primitive
authorfennecdjay <fennecdjay@gmail.com>
Tue, 11 Oct 2022 10:21:11 +0000 (12:21 +0200)
committerfennecdjay <fennecdjay@gmail.com>
Tue, 11 Oct 2022 10:21:11 +0000 (12:21 +0200)
20 files changed:
ast
include/emit.h
include/env/type.h
include/import/tdef.h
src/clean.c
src/emit/emit.c
src/env/context.c
src/import/import_prim.c [new file with mode: 0644]
src/import/import_tdef.c
src/lib/array.c
src/lib/prim.c
src/parse/check.c
src/parse/scan0.c
src/parse/scan1.c
src/parse/scan2.c
tests/primitive/access.gw [new file with mode: 0644]
tests/primitive/dyn_access.gw [new file with mode: 0644]
tests/primitive/oob.gw [new file with mode: 0644]
tests/primitive/static_oob.gw [new file with mode: 0644]
tests/primitive/too_many_exp.gw [new file with mode: 0644]

diff --git a/ast b/ast
index 310aab6d18d29f3bcb06fa1b5b12f2e7d2e79555..f6c9ae7feb355a64345da5c99c479a32a310df11 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit 310aab6d18d29f3bcb06fa1b5b12f2e7d2e79555
+Subproject commit f6c9ae7feb355a64345da5c99c479a32a310df11
index 46c3dfbfc75cbe10aa9ff1ca76c799e89e56a96f..942f67d4205bb7df379e78c4f7a5e4067893d5d7 100644 (file)
@@ -125,4 +125,5 @@ ANN void emit_pop_scope(const Emitter emit);
 
 ANN m_bool ensure_emit(const Emitter, const Type);
 ANN m_bool emit_ensure_func(const Emitter emit, const Func f);
+ANN m_bool get_emit_var(const Emitter emit, const Type t, bool is_var);
 #endif
index fbe56d9e3c3080521cc20da74067af7658d2579b..6c528adc9d4be7218df65b3ea8d89841c7a4cdee 100644 (file)
@@ -41,6 +41,7 @@ enum tflag {
   tflag_union    = 1 << 21,
   tflag_enum     = 1 << 22,
   tflag_ref      = 1 << 23,
+  tflag_packed   = 1 << 24,
 } __attribute__((packed));
 
 struct Type_ {
index fb19235ef153466c52151defdcdcbce27dbe4b2f..1c19a03309538c4b4a153b354aa8d8e0fc8171ef 100644 (file)
@@ -5,4 +5,8 @@ ANN m_int gwi_typedef_ini(const Gwi gwi, const restrict m_str type,
                           const restrict m_str name);
 ANN Type  gwi_typedef_end(const Gwi gwi, const ae_flag flag);
 ANN void  ck_clean_tdef(MemPool, ImportCK *);
+
+ANN Type mk_primitive(const Env env, const m_str name, const m_uint size);
+//ANN Type gwi_primitive(const Gwi gwi, const m_str name, const m_uint size, const ae_flag flag);
+ANN m_bool gwi_primitive(const Gwi gwi, const m_str name, const m_uint size, const ae_flag flag);
 #endif
index 65f07230ac18699bde7374d311e6a0adfb3c590e..69aea438239a336bedeb2c7c907a28a4025991d5 100644 (file)
@@ -339,6 +339,7 @@ ANN static void clean_trait_def(Clean *a, Trait_Def b) {
   if (b->traits) clean_id_list(a, b->traits);
   if (b->body) clean_ast(a, b->body);
 }
+ANN static void clean_prim_def(Clean *a NUSED, Prim_Def b NUSED) {}
 
 DECL_SECTION_FUNC(clean, void, Clean *);
 
index e6e80fb0ecd92fa4113ffc3d4e43ae5b75274db6..62f1c7ccce16f2d7c862a02481239707be0748f4 100644 (file)
@@ -757,9 +757,13 @@ ANN m_bool emit_array_access(const Emitter                 emit,
 }
 
 ANN static m_bool emit_exp_array(const Emitter emit, const Exp_Array *array) {
-  CHECK_BB(emit_exp(emit, array->base));
   const Exp              e    = exp_self(array);
-  struct ArrayAccessInfo info = {*array->array, e->type, exp_getvar(e)};
+  exp_setvar(array->base, get_emit_var(emit, array->base->type, exp_getvar(e)));
+  CHECK_BB(emit_exp(emit, array->base));
+  struct ArrayAccessInfo info = {
+    .array = *array->array,
+    .type = e->type,
+    .is_var = exp_getvar(e)};
   return emit_array_access(emit, &info);
 }
 
@@ -965,7 +969,8 @@ ANN static m_bool decl_static(const Emitter emit, const Exp_Decl *decl,
 }
 
 ANN static inline int struct_ctor(const Value v) {
-  return tflag(v->type, tflag_struct) && v->type->nspc->pre_ctor;
+  return tflag(v->type, tflag_struct) && v->type->nspc && v->type->nspc->pre_ctor;
+//  return tflag(v->type, tflag_struct) && v->type->nspc->pre_ctor;
 }
 
 ANN static void decl_expand(const Emitter emit, const Type t) {
@@ -2898,6 +2903,7 @@ ANN m_bool emit_func_def(const Emitter emit, const Func_Def fdef) {
 #define emit_fptr_def  dummy_func
 #define emit_trait_def dummy_func
 #define emit_extend_def dummy_func
+#define emit_prim_def dummy_func
 
 HANDLE_SECTION_FUNC(emit, m_bool, Emitter);
 
index 760e68170f21ffd17c68430d803e884af6fc9604..207062b38cf955420a23095f543e3fa3f50ccd75 100644 (file)
@@ -9,7 +9,9 @@ ANN void free_context(const Context a, Gwion gwion) {
   const Nspc global = a->nspc->parent;
   if(!a->error) // this is quite a hack
     nspc_remref(a->nspc, gwion);
-  if(a->error) nspc_remref(global, gwion);
+//  if(a->error) // this is quite a hack
+  if(a->global) // this is quite a hack
+    nspc_remref(global, gwion);
   free_mstr(gwion->mp, a->name);
   ast_cleaner(gwion, a->tree);
   mp_free(gwion->mp, Context, a);
diff --git a/src/import/import_prim.c b/src/import/import_prim.c
new file mode 100644 (file)
index 0000000..3a2dc48
--- /dev/null
@@ -0,0 +1,235 @@
+#include <limits.h>
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "vm.h"
+#include "instr.h"
+#include "emit.h"
+#include "gwion.h"
+#include "object.h"
+#include "operator.h"
+#include "import.h"
+#include "gwi.h"
+#include "array.h"
+#include "gack.h"
+
+static GACK(gack_prim) {
+  for(m_uint i = 0; i < t->actual_size; i++) {
+    const m_bit *value = VALUE + i;
+    for(unsigned char mask = 1U << (CHAR_BIT-1); mask; mask >>= 1)
+      INTERP_PRINTF("%c", *(uint8_t*)value & mask ? '1' : '0');
+    if(i < t->actual_size - 1)
+      INTERP_PRINTF(" ");
+  }
+}
+
+static INSTR(bit_set) {
+  POP_REG(shred, SZ_INT);
+  const m_int offset = *(m_int*)REG(0);
+  const m_uint byte = offset / CHAR_BIT;
+  const m_uint idx = offset % CHAR_BIT;
+  uint8_t *val = *(uint8_t**)REG(-SZ_INT);
+  val += byte;
+  const m_int key = *(m_int*)REG(-SZ_INT*2);
+  if(key) *val = ((1 << idx) | (*val));
+  else **(m_bit**)REG(-SZ_INT) = ((*val) & (~(1 << (idx))));
+  *(m_bit**)REG(-SZ_INT) = REG(0);
+}
+
+static INSTR(bit_set_fast) {
+  uint8_t *val = *(uint8_t**)REG(-SZ_INT);
+  val += instr->m_val;
+  const m_uint idx = instr->m_val2;
+  const m_int key = *(m_int*)REG(-SZ_INT*2);
+  if(key) *val = ((1 << idx) | (*val));
+  else **(m_bit**)REG(-SZ_INT) = ((*val) & (~(1 << (idx))));
+  *(m_bit**)REG(-SZ_INT) = REG(0);
+}
+
+static INSTR(bit_check) {
+  const m_int offset = *(m_int*)REG(-SZ_INT);
+  if(offset < 0 || offset >= (m_int)instr->m_val)
+    handle(shred, "OutOfBoundByteAccess");
+}
+
+ANN static bool _bit_get(const uint8_t val, const m_uint idx) {
+  const int mask =  1 << idx;
+  const int masked_n = val & mask;
+  return masked_n >> idx;
+}
+
+static INSTR(bit_get) {
+  POP_REG(shred, instr->m_val);
+  const m_int offset = *(m_int*)REG(0);
+  const m_uint byte = offset / CHAR_BIT;
+  const uint8_t val = *(uint8_t*)REG(byte - SZ_INT);
+  *(m_int*)REG(-SZ_INT) = _bit_get(val, offset % CHAR_BIT);
+}
+
+static INSTR(bit_get_fast) {
+  const uint8_t val = *(uint8_t*)REG((int16_t)instr->udata.two);
+  *(m_int*)REG(-instr->m_val) = _bit_get(val, instr->udata.one);
+}
+
+static OP_EMIT(opem_bit_access) {
+  struct ArrayAccessInfo *const info = (struct ArrayAccessInfo *)data;
+  if(!is_prim_int(info->array.exp)) {
+    CHECK_BB(emit_exp(emit, info->array.exp));
+    const Instr check = emit_add_instr(emit, bit_check);
+    check->m_val = info->array.type->actual_size * CHAR_BIT;
+    if(!info->is_var) {
+      const Instr instr = emit_add_instr(emit, bit_get);
+      instr->m_val = info->array.type->size;
+    } else emit_add_instr(emit, bit_set);
+  } else {
+    const m_uint offset = info->array.exp->d.prim.d.num;
+    if(!info->is_var) {
+      const Instr instr = emit_add_instr(emit, bit_get_fast);
+      instr->m_val  = info->type->size;
+      instr->udata.one  = offset % CHAR_BIT;
+      instr->udata.two = (m_int)((offset / CHAR_BIT) - SZ_INT);
+    } else {
+      const Instr instr = emit_add_instr(emit, bit_set_fast);
+      const m_uint offset = info->array.exp->d.prim.d.num;
+      instr->m_val2  = offset % CHAR_BIT;
+      instr->m_val = (offset / CHAR_BIT);
+    }
+  }
+  return GW_OK;
+}
+
+static OP_EMIT(opem_bit_exp) {
+  bool *var = data;
+  var[1] = var[0];
+  return GW_OK;
+}
+
+static OP_CHECK(opck_bit_access) {
+  Array_Sub array = data;
+  const Exp e = array->exp;
+  if(e->next) ERR_N(e->next->pos, "too many expressions for bit access");
+  if(is_prim_int(e)) {
+    m_int idx = e->d.prim.d.num;
+    if(idx < 0 || idx >= (m_int)array->type->size * CHAR_BIT)
+      ERR_N(e->pos, "bit access out of bound");
+  }
+  return env->gwion->type[et_bool];
+}
+
+ANN static void scan_prim_op(const Env env, const Type t){
+  struct Op_Func   opfunc = { .ck = opck_bit_access, .em = opem_bit_access };
+  struct Op_Import opi    = {
+      .op = insert_symbol(env->gwion->st, "@array"),
+      .lhs = env->gwion->type[et_int],
+      .rhs = t,
+      .func = &opfunc
+  };
+  add_op(env->gwion, &opi);
+}
+
+ANN static void scan_prim_op2(const Env env, const Type t){
+  struct Op_Func   opfunc = {.em = opem_bit_exp };
+  struct Op_Import opi    = {
+      .op = insert_symbol(env->gwion->st, "@array_init"),
+      .lhs = t,
+      .ret = env->gwion->type[et_bool],
+      .func = &opfunc
+  };
+  add_op(env->gwion, &opi);
+}
+
+static INSTR(bitset) {
+  POP_REG(shred,  SZ_INT);
+  memcpy(*(uint8_t**)REG(0), REG(-SZ_INT), instr->m_val);
+}
+
+static OP_EMIT(opem_bitset) {
+  Exp_Binary *bin = data;
+  const Instr instr = emit_add_instr(emit, bitset);
+  const Type t = isa(bin->rhs->type, emit->gwion->type[et_int]) > 0
+     ? bin->lhs->type
+     : bin->rhs->type;
+  instr->m_val = t->actual_size;
+  return GW_OK;
+}
+
+static INSTR(bitcast) {
+  memset(REG((m_int)instr->m_val), 0, instr->m_val2);
+}
+
+static OP_EMIT(opem_bitcast) {
+  Exp_Cast *cast = data;
+  const Type t = isa(cast->exp->type, emit->gwion->type[et_int]) > 0
+     ? known_type(emit->env, cast->td)
+     : cast->exp->type;
+  const Instr instr = emit_add_instr(emit, bitcast);
+  instr->m_val  = -SZ_INT + t->actual_size;
+  instr->m_val2 = SZ_INT - t->actual_size;
+  return GW_OK;
+}
+
+ANN2(1,2,3,5) static void prim_op(const Env env, const Type t, const m_str op, const opck ck, const opem em){
+  struct Op_Func   opfunc = { .ck = ck, .em = em };
+  struct Op_Import opi    = {
+      .op = insert_symbol(env->gwion->st, op),
+      .lhs = env->gwion->type[et_int],
+      .rhs = t,
+      .ret = t,
+      .func = &opfunc
+  };
+  add_op(env->gwion, &opi);
+  opi.lhs = t;
+  opi.rhs = opi.ret = env->gwion->type[et_int];
+  add_op(env->gwion, &opi);
+}
+
+ANN static void prim_implicit(const Env env, const Type t){
+  struct Op_Import opi    = {
+      .op = insert_symbol(env->gwion->st, "@implicit"),
+      .lhs = t,
+      .rhs = env->gwion->type[et_int],
+      .ret = env->gwion->type[et_int],
+  };
+  add_op(env->gwion, &opi);
+}
+
+ANN Type mk_primitive(const Env env, const m_str name, const m_uint size) {
+  m_uint sz = SZ_INT;
+  while(sz < size) sz += SZ_INT;
+  const Type t = new_type(env->gwion->mp, name, NULL);
+  t->size = sz;
+  t->actual_size = size;
+  scan_prim_op(env, t);
+  scan_prim_op2(env, t);
+  if(size < SZ_INT) {
+    prim_op(env, t, ":=>", opck_rassign, opem_bitset);
+    prim_op(env, t, "$", NULL, opem_bitcast);
+    prim_implicit(env, t);
+  } else if(size == SZ_INT) {
+    prim_op(env, t, ":=>", opck_rassign, (opem)dummy_func);
+    prim_op(env, t, "$", NULL, (opem)dummy_func);
+    prim_implicit(env, t);
+  } // else provide function to get slices
+  CHECK_BO(mk_gack(env->gwion->mp, t, gack_prim));
+  return t;
+}
+
+// actually we should make a Prim_Def
+// and either execute and free it already
+// or add it to the current ast
+
+ANN m_bool scan0_prim_def(const Env env, const Prim_Def pdef);
+
+//ANN Type gwi_primitive(const Gwi gwi, const m_str name, const m_uint size, const ae_flag flag) {
+ANN m_bool gwi_primitive(const Gwi gwi, const m_str name, const m_uint size, const ae_flag flag) {
+  const Env env = gwi->gwion->env;
+  const Prim_Def pdef = new_prim_def(gwi->gwion->mp, insert_symbol(gwi->gwion->st, name), size, gwi->loc, flag);
+  if(!env->class_def || !tflag(env->class_def, tflag_tmpl)) {
+    const m_bool ret = scan0_prim_def(gwi->gwion->env, pdef);
+    free_prim_def(gwi->gwion->mp, pdef);
+    return ret;
+  }
+  Section section = MK_SECTION(primitive, prim_def, pdef);
+  gwi_body(gwi, &section);
+  return GW_OK;
+}
index ab4a40925e0287dc9cc0f5ea8755905ea55d8828..22030732c0bfb9580bd17563c5159399fec34c90 100644 (file)
@@ -1,6 +1,3 @@
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
 #include "gwion_util.h"
 #include "gwion_ast.h"
 #include "gwion_env.h"
@@ -13,8 +10,6 @@
 #include "operator.h"
 #include "import.h"
 #include "gwi.h"
-#include "mpool.h"
-#include "specialid.h"
 
 ANN m_int gwi_typedef_ini(const Gwi gwi, const restrict m_str type,
                           const restrict m_str name) {
index 419f3be7942ea10cf6cbfc9f9ff31153de8c1c91..eb7b6f67e4a302e4fc954dc96368e8d32628b88c 100644 (file)
@@ -348,6 +348,16 @@ ANN static inline m_bool array_do(const Emitter emit, const Array_Sub array,
   return GW_OK;
 }
 
+ANN m_bool get_emit_var(const Emitter emit, const Type t, bool is_var) {
+  const Env env = emit->env;
+  bool vars[2] = { is_var };
+  struct Op_Import opi = {.op   = insert_symbol("@array_init"),
+                          .lhs  = t,
+                          .data = (uintptr_t)vars};
+  CHECK_BB(op_emit(emit, &opi));
+  return vars[1];
+}
+
 ANN static inline Exp emit_n_exp(const Emitter                 emit,
                                  struct ArrayAccessInfo *const info) {
   const Exp e               = take_exp(info->array.exp, info->array.depth);
@@ -355,7 +365,8 @@ ANN static inline Exp emit_n_exp(const Emitter                 emit,
   e->next                   = NULL;
   struct Array_Sub_ partial = {info->array.exp, info->array.type,
                                info->array.depth};
-  const m_bool      ret     = array_do(emit, &partial, 0);
+  const bool is_var = get_emit_var(emit, array_base(info->array.type), info->is_var);
+  const m_bool      ret     = array_do(emit, &partial, is_var);
   e->next                   = next;
   return ret > 0 ? next : NULL;
 }
@@ -986,6 +997,10 @@ GWION_IMPORT(array) {
   GWI_BB(gwi_oper_ini(gwi, "Array", NULL, NULL))
   GWI_BB(gwi_oper_add(gwi, opck_array_scan))
   GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
+
+  GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, NULL, "bool"))
+  GWI_BB(gwi_oper_end(gwi, "@array_init", NoOp))
+
   gwi_register_freearg(gwi, ArrayAlloc, freearg_array);
   return GW_OK;
 }
index 4e0fa1ab834c470b34567e1ca1cd1d669dc4e214..c1cf7acd1c3011c9d4a88118d6ab28d21bdbc364 100644 (file)
@@ -1,3 +1,4 @@
+#include <limits.h>
 #include "gwion_util.h"
 #include "gwion_ast.h"
 #include "gwion_env.h"
 
 #define CHECK_OP(op, check, func) _CHECK_OP(op, check, int_##func)
 
-static inline bool is_prim(const Exp e) { return e->exp_type == ae_exp_primary; }
-
-static inline bool is_prim_int(const Exp e) {
-  return (is_prim(e) && e->d.prim.prim_type == ae_prim_num);
-}
-
-static inline bool is_prim_float(const Exp e) {
-  return (is_prim(e) && e->d.prim.prim_type == ae_prim_float);
-}
-
 #define POWEROF2_OPT(name, OP)                                                 \
   if (is_prim_int(bin->rhs) && pot(bin->rhs->d.prim.d.num)) {                  \
     bin->op                = insert_symbol(#OP);                               \
@@ -622,38 +613,20 @@ static GWION_IMPORT(float) {
   return GW_OK;
 }
 
-static GACK(gack_u8) {
-  INTERP_PRINTF("%u", *(uint8_t*)VALUE);
-}
-
-static GACK(gack_u16) {
-  INTERP_PRINTF("%u", *(uint16_t*)VALUE);
-}
-
-static GACK(gack_u32) {
-  INTERP_PRINTF("%u", *(uint32_t*)VALUE);
+ANN static m_bool import_ux(const Gwi gwi) {
+  char c[8] = { 'u' };
+  const Env env = gwi->gwion->env;
+  for(uint i = 1; i <= SZ_INT; i *= 2) {
+    sprintf(c+1, "%u", i * CHAR_BIT);
+    const Symbol s = insert_symbol(c);
+    GWI_OB(gwi_primitive(gwi, s_name(s), i, ae_flag_none));
+  }
+  return GW_OK;
 }
 
 GWION_IMPORT(prim) {
-  GWI_BB(import_int(gwi))      // const folded + imm optimized
-  const Type t_u8 = gwi_mk_type(gwi, "u8", SZ_INT, "int");
-  t_u8->actual_size = 1;
-  gwi_gack(gwi, t_u8, gack_u8);
-  gwi_add_type(gwi, t_u8);
-  GWI_BB(gwi_oper_ini(gwi, "int", "u8", "u8"))
-  GWI_BB(gwi_oper_end(gwi, "@implicit", NoOp))
-  const Type t_u16 = gwi_mk_type(gwi, "u16", SZ_INT, "int");
-  t_u16->actual_size = 2;
-  gwi_gack(gwi, t_u16, gack_u16);
-  gwi_add_type(gwi, t_u16);
-  GWI_BB(gwi_oper_ini(gwi, "int", "u16", "u16"))
-  GWI_BB(gwi_oper_end(gwi, "@implicit", NoOp))
-  const Type t_u32 = gwi_mk_type(gwi, "u32", SZ_INT, "int");
-  t_u32->actual_size = 4;
-  gwi_gack(gwi, t_u32, gack_u32);
-  gwi_add_type(gwi, t_u32);
-  GWI_BB(gwi_oper_ini(gwi, "int", "u32", "u32"))
-  GWI_BB(gwi_oper_end(gwi, "@implicit", NoOp))
+  GWI_BB(import_int(gwi))
+  GWI_BB(import_ux(gwi));
   GWI_BB(import_float(gwi))    // const folded
   GWI_BB(import_intfloat(gwi)) // const folded
   GWI_BB(import_floatint(gwi)) // const folded
index 656528b23e88ae1145c2ad296ba7184fd7bb59af..68756d4fb4f3ddf02ac450660789ba0e2eca949e 100644 (file)
@@ -62,12 +62,19 @@ ANN static inline m_bool check_exp_decl_parent(const Env      env,
   return GW_OK;
 }
 
+ANN static m_uint get_decl_size(const Env env, const Value v) {
+  if(safe_tflag(env->class_def, tflag_packed) && v->type->actual_size)
+    return v->type->actual_size;
+  return v->type->size;
+
+}
+
 #define describe_check_decl(a, b, flag)                            \
   ANN static inline void decl_##a(const Env env, const Value v) {  \
     const Nspc nspc = env->curr;                                   \
     flag;                                                          \
     v->from->offset = nspc->b;                                     \
-    nspc->b += v->type->size;                                      \
+    nspc->b += get_decl_size(env, v);                              \
   }
 
 describe_check_decl(member, offset, v->vflag |= vflag_member);
@@ -1919,6 +1926,7 @@ ANN m_bool check_fptr_def(const Env env, const Fptr_Def fptr) {
   return ret;
 }
 
+#define check_prim_def dummy_func
 HANDLE_SECTION_FUNC(check, m_bool, Env)
 
 ANN static m_bool check_parent(const Env env, const Class_Def cdef) {
index 6a4a706636d134dba954f44cd005fabaa8893157..ae57aef3e6533850dcf0ce4ad9d85db71b301f57 100644 (file)
@@ -482,6 +482,23 @@ ANN static m_bool scan0_trait_def(const Env env, const Trait_Def pdef) {
   return GW_OK;
 }
 
+ANN m_bool scan0_prim_def(const Env env, const Prim_Def pdef) {
+  const loc_t loc = pdef->loc;
+  CHECK_BB(env_access(env, pdef->flag, loc));
+  CHECK_BB(scan0_defined(env, pdef->name, loc));
+  const bool global = GET_FLAG(pdef, global);
+  if(global) {
+    context_global(env);
+    env_push_global(env);
+  }
+  const Type t = mk_primitive(env, s_name(pdef->name), pdef->size);
+  add_type(env, env->curr, t);
+  mk_class(env, t, pdef->loc);
+  t->flag = pdef->flag;
+  if(global) env_pop(env, 0);
+  return GW_OK;
+}
+
 HANDLE_SECTION_FUNC(scan0, m_bool, Env)
 
 ANN static m_bool scan0_class_def_inner(const Env env, const Class_Def cdef) {
index e87d898512b347bdcc583021bfd2265f464f90aa..0129144f54ca42b4b29b959fc005a55c98bf9264 100644 (file)
@@ -527,6 +527,10 @@ ANN static m_bool scan1_stmt_return(const Env env, const Stmt_Exp stmt) {
 
 ANN static m_bool scan1_stmt_pp(const Env env, const Stmt_PP stmt) {
   if (stmt->pp_type == ae_pp_include) env->name = stmt->data;
+  if (stmt->pp_type == ae_pp_pragma && !strcmp(stmt->data, "packed")) {
+    if(env->class_def && !tflag(env->class_def, tflag_union)) set_tflag(env->class_def, tflag_packed);
+    else ERR_B(stmt_self(stmt)->pos, "`packed` pragma outside of {G+}class{0} or {G+}struct{0} declaration");
+  }
   return GW_OK;
 }
 
@@ -649,6 +653,7 @@ ANN static inline m_bool scan1_fdef_defined(const Env      env,
   const Value v = nspc_lookup_value1(env->curr, fdef->base->xid);
   if (!v) return GW_OK;
   if (is_func(env->gwion, actual_type(env->gwion, v->type))) return GW_OK; // is_callable
+  if(fdef->builtin) return GW_OK;
   if ((!env->class_def || !GET_FLAG(env->class_def, final)) &&
       !nspc_lookup_value0(env->curr, fdef->base->xid))
     ERR_B(fdef->base->pos,
@@ -686,7 +691,6 @@ ANN static m_bool _scan1_func_def(const Env env, const Func_Def fdef) {
   return ret;
 }
 
-
 ANN m_bool scan1_func_def(const Env env, const Func_Def fdef) {
   const uint16_t depth = env->scope->depth;
   env->scope->depth = 0;
@@ -697,6 +701,7 @@ ANN m_bool scan1_func_def(const Env env, const Func_Def fdef) {
 
 #define scan1_trait_def dummy_func
 #define scan1_extend_def dummy_func
+#define scan1_prim_def dummy_func
 HANDLE_SECTION_FUNC(scan1, m_bool, Env)
 
 ANN static Type scan1_get_parent(const Env env, const Type_Def tdef) {
index dcf04cfda143e476ca880cfa16305f3aebaf46cb..c7aefd8f4427bcd96169b46b53eb277f3c2aec9a 100644 (file)
@@ -586,6 +586,7 @@ ANN m_bool scan2_func_def(const Env env, const Func_Def fdef) {
 #define scan2_enum_def  dummy_func
 #define scan2_trait_def dummy_func
 #define scan2_extend_def dummy_func
+#define scan2_prim_def dummy_func
 HANDLE_SECTION_FUNC(scan2, m_bool, Env)
 
 ANN static m_bool scan2_parent(const Env env, const Class_Def cdef) {
diff --git a/tests/primitive/access.gw b/tests/primitive/access.gw
new file mode 100644 (file)
index 0000000..a632e7b
--- /dev/null
@@ -0,0 +1,4 @@
+#! [contains] true
+var u8 u;
+true :=> u[2];
+<<< u[2] >>>;
diff --git a/tests/primitive/dyn_access.gw b/tests/primitive/dyn_access.gw
new file mode 100644 (file)
index 0000000..d98ac5c
--- /dev/null
@@ -0,0 +1,6 @@
+#! [contains] true
+var u8 u;
+2 :=> var int i;
+true :=> u[i];
+<<< u >>>;
+<<< u[i] >>>;
diff --git a/tests/primitive/oob.gw b/tests/primitive/oob.gw
new file mode 100644 (file)
index 0000000..b247d64
--- /dev/null
@@ -0,0 +1,4 @@
+#! [contains] OutOfBoundByteAccess
+9 :=> var int i;
+var u8 u;
+u[i];
diff --git a/tests/primitive/static_oob.gw b/tests/primitive/static_oob.gw
new file mode 100644 (file)
index 0000000..5e4498f
--- /dev/null
@@ -0,0 +1,3 @@
+#! [contains] out of bound
+var u8 u;
+u[-3];
diff --git a/tests/primitive/too_many_exp.gw b/tests/primitive/too_many_exp.gw
new file mode 100644 (file)
index 0000000..839f4b7
--- /dev/null
@@ -0,0 +1,3 @@
+#! [contains] too many expressions
+var u8 u;
+u[1][2];