-Subproject commit e3939cd9cdb1f8aeab49df8db855fea945938ba9
+Subproject commit 318792cdc12f6b9632f89052c2d6cc258031b99c
fun void test(...) {
int i;
- vararg.start;
-
- if(i == 0)
- <<< vararg $ int >>>;
- else if(i == 1)
- <<< vararg $ float >>>;
- else if(i == 2)
- <<< vararg $ Object >>>;
- i++;
- vararg.end;
+ varloop vararg {
+ if(i == 0)
+ <<< vararg $ int >>>;
+ else if(i == 1)
+ <<< vararg $ float >>>;
+ else if(i == 2)
+ <<< vararg $ Object >>>;
+ i++;
+ }
}
test(1);
test(1, 2.3, null);
struct EmitterInfo_ {
struct Vector_ pure;
- struct Vector_ variadic;
char *escape;
f_instr finalyzer;
VM_Code (*emit_code)(const Emitter);
struct VM_Code_* dtor;
struct NspcInfo_* info;
HAS_OBJ
- uint is_union;
};
extern ANEW ANN Nspc new_nspc(MemPool p, const m_str name);
typedef enum {
et_void, et_int, et_bool, et_char, et_float,
et_null, et_object, et_shred, et_fork, et_event, et_ugen, et_string, et_ptr, et_array, et_gack,
- et_function, et_fptr, et_varloop, et_lambda, et_class, et_union, et_undefined, et_auto,
+ et_function, et_fptr, et_vararg, et_lambda, et_class, et_union, et_undefined, et_auto,
MAX_TYPE
} type_enum;
#endif
ANN2(1,2) Type gwi_class_spe(const Gwi gwi, const m_str, const m_uint size);
ANN2(1) void gwi_class_xtor(const Gwi gwi, const f_xtor ctor, const f_xtor dtor);
ANN m_int gwi_class_end(const Gwi gwi);
+ANN void inherit(const Type);
#endif
Instr (*em)(Emitter, void*); // oper
m_str lhs;// oper
m_str rhs;// oper
+ m_uint emit_var;
} OperCK;
struct array_checker {
ANN2(1) m_int gwi_oper_end(const Gwi gwi, const m_str op, const f_instr f);
ANN m_int gwi_oper_cond(const Gwi, const m_str, const f_instr, const f_instr);
+//! use this with one if the right side operator's to emit_var is set
+ANN m_int gwi_oper_var(const Gwi gwi, const m_bool offset);
+
#define _EQUALITY_OPER(sz, sign) \
POP_REG(shred, sz*2 - SZ_INT); \
*(m_uint*)REG(-SZ_INT) = sign \
/* vararg */
INSTR(VarargIni);
-INSTR(VarargTop);
-INSTR(VarargEnd);
-INSTR(VecCpy);
-INSTR(VecMember);
INSTR(PopArrayClass);
INSTR(DotTmpl);
ANN m_bool import_ptr(const Gwi gwi);
ANN m_bool import_func(const Gwi gwi);
ANN m_bool import_modules(const Gwi gwi);
+ANN m_bool import_object_op(const Gwi gwi);
+ANN m_bool import_values(const Gwi gwi);
#endif
typedef Type (*opck)(const Env, void*, m_bool*);
typedef struct Instr_* (*opem)(const Emitter, void*);
-struct Op_Import {
- Type lhs, rhs, ret;
+struct Op_Func {
opck ck;
opem em;
+};
+
+struct Op_Import {
+ Type lhs, rhs, ret;
+ const struct Op_Func *func;
uintptr_t data;
loc_t pos;
Symbol op;
+ m_uint emit_var;
};
struct Implicit {
#ifndef __VARARG
#define __VARARG
struct Vararg_ {
- m_uint* k; // sizes
- Type* t; // types
- m_bit* d; // d(ata)
- m_uint o, i, s; // o(ffset), i(ndex), s(ize)
+ struct Vector_ t; // types
+ m_bit *d; // d(ata)
+ m_uint o, i, s, l; // o(ffset), i(ndex), s(ize), l(en)
+ m_uint pc;
};
+ANN void emit_vararg_end(const Emitter emit, const m_uint pc);
void free_vararg(MemPool p, struct Vararg_* arg);
#endif
#include "parser.h"
#include "tuple.h"
#include "specialid.h"
+#include "vararg.h"
#undef insert_symbol
#define insert_symbol(a) insert_symbol(emit->gwion->st, (a))
return GW_OK;
}
+ANN static m_bool variadic_state(const Emitter emit, const Stmt_VarLoop stmt, const m_uint status) {
+ regpushi(emit, status);
+ CHECK_BB(emit_exp(emit, stmt->exp, 0))
+ emit_add_instr(emit, SetObj);
+ const Instr member = emit_add_instr(emit, DotMember4);
+ member->m_val = SZ_INT;
+ emit_add_instr(emit, int_r_assign);
+ regpop(emit, SZ_INT);
+ return GW_OK;
+}
+
+ANN static m_bool emit_stmt_varloop(const Emitter emit, const Stmt_VarLoop stmt) {
+ CHECK_BB(variadic_state(emit, stmt, 1))
+ CHECK_BB(emit_exp(emit, stmt->exp, 0))
+ const Instr instr = emit_add_instr(emit, BranchEqInt);
+ const m_uint pc = emit_code_size(emit);
+ emit_stmt(emit, stmt->body, 1);
+ CHECK_BB(emit_exp(emit, stmt->exp, 0))
+ emit_vararg_end(emit, pc);
+ instr->m_val = emit_code_size(emit);
+ CHECK_BB(variadic_state(emit, stmt, 0))
+ return GW_OK;
+}
+
// scope push problem
ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) {
emit_push_stack(emit);
return GW_OK;
}
-ANN static inline Instr get_variadic(const Emitter emit) {
- return (Instr)vector_back(&emit->info->variadic);
-}
-
ANN static inline m_bool ensure_emit(const Emitter emit, const Type type) {
const Type t = actual_type(emit->gwion, type) ?: type;
if(!GET_FLAG(t, emit) && t->e->def)
return finalyze(emit, FuncReturn);
}
-ANN static m_bool _fdef_body(const Emitter emit, const Func_Def fdef) {
+ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def fdef) {
if(fdef->base->args)
emit_func_def_args(emit, fdef->base->args);
if(GET_FLAG(fdef, variadic))
return GW_OK;
}
-ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def fdef) {
- vector_add(&emit->info->variadic, 0);
- CHECK_BB(_fdef_body(emit, fdef))
- if(GET_FLAG(fdef, variadic)) {
- if(!get_variadic(emit))
- ERR_B(fdef->pos, _("invalid variadic use"))
- if(!GET_FLAG(fdef->base->func, empty))
- ERR_B(fdef->pos, _("invalid variadic use"))
- }
- vector_pop(&emit->info->variadic);
- return GW_OK;
-}
-
ANN static Instr me_top(MemoizeEmitter *me) {
const Instr idx = emit_add_instr(me->emit, MemSetImm);
idx->m_val = me->offset;
vector_init(&emit->stack);
emit->info = (struct EmitterInfo_*)mp_calloc(p, EmitterInfo);
vector_init(&emit->info->pure);
- vector_init(&emit->info->variadic);
emit->info->escape = escape_table(p);
emit->info->emit_code = emit_code;
emit->info->finalyzer = EOC;
ANN void free_emitter(MemPool p, Emitter a) {
vector_release(&a->stack);
vector_release(&a->info->pure);
- vector_release(&a->info->variadic);
mp_free2(p, 256, a->info->escape);
mp_free(p, EmitterInfo, a->info);
mp_free(p, Emitter, a);
ANN static void free_nspc_value(const Nspc a, Gwion gwion) {
struct scope_iter iter = { a->info->value, 0, 0 };
Value v;
- if(!a->is_union) {
- while(scope_iter(&iter, &v) > 0) {
- if(v) {
- if(isa(v->type, gwion->type[et_object]) > 0)
- nspc_release_object(a, v, gwion);
- REM_REF(v, gwion);
- }
- }
+ while(scope_iter(&iter, &v) > 0) {
+ if(isa(v->type, gwion->type[et_object]) > 0)
+ nspc_release_object(a, v, gwion);
+ REM_REF(v, gwion);
}
free_scope(gwion->mp, a->info->value);
}
return GW_OK;
}
+ANN2(1,2) static inline m_bool class_parent(const Env env, const Type t) {
+ Type parent = t->e->parent;
+ while(parent && !GET_FLAG(parent, checked)) {
+ if(t->e->def)
+ CHECK_BB(traverse_class_def(env, t->e->def))
+ parent = parent->e->parent;
+ }
+ return GW_OK;
+}
+
+ANN void inherit(const Type t) {
+ const Nspc nspc = t->nspc, parent = t->e->parent->nspc;
+ if(!nspc || !parent)
+ return;
+ nspc->info->offset = parent->info->offset;
+ if(parent->info->vtable.ptr)
+ vector_copy2(&parent->info->vtable, &nspc->info->vtable);
+}
+
ANN2(1,2) static void import_class_ini(const Env env, const Type t) {
t->nspc = new_nspc(env->gwion->mp, t->name);
t->nspc->parent = env->curr;
- if(t->e->parent && t->e->parent->nspc) {
- t->nspc->info->offset = t->e->parent->nspc->info->offset;
- if(t->e->parent->nspc->info->vtable.ptr)
- vector_copy2(&t->e->parent->nspc->info->vtable, &t->nspc->info->vtable);
- }
+ inherit(t);
t->e->owner = env->curr;
SET_FLAG(t, checked);
env_push_type(env, t);
ANN static Type type_finish(const Gwi gwi, const Type t) {
gwi_add_type(gwi, t);
+ CHECK_BO(class_parent(gwi->gwion->env, t))
import_class_ini(gwi->gwion->env, t);
return t;
}
}
//! convert a string to a Type_Decl
-ANN Type_Decl* str2decl(const Gwi gwi, const m_str s) {
+ANN Type_Decl* str2decl(const Gwi gwi, const m_str str) {
+ const ae_flag flag = strncmp(str, "nonnull ", 8) ? ae_flag_none : ae_flag_nonnull;
+ const m_str s = strncmp(str, "nonnull ", 8) ? str : str + 8;
// we can do better
DECL_OO(const m_str, type_name, = get_type_name(gwi->gwion->env, s, 0))
struct array_checker ck = { .str=type_name };
td->array = new_array_sub(gwi->gwion->mp, ck.exp);
td->array->depth = ck.depth;
}
+ td->flag |= flag;
return td;
}
#include "mpool.h"
#include "specialid.h"
-ANN static Type _get_type(const Gwi gwi, const m_str str) {
- if(str == (m_str)OP_ANY_TYPE)
+ANN static Type _get_type(const Gwi gwi, const m_str s) {
+ if(s == (m_str)OP_ANY_TYPE)
return OP_ANY_TYPE;
- struct array_checker ck = { .str=str };
- DECL_OO(const ID_List, list, = ck2list(gwi, &ck))
- const Type t = find_type(gwi->gwion->env, list);
- if(list)
- free_id_list(gwi->gwion->mp, list);
- return t ? (ck.depth ? array_type(gwi->gwion->env, t, ck.depth) : t) : NULL;
+ Type_Decl *td = str2decl(gwi, s);
+ const Type t = known_type(gwi->gwion->env, td);
+ free_type_decl(gwi->gwion->mp, td);
+ return t;
}
ANN2(1) static inline Type get_type(const Gwi gwi, const m_str str) {
const Type lhs = get_type(gwi, op->lhs),
rhs = get_type(gwi, op->rhs),
ret = get_type(gwi, op->ret);
- const struct Op_Import opi = { lhs, rhs, ret,
- op->ck, op->em, (uintptr_t)f, gwi->loc, op->sym };
+ const struct Op_Func opfunc = { .ck=op->ck, .em=op->em };
+ const struct Op_Import opi = { .lhs=lhs, .rhs=rhs, .ret=ret,
+ .func=&opfunc, .data=(uintptr_t)f, .pos=gwi->loc, .op=op->sym, .emit_var=op->emit_var };
return add_op(gwi->gwion, &opi);
}
return GW_OK;
}
+ANN m_int gwi_oper_var(const Gwi gwi, const m_bool offset) {
+ gwi->oper->emit_var = offset;
+ return GW_OK;
+}
+
ANN m_int gwi_oper_emi(const Gwi gwi, const opem em) {
gwi->oper->em = em;
return GW_OK;
ANN m_int gwi_oper_cond(const Gwi gwi, const m_str type,
const f_instr f1, const f_instr f2) {
- GWI_BB(gwi_oper_ini(gwi, NULL, type, "int"))
+ GWI_BB(gwi_oper_ini(gwi, NULL, type, "bool"))
GWI_BB(gwi_oper_end(gwi, "@conditionnal", f1))
GWI_BB(gwi_oper_end(gwi, "@unconditionnal", f2))
return GW_OK;
const Type type = bin->rhs->type;
const Instr pop = emit_add_instr(emit, RegPop);
pop->m_val = type->size;
- if(!GET_FLAG(bin->lhs->type, nonnull))
- emit_add_instr(emit, GWOP_EXCEPT);
return emit_add_instr(emit, ArrayAppend);
}
}
static OP_EMIT(opem_array_slice) {
- const Exp exp = (Exp)data;
- if(!GET_FLAG(exp->type, nonnull))
- emit_add_instr(emit, GWOP_EXCEPT);
emit_add_instr(emit, ArraySlice);
return emit_add_instr(emit, GcAdd);
}
GWI_BB(gwi_oper_ini(gwi, "@Array", (m_str)OP_ANY_TYPE, 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_add(gwi, opck_array_shift))
GWI_BB(gwi_oper_emi(gwi, opem_array_shift))
GWI_BB(gwi_oper_end(gwi, "<<", NULL))
GWI_BB(gwi_oper_add(gwi, opck_array_cast))
GWI_BB(gwi_oper_emi(gwi, opem_basic_cast))
GWI_BB(gwi_oper_end(gwi, "$", NULL))
- GWI_BB(gwi_oper_ini(gwi, "@Array", "int", "int"))
+ GWI_BB(gwi_oper_ini(gwi, "nonnull @Array", "int", "int"))
GWI_BB(gwi_oper_add(gwi, opck_array_slice))
GWI_BB(gwi_oper_emi(gwi, opem_array_slice))
+ GWI_BB(gwi_oper_var(gwi, SZ_INT*2))
GWI_BB(gwi_oper_end(gwi, "@slice", NULL))
- GWI_BB(gwi_oper_add(gwi, opck_array_slice))
GWI_BB(gwi_oper_ini(gwi, "int", (m_str)OP_ANY_TYPE, NULL))
GWI_BB(gwi_oper_add(gwi, opck_not_array))
GWI_BB(gwi_oper_end(gwi, "@array", NULL))
#include "specialid.h"
#include "gack.h"
+#undef insert_symbol
static GACK(gack_class) {
const Type type = actual_type(shred->info->vm->gwion, t) ?: t;
INTERP_PRINTF("class(%s)", type->name)
GWI_BB(gwi_oper_emi(gwi, opem_object_dot))
GWI_BB(gwi_oper_end(gwi, "@dot", NULL))
GWI_BB(gwi_gack(gwi, gwi->gwion->type[et_class], gack_class)) // not working yet
- gwi->gwion->type[et_class] = t_class;
const Type t_undefined = gwi_mk_type(gwi, "@Undefined", SZ_INT, NULL);
GWI_BB(gwi_set_global_type(gwi, t_undefined, et_undefined))
const Type t_auto = gwi_mk_type(gwi, "auto", SZ_INT, NULL);
const Type t_void = gwi_mk_type(gwi, "void", 0, NULL);
GWI_BB(gwi_gack(gwi, t_void, gack_void))
GWI_BB(gwi_set_global_type(gwi, t_void, et_void))
- const Type t_function = gwi_mk_type(gwi, "@function", SZ_INT, NULL);
- GWI_BB(gwi_gack(gwi, t_function, gack_function))
- GWI_BB(gwi_set_global_type(gwi, t_function, et_function))
- const Type t_fptr = gwi_mk_type(gwi, "@func_ptr", SZ_INT, "@function");
- GWI_BB(gwi_gack(gwi, t_fptr, gack_fptr))
- GWI_BB(gwi_set_global_type(gwi, t_fptr, et_fptr))
- const Type t_lambda = gwi_mk_type(gwi, "@lambda", SZ_INT, "@function");
- GWI_BB(gwi_set_global_type(gwi, t_lambda, et_lambda))
const Type t_gack = gwi_mk_type(gwi, "@Gack", SZ_INT, NULL);
GWI_BB(gwi_set_global_type(gwi, t_gack, et_gack))
const Type t_int = gwi_mk_type(gwi, "int", SZ_INT, NULL);
struct SpecialId_ spid = { .type=t_now, .exec=RegPushNow, .is_const=1 };
gwi_specialid(gwi, "now", &spid);
+ GWI_BB(import_object(gwi))
+ GWI_BB(import_prim(gwi))
+ const Type t_function = gwi_mk_type(gwi, "@function", SZ_INT, NULL);
+ GWI_BB(gwi_gack(gwi, t_function, gack_function))
+ GWI_BB(gwi_set_global_type(gwi, t_function, et_function))
+ const Type t_fptr = gwi_mk_type(gwi, "@func_ptr", SZ_INT, "@function");
+ GWI_BB(gwi_gack(gwi, t_fptr, gack_fptr))
+ GWI_BB(gwi_set_global_type(gwi, t_fptr, et_fptr))
+ const Type t_lambda = gwi_mk_type(gwi, "@lambda", SZ_INT, "@function");
+ GWI_BB(gwi_set_global_type(gwi, t_lambda, et_lambda))
GWI_BB(gwi_typedef_ini(gwi, "int", "@internal"))
GWI_BB(gwi_typedef_end(gwi, ae_flag_none))
- GWI_BB(import_object(gwi))
+
+ GWI_BB(import_object_op(gwi))
+ GWI_BB(import_values(gwi))
// TODO: check me
const Type t_union = gwi_class_ini(gwi, "@Union", NULL);
GWI_BB(gwi_oper_add(gwi, opck_new))
GWI_BB(gwi_oper_emi(gwi, opem_new))
GWI_BB(gwi_oper_end(gwi, "new", NULL))
- GWI_BB(import_prim(gwi))
+// GWI_BB(import_prim(gwi))
GWI_BB(import_vararg(gwi))
GWI_BB(import_string(gwi))
GWI_BB(import_shred(gwi))
static INSTR(EventWait) {
POP_REG(shred, SZ_FLOAT);
const M_Object event = *(M_Object*)REG(-SZ_INT);
- if(!event)
- Except(shred, "NullEventWait");
shreduler_remove(shred->tick->shreduler, shred, 0);
const Vector v = EV_SHREDS(event);
vector_add(v, (vtype)shred);
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, "Event", "@now", "int"))
+ GWI_BB(gwi_oper_ini(gwi, "nonnull Event", "@now", "int"))
+ GWI_BB(gwi_oper_var(gwi, -SZ_FLOAT))
_CHECK_OP("=>", eventwait, EventWait)
return GW_OK;
}
mp_free(p, M_Object, o);
}
-#define describe_logical(name, op) \
-static INSTR(name##Object) {\
- POP_REG(shred, SZ_INT); \
- const M_Object lhs = *(M_Object*)REG(-SZ_INT); \
- const M_Object rhs = *(M_Object*)REG(0); \
- *(m_uint*)REG(-SZ_INT) = (lhs op rhs); \
- release(lhs, shred); \
- release(rhs, shred); \
-}
-
-describe_logical(Eq, ==)
-describe_logical(Neq, !=)
-
-static inline m_bool nonnull_check(const Type l, const Type r) {
- return !GET_FLAG(l, nonnull) && GET_FLAG(r, nonnull);
-}
-
-static inline Type check_nonnull(const Env env, const Type l, const Type r,
- const m_str action, const loc_t pos) {
- if(GET_FLAG(r, 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, r) < 0)
- ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name);
- return r->e->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->type;
- const Type r = bin->rhs->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(bin->rhs->exp_type == ae_exp_decl) {
- SET_FLAG(bin->rhs->d.exp_decl.td, ref);
- SET_FLAG(bin->rhs->d.exp_decl.list->self->value, ref);
- }
- bin->rhs->emit_var = 1;
- return r;
-}
-
-static OP_EMIT(opem_at_object) {
- const Exp_Binary* bin = (Exp_Binary*)data;
- const Type l = bin->lhs->type;
- const Type r = bin->rhs->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);
-}
-
-#define STR_FORCE ":force"
-#define STRLEN_FORCE strlen(STR_FORCE)
-
-static inline Type new_force_type(MemPool p, const Type t, const Symbol sym) {
- const Type ret = type_copy(p, t);
- if(ret->nspc)
- ADD_REF(ret->nspc)
- ret->name = s_name(sym);
- ret->flag = t->flag | ae_flag_force;
- nspc_add_type_front(t->e->owner, sym, ret);
- return ret;
- }
-
-static Type get_force_type(const Env env, const Type t) {
- const size_t len = strlen(t->name);
- char name[len + STRLEN_FORCE + 2];
- strcpy(name, t->name);
- strcpy(name + len, STR_FORCE);
- const Symbol sym = insert_symbol(env->gwion->st, name);
- return nspc_lookup_type1(t->e->owner, sym) ?: new_force_type(env->gwion->mp, t, sym);
-}
-
-static OP_CHECK(opck_object_cast) {
- const Exp_Cast* cast = (Exp_Cast*)data;
- const Type l = cast->exp->type;
- const Type r = exp_self(cast)->type;
- if(check_nonnull(env, l, r, "cast", exp_self(cast)->pos) == env->gwion->type[et_null])
- return env->gwion->type[et_null];
- return get_force_type(env, r);
-}
-
-static OP_EMIT(opem_object_cast) {
- const Exp_Cast* cast = (Exp_Cast*)data;
- const Type l = cast->exp->type;
- const Type r = exp_self(cast)->type;
- if(nonnull_check(l, r))
- emit_add_instr(emit, GWOP_EXCEPT);
- return (Instr)GW_OK;
-}
-
-static OP_CHECK(opck_implicit_null2obj) {
- const struct Implicit* imp = (struct Implicit*)data;
- const Type l = imp->e->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];
- imp->e->cast_to = r;
- return imp->t;
-}
-
-static OP_EMIT(opem_implicit_null2obj) {
- const struct Implicit* imp = (struct Implicit*)data;
- const Type l = imp->e->type;
- const Type r = imp->t;
- if(nonnull_check(l, r))
- emit_add_instr(emit, GWOP_EXCEPT);
- 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..."))
INTERP_PRINTF("%p", *(M_Object*)VALUE);
}
-ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td);
-
-static OP_CHECK(opck_object_scan) {
- struct TemplateScan *ts = (struct TemplateScan*)data;
- if(ts->td->types)
- return scan_class(env, ts->t, ts->td);
- ERR_O(td_pos(ts->td), _("you must provide template types for type '%s'"), ts->t->name)
-}
-
-static const f_instr dotstatic[] = { DotStatic, DotStatic2, DotStatic3, RegPushImm };
-ANN Instr emit_kind(Emitter emit, const m_uint size, const uint addr, const f_instr func[]);
-ANN static void emit_dot_static_data(const Emitter emit, const Value v, const uint emit_var) {
- const m_uint size = v->type->size;
- const Instr instr = emit_kind(emit, size, emit_var, dotstatic);
- instr->m_val = (m_uint)(v->from->owner->info->class_data + v->from->offset);
- instr->m_val2 = size;
-}
-
-static const f_instr regpushimm[] = { RegPushImm, RegPushImm2, RegPushImm3, RegPushImm4 };
-ANN static void emit_dot_static_import_data(const Emitter emit, const Value v, const uint emit_addr) {
- if(v->d.ptr && GET_FLAG(v, builtin) && GET_FLAG(v, const)) {
- const m_uint size = v->type->size;
- const Instr instr = emit_kind(emit, size, emit_addr, regpushimm);
- instr->m_val = (m_uint)v->d.ptr;
- instr->m_val2 = size;
- } else
- emit_dot_static_data(emit, v, emit_addr);
-}
-static const f_instr dotmember[] = { DotMember, DotMember2, DotMember3, DotMember4 };
-
-ANN static void emit_member_func(const Emitter emit, const Exp_Dot* member) {
- const Func f = exp_self(member)->type->e->d.func;
- if(is_class(emit->gwion, member->t_base) || GET_FLAG(member->base->type, force)) {
- const Instr func_i = emit_add_instr(emit, f->code ? RegPushImm : PushStaticCode);
- func_i->m_val = (m_uint)f->code;
- return;
- }
- if(f->def->base->tmpl)
- emit_add_instr(emit, DotTmplVal);
- else {
- const Instr instr = emit_add_instr(emit, GET_FLAG(f, member) ? DotFunc : DotStaticFunc);
- instr->m_val = f->vt_index;
- }
- return;
-}
-
-ANN static inline void emit_member(const Emitter emit, const Value v, const uint emit_addr) {
- const m_uint size = v->type->size;
- const Instr instr = emit_kind(emit, size, emit_addr, dotmember);
- instr->m_val = v->from->offset;
- instr->m_val2 = size;
-}
-
-ANN m_bool not_from_owner_class(const Env env, const Type t, const Value v, const loc_t pos);
-OP_CHECK(opck_object_dot) {
- const Exp_Dot *member = (Exp_Dot*)data;
- const m_str str = s_name(member->xid);
- const m_bool base_static = is_class(env->gwion, member->t_base);
- const Type the_base = base_static ? member->t_base->e->d.base_type : member->t_base;
- if(!the_base->nspc)
- ERR_O(member->base->pos,
- _("type '%s' does not have members - invalid use in dot expression of %s"),
- the_base->name, str)
- if(member->xid == insert_symbol(env->gwion->st, "this") && base_static)
- ERR_O(exp_self(member)->pos,
- _("keyword 'this' must be associated with object instance..."))
- const Value value = find_value(the_base, member->xid);
- if(!value) {
- env_err(env, exp_self(member)->pos,
- _("class '%s' has no member '%s'"), the_base->name, str);
- if(member->t_base->nspc)
- did_you_mean_type(the_base, str);
- return NULL;
- }
- CHECK_BO(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) {
- if(GET_FLAG(value, private))
- ERR_O(exp_self(member)->pos,
- _("can't access private '%s' outside of class..."), value->name)
- else if(GET_FLAG(value, protect))
- exp_self(member)->meta = ae_meta_protect;
- }
- if(base_static && GET_FLAG(value, member))
- ERR_O(exp_self(member)->pos,
- _("cannot access member '%s.%s' without object instance..."),
- the_base->name, str)
- if(GET_FLAG(value, const) || GET_FLAG(value, enum))
- exp_self(member)->meta = ae_meta_value;
- return value->type;
-}
-
-OP_EMIT(opem_object_dot) {
- const Exp_Dot *member = (Exp_Dot*)data;
- const Value value = find_value(actual_type(emit->gwion, member->t_base), member->xid);
- if(!is_class(emit->gwion, member->t_base) && (GET_FLAG(value, member) ||
- (isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 &&
- !is_fptr(emit->gwion, exp_self(member)->type)))) {
- CHECK_BO(emit_exp(emit, member->base, 0))
- emit_except(emit, member->t_base);
- }
- if(isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 && !is_fptr(emit->gwion, exp_self(member)->type))
- emit_member_func(emit, member);
- else (GET_FLAG(value, member) ? emit_member : emit_dot_static_import_data)(emit, value, exp_self(member)->emit_var);
- return (Instr)GW_OK;
-}
-
GWION_IMPORT(object) {
const Type t_object = gwi_mk_type(gwi, "Object", SZ_INT, NULL);
gwi_add_type(gwi, t_object);
GWI_BB(gwi_gack(gwi, t_object, gack_object))
SET_FLAG(t_object, checked); // should be set by gwi_add_type
gwi->gwion->type[et_object] = t_object;
-
- const Type t_null = gwi_mk_type(gwi, "@null", SZ_INT, "Object");
- gwi->gwion->type[et_null] = t_null;
- GWI_BB(gwi_set_global_type(gwi, t_null, et_null))
- 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, "@=>", 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", "int"))
- 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", "bool"))
- GWI_BB(gwi_oper_add(gwi, opck_unary_meta2))
- GWI_BB(gwi_oper_end(gwi, "!", IntNot))
- GWI_BB(gwi_oper_ini(gwi, "Object", NULL, NULL))
- GWI_BB(gwi_oper_add(gwi, opck_object_scan))
- GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
- gwi_item_ini(gwi, "@null", "null");
- gwi_item_end(gwi, 0, NULL);
struct SpecialId_ spid = { .ck=check_this, .exec=RegPushMem, .is_const=1 };
gwi_specialid(gwi, "this", &spid);
return GW_OK;
}
-struct tmpl_info {
- const Class_Def cdef;
- Type_List call;
- struct Vector_ type;
- struct Vector_ size;
- uint8_t index;
-};
-
-ANN static inline size_t tmpl_set(struct tmpl_info* info, const Type t) {
- vector_add(&info->type, (vtype)t);
- const size_t len = strlen(t->name);
- vector_add(&info->size, len);
- return len;
-}
-
-ANN static ssize_t template_size(const Env env, struct tmpl_info* info) {
- ID_List base = info->cdef->base.tmpl->list;
- Type_List call = info->call;
- size_t size = tmpl_set(info, info->cdef->base.type);
- do {
- DECL_OB(const Type, t, = known_type(env, call->td))
- size += tmpl_set(info, t);
- } while((call = call->next) && (base = base->next) && ++size);
- return size + 16 + 3;
-}
-
-ANN static inline m_str tmpl_get(struct tmpl_info* info, m_str str) {
- const Type t = (Type)vector_at(&info->type, info->index);
- strcpy(str, t->name);
- return str += vector_at(&info->size, info->index);
-}
-
-ANN static void template_name(struct tmpl_info* info, m_str s) {
- m_str str = s;
- str = tmpl_get(info, str);
- *str++ = '<';
- *str++ = '~';
- const m_uint size = vector_size(&info->type);
- for(info->index = 1; info->index < size; ++info->index) {
- str = tmpl_get(info, str);
- if(info->index < size - 1)
- *str++ = ',';
- else {
- *str++ = '~';
- *str++ = '>';
- }
- }
- *str = '\0';
-}
-
-ANEW ANN static Symbol template_id(const Env env, const Class_Def c, const Type_List call) {
- struct tmpl_info info = { .cdef=c, .call=call };
- vector_init(&info.type);
- vector_init(&info.size);
- ssize_t sz = template_size(env, &info);
- char name[sz];
- if(sz > GW_ERROR)
- template_name(&info, name);
- vector_release(&info.type);
- vector_release(&info.size);
- return sz > GW_ERROR ? insert_symbol(env->gwion->st, name) : NULL;
-}
-
-ANN m_bool template_match(ID_List base, Type_List call) {
- while((call = call->next) && (base = base->next));
- return !call ? GW_OK : GW_ERROR;
-}
-
-ANN static Class_Def template_class(const Env env, const Class_Def def, const Type_List call) {
- DECL_OO(const Symbol, name, = template_id(env, def, call))
- if(env->class_def && name == insert_symbol(env->gwion->st, env->class_def->name))
- return env->class_def->e->def;
- const Type t = nspc_lookup_type1(env->curr, name);
- if(t)
- return t->e->def;
- const Class_Def c = cpy_class_def(env->gwion->mp, def);
- c->base.xid = name;
- SET_FLAG(c, template | ae_flag_ref);
- return c;
-
-}
-
-extern ANN m_bool scan0_class_def(const Env, const Class_Def);
-extern ANN m_bool scan1_class_def(const Env, const Class_Def);
-extern ANN m_bool traverse_func_def(const Env, const Func_Def);
-extern ANN m_bool traverse_class_def(const Env, const Class_Def);
-
-ANN static m_bool class2udef(const Env env, const Class_Def a, const Type t) {
- a->union_def = new_union_def(env->gwion->mp, a->list,
- loc_cpy(env->gwion->mp, t->e->def->pos));
- a->union_def->type_xid = a->base.xid;
- CHECK_BB(scan0_union_def(env, a->union_def))
- SET_FLAG(a, scan0);
- a->base.type = a->union_def->type;
- a->base.type->e->def = a;
- return GW_OK;
-}
-
-ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td) {
- if(template_match(t->e->def->base.tmpl->list, td->types) < 0)
- ERR_O(td->xid->pos, _("invalid template types number"))
- DECL_OO(const Class_Def, a, = template_class(env, t->e->def, td->types))
- if(a->base.type)
- return a->base.type;
- a->base.tmpl = mk_tmpl(env, t->e->def->base.tmpl, td->types);
- if(t->e->parent != env->gwion->type[et_union])
- CHECK_BO(scan0_class_def(env, a))
- else
- CHECK_BO(class2udef(env, a, t))
- SET_FLAG(a->base.type, template);
- if(GET_FLAG(t, builtin))
- SET_FLAG(a->base.type, builtin);
- CHECK_BO(scan1_cdef(env, a))
- return a->base.type;
-}
-
-ANN static inline Symbol dot_symbol(SymTable *st, const Value v) {
- const m_str name = !GET_FLAG(v, static) ? "this" : v->from->owner_class->name;
- return insert_symbol(st, name);
-}
-
-ANN static inline Type dot_type(SymTable *st, const Value v) {
- const Type t = v->from->owner_class;
- if(!GET_FLAG(v, static))
- return t;
- const Value val = nspc_lookup_value1(t->nspc->parent, insert_symbol(st, t->name));
- return val->type;
-}
-
-ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data) {
- const Value v = prim_self(data)->value;
- const Exp base = new_prim_id(gwion->mp, dot_symbol(gwion->st, v), loc_cpy(gwion->mp, prim_pos(data)));
- const Exp dot = new_exp_dot(gwion->mp, base, *data);
- dot->d.exp_dot.t_base = dot->d.exp_dot.base->type = dot_type(gwion->st, v);
- dot->type = prim_exp(data)->type;
- dot->emit_var = prim_exp(data)->emit_var;
- return dot;
-}
--- /dev/null
+#include <stdlib.h>
+#include <string.h>
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "vm.h"
+#include "gwion.h"
+#include "instr.h"
+#include "object.h"
+#include "operator.h"
+#include "import.h"
+#include "emit.h"
+#include "traverse.h"
+#include "template.h"
+#include "parse.h"
+#include "specialid.h"
+
+#include "gwi.h"
+
+#undef insert_symbol
+
+#define describe_logical(name, op) \
+static INSTR(name##Object) {\
+ POP_REG(shred, SZ_INT); \
+ const M_Object lhs = *(M_Object*)REG(-SZ_INT); \
+ const M_Object rhs = *(M_Object*)REG(0); \
+ *(m_uint*)REG(-SZ_INT) = (lhs op rhs); \
+ release(lhs, shred); \
+ release(rhs, shred); \
+}
+
+describe_logical(Eq, ==)
+describe_logical(Neq, !=)
+static inline m_bool nonnull_check(const Type l, const Type r) {
+ return !GET_FLAG(l, nonnull) && GET_FLAG(r, nonnull);
+}
+
+static inline Type check_nonnull(const Env env, const Type l, const Type r,
+ const m_str action, const loc_t pos) {
+ if(GET_FLAG(r, 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, r) < 0)
+ ERR_N(pos, _("can't %s '%s' to '%s'"), action, l->name, r->name);
+ return r->e->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->type;
+ const Type r = bin->rhs->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(bin->rhs->exp_type == ae_exp_decl) {
+ SET_FLAG(bin->rhs->d.exp_decl.td, ref);
+ SET_FLAG(bin->rhs->d.exp_decl.list->self->value, ref);
+ }
+ bin->rhs->emit_var = 1;
+ return r;
+}
+
+static OP_EMIT(opem_at_object) {
+ const Exp_Binary* bin = (Exp_Binary*)data;
+ const Type l = bin->lhs->type;
+ const Type r = bin->rhs->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);
+}
+
+#define STR_FORCE ":force"
+#define STRLEN_FORCE strlen(STR_FORCE)
+
+static inline Type new_force_type(MemPool p, const Type t, const Symbol sym) {
+ const Type ret = type_copy(p, t);
+ if(ret->nspc)
+ ADD_REF(ret->nspc)
+ ret->name = s_name(sym);
+ ret->flag = t->flag | ae_flag_force;
+ nspc_add_type_front(t->e->owner, sym, ret);
+ return ret;
+ }
+
+static Type get_force_type(const Env env, const Type t) {
+ const size_t len = strlen(t->name);
+ char name[len + STRLEN_FORCE + 2];
+ strcpy(name, t->name);
+ strcpy(name + len, STR_FORCE);
+ const Symbol sym = insert_symbol(env->gwion->st, name);
+ return nspc_lookup_type1(t->e->owner, sym) ?: new_force_type(env->gwion->mp, t, sym);
+}
+
+static OP_CHECK(opck_object_cast) {
+ const Exp_Cast* cast = (Exp_Cast*)data;
+ const Type l = cast->exp->type;
+ const Type r = exp_self(cast)->type;
+ if(check_nonnull(env, l, r, "cast", exp_self(cast)->pos) == env->gwion->type[et_null])
+ return env->gwion->type[et_null];
+ return get_force_type(env, r);
+}
+
+static OP_EMIT(opem_object_cast) {
+ const Exp_Cast* cast = (Exp_Cast*)data;
+ const Type l = cast->exp->type;
+ const Type r = exp_self(cast)->type;
+ if(nonnull_check(l, r))
+ emit_add_instr(emit, GWOP_EXCEPT);
+ return (Instr)GW_OK;
+}
+
+static OP_CHECK(opck_implicit_null2obj) {
+ const struct Implicit* imp = (struct Implicit*)data;
+ const Type l = imp->e->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];
+ imp->e->cast_to = r;
+ return imp->t;
+}
+
+static OP_EMIT(opem_implicit_null2obj) {
+ const struct Implicit* imp = (struct Implicit*)data;
+ const Type l = imp->e->type;
+ const Type r = imp->t;
+ if(nonnull_check(l, r))
+ emit_add_instr(emit, GWOP_EXCEPT);
+ return (Instr)GW_OK;
+}
+
+ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td);
+
+OP_CHECK(opck_object_scan) {
+ struct TemplateScan *ts = (struct TemplateScan*)data;
+ if(ts->td->types)
+ return scan_class(env, ts->t, ts->td);
+ if(GET_FLAG(ts->t, unary))
+ return ts->t;
+ ERR_O(td_pos(ts->td), _("you must provide template types for type '%s'"), ts->t->name)
+}
+
+static const f_instr dotstatic[] = { DotStatic, DotStatic2, DotStatic3, RegPushImm };
+ANN Instr emit_kind(Emitter emit, const m_uint size, const uint addr, const f_instr func[]);
+ANN static void emit_dot_static_data(const Emitter emit, const Value v, const uint emit_var) {
+ const m_uint size = v->type->size;
+ const Instr instr = emit_kind(emit, size, emit_var, dotstatic);
+ instr->m_val = (m_uint)(v->from->owner->info->class_data + v->from->offset);
+ instr->m_val2 = size;
+}
+
+static const f_instr regpushimm[] = { RegPushImm, RegPushImm2, RegPushImm3, RegPushImm4 };
+ANN static void emit_dot_static_import_data(const Emitter emit, const Value v, const uint emit_addr) {
+ if(v->d.ptr && GET_FLAG(v, builtin) && GET_FLAG(v, const)) {
+ const m_uint size = v->type->size;
+ const Instr instr = emit_kind(emit, size, emit_addr, regpushimm);
+ instr->m_val = (m_uint)v->d.ptr;
+ instr->m_val2 = size;
+ } else
+ emit_dot_static_data(emit, v, emit_addr);
+}
+static const f_instr dotmember[] = { DotMember, DotMember2, DotMember3, DotMember4 };
+
+ANN static void emit_member_func(const Emitter emit, const Exp_Dot* member) {
+ const Func f = exp_self(member)->type->e->d.func;
+ if(is_class(emit->gwion, member->t_base) || GET_FLAG(member->base->type, force)) {
+ const Instr func_i = emit_add_instr(emit, f->code ? RegPushImm : PushStaticCode);
+ func_i->m_val = (m_uint)f->code;
+ return;
+ }
+ if(f->def->base->tmpl)
+ emit_add_instr(emit, DotTmplVal);
+ else {
+ const Instr instr = emit_add_instr(emit, GET_FLAG(f, member) ? DotFunc : DotStaticFunc);
+ instr->m_val = f->vt_index;
+ }
+ return;
+}
+
+ANN static inline void emit_member(const Emitter emit, const Value v, const uint emit_addr) {
+ const m_uint size = v->type->size;
+ const Instr instr = emit_kind(emit, size, emit_addr, dotmember);
+ instr->m_val = v->from->offset;
+ instr->m_val2 = size;
+}
+
+ANN m_bool not_from_owner_class(const Env env, const Type t, const Value v, const loc_t pos);
+OP_CHECK(opck_object_dot) {
+ const Exp_Dot *member = (Exp_Dot*)data;
+ const m_str str = s_name(member->xid);
+ const m_bool base_static = is_class(env->gwion, member->t_base);
+ const Type the_base = base_static ? member->t_base->e->d.base_type : member->t_base;
+ if(!the_base->nspc)
+ ERR_O(member->base->pos,
+ _("type '%s' does not have members - invalid use in dot expression of %s"),
+ the_base->name, str)
+ if(member->xid == insert_symbol(env->gwion->st, "this") && base_static)
+ ERR_O(exp_self(member)->pos,
+ _("keyword 'this' must be associated with object instance..."))
+ const Value value = find_value(the_base, member->xid);
+ if(!value) {
+ env_err(env, exp_self(member)->pos,
+ _("class '%s' has no member '%s'"), the_base->name, str);
+ if(member->t_base->nspc)
+ did_you_mean_type(the_base, str);
+ return NULL;
+ }
+ CHECK_BO(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) {
+ if(GET_FLAG(value, private))
+ ERR_O(exp_self(member)->pos,
+ _("can't access private '%s' outside of class..."), value->name)
+ else if(GET_FLAG(value, protect))
+ exp_self(member)->meta = ae_meta_protect;
+ }
+ if(base_static && GET_FLAG(value, member))
+ ERR_O(exp_self(member)->pos,
+ _("cannot access member '%s.%s' without object instance..."),
+ the_base->name, str)
+ if(GET_FLAG(value, const) || GET_FLAG(value, enum))
+ exp_self(member)->meta = ae_meta_value;
+ return value->type;
+}
+
+OP_EMIT(opem_object_dot) {
+ const Exp_Dot *member = (Exp_Dot*)data;
+ const Value value = find_value(actual_type(emit->gwion, member->t_base), member->xid);
+ if(!is_class(emit->gwion, member->t_base) && (GET_FLAG(value, member) ||
+ (isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 &&
+ !is_fptr(emit->gwion, exp_self(member)->type)))) {
+ CHECK_BO(emit_exp(emit, member->base, 0))
+ emit_except(emit, member->t_base);
+ }
+ if(isa(exp_self(member)->type, emit->gwion->type[et_function]) > 0 && !is_fptr(emit->gwion, exp_self(member)->type))
+ emit_member_func(emit, member);
+ else (GET_FLAG(value, member) ? emit_member : emit_dot_static_import_data)(emit, value, exp_self(member)->emit_var);
+ return (Instr)GW_OK;
+}
+
+struct tmpl_info {
+ const Class_Def cdef;
+ Type_List call;
+ struct Vector_ type;
+ struct Vector_ size;
+ uint8_t index;
+};
+
+ANN static inline size_t tmpl_set(struct tmpl_info* info, const Type t) {
+ vector_add(&info->type, (vtype)t);
+ const size_t len = strlen(t->name);
+ vector_add(&info->size, len);
+ return len;
+}
+
+ANN static ssize_t template_size(const Env env, struct tmpl_info* info) {
+ ID_List base = info->cdef->base.tmpl->list;
+ Type_List call = info->call;
+ size_t size = tmpl_set(info, info->cdef->base.type);
+ do {
+ DECL_OB(const Type, t, = known_type(env, call->td))
+ size += tmpl_set(info, t);
+ } while((call = call->next) && (base = base->next) && ++size);
+ return size + 16 + 3;
+}
+
+ANN static inline m_str tmpl_get(struct tmpl_info* info, m_str str) {
+ const Type t = (Type)vector_at(&info->type, info->index);
+ strcpy(str, t->name);
+ return str += vector_at(&info->size, info->index);
+}
+
+ANN static void template_name(struct tmpl_info* info, m_str s) {
+ m_str str = s;
+ str = tmpl_get(info, str);
+ *str++ = '<';
+ *str++ = '~';
+ const m_uint size = vector_size(&info->type);
+ for(info->index = 1; info->index < size; ++info->index) {
+ str = tmpl_get(info, str);
+ if(info->index < size - 1)
+ *str++ = ',';
+ else {
+ *str++ = '~';
+ *str++ = '>';
+ }
+ }
+ *str = '\0';
+}
+
+ANEW ANN static Symbol template_id(const Env env, const Class_Def c, const Type_List call) {
+ struct tmpl_info info = { .cdef=c, .call=call };
+ vector_init(&info.type);
+ vector_init(&info.size);
+ ssize_t sz = template_size(env, &info);
+ char name[sz];
+ if(sz > GW_ERROR)
+ template_name(&info, name);
+ vector_release(&info.type);
+ vector_release(&info.size);
+ return sz > GW_ERROR ? insert_symbol(env->gwion->st, name) : NULL;
+}
+
+ANN m_bool template_match(ID_List base, Type_List call) {
+ while((call = call->next) && (base = base->next));
+ return !call ? GW_OK : GW_ERROR;
+}
+
+ANN static Class_Def template_class(const Env env, const Class_Def def, const Type_List call) {
+ DECL_OO(const Symbol, name, = template_id(env, def, call))
+ if(env->class_def && name == insert_symbol(env->gwion->st, env->class_def->name))
+ return env->class_def->e->def;
+ const Type t = nspc_lookup_type1(env->curr, name);
+ if(t)
+ return t->e->def;
+ const Class_Def c = cpy_class_def(env->gwion->mp, def);
+ c->base.xid = name;
+ SET_FLAG(c, template | ae_flag_ref);
+ return c;
+
+}
+
+extern ANN m_bool scan0_class_def(const Env, const Class_Def);
+extern ANN m_bool scan1_class_def(const Env, const Class_Def);
+extern ANN m_bool traverse_func_def(const Env, const Func_Def);
+extern ANN m_bool traverse_class_def(const Env, const Class_Def);
+
+ANN static m_bool class2udef(const Env env, const Class_Def a, const Type t) {
+ a->union_def = new_union_def(env->gwion->mp, a->list,
+ loc_cpy(env->gwion->mp, t->e->def->pos));
+ a->union_def->type_xid = a->base.xid;
+ CHECK_BB(scan0_union_def(env, a->union_def))
+ SET_FLAG(a, scan0);
+ a->base.type = a->union_def->type;
+ a->base.type->e->def = a;
+ return GW_OK;
+}
+
+ANN static Type scan_class(const Env env, const Type t, const Type_Decl* td) {
+ if(template_match(t->e->def->base.tmpl->list, td->types) < 0)
+ ERR_O(td->xid->pos, _("invalid template types number"))
+ DECL_OO(const Class_Def, a, = template_class(env, t->e->def, td->types))
+ if(a->base.type)
+ return a->base.type;
+ a->base.tmpl = mk_tmpl(env, t->e->def->base.tmpl, td->types);
+ if(t->e->parent != env->gwion->type[et_union])
+ CHECK_BO(scan0_class_def(env, a))
+ else
+ CHECK_BO(class2udef(env, a, t))
+ SET_FLAG(a->base.type, template);
+ if(GET_FLAG(t, builtin))
+ SET_FLAG(a->base.type, builtin);
+ CHECK_BO(scan1_cdef(env, a))
+ return a->base.type;
+}
+
+ANN static inline Symbol dot_symbol(SymTable *st, const Value v) {
+ const m_str name = !GET_FLAG(v, static) ? "this" : v->from->owner_class->name;
+ return insert_symbol(st, name);
+}
+
+ANN static inline Type dot_type(SymTable *st, const Value v) {
+ const Type t = v->from->owner_class;
+ if(!GET_FLAG(v, static))
+ return t;
+ const Value val = nspc_lookup_value1(t->nspc->parent, insert_symbol(st, t->name));
+ return val->type;
+}
+
+ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data) {
+ const Value v = prim_self(data)->value;
+ const Exp base = new_prim_id(gwion->mp, dot_symbol(gwion->st, v), loc_cpy(gwion->mp, prim_pos(data)));
+ const Exp dot = new_exp_dot(gwion->mp, base, *data);
+ dot->d.exp_dot.t_base = dot->d.exp_dot.base->type = dot_type(gwion->st, v);
+ dot->type = prim_exp(data)->type;
+ dot->emit_var = prim_exp(data)->emit_var;
+ return dot;
+}
+
+GWION_IMPORT(object_op) {
+ const Type t_null = gwi_mk_type(gwi, "@null", SZ_INT, "Object");
+ gwi->gwion->type[et_null] = t_null;
+ GWI_BB(gwi_set_global_type(gwi, t_null, et_null))
+ 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, "@=>", 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", "int"))
+ 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", "bool"))
+ GWI_BB(gwi_oper_add(gwi, opck_unary_meta2))
+ GWI_BB(gwi_oper_end(gwi, "!", IntNot))
+ GWI_BB(gwi_oper_ini(gwi, "Object", NULL, NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_object_scan))
+ GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
+ gwi_item_ini(gwi, "@null", "null");
+ gwi_item_end(gwi, 0, NULL);
+ return GW_OK;
+}
}
static GWION_IMPORT(int) {
+ GWI_BB(import_int_values(gwi))
GWI_BB(gwi_oper_cond(gwi, "int", BranchEqInt, BranchNeqInt))
GWI_BB(gwi_oper_ini(gwi, "int", "int", "int"))
GWI_BB(import_int_op(gwi))
GWI_BB(import_int_logical(gwi))
GWI_BB(import_int_r(gwi))
GWI_BB(import_int_unary(gwi))
- return import_int_values(gwi);
-}
-
-static GWION_IMPORT(values) {
- VM* vm = gwi_vm(gwi);
- ALLOC_PTR(gwi->gwion->mp, d_zero, m_float, 0.0);
- ALLOC_PTR(gwi->gwion->mp, sr, m_float, (m_float)vm->bbq->si->sr);
- ALLOC_PTR(gwi->gwion->mp, samp, m_float, 1.0);
- ALLOC_PTR(gwi->gwion->mp, ms, m_float, (m_float)(*sr / 1000.));
- ALLOC_PTR(gwi->gwion->mp, second, m_float, (m_float)*sr);
- ALLOC_PTR(gwi->gwion->mp, minute, m_float, (m_float)(*sr * 60.0));
- ALLOC_PTR(gwi->gwion->mp, hour, m_float, (m_float)(*minute * 60.0));
- ALLOC_PTR(gwi->gwion->mp, t_zero, m_float, 0.0);
- ALLOC_PTR(gwi->gwion->mp, pi, m_float, (m_float)M_PI);
- gwi_item_ini(gwi, "float", "samplerate");
- gwi_item_end(gwi, ae_flag_const, sr);
- gwi_item_ini(gwi, "float", "pi");
- gwi_item_end(gwi, ae_flag_const, pi);
- gwi_item_ini(gwi, "dur", "d_zero");
- gwi_item_end(gwi, ae_flag_const, d_zero);
- gwi_item_ini(gwi, "dur", "samp");
- gwi_item_end(gwi, ae_flag_const, samp);
- gwi_item_ini(gwi, "dur", "ms");
- gwi_item_end(gwi, ae_flag_const, ms);
- gwi_item_ini(gwi, "dur", "second");
- gwi_item_end(gwi, ae_flag_const, second);
- gwi_item_ini(gwi, "dur", "minute");
- gwi_item_end(gwi, ae_flag_const, minute);
- gwi_item_ini(gwi, "dur", "hour");
- gwi_item_end(gwi, ae_flag_const, hour);
- gwi_item_ini(gwi, "time", "t_zero");
- gwi_item_end(gwi, ae_flag_const, t_zero);
return GW_OK;
}
GWI_BB(import_intfloat(gwi))
GWI_BB(import_floatint(gwi))
GWI_BB(import_dur(gwi))
- GWI_BB(import_time(gwi))
- return import_values(gwi);
+ return import_time(gwi);
}
--- /dev/null
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "vm.h"
+#include "gwion.h"
+#include "instr.h"
+#include "object.h"
+#include "emit.h"
+#include "operator.h"
+#include "import.h"
+#include "gwi.h"
+#include "driver.h"
+#include "traverse.h"
+#include "parse.h"
+#include "specialid.h"
+#include "array.h"
+#include "gack.h"
+
+GWION_IMPORT(values) {
+ VM* vm = gwi_vm(gwi);
+ ALLOC_PTR(gwi->gwion->mp, d_zero, m_float, 0.0);
+ ALLOC_PTR(gwi->gwion->mp, sr, m_float, (m_float)vm->bbq->si->sr);
+ ALLOC_PTR(gwi->gwion->mp, samp, m_float, 1.0);
+ ALLOC_PTR(gwi->gwion->mp, ms, m_float, (m_float)(*sr / 1000.));
+ ALLOC_PTR(gwi->gwion->mp, second, m_float, (m_float)*sr);
+ ALLOC_PTR(gwi->gwion->mp, minute, m_float, (m_float)(*sr * 60.0));
+ ALLOC_PTR(gwi->gwion->mp, hour, m_float, (m_float)(*minute * 60.0));
+ ALLOC_PTR(gwi->gwion->mp, t_zero, m_float, 0.0);
+ ALLOC_PTR(gwi->gwion->mp, pi, m_float, (m_float)M_PI);
+ gwi_item_ini(gwi, "float", "samplerate");
+ gwi_item_end(gwi, ae_flag_const, sr);
+ gwi_item_ini(gwi, "float", "pi");
+ gwi_item_end(gwi, ae_flag_const, pi);
+ gwi_item_ini(gwi, "dur", "d_zero");
+ gwi_item_end(gwi, ae_flag_const, d_zero);
+ gwi_item_ini(gwi, "dur", "samp");
+ gwi_item_end(gwi, ae_flag_const, samp);
+ gwi_item_ini(gwi, "dur", "ms");
+ gwi_item_end(gwi, ae_flag_const, ms);
+ gwi_item_ini(gwi, "dur", "second");
+ gwi_item_end(gwi, ae_flag_const, second);
+ gwi_item_ini(gwi, "dur", "minute");
+ gwi_item_end(gwi, ae_flag_const, minute);
+ gwi_item_ini(gwi, "dur", "hour");
+ gwi_item_end(gwi, ae_flag_const, hour);
+ gwi_item_ini(gwi, "time", "t_zero");
+ gwi_item_end(gwi, ae_flag_const, t_zero);
+ return GW_OK;
+}
ERR_N(exp_self(bin)->pos, _("left side operand is constant"));
bin->lhs->emit_var = 1;
Type t = bin->lhs->type;
- do if(!strcmp(t->name, get_type_name(env, bin->rhs->type->name, 1)))
- return bin->lhs->type;
- while((t = t->e->parent));
+ do {
+ Type u = bin->rhs->type;
+ do {
+ const m_str str = get_type_name(env, u->name, 1);
+ if(str && !strcmp(t->name, str))
+ return bin->lhs->type;
+ } while((u = u->e->parent));
+ } while((t = t->e->parent));
return env->gwion->type[et_null];
}
*(m_uint**)o->data = *(m_uint**)REG(-SZ_INT);
}
-static OP_EMIT(opem_ptr_assign) {
- const Exp_Binary* bin = (Exp_Binary*)data;
- if(!GET_FLAG(bin->rhs->type, nonnull))
- emit_add_instr(emit, GWOP_EXCEPT);
- return emit_add_instr(emit, instr_ptr_assign);
-}
-
static OP_CHECK(opck_ptr_deref) {
const Exp_Unary* unary = (Exp_Unary*)data;
- return exp_self(unary)->type = nspc_lookup_type1(env->curr, insert_symbol(get_type_name(env, unary->exp->type->name, 1)));
+ DECL_ON(const m_str, str, = get_type_name(env, unary->exp->type->name, 1))
+ return exp_self(unary)->type = nspc_lookup_type1(env->curr, insert_symbol(str));
}
static OP_CHECK(opck_ptr_cast) {
const Exp_Cast* cast = (Exp_Cast*)data;
DECL_ON(const Type, t, = type_decl_resolve(env, cast->td))
- if(!GET_FLAG(t, check)) {
- assert(t->e->def);
+ if(!GET_FLAG(t, check))
CHECK_BN(traverse_class_def(env, t->e->def))
- }
const Type to = known_type(env, cast->td->types->td);
if(isa(cast->exp->type, to) > 0)
return t;
ERR_N(exp_self(cast)->pos, "invalid pointer cast")
}
-static OP_CHECK(opck_implicit_ptr) {
+static OP_CHECK(opck_ptr_implicit) {
const struct Implicit* imp = (struct Implicit*)data;
const Exp e = imp->e;
if(!strcmp(get_type_name(env, imp->t->name, 1), e->type->name)) {
ERR_N(e->pos, _("can't cast constant to Ptr"));
e->cast_to = imp->t;
e->emit_var = 1;
+ if(!GET_FLAG(imp->t, check))
+ CHECK_BN(traverse_class_def(env, imp->t->e->def))
return imp->t;
}
return NULL;
}
static INSTR(Cast2Ptr) {
- const M_Object o = new_object(shred->info->mp, shred, shred->info->vm->gwion->type[et_ptr]);
+ const M_Object o = new_object(shred->info->mp, shred, (Type)instr->m_val);
*(m_uint**)o->data = *(m_uint**)REG(-SZ_INT);
*(M_Object*)REG(-SZ_INT) = o;
}
-/*
+
static OP_EMIT(opem_ptr_cast) {
const Exp_Cast* cast = (Exp_Cast*)data;
const Instr instr = emit_add_instr(emit, Cast2Ptr);
instr->m_val = (m_uint)exp_self(cast)->type;
- return GW_OK;
+ return instr;
}
-*/
+
+static OP_EMIT(opem_ptr_implicit) {
+ const struct Implicit* imp = (struct Implicit*)data;
+ const Instr instr = emit_add_instr(emit, Cast2Ptr);
+ instr->m_val = (m_uint)imp->t;
+ return instr;
+}
+
static OP_EMIT(opem_ptr_deref) {
const Exp_Unary* unary = (Exp_Unary*)data;
const Instr instr = emit_add_instr(emit, instr_ptr_deref);
GWI_BB(gwi_item_ini(gwi, "@internal", "@val"))
GWI_BB(gwi_item_end(gwi, 0, NULL))
GWI_BB(gwi_class_end(gwi))
- t_ptr->nspc->info->offset = SZ_INT;
- GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "Ptr", NULL))
+ SET_FLAG(t_ptr, unary);
+ GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "nonnull Ptr", NULL))
GWI_BB(gwi_oper_add(gwi, opck_ptr_assign))
- GWI_BB(gwi_oper_emi(gwi, opem_ptr_assign))
GWI_BB(gwi_oper_end(gwi, ":=>", instr_ptr_assign))
- GWI_BB(gwi_oper_add(gwi, opck_implicit_ptr))
+ GWI_BB(gwi_oper_add(gwi, opck_ptr_implicit))
+ GWI_BB(gwi_oper_emi(gwi, opem_ptr_implicit))
GWI_BB(gwi_oper_end(gwi, "@implicit", Cast2Ptr))
- GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, "Ptr", NULL))
GWI_BB(gwi_oper_add(gwi, opck_ptr_cast))
+ GWI_BB(gwi_oper_emi(gwi, opem_ptr_cast))
GWI_BB(gwi_oper_end(gwi, "$", Cast2Ptr))
- GWI_BB(gwi_oper_ini(gwi, NULL, "Ptr", NULL))
+ GWI_BB(gwi_oper_ini(gwi, NULL, "nonnull Ptr", NULL))
GWI_BB(gwi_oper_add(gwi, opck_ptr_deref))
GWI_BB(gwi_oper_emi(gwi, opem_ptr_deref))
GWI_BB(gwi_oper_end(gwi, "*", instr_ptr_deref))
"%p%s", (void*)lhs, rhs ? STRING(rhs) : "")
-#define describe_string_plus(name, offset, type, opt, len, format, ...) \
-static INSTR(name##String_Plus) {\
- POP_REG(shred, offset); \
- const type lhs = *(type*)REG(-SZ_INT); \
- const M_Object rhs = *(M_Object*)REG(offset - SZ_INT); \
- opt; \
- if(!rhs) \
- Except(shred, "NullPtrException"); \
- char c[strlen(STRING(rhs)) + (len) + 1]; \
- sprintf(c, "%s"format, STRING(rhs), __VA_ARGS__); \
- push_string(shred, rhs, c); \
+#define describe_string_plus(_name, offset, type, opt, len, format, ...) \
+static INSTR(_name##String_Plus) { \
+ POP_REG(shred, offset); \
+ const type lhs = *(type*)REG(-SZ_INT); \
+ const M_Object rhs = *(M_Object*)REG(offset - SZ_INT); \
+ opt; \
+ if(!rhs) \
+ Except(shred, "NullPtrException"); \
+ char c[strlen(STRING(rhs)) + (len) + 1]; \
+ sprintf(c, "%s"format, STRING(rhs), __VA_ARGS__); \
+ push_string(shred, rhs, c); \
}
describe_string_plus(,SZ_INT, M_Object, release(lhs, shred),
lhs ? strlen(STRING(lhs)) : 0, "%s", lhs ? STRING(lhs) : "")
}
}
-ANN static m_bool connect_init(const VM_Shred shred, restrict M_Object* lhs, restrict M_Object* rhs) {
+ANN void connect_init(const VM_Shred shred, restrict M_Object* lhs, restrict M_Object* rhs) {
POP_REG(shred, SZ_INT * 2);
*rhs = *(M_Object*)REG(SZ_INT);
*lhs = *(M_Object*)REG(0);
- if(!*lhs) {
- if(*rhs)
- _release(*rhs, shred);
- goto end;
- }
- if(!*rhs) {
- _release(*lhs, shred);
- goto end;
- }
- return GW_OK;
-end:
- exception(shred, "UgenConnectException");
- return GW_ERROR;
}
#define describe_connect(name, func) \
Except(shred, "NonTriggerException"); \
}
#define describe_connect_instr(name, func, opt) \
-static INSTR(name##func) {\
+static INSTR(name##func) { \
M_Object lhs, rhs; \
- if(connect_init(shred, &lhs, &rhs) > 0) { \
- opt \
- _do_(func, UGEN(lhs), UGEN(rhs)); /*}*/ \
- release_connect(shred); } \
+ connect_init(shred, &lhs, &rhs); \
+ opt \
+ _do_(func, UGEN(lhs), UGEN(rhs)); \
+ release_connect(shred); \
}
describe_connect_instr(Ugen, Connect,)
describe_connect_instr(Ugen, Disconnect,)
GWI_BB(gwi_func_end(gwi, ugen_get_last, ae_flag_none))
GWI_BB(gwi_class_end(gwi))
- GWI_BB(gwi_oper_ini(gwi, "UGen", "UGen", "UGen"))
+ GWI_BB(gwi_oper_ini(gwi, "nonnull UGen", "nonnull UGen", "nonnull UGen"))
_CHECK_OP("=>", chuck_ugen, UgenConnect)
_CHECK_OP("=<", chuck_ugen, UgenDisconnect)
_CHECK_OP(":=>", chuck_ugen, TrigConnect)
void free_vararg(MemPool p, struct Vararg_* arg) {
xfree(arg->d);
- xfree(arg->t);
+ vector_release(&arg->t);
mp_free(p, Vararg, arg);
}
+static DTOR(vararg_dtor) {
+ struct Vararg_ *arg = *(struct Vararg_**)o->data;
+ m_uint offset = 0;
+ for(m_uint i = 0; i < vector_size(&arg->t); ++i) {
+ const Type t = (Type)vector_at(&arg->t, arg->i);
+ *(m_uint*)(arg->d + offset) = *(m_uint*)(shred->reg - SZ_INT + offset);
+ if(isa(t, shred->info->vm->gwion->type[et_object]) > 0)
+ release(*(M_Object*)(arg->d + offset), shred);
+ offset += t->size;
+ }
+ free_vararg(shred->info->vm->gwion->mp, arg);
+}
+
+ANN static M_Object vararg_cpy(VM_Shred shred, struct Vararg_* src) {
+ const M_Object o = new_object(shred->info->mp, shred, shred->info->vm->gwion->type[et_vararg]);
+ struct Vararg_* arg = mp_calloc(shred->info->mp, Vararg);
+ vector_copy2(&src->t, &arg->t);
+ arg->l = src->l;
+ arg->d = (m_bit*)xmalloc(round2szint(arg->l));
+ m_uint offset = 0;
+ for(m_uint i = 0; i < vector_size(&arg->t); ++i) {
+ const Type t = (Type)vector_at(&arg->t, arg->i);
+ *(m_uint*)(arg->d + offset) = *(m_uint*)(src->d + offset);
+ if(isa(t, shred->info->vm->gwion->type[et_object]) > 0)
+ ++(*(M_Object*)(arg->d + offset))->ref;
+ offset += t->size;
+ }
+ arg->s = vector_size(&arg->t);
+ arg->i = src->i;
+ arg->o = src->o;
+ *(struct Vararg_**)o->data = arg;
+ return o;
+}
+
+static MFUN(mfun_vararg_cpy) {
+ *(M_Object*)RETURN = vararg_cpy(shred, *(struct Vararg_**)o->data);
+}
+
INSTR(VarargIni) {
+ const M_Object o = new_object(shred->info->mp, shred, shred->info->vm->gwion->type[et_vararg]);
struct Vararg_* arg = mp_calloc(shred->info->mp, Vararg);
POP_REG(shred, instr->m_val - SZ_INT)
- arg->d = (m_bit*)xmalloc(round2szint(instr->m_val));
- for(m_uint i = 0; i < instr->m_val; i += SZ_INT)
- *(m_uint*)(arg->d + i) = *(m_uint*)(shred->reg - SZ_INT + i);
+ arg->l = instr->m_val;
+ arg->d = (m_bit*)xmalloc(round2szint(arg->l));
const Vector kinds = (Vector)instr->m_val2;
- arg->s = vector_size(kinds);
- arg->t = (Type*)xmalloc(arg->s * SZ_INT);
- for(m_uint i = 0; i < arg->s; ++i) {
- const Type t = (Type)vector_at(kinds, i);
- *(Type*)(arg->t + i) = t;
+ vector_copy2(kinds, &arg->t);
+ m_uint offset = 0;
+ for(m_uint i = 0; i < vector_size(&arg->t); ++i) {
+ const Type t = (Type)vector_at(&arg->t, arg->i);
+ *(m_uint*)(arg->d + offset) = *(m_uint*)(shred->reg - SZ_INT + offset);
+ if(isa(t, shred->info->vm->gwion->type[et_object]) > 0)
+ ++(*(M_Object*)(arg->d + offset))->ref;
+ offset += t->size;
}
- *(struct Vararg_**)REG(-SZ_INT) = arg;
+ arg->s = vector_size(kinds);
+ *(struct Vararg_**)o->data = arg;
+ *(M_Object*)REG(-SZ_INT) = o;
}
static INSTR(VarargEnd) {
- struct Vararg_* arg = *(struct Vararg_**)REG(0);
- arg->o += arg->t[arg->i]->size;
+ const M_Object o = *(M_Object*)REG(0);
+ struct Vararg_* arg = *(struct Vararg_**)o->data;
+ arg->o += ((Type)vector_at(&arg->t, arg->i))->size;
if(++arg->i < arg->s)
shred->pc = instr->m_val;
else
- free_vararg(shred->info->mp, arg);
+ arg->i = arg->o = 0;
}
static OP_CHECK(opck_vararg_cast) {
return known_type(env, cast->td);
}
+static OP_CHECK(opck_vararg_at) {
+ return env->gwion->type[et_null];
+}
+
static INSTR(VarargCast) {
- struct Vararg_* arg = *(struct Vararg_**)REG(-SZ_INT);
- const Type t = (Type)instr->m_val2;
- if(isa(arg->t[arg->i], t) < 0){
- free_vararg(shred->info->mp, arg);
+ const M_Object o = *(M_Object*)REG(-SZ_INT);
+ if(!*(m_uint*)(o->data + SZ_INT))
+ Except(shred, "Using Vararg outside varloop");
+ struct Vararg_* arg = *(struct Vararg_**)o->data;
+ const Type t = (Type)instr->m_val;
+ if(isa((Type)vector_at(&arg->t, arg->i), t) < 0)
Except(shred, "InvalidVariadicAccess");
- }
for(m_uint i = 0; i < t->size; i += SZ_INT)
- *(m_uint*)REG(i - SZ_INT*2) = *(m_uint*)(arg->d + arg->o + i);
-}
-
-ANN static inline Instr get_variadic(const Emitter emit) {
- return (Instr)vector_back(&emit->info->variadic);
-}
-
-ANN m_bool variadic_check(const Emitter emit, const loc_t pos) {
- const Env env = emit->env;
- if(!get_variadic(emit))
- ERR_B(pos, _("vararg.xxx used before vararg.start"))
- if(GET_FLAG(emit->env->func, empty))
- ERR_B(pos, _("vararg.xxx used after vararg.end"))
- return GW_OK;
+ *(m_uint*)REG(i - SZ_INT) = *(m_uint*)(arg->d + arg->o + i);
}
static OP_EMIT(opem_vararg_cast) {
const Exp_Cast* cast = (Exp_Cast*)data;
- CHECK_BO(variadic_check(emit, cast->exp->pos))
- CHECK_BO(emit_exp(emit, cast->exp, 0))
const Instr instr = emit_add_instr(emit, VarargCast);
- instr->m_val = get_variadic(emit)->m_val;
- instr->m_val2 = (m_uint)exp_self(cast)->type;
- const Instr pop = emit_add_instr(emit, RegPush);
- pop->m_val = exp_self(cast)->type->size - SZ_INT *2;
+ instr->m_val = (m_uint)exp_self(cast)->type;
+ const Instr push = emit_add_instr(emit, RegPush);
+ push->m_val = exp_self(cast)->type->size - SZ_INT;
return instr;
}
static ID_CHECK(idck_vararg) {
if(env->func && GET_FLAG(env->func->def, variadic))
- return exp_self(prim)->type;
+ return type_nonnull(env, exp_self(prim)->type);
ERR_O(exp_self(prim)->pos, _("'vararg' must be used inside variadic function"))
}
INTERP_PRINTF("%p", *(M_Object*)VALUE);
}
-ANN static inline m_uint emit_code_size(const Emitter emit) {
- return vector_size(&emit->code->instr);
-}
-ANN static m_bool emit_vararg_start(const Emitter emit, const m_uint offset) {
- const Instr instr = emit_add_instr(emit, BranchEqInt);
- instr->m_val = emit_code_size(emit);
- vector_set(&emit->info->variadic, vector_size(&emit->info->variadic) -1, (vtype)instr);
- return GW_OK;
-}
-
-ANN static void emit_vararg_end(const Emitter emit, const m_uint offset) {
+ANN void emit_vararg_end(const Emitter emit, const m_uint pc) {
const Instr pop = emit_add_instr(emit, RegPop);
pop->m_val = SZ_INT;
- const Instr instr = emit_add_instr(emit, VarargEnd),
- variadic = get_variadic(emit);
- instr->m_val = variadic->m_val;
- variadic->m_val = emit_code_size(emit);
- SET_FLAG(emit->env->func, empty);// mark vararg func as complete
-}
-
-static OP_CHECK(opck_vararg_dot) {
- const Exp_Dot *member = (Exp_Dot*)data;
- const m_str str = s_name(member->xid);
- if(!strcmp(str, "start") || !strcmp(str, "end"))
- return env->gwion->type[et_varloop];
- ERR_O(exp_self(member)->pos, _("'%s' is not a vararg keyword."), str)
-}
-
-static OP_EMIT(opem_vararg_dot) {
- const Env env = emit->env;
- const Exp_Dot *member = (Exp_Dot*)data;
- const m_str str = s_name(member->xid);
- const m_uint offset = emit->code->stack_depth - SZ_INT;
- CHECK_BO(emit_exp(emit, member->base, 0))
- if(str[0] == 's') {
- if(get_variadic(emit))
- ERR_O(exp_self(member)->pos, _("vararg.start already used"))
- emit_vararg_start(emit, offset);
- return (Instr)GW_OK;
- }
- if(!get_variadic(emit))
- ERR_O(exp_self(member)->pos, _("vararg.start not used before vararg.end"))
- emit_vararg_end(emit, offset);
- return (Instr)GW_OK;
+ const Instr instr = emit_add_instr(emit, VarargEnd);
+ instr->m_val = pc;
}
-OP_CHECK(opck_object_dot);
GWION_IMPORT(vararg) {
- const Type t_varloop = gwi_mk_type(gwi, "@VarLoop", 0, NULL);
- GWI_BB(gwi_set_global_type(gwi, t_varloop, et_varloop))
- const Type t_vararg = gwi_mk_type(gwi, "@Vararg", SZ_INT, NULL);
+ const Type t_vararg = gwi_class_ini(gwi, "Vararg", "Object");
+ gwi_class_xtor(gwi, NULL, vararg_dtor);
gwi_gack(gwi, t_vararg, gack_vararg);
-// gwi_gack(gwi, t_varloop, gack_vararg);// ????
- GWI_BB(gwi_add_type(gwi, t_vararg))
- GWI_BB(gwi_oper_ini(gwi, "@Vararg", (m_str)OP_ANY_TYPE, NULL))
- GWI_BB(gwi_oper_add(gwi, opck_vararg_dot))
- GWI_BB(gwi_oper_emi(gwi, opem_vararg_dot))
- GWI_BB(gwi_oper_end(gwi, "@dot", NULL))
+ CHECK_BB(gwi_item_ini(gwi, "@internal", "@data"))
+ CHECK_BB(gwi_item_end(gwi, ae_flag_none, NULL))
+ CHECK_BB(gwi_item_ini(gwi, "int", "@inLoop"))
+ CHECK_BB(gwi_item_end(gwi, ae_flag_none, NULL))
+ CHECK_BB(gwi_func_ini(gwi, "Vararg", "cpy"))
+ CHECK_BB(gwi_func_end(gwi, mfun_vararg_cpy, ae_flag_none))
+ GWI_BB(gwi_class_end(gwi))
+ SET_FLAG(t_vararg, abstract | ae_flag_const);
+ CHECK_BB(gwi_set_global_type(gwi, t_vararg, et_vararg))
+ GWI_BB(gwi_oper_ini(gwi, "nonnull 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))
+ GWI_BB(gwi_oper_ini(gwi, "Vararg", (m_str)OP_ANY_TYPE, NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_vararg_at))
+ GWI_BB(gwi_oper_end(gwi, "@=>", NULL))
gwi_register_freearg(gwi, VarargIni, freearg_vararg);
struct SpecialId_ spid = { .type=t_vararg, .is_const=1, .ck=idck_vararg, .em=idem_vararg};
gwi_specialid(gwi, "vararg", &spid);
const Type owner = nspc_lookup_type1(t->e->owner->parent,
insert_symbol(t->e->owner->name));
const m_bool ret = check_lambda(env, owner, &e->d.exp_lambda, t->e->d.func->def);
- e->emit_var = 1;
+// e->emit_var = 1;
return ret;
}
if(implicit)
DECL_EXP_FUNC(check, Type, Env)
ANN Type check_exp(const Env env, const Exp exp) {
- Exp curr = exp, next = NULL, prev = NULL;
+ Exp curr = exp;
do {
- next = curr->next;
CHECK_OO((curr->type = check_exp_func[curr->exp_type](env, &curr->d)))
- if(env->gwion->type[et_varloop] && isa(curr->type, env->gwion->type[et_varloop]) > 0 && (prev || next))
- ERR_O(exp->pos, _("Varloop must be the only expression"))
if(env->func && isa(curr->type, env->gwion->type[et_lambda]) < 0 && isa(curr->type, env->gwion->type[et_function]) > 0 &&
!GET_FLAG(curr->type->e->d.func, pure))
UNSET_FLAG(env->func, pure);
- prev = curr;
- } while((curr = next));
+ } while((curr = curr->next));
return exp->type;
}
return GW_OK;
}
+ANN static m_bool check_stmt_varloop(const Env env, const Stmt_VarLoop stmt) {
+ CHECK_OB(check_exp(env, stmt->exp))
+ if(isa(stmt->exp->type, env->gwion->type[et_vararg]) < 0)
+ ERR_B(stmt->exp->pos, "varloop expression type must be '%s', not '%s'",
+ env->gwion->type[et_vararg]->name, stmt->exp->type->name)
+ return check_stmt(env, stmt->body);
+}
+
ANN static inline m_bool _check_breaks(const Env env, const Stmt b) {
RET_NSPC(check_stmt(env, b))
}
return GW_OK;
}
-ANN static inline void inherit(const Type t) {
- const Nspc nspc = t->nspc, parent = t->e->parent->nspc;
- if(!parent)
- return;
- nspc->info->offset = parent->info->offset;
- if(parent->info->vtable.ptr)
- vector_copy2(&parent->info->vtable, &nspc->info->vtable);
-}
-
ANN static m_bool cdef_parent(const Env env, const Class_Def cdef) {
if(cdef->base.tmpl && cdef->base.tmpl->list)
CHECK_BB(template_push_types(env, cdef->base.tmpl))
Func func;
opck ck;
opem em;
+ m_uint emit_var;
} M_Operator;
ANN void free_op_map(Map map, struct Gwion_ *gwion) {
return GW_OK;
Type type = t;
while(SAFE_FLAG(type, template) && type->e->def && type->e->def->base.tmpl && type->e->def->base.tmpl->call) type = type->e->parent;
-// if((t && mo && mo->xid == t->xid) || (!t && !mo))
if((type && mo && mo->xid == type->xid) || (!type && !mo))
return GW_OK;
return 0;
mo->rhs = opi->rhs;
mo->ret = opi->ret;
mo->instr = (f_instr)opi->data;
- mo->ck = opi->ck;
- mo->em = opi->em;
+ if(opi->func) {
+ mo->ck = opi->func->ck;
+ mo->em = opi->func->em;
+ }
+ mo->emit_var = opi->emit_var;
return mo;
}
return nspc;
}
+ANN void op_emit_nonnull(const Emitter emit, const Type mo, const Type opi, const m_uint offset) {
+ if(!mo || mo == OP_ANY_TYPE)
+ return;
+ if(GET_FLAG(mo, nonnull) && !GET_FLAG(opi, nonnull)) {
+ const Instr instr = emit_add_instr(emit, GWOP_EXCEPT);
+ instr->m_val = offset;
+ }
+}
+
ANN Instr op_emit(const Emitter emit, const struct Op_Import* opi) {
DECL_OO(Nspc, nspc, = ensure_nspc(emit->gwion->st, opi))
Type l = opi->lhs;
if(!v)continue;
const M_Operator* mo = operator_find(v, l, r);
if(mo) {
+ const m_uint sz = opi->rhs ? opi->rhs->size : 0;
+ op_emit_nonnull(emit, mo->lhs, opi->lhs, mo->emit_var ?: sz);
+ op_emit_nonnull(emit, mo->rhs, opi->rhs, 0);
if(mo->em)
return mo->em(emit, (void*)opi->data);
return handle_instr(emit, mo);
}
ANN static void scan0_implicit_similar(const Env env, const Type lhs, const Type rhs) {
- struct Op_Import opi = { .op=insert_symbol("$"), .lhs=lhs, .rhs=rhs, .ck=opck_cast_similar };
+ struct Op_Func opfunc = { .ck=opck_cast_similar };
+ struct Op_Import opi = { .op=insert_symbol("$"), .lhs=lhs, .rhs=rhs, .func=&opfunc };
add_op(env->gwion, &opi);
opi.lhs=rhs;
opi.rhs=lhs;
add_op(env->gwion, &opi);
- opi.ck = opck_implicit_similar;
+ opfunc.ck = opck_implicit_similar;
opi.op=insert_symbol("@implicit");
add_op(env->gwion, &opi);
}
t->name = name;
t->nspc = new_nspc(env->gwion->mp, name);
t->e->owner = t->nspc->parent = env->curr;
- t->nspc->is_union = 1;
t->e->parent = env->gwion->type[et_union];
add_type(env, env->curr, t);
if(add) {
CHECK_BB(env_storage(env, decl->td->flag, exp_self(decl)->pos))
((Exp_Decl*)decl)->type = scan1_exp_decl_type(env, (Exp_Decl*)decl);
CHECK_OB(decl->type)
+ if(GET_FLAG(decl->type, const))
+ exp_self(decl)->meta = ae_meta_value;
+// SET_FLAG(decl->td, const);
const m_bool global = GET_FLAG(decl->td, global);
if(global && decl->type->e->owner != env->global_nspc)
ERR_B(exp_self(decl)->pos, _("type '%s' is not global"), decl->type->name)
#define describe_ret_nspc(name, type, prolog, exp) describe_stmt_func(scan1, name, type, prolog, exp)
describe_ret_nspc(flow, Stmt_Flow,, !(scan1_exp(env, stmt->cond) < 0 ||
scan1_stmt(env, stmt->body) < 0) ? 1 : -1)
+describe_ret_nspc(varloop, Stmt_VarLoop,, !(scan1_exp(env, stmt->exp) < 0 ||
+ scan1_stmt(env, stmt->body) < 0) ? 1 : -1)
describe_ret_nspc(for, Stmt_For,, !(scan1_stmt(env, stmt->c1) < 0 ||
scan1_stmt(env, stmt->c2) < 0 ||
(stmt->c3 && scan1_exp(env, stmt->c3) < 0) ||
return GW_OK;
}
+ANN static Value arg_value(MemPool p, const Arg_List list) {
+ const Var_Decl var = list->var_decl;
+ const Value v = new_value(p, list->type, var->xid ? s_name(var->xid) : (m_str)__func__);
+ if(list->td)
+ v->flag = list->td->flag | ae_flag_arg;
+ return v;
+}
ANN static m_bool scan1_args(const Env env, Arg_List list) {
do {
const Var_Decl var = list->var_decl;
CHECK_BB(isres(env, var->xid, var->pos))
if(list->td)
CHECK_OB((list->type = void_type(env, list->td)))
+ var->value = arg_value(env->gwion->mp, list);
+ nspc_add_value(env->curr, var->xid, var->value);
} while((list = list->next));
return GW_OK;
}
else if(GET_FLAG(udef, static))
SET_FLAG(decl.td, static);
CHECK_BB(scan1_exp(env, l->self))
+
+Var_Decl_List list = decl.list;
+do ADD_REF(list->self->value)
+while((list = list->next));
+
+
if(global)
SET_FLAG(decl.td, global);
return GW_OK;
return GW_OK;
}
+ANN m_bool scan1_fbody(const Env env, const Func_Def fdef) {
+ if(fdef->base->args)
+ CHECK_BB(scan1_args(env, fdef->base->args))
+ if(!GET_FLAG(fdef, builtin) && fdef->d.code && fdef->d.code->d.stmt_code.stmt_list)
+ CHECK_BB(scan1_stmt_list(env, fdef->d.code->d.stmt_code.stmt_list))
+ return GW_OK;
+}
+
ANN m_bool scan1_fdef(const Env env, const Func_Def fdef) {
if(fdef->base->td)
CHECK_OB((fdef->base->ret_type = known_type(env, fdef->base->td)))
CHECK_BB(scan_internal(env, fdef->base))
else if(GET_FLAG(fdef, op) && env->class_def)
SET_FLAG(fdef, static);
- if(fdef->base->args)
- CHECK_BB(scan1_args(env, fdef->base->args))
- if(!GET_FLAG(fdef, builtin) && fdef->d.code)
- CHECK_BB(scan1_stmt_code(env, &fdef->d.code->d.stmt_code))
+ RET_NSPC(scan1_fbody(env, fdef))
return GW_OK;
}
return ret;
}
-ANN static Value arg_value(MemPool p, const Arg_List list) {
- const Var_Decl var = list->var_decl;
- const Value v = new_value(p, list->type, var->xid ? s_name(var->xid) : (m_str)__func__);
- if(list->td)
- v->flag = list->td->flag | ae_flag_arg;
- return v;
-}
-
ANN static m_bool scan2_args(const Env env, const Func_Def f) {
Arg_List list = f->base->args;
do {
const Var_Decl var = list->var_decl;
if(var->array)
list->type = array_type(env, list->type, var->array->depth);
- var->value = arg_value(env->gwion->mp, list);
var->value->from->offset = f->stack_depth;
f->stack_depth += list->type->size;
} while((list = list->next));
#define scan2_stmt_func(name, type, prolog, exp) describe_stmt_func(scan2, name, type, prolog, exp)
scan2_stmt_func(flow, Stmt_Flow,, !(scan2_exp(env, stmt->cond) < 0 ||
scan2_stmt(env, stmt->body) < 0) ? 1 : -1)
+scan2_stmt_func(varloop, Stmt_VarLoop,, !(scan2_exp(env, stmt->exp) < 0 ||
+ scan2_stmt(env, stmt->body) < 0) ? 1 : -1)
scan2_stmt_func(for, Stmt_For,, !(scan2_stmt(env, stmt->c1) < 0 ||
scan2_stmt(env, stmt->c2) < 0 ||
(stmt->c3 && scan2_exp(env, stmt->c3) < 0) ||
const Type r = f->base->args ? is_unary ? f->base->args->var_decl->value->type :
f->base->args->next ? f->base->args->next->var_decl->value->type :
f->base->ret_type : NULL;
+ struct Op_Func opfunc = { .ck=strcmp(str, "@implicit") ? 0 : opck_usr_implicit };
struct Op_Import opi = { .op=f->base->xid, .lhs=l, .rhs=r, .ret=f->base->ret_type,
- .pos=f->pos, .data=(uintptr_t)f->base->func };
- if(!strcmp(str, "@implicit"))
- opi.ck = opck_usr_implicit;
+ .pos=f->pos, .data=(uintptr_t)f->base->func, .func=&opfunc };
CHECK_BB(add_op(env->gwion, &opi))
operator_set_func(&opi);
return GW_OK;
t->flag = base->flag;
SET_FLAG(t, nonnull);
nspc_add_type_front(t->e->owner, sym, t);
+ mk_class(env, t);
return t;
}
M_Object obj;
VM_Code code;
} a;
+PRAGMA_PUSH()
register VM_Shred child;
+PRAGMA_POP()
MUTEX_LOCK(s->mutex);
do {
SDISPATCH();
-#! [contains] UgenConnectException
+#! [contains] NullPtrException
UGen ref u;
adc => u;
-#! [contains] NullEventWait
+#! [contains] NullPtrException
Event ref e;
e => now;
+++ /dev/null
-#! [contains] used after
-fun void test(...) {
- vararg.start;
- vararg.end;
- vararg $ int;
-}
+++ /dev/null
-#! [contains] used before
-fun void test(...) {
- vararg $ int;
-}
#! [contains] InvalidVariadicAccess
fun void test(...) {
- vararg.start;
- <<<vararg $ int >>>;
- vararg.end;
+ varloop vararg {
+ <<<vararg $ int >>>;
+ }
}
new Object => test;
--- /dev/null
+#! [contains] outside varloop
+fun void test(...) {
+ <<<vararg $ int >>>;
+}
+new Object => test;
+++ /dev/null
-#! [contains] vararg.start not used before vararg.end
-fun void test(int i, ...) {
- vararg.end;
-#! vararg.start;
-}
-
-test(1, 2.3, null);
+++ /dev/null
-#! [contains] vararg.start already used
-fun void test(...) { vararg.start; vararg.start;}
+++ /dev/null
-#! [contains] vararg.start not used before vararg.end
-fun void test(int i, ...) {
- vararg.end;
-#! vararg.start;
-}
-
-test(1, 2.3, null);
--- /dev/null
+#! varloop expression type must be
+varloop 1 {
+
+}
+++ /dev/null
-#! [contains] Varloop must be the only expression
-fun void test(...) {
- <<<"test">>>, vararg.start;
- vararg.end;
-}
--- /dev/null
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "vm.h"
+#include "object.h"
+#include "instr.h"
+#include "gwion.h"
+#include "operator.h"
+#include "import.h"
+
+static OP_CHECK(opck_ptrext_assign) {
+ const Exp_Binary* bin = (Exp_Binary*)data;
+ if(bin->rhs->meta != ae_meta_var)
+ ERR_N(exp_self(bin)->pos, _("left side operand is constant"));
+ bin->rhs->emit_var = 1;
+ Type t = bin->rhs->type;
+ do {
+ Type u = bin->lhs->type;
+ do {
+ const m_str str = get_type_name(env, u->name, 1);
+ if(str && !strcmp(t->name, str))
+ return bin->lhs->type;
+ } while((u = u->e->parent));
+ } while((t = t->e->parent));
+ return env->gwion->type[et_null];
+}
+
+static INSTR(instr_ptrext_assign) {
+ POP_REG(shred, SZ_INT)
+ const M_Object o = *(M_Object*)REG(-SZ_INT);
+ *(m_float**)o->data = *(m_float**)REG(0);
+}
+
+GWION_IMPORT(typedef_test) {
+ GWI_OB(gwi_class_ini(gwi, "PtrExt", "Ptr<~float~>"))
+ GWI_BB(gwi_class_end(gwi))
+ GWI_BB(gwi_oper_ini(gwi, "nonnull PtrExt", "float", NULL))
+ GWI_BB(gwi_oper_var(gwi, SZ_INT))
+ GWI_BB(gwi_oper_add(gwi, opck_ptrext_assign))
+ GWI_BB(gwi_oper_end(gwi, "<=:", instr_ptrext_assign))
+ return GW_OK;
+}
--- /dev/null
+1234.5 => float f;
+PtrExt ref ptr;
+<<< ptr >>>;
+ptr <=: f;
+<<< f >>>;
#!/bin/bash
-# [test] #74
+# [test] #75
n=0
[ "$1" ] && n="$1"