From cf903556af71ae49899253041bad8278cb5f6507 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Sat, 12 Dec 2020 12:11:37 +0100 Subject: [PATCH] :art: More Tagged unions --- ast | 2 +- examples/member.gw | 1 - examples/object.gw | 2 - examples/op.gw | 1 - examples/static.gw | 1 - examples/string.gw | 1 - examples/union.gw | 6 - examples/vararg.gw | 2 +- include/emit.h | 4 - include/env/env.h | 4 - include/env/type.h | 9 +- include/operator.h | 18 +- scripts/afl-dict/sum | 1 - src/emit/emit.c | 14 +- src/env/type.c | 2 +- src/env/type_special.c | 62 ------ src/import/import_checker.c | 4 - src/lib/array.c | 29 +-- src/lib/engine.c | 8 +- src/lib/event.c | 2 +- src/lib/instr.c | 2 +- src/lib/lib_func.c | 38 +--- src/lib/lib_func.cnano | 196 ------------------ src/lib/object.c | 4 +- src/lib/object_op.c | 154 ++++---------- src/lib/opfunc.c | 6 +- src/lib/prim.c | 2 +- src/lib/ptr.c | 4 +- src/lib/string.c | 28 +-- src/lib/ugen.c | 8 +- src/lib/vararg.c | 6 +- src/parse/check.c | 48 ++++- src/parse/operator.c | 64 +----- src/parse/scan1.c | 2 - src/parse/scanx.c | 8 +- src/parse/type_decl.c | 17 +- tests/UsrUgen/null_tick.gw | 3 - tests/bug/Tester.gw | 26 --- tests/error/array_incompatible.gw | 2 +- tests/error/array_multi_except.gw | 4 - tests/error/connect_except.gw | 3 - tests/error/empty_member_ptr.gw | 9 - tests/error/empty_obj_data.gw | 8 - tests/error/ev.gw | 3 - tests/error/fail_assign.gw | 3 - tests/error/func_non.gw | 2 +- tests/error/func_ptr_empty.gw | 4 - tests/error/if_exp_compat.gw | 2 +- .../error/non_public_typedef_global_scope.gw | 6 - tests/error/nonnull_class_extend.gw | 4 - tests/error/not_nn.gw | 3 - tests/error/null_array_access.gw | 3 - tests/error/null_array_access_multi.gw | 3 - tests/error/null_auto.gw | 4 - tests/error/op_match.gw | 2 +- tests/error/union_unknown.gw | 5 +- tests/interp/to_string.gw | 2 +- tests/new/ref.gw | 2 +- tests/nonnull/cast_non_null.gw | 2 - tests/nonnull/cast_non_null2.gw | 2 - tests/nonnull/dynamic_implicit_nonnull.gw | 3 - tests/nonnull/nonnull2nullable.gw | 1 - tests/nonnull/nonnull_assign_nonnull.gw | 2 - tests/nonnull/nonnull_at_nonnull.gw | 1 - tests/nonnull/nonnull_cast_nonnull.gw | 1 - tests/nonnull/nonnull_decl.gw | 1 - tests/nonnull/nonnull_decl_ref_assign.gw | 1 - tests/nonnull/nonnull_err_cast_dynamic.gw | 3 - tests/nonnull/nonnull_err_dynamic.gw | 5 - tests/nonnull/nonnull_err_static_cast.gw | 3 - tests/nonnull/nonnull_impl_nonnull.gw | 2 - tests/nonnull/nonnull_implicit_nonnull.gw | 2 - tests/nonnull/normal_at_nonnull.gw | 1 - tests/nonnull/normal_cast_nonnull.gw | 1 - tests/nonnull/normal_impl_nonnull.gw | 2 - tests/nonnull/null_at_nonnull.gw | 2 - tests/nonnull/null_cast_nonnull.gw | 2 - tests/nonnull/null_impl_nonnull.gw | 3 - tests/nonnull/ref.gw | 1 - tests/nonnull/ref_at_nonnull.gw | 2 - tests/nonnull/ref_cast_nonnull.gw | 2 - tests/nonnull/ref_impl_nonnull.gw | 3 - tests/nonnull/ref_nonnull.gw | 3 - tests/nonnull/static_implicit_nonnull.gw | 4 - tests/nonnull/void_nonnull.gw | 2 - tests/string/eq.gw | 9 - tests/tree/call_nonnull.gw | 3 - tests/tree/new.gw | 1 - tests/tree/set_obj.gw | 4 +- tests/tree/variadic_test.gw | 2 +- 90 files changed, 169 insertions(+), 770 deletions(-) delete mode 100644 examples/object.gw delete mode 100644 examples/union.gw delete mode 100644 src/env/type_special.c delete mode 100644 src/lib/lib_func.cnano delete mode 100644 tests/UsrUgen/null_tick.gw delete mode 100644 tests/bug/Tester.gw delete mode 100644 tests/error/array_multi_except.gw delete mode 100644 tests/error/connect_except.gw delete mode 100644 tests/error/empty_member_ptr.gw delete mode 100644 tests/error/empty_obj_data.gw delete mode 100644 tests/error/ev.gw delete mode 100644 tests/error/fail_assign.gw delete mode 100644 tests/error/func_ptr_empty.gw delete mode 100644 tests/error/non_public_typedef_global_scope.gw delete mode 100644 tests/error/nonnull_class_extend.gw delete mode 100644 tests/error/not_nn.gw delete mode 100644 tests/error/null_array_access.gw delete mode 100644 tests/error/null_array_access_multi.gw delete mode 100644 tests/error/null_auto.gw delete mode 100644 tests/nonnull/cast_non_null.gw delete mode 100644 tests/nonnull/cast_non_null2.gw delete mode 100644 tests/nonnull/dynamic_implicit_nonnull.gw delete mode 100644 tests/nonnull/nonnull2nullable.gw delete mode 100644 tests/nonnull/nonnull_assign_nonnull.gw delete mode 100644 tests/nonnull/nonnull_at_nonnull.gw delete mode 100644 tests/nonnull/nonnull_cast_nonnull.gw delete mode 100644 tests/nonnull/nonnull_decl.gw delete mode 100644 tests/nonnull/nonnull_decl_ref_assign.gw delete mode 100644 tests/nonnull/nonnull_err_cast_dynamic.gw delete mode 100644 tests/nonnull/nonnull_err_dynamic.gw delete mode 100644 tests/nonnull/nonnull_err_static_cast.gw delete mode 100644 tests/nonnull/nonnull_impl_nonnull.gw delete mode 100644 tests/nonnull/nonnull_implicit_nonnull.gw delete mode 100644 tests/nonnull/normal_at_nonnull.gw delete mode 100644 tests/nonnull/normal_cast_nonnull.gw delete mode 100644 tests/nonnull/normal_impl_nonnull.gw delete mode 100644 tests/nonnull/null_at_nonnull.gw delete mode 100644 tests/nonnull/null_cast_nonnull.gw delete mode 100644 tests/nonnull/null_impl_nonnull.gw delete mode 100644 tests/nonnull/ref.gw delete mode 100644 tests/nonnull/ref_at_nonnull.gw delete mode 100644 tests/nonnull/ref_cast_nonnull.gw delete mode 100644 tests/nonnull/ref_impl_nonnull.gw delete mode 100644 tests/nonnull/ref_nonnull.gw delete mode 100644 tests/nonnull/static_implicit_nonnull.gw delete mode 100644 tests/nonnull/void_nonnull.gw delete mode 100644 tests/tree/call_nonnull.gw diff --git a/ast b/ast index 3047b71b..2c9e91d5 160000 --- a/ast +++ b/ast @@ -1 +1 @@ -Subproject commit 3047b71b37f6f2416d9374da8875a7d17da0ad65 +Subproject commit 2c9e91d5b289259b22c78a2b75b34b3c4111dbc6 diff --git a/examples/member.gw b/examples/member.gw index 1820dead..b06f513d 100644 --- a/examples/member.gw +++ b/examples/member.gw @@ -19,4 +19,3 @@ var C c; #! write members <<< 12 => c.i >>>; <<< 1.2 => c.f >>>; -<<< null @=> c.o >>>; diff --git a/examples/object.gw b/examples/object.gw deleted file mode 100644 index b134402f..00000000 --- a/examples/object.gw +++ /dev/null @@ -1,2 +0,0 @@ -fun void test(Object o) { <<< o >>>; } -<<< new Object == null , " ", null => test >>>; diff --git a/examples/op.gw b/examples/op.gw index 6a207eeb..f6a264b0 100644 --- a/examples/op.gw +++ b/examples/op.gw @@ -14,7 +14,6 @@ operator void => (Object o, C c) { <<< "success" >>>; } -#!operator int plusplus(null d, int i){} var int i; var Object o; <<< o, " ", i >>>; diff --git a/examples/static.gw b/examples/static.gw index 1287dbc8..777b56f7 100644 --- a/examples/static.gw +++ b/examples/static.gw @@ -22,4 +22,3 @@ class C #! write members <<< 12 => C.i >>>; <<< 1.2 => C.f >>>; -<<< null @=> C.o >>>; diff --git a/examples/string.gw b/examples/string.gw index f6978082..a0ce84ba 100644 --- a/examples/string.gw +++ b/examples/string.gw @@ -1,4 +1,3 @@ var string s; "CamelCase" => s; <<< "test" => s >>>; -<<< null @=> s >>>; #!test me diff --git a/examples/union.gw b/examples/union.gw deleted file mode 100644 index b20c5517..00000000 --- a/examples/union.gw +++ /dev/null @@ -1,6 +0,0 @@ -union -{ - int i; - Object o; -}; -<<< i, " ", o >>>; diff --git a/examples/vararg.gw b/examples/vararg.gw index 52c70146..6b8603f4 100644 --- a/examples/vararg.gw +++ b/examples/vararg.gw @@ -11,4 +11,4 @@ fun void test(...) { } } test(1); -test(1, 2.3, null); +test(1, 2.3, new Object); diff --git a/include/emit.h b/include/emit.h index 9a8009ab..a3204bda 100644 --- a/include/emit.h +++ b/include/emit.h @@ -45,10 +45,6 @@ ANN m_uint emit_code_offset(const Emitter emit); ANN m_uint emit_local(const Emitter emit, const Type t); ANN Instr emit_exp_spork(const Emitter, const Exp_Unary*); ANN m_bool emit_exp(const Emitter, const Exp); -ANN static inline void emit_except(const Emitter emit, const Type t) { - if(!GET_FLAG(t, nonnull)) - emit_add_instr(emit, GWOP_EXCEPT); -} ANN static inline Instr emit_gc(const Emitter emit, const m_int offset) { const Instr gc = emit_add_instr(emit, GcAdd); gc->m_val = offset; diff --git a/include/env/env.h b/include/env/env.h index 2e9e5bf5..41c76f8b 100644 --- a/include/env/env.h +++ b/include/env/env.h @@ -39,10 +39,6 @@ ANN Value mk_class(const Env env, const Type base); ANEW ANN m_str tl2str(const Env, const Type_List); // in type_decl.c ANN m_bool compat_func(const __restrict__ Func_Def, const __restrict__ Func_Def); ANN Type known_type(const Env env, Type_Decl*); -__attribute__((returns_nonnull)) -ANN Type special_type(const Env, const Type, const uint); -#define nonnul_type(a, b) special_type(a, (b), 0); -#define force_type(a, b) special_type(a, (b), 1); ANN Type prim_ref(const Env env, const Type t, const Type_Decl* td); ANN m_bool env_access(const Env env, const ae_flag flag, const loc_t pos); ANN m_bool env_storage(const Env env, ae_flag flag, const loc_t pos); diff --git a/include/env/type.h b/include/env/type.h index 21811c0b..b40df49e 100644 --- a/include/env/type.h +++ b/include/env/type.h @@ -35,8 +35,6 @@ enum tflag { tflag_dtor = 1 << 15, tflag_tmpl = 1 << 16, tflag_typedef = 1 << 17, - tflag_nonnull = 1 << 18, - tflag_force = 1 << 19, } __attribute__((packed)); struct Type_ { @@ -81,17 +79,12 @@ ANN static inline Type get_gack(Type t) { return t; // unreachable } -__attribute__((returns_nonnull)) -ANN Type unflag_type(const Type t); __attribute__((returns_nonnull)) ANN Type get_type(const Type t); -ANN static inline int is_special(const Type t) { - return tflag(t, tflag_nonnull) || tflag(t, tflag_force); -} typedef enum { et_void, et_int, et_bool, et_char, et_float, - et_null, et_compound, et_object, et_shred, et_fork, et_event, et_ugen, et_string, et_ptr, et_array, et_gack, + et_error, et_compound, et_object, et_shred, et_fork, et_event, et_ugen, et_string, et_ptr, et_array, et_gack, et_function, et_fptr, et_vararg, et_lambda, et_class, et_union, et_undefined, et_auto, MAX_TYPE } type_enum; diff --git a/include/operator.h b/include/operator.h index ff2d3a6a..f44f404f 100644 --- a/include/operator.h +++ b/include/operator.h @@ -2,15 +2,15 @@ #define __OPERATOR #define OP_ANY_TYPE (Type)1 -#define ERR_N(a, b, ...) { env_err(env, (a), (b), ## __VA_ARGS__); return env->gwion->type[et_null]; } -#define DECL_ON(decl, f, exp) decl f exp; { if(!f) return env->gwion->type[et_null]; } -#define DECL_BN(decl, f, exp) decl f exp; { if(f < 0) return env->gwion->type[et_null]; } -#define DECL_NN(decl, f, exp) decl f exp; { if(f == env->gwion->type[et_null]) return env->gwion->type[et_null]; } -#define CHECK_ON(f) { if(!f) return env->gwion->type[et_null]; } -#define CHECK_NB(f) { if(f == env->gwion->type[et_null]) return GW_ERROR; } -#define CHECK_NO(f) { if(f == env->gwion->type[et_null]) return NULL; } -#define CHECK_BN(f) { if(f < 0) return env->gwion->type[et_null]; } -#define CHECK_NN(f) { if(f == env->gwion->type[et_null]) return env->gwion->type[et_null]; } +#define ERR_N(a, b, ...) { env_err(env, (a), (b), ## __VA_ARGS__); return env->gwion->type[et_error]; } +#define DECL_ON(decl, f, exp) decl f exp; { if(!f) return env->gwion->type[et_error]; } +#define DECL_BN(decl, f, exp) decl f exp; { if(f < 0) return env->gwion->type[et_error]; } +#define DECL_NN(decl, f, exp) decl f exp; { if(f == env->gwion->type[et_error]) return env->gwion->type[et_error]; } +#define CHECK_ON(f) { if(!f) return env->gwion->type[et_error]; } +#define CHECK_NB(f) { if(f == env->gwion->type[et_error]) return GW_ERROR; } +#define CHECK_NO(f) { if(f == env->gwion->type[et_error]) return NULL; } +#define CHECK_BN(f) { if(f < 0) return env->gwion->type[et_error]; } +#define CHECK_NN(f) { if(f == env->gwion->type[et_error]) return env->gwion->type[et_error]; } typedef Type (*opck)(const Env, void*, m_bool*); typedef struct Instr_* (*opem)(const Emitter, void*); diff --git a/scripts/afl-dict/sum b/scripts/afl-dict/sum index 04291c15..1795637c 100644 --- a/scripts/afl-dict/sum +++ b/scripts/afl-dict/sum @@ -16,7 +16,6 @@ keyword_protect="protect" keyword_private="private" keyword_const="const" keyword_ref="ref" -keyword_nonnull="nonnull" keyword_if="if" keyword_else="else" keyword_break="break" diff --git a/src/emit/emit.c b/src/emit/emit.c index a7beb5ce..a59c34ca 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -224,7 +224,7 @@ ANN m_uint emit_local(const Emitter emit, const Type t) { ANN void emit_ext_ctor(const Emitter emit, const Type t); ANN static inline void maybe_ctor(const Emitter emit, const Type t) { - if(!is_special(t) && tflag(t, tflag_ctor)) + if(tflag(t, tflag_ctor)) emit_ext_ctor(emit, t); } @@ -594,7 +594,7 @@ ANN static m_bool emit_interp(const Emitter emit, const Exp exp) { regseti(emit, (m_uint)e->info->type); interp_size(emit, e->info->type); const m_bool isobj = isa(e->info->type, emit->gwion->type[et_object]) > 0; - if(isobj && !tflag(e->info->type, tflag_force)) + if(isobj && e->exp_type != ae_exp_cast) emit_add_instr(emit, GackType); const Instr instr = emit_add_instr(emit, Gack); instr->m_val = emit_code_offset(emit); @@ -777,6 +777,8 @@ ANN static m_bool emit_decl(const Emitter emit, const Exp_Decl* decl) { CHECK_BB(emit_exp_decl_non_static(emit, decl, list->self, ref, var)) else CHECK_BB(emit_exp_decl_global(emit, list->self, ref, var)) + if(!var && !GET_FLAG(decl->td, optionnal) && (GET_FLAG(decl->td, ref) || is_fptr(emit->gwion, list->self->value->type))) + ERR_B(list->self->pos, "kljlkj") } while((list = list->next)); return GW_OK; } @@ -1015,7 +1017,6 @@ ANN static void tmpl_prelude(const Emitter emit, const Func f) { ANN static Instr get_prelude(const Emitter emit, const Func f) { const Type t = actual_type(emit->gwion, f->value_ref->type); if(is_fptr(emit->gwion, t)) { - emit_except(emit, t); if(f->def->base->tmpl) tmpl_prelude(emit, f); } @@ -1319,9 +1320,7 @@ ANN static Instr _flow(const Emitter emit, const Exp e, const m_bool b) { emit_exp_addref1(emit, e, -exp_size(e)); struct Op_Import opi = { .op=insert_symbol(b ? "@conditionnal" : "@unconditionnal"), .rhs=e->info->type, .pos=e->pos, .data=(uintptr_t)e, .op_type=op_exp }; - const Instr instr = op_emit(emit, &opi); - assert(instr != (Instr)GW_OK); - return instr; + return op_emit(emit, &opi); } #define emit_flow(emit,b) _flow(emit, b, 1) @@ -1444,8 +1443,6 @@ ANN2(1) /*static */m_bool emit_exp(const Emitter emit, /* const */Exp e) { Exp exp = e; do { CHECK_BB(emit_exp_func[exp->exp_type](emit, &exp->d)) - if(exp_getnonnull(exp)) - emit_except(emit, exp->info->type); if(exp->info->cast_to) CHECK_BB(emit_implicit_cast(emit, exp, exp->info->cast_to)) } while((exp = exp->next)); @@ -1607,7 +1604,6 @@ ANN static m_bool _emit_stmt_each(const Emitter emit, const Stmt_Each stmt, m_ui emit_local(emit, emit->gwion->type[et_int]); stmt->v->from->offset = offset + SZ_INT; const m_uint ini_pc = emit_code_size(emit); - emit_except(emit, stmt->exp->info->type); const Instr loop = emit_add_instr(emit, stmt->is_ptr ? AutoLoopPtr : AutoLoop); const Instr end = emit_add_instr(emit, BranchEqInt); const m_bool ret = scoped_stmt(emit, stmt->body, 1); diff --git a/src/env/type.c b/src/env/type.c index fdf63d04..4c1bd621 100644 --- a/src/env/type.c +++ b/src/env/type.c @@ -9,7 +9,7 @@ #include "object.h" ANN static inline m_bool freeable(const Type a) { - return !(tflag(a, tflag_force) || tflag(a, tflag_nonnull)) && (tflag(a, tflag_tmpl) ||GET_FLAG(a, global)); + return tflag(a, tflag_tmpl) ||GET_FLAG(a, global); } ANN void free_type(const Type a, struct Gwion_ *const gwion) { diff --git a/src/env/type_special.c b/src/env/type_special.c deleted file mode 100644 index 8a7c5ccc..00000000 --- a/src/env/type_special.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "gwion_util.h" -#include "gwion_ast.h" -#include "gwion_env.h" -#include "vm.h" -#include "gwion.h" - -static m_str const special_name[] = { "^nonnull", "^force" }; -#define SPECIAL_LEN strlen(special_name[0]) + strlen(special_name[1]) -static const enum tflag special_flag[] = { tflag_nonnull, tflag_force }; - -typedef struct { - const Type type; - Symbol name; - enum tflag flag; - uint st_type; -} SpecialType; - - -ANN static Type specialtype_create(const Env env, const SpecialType *s) { - const Type t = type_copy(env->gwion->mp, s->type); - if(t->nspc) - nspc_addref(t->nspc); - t->name = s_name(s->name); - t->flag = s->type->flag; - t->tflag |= s->type->tflag | s->flag; - t->info->parent = unflag_type(s->type); - nspc_add_type_front(s->type->info->owner, s->name, t); - mk_class(env, t); - return t; -} - -static inline int get_flag(const Type t, const enum tflag flag) { - return (t->tflag & flag) == flag; -} - - -ANN static void specialtype_flag(SpecialType *s, m_str c, const uint i) { - const enum tflag flag = special_flag[i]; - if(i == s->st_type || get_flag(s->type, flag)) { - strcat(c, special_name[i]); - s->flag |= flag; - } -} - -ANN static void specialtype_init(SymTable *st, SpecialType *s) { - const size_t sz = strlen(s->type->name); - char c[sz + SPECIAL_LEN + 1]; - strcpy(c, s->type->name); - m_str flagged = strchr(c, '^'); - if(flagged) - *flagged = '\0'; - specialtype_flag(s, c, 0); - specialtype_flag(s, c, 1); - s->name = insert_symbol(st, c); -} - -ANN Type special_type(const Env env, const Type t, const uint st_type) { - SpecialType s = { .type=t, .st_type=st_type }; - specialtype_init(env->gwion->st, &s); - return nspc_lookup_type1(t->info->owner, s.name) ?: - specialtype_create(env, &s); -} diff --git a/src/import/import_checker.c b/src/import/import_checker.c index 416a22d7..214fb755 100644 --- a/src/import/import_checker.c +++ b/src/import/import_checker.c @@ -202,16 +202,12 @@ ANN static Type_Decl* _str2decl(const Gwion gwion, struct td_checker *tdc) { } ANN Type_Decl* str2decl(const Gwion gwion, const m_str str, const loc_t pos) { - const ae_flag flag = strncmp(str, "nonnull ", 8) ? ae_flag_none : ae_flag_nonnull; struct td_checker tdc = { .str=str, .pos=pos }; - if(flag == ae_flag_nonnull) - tdc.str += 8; DECL_OO(Type_Decl *, td, = _str2decl(gwion, &tdc)) if(*tdc.str) { free_type_decl(gwion->mp, td); GWION_ERR_O(pos, "excedental character '%c'", *tdc.str); } - td->flag |= flag; return td; } diff --git a/src/lib/array.c b/src/lib/array.c index 5580439b..775fef1e 100644 --- a/src/lib/array.c +++ b/src/lib/array.c @@ -48,7 +48,7 @@ void free_m_vector(MemPool p, M_Vector a) { } static DTOR(array_dtor) { - const Type t = unflag_type(o->type_ref); + const Type t = o->type_ref; if(*(void**)(o->data + SZ_INT)) xfree(*(void**)(o->data + SZ_INT)); struct M_Vector_* a = ARRAY(o); @@ -115,7 +115,7 @@ static MFUN(vm_vector_rem) { const M_Vector v = ARRAY(o); if(index < 0 || (m_uint)index >= ARRAY_LEN(v)) return; - const Type t = unflag_type(o->type_ref); + const Type t = o->type_ref; if(t->nspc->info->class_data_size) (*(f_release**)t->nspc->info->class_data)(shred, array_base(t), ARRAY_PTR(v) + index * ARRAY_SIZE(v)); m_vector_rem(v, (vtype)index); @@ -151,9 +151,9 @@ ANN static Type get_array_type(Type t) { static OP_CHECK(opck_array_at) { const Exp_Binary* bin = (Exp_Binary*)data; - if(opck_const_rhs(env, data, mut) == env->gwion->type[et_null]) - return env->gwion->type[et_null]; - if(bin->lhs->info->type != env->gwion->type[et_null]) { + if(opck_const_rhs(env, data, mut) == env->gwion->type[et_error]) + return env->gwion->type[et_error]; + if(bin->lhs->info->type != env->gwion->type[et_error]) { ARRAY_OPCK(bin->lhs, bin->rhs, exp_self(bin)->pos) if(bin->lhs->info->type->array_depth != bin->rhs->info->type->array_depth) ERR_N(exp_self(bin)->pos, _("array depths do not match.")) @@ -170,7 +170,7 @@ static OP_CHECK(opck_array_at) { ANN static Type check_array_shift(const Env env, const Exp a, const Exp b, const m_str str, const loc_t pos) { - if(a->info->type == env->gwion->type[et_null] && + if(a->info->type == env->gwion->type[et_error] && b->info->type->array_depth > 1) return a->info->type; ARRAY_OPCK(a, b, pos) @@ -270,13 +270,12 @@ static OP_CHECK(opck_array_cast) { r = r->info->parent; if(get_depth(cast->exp->info->type) == get_depth(exp_self(cast)->info->type) && isa(l->info->base_type, r->info->base_type) > 0) return l; - return env->gwion->type[et_null]; + return env->gwion->type[et_error]; } static OP_CHECK(opck_array_slice) { const Exp e = (Exp)data; exp_setmeta(exp_self(e), 1); - exp_setnonnull(e->d.exp_slice.base, 1); return e->d.exp_slice.base->info->type; } @@ -336,7 +335,6 @@ static OP_CHECK(opck_array) { ANN static void array_loop(const Emitter emit, const m_uint depth) { const Instr pre_pop = emit_add_instr(emit, RegPop); pre_pop->m_val = depth * SZ_INT; - emit_add_instr(emit, GWOP_EXCEPT); for(m_uint i = 0; i < depth - 1; ++i) { const Instr access = emit_add_instr(emit, ArrayAccess); access->m_val = i * SZ_INT; @@ -344,7 +342,6 @@ ANN static void array_loop(const Emitter emit, const m_uint depth) { const Instr get = emit_add_instr(emit, ArrayGet); get->m_val = i * SZ_INT; get->m_val2 = -SZ_INT; - emit_add_instr(emit, GWOP_EXCEPT); } const Instr post_pop = emit_add_instr(emit, RegPop); post_pop->m_val = SZ_INT; @@ -391,7 +388,7 @@ static OP_EMIT(opem_array_access) { info->array = next; return (Instr)(m_uint)(exp ? emit_array_access(emit, info) : GW_ERROR); } -OP_EMIT(opem_at_object); + GWION_IMPORT(array) { const Type t_array = gwi_class_ini(gwi, "@Array", NULL); gwi->gwion->type[et_array] = t_array; @@ -416,23 +413,19 @@ GWION_IMPORT(array) { GWI_BB(gwi_class_end(gwi)) GWI_BB(gwi_oper_ini(gwi, "@Array", "@Array", NULL)) GWI_BB(gwi_oper_add(gwi, opck_array_at)) - GWI_BB(gwi_oper_emi(gwi, opem_at_object)) - GWI_BB(gwi_oper_end(gwi, "@=>", ObjectAssign)) - GWI_BB(gwi_oper_ini(gwi, "@null", "@Array", NULL)) - GWI_BB(gwi_oper_add(gwi, opck_array_at)) GWI_BB(gwi_oper_end(gwi, "@=>", ObjectAssign)) - GWI_BB(gwi_oper_ini(gwi, "nonnull @Array", (m_str)OP_ANY_TYPE, NULL)) + GWI_BB(gwi_oper_ini(gwi, "@Array", (m_str)OP_ANY_TYPE, NULL)) GWI_BB(gwi_oper_add(gwi, opck_array_sl)) GWI_BB(gwi_oper_emi(gwi, opem_array_sl)) GWI_BB(gwi_oper_end(gwi, "<<", NULL)) - GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "nonnull @Array", NULL)) + GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "@Array", NULL)) GWI_BB(gwi_oper_add(gwi, opck_array_sr)) GWI_BB(gwi_oper_emi(gwi, opem_array_sr)) GWI_BB(gwi_oper_end(gwi, ">>", NULL)) GWI_BB(gwi_oper_ini(gwi, "@Array", "@Array", NULL)) GWI_BB(gwi_oper_add(gwi, opck_array_cast)) GWI_BB(gwi_oper_end(gwi, "$", NULL)) - GWI_BB(gwi_oper_ini(gwi, "int", "nonnull @Array", "int")) + GWI_BB(gwi_oper_ini(gwi, "int", "@Array", "int")) GWI_BB(gwi_oper_add(gwi, opck_array_slice)) GWI_BB(gwi_oper_emi(gwi, opem_array_slice)) GWI_BB(gwi_oper_end(gwi, "@slice", NULL)) diff --git a/src/lib/engine.c b/src/lib/engine.c index b53a4851..6e4f8245 100644 --- a/src/lib/engine.c +++ b/src/lib/engine.c @@ -99,10 +99,16 @@ static INSTR(UnionGet) { POP_REG(shred, SZ_INT - instr->m_val); memcpy(REG(-instr->m_val), o->data + SZ_INT, instr->m_val); } - +MFUN(union_is); static OP_EMIT(opem_dot_union) { Exp_Dot *dot = (Exp_Dot*)data; CHECK_BO(emit_exp(emit, dot->base)) + if(isa(exp_self(dot)->info->type, emit->gwion->type[et_function]) > 0) { + const Func f = (Func)vector_at(&dot->t_base->nspc->info->vtable, 0); + const Instr instr = emit_add_instr(emit, RegPushImm); + instr->m_val = (m_uint)f->code; + return instr; + } const uint emit_var = exp_getvar(exp_self(dot)); const Value v = nspc_lookup_value0(dot->t_base->nspc, dot->xid); const Instr instr = emit_add_instr(emit, !emit_var ? UnionGet : UnionSet); diff --git a/src/lib/event.c b/src/lib/event.c index d025f716..0d7c09d4 100644 --- a/src/lib/event.c +++ b/src/lib/event.c @@ -60,7 +60,7 @@ GWION_IMPORT(event) { GWI_BB(gwi_func_ini(gwi, "void", "broadcast")) GWI_BB(gwi_func_end(gwi, event_broadcast, ae_flag_none)) GWI_BB(gwi_class_end(gwi)) - GWI_BB(gwi_oper_ini(gwi, "nonnull Event", "@now", "int")) + GWI_BB(gwi_oper_ini(gwi, "Event", "@now", "int")) GWI_BB(gwi_oper_end(gwi, "=>", EventWait)) return GW_OK; } diff --git a/src/lib/instr.c b/src/lib/instr.c index ffe2839b..0fe1eb3b 100644 --- a/src/lib/instr.c +++ b/src/lib/instr.c @@ -82,7 +82,7 @@ INSTR(DotTmpl) { struct dottmpl_ *dt = (struct dottmpl_*)instr->m_val; const m_str name = dt->name; const M_Object o = *(M_Object*)REG(-SZ_INT); - Type t = !tflag(o->type_ref, tflag_nonnull) ? o->type_ref : o->type_ref->info->parent; + Type t = o->type_ref; do { const Emitter emit = shred->info->vm->gwion->emit; emit->env->name = "runtime"; diff --git a/src/lib/lib_func.c b/src/lib/lib_func.c index e73a1de8..9fdeaa34 100644 --- a/src/lib/lib_func.c +++ b/src/lib/lib_func.c @@ -20,7 +20,7 @@ static OP_CHECK(opck_func_call) { e->exp_type = ae_exp_call; memcpy(&e->d.exp_call, &call, sizeof(Exp_Call)); ++*mut; - return check_exp_call1(env, &e->d.exp_call) ?: env->gwion->type[et_null]; + return check_exp_call1(env, &e->d.exp_call) ?: env->gwion->type[et_error]; } static inline void fptr_instr(const Emitter emit, const Func f, const m_uint i) { @@ -176,10 +176,8 @@ ANN m_bool check_lambda(const Env env, const Type t, Exp_Lambda *l) { ANN static m_bool fptr_do(const Env env, struct FptrInfo *info) { if(isa(info->exp->info->type, env->gwion->type[et_lambda]) < 0) { - m_bool nonnull = tflag(info->exp->info->type, tflag_nonnull); CHECK_BB(fptr_check(env, info)) - DECL_OB(const Type, t, = fptr_type(env, info)) - info->exp->info->type = !nonnull ? t : nonnul_type(env, t); + CHECK_OB((info->exp->info->type = fptr_type(env, info))) return GW_OK; } Exp_Lambda *l = &info->exp->d.exp_lambda; @@ -190,7 +188,7 @@ static OP_CHECK(opck_auto_fptr) { const Exp_Binary* bin = (Exp_Binary*)data; // we'll only deal with auto fptr declaration if(bin->rhs->exp_type != ae_exp_decl && bin->rhs->d.exp_decl.td->xid != insert_symbol("auto")) - return env->gwion->type[et_null]; + return env->gwion->type[et_error]; // create a matching signature // TODO: we could check first if there a matching existing one Func_Base *const fbase = cpy_func_base(env->gwion->mp, bin->lhs->info->type->info->func->def->base); @@ -205,7 +203,7 @@ static OP_CHECK(opck_auto_fptr) { type_remref(t, env->gwion); bin->rhs->d.exp_decl.list->self->value->type = bin->rhs->info->type = bin->rhs->d.exp_decl.type = t; exp_setvar(bin->rhs, 1); - return ret > 0 ? t : env->gwion->type[et_null]; + return ret > 0 ? t : env->gwion->type[et_error]; } static OP_CHECK(opck_fptr_at) { @@ -225,13 +223,6 @@ static OP_CHECK(opck_fptr_at) { return bin->rhs->info->type; } -static OP_CHECK(opck_null_fptr_at) { - Exp_Binary* bin = (Exp_Binary*)data; - CHECK_NN(opck_const_rhs(env, bin, mut)) - exp_setvar(bin->rhs, 1); - return bin->rhs->info->type; -} - static OP_CHECK(opck_fptr_cast) { Exp_Cast* cast = (Exp_Cast*)data; const Type t = exp_self(cast)->info->type; @@ -248,16 +239,15 @@ static void member_fptr(const Emitter emit) { dup->m_val = -SZ_INT; } -static int is_member(const Type from, const Type to) { - return vflag(from->info->func->value_ref, vflag_member) && - !(tflag(from, tflag_nonnull) || tflag(to, tflag_nonnull)); +static inline int is_member(const Type from) { + return vflag(from->info->func->value_ref, vflag_member); } static OP_EMIT(opem_fptr_cast) { const Exp_Cast* cast = (Exp_Cast*)data; if(exp_self(cast)->info->type->info->func->def->base->tmpl) fptr_instr(emit, cast->exp->info->type->info->func, 1); - if(is_member(cast->exp->info->type, exp_self(cast)->info->type)) + if(is_member(cast->exp->info->type)) member_fptr(emit); return (Instr)GW_OK; } @@ -272,7 +262,7 @@ static OP_CHECK(opck_fptr_impl) { static OP_EMIT(opem_fptr_impl) { struct Implicit *impl = (struct Implicit*)data; - if(is_member(impl->e->info->type, impl->t)) + if(is_member(impl->e->info->type)) member_fptr(emit); if(impl->t->info->func->def->base->tmpl) fptr_instr(emit, ((Exp)impl->e)->info->type->info->func, 1); @@ -297,7 +287,7 @@ ANN static Type fork_type(const Env env, const Exp_Unary* unary) { if(t == env->gwion->type[et_void]) return env->gwion->type[et_fork]; char c[21 + strlen(t->name)]; - sprintf(c, "nonnull TypedFork:[%s]", t->name); + sprintf(c, "TypedFork:[%s]", t->name); const Type fork = env->gwion->type[et_fork]; UNSET_FLAG(fork, final); const Type typed = str2type(env->gwion, "TypedFork", exp_self(unary)->pos); @@ -359,16 +349,6 @@ GWION_IMPORT(func) { GWI_BB(gwi_oper_add(gwi, opck_fptr_impl)) GWI_BB(gwi_oper_emi(gwi, opem_fptr_impl)) GWI_BB(gwi_oper_end(gwi, "@implicit", NULL)) - GWI_BB(gwi_oper_ini(gwi, "@null", "@func_ptr", NULL)) - GWI_BB(gwi_oper_add(gwi, opck_null_fptr_at)) - GWI_BB(gwi_oper_emi(gwi, opem_func_assign)) - GWI_BB(gwi_oper_end(gwi, "@=>", NULL)) - GWI_BB(gwi_oper_add(gwi, opck_fptr_cast)) - GWI_BB(gwi_oper_emi(gwi, opem_fptr_cast)) - GWI_BB(gwi_oper_end(gwi, "$", NULL)) - GWI_BB(gwi_oper_add(gwi, opck_fptr_impl)) - GWI_BB(gwi_oper_emi(gwi, opem_fptr_impl)) - GWI_BB(gwi_oper_end(gwi, "@implicit", NULL)) GWI_BB(gwi_oper_ini(gwi, NULL, (m_str)OP_ANY_TYPE, NULL)) GWI_BB(gwi_oper_add(gwi, opck_spork)) GWI_BB(gwi_oper_emi(gwi, opem_spork)) diff --git a/src/lib/lib_func.cnano b/src/lib/lib_func.cnano deleted file mode 100644 index d524d5cd..00000000 --- a/src/lib/lib_func.cnano +++ /dev/null @@ -1,196 +0,0 @@ -#require Std -#require Math -#require Modules - -enum Pitch { C, D, E, F, G, A, B } - -class MusicObject { - fun UGen update() {} - fun UGen onStart() {} - fun UGen onEnd() {} -} - -var SinOsc osc; - -class MyTone extends MusicObject { - var float freq; - - fun UGen onStart() { - freq => osc.freq; - return osc => dac; - } - - fun UGen onEnd() { - return osc =< dac; - } -} - -fun MyTone tone(float freq) { - var MyTone t; - 660 => t.freq; - return t; -} - -class Note extends MusicObject { - var Pitch pitch; - var int accidental; - var int octave; - - - fun int toMidi() { - var int p; - - match (pitch) { - case C: 0 => p; - case D: 2 => p; - case E: 4 => p; - case F: 5 => p; - case G: 7 => p; - case A: 9 => p; - case B: 11 => p; - } - - return p + (12 * (octave+1)) + accidental; - } - - fun UGen onStart() { - toMidi() => Std.mtof => osc.freq; - return osc => dac; - } - - fun UGen onEnd() { - osc =< dac; - } -} - -fun Note note(Pitch pitch, int accidental, int octave) { - var Note n; - A => n.pitch; - 0 => n.accidental; - 4 => n.octave; - return n; -} - -class Coord { - var dur start; - var dur end; -} - -fun Coord coord(dur start, dur end) { - const Coord c; - start => c.start; - end => c.end; - return c; -} - -class TLEvent { - fun dur getStart() {} - fun void doIt() {} -} - -class StartTLEvent extends TLEvent { - var dur start; - var MusicObject obj; - fun dur getStart() { return start; } - fun void doIt() { - obj.onStart(); - } -} - -fun StartTLEvent startevent(dur start, MusicObject obj) { - const StartTLEvent evt; - start => evt.start; - obj @=> evt.obj; - return evt; -} - -class EndTLEvent extends TLEvent { - var dur start; - var MusicObject obj; - fun dur getStart() { return start; } - fun void doIt() { - obj.onEnd(); - } -} - -fun EndTLEvent endevent(dur start, MusicObject obj) { - const EndTLEvent evt; - start => evt.start; - obj @=> evt.obj; - return evt; -} - -class DTimeline { - var TLEvent events[0]; - - fun void add(TLEvent event) { - for (0 => var int i; i < events.size(); ++i) { - if (event.getStart() < events[i].getStart()) { - for (events.size()-1 => var int j; j >= i; --j) { - events[j-1] @=> const TLEvent temp; - events[j] @=> events[j-1]; - temp @=> events[j]; - } - return; - } - } - events << event; - } - - fun void perform() { - 0::second => var dur current; - foreach(evt:events) { - evt.getStart() - current => now; - evt.getStart() => current; - evt.doIt(); - } - } -} - -class Frame { - var int test; - var Coord coord; - var MusicObject objs[0]; -} - -class Timeline { - const Frame frames[0]; - - fun void add(Coord c, MusicObject obj) { - var Frame toAdd; - for (0 => var int i; i < frames.size(); ++i) { - if ((c.start >= frames[i].coord.start) && (c.start <= frames[i].coord.start) - && (c.end >= frames[i].coord.end) && (c.end <= frames[i].coord.end)) { - frames[i].objs << obj; - return; - } - } - var Coord c2; - c.start => c2.start; - c.end => c2.end; - toAdd.objs << obj; - c2 @=> toAdd.coord; - frames << toAdd; - } - - fun DTimeline toDTimeline() { - var DTimeline theTL; - foreach(frame:frames) { - foreach(obj:frame.objs) { - theTL.add(startevent(frame.coord.start, obj)); - theTL.add(endevent(frame.coord.end, obj)); - } - } - return theTL; - } - - fun void perform() { - this.toDTimeline().perform(); - } -} - -var Timeline t; -t.add(coord(0::second, 2::second), note(A,0,4)); -t.add(coord(2::second,4::second), note(C,1,5)); -<<< t.frames[0].objs.size() >>>; -t.perform(); diff --git a/src/lib/object.c b/src/lib/object.c index 64cd45f3..1a9fec85 100644 --- a/src/lib/object.c +++ b/src/lib/object.c @@ -66,7 +66,7 @@ ANN void __release(const M_Object o, const VM_Shred shred) { MemPool p = shred->info->mp; Type t = o->type_ref; do { - if(!t->nspc || is_special(t) || tflag(t, tflag_udef)) + if(!t->nspc || isa(t, shred->info->vm->gwion->type[et_union]) > 0) continue; struct scope_iter iter = { t->nspc->info->value, 0, 0 };\ Value v; @@ -111,7 +111,7 @@ static ID_CHECK(opck_this) { if(env->func && !vflag(env->func->value_ref, vflag_member)) ERR_O(exp_self(prim)->pos, _("keyword 'this' cannot be used inside static functions...")) if(env->func && !strcmp(s_name(env->func->def->base->xid), "@gack")) - return force_type(env, get_gack(env->class_def->info->parent)); // get_gack ? + return get_gack(env->class_def->info->parent); // get_gack ? return env->class_def; } diff --git a/src/lib/object_op.c b/src/lib/object_op.c index cb57147c..0c8a21c7 100644 --- a/src/lib/object_op.c +++ b/src/lib/object_op.c @@ -31,98 +31,43 @@ static INSTR(name##Object) { \ describe_logical(Eq, ==) describe_logical(Neq, !=) -static inline m_bool nonnull_check(const Type l, const Type r) { - return !tflag(l, tflag_nonnull) && tflag(r, tflag_nonnull); -} - -ANN static inline Type check_nonnull(const Env env, const Type l, const Type r, - const m_str action, const loc_t pos) { - if(tflag(r, tflag_nonnull)) { - if(isa(l, env->gwion->type[et_null]) > 0) - ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name); - if(isa(l, unflag_type(r)) < 0) - ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name); - return r->info->parent; - } - if(l != env->gwion->type[et_null] && isa(l, r) < 0) - ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name); - return r; -} static OP_CHECK(at_object) { const Exp_Binary* bin = (Exp_Binary*)data; - const Type l = bin->lhs->info->type; - const Type r = bin->rhs->info->type; - if(opck_rassign(env, data, mut) == env->gwion->type[et_null]) - return env->gwion->type[et_null]; - if(check_nonnull(env, l, r, "assign", exp_self(bin)->pos) == env->gwion->type[et_null]) - return env->gwion->type[et_null]; + if(opck_rassign(env, data, mut) == env->gwion->type[et_error]) + return env->gwion->type[et_error]; if(bin->rhs->exp_type == ae_exp_decl) SET_FLAG(bin->rhs->d.exp_decl.td, ref); exp_setvar(bin->rhs, 1); - return r; -} - -/*static*/ OP_EMIT(opem_at_object) { - const Exp_Binary* bin = (Exp_Binary*)data; - const Type l = bin->lhs->info->type; - const Type r = bin->rhs->info->type; - if(nonnull_check(l, r)) { - const Instr instr = emit_add_instr(emit, GWOP_EXCEPT); - instr->m_val = SZ_INT; - } - return emit_add_instr(emit, ObjectAssign); + CHECK_BO(isa(bin->lhs->info->type , bin->rhs->info->type)) + return bin->rhs->info->type; } static OP_CHECK(opck_object_cast) { const Exp_Cast* cast = (Exp_Cast*)data; - const Type l = cast->exp->info->type; - const Type r = exp_self(cast)->info->type; - if(check_nonnull(env, l, r, "cast", exp_self(cast)->pos) == env->gwion->type[et_null]) - return env->gwion->type[et_null]; - return force_type(env, r); -} - -static OP_EMIT(opem_object_cast) { - const Exp_Cast* cast = (Exp_Cast*)data; - const Type l = cast->exp->info->type; - const Type r = exp_self(cast)->info->type; - if(nonnull_check(l, r)) - emit_add_instr(emit, GWOP_EXCEPT); - return (Instr)GW_OK; + const Type to = known_type(env, cast->td); + if(isa(cast->exp->info->type, to) < 0) { + if(isa(to, cast->exp->info->type) > 0) + ERR_N(exp_self(cast)->pos, _("can't upcast '%s' to '%s'"), cast->exp->info->type->name, to->name) + ERR_N(exp_self(cast)->pos, _("can't cast '%s' to '%s'"), cast->exp->info->type->name, to->name) + } + return exp_self(cast)->info->type; } static OP_CHECK(opck_implicit_null2obj) { const struct Implicit* imp = (struct Implicit*)data; - const Type l = imp->e->info->type; - const Type r = imp->t; - if(check_nonnull(env, l, r, "implicitly cast", imp->e->pos) == env->gwion->type[et_null]) - return env->gwion->type[et_null]; return imp->t; } static OP_EMIT(opem_implicit_null2obj) { - const struct Implicit* imp = (struct Implicit*)data; - const Type l = imp->e->info->type; - const Type r = imp->t; - if(nonnull_check(l, r)) - emit_add_instr(emit, GWOP_EXCEPT); return (Instr)GW_OK; } -static OP_CHECK(opck_object_not) { - const Exp_Unary* unary = (Exp_Unary*)data; - const Type t = unary->exp->info->type; - if(tflag(t, tflag_nonnull)) - ERR_N(unary->exp->pos, "expression is known to be nonnull"); - return unary->exp->info->type; -} - ANN /*static*/ Type scan_class(const Env env, const Type t, const Type_Decl * td); static Type opck_object_scan(const Env env, const struct TemplateScan *ts) { if(ts->td->types) - return scan_class(env, ts->t, ts->td) ?: env->gwion->type[et_null]; + return scan_class(env, ts->t, ts->td) ?: env->gwion->type[et_error]; ERR_N(td_pos(ts->td), _("you must provide template types for type '%s'"), ts->t->name) } @@ -159,7 +104,7 @@ ANN static void emit_member_func(const Emitter emit, const Exp_Dot* member) { if(f->def->base->tmpl) emit_add_instr(emit, DotTmplVal); else - if(is_class(emit->gwion, member->t_base) || tflag(member->base->info->type, tflag_force)) { + if(is_class(emit->gwion, member->t_base) || member->base->exp_type == ae_exp_cast) { const Instr func_i = emit_add_instr(emit, f->code ? RegPushImm : SetFunc); func_i->m_val = (m_uint)f->code ?: (m_uint)f; return; @@ -217,7 +162,7 @@ OP_CHECK(opck_object_dot) { _("class '%s' has no member '%s'"), the_base->name, str); if(member->t_base->nspc) did_you_mean_type(the_base, str); - return env->gwion->type[et_null]; + return env->gwion->type[et_error]; } CHECK_BN(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) { @@ -245,8 +190,6 @@ OP_EMIT(opem_object_dot) { !is_fptr(emit->gwion, exp_self(member)->info->type)))) { if(!tflag(t_base, tflag_struct)) CHECK_BO(emit_exp(emit, member->base)) - if(isa(member->t_base, emit->env->gwion->type[et_object]) > 0) - emit_except(emit, member->t_base); } if(isa(exp_self(member)->info->type, emit->gwion->type[et_function]) > 0 && !is_fptr(emit->gwion, exp_self(member)->info->type)) emit_member_func(emit, member); @@ -351,33 +294,22 @@ ANN static OP_EMIT(opem_option_setn) { ANN static OP_EMIT(opem_option_not) { Exp_Unary *unary = (Exp_Unary*)data; const Instr pop = emit_add_instr(emit, RegPop); - pop->m_val = unary->exp->info->type->nspc->info->offset - sizeof(uint16_t)*2; - const Instr set = emit_add_instr(emit, Reg2Reg); - set->m_val = -sizeof(uint16_t)*2; - set->m_val2 = unary->exp->info->type->nspc->info->offset - sizeof(uint16_t)*2; + pop->m_val = unary->exp->info->type->size - SZ_INT; return emit_add_instr(emit, IntNot); } ANN static OP_EMIT(opem_option_cond) { Exp exp = (Exp)data; - const Instr set = emit_add_instr(emit, Reg2Reg); - set->m_val = -exp->info->type->size; - set->m_val2 = -sizeof(uint16_t)*2; - const Instr pop2 = emit_add_instr(emit, RegPop); - pop2->m_val = exp->info->type->nspc->info->offset - sizeof(uint16_t)*2; - const Instr instr = emit_add_instr(emit, BranchEqInt); - return instr; + const Instr pop = emit_add_instr(emit, RegPop); + pop->m_val = exp->info->type->size - SZ_INT; + return emit_add_instr(emit, BranchEqInt); } ANN static OP_EMIT(opem_option_uncond) { Exp exp = (Exp)data; - const Instr set = emit_add_instr(emit, Reg2Reg); - set->m_val = -exp->info->type->size; - set->m_val2 = -sizeof(uint16_t)*2; - const Instr pop2 = emit_add_instr(emit, RegPop); - pop2->m_val = exp->info->type->size - sizeof(uint16_t)*2; - const Instr instr = emit_add_instr(emit, BranchNeqInt); - return instr; + const Instr pop = emit_add_instr(emit, RegPop); + pop->m_val = exp->info->type->size - SZ_INT; + return emit_add_instr(emit, BranchNeqInt); } @@ -403,7 +335,7 @@ ANN static m_bool scantmpl_union_def(const Env env, struct tmpl_info *info) { .op=insert_symbol(env->gwion->st, "@=>"), .pos=info->td->pos }; CHECK_BB(add_op(env->gwion, &opi1)) const struct Op_Func opfunc2 = { .ck=opck_option_setn, .em=opem_option_setn }; - struct Op_Import opi2 = { .lhs=env->gwion->type[et_null], .rhs=udef->type, .ret=udef->type, .func=&opfunc2, + struct Op_Import opi2 = { .lhs=env->gwion->type[et_error], .rhs=udef->type, .ret=udef->type, .func=&opfunc2, .op=insert_symbol(env->gwion->st, "@=>"), .pos=info->td->pos }; CHECK_BB(add_op(env->gwion, &opi2)) const struct Op_Func opfunc3 = { .em=opem_option_not }; @@ -442,11 +374,24 @@ ANN Type scan_class(const Env env, const Type t, const Type_Decl *td) { struct tmpl_info info = { .base=t, .td=td, .list=t->info->cdef->base.tmpl->list }; const Type exists = tmpl_exists(env, &info); if(exists) - return exists != env->gwion->type[et_null] ? exists : NULL; + return exists != env->gwion->type[et_error] ? exists : NULL; struct EnvSet es = { .env=env, .data=env, .func=(_exp_func)scan0_cdef, .scope=env->scope->depth, .flag=tflag_scan0 }; +// CHECK_BO(envset_push(&es, t->info->owner_class, t->info->ctx ? t->info->ctx->nspc : env->curr)) +//const Nspc former = env->curr; +//if(env->class_def) +//const Type cdef = env->class_def; CHECK_BO(envset_push(&es, t->info->owner_class, t->info->ctx ? t->info->ctx->nspc : env->curr)) +// CHECK_BO(envset_push(&es, t->info->owner_class, t->info->owner)) +/*{ +nspc_push_type(env->gwion->mp, env->curr); + Type_List tl = td->types; + do { + nspc_add_type(env->curr, tl->td->xid, nspc_lookup_type0(former, tl->td->xid)); + } while((tl = tl->next)); +}*/ const Type ret = _scan_class(env, &info); +//nspc_pop_type(env->gwion->mp, env->curr); if(es.run) envset_pop(&es, t->info->owner_class); return ret; @@ -485,42 +430,23 @@ ANN void struct_release(const VM_Shred shred, const Type base, const m_bit *ptr) } GWION_IMPORT(object_op) { - const Type t_null = gwi_mk_type(gwi, "@null", SZ_INT, NULL); - gwi->gwion->type[et_null] = t_null; - GWI_BB(gwi_set_global_type(gwi, t_null, et_null)) + const Type t_error = gwi_mk_type(gwi, "@error", 0, NULL); + gwi->gwion->type[et_error] = t_error; + GWI_BB(gwi_set_global_type(gwi, t_error, et_error)) GWI_BB(gwi_oper_cond(gwi, "Object", BranchEqInt, BranchNeqInt)) GWI_BB(gwi_oper_ini(gwi, "Object", "Object", NULL)) GWI_BB(gwi_oper_add(gwi, at_object)) - GWI_BB(gwi_oper_emi(gwi, opem_at_object)) - GWI_BB(gwi_oper_end(gwi, "@=>", NULL)) - GWI_BB(gwi_oper_ini(gwi, "@null", "Object", NULL)) - GWI_BB(gwi_oper_add(gwi, at_object)) - GWI_BB(gwi_oper_emi(gwi, opem_at_object)) - GWI_BB(gwi_oper_end(gwi, "@=>", NULL)) + GWI_BB(gwi_oper_end(gwi, "@=>", ObjectAssign)) GWI_BB(gwi_oper_ini(gwi, "Object", "Object", "int")) GWI_BB(gwi_oper_end(gwi, "==", EqObject)) GWI_BB(gwi_oper_end(gwi, "!=", NeqObject)) 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_add(gwi, opck_implicit_null2obj)) GWI_BB(gwi_oper_emi(gwi, opem_implicit_null2obj)) GWI_BB(gwi_oper_end(gwi, "@implicit", NULL)) - GWI_BB(gwi_oper_ini(gwi, "@null", "Object", NULL)) - GWI_BB(gwi_oper_add(gwi, opck_implicit_null2obj)) - GWI_BB(gwi_oper_end(gwi, "@implicit", NULL)) - GWI_BB(gwi_oper_ini(gwi, "@null", "Object", NULL)) - 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_ini(gwi, NULL, "Object", "bool")) - GWI_BB(gwi_oper_add(gwi, opck_unary_meta2)) // this is suspicious - GWI_BB(gwi_oper_add(gwi, opck_object_not)) - GWI_BB(gwi_oper_end(gwi, "!", IntNot)) GWI_BB(gwi_oper_ini(gwi, "@Compound", NULL, NULL)) GWI_BB(gwi_oper_add(gwi, opck_struct_scan)) GWI_BB(gwi_oper_end(gwi, "@scan", NULL)) - gwi_item_ini(gwi, "@null", "null"); - gwi_item_end(gwi, 0, NULL); return GW_OK; } diff --git a/src/lib/opfunc.c b/src/lib/opfunc.c index 439bbc05..baa7462a 100644 --- a/src/lib/opfunc.c +++ b/src/lib/opfunc.c @@ -13,7 +13,7 @@ OP_CHECK(opck_basic_cast) { const Exp_Cast* cast = (Exp_Cast*)data; return isa(cast->exp->info->type, exp_self(cast)->info->type) > 0 ? - exp_self(cast)->info->type : env->gwion->type[et_null]; + exp_self(cast)->info->type : env->gwion->type[et_error]; } OP_CHECK(opck_usr_implicit) { @@ -34,8 +34,8 @@ OP_CHECK(opck_const_rhs) { OP_CHECK(opck_rassign) { const Exp_Binary* bin = (Exp_Binary*)data; - if(opck_const_rhs(env, data, mut) == env->gwion->type[et_null]) - return env->gwion->type[et_null]; + if(opck_const_rhs(env, data, mut) == env->gwion->type[et_error]) + return env->gwion->type[et_error]; exp_setvar(bin->rhs, 1); return bin->rhs->info->type; } diff --git a/src/lib/prim.c b/src/lib/prim.c index 2dbbcba9..af905000 100644 --- a/src/lib/prim.c +++ b/src/lib/prim.c @@ -137,7 +137,7 @@ static OP_CHECK(opck_cast_f2i) { } static OP_CHECK(opck_implicit_f2i) { - return env->gwion->type[et_null]; + return env->gwion->type[et_error]; } static OP_CHECK(opck_cast_i2f) { diff --git a/src/lib/ptr.c b/src/lib/ptr.c index 4e5d2f3d..eefea3b7 100644 --- a/src/lib/ptr.c +++ b/src/lib/ptr.c @@ -30,16 +30,14 @@ static OP_CHECK(opck_ptr_assign) { exp_setvar(bin->rhs, 1); Type t = bin->lhs->info->type; do { -// t = unflag_type(t); Type u = bin->rhs->info->type; do { -// u = unflag_type(u); const m_str str = get_type_name(env, u, 1); if(str && !strcmp(t->name, str)) return bin->lhs->info->type; // use rhs? } while((u = u->info->parent)); } while((t = t->info->parent)); - return env->gwion->type[et_null]; + return env->gwion->type[et_error]; } static INSTR(instr_ptr_assign) { diff --git a/src/lib/string.c b/src/lib/string.c index db68d0ed..56cc864d 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -15,12 +15,6 @@ #include "gwi.h" #include "gack.h" -ANN static void push_string(const VM_Shred shred, const M_Object obj, const m_str c) { - STRING(obj) = s_name(insert_symbol(shred->info->vm->gwion->st, c)); - *(M_Object*)REG(-SZ_INT) = (M_Object)obj; - _release(obj, shred); -} - #define describe_string_logical(name, action) \ static INSTR(String_##name) { \ POP_REG(shred, SZ_INT); \ @@ -33,14 +27,6 @@ static INSTR(String_##name) { \ describe_string_logical(eq, (lhs && rhs && STRING(lhs) == STRING(rhs)) || (!lhs && !rhs)) describe_string_logical(neq, !(lhs && rhs && STRING(lhs) == STRING(rhs)) || (!lhs && !rhs)) -static INSTR(String_Assign) { - POP_REG(shred, SZ_INT); - const M_Object lhs = *(M_Object*)REG(-SZ_INT); - const M_Object rhs = *(M_Object*)REG(0); - release(lhs, shred); - push_string(shred, rhs, lhs ? STRING(lhs) : ""); -} - static CTOR(string_ctor) { STRING(o) = ""; } @@ -437,11 +423,11 @@ GWION_IMPORT(string) { GWI_BB(gwi_func_end(gwi, string_findStart, ae_flag_none)) gwi_func_ini(gwi, "int", "find"); - gwi_func_arg(gwi, "nonnull string", "str"); + gwi_func_arg(gwi, "string", "str"); GWI_BB(gwi_func_end(gwi, string_findStr, ae_flag_none)) gwi_func_ini(gwi, "int", "find"); - gwi_func_arg(gwi, "nonnull string", "str"); + gwi_func_arg(gwi, "string", "str"); gwi_func_arg(gwi, "int", "pos"); GWI_BB(gwi_func_end(gwi, string_findStrStart, ae_flag_none)) @@ -455,11 +441,11 @@ GWION_IMPORT(string) { GWI_BB(gwi_func_end(gwi, string_rfindStart, ae_flag_none)) gwi_func_ini(gwi, "int", "rfind"); - gwi_func_arg(gwi, "nonnull string", "str"); + gwi_func_arg(gwi, "string", "str"); GWI_BB(gwi_func_end(gwi, string_rfindStr, ae_flag_none)) gwi_func_ini(gwi, "int", "rfind"); - gwi_func_arg(gwi, "nonnull string", "str"); + gwi_func_arg(gwi, "string", "str"); gwi_func_arg(gwi, "int", "pos"); GWI_BB(gwi_func_end(gwi, string_rfindStrStart, ae_flag_none)) @@ -470,15 +456,11 @@ GWION_IMPORT(string) { GWI_BB(gwi_class_end(gwi)) - GWI_BB(gwi_oper_ini(gwi, "string", "nonnull string", "nonnull string")) - GWI_BB(gwi_oper_add(gwi, opck_const_rhs)) - GWI_BB(gwi_oper_end(gwi, "=>", String_Assign)) - GWI_BB(gwi_oper_ini(gwi, "string", "string", "bool")) GWI_BB(gwi_oper_end(gwi, "==", String_eq)) GWI_BB(gwi_oper_end(gwi, "!=", String_neq)) - GWI_BB(gwi_oper_ini(gwi, "int", "nonnull string", "nonnull string")) + GWI_BB(gwi_oper_ini(gwi, "int", "string", "string")) GWI_BB(gwi_oper_end(gwi, "@slice", StringSlice)) struct SpecialId_ spid = { .ck=check_funcpp, .exec=RegPushMe, .is_const=1 }; diff --git a/src/lib/ugen.c b/src/lib/ugen.c index b34d1b39..70939a1e 100644 --- a/src/lib/ugen.c +++ b/src/lib/ugen.c @@ -399,25 +399,25 @@ GWION_IMPORT(ugen) { GWI_BB(gwi_func_end(gwi, ugen_get_last, ae_flag_none)) GWI_BB(gwi_class_end(gwi)) - GWI_BB(gwi_oper_ini(gwi, "nonnull UGen", "nonnull UGen", "nonnull UGen")) + GWI_BB(gwi_oper_ini(gwi, "UGen", "UGen", "UGen")) _CHECK_OP("=>", chuck_ugen, UgenConnect) _CHECK_OP("=<", chuck_ugen, UgenDisconnect) _CHECK_OP(":=>", chuck_ugen, TrigConnect) _CHECK_OP(":=<", chuck_ugen, TrigDisconnect) - GWI_BB(gwi_oper_ini(gwi, "nonnull UGen[]", "nonnull UGen[]", "nonnull UGen[]")) + GWI_BB(gwi_oper_ini(gwi, "UGen[]", "UGen[]", "UGen[]")) _CHECK_OP("=>", chuck_ugen, UgenAAConnect) _CHECK_OP("=<", chuck_ugen, UgenAADisconnect) _CHECK_OP(":=>", chuck_ugen, TrigAAConnect) _CHECK_OP(":=<", chuck_ugen, TrigAADisconnect) - GWI_BB(gwi_oper_ini(gwi, "nonnull UGen", "nonnull UGen[]", "nonnull UGen[]")) + GWI_BB(gwi_oper_ini(gwi, "UGen", "UGen[]", "UGen[]")) _CHECK_OP("=>", chuck_ugen, UgenUAConnect) _CHECK_OP("=<", chuck_ugen, UgenUADisconnect) _CHECK_OP(":=>", chuck_ugen, TrigUAConnect) _CHECK_OP(":=<", chuck_ugen, TrigUADisconnect) - GWI_BB(gwi_oper_ini(gwi, "nonnull UGen[]", "nonnull UGen", "nonnull UGen")) + GWI_BB(gwi_oper_ini(gwi, "UGen[]", "UGen", "UGen")) _CHECK_OP("=>", chuck_ugen, UgenAUConnect) _CHECK_OP("=<", chuck_ugen, UgenAUDisconnect) _CHECK_OP(":=>", chuck_ugen, TrigAUConnect) diff --git a/src/lib/vararg.c b/src/lib/vararg.c index 653c6e09..b3ab0504 100644 --- a/src/lib/vararg.c +++ b/src/lib/vararg.c @@ -118,7 +118,7 @@ static INSTR(VarargCast) { const Type t = (Type)instr->m_val, u = (Type)vector_at(&arg->t, arg->i); if(isa(u, t) > 0 || - (u == shred->info->vm->gwion->type[et_null] && + (u == shred->info->vm->gwion->type[et_error] && isa(t, shred->info->vm->gwion->type[et_object]) > 0)) { for(m_uint i = 0; i < t->size; i += SZ_INT) *(m_uint*)REG(i - SZ_INT) = *(m_uint*)(arg->d + arg->o + i); @@ -142,7 +142,7 @@ static FREEARG(freearg_vararg) { static ID_CHECK(idck_vararg) { if(env->func && fbflag(env->func->def->base, fbflag_variadic)) - return nonnul_type(env, exp_self(prim)->info->type); + return exp_self(prim)->info->type; ERR_O(exp_self(prim)->pos, _("'vararg' must be used inside variadic function")) } @@ -178,7 +178,7 @@ GWION_IMPORT(vararg) { GWI_BB(gwi_class_end(gwi)) SET_FLAG(t_vararg, abstract | ae_flag_final); gwi->gwion->type[et_vararg] = t_vararg; - GWI_BB(gwi_oper_ini(gwi, "nonnull Vararg", (m_str)OP_ANY_TYPE, 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, "$", NULL)) diff --git a/src/parse/check.c b/src/parse/check.c index 1c0e857f..9fa666a4 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -350,8 +350,7 @@ ANN static Type check_prim_typeof(const Env env, const Exp *exp) { const Exp e = *exp; DECL_OO(const Type, t, = check_exp(env, e)) CHECK_BO(inferable(env, t, (*exp)->pos)) - const Type force = force_type(env, t); - return type_class(env->gwion, force); + return type_class(env->gwion, t); } ANN static Type check_prim_interp(const Env env, const Exp* exp) { @@ -687,16 +686,15 @@ ANN static Type check_lambda_call(const Env env, const Exp_Call *exp) { ANN m_bool func_check(const Env env, const Exp_Call *exp) { CHECK_OB(check_exp(env, exp->func)) - const Type t = actual_type(env->gwion, unflag_type(exp->func->info->type)); + const Type t = actual_type(env->gwion, exp->func->info->type); struct Op_Import opi = { .op=insert_symbol("@func_check"), .rhs=t, .pos=exp_self(exp)->pos, .data=(uintptr_t)exp, .op_type=op_exp }; CHECK_NB(op_check(env, &opi)) // doesn't really return NULL - return exp_self(exp)->info->type != env->gwion->type[et_null] ? + return exp_self(exp)->info->type != env->gwion->type[et_error] ? GW_OK : GW_ERROR; } ANN Type check_exp_call1(const Env env, const Exp_Call *exp) { -// CHECK_OO(check_exp(env, exp->func)) CHECK_BO(func_check(env, exp)) const Type t = actual_type(env->gwion, exp->func->info->type); if(isa(t, env->gwion->type[et_function]) < 0) { @@ -777,7 +775,7 @@ ANN static m_bool predefined_call(const Env env, const Type t, const loc_t pos) ANN static Type check_exp_call(const Env env, Exp_Call* exp) { if(exp->tmpl) { CHECK_BO(func_check(env, exp)) - const Type t = actual_type(env->gwion, unflag_type(exp->func->info->type)); + const Type t = actual_type(env->gwion, exp->func->info->type); if(isa(t, env->gwion->type[et_function]) < 0) return check_exp_call1(env, exp); if(exp->args) @@ -921,7 +919,7 @@ ANN static m_bool do_stmt_each(const Env env, const Stmt_Each stmt) { if(depth) ptr = array_type(env, ptr, depth); char c[15 + strlen(ptr->name)]; - sprintf(c, "nonnull Ptr:[%s]", ptr->name); + sprintf(c, "Ptr:[%s]", ptr->name); ptr = str2type(env->gwion, c, stmt->exp->pos); const Type base = get_type(ptr); CHECK_BB(ensure_traverse(env, base)) @@ -1026,11 +1024,47 @@ ANN m_bool check_union_decl(const Env env, const Union_Def udef) { return GW_OK; } +static OP_CHECK(opck_union_is) { + Exp_Call *call = (Exp_Call*)data; + Exp exp = call->args; + if(exp->exp_type != ae_exp_primary && exp->d.prim.prim_type != ae_prim_id) + ERR_N(exp->pos, "FFI variadic arguments must be of FFI type CHANGE ME"); + const Value v = find_value(call->func->info->type->info->owner_class, exp->d.prim.d.var); + if(!v) + ERR_N(exp->pos, "'%s' has no member '%s'", call->func->info->type->info->owner_class, exp->d.prim.d.var); + exp->d.prim.prim_type = ae_prim_num; + exp->d.prim.d.num = v->from->offset; + return NULL; +} + +/*static*/ MFUN(union_is) { + *(m_uint*)RETURN = *(m_uint*)MEM(SZ_INT) == *(m_uint*)o->data; +} + ANN m_bool check_union_def(const Env env, const Union_Def udef) { if(tmpl_base(udef->tmpl)) // there's a func for this return GW_OK; const m_uint scope = env_push_type(env, udef->type); const m_bool ret = check_union_decl(env, udef); + + Type_Decl *td = new_type_decl(env->gwion->mp, insert_symbol("bool"), loc_cpy(env->gwion->mp, udef->pos)); +// Type_Decl *arg_td = new_type_decl(env->gwion->mp, insert_symbol(), loc_cpy(env->gwion->mp, udef->pos)); + Type_Decl *arg_td = new_type_decl(env->gwion->mp, insert_symbol("int"), loc_cpy(env->gwion->mp, udef->pos));; + Var_Decl var = new_var_decl(env->gwion->mp, insert_symbol("arg"), NULL, loc_cpy(env->gwion->mp, udef->pos)); + Arg_List args = new_arg_list(env->gwion->mp, arg_td, var, NULL); + Func_Base *fb = new_func_base(env->gwion->mp, td, insert_symbol("is"), args, ae_flag_none); + Func_Def fdef = new_func_def(env->gwion->mp, fb, NULL, loc_cpy(env->gwion->mp, udef->pos)); + CHECK_BB(traverse_func_def(env, fdef)) // use ret + builtin_func(env->gwion->mp, fb->func, union_is); + + const m_uint oscope = env_push(env, udef->type->info->owner_class, udef->type->info->owner); + const struct Op_Func opfunc = { .ck=opck_union_is }; + const struct Op_Import opi = { .rhs=fb->func->value_ref->type, + .func=&opfunc, .data=(uintptr_t)fb->func, .pos=udef->pos, .op=insert_symbol("@func_check") }; + CHECK_BB(add_op(env->gwion, &opi)) + env_pop(env, oscope); +// set_vflag(fb->func->value_ref, vflag_builtin); + env_pop(env, scope); set_tflag(udef->type, tflag_check); return ret; diff --git a/src/parse/operator.c b/src/parse/operator.c index 640261f3..d5181711 100644 --- a/src/parse/operator.c +++ b/src/parse/operator.c @@ -49,8 +49,6 @@ ANN static Type op_parent(const Env env, const Type t) { static m_bool op_match(const restrict Type t, const restrict Type mo) { if(t == OP_ANY_TYPE || mo == OP_ANY_TYPE) return GW_OK; - if(t && mo) - return unflag_type(t) == unflag_type(mo); return t == mo; } @@ -168,72 +166,12 @@ ANN static void set_nspc(struct Op_Import *opi, const Nspc nspc) { exp_self((union exp_data*)opi->data)->info->nspc = nspc; } -ANN static inline void set_nonnull(const Type t, const Exp exp) { - if(t != OP_ANY_TYPE && tflag(t, tflag_nonnull)) - exp_setnonnull(exp, 1); -} - -ANN static void nn_implicit(const M_Operator *mo, const struct Op_Import *opi) { - const struct Implicit *a = (struct Implicit*)opi->data; - set_nonnull(mo->lhs, a->e); -} - -ANN static void nn_exp(const M_Operator *mo, const struct Op_Import *opi) { - const Exp a = (Exp)opi->data; - set_nonnull(mo->rhs, a); // rhs ??? -} - -ANN static void nn_dot(const M_Operator *mo, const struct Op_Import *opi) { - const Exp_Dot *a = (Exp_Dot*)opi->data; - set_nonnull(mo->lhs, a->base); -} - -ANN static void nn_array(const M_Operator *mo, const struct Op_Import *opi) { - const Array_Sub a = (Array_Sub)opi->data; - set_nonnull(mo->lhs, a->exp); -} - -ANN static void nn_binary(const M_Operator *mo, const struct Op_Import *opi) { - const Exp_Binary *a = (Exp_Binary*)opi->data; - set_nonnull(mo->lhs, a->lhs); - set_nonnull(mo->rhs, a->rhs); -} - -ANN static void nn_cast(const M_Operator *mo, const struct Op_Import *opi) { - const Exp_Cast *a = (Exp_Cast*)opi->data; - set_nonnull(mo->lhs, a->exp); -} - -ANN static void nn_postfix(const M_Operator *mo, const struct Op_Import *opi) { - const Exp_Postfix *a = (Exp_Postfix*)opi->data; - set_nonnull(mo->lhs, a->exp); -} - -ANN static void nn_unary(const M_Operator *mo, const struct Op_Import *opi) { - const Exp_Unary *a = (Exp_Unary*)opi->data; - set_nonnull(mo->rhs, a->exp); -} - -ANN static void nn_scan(const M_Operator *mo NUSED, const struct Op_Import *opi NUSED) { -} - -typedef void (*nn_f)(const M_Operator *mo, const struct Op_Import *opi); -static const nn_f nn_func[] = { - nn_implicit, nn_exp, nn_dot, nn_array, - nn_binary, nn_cast, nn_postfix, nn_unary, nn_scan -}; - -ANN static void opi_nonnull(const M_Operator *mo, const struct Op_Import *opi) { - nn_func[opi->op_type](mo, opi); -} - ANN static Type op_check_inner(struct OpChecker* ock) { Type t, r = ock->opi->rhs; do { const M_Operator* mo; const Vector v = (Vector)map_get(ock->map, (vtype)ock->opi->op); if(v && (mo = operator_find(v, ock->opi->lhs, r))) { - opi_nonnull(mo, ock->opi); if((mo->ck && (t = mo->ck(ock->env, (void*)ock->opi->data, &ock->mut)))) return t; else @@ -253,7 +191,7 @@ ANN Type op_check(const Env env, struct Op_Import* opi) { struct OpChecker ock = { env, &nspc->info->op_map, &opi2, 0 }; const Type ret = op_check_inner(&ock); if(ret) { - if(ret == env->gwion->type[et_null]) + if(ret == env->gwion->type[et_error]) break; if(!ock.mut) set_nspc(&opi2, nspc); diff --git a/src/parse/scan1.c b/src/parse/scan1.c index 54b21a8c..374c5c35 100644 --- a/src/parse/scan1.c +++ b/src/parse/scan1.c @@ -578,8 +578,6 @@ ANN static m_bool scan1_parent(const Env env, const Class_Def cdef) { CHECK_BB(ensure_scan1(env, parent)) if(type_ref(parent)) ERR_B(pos, _("can't use ref type in class extend")) - if(tflag(parent, tflag_nonnull)) - ERR_B(pos, _("can't use nonnull type in class extend")) return GW_OK; } diff --git a/src/parse/scanx.c b/src/parse/scanx.c index 39a491eb..7230326c 100644 --- a/src/parse/scanx.c +++ b/src/parse/scanx.c @@ -41,16 +41,10 @@ scanx_body(const Env e, const Class_Def c, const _exp_func f, void* d) { return ret; } -__attribute__((returns_nonnull)) -ANN Type unflag_type(const Type t) { - const Type type = !tflag(t, tflag_nonnull) ? t : t->info->parent; - return !tflag(type, tflag_force) ? type : type->info->parent; -} - __attribute__((returns_nonnull)) ANN Type get_type(const Type t) { const Type type = !t->array_depth ? t : array_base(t); - return unflag_type(type); + return type; } ANN m_bool scanx_cdef(const Env env, void* opt, const Type base, diff --git a/src/parse/type_decl.c b/src/parse/type_decl.c index fae410c5..d8af4d29 100644 --- a/src/parse/type_decl.c +++ b/src/parse/type_decl.c @@ -5,6 +5,14 @@ #include "traverse.h" #include "parse.h" +ANN static Type option(const Env env, Type_Decl* td) { + struct Type_List_ tl = { .td=td }; + Type_Decl option_td = { .xid=insert_symbol("Option"), .types=&tl }; + UNSET_FLAG(td, optionnal); + const Type ret = known_type(env, &option_td); + SET_FLAG(td, optionnal); + return ret; +} ANN static Type resolve(const Env env, Type_Decl* td) { DECL_OO(const Type, base, = find_type(env, td)) @@ -12,14 +20,7 @@ ANN static Type resolve(const Env env, Type_Decl* td) { ERR_O(td_pos(td), _("type '%s' is invalid"), base->name) DECL_OO(const Type, t, = scan_type(env, base, td)) const Type ret = !td->array ? t : array_type(env, t, td->array->depth); - if(GET_FLAG(td, nonnull)) { - if(isa(ret, env->gwion->type[et_void]) > 0) - ERR_O(td_pos(td), _("void types can't be nonnull.")) - if(isa(ret, env->gwion->type[et_object]) < 0 && isa(ret, env->gwion->type[et_fptr]) < 0) - return ret; - return nonnul_type(env, ret); - } - return ret; + return !GET_FLAG(td, optionnal) ? ret : option(env, td); } struct td_info { diff --git a/tests/UsrUgen/null_tick.gw b/tests/UsrUgen/null_tick.gw deleted file mode 100644 index 91d5280f..00000000 --- a/tests/UsrUgen/null_tick.gw +++ /dev/null @@ -1,3 +0,0 @@ -#! [contains] NullTickException -funcdef float ptr_t(float); -var ptr_t ptr ~= var UsrUGen u; diff --git a/tests/bug/Tester.gw b/tests/bug/Tester.gw deleted file mode 100644 index 4c6f1800..00000000 --- a/tests/bug/Tester.gw +++ /dev/null @@ -1,26 +0,0 @@ -class Tester -{ - fun int assert_equal:[A](string description, A a, A b){ if(a == b) return 0; return 1; } - fun int assert_not_equal:[A](string description, A a, A b){ if(a != b) return 0; return 1; } -} - -var Tester t; -var Object o; -ref Object oref; -"test" => var string s; -#!<<< t.assert_equal("test", 1, 1) >>>; -#!<<< t.assert_equal("test", 2, 1) >>>; -<<< t.assert_equal(s, 1, 1) >>>; -<<< t.assert_equal(s, 2, 1 + 1) >>>; -<<< t.assert_equal(s, 2, 1) >>>; -<<< t.assert_equal(s, o, o) >>>; -<<< t.assert_equal(s, o, null) >>>; -<<< t.assert_equal(s, null $ Object, null) >>>; -<<< t.assert_equal(s, oref, null) >>>; -<<< t.assert_not_equal(s, 1, 1) >>>; -<<< t.assert_not_equal(s, 2, 1 + 1) >>>; -<<< t.assert_not_equal(s, 2, 1) >>>; -<<< t.assert_not_equal(s, o, o) >>>; -<<< t.assert_not_equal(s, o, null) >>>; -<<< t.assert_not_equal(s, null $ Object, null) >>>; -<<< t.assert_not_equal(s, oref, null) >>>; diff --git a/tests/error/array_incompatible.gw b/tests/error/array_incompatible.gw index 0af41e4b..ab5dbe37 100644 --- a/tests/error/array_incompatible.gw +++ b/tests/error/array_incompatible.gw @@ -1,2 +1,2 @@ #! [contains] contains incompatible types -[null, 1]; +[new Object, 1]; diff --git a/tests/error/array_multi_except.gw b/tests/error/array_multi_except.gw deleted file mode 100644 index 3ad377c7..00000000 --- a/tests/error/array_multi_except.gw +++ /dev/null @@ -1,4 +0,0 @@ -#! [contains] NullPtrException -var int i[1][1]; -null @=> i[0]; -<<< i[0][0] >>>; diff --git a/tests/error/connect_except.gw b/tests/error/connect_except.gw deleted file mode 100644 index 084f50b4..00000000 --- a/tests/error/connect_except.gw +++ /dev/null @@ -1,3 +0,0 @@ -#! [contains] NullPtrException -ref UGen u; -adc => u; diff --git a/tests/error/empty_member_ptr.gw b/tests/error/empty_member_ptr.gw deleted file mode 100644 index 4e83d5c1..00000000 --- a/tests/error/empty_member_ptr.gw +++ /dev/null @@ -1,9 +0,0 @@ -#! [contains] NullPtrException -class C -{ - funcdef void test(); - var test t; -} -<<< var C c >>>; -<<< c.t >>>; -c.t(); diff --git a/tests/error/empty_obj_data.gw b/tests/error/empty_obj_data.gw deleted file mode 100644 index c4d18b63..00000000 --- a/tests/error/empty_obj_data.gw +++ /dev/null @@ -1,8 +0,0 @@ -#! [contains] NullPtrException -class C -{ - var int i; -} - -ref C c; -c.i; diff --git a/tests/error/ev.gw b/tests/error/ev.gw deleted file mode 100644 index 1508bd6a..00000000 --- a/tests/error/ev.gw +++ /dev/null @@ -1,3 +0,0 @@ -#! [contains] NullPtrException -ref Event e; -e => now; diff --git a/tests/error/fail_assign.gw b/tests/error/fail_assign.gw deleted file mode 100644 index cd1db1a2..00000000 --- a/tests/error/fail_assign.gw +++ /dev/null @@ -1,3 +0,0 @@ -#! [contains] can't assign -class C extends Event{} -var Event e @=> var C o; diff --git a/tests/error/func_non.gw b/tests/error/func_non.gw index cf68a27d..af010598 100644 --- a/tests/error/func_non.gw +++ b/tests/error/func_non.gw @@ -1,2 +1,2 @@ #! [contains] non-callable value -null(); +1(); diff --git a/tests/error/func_ptr_empty.gw b/tests/error/func_ptr_empty.gw deleted file mode 100644 index 19debcc4..00000000 --- a/tests/error/func_ptr_empty.gw +++ /dev/null @@ -1,4 +0,0 @@ -#! [contains] NullPtrException -funcdef void Test(); -var Test test; -test(); diff --git a/tests/error/if_exp_compat.gw b/tests/error/if_exp_compat.gw index 2cc6d045..2da42533 100644 --- a/tests/error/if_exp_compat.gw +++ b/tests/error/if_exp_compat.gw @@ -1,2 +1,2 @@ #! [contains] incompatible types -maybe ? null : 1; +maybe ? 2.1 : 1; diff --git a/tests/error/non_public_typedef_global_scope.gw b/tests/error/non_public_typedef_global_scope.gw deleted file mode 100644 index ac05dd23..00000000 --- a/tests/error/non_public_typedef_global_scope.gw +++ /dev/null @@ -1,6 +0,0 @@ -#! [contains] NullPtrException -class C { - funcdef void t_ptr(); -} -var C.t_ptr ptr; -ptr(); diff --git a/tests/error/nonnull_class_extend.gw b/tests/error/nonnull_class_extend.gw deleted file mode 100644 index 77dd193c..00000000 --- a/tests/error/nonnull_class_extend.gw +++ /dev/null @@ -1,4 +0,0 @@ -#! [contains] can't use nonnull type in class extend -class C extends nonnull Object { - -} diff --git a/tests/error/not_nn.gw b/tests/error/not_nn.gw deleted file mode 100644 index 748b8ff7..00000000 --- a/tests/error/not_nn.gw +++ /dev/null @@ -1,3 +0,0 @@ -#! [contains] expression is known to be nonnull -nonnull Object o; -<<< (!o) >>>; diff --git a/tests/error/null_array_access.gw b/tests/error/null_array_access.gw deleted file mode 100644 index 108472f4..00000000 --- a/tests/error/null_array_access.gw +++ /dev/null @@ -1,3 +0,0 @@ -#! [contains] NullPtrException -var int i[]; -i[0]; diff --git a/tests/error/null_array_access_multi.gw b/tests/error/null_array_access_multi.gw deleted file mode 100644 index 4995d847..00000000 --- a/tests/error/null_array_access_multi.gw +++ /dev/null @@ -1,3 +0,0 @@ -#! [contains] NullPtrException -var int i[][]; -i[0][0]; diff --git a/tests/error/null_auto.gw b/tests/error/null_auto.gw deleted file mode 100644 index ddcbbe61..00000000 --- a/tests/error/null_auto.gw +++ /dev/null @@ -1,4 +0,0 @@ -#! [contains] NullPtrException -var int i[]; -foreach(a : i) - <<< a >>>; diff --git a/tests/error/op_match.gw b/tests/error/op_match.gw index dfccfc34..153a42ce 100644 --- a/tests/error/op_match.gw +++ b/tests/error/op_match.gw @@ -1,3 +1,3 @@ #! [contains] no match found for operator var Object o; -null +=> o; +1 +=> o; diff --git a/tests/error/union_unknown.gw b/tests/error/union_unknown.gw index 788a6ade..ef81d7c3 100644 --- a/tests/error/union_unknown.gw +++ b/tests/error/union_unknown.gw @@ -1,5 +1,4 @@ #! [contains] unknown_type -union U -{ +union U { unknown_type unknown_variable; -}; +} diff --git a/tests/interp/to_string.gw b/tests/interp/to_string.gw index eb827980..14d9af9f 100644 --- a/tests/interp/to_string.gw +++ b/tests/interp/to_string.gw @@ -1,4 +1,4 @@ #! [contains] Hello, interpolation! 1 1 => var int my; -"Hello, interpolation! ${ my }" => var string s; +"Hello, interpolation! ${ my }" @=> var string s; <<< s >>>; diff --git a/tests/new/ref.gw b/tests/new/ref.gw index ea7ac129..d3657fcf 100644 --- a/tests/new/ref.gw +++ b/tests/new/ref.gw @@ -1 +1 @@ -new Object @=> nonnull Object o; +new Object @=> var Object? o; diff --git a/tests/nonnull/cast_non_null.gw b/tests/nonnull/cast_non_null.gw deleted file mode 100644 index 0087c856..00000000 --- a/tests/nonnull/cast_non_null.gw +++ /dev/null @@ -1,2 +0,0 @@ -ref Object o; -o $ nonnull Event; diff --git a/tests/nonnull/cast_non_null2.gw b/tests/nonnull/cast_non_null2.gw deleted file mode 100644 index 4dbedf5c..00000000 --- a/tests/nonnull/cast_non_null2.gw +++ /dev/null @@ -1,2 +0,0 @@ -ref Object o; -o $ Object; diff --git a/tests/nonnull/dynamic_implicit_nonnull.gw b/tests/nonnull/dynamic_implicit_nonnull.gw deleted file mode 100644 index 0ebff9bf..00000000 --- a/tests/nonnull/dynamic_implicit_nonnull.gw +++ /dev/null @@ -1,3 +0,0 @@ -fun void test(nonnull Object o) { <<< o >>>; } - -ref Object o => test; diff --git a/tests/nonnull/nonnull2nullable.gw b/tests/nonnull/nonnull2nullable.gw deleted file mode 100644 index f9c6956e..00000000 --- a/tests/nonnull/nonnull2nullable.gw +++ /dev/null @@ -1 +0,0 @@ -nonnull Object o @=> ref Object p; diff --git a/tests/nonnull/nonnull_assign_nonnull.gw b/tests/nonnull/nonnull_assign_nonnull.gw deleted file mode 100644 index f61c76c6..00000000 --- a/tests/nonnull/nonnull_assign_nonnull.gw +++ /dev/null @@ -1,2 +0,0 @@ -nonnull Object o, p; -o @=> p; diff --git a/tests/nonnull/nonnull_at_nonnull.gw b/tests/nonnull/nonnull_at_nonnull.gw deleted file mode 100644 index 9bfe9ba3..00000000 --- a/tests/nonnull/nonnull_at_nonnull.gw +++ /dev/null @@ -1 +0,0 @@ -new nonnull Object @=> nonnull Object o; diff --git a/tests/nonnull/nonnull_cast_nonnull.gw b/tests/nonnull/nonnull_cast_nonnull.gw deleted file mode 100644 index cd1e47d3..00000000 --- a/tests/nonnull/nonnull_cast_nonnull.gw +++ /dev/null @@ -1 +0,0 @@ -(nonnull Object o) $ nonnull Object; diff --git a/tests/nonnull/nonnull_decl.gw b/tests/nonnull/nonnull_decl.gw deleted file mode 100644 index 59f539ea..00000000 --- a/tests/nonnull/nonnull_decl.gw +++ /dev/null @@ -1 +0,0 @@ -nonnull Object o; diff --git a/tests/nonnull/nonnull_decl_ref_assign.gw b/tests/nonnull/nonnull_decl_ref_assign.gw deleted file mode 100644 index 89a9aaf2..00000000 --- a/tests/nonnull/nonnull_decl_ref_assign.gw +++ /dev/null @@ -1 +0,0 @@ -new Object @=> nonnull ref Object o; diff --git a/tests/nonnull/nonnull_err_cast_dynamic.gw b/tests/nonnull/nonnull_err_cast_dynamic.gw deleted file mode 100644 index 58524f58..00000000 --- a/tests/nonnull/nonnull_err_cast_dynamic.gw +++ /dev/null @@ -1,3 +0,0 @@ -#! [contains] NullPtrException -ref Object o; -<<< o $ nonnull Object >>>; diff --git a/tests/nonnull/nonnull_err_dynamic.gw b/tests/nonnull/nonnull_err_dynamic.gw deleted file mode 100644 index 31fc112f..00000000 --- a/tests/nonnull/nonnull_err_dynamic.gw +++ /dev/null @@ -1,5 +0,0 @@ -#! [contains} NullPtrException -fun void test(nonnull Object o) { - <<< o >>>; -} -ref Object o => test; diff --git a/tests/nonnull/nonnull_err_static_cast.gw b/tests/nonnull/nonnull_err_static_cast.gw deleted file mode 100644 index 95cd395c..00000000 --- a/tests/nonnull/nonnull_err_static_cast.gw +++ /dev/null @@ -1,3 +0,0 @@ -#! [contains] NullPtrException -ref Object ref_object; -<<< ref_object $ nonnull Object >>>; diff --git a/tests/nonnull/nonnull_impl_nonnull.gw b/tests/nonnull/nonnull_impl_nonnull.gw deleted file mode 100644 index f8e288ad..00000000 --- a/tests/nonnull/nonnull_impl_nonnull.gw +++ /dev/null @@ -1,2 +0,0 @@ -fun void test(nonnull Object o) { <<< o >>>; } -nonnull Object o => test; diff --git a/tests/nonnull/nonnull_implicit_nonnull.gw b/tests/nonnull/nonnull_implicit_nonnull.gw deleted file mode 100644 index f8e288ad..00000000 --- a/tests/nonnull/nonnull_implicit_nonnull.gw +++ /dev/null @@ -1,2 +0,0 @@ -fun void test(nonnull Object o) { <<< o >>>; } -nonnull Object o => test; diff --git a/tests/nonnull/normal_at_nonnull.gw b/tests/nonnull/normal_at_nonnull.gw deleted file mode 100644 index ea7ac129..00000000 --- a/tests/nonnull/normal_at_nonnull.gw +++ /dev/null @@ -1 +0,0 @@ -new Object @=> nonnull Object o; diff --git a/tests/nonnull/normal_cast_nonnull.gw b/tests/nonnull/normal_cast_nonnull.gw deleted file mode 100644 index c630d989..00000000 --- a/tests/nonnull/normal_cast_nonnull.gw +++ /dev/null @@ -1 +0,0 @@ -new Object $ nonnull Object; diff --git a/tests/nonnull/normal_impl_nonnull.gw b/tests/nonnull/normal_impl_nonnull.gw deleted file mode 100644 index 6d30b14e..00000000 --- a/tests/nonnull/normal_impl_nonnull.gw +++ /dev/null @@ -1,2 +0,0 @@ -fun void test(nonnull Object o) { <<< o >>>; } -new Object => test; diff --git a/tests/nonnull/null_at_nonnull.gw b/tests/nonnull/null_at_nonnull.gw deleted file mode 100644 index adc5ded2..00000000 --- a/tests/nonnull/null_at_nonnull.gw +++ /dev/null @@ -1,2 +0,0 @@ -#! [contains] can't assign -null @=> nonnull Object o; diff --git a/tests/nonnull/null_cast_nonnull.gw b/tests/nonnull/null_cast_nonnull.gw deleted file mode 100644 index d2e50569..00000000 --- a/tests/nonnull/null_cast_nonnull.gw +++ /dev/null @@ -1,2 +0,0 @@ -#! [contains] can't cast -null $ nonnull Object; diff --git a/tests/nonnull/null_impl_nonnull.gw b/tests/nonnull/null_impl_nonnull.gw deleted file mode 100644 index 3c2fbca3..00000000 --- a/tests/nonnull/null_impl_nonnull.gw +++ /dev/null @@ -1,3 +0,0 @@ -#! [contains] can't implicitly cast -fun void test(nonnull Object o) { <<< o >>>; } -null => test; diff --git a/tests/nonnull/ref.gw b/tests/nonnull/ref.gw deleted file mode 100644 index ea7ac129..00000000 --- a/tests/nonnull/ref.gw +++ /dev/null @@ -1 +0,0 @@ -new Object @=> nonnull Object o; diff --git a/tests/nonnull/ref_at_nonnull.gw b/tests/nonnull/ref_at_nonnull.gw deleted file mode 100644 index db626b45..00000000 --- a/tests/nonnull/ref_at_nonnull.gw +++ /dev/null @@ -1,2 +0,0 @@ -#! [contains] NullPtrException -ref Object o @=> nonnull Object p; diff --git a/tests/nonnull/ref_cast_nonnull.gw b/tests/nonnull/ref_cast_nonnull.gw deleted file mode 100644 index 6f63edb7..00000000 --- a/tests/nonnull/ref_cast_nonnull.gw +++ /dev/null @@ -1,2 +0,0 @@ -#! [contains] NullPtrException -(ref Object o) $ nonnull Object; diff --git a/tests/nonnull/ref_impl_nonnull.gw b/tests/nonnull/ref_impl_nonnull.gw deleted file mode 100644 index 003d9a2e..00000000 --- a/tests/nonnull/ref_impl_nonnull.gw +++ /dev/null @@ -1,3 +0,0 @@ -#! [contains] NullPtrException -fun void test(nonnull Object o) { <<< o >>>; } -ref Object o => test; diff --git a/tests/nonnull/ref_nonnull.gw b/tests/nonnull/ref_nonnull.gw deleted file mode 100644 index 1ff7a38b..00000000 --- a/tests/nonnull/ref_nonnull.gw +++ /dev/null @@ -1,3 +0,0 @@ -#! [contains] NullPtrException -ref Object a @=> nonnull Object o; -<<< o >>>; diff --git a/tests/nonnull/static_implicit_nonnull.gw b/tests/nonnull/static_implicit_nonnull.gw deleted file mode 100644 index 3f657ac4..00000000 --- a/tests/nonnull/static_implicit_nonnull.gw +++ /dev/null @@ -1,4 +0,0 @@ -#! [contains] can't implicitly cast -fun void test(nonnull Object o) { <<< o >>>; } - -null => test; diff --git a/tests/nonnull/void_nonnull.gw b/tests/nonnull/void_nonnull.gw deleted file mode 100644 index 7952f23c..00000000 --- a/tests/nonnull/void_nonnull.gw +++ /dev/null @@ -1,2 +0,0 @@ -#! [contains] void types can't be nonnull -nonnull void i; diff --git a/tests/string/eq.gw b/tests/string/eq.gw index f2b95b86..14ace808 100644 --- a/tests/string/eq.gw +++ b/tests/string/eq.gw @@ -6,12 +6,3 @@ <<< s0 != s0 >>>; <<< s0 != s1 >>>; - -<<< null == s0 >>>; -<<< null != s0 >>>; - -<<< s0 == null >>>; -<<< s0 != null >>>; - -<<< null == null >>>; -<<< null != null >>>; diff --git a/tests/tree/call_nonnull.gw b/tests/tree/call_nonnull.gw deleted file mode 100644 index 49ba3189..00000000 --- a/tests/tree/call_nonnull.gw +++ /dev/null @@ -1,3 +0,0 @@ -funcdef void test_t:[A](); -nonnull test_t t; -t:[int](); diff --git a/tests/tree/new.gw b/tests/tree/new.gw index 8cb564e0..38ff83ae 100644 --- a/tests/tree/new.gw +++ b/tests/tree/new.gw @@ -5,4 +5,3 @@ var Event ev; ev @=> ref Event e; new Event @=> e; ev @=> e; -null @=> e; diff --git a/tests/tree/set_obj.gw b/tests/tree/set_obj.gw index 6a7374e8..ae8180a6 100644 --- a/tests/tree/set_obj.gw +++ b/tests/tree/set_obj.gw @@ -1,4 +1,4 @@ -typedef int[2]Type; -nonnull Type type; +typedef int[2] Type; +Type type; <<>>; foreach(ref a : type); diff --git a/tests/tree/variadic_test.gw b/tests/tree/variadic_test.gw index 92fb715b..989af2a5 100644 --- a/tests/tree/variadic_test.gw +++ b/tests/tree/variadic_test.gw @@ -1,3 +1,3 @@ fun void test(int i, ...) {} -test(1, 2.3, null); +test(1, 2.3, new Object); -- 2.43.0