From 72335afb3c27dd967c1f7d53dd74ecc26bd61c6b Mon Sep 17 00:00:00 2001 From: fennecdjay Date: Mon, 23 Sep 2019 16:16:43 +0200 Subject: [PATCH] :art: Introduce SpecialId --- include/gwiondata.h | 1 + include/import.h | 3 ++- include/specialid.h | 33 +++++++++++++++++++++++++++++++++ src/emit/emit.c | 12 ++++-------- src/gwion.c | 10 ++++++++++ src/gwiondata.c | 10 ++++++++++ src/lib/import.c | 10 ++++++++++ src/lib/object.c | 17 +++++++++++++++++ src/lib/prim.c | 9 +++++++-- src/lib/shred.c | 7 +++++-- src/lib/string.c | 18 ++++++++++++++++-- src/parse/check.c | 20 ++++++-------------- 12 files changed, 121 insertions(+), 29 deletions(-) create mode 100644 include/specialid.h diff --git a/include/gwiondata.h b/include/gwiondata.h index f0e31285..c21a27ac 100644 --- a/include/gwiondata.h +++ b/include/gwiondata.h @@ -2,6 +2,7 @@ #define __GWIONDATA typedef struct GwionData_ { struct Map_ freearg; + struct Map_ id; MUTEX_TYPE mutex; struct Vector_ child; struct Vector_ reserved; diff --git a/include/import.h b/include/import.h index d8bd808d..3122f6ff 100644 --- a/include/import.h +++ b/include/import.h @@ -89,5 +89,6 @@ ANN Type_List str2tl(const Env env, const m_str s, m_uint *depth); typedef void (*f_freearg)(Instr, void*); ANN void register_freearg(const Gwi, const f_instr, const f_freearg); ANN void gwi_reserve(const Gwi, const m_str); - +typedef struct SpecialId_* SpecialId; +ANN void gwi_specialid(const Gwi gwi, const m_str id, const SpecialId); #endif diff --git a/include/specialid.h b/include/specialid.h new file mode 100644 index 00000000..13fe0e5f --- /dev/null +++ b/include/specialid.h @@ -0,0 +1,33 @@ +#ifndef __SPECIALID +#define __SPECIALID + +//typedef struct SpecialId_* SpecialId; +struct SpecialId_; +typedef Type (*idck)(const Env, Exp_Primary*); +typedef Instr (*idem)(const Emitter, Exp_Primary*); + +struct SpecialId_ { + Type type; + idck ck; + f_instr exec; + idem em; + m_bool is_const; +}; + +#define ID_CHECK(a) ANN Type a(const Env env NUSED, Exp_Primary* prim NUSED) +#define ID_EMIT(a) ANN Instr a(const Emitter emit NUSED, Exp_Primary* prim NUSED) + +ANN static inline Type specialid_type(const Env env, + struct SpecialId_ *spid, const Exp_Primary* prim) { + if(spid->is_const) + exp_self(prim)->meta = ae_meta_value; + return spid->type ?: spid->ck(env, prim); +} + +ANN static inline Instr specialid_instr(const Emitter emit, + struct SpecialId_ *spid, const Exp_Primary* prim) { + return spid->exec ? emit_add_instr(emit, spid->exec) : spid->em(emit, prim); +} + +ANN struct SpecialId_* specialid_get(const Gwion, const Symbol); +#endif diff --git a/src/emit/emit.c b/src/emit/emit.c index 38681317..abaca1d6 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -24,6 +24,7 @@ #include "match.h" #include "parser.h" #include "tuple.h" +#include "specialid.h" #undef insert_symbol #define insert_symbol(a) insert_symbol(emit->gwion->st, (a)) @@ -512,14 +513,9 @@ ANN static m_bool prim_vec(const Emitter emit, const Exp_Primary * primary) { } ANN static m_bool prim_id(const Emitter emit, const Exp_Primary* prim) { - if(prim->d.var == insert_symbol("this")) - emit_add_instr(emit, RegPushMem); - else if(prim->d.var == insert_symbol("me")) - emit_add_instr(emit, RegPushMe); - else if(prim->d.var == insert_symbol("now")) - emit_add_instr(emit, RegPushNow); - else if(prim->d.var == insert_symbol("maybe")) - emit_add_instr(emit, RegPushMaybe); + struct SpecialId_ * spid = specialid_get(emit->gwion, prim->d.var); + if(spid) + return specialid_instr(emit, spid, prim) ? GW_OK : GW_ERROR; else emit_symbol(emit, prim); return GW_OK; diff --git a/src/gwion.c b/src/gwion.c index edb8c222..f80bb4dc 100644 --- a/src/gwion.c +++ b/src/gwion.c @@ -17,6 +17,7 @@ #include "compile.h" #include "object.h" // fork_clean #include "pass.h" // fork_clean +#include "specialid.h" // fork_clean ANN m_bool gwion_audio(const Gwion gwion) { Driver* di = gwion->vm->bbq; @@ -129,3 +130,12 @@ ANN void env_err(const Env env, const struct YYLTYPE* pos, const m_str fmt, ...) if(env->context) env->context->error = 1; } + +ANN struct SpecialId_* specialid_get(const Gwion gwion, const Symbol sym) { + const Map map = &gwion->data->id; + for(m_uint i = 0; i < map_size(map); ++i) { + if(sym == (Symbol)VKEY(map, i)) + return (struct SpecialId_*)VVAL(map, i); + } + return NULL; +} diff --git a/src/gwiondata.c b/src/gwiondata.c index 92645bf2..11306a63 100644 --- a/src/gwiondata.c +++ b/src/gwiondata.c @@ -1,10 +1,17 @@ #include "gwion_util.h" #include "gwion_ast.h" #include "gwiondata.h" +#include "oo.h" +#include "env.h" +#include "vm.h" +#include "instr.h" +#include "gwion.h" +#include "specialid.h" ANN GwionData* new_gwiondata(MemPool mp) { struct GwionData_ *data = mp_calloc(mp, GwionData); map_init(&data->freearg); + map_init(&data->id); vector_init(&data->reserved); map_init(&data->pass_map); vector_init(&data->pass); @@ -14,6 +21,9 @@ ANN GwionData* new_gwiondata(MemPool mp) { ANN void free_gwiondata(MemPool mp, GwionData *data) { map_release(&data->freearg); + for(m_uint i = 0; i < map_size(&data->id); ++i) + mp_free(mp, SpecialId, (struct SpecialId_*)map_at(&data->id, i)); + map_release(&data->id); vector_release(&data->reserved); map_release(&data->pass_map); vector_release(&data->pass); diff --git a/src/lib/import.c b/src/lib/import.c index 10103aa2..6391fce5 100644 --- a/src/lib/import.c +++ b/src/lib/import.c @@ -19,6 +19,7 @@ #include "import.h" #include "gwi.h" #include "mpool.h" +#include "specialid.h" #define GWI_ERR_B(a,...) { env_err(gwi->gwion->env, gwi->loc, (a), ## __VA_ARGS__); return GW_ERROR; } #define GWI_ERR_O(a,...) { env_err(gwi->gwion->env, gwi->loc, (a), ## __VA_ARGS__); return NULL; } @@ -679,3 +680,12 @@ ANN void register_freearg(const Gwi gwi, const f_instr _exec, const f_freearg _f ANN void gwi_reserve(const Gwi gwi, const m_str str) { vector_add(&gwi->gwion->data->reserved, (vtype)insert_symbol(gwi->gwion->st, str)); } + +ANN void gwi_specialid(const Gwi gwi, const m_str id, const SpecialId spid) { + struct SpecialId_ *a = mp_calloc(gwi->gwion->mp, SpecialId); + a->type = spid->type; + a->ck = spid->ck; + a->exec = spid->exec; + a->em = spid->em; + map_set(&gwi->gwion->data->id, (vtype)insert_symbol(gwi->gwion->st, id), (vtype)a); +} diff --git a/src/lib/object.c b/src/lib/object.c index 482f66af..fc5cad82 100644 --- a/src/lib/object.c +++ b/src/lib/object.c @@ -14,7 +14,14 @@ #include "operator.h" #include "import.h" #include "emit.h" +#include "traverse.h" +#include "parse.h" +#include "func.h" +#include "specialid.h" +#include "gwi.h" + +#undef insert_symbol ANN void exception(const VM_Shred shred, const m_str c) { gw_err("%s: shred[id=%" UINT_F ":%s], PC=[%" UINT_F "]\n", c, shred->tick->xid, shred->info->name, shred->pc - 1); @@ -206,6 +213,14 @@ static OP_EMIT(opem_implicit_null2obj) { return (Instr)GW_OK; } +static ID_CHECK(check_this) { + if(!env->class_def) + ERR_O(exp_self(prim)->pos, _("keyword 'this' can be used only inside class definition...")) + if(env->func && !GET_FLAG(env->func, member)) + ERR_O(exp_self(prim)->pos, _("keyword 'this' cannot be used inside static functions...")) + return env->class_def; +} + GWION_IMPORT(object) { t_object = gwi_mk_type(gwi, "Object", SZ_INT, NULL); GWI_BB(gwi_class_ini(gwi, t_object, NULL, NULL)) @@ -244,5 +259,7 @@ GWION_IMPORT(object) { gwi_item_ini(gwi, "@null", "null"); gwi_item_end(gwi, 0, NULL); gwi_reserve(gwi, "this"); + struct SpecialId_ spid = { .ck=check_this, .exec=RegPushMem, .is_const=1 }; + gwi_specialid(gwi, "this", &spid); return GW_OK; } diff --git a/src/lib/prim.c b/src/lib/prim.c index 8a4048c9..295e6809 100644 --- a/src/lib/prim.c +++ b/src/lib/prim.c @@ -14,6 +14,7 @@ #include "driver.h" #include "traverse.h" #include "parse.h" +#include "specialid.h" #define CHECK_OP(op, check, func) _CHECK_OP(op, check, int_##func) @@ -78,9 +79,11 @@ static GWION_IMPORT(int_values) { GWI_BB(gwi_enum_add(gwi, "false", 0)) GWI_BB(gwi_enum_add(gwi, "true", 1)) t_bool = gwi_enum_end(gwi); - GWI_BB(gwi_item_ini(gwi, "bool", "maybe")) - GWI_BB(gwi_item_end(gwi, 0, NULL)) +// GWI_BB(gwi_item_ini(gwi, "bool", "maybe")) +// GWI_BB(gwi_item_end(gwi, 0, NULL)) gwi_reserve(gwi, "maybe"); + struct SpecialId_ spid = { .type=t_bool, .exec=RegPushMaybe, .is_const=1 }; + gwi_specialid(gwi, "maybe", &spid); return GW_OK; } @@ -126,6 +129,8 @@ static GWION_IMPORT(values) { gwi_item_ini(gwi, "@now", "now"); gwi_item_end(gwi, ae_flag_const, NULL); gwi_reserve(gwi, "now"); + struct SpecialId_ spid = { .type=t_now, .exec=RegPushNow, .is_const=1 }; + gwi_specialid(gwi, "now", &spid); return GW_OK; } /* diff --git a/src/lib/shred.c b/src/lib/shred.c index a727e08a..da411adf 100644 --- a/src/lib/shred.c +++ b/src/lib/shred.c @@ -12,6 +12,7 @@ #include "gwion.h" #include "operator.h" #include "import.h" +#include "specialid.h" static m_int o_fork_thread, o_shred_cancel, o_fork_done, o_fork_ev, o_fork_retsize, o_fork_retval, o_fork_orig; @@ -291,8 +292,10 @@ GWION_IMPORT(shred) { GWI_BB(gwi_func_end(gwi, 0)) GWI_BB(gwi_class_end(gwi)) - gwi_item_ini(gwi, "Shred", "me"); - gwi_item_end(gwi, ae_flag_const, NULL); + gwi_reserve(gwi, "me"); + struct SpecialId_ spid = { .type=t_shred, .exec=RegPushMe, .is_const=1 }; + gwi_specialid(gwi, "me", &spid); + SET_FLAG((t_shred), abstract); GWI_OB((t_fork = gwi_mk_type(gwi, "Fork", SZ_INT, t_shred))) diff --git a/src/lib/string.c b/src/lib/string.c index d323bbce..fbb3ecba 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -13,6 +13,8 @@ #include "gwion.h" #include "operator.h" #include "import.h" +#include "specialid.h" +#include "func.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)); @@ -169,6 +171,14 @@ static CTOR(string_ctor) { STRING(o) = ""; } +ANN Type prim_str(const Env, Exp_Primary *const); +ID_CHECK(check_funcpp) { + prim->primary_type = ae_primary_str; + prim->d.str = env->func ? env->func->name : env->class_def ? + env->class_def->name : env->name; + return prim_str(env, prim); +} + GWION_IMPORT(string) { t_string = gwi_mk_type(gwi, "string", SZ_INT, t_object); GWI_BB(gwi_class_ini(gwi, t_string, string_ctor, NULL)) @@ -244,8 +254,12 @@ GWION_IMPORT(string) { GWI_BB(gwi_oper_add(gwi, opck_const_rhs)) GWI_BB(gwi_oper_end(gwi, "+=>", Object_String_Plus)) - gwi_item_ini(gwi, "string", "__func__"); - gwi_item_end(gwi, ae_flag_const, NULL); +// gwi_item_ini(gwi, "string", "__func__"); +// gwi_item_end(gwi, ae_flag_const, NULL); +// gwi_reserve(gwi, "__func__"); + gwi_reserve(gwi, "__func__"); + struct SpecialId_ spid = { .ck=check_funcpp, .exec=RegPushMe, .is_const=1 }; + gwi_specialid(gwi, "__func__", &spid); return GW_OK; } diff --git a/src/parse/check.c b/src/parse/check.c index 52897ff1..9c8881bc 100644 --- a/src/parse/check.c +++ b/src/parse/check.c @@ -20,6 +20,7 @@ #include "match.h" #include "cpy_ast.h" #include "tuple.h" +#include "specialid.h" ANN static Type check_exp(const Env env, Exp exp); ANN static m_bool check_stmt_list(const Env env, Stmt_List list); @@ -237,16 +238,6 @@ ANN static Type prim_id_non_res(const Env env, const Exp_Primary* primary) { return v->type; } -ANN static Type check_exp_prim_this(const Env env, const Exp_Primary* primary) { - if(!env->class_def) - ERR_O(exp_self(primary)->pos, _("keyword 'this' can be used only inside class definition...")) - if(env->func && !GET_FLAG(env->func, member)) - ERR_O(exp_self(primary)->pos, _("keyword 'this' cannot be used inside static functions...")) - exp_self(primary)->meta = ae_meta_value; - return env->class_def; -} - - ANN static inline Value prim_str_value(const Env env, const Symbol sym) { const Value v = nspc_lookup_value0(env->global_nspc, sym); if(v) @@ -256,7 +247,7 @@ ANN static inline Value prim_str_value(const Env env, const Symbol sym) { return value; } -ANN static Type prim_str(const Env env, Exp_Primary *const prim) { +ANN Type prim_str(const Env env, Exp_Primary *const prim) { if(!prim->value) { const m_str str = prim->d.str; char c[strlen(str) + 8]; @@ -267,10 +258,11 @@ ANN static Type prim_str(const Env env, Exp_Primary *const prim) { } ANN static Type prim_id(const Env env, Exp_Primary* primary) { + struct SpecialId_ * spid = specialid_get(env->gwion, primary->d.var); + if(spid) + return specialid_type(env, spid, primary); const m_str str = s_name(primary->d.var); - if(!strcmp(str, "this")) - return check_exp_prim_this(env, primary); - else if(!strcmp(str, "__func__")) { + if(!strcmp(str, "__func__")) { primary->primary_type = ae_primary_str; primary->d.str = env->func ? env->func->name : env->class_def ? env->class_def->name : env->name; -- 2.43.0