-Subproject commit ac133c43c04c4e53331321c18596d22b214d93f8
+Subproject commit d309c7d2f7152d08e0880fdd068666ebc963738a
#ifndef __CPY_AST
#define __CPY_AST
+ANN Array_Sub cpy_array_sub(MemPool, Array_Sub);
+ANN Type_Decl* cpy_type_decl(MemPool, const Type_Decl*);
+ANN Type_List cpy_type_list(MemPool, const Type_List);
+ANN Func_Def cpy_func_def(MemPool, const Func_Def);
ANN Func_Def cpy_func_def(MemPool, Func_Def);
ANN struct Func_Base_* cpy_func_base(MemPool, struct Func_Base_*);
ANN Class_Def cpy_class_def(MemPool, Class_Def);
INSTR(DotTmpl);
INSTR(GTmpl);
+INSTR(TupleCtor);
+INSTR(TupleMember);
+
struct dottmpl_ {
size_t len;
m_str name;
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_tuple(const Gwi gwi);
#endif
};
struct Implicit {
- void* e;
+ Exp e;
Type t;
loc_t pos;
};
Type base_type;
} d;
struct Vector_ contains;
+ struct Vector_ tuple_form;
+ struct Vector_ tuple_offset;
+ Type_List tuple_tl;
};
struct Type_ {
extern Type t_void, t_int, t_bool, t_float, t_dur, t_time, t_now, t_complex, t_polar, t_vec3, t_vec4,
t_null, t_object, t_shred, t_fork, t_event, t_ugen, t_string, t_ptr, t_array, t_gack,
- t_function, t_fptr, t_vararg, t_lambda, t_class, t_union, t_undefined, t_auto;
+ t_function, t_fptr, t_vararg, t_lambda, t_class, t_union, t_undefined, t_auto, t_tuple;
ANN2(1,3) ANEW Type new_type(MemPool, const m_uint xid, const m_str name, const Type);
ANEW ANN Type type_copy(MemPool, const Type type);
return isa(actual_type(t), t_fptr) > 0;
}
ANN m_uint get_depth(const Type type);
+
+
+ANN Type tuple_type(const Env, const Vector, const loc_t);
+ANN void tuple_info(const Env, Type_Decl*, const Var_Decl);
#endif
return vector_size(&emit->code->instr);
}
-ANN static inline m_uint emit_code_offset(const Emitter emit) {
+ANN /*static inline */m_uint emit_code_offset(const Emitter emit) {
return emit->code->frame->curr_offset;
}
-ANN static inline m_uint emit_local(const Emitter emit, const m_uint size, const m_bool is_obj) {
+ANN /*static inline */m_uint emit_local(const Emitter emit, const m_uint size, const m_bool is_obj) {
return frame_local(emit->gwion->mp, emit->code->frame, size, is_obj);
}
info->base = base;
const Instr alloc = emit_add_instr(emit, ArrayAlloc);
alloc->m_val = (m_uint)info;
- if(isa(base, t_object) > 0) {
+ if(isa(base, t_object) > 0 && !GET_FLAG(base, abstract)) {
emit_pre_constructor_array(emit, base);
info->is_obj = 1;
}
ANN static m_bool emit_exp_array(const Emitter emit, const Exp_Array* array) {
const m_uint is_var = exp_self(array)->emit_var;
- const m_uint depth = get_depth(array->base->type) - get_depth(exp_self(array)->type);
CHECK_BB(emit_exp(emit, array->base, 0))
+ const m_uint depth = get_depth(array->base->type) - get_depth(exp_self(array)->type);
+
+const Type t_base = array->base->type;
+Type type = array_base(t_base) ?: t_base;
+if(isa(type, t_tuple) > 0 && isa(exp_self(array)->type, t_tuple) < 0) {
+ Exp e = array->array->exp;
+ while(e->next && e->next->next)
+ e = e->next;
+ const Exp next = e->next;
+ if(!next) {
+ emit_add_instr(emit, GWOP_EXCEPT);
+ const Instr instr = emit_add_instr(emit, TupleMember);
+ instr->m_val = array->array->exp->d.exp_primary.d.num;
+ instr->m_val2 = is_var;
+ emit_add_instr(emit, DotMember); // just a place holder.
+ return GW_OK;
+ }
+ emit_add_instr(emit, GcAdd);
+ e->next = NULL;
+ CHECK_BB(emit_exp(emit, array->array->exp, 0))
+ e->next = next;
+ regpop(emit, (depth) * SZ_INT);
+ emit_add_instr(emit, GWOP_EXCEPT);
+assert(depth);
+ if(depth)
+ for(m_uint i = 0; i < depth-1; ++i) {
+ const Instr access = emit_add_instr(emit, ArrayAccess);
+ access->m_val = i;
+ const Instr get = emit_add_instr(emit, ArrayGet);
+ get->m_val = i;
+ get->m_val2 = -SZ_INT;
+ emit_add_instr(emit, GWOP_EXCEPT);
+ }
+ regpop(emit, SZ_INT);
+ const Instr access = emit_add_instr(emit, ArrayAccess);
+ access->m_val = depth;
+ const Instr get = emit_add_instr(emit, ArrayGet);
+ get->m_val = depth;
+ const Instr push = emit_add_instr(emit, ArrayValid);
+ push->m_val = SZ_INT;
+ emit_add_instr(emit, GWOP_EXCEPT);
+ const Instr instr = emit_add_instr(emit, TupleMember);
+ instr->m_val = next->d.exp_primary.d.num;
+ instr->m_val2 = is_var;
+ emit_add_instr(emit, DotMember); // just a place holder.
+ return GW_OK;
+ }
emit_add_instr(emit, GcAdd);
CHECK_BB(emit_exp(emit, array->array->exp, 0))
regpop(emit, depth * SZ_INT);
return GW_OK;
}
+ANN static m_bool prim_tuple(const Emitter emit, const Exp_Primary * primary) {
+ CHECK_BB(emit_exp(emit, primary->d.tuple.exp, 1))
+ const Instr instr = emit_add_instr(emit, TupleCtor);
+ instr->m_val = (m_uint)exp_self(primary)->type;
+ return GW_OK;
+}
+
ANN static m_bool prim_num(const Emitter emit, const Exp_Primary * primary) {
regpushi(emit, primary->d.num);
return GW_OK;
return GW_OK;
}
+#define prim_unpack dummy_func
static const _exp_func prim_func[] = {
(_exp_func)prim_id, (_exp_func)prim_num, (_exp_func)prim_float, (_exp_func)prim_str,
(_exp_func)prim_array, (_exp_func)prim_gack, (_exp_func)prim_vec, (_exp_func)prim_vec,
- (_exp_func)prim_vec, (_exp_func)prim_char, (_exp_func)dummy_func,
+ (_exp_func)prim_vec, (_exp_func)prim_tuple, (_exp_func)prim_unpack,
+ (_exp_func)prim_char, (_exp_func)dummy_func,
};
ANN static m_bool emit_exp_primary(const Emitter emit, const Exp_Primary* prim) {
const m_bool is_obj = isa(type, t_object) > 0;
const uint emit_addr = ((is_ref && !array) || isa(type, t_object) < 0) ?
emit_var : 1;
- if(is_obj && (is_array || !is_ref) && !GET_FLAG(var_decl->value, ref))
+ if(is_obj && (is_array || !is_ref)/* && !GET_FLAG(var_decl->value, ref)*/)
CHECK_BB(emit_instantiate_object(emit, type, array, is_ref))
f_instr *exec = (f_instr*)allocmember;
if(!GET_FLAG(v, member)) {
ANN static m_bool emit_exp_decl(const Emitter emit, const Exp_Decl* decl) {
Var_Decl_List list = decl->list;
- const uint ref = GET_FLAG(decl->td, ref) || type_ref(decl->type);
+ const uint ref = GET_FLAG(decl->td, ref) || type_ref(decl->type);
const uint var = exp_self(decl)->emit_var;
if(GET_FLAG(decl->type, template))
CHECK_BB(emit_exp_decl_template(emit, decl))
const m_bool global = GET_FLAG(decl->td, global);
const m_uint scope = !global ? emit->env->scope->depth : emit_push_global(emit);
do {
- const uint r = (uint)(GET_FLAG(list->self->value, ref) + ref);
+ const uint r = (list->self->array && list->self->array->exp && ref) ? 0 : (uint)(GET_FLAG(list->self->value, ref) + ref);
// if(!GET_FLAG(list->self->value, used))
// continue;
if(GET_FLAG(decl->td, static))
ANN m_bool emit_exp_spork(const Emitter emit, const Exp_Unary* unary) {
const m_bool is_spork = unary->op == insert_symbol("spork");
const Func f = !unary->code ? unary->exp->d.exp_call.m_func : NULL;
- if(!f) {
+ if(unary->code) {
emit_add_instr(emit, RegPushImm);
push_spork_code(emit, is_spork ? SPORK_CODE_PREFIX : FORK_CODE_PREFIX, unary->code->pos);
if(!SAFE_FLAG(emit->env->func, member))
const Exp exp = new_exp_decl(emit->gwion->mp, type_decl, var_decl_list);
exp->d.exp_decl.type = udef->value->type;
var_decl->value = udef->value;
- CHECK_BB(emit_exp_decl(emit, &exp->d.exp_decl))
+ const m_bool ret = emit_exp_decl(emit, &exp->d.exp_decl);
free_exp(emit->gwion->mp, exp);
+ CHECK_BB(ret)
if(global) {
const M_Object o = new_object(emit->gwion->mp, NULL, udef->value->type);
udef->value->d.ptr = (m_uint*)o;
}
ANN static m_bool import_core_libs(const Gwi gwi) {
- GWI_OB((t_undefined = gwi_mk_type(gwi, "@Undefined", SZ_INT, NULL))) // size = SZ_INT to enable declarations
GWI_OB((t_class = gwi_mk_type(gwi, "Class", SZ_INT, NULL)))
GWI_BB(gwi_add_type(gwi, t_class))
+ GWI_OB((t_undefined = gwi_mk_type(gwi, "@Undefined", SZ_INT, NULL))) // size = SZ_INT to enable declarations
+ GWI_BB(gwi_add_type(gwi, t_undefined))
GWI_OB((t_auto = gwi_mk_type(gwi, "auto", SZ_INT, NULL))) // size = SZ_INT to enable declarations
GWI_BB(gwi_add_type(gwi, t_auto))
SET_FLAG(t_class, abstract);
GWI_OB((t_fptr = gwi_mk_type(gwi, "@func_ptr", SZ_INT, t_function)))
GWI_BB(gwi_add_type(gwi, t_fptr))
GWI_OB((t_lambda = gwi_mk_type(gwi, "@lambda", SZ_INT, t_function)))
- GWI_BB(gwi_add_type(gwi, t_fptr))
+ GWI_BB(gwi_add_type(gwi, t_lambda))
GWI_OB((t_gack = gwi_mk_type(gwi, "@Gack", SZ_INT, NULL)))
GWI_BB(gwi_add_type(gwi, t_gack))
GWI_OB((t_int = gwi_mk_type(gwi, "int", SZ_INT, NULL)))
GWI_OB((t_union = gwi_mk_type(gwi, "@Union", SZ_INT, t_object)))
GWI_BB(gwi_class_ini(gwi, t_union, NULL, NULL))
GWI_BB(gwi_class_end(gwi))
+ GWI_BB(import_tuple(gwi))
GWI_BB(import_array(gwi))
GWI_BB(import_event(gwi))
GWI_BB(import_ugen(gwi))
static OP_CHECK(opck_fptr_impl) {
struct Implicit *impl = (struct Implicit*)data;
- struct FptrInfo info = { ((Exp)impl->e)->type->e->d.func, impl->t->e->d.func,
- (Exp)impl->e, ((Exp)impl->e)->pos };
+ struct FptrInfo info = { impl->e->type->e->d.func, impl->t->e->d.func,
+ impl->e, impl->e->pos };
CHECK_BO(fptr_do(env, &info))
return ((Exp)impl->e)->cast_to = impl->t;
}
static OP_CHECK(opck_implicit_null2obj) {
const struct Implicit* imp = (struct Implicit*)data;
- const Type l = ((Exp)imp->e)->type;
+ const Type l = imp->e->type;
const Type r = imp->t;
if(check_nonnull(env, l, r, "implicitly cast", imp->pos) == t_null)
return t_null;
- ((Exp)imp->e)->cast_to = r;
+ imp->e->cast_to = r;
return imp->t;
}
static OP_EMIT(opem_implicit_null2obj) {
const struct Implicit* imp = (struct Implicit*)data;
- const Type l = ((Exp)imp->e)->type;
+ const Type l = imp->e->type;
const Type r = imp->t;
if(nonnull_check(l, r))
emit_add_instr(emit, GWOP_EXCEPT);
static OP_CHECK(opck_implicit_i2f) {
struct Implicit* imp = (struct Implicit*)data;
- ((Exp)imp->e)->cast_to = t_float;
+ imp->e->cast_to = t_float;
return t_float;
}
static OP_CHECK(opck_implicit_ptr) {
const struct Implicit* imp = (struct Implicit*)data;
- const Exp e = (Exp)imp->e;
+ const Exp e = imp->e;
if(!strcmp(get_type_name(env, imp->t->name, 1), e->type->name)) {
if(e->meta == ae_meta_value)
ERR_N(e->pos, _("can't cast constant to Ptr"));
--- /dev/null
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "instr.h"
+#include "nspc.h"
+#include "type.h"
+#include "object.h"
+#include "emit.h"
+#include "env.h"
+#include "vm.h"
+#include "gwion.h"
+#include "operator.h"
+#include "import.h"
+#include "gwi.h"
+#include "engine.h"
+#include "parser.h"
+#include "value.h"
+#include "cpy_ast.h"
+#include "traverse.h"
+
+struct TupleEmit {
+ Exp e;
+ Vector v;
+ m_uint obj_offset;
+ m_uint tmp_offset;
+ m_uint mem_offset;
+ m_uint sz;
+ m_uint idx;
+};
+
+struct UnpackInfo_ {
+ m_uint obj_offset;
+ m_uint mem_offset;
+ m_uint size;
+};
+
+static INSTR(TupleUnpack) {
+ const M_Object o = *(M_Object*)(shred->reg - SZ_INT);
+ struct UnpackInfo_ *info = (struct UnpackInfo_*)instr->m_val;
+ memcpy(shred->mem + info->mem_offset, o->data + t_tuple->nspc->info->offset + info->obj_offset, info->size);
+}
+
+INSTR(TupleMember) {
+ const M_Object o = *(M_Object*)(shred->reg - SZ_INT);
+ const Type base = o->type_ref;
+ const m_bit* byte = shred->code->bytecode + shred->pc * BYTECODE_SZ;
+ const Type t = (Type)vector_at(&base->e->tuple_form, instr->m_val);
+ const m_uint offset = vector_at(&base->e->tuple_offset, instr->m_val);
+ *(m_uint*)(byte + SZ_INT) = offset;
+ if(!instr->m_val2) {
+ if(t->size == SZ_INT)
+ *(m_uint*)(byte) = eDotMember;
+ else if(t->size == SZ_FLOAT)
+ *(m_uint*)(byte) = eDotMember2;
+ else {
+ *(m_uint*)(byte) = eDotMember3;
+ *(m_uint*)(byte + SZ_INT*2) = t->size;
+ }
+ } else
+ *(m_uint*)(byte) = eDotMember4;
+}
+
+static FREEARG(freearg_tuple_at) {
+ mp_free(((Gwion)gwion)->mp, UnpackInfo, (struct UnpackInfo*)instr->m_val);
+}
+
+ANN static void emit_unpack_instr_inner(const Emitter emit, struct TupleEmit *te) {
+ const Instr instr = emit_add_instr(emit, TupleUnpack);
+ struct UnpackInfo_ *info = mp_malloc2(emit->gwion->mp, sizeof(struct UnpackInfo_));
+ info->obj_offset = te->tmp_offset;
+ info->mem_offset = te->mem_offset;
+ info->size = te->sz;
+ instr->m_val = (m_uint)info;
+}
+
+ANN static int tuple_continue(struct TupleEmit *te) {
+ const m_bool ret = (te->e = te->e->next) &&
+ ++te->idx < VLEN(te->v);
+ if(!ret)
+ te->e = NULL;
+ return ret;
+}
+
+ANN static void unpack_instr_decl(const Emitter emit, struct TupleEmit *te) {
+ m_uint sz = 0;
+ te->sz = 0;
+ do {
+ if(te->e->exp_type == ae_exp_decl) {
+ const Value value = te->e->d.exp_decl.list->self->value;
+ te->sz += value->type->size;
+ value->offset = emit_local(emit, value->type->size, 0);
+ te->tmp_offset = te->obj_offset;
+ te->obj_offset += ((Type)vector_at(te->v, te->idx))->size;
+ } else {
+ sz = ((Type)vector_at(te->v, te->idx))->size;
+ break;
+ }
+ } while(tuple_continue(te));
+ te->obj_offset += sz;
+}
+
+ANN void emit_unpack_instr(const Emitter emit, struct TupleEmit *te) {
+ te->mem_offset = emit_code_offset(emit);
+ unpack_instr_decl(emit, te);
+ if(te->sz)
+ emit_unpack_instr_inner(emit, te);
+ if(te->e && (te->e = te->e->next))
+ emit_unpack_instr(emit, te);
+}
+
+static m_bool tuple_match(const Env env, const Type type[2]) {
+ const Vector lv = &type[0]->e->tuple_form;
+ const Vector rv = &type[1]->e->tuple_form;
+ for(m_uint i = 0; i < vector_size(rv); i++) {
+ DECL_OB(const Type, l, = (Type)vector_at(lv, i))
+ const Type r = (Type)vector_at(rv, i);
+ if(r != t_undefined)
+ CHECK_BB(isa(l, r))
+ }
+ return GW_OK;
+}
+
+static OP_CHECK(opck_at_tuple) {
+ const Exp_Binary *bin = (Exp_Binary*)data;
+ if(bin->rhs->exp_type == ae_exp_primary &&
+ bin->rhs->d.exp_primary.primary_type == ae_primary_unpack) {
+ Exp e = bin->rhs->d.exp_primary.d.tuple.exp;
+ int i = 0;
+ do {
+ if(e->exp_type == ae_exp_decl) {
+ e->d.exp_decl.td->xid->xid = insert_symbol(env->gwion->st, // could be better
+ ((Type)VPTR(&bin->lhs->type->e->tuple_form, i))->name);
+ CHECK_BO(traverse_decl(env, &e->d.exp_decl))
+ }
+ ++i;
+ } while((e = e->next));
+ } else {
+ if(opck_rassign(env, data, mut) == t_null)
+ return t_null;
+ const Type type[2] = { bin->lhs->type, bin->rhs->type };
+ if(tuple_match(env, type) < 0)
+ return t_null;
+ bin->rhs->emit_var = 1;
+ }
+ return bin->lhs->type;
+}
+
+static OP_CHECK(opck_cast_tuple) {
+ Exp_Cast *cast = (Exp_Cast*)data;
+ if(exp_self(cast)->type->e->def && cast->exp->type->e->def) {
+ const Type type[2] = { exp_self(cast)->type, cast->exp->type };
+ CHECK_BO(tuple_match(env, type))
+ }
+ return exp_self(cast)->type;
+}
+
+static OP_CHECK(opck_impl_tuple) {
+ struct Implicit *imp = (struct Implicit*)data;
+ const Type type[2] = { imp->e->type, imp->t };
+ CHECK_BO(tuple_match(env, type))
+ return imp->t;
+}
+
+static OP_EMIT(opem_at_tuple) {
+ const Exp_Binary *bin = (Exp_Binary*)data;
+ if(!(bin->rhs->exp_type == ae_exp_primary &&
+ bin->rhs->d.exp_primary.primary_type == ae_primary_unpack)) {
+ emit_add_instr(emit, ObjectAssign);
+// emit_add_instr(emit, int_r_assign);
+// const Instr instr = emit_add_instr(emit, RegAddRef);
+//instr->m_val = 1;
+ return GW_OK;
+ }
+ const Exp e = bin->rhs->d.exp_primary.d.tuple.exp;
+ const Vector v = &bin->lhs->type->e->tuple_form;
+ struct TupleEmit te = { .e=e, .v=v };
+ emit_unpack_instr(emit, &te);
+ return GW_OK;
+}
+
+ANN void tuple_info(const Env env, Type_Decl *base, const Var_Decl var) {
+ const Value v = var->value;
+ if(v->name[0] != '@') {
+ const m_uint offset = vector_back(&env->class_def->e->tuple_offset);
+ vector_add(&env->class_def->e->tuple_form, (vtype)v->type);
+ vector_add(&env->class_def->e->tuple_offset, offset + v->type->size);
+ Type_Decl *td = cpy_type_decl(env->gwion->mp, base);
+ if(var->array) {
+ if(td->array)
+ td->array->depth += var->array->depth;
+ else
+ td->array = cpy_array_sub(env->gwion->mp, var->array);
+ }
+ if(env->class_def->e->tuple_tl) {
+ Type_List tl = env->class_def->e->tuple_tl;
+ while(tl->next)
+ tl = tl->next;
+ tl->next = new_type_list(env->gwion->mp, td, NULL);
+ } else
+ env->class_def->e->tuple_tl = new_type_list(env->gwion->mp, td, NULL);
+ }
+}
+
+INSTR(TupleCtor) {
+ const Type t = (Type)instr->m_val;
+ const M_Object o = new_object(shred->info->vm->gwion->mp, shred, t);
+ const size_t sz = t_tuple->nspc->info->offset;
+ memcpy(o->data + t_tuple->nspc->info->offset,
+ shred->reg - (t->nspc->info->offset - sz), (t->nspc->info->offset - sz));
+ shred->reg -= (t->nspc->info->offset - sz - SZ_INT);
+ *(M_Object*)(shred->reg - SZ_INT) = o;
+}
+
+GWION_IMPORT(tuple) {
+ GWI_OB((t_tuple = gwi_mk_type(gwi, "Tuple", SZ_INT, t_object)))
+ GWI_BB(gwi_class_ini(gwi, t_tuple, NULL, NULL))
+ GWI_BB(gwi_class_end(gwi))
+ SET_FLAG(t_tuple, abstract | ae_flag_template);
+ GWI_BB(gwi_oper_ini(gwi, "Object", "Tuple", NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_at_tuple))
+ GWI_BB(gwi_oper_emi(gwi, opem_at_tuple))
+ GWI_BB(gwi_oper_end(gwi, "@=>", NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_cast_tuple))
+ GWI_BB(gwi_oper_end(gwi, "$", NULL))
+ GWI_BB(gwi_oper_add(gwi, opck_impl_tuple))
+ GWI_BB(gwi_oper_end(gwi, "@implicit", NULL))
+ register_freearg(gwi, TupleUnpack, freearg_tuple_at);
+ return GW_OK;
+}
if(a->info->op_map.ptr)
free_op_map(&a->info->op_map, gwion);
nspc_free_type(a, gwion);
- if(a->info->class_data)
+ if(a->info->class_data && a->info->class_data_size)
mp_free2(gwion->mp, a->info->class_data_size, a->info->class_data);
if(a->info->vtable.ptr)
vector_release(&a->info->vtable);
free_union_def(gwion->mp, a->e->def->union_def);
}
a->e->def->union_def = NULL;
- } else
+ } else if(a->e->def)
free_class_def(gwion->mp, a->e->def);
}
if(a->nspc)
REM_REF(a->nspc, gwion);
+ if(a->e->tuple_form.ptr)
+ vector_release(&a->e->tuple_form);
+ if(a->e->tuple_offset.ptr)
+ vector_release(&a->e->tuple_offset);
+ if(a->e->tuple_tl)
+ free_type_list(gwion->mp, a->e->tuple_tl);
if(a->e->contains.ptr) {
for(m_uint i = 0; i < vector_size(&a->e->contains); ++i)
REM_REF((Type)vector_at(&a->e->contains, i), gwion);
type->name = name;
type->e = mp_calloc(p, TypeInfo);
type->e->parent = parent;
- if(type->e->parent)
+ if(type->e->parent) {
type->size = parent->size;
+ vector_init(&type->e->tuple_form);
+ vector_init(&type->e->tuple_offset);
+ vector_add(&type->e->tuple_offset, 0);
+ }
type->ref = new_refcount(p, free_type);
return type;
}
a->e->d.base_type = type->e->d.base_type;
a->array_depth = type->array_depth;
a->e->def = type->e->def;
+ if(t_function && isa(type, t_function) > 0) {
+ vector_release(&a->e->tuple_form);
+ a->e->tuple_form.ptr = NULL;
+ vector_release(&a->e->tuple_offset);
+ a->e->tuple_offset.ptr = NULL;
+ }
return a;
}
m_uint n = 1;
const size_t len = name ? strlen(name) : 0;
const size_t slen = strlen(s);
- const size_t tlen = slen -len + 1;
- char c[slen];
+ const size_t tlen = slen - len + 1;
+ char c[slen + 1];
if(!name)
return index ? NULL : s_name(insert_symbol(s));
Type t_void, t_int, t_bool, t_float, t_dur, t_time, t_now, t_complex, t_polar, t_vec3, t_vec4,
t_null, t_object, t_shred, t_fork, t_event, t_ugen, t_string, t_ptr, t_array, t_gack,
- t_function, t_fptr, t_vararg, t_lambda, t_class, t_union, t_undefined, t_auto;
+ t_function, t_fptr, t_vararg, t_lambda, t_class, t_union, t_undefined, t_auto, t_tuple;
}
#define describe_check_decl(a, b) \
-ANN static inline void decl_##a(const Nspc nspc, const Value v) { \
+ANN static inline void decl_##a(const Env env, const Value v) { \
+ const Nspc nspc = env->curr;\
SET_FLAG(v, a); \
v->offset = nspc->info->b; \
nspc->info->b += v->type->size; \
CHECK_BO(check_exp_decl_parent(env, var))
if(var->array && var->array->exp)
CHECK_BO(check_exp_array_subscripts(env, var->array->exp))
- if(GET_FLAG(decl->td, member))
- decl_member(env->curr, v);
+ if(GET_FLAG(decl->td, member) && env->class_def) {
+ decl_member(env, v);
+ if(isa(env->class_def, t_object) > 0)
+ tuple_info(env, decl->td, var);
+ }
else if(GET_FLAG(decl->td, static))
- decl_static(env->curr, v);
+ decl_static(env, v);
else if(global || (env->func && GET_FLAG(env->func->def, global)))
SET_FLAG(v, abstract);
if(isa(decl->type, t_fptr) > 0)
ANN static Type prim_str(const Env env, Exp_Primary *const prim) {
if(!prim->value) {
const m_str str = prim->d.str;
+ const Value v = new_value(env->gwion->mp, t_string, str);
char c[strlen(str) + 8];
sprintf(c, "%s:string", str);
- const Symbol sym = insert_symbol(c);
- const Value exist = nspc_lookup_value0(env->global_nspc, sym);
- if(exist)
- prim->value = exist;
- else {
- const Value v = new_value(env->gwion->mp, t_string, s_name(sym));
- nspc_add_value(env->global_nspc, sym, v);
- prim->value = v;
- }
+ nspc_add_value(env_nspc(env), insert_symbol(c), v);
+ prim->value = v;
}
return t_string;
}
return t_gack;
}
+ANN static Type prim_tuple(const Env env, const Exp_Primary * primary) {
+ CHECK_OO(check_exp(env, primary->d.tuple.exp))
+ Exp e = primary->d.tuple.exp;
+ struct Vector_ v;
+ vector_init(&v);
+ do {
+ vector_add(&v, (m_uint)e->type);
+ } while((e = e->next));
+ const Type ret = tuple_type(env, &v, exp_self(primary)->pos);
+ vector_release(&v);
+ return ret;
+}
+
#define describe_prim_xxx(name, type) \
ANN static Type prim_##name(const Env env NUSED, const Exp_Primary * primary NUSED) {\
return type; \
describe_prim_xxx(num, t_int)
describe_prim_xxx(float, t_float)
describe_prim_xxx(nil, t_void)
+describe_prim_xxx(unpack, t_tuple)
typedef Type (*_type_func)(const Env, const void*);
static const _type_func prim_func[] = {
- (_type_func)prim_id, (_type_func)prim_num, (_type_func)prim_float, (_type_func)prim_str,
- (_type_func)prim_array, (_type_func)prim_gack, (_type_func)prim_vec, (_type_func)prim_vec,
- (_type_func)prim_vec, (_type_func)prim_num, (_type_func)prim_nil,
+ (_type_func)prim_id, (_type_func)prim_num, (_type_func)prim_float, (_type_func)prim_str,
+ (_type_func)prim_array, (_type_func)prim_gack, (_type_func)prim_vec, (_type_func)prim_vec,
+ (_type_func)prim_vec, (_type_func)prim_tuple, (_type_func)prim_unpack,
+ (_type_func)prim_num, (_type_func)prim_nil,
};
ANN static Type check_exp_primary(const Env env, const Exp_Primary* primary) {
}
ANN Type at_depth(const Env env, const Type t, const m_uint depth) {
+ if(!depth)
+ return t;
if(GET_FLAG(t, typedef))
- return !depth ? t : at_depth(env, t->e->parent, depth);
+ return at_depth(env, t->e->parent, depth);
if(depth > t->array_depth)
return at_depth(env, t->e->d.base_type, depth - t->array_depth);
- return !depth ? t : array_type(env, array_base(t), t->array_depth - depth);
+ return array_type(env, array_base(t), t->array_depth - depth);
}
static inline m_bool index_is_int(const Env env, Exp e, m_uint *depth) {
if(depth != array->array->depth)
ERR_B(exp_self(array)->pos, _("invalid array acces expression."))
DECL_OB(const Type, t_base, = check_exp(env, array->base))
- if(depth > get_depth(t_base))
+ if(depth > get_depth(t_base)) {
+ const Type type = array_base(t_base) ?: t_base;
+ if(isa(type, t_tuple) > 0 && depth - get_depth(t_base) == 1) {
+ Exp e = array->array->exp;
+ while(e->next)
+ e = e->next;
+ if(e->exp_type != ae_exp_primary ||
+ e->d.exp_primary.primary_type != ae_primary_num)
+ ERR_B(exp_self(array)->pos, _("tuple subscripts must be litteral"))
+ if((Type)vector_at(&type->e->tuple_form, e->d.exp_primary.d.num) == t_undefined)
+ ERR_B(exp_self(array)->pos, _("tuple subscripts is undefined"))
+ return 0;
+ }
ERR_B(exp_self(array)->pos,
_("array subscripts (%i) exceeds defined dimension (%i)"),
- array->array->depth, depth)
+ array->array->depth, get_depth(t_base))
+ }
return GW_OK;
}
static ANN Type check_exp_array(const Env env, const Exp_Array* array) {
CHECK_OO(check_exp(env, array->array->exp))
- CHECK_BO(array_access_valid(env, array))
+ const m_bool ret = array_access_valid(env, array);
+ CHECK_BO(ret);
+ if(!ret) {
+ Exp e = array->array->exp;
+ while(e->next)
+ e = e->next;
+ // if we implement tuple with no type, err_msg
+ const Type type = array_base(array->base->type) ?: array->base->type;
+ if(e->d.exp_primary.d.num >= vector_size(&type->e->tuple_form))
+ ERR_O(exp_self(array)->pos, "Invalid tuple subscript")
+ return (Type)vector_at(&type->e->tuple_form, e->d.exp_primary.d.num);
+ }
return at_depth(env, array->base->type, array->array->depth);
}
}
ANN static Func _find_template_match(const Env env, const Value v, const Exp_Call* exp) {
- CHECK_BO(check_call(env, exp))
+CHECK_BO(check_call(env, exp))
const Type_List types = exp->tmpl->call;
Func m_func = NULL, former = env->func;
DECL_OO(const m_str, tmpl_name, = tl2str(env, types))
Func_Base *fbase = cpy_func_base(env->gwion->mp, base->base);
fbase->xid = sym;
fbase->tmpl->base = 0;
- fbase->tmpl->call = cpy_type_list(env->gwion->mp, types);
+ fbase->tmpl->call = types;
if(template_push_types(env, fbase->tmpl) > 0) {
const Fptr_Def fptr = new_fptr_def(env->gwion->mp, fbase, base->flag);
if(value) {
continue;
const Func_Def fdef = (Func_Def)cpy_func_def(env->gwion->mp, value->d.func_ref->def);
SET_FLAG(fdef, template);
- fdef->base->tmpl->call = cpy_type_list(env->gwion->mp, types);
+ fdef->base->tmpl->call = types;
fdef->base->tmpl->base = i;
if((m_func = ensure_tmpl(env, fdef, exp)))
break;
if(f) {
Tmpl* tmpl = new_tmpl_call(env->gwion->mp, func->tmpl->call);
tmpl->list = v->d.func_ref ? v->d.func_ref->def->base->tmpl->list : func->func->type->e->d.func->def->base->tmpl->list;
-// tmpl->list = cpy_id_list(env->gwion->mp, tmpl->list);
((Exp_Call*)func)->tmpl = tmpl;
return ((Exp_Call*)func)->m_func = f;
}
CHECK_BO(check_exp_call1_check(env, exp->func))
if(exp->func->type == t_lambda)
return check_lambda_call(env, exp);
+ if(GET_FLAG(exp->func->type->e->d.func, ref)) {
+ const Value value = exp->func->type->e->d.func->value_ref;
+ CHECK_BO(traverse_class_def(env, value->owner_class->e->def))
+ }
if(exp->args)
CHECK_OO(check_exp(env, exp->args))
if(GET_FLAG(exp->func->type, func))
ANN m_bool check_enum_def(const Env env, const Enum_Def edef) {
if(env->class_def) {
ID_List list = edef->list;
- do decl_static(env->curr, nspc_lookup_value0(env->curr, list->xid));
+ do decl_static(env, nspc_lookup_value0(env->curr, list->xid));
while((list = list->next));
}
return GW_OK;
const m_uint depth = t->array_depth - 1;
if(GET_FLAG(t, typedef))
t = t->e->parent;
- if(!t || !ptr || isa(t, t_array) < 0)
+ if(!ptr || isa(t, t_array) < 0)
ERR_B(stmt_self(stmt)->pos, _("type '%s' is not array.\n"
" This is not allowed in auto loop"), stmt->exp->type->name)
if(stmt->is_ptr) {
array.depth = depth;
td.array = &array;
}
- ptr = type_decl_resolve(env, &td);
+// ptr = type_decl_resolve(env, &td); exit(3);
+ ptr = known_type(env, &td);
if(!GET_FLAG(ptr, checked))
check_class_def(env, ptr->e->def);
-// CHECK_BB(traverse_class_def(env, ptr->e->def))
+// traverse_class_def(env, ptr->e->def);
}
t = depth ? array_type(env, ptr, depth) : ptr;
stmt->v = new_value(env->gwion->mp, t, s_name(stmt->sym));
return GW_OK;
if(udef->xid) {
if(env->class_def)
- (!GET_FLAG(udef, static) ? decl_member : decl_static)(env->curr, udef->value);
+ (!GET_FLAG(udef, static) ? decl_member : decl_static)(env, udef->value);
} else if(env->class_def) {
if(!GET_FLAG(udef, static))
udef->o = env->class_def->nspc->info->offset;
a->name = src->name;
}
-ANN static Array_Sub cpy_array_sub(MemPool p, const Array_Sub src) {
+ANN Array_Sub cpy_array_sub(MemPool p, const Array_Sub src) {
Array_Sub a = mp_calloc(p, Array_Sub);
if(src->exp)
a->exp = cpy_exp(p, src->exp);
return a;
}
-ANN static Type_Decl* cpy_type_decl(MemPool p, const Type_Decl* src) {
+ANN Type_Decl* cpy_type_decl(MemPool p, const Type_Decl* src) {
Type_Decl* a = mp_calloc(p, Type_Decl);
if(src->xid)
a->xid = cpy_id_list(p, src->xid); // 1
ANN static Type void_type(const Env env, const Type_Decl* td) {
DECL_OO(const Type, t, = known_type(env, td))
+ if(t->e->def && !GET_FLAG(t, scan1))
+ CHECK_BO(scan1_cdef(env, t->e->def))
if(t->size)
return t;
ERR_O(td_pos(td), _("cannot declare variables of size '0' (i.e. 'void')..."))
if(!GET_FLAG(decl->td, static))
SET_FLAG(decl->td, member);
}
- if(GET_FLAG(t, abstract) && !GET_FLAG(decl->td, ref))
- ERR_O(exp_self(decl)->pos, _("Type '%s' is abstract, declare as ref. (use @)"), t->name)
+// if(GET_FLAG(t, abstract) && !GET_FLAG(decl->td, ref))
+// ERR_O(exp_self(decl)->pos, _("Type '%s' is abstract, declare as ref. (use @)"), t->name)
if(GET_FLAG(t, private) && t->e->owner != env->curr)
ERR_O(exp_self(decl)->pos, _("can't use private type %s"), t->name)
if(GET_FLAG(t, protect) && (!env->class_def || isa(t, env->class_def) < 0))
CHECK_BB(isres(env, var->xid, exp_self(decl)->pos))
Type t = decl->type;
const Value former = nspc_lookup_value0(env->curr, var->xid);
- if(former)
+ if(former && t != t_auto)
ERR_B(var->pos, _("variable %s has already been defined in the same scope..."),
s_name(var->xid))
if(var->array) {
if(var->array->exp) {
- if(GET_FLAG(decl->td, ref))
+// if(GET_FLAG(decl->td, ref))
+ if(GET_FLAG(decl->td, ref) && isa(t, t_object) < 0)
ERR_B(td_pos(decl->td), _("ref array must not have array expression.\n"
- "e.g: int @my_array[];\nnot: @int my_array[2];"))
+ "e.g: int @my_array[];\nnot: int @my_array[2];"))
CHECK_BB(scan1_exp(env, var->array->exp))
}
t = array_type(env, decl->type, var->array->depth);
- }
- assert(!var->value);
- const Value v = var->value = new_value(env->gwion->mp, t, s_name(var->xid));
+ } else if(GET_FLAG(t, abstract) && !GET_FLAG(decl->td, ref))
+ ERR_B(exp_self(decl)->pos, _("Type '%s' is abstract, declare as ref. (use @)"), t->name)
+
+ //assert(!var->value);
+ const Value v = var->value = former ?: new_value(env->gwion->mp, t, s_name(var->xid));
nspc_add_value(nspc, var->xid, v);
v->flag = decl->td->flag;
+ v->type = t;
if(var->array && !var->array->exp)
SET_FLAG(v, ref);
if(!env->scope->depth && !env->class_def)
return scan1_exp(env, prim->d.exp);
if(prim->primary_type == ae_primary_array && prim->d.array->exp)
return scan1_exp(env, prim->d.array->exp);
+ if(prim->primary_type == ae_primary_tuple)
+ return scan1_exp(env, prim->d.tuple.exp);
+// if(prim->primary_type == ae_primary_unpack)
+// return scan1_exp(env, prim->d.tuple.exp);
return GW_OK;
}
}
ANN m_bool scan1_type_def(const Env env, const Type_Def tdef) {
- return tdef->type->e->def ? scan1_cdef(env, tdef->type->e->def) : GW_OK;
+ if(!tdef->type->e->def)return GW_OK;
+// return tdef->type->e->def ? scan1_cdef(env, tdef->type->e->def) : GW_OK;
+ return isa(tdef->type, t_fptr) < 0 ? scan1_cdef(env, tdef->type->e->def) : GW_OK;
}
ANN m_bool scan1_union_def(const Env env, const Union_Def udef) {
if(isa(parent, t_object) < 0)
ERR_B(pos, _("cannot extend primitive type '%s'"), parent->name)
if(parent->e->def && !GET_FLAG(parent, scan1))
- CHECK_BB(scanx_parent(parent, scan1_cdef, env))
+// CHECK_BB(scanx_parent(parent, scan1_cdef, env))
+ CHECK_BB(scan1_cdef(env, parent->e->def))
if(type_ref(parent))
ERR_B(pos, _("can't use ref type in class extend"))
return GW_OK;
const m_bool global = GET_FLAG(decl->td, global);
const m_uint scope = !global ? env->scope->depth : env_push_global(env);
const Type type = decl->type;
- if(GET_FLAG(type, template) && !GET_FLAG(type, scan2))
+ if(type->e->def && /*GET_FLAG(type, template) &&*/ !GET_FLAG(type, scan2))
CHECK_BB(scan2_cdef(env, decl->type->e->def))
Var_Decl_List list = decl->list;
do {
CHECK_BB(scan2_args(env, def))
} else
SET_FLAG(fptr->type, func);
+// nspc_add_func(fptr->type->e->owner, fptr->base->xid, fptr->base->func);
return GW_OK;
}
ANN m_bool scan2_type_def(const Env env, const Type_Def tdef) {
- return tdef->type->e->def ? scan2_class_def(env, tdef->type->e->def) : GW_OK;
+// return tdef->type->e->def ? scan2_class_def(env, tdef->type->e->def) : GW_OK;
+ if(!tdef->type->e->def) return GW_OK;
+ return isa(tdef->type, t_fptr) < 0 ? scan2_class_def(env, tdef->type->e->def) : GW_OK;
}
ANN static inline Value prim_value(const Env env, const Symbol s) {
SET_FLAG(v, used);
} else if(prim->primary_type == ae_primary_array && prim->d.array->exp)
return scan2_exp(env, prim->d.array->exp);
+ if(prim->primary_type == ae_primary_tuple)
+ return scan2_exp(env, prim->d.tuple.exp);
+// if(prim->primary_type == ae_primary_unpack)
+// return scan2_exp(env, prim->d.tuple.exp);
return GW_OK;
}
ANN2(1,2) static Value func_value(const Env env, const Func f,
const Value overload) {
const Type t = func_type(env, f);
- const Value v = new_value(env->gwion->mp, t, s_name(insert_symbol(t->name)));
+ const Value v = new_value(env->gwion->mp, t, t->name);
CHECK_OO(scan2_func_assign(env, f->def, f, v))
if(!overload) {
ADD_REF(v);
}
ANN static inline int actual(const Tmpl *tmpl) {
- return tmpl->call && tmpl->call != (Type_List)1;
+ return tmpl->call && tmpl->call != (Type_List)1 && tmpl->list;
}
ANN static inline m_bool tmpl_push(const Env env, const Tmpl* tmpl) {
}
ANN static inline void _pop(const Env e, const Class_Def c, const m_uint s) {
- if(c->base.tmpl && actual(c->base.tmpl))
+ if(c->base.tmpl && actual(c->base.tmpl) && c->base.tmpl->list)
nspc_pop_type(e->gwion->mp, e->curr);
env_pop(e, s);
}
ANN m_bool scanx_cdef(const Env env, void* opt, const Class_Def cdef,
const _exp_func f_cdef, const _exp_func f_union) {
- if(cdef->base.type && cdef->base.type->e->parent != t_union)
+ if(cdef->base.type->e->parent != t_union)
return f_cdef(opt, cdef);
CHECK_BB(template_push_types(env, cdef->base.tmpl))
const m_bool ret = f_union(opt, cdef->union_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 Type scan_tuple(const Env env, const Type_Decl *td) {
+ struct Vector_ v;
+ vector_init(&v);
+ Type_List tl = td->types;
+ do {
+ const Type t = tl->td->xid->xid != insert_symbol("_") ?
+ known_type(env, tl->td) : 1;
+ if(!t)
+ break;
+ vector_add(&v, (m_uint)t);
+ } while((tl = tl->next));
+ const Type ret = tuple_type(env, &v, td_pos(td));
+ vector_release(&v);
+ return ret;
+}
+
ANN Tmpl* mk_tmpl(const Env env, const Type t, const Tmpl *tm, const Type_List types) {
Tmpl *tmpl = new_tmpl(env->gwion->mp, get_total_type_list(env, t, tm), 0);
tmpl->call = cpy_type_list(env->gwion->mp, types);
if(GET_FLAG(t, template)) {
if(GET_FLAG(t, ref))
return t;
- if(!type->types)
- ERR_O(t->e->def->pos,
- _("you must provide template types for type '%s'"), t->name)
- if(template_match(t->e->def->base.tmpl->list, type->types) < 0)
- ERR_O(type->xid->pos, _("invalid template types number"))
- DECL_OO(const Class_Def, a, = template_class(env, t->e->def, type->types))
- SET_FLAG(a, ref);
- if(a->base.type)
- return a->base.type;
- a->base.tmpl = mk_tmpl(env, t, t->e->def->base.tmpl, type->types);
- if(t->e->parent != t_union) {
- CHECK_BO(scan0_class_def(env, a))
- map_set(&env->curr->info->type->map, (vtype)a->base.xid, (vtype)a->base.type);
- } else {
- a->union_def = new_union_def(env->gwion->mp, a->list, t->e->def->pos);
- a->union_def->type_xid = a->base.xid;
- CHECK_BO(scan0_union_def(env, a->union_def))
- a->base.type = a->union_def->type;
- a->base.type->e->def = a;
- assert(GET_FLAG(a, union));
- }
- SET_FLAG(a->base.type, template | ae_flag_ref);
- a->base.type->e->owner = t->e->owner;
- if(GET_FLAG(t, builtin))
+ if(!type->types) {
+ if(t != t_tuple)
+ ERR_O(t->e->def->pos,
+ _("you must provide template types for type '%s'"), t->name)
+ return t;
+ }
+ if(t->e->def) {// not tuple
+ if(template_match(t->e->def->base.tmpl->list, type->types) < 0)
+ ERR_O(type->xid->pos, _("invalid template types number"))
+ DECL_OO(const Class_Def, a, = template_class(env, t->e->def, type->types))
+ SET_FLAG(a, ref);
+ if(a->base.type)
+ return a->base.type;
+ a->base.tmpl = mk_tmpl(env, t, t->e->def->base.tmpl, type->types);
+ if(t->e->parent != t_union) {
+ CHECK_BO(scan0_class_def(env, a))
+ map_set(&env->curr->info->type->map, (vtype)a->base.xid, (vtype)a->base.type);
+ } else {
+ a->union_def = new_union_def(env->gwion->mp, a->list, t->e->def->pos);
+ a->union_def->type_xid = a->base.xid;
+ CHECK_BO(scan0_union_def(env, a->union_def))
+ a->base.type = a->union_def->type;
+ a->base.type->e->def = a;
+ assert(GET_FLAG(a, union));
+ }
+ SET_FLAG(a->base.type, template | ae_flag_ref);
+ a->base.type->e->owner = t->e->owner;
+ if(GET_FLAG(t, builtin))
SET_FLAG(a->base.type, builtin);
- CHECK_BO(scan1_cdef(env, a))
- return a->base.type;
- } else if(type->types) { // TODO: clean me
+ CHECK_BO(scan1_cdef(env, a))
+ return a->base.type;
+ } else
+ return scan_tuple(env, type);
+ } else if(type->types) { // TODO: clean me
if(isa(t, t_function) > 0 && t->e->d.func->def->base->tmpl) {
DECL_OO(const m_str, tl_name, = tl2str(env, type->types))
const Symbol sym = func_symbol(env, t->e->owner->name, t->e->d.func->name, tl_name, 0);
--- /dev/null
+#include <string.h>
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "oo.h"
+#include "vm.h"
+#include "env.h"
+#include "type.h"
+#include "func.h"
+#include "value.h"
+#include "nspc.h"
+#include "traverse.h"
+#include "template.h"
+#include "vm.h"
+#include "parse.h"
+#include "gwion.h"
+#include "cpy_ast.h"
+
+
+ANN static Symbol tuple_sym(const Env env, const Vector v) {
+ GwText text = { .mp=env->gwion->mp };
+ text_add(&text, t_tuple->name);
+ text_add(&text, "<~");
+ for(m_uint i = 0; i < vector_size(v); ++i) {
+ const Type t = (Type)vector_at(v, i);
+ text_add(&text, t != 1 ? t->name : "_");
+ if(i+1 < vector_size(v))
+ text_add(&text, ",");
+ }
+ text_add(&text, "~>");
+ const Symbol sym = insert_symbol(text.str);
+ text_release(&text);
+ return sym;
+}
+
+ANN Type tuple_type(const Env env, const Vector v, const loc_t pos) {
+ const Symbol sym = tuple_sym(env, v);
+ const Type exists = nspc_lookup_type1(env->curr, sym);
+ if(exists)
+ return exists;
+ Stmt_List base = NULL, curr = NULL;
+ Type_List tlbase = NULL, tl = NULL;
+ for(m_uint i = 0; i < vector_size(v); ++i) {
+ char name[num_digit(i) + 2];
+ sprintf(name, "e%lu", i);
+ const Symbol sym = insert_symbol(name);
+ const Type t = (Type)vector_at(v, i);
+ const Symbol tsym = insert_symbol(t != 1 ? t->name : "@Undefined");
+// const Symbol tsym = t != 1 ? insert_symbol(t->name) : insert_symbol("@undefined");
+ Exp decl = decl_from_id(env->gwion->mp, tsym, sym, loc_cpy(env->gwion->mp, pos));
+ const Stmt stmt = new_stmt_exp(env->gwion->mp, ae_stmt_exp, decl);
+ const Stmt_List slist = new_stmt_list(env->gwion->mp, stmt, NULL);
+ if(curr)
+ curr->next = slist;
+ if(!base)
+ base = slist;
+{// build Type_List
+ const ID_List ilist = new_id_list(env->gwion->mp, tsym,
+ loc_cpy(env->gwion->mp, pos));
+ Type_Decl *td = new_type_decl(env->gwion->mp, ilist);
+ Type_List tmp_tl = new_type_list(env->gwion->mp, td, NULL);
+ if(tl)
+ tl->next = tmp_tl;
+ if(!tlbase)
+ tlbase = tl = tmp_tl;
+
+}
+ curr = slist;
+ }
+ Section * section = new_section_stmt_list(env->gwion->mp, base);
+ Class_Body body = new_class_body(env->gwion->mp, section, NULL);
+ const ID_List ilist = new_id_list(env->gwion->mp, insert_symbol(t_tuple->name),
+ loc_cpy(env->gwion->mp, pos));
+ Type_Decl *td = new_type_decl(env->gwion->mp, ilist);
+ Class_Def cdef = new_class_def(env->gwion->mp, ae_flag_template,
+ sym, td, body, loc_cpy(env->gwion->mp, pos));
+ Tmpl* tmpl = new_tmpl_call(env->gwion->mp, tlbase);
+ cdef->base.tmpl = tmpl;
+ CHECK_BO(scan0_class_def(env, cdef))
+ SET_FLAG(cdef->base.type, abstract);
+ cdef->base.type->e->tuple_tl = tlbase;
+// CHECK_BO(scan1_cdef(env, cdef))
+ CHECK_BO(traverse_cdef(env, cdef))
+ nspc_add_type(env->curr, sym, cdef->base.type);
+// map_set((Map)vector_front(&env->curr->info->type), sym, cdef->base.type);
+ return cdef->base.type;
+}
reg += SZ_INT;
DISPATCH()
dotmember:
+//printf("VAL %lu %p\n", VAL, );
*(m_uint*)(reg-SZ_INT) = *(m_uint*)(a.obj->data + VAL);
DISPATCH()
dotfloat:
--- /dev/null
+new Object @=> Object ! @ o;
--- /dev/null
+class Person {
+ "Phil" @=> string @name;
+ 45 => int age;
+}
+
+Person p @=> <~string,int~>Tuple @t;
+<<<t.e0>>>;
+<<<t.e1>>>;
--- /dev/null
+class Person {
+ "Phil" @=> string @name;
+ 45 => int age;
+}
+
+Person p @=> <~string,string~>Tuple @t;
+<<<t.e0>>>;
+<<<t.e1>>>;
--- /dev/null
+Object t[2];
+#!<<< t[0] >>>;
+#!null @=> t[0];
+<<< t >>>;
+<("tom", 12) @=> t[0];
+#!t << <("tom", 12);
+#!<<< t.size() >>>;
+#!<<< t[0][0] >>>;
+#!<<< t[0][1] >>>;
--- /dev/null
+#! [contains] Type 'Tuple' is abstract, declare as ref
+Tuple u;
--- /dev/null
+<<< <("Tom", 12)[0] >>> ;
+#! <<< <("Tom", 12)[1] >>> ;
+
+#! <<< <("Tom", 12) @=> <~string, int~>Tuple @t >>> ;
+#! <<< t[0] >>> ;
+#! <<< t[1] >>> ;
--- /dev/null
+<("Tom", 12)[0][2];
--- /dev/null
+<~string,int~>Tuple t[2];
+#!<<< t[0] >>>;
+#!null @=> t[0];
+<<< t >>>;
+<<< t[0] >>>;
+<<< <("tom", 12) @=> t[0] >>> ;
+
+#!t << <("tom", 12);
+#!<<< t.size() >>>;
+#!<<< t[0][0] >>>;
+#!<<< t[0][1] >>>;
--- /dev/null
+int i;
+<("Tom", 12)[i];
--- /dev/null
+<(1.2,"test")[3];
--- /dev/null
+<("Tom", 6) @=>
+<~string, int~>Tuple @tup;
+<<< typeof(tup) >>>;
+<<< tup >>>;
--- /dev/null
+<("Tom", 6) @=>
+<~float, int~>Tuple @tup;
+<<< typeof(tup) >>>;
+<<< tup >>>;
--- /dev/null
+#! [contains] cannot assign
+<("Tom", 6) @=> <("Pat", 22);
--- /dev/null
+<~int~>Tuple @a;
+
+<<< a >>>;
+<<< a $ Tuple >>>;
--- /dev/null
+<~int,int~>Tuple @a;
+
+<<< a >>>;
+<<< a $ <~int~>Tuple >>>;
--- /dev/null
+<~int~>Tuple @a;
--- /dev/null
+#! [contains] Tom
+fun void test(<~string~>Tuple t) {
+#! <<< t.e0 >>>;
+ <<< t[0] >>>;
+}
+
+<( "Tom", 21) => test;
+#!<("Tom") => test;
--- /dev/null
+<( new int);
--- /dev/null
+<(1, 2, 3) @=> >(b, _, c);
+<<< c >>>;
--- /dev/null
+<("Tom", 2, "Taxi driver") @=> <~string,_, string~>Tuple @t;
+<<< t>>>;
+<<< t[0]>>>;
+<("Tom", 2.3, "Cook") @=> t;
+#!<<< t[1]>>>;
+<<< t[2]>>>;
--- /dev/null
+<~int, strong~>Tuple @a;
+<~int, string~>Tuple @a;
--- /dev/null
+#! [contains] already been defined in the same scope
+int i;
+<(12) @=> >(i);