]> Nishi Git Mirror - gwion.git/commitdiff
:art: Use t_undefined
authorfennecdjay <astor.jeremie@wanadoo.fr>
Mon, 8 Apr 2019 15:26:22 +0000 (17:26 +0200)
committerfennecdjay <astor.jeremie@wanadoo.fr>
Mon, 8 Apr 2019 15:26:22 +0000 (17:26 +0200)
15 files changed:
ast
include/env.h
include/parse.h
include/type.h
src/emit/emit.c
src/lib/engine.c
src/lib/gack.c
src/lib/import.c
src/lib/ptr.c
src/parse/check.c
src/parse/scan1.c
src/parse/scan2.c
src/parse/type_decl.c
tests/error/typeof_error.gw [new file with mode: 0644]
tests/tree/unused_var.gw [deleted file]

diff --git a/ast b/ast
index de339e926479367591c6dd16f63d331a4aedc797..be6de5a94edfab64aa61709c2a9ff3f1de5b9bff 160000 (submodule)
--- a/ast
+++ b/ast
@@ -1 +1 @@
-Subproject commit de339e926479367591c6dd16f63d331a4aedc797
+Subproject commit be6de5a94edfab64aa61709c2a9ff3f1de5b9bff
index ade845ade40480007c63afcc5e18b4ae3ac8b3d4..9934d14313b341229efd4ca14c8d3e8980bd6d94 100644 (file)
@@ -58,4 +58,5 @@ ANN m_bool already_defined(const Env env, const Symbol s, const uint pos);
 ANN m_bool type_engine_check_prog(const Env, const Ast);
 ANN Func get_func(const Env, const Func_Def);
 ANN m_bool traverse_func_template(const Env env, const Func_Def def, const Type_List types);
+ANN ID_List str2list(SymTable *st, const m_str path, m_uint* array_depth);
 #endif
index f5224338f33dcc5b214e260b4b81140c90dfe9e0..c5350fe91b56fb7b90fb6a118a0b900409caecc8 100644 (file)
@@ -27,7 +27,7 @@ static const _exp_func exp_func[] = {
   (_exp_func)prefix##_exp_decl,    (_exp_func)prefix##_exp_binary, (_exp_func)prefix##_exp_unary, \
   (_exp_func)prefix##_exp_primary, (_exp_func)prefix##_exp_cast,   (_exp_func)prefix##_exp_post,  \
   (_exp_func)prefix##_exp_call,    (_exp_func)prefix##_exp_array,  (_exp_func)prefix##_exp_if,    \
-  (_exp_func)prefix##_exp_dot,     (_exp_func)prefix##_exp_lambda                                 \
+  (_exp_func)prefix##_exp_dot,     (_exp_func)prefix##_exp_lambda, (_exp_func)prefix##_exp_typeof \
 };
 
 #define DECL_SECTION_FUNC(prefix)                                                                 \
@@ -41,11 +41,13 @@ ANN static inline m_bool prefix##_section(const void* a, /* const */ Section* se
 
 #define HANDLE_EXP_FUNC(prefix, type, ret)                                                        \
 DECL_EXP_FUNC(prefix)                                                                             \
-ANN static inline type prefix##_exp(const Env env, Exp exp) { GWDEBUG_EXE                         \
+ANN type prefix##_exp(const Env env, Exp exp) { GWDEBUG_EXE                         \
   do CHECK_BB(exp_func[exp->exp_type](env, &exp->d))                                              \
   while((exp = exp->next));                                                                       \
   return ret;                                                                                     \
 }
+ANN m_bool scan1_exp(const Env, Exp);
+ANN m_bool scan2_exp(const Env, Exp);
 
 #define describe_stmt_func(prefix, name, type, prolog, exp) \
 ANN static m_bool prefix##_stmt_##name(const Env env, const type stmt) { GWDEBUG_EXE \
index 3340d6107ab35fe5f6fa241a754d95e24290bd60..228891f376ae19cf8df45dd4c1b75fade5191fbd 100644 (file)
@@ -21,7 +21,7 @@ struct Type_ {
 
 Type t_void, t_int, t_bool, t_float, t_dur, t_time, t_now, t_complex, t_polar, t_vec3, t_vec4,
   t_null, t_object, t_shred, t_fork, t_event, t_ugen, t_string, t_ptr, t_array, t_gack,
-  t_function, t_fptr, t_vararg, t_lambda, t_class, t_union;
+  t_function, t_fptr, t_vararg, t_lambda, t_class, t_union, t_undefined;
 
 ANN2(1,3) ANEW Type new_type(MemPool, const m_uint xid, const m_str name, const Type);
 ANEW ANN Type type_copy(MemPool, const Type type);
index 1f41203c71851be0a80d839ae713070751e3665c..0eb218a0adee5f5169ead50e3d86bd6fbc0015d7 100644 (file)
@@ -479,6 +479,7 @@ ANN static m_bool prim_gack(const Emitter emit, const Exp_Primary* primary) {
     offset += e->type->size;
     if(e->type != emit->env->class_def)
       ADD_REF(e->type);
+puts(e->type->name);
   } while((e = e->next));
   if(emit_exp(emit, exp, 0) < 0) {
     free_vector(emit->gwion->p, v);
@@ -502,9 +503,14 @@ ANN static m_bool emit_exp_primary(const Emitter emit, const Exp_Primary* prim)
 
 ANN static m_bool emit_dot_static_data(const Emitter emit, const Value v, const uint emit_var) { GWDEBUG_EXE
   const m_uint size = v->type->size;
-  const Instr instr = emit_kind(emit, size, emit_var, dotstatic);
-  instr->m_val =  (m_uint)(v->owner_class->nspc->info->class_data + v->offset);
-  instr->m_val2 = size;
+  if(isa(v->type, t_class) < 0) {
+    const Instr instr = emit_kind(emit, size, emit_var, dotstatic);
+    instr->m_val = (m_uint)(v->owner_class->nspc->info->class_data + v->offset);
+    instr->m_val2 = size;
+  } else {
+    const Instr instr = emit_add_instr(emit, RegPushImm);
+    instr->m_val = (m_uint)v->type;
+  }
   return GW_OK;
 }
 
@@ -535,6 +541,7 @@ ANN static m_bool emit_exp_decl_non_static(const Emitter emit, const Var_Decl va
   const m_bool is_obj = isa(type, t_object) > 0;
   const uint emit_addr = ((is_ref && !array) || isa(type, t_object) < 0) ?
     emit_var : 1;
+puts(v->type->name);
   if(is_obj && (is_array || !is_ref))
     CHECK_BB(emit_instantiate_object(emit, type, array, is_ref))
   f_instr *exec = (f_instr*)allocmember;
@@ -980,6 +987,12 @@ ANN static m_bool emit_exp_lambda(const Emitter emit, const Exp_Lambda * lambda)
   return GW_OK;
 }
 
+ANN static m_bool emit_exp_typeof(const Emitter emit, const Exp_Typeof *exp) {
+  const Instr instr = emit_add_instr(emit, RegPushImm);
+  instr->m_val = (m_uint)exp->exp->type;
+  return GW_OK;
+}
+
 DECL_EXP_FUNC(emit)
 
 ANN2(1) static m_bool emit_exp(const Emitter emit, Exp exp, const m_bool ref) { GWDEBUG_EXE
index 7ba41df000bcf8e0d7cf0a01859e98ab3caa26f8..ff4608ab83316415a6ec27f5b7625a2a0fcef41e 100644 (file)
@@ -34,7 +34,10 @@ static FREEARG(freearg_gack) {
 }
 
 ANN static m_bool import_core_libs(const Gwi gwi) {
-  CHECK_OB((t_class = gwi_mk_type(gwi, "@Class", SZ_INT, NULL)))
+  CHECK_OB((t_undefined = gwi_mk_type(gwi, "@Undefined", SZ_INT, NULL))) // size = SZ_INT to enable declarations
+  CHECK_OB((t_class = gwi_mk_type(gwi, "Class", SZ_INT, NULL)))
+  CHECK_BB(gwi_add_type(gwi, t_class))
+  SET_FLAG(t_class, abstract);
   CHECK_OB((t_void  = gwi_mk_type(gwi, "void", 0, NULL)))
   CHECK_BB(gwi_add_type(gwi, t_void))
   CHECK_OB((t_null  = gwi_mk_type(gwi, "@null",  SZ_INT, NULL)))
index a82199f4eda59aa7c4bbfb35c4bddfc14e6597d6..2eecff797fb637066f717c3ecb3d270def2f76b5 100644 (file)
@@ -114,6 +114,8 @@ ANN void gack(const m_bit* reg, const Instr instr) {
       print_object(type, *(M_Object*)(reg-offset));
     else if(isa(type, t_function) > 0)
       print_func(type, (reg-offset));
+    else if(type == t_class)
+      print_type(type);
     else if(isa(type, t_class) > 0)
       print_type(type->d.base_type);
     else if(isa(type, t_void) > 0)
index 1c4cd2836b9244e56a60b3c8ea3bc7b3d227003d..fc2f8db52019ae37a13b595b93f9bcb20a03cc42 100644 (file)
@@ -140,7 +140,7 @@ ANN static m_bool path_valid(SymTable *st,ID_List* list, const struct Path* p) {
   return GW_OK;
 }
 
-ANN static ID_List str2list(SymTable *st, const m_str path, m_uint* array_depth) {
+ANN /* static */ ID_List str2list(SymTable *st, const m_str path, m_uint* array_depth) {
   const m_uint len = strlen(path);
   ID_List list = NULL;
   m_uint depth = 0;
index 735baa4817134d84c9f67872448baf3b65f6dc3e..95a4298f167c9def657686396ac39909373ab21f 100644 (file)
 
 static OP_CHECK(opck_ptr_assign) {
   const Exp_Binary* bin = (Exp_Binary*)data;
-Type t = bin->lhs->type;
-do {
-  if(!strcmp(t->name, get_type_name(env, bin->rhs->type->name, 1))) {
-    if(bin->lhs->meta != ae_meta_var)
-      ERR_N(0, "left side operand is constant")
-    bin->lhs->emit_var = 1;
-    return bin->lhs->type;
-  }
-} while((t = t->parent));
+  Type t = bin->lhs->type;
+  do {
+    if(!strcmp(t->name, get_type_name(env, bin->rhs->type->name, 1))) {
+      if(bin->lhs->meta != ae_meta_var)
+        ERR_N(0, "left side operand is constant")
+      bin->lhs->emit_var = 1;
+      return bin->lhs->type;
+    }
+  } while((t = t->parent));
   return t_null;
 }
 
index a4a29ba6d4bdd9978c0a944f07e3a6d91b899d01..4c509fbe0d74f007075109e42b3c180cfef164fb 100644 (file)
@@ -74,8 +74,30 @@ ANN static m_bool check_fptr_decl(const Env env, const Var_Decl var) {
   return GW_OK;
 }
 
+ANN Type check_td(const Env env, Type_Decl *td) {
+  CHECK_BO(scan1_exp(env, td->exp))
+  CHECK_BO(scan2_exp(env, td->exp))
+  CHECK_OO(check_exp(env, td->exp))
+//assert(actual_type(td->exp->type));
+//printf("HERE %p %p %p\n", t_class, td->exp->type, td->exp->type->d.base_type);
+  if(!actual_type(td->exp->type) || (isa(td->exp->type, t_class) < 0 && actual_type(td->exp->type) == t_class))
+    ERR_O(td->exp->pos, "Expression must be of type '%s', not '%s'\n"
+      "maybe you meant typeof(Expression)", t_class->name, td->exp->type->name);
+  m_uint depth;
+  td->xid = str2list(env->gwion->st, actual_type(td->exp->type)->name, &depth);
+  return actual_type(td->exp->type);
+}
+
 ANN Type check_exp_decl(const Env env, const Exp_Decl* decl) { GWDEBUG_EXE
   Var_Decl_List list = decl->list;
+
+  if(!decl->td->xid) {
+    const Type t = check_td(env, decl->td);
+    CHECK_OO(t)
+    ((Exp_Decl*)decl)->type = NULL;
+    CHECK_BO(scan1_exp(env, exp_self(decl)))
+    CHECK_BO(scan2_exp(env, exp_self(decl)))
+  }
   if(GET_FLAG(decl->type , template)) {
     const Type t = typedef_base(decl->type);
     CHECK_BO(traverse_template(env, t->def))
@@ -85,12 +107,6 @@ ANN Type check_exp_decl(const Env env, const Exp_Decl* decl) { GWDEBUG_EXE
   if(global)
     scope = env_push_global(env);
   do {
-    if(!env->class_def && !GET_FLAG(list->self->value, builtin) &&
-        !GET_FLAG(list->self->value, used)) {
-      err_msg(list->self->pos, "unused variable '%s'",
-          list->self->value->name);
-      continue;
-    }
     const Var_Decl var = list->self;
     const Value v = var->value;
     if(env->class_def && !env->scope->depth && env->class_def->parent)
@@ -593,7 +609,7 @@ ANN static Type check_exp_binary(const Env env, const Exp_Binary* bin) { GWDEBUG
 ANN static Type check_exp_cast(const Env env, const Exp_Cast* cast) { GWDEBUG_EXE
   const Type t = check_exp(env, cast->exp);
   CHECK_OO(t)
-  CHECK_OO((exp_self(cast)->type = known_type(env, cast->td)))
+  CHECK_OO((exp_self(cast)->type = cast->td->xid ? known_type(env, cast->td) : check_td(env, cast->td)))
   struct Op_Import opi = { .op=op_cast, .lhs=t, .rhs=exp_self(cast)->type, .data=(uintptr_t)cast };
   OP_RET(cast, "cast")
 }
@@ -686,11 +702,19 @@ ANN static m_bool check_stmt_type(const Env env, const Stmt_Type stmt) { GWDEBUG
 ANN static Type check_exp_lambda(const Env env NUSED,
     const Exp_If* exp_if NUSED) { return t_lambda; }
 
+ANN static Type check_exp_typeof(const Env env, const Exp_Typeof *exp) {
+  const Type t = check_exp(env, exp->exp);
+  CHECK_OO(t)
+  const Value v = nspc_lookup_value1(t->owner, insert_symbol(t->name));
+  CHECK_OO(v)
+  return v->type;
+}
+
 static const _type_func exp_func[] = {
   (_type_func)check_exp_decl,    (_type_func)check_exp_binary, (_type_func)check_exp_unary,
   (_type_func)check_exp_primary, (_type_func)check_exp_cast,   (_type_func)check_exp_post,
   (_type_func)check_exp_call,    (_type_func)check_exp_array,  (_type_func)check_exp_if,
-  (_type_func)check_exp_dot,     (_type_func)check_exp_lambda
+  (_type_func)check_exp_dot,     (_type_func)check_exp_lambda, (_type_func)check_exp_typeof
 };
 
 ANN static inline Type check_exp(const Env env, const Exp exp) { GWDEBUG_EXE
@@ -996,6 +1020,8 @@ ANN static m_bool check_func_args(const Env env, Arg_List arg_list) { GWDEBUG_EX
   do {
     const Var_Decl decl = arg_list->var_decl;
     const Value v = decl->value;
+    if(arg_list->td && !arg_list->td->xid)
+      arg_list->type = v->type = check_td(env, arg_list->td);
     if(isa(v->type, t_object) > 0 || isa(v->type, t_function) > 0)
       UNSET_FLAG(env->func, pure);
     CHECK_BB(already_defined(env, decl->xid, decl->pos))
@@ -1061,6 +1087,10 @@ ANN m_bool check_func_def(const Env env, const Func_Def f) { GWDEBUG_EXE
   m_bool ret = GW_OK;
   if(tmpl_list_base(f->tmpl))
     return env->class_def ? check_parent_match(env, f) : 1;
+  if(f->base->td && !f->base->td->xid) {
+    f->base->ret_type = check_td(env, f->base->td);
+    return traverse_func_def(env, f);
+  }
   CHECK_BB(check_func_def_override(env, f))
   if(env->class_def)
     CHECK_BB(check_parent_match(env, f))
@@ -1139,6 +1169,10 @@ ANN static inline void inherit(const Type t) {
 ANN m_bool check_class_def(const Env env, const Class_Def class_def) { GWDEBUG_EXE
   if(tmpl_class_base(class_def->tmpl))
     return GW_OK;
+  if(class_def->base.type->parent == t_undefined) {
+    class_def->base.type->parent = check_td(env, class_def->base.ext);
+    return traverse_class_def(env, class_def);
+  }
   const Type the_class = class_def->base.type;
   if(class_def->base.ext)
     CHECK_BB(check_class_parent(env, class_def))
index b98a6753a1c13c26d9e0bb59a02973182426bee7..44fe66f5d8bdfb7efdd5fa960871ba73b5b7ecbb 100644 (file)
@@ -12,7 +12,7 @@
 #define FAKE_FUNC ((Func)1)
 
 ANN m_bool scan0_class_def(const Env env, const Class_Def class_def);
-ANN static m_bool scan1_exp(const Env env, Exp exp);
+ANN /* static */ m_bool scan1_exp(const Env env, Exp exp);
 ANN static m_bool scan1_stmt_list(const Env env, Stmt_List list);
 ANN m_bool scan1_class_def(const Env env, const Class_Def class_def);
 ANN static m_bool scan1_stmt(const Env env, Stmt stmt);
@@ -64,7 +64,7 @@ ANN m_bool scan1_exp_decl(const Env env, Exp_Decl* decl) { GWDEBUG_EXE
     const Var_Decl var = list->self;
     const Value former = nspc_lookup_value0(env->curr, var->xid);
     CHECK_BB(isres(var->xid))
-    if(former && (!env->class_def ||
+    if(!decl->td->exp && former && (!env->class_def ||
         (!GET_FLAG(env->class_def, template) || !GET_FLAG(env->class_def, scan1))))
       ERR_B(var->pos, "variable %s has already been defined in the same scope...",
               s_name(var->xid))
@@ -80,6 +80,7 @@ ANN m_bool scan1_exp_decl(const Env env, Exp_Decl* decl) { GWDEBUG_EXE
       SET_FLAG(v, ref);
     if(!env->func && !env->scope->depth && !env->class_def)
       SET_FLAG(v, global);
+    v->type = t;
     v->d.ptr = var->addr;
     v->owner = !env->func ? env->curr : NULL;
     v->owner_class = env->scope->depth ? NULL : env->class_def;
@@ -135,12 +136,16 @@ ANN static m_bool scan1_exp_if(const Env env, const Exp_If* exp_if) { GWDEBUG_EX
   return scan1_exp(env, exp_if->else_exp);
 }
 
-ANN static inline m_bool scan1_exp_unary(const restrict Env env, const Exp_Unary * unary) {
+ANN static inline m_bool scan1_exp_unary(const restrict Env env, const Exp_Unary *unary) {
   if((unary->op == op_spork || unary->op == op_fork) && unary->code)
     return scan1_stmt(env, unary->code);
   return unary->exp ? scan1_exp(env, unary->exp) : GW_OK;
 }
 
+ANN static inline m_bool scan1_exp_typeof(const restrict Env env, const Exp_Typeof *exp) {
+  return scan1_exp(env, exp->exp);
+}
+
 #define scan1_exp_lambda dummy_func
 HANDLE_EXP_FUNC(scan1, m_bool, 1)
 
@@ -291,20 +296,24 @@ ANN m_bool scan1_func_def(const Env env, const Func_Def f) { GWDEBUG_EXE
 DECL_SECTION_FUNC(scan1)
 
 ANN static m_bool scan1_class_parent(const Env env, const Class_Def class_def) {
+  const uint pos = class_def->base.ext->xid ? class_def->base.ext->xid->pos :
+    class_def->base.ext->exp->pos;
   if(class_def->base.ext->array)
     CHECK_BB(scan1_exp(env, class_def->base.ext->array->exp))
   const Type parent = class_def->base.type->parent = known_type(env, class_def->base.ext);
   CHECK_OB(parent)
+  if(parent == t_undefined)
+    return GW_OK;
   if(parent == class_def->base.type)
-    ERR_B(class_def->base.ext->xid->pos, "class '%s' cannot extend itself",
+    ERR_B(pos, "class '%s' cannot extend itself",
       class_def->base.type->name);
   if(isa(class_def->base.type->parent, t_object) < 0)
-    ERR_B(class_def->base.ext->xid->pos, "cannot extend primitive type '%s'",
+    ERR_B(pos, "cannot extend primitive type '%s'",
             class_def->base.type->parent->name)
   if(!GET_FLAG(parent, scan1) && parent->def)
     CHECK_BB(scan1_class_def(env, parent->def))
   if(type_ref(parent))
-    ERR_B(class_def->base.ext->xid->pos, "can't use ref type in class extend")
+    ERR_B(pos, "can't use ref type in class extend")
   return GW_OK;
 }
 
index 9f1ec4d59b66c09556ac5d095a1095d30d55052d..e544d2f364ef768eb5256d5ea09a7f32c7182e79 100644 (file)
@@ -13,7 +13,7 @@
 #include "nspc.h"
 #include "operator.h"
 
-ANN static m_bool scan2_exp(const Env, const Exp);
+ANN /* static */ m_bool scan2_exp(const Env, const Exp);
 ANN static m_bool scan2_stmt(const Env, const Stmt);
 ANN static m_bool scan2_stmt_list(const Env, Stmt_List);
 extern ANN m_bool scan1_class_def(const Env, const Class_Def);
@@ -208,6 +208,10 @@ ANN static m_bool scan2_exp_unary(const Env env, const Exp_Unary * unary) {
   return GW_OK;
 }
 
+ANN static inline m_bool scan2_exp_typeof(const restrict Env env, const Exp_Typeof *exp) {
+  return scan2_exp(env, exp->exp);
+}
+
 #define scan2_exp_lambda dummy_func
 HANDLE_EXP_FUNC(scan2, m_bool, 1)
 
@@ -502,7 +506,7 @@ ANN m_bool scan2_func_def(const Env env, const Func_Def f) { GWDEBUG_EXE
         f->stack_depth += SZ_INT;
       if(GET_FLAG(func->def, variadic))
         f->stack_depth += SZ_INT;
-      f->base->ret_type = type_decl_resolve(env, f->base->td);
+      f->base->ret_type = known_type(env, f->base->td);
       return (f->base->args && f->base->args->type) ? scan2_args(env, f) : GW_OK;
     }
   }
index b410083dac23c9c4e4841116cefefad09387480e..9bbc9598111047a448905a24b354146664837d3d 100644 (file)
@@ -81,12 +81,14 @@ ANN static inline void* type_unknown(const Env env, const ID_List id) {
 }
 
 ANN static Type prim_ref(const Type t, const Type_Decl* td) {
-  if(GET_FLAG(td, ref) && isa(t, t_object) < 0)
+  if(GET_FLAG(td, ref) && isa(t, t_object) < 0 && isa(t, t_class) < 0)
     ERR_O(td->xid->pos, "primitive types cannot be used as reference (@)...\n")
   return t;
 }
 
 ANN Type known_type(const Env env, const Type_Decl* td) {
+  if(!td->xid)
+    return t_undefined;
   const Type t = type_decl_resolve(env, td);
   return t ? prim_ref(t, td) : type_unknown(env, td->xid);
 }
diff --git a/tests/error/typeof_error.gw b/tests/error/typeof_error.gw
new file mode 100644 (file)
index 0000000..fcfd205
--- /dev/null
@@ -0,0 +1 @@
+~~ 1 + 2 ~~ i;
\ No newline at end of file
diff --git a/tests/tree/unused_var.gw b/tests/tree/unused_var.gw
deleted file mode 100644 (file)
index 9744da1..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-// [contains] unused variable
-int i;