CFLAGS += -Iutil/include -Iast/include -Ilibcmdapp/src -D_GNU_SOURCE
+CFLAGS += -Iast/libprettyerr/src
# add commit hash to version for now
CFLAGS += -DGWION_VERSION=\"$(shell git log -n1 --format="%h")\"
CFLAGS += -DGWION_BUILTIN
-_GWLIBS = util/libgwion_util.a ast/libgwion_ast.a libcmdapp/libcmdapp.a lib${PRG}.a util/libtermcolor/libtermcolor.a
-GWLIBS = lib${PRG}.a libcmdapp/libcmdapp.a ast/libgwion_ast.a util/libgwion_util.a util/libtermcolor/libtermcolor.a
+_GWLIBS = util/libgwion_util.a ast/libgwion_ast.a libcmdapp/libcmdapp.a lib${PRG}.a util/libtermcolor/libtermcolor.a ast/libprettyerr/libprettyerr.a
+GWLIBS = lib${PRG}.a libcmdapp/libcmdapp.a ast/libgwion_ast.a ast/libprettyerr/libprettyerr.a util/libgwion_util.a util/libtermcolor/libtermcolor.a
_LDFLAGS = ${GWLIBS} ${LDFLAGS}
all: options-show ${_GWLIBS} src/main.o
libcmdapp/libcmdapp.a:
@+${MAKE} -s -C libcmdapp static
+ast/libprettyerr/libprettyerr.a:
+ @+CFLAGS=-I${PWD}/util/libtermcolor/src ${MAKE} -s -C ast/libprettyerr static
+
ast: ast/libgwion_ast.a
@(info build ast)
-Subproject commit a6f47836656ec77d15a9ad1914b05779692bdaba
+Subproject commit d5f0d5d1df9b07c116da954771d566af9aa2ad10
ANN static void clean_type_def(Clean *a, Type_Def b) {
if(b->ext)
clean_type_decl(a, b->ext);
+ if(b->when) {
+ clean_exp(a, b->when);
+ if(b->when_def)
+ clean_func_def(a, b->when_def);
+ }
if(b->tmpl)
clean_tmpl(a, b->tmpl);
}
CHECK_BB(emit_implicit_cast(emit, exp, exp->cast_to))
if(isa(e->type, emit->gwion->type[et_object]) > 0 &&
(e->cast_to ? isa(e->cast_to, emit->gwion->type[et_object]) > 0 : 1) &&
- e->exp_type == ae_exp_decl && GET_FLAG(e->d.exp_decl.td, late) && exp_getuse(e) && !exp_getvar(e)) {
+ e->exp_type == ae_exp_decl && GET_FLAG(e->d.exp_decl.td, late) && exp_getuse(e) && !exp_getvar(e) && GET_FLAG(e->d.exp_decl.list->self->value, late)) {
+// e->exp_type == ae_exp_decl && !exp_getvar(e)) {
const Instr instr = emit_add_instr(emit, GWOP_EXCEPT);
instr->m_val = -SZ_INT;
}
}
ANN static m_bool emit_type_def(const Emitter emit, const Type_Def tdef) {
+ if(tdef->when)
+ CHECK_BB(emit_func_def(emit, tdef->when_def))
return (!is_fptr(emit->gwion, tdef->type) && tdef->type->info->cdef) ?
emit_class_def(emit, tdef->type->info->cdef) : GW_OK;
}
ANN static void env_header(const Env env) {
if(env->class_def)
- gw_err(_("in class: '%s'\n"), env->class_def->name);
- if(env->func)
- gw_err(_("in function: '%s'\n"), env->func->name);
+ gwerr_secondary("in class:", env->name, env->class_def->info->cdef->pos);
+ if(env->func && env->func != (Func)1 && env->func->def)
+ gwerr_secondary("in function:", env->name, env->func->def->pos);
}
ANN static void env_xxx(const Env env, const loc_t pos, const m_str fmt, va_list arg) {
#ifndef __FUZZING__
+ va_list tmpa;
+ va_copy(tmpa, arg);
+ const int size = vsnprintf(NULL, 0, fmt, tmpa);
+ va_end(tmpa);
+ char c[size + 1];
+ vsprintf(c, fmt, arg);
+ gwerr_basic(c, NULL, NULL, env->name, pos, 0);
env_header(env);
- loc_header(pos, env->name);
- vfprintf(stderr, fmt, arg);
- fprintf(stderr, "\n");
- loc_err(pos, env->name);
#endif
}
CHECK_BO(ck_ok(gwi, ck_tdef))
Type_Decl *td = gwi->ck->td;
td->flag |= flag;
- const Type_Def tdef = new_type_def(gwi->gwion->mp, td, gwi->ck->sym);
+ const Type_Def tdef = new_type_def(gwi->gwion->mp, td, gwi->ck->sym, gwi->loc);
if(gwi->ck->tmpl)
tdef->tmpl = gwi_tmpl(gwi);
gwi->ck->td = NULL;
ERR_N(exp_self(call)->pos, _("can't call a non-callable value"))
}
+static INSTR(PredicateCheck) {
+ if(!*(m_uint*)REG(-SZ_INT))
+ Except(shred, "predicate failed");
+}
+
ANN static m_bool import_core_libs(const Gwi gwi) {
const Type t_class = gwi_mk_type(gwi, "@Class", SZ_INT, NULL);
set_tflag(t_class, tflag_infer);
struct SpecialId_ spid = { .type=t_now, .exec=RegPushNow, .is_const=1 };
gwi_specialid(gwi, "now", &spid);
+ struct SpecialId_ predicate = { .type=t_void, .exec=PredicateCheck, .is_const=1 };
+ gwi_specialid(gwi, "@predicate", &predicate);
+
const Type t_compound = gwi_mk_type(gwi, "@Compound", SZ_INT, NULL);
GWI_BB(gwi_gack(gwi, t_compound, gack_compound))
GWI_BB(gwi_set_global_type(gwi, t_compound, et_compound))
#undef insert_symbol
ANN void exception(const VM_Shred shred, const m_str c) {
- gw_err("%s: shred[id=%" UINT_F ":%s], PC=[%" UINT_F "]\n",
+ gw_err("{+}%s{0}: shred[{-}id=%" UINT_F "{0}:%s], PC=[{-}%" UINT_F "{0}]\n",
c, shred->tick->xid, shred->info->name, shred->pc - 1);
vm_shred_exit(shred);
}
const m_str access = exp_access(e);
if(!access)
return GW_OK;
- ERR_B(e->pos, _("operand is %s"), access);
+ env_err(env, e->pos, _("operand is %s"), access );
+ return GW_ERROR;
}
static OP_CHECK(opck_implicit_similar) {
}
ANN m_bool check_type_def(const Env env, const Type_Def tdef) {
+ if(tdef->when) {
+ const Var_Decl decl = new_var_decl(env->gwion->mp, insert_symbol("self"), NULL, tdef->when->pos);
+ const Arg_List args = new_arg_list(env->gwion->mp, cpy_type_decl(env->gwion->mp, tdef->ext), decl, NULL);
+ Func_Base *fb = new_func_base(env->gwion->mp, type2td(env->gwion, tdef->type, tdef->when->pos),
+ insert_symbol("@implicit"), args, ae_flag_none);
+ set_fbflag(fb, fbflag_op);
+ const Exp helper = new_prim_id(env->gwion->mp, insert_symbol("@predicate"), tdef->when->pos);
+ tdef->when->next = helper;
+ const Stmt stmt = new_stmt_exp(env->gwion->mp, ae_stmt_exp, cpy_exp(env->gwion->mp, tdef->when), tdef->when->pos);// copy exp
+ const Stmt_List body = new_stmt_list(env->gwion->mp, stmt, NULL);//ret_list);
+ const Stmt code = new_stmt_code(env->gwion->mp, body, tdef->when->pos);
+ const Func_Def fdef = new_func_def(env->gwion->mp, fb, code, tdef->when->pos);
+ CHECK_BB(traverse_func_def(env, fdef))
+ const Exp predicate = stmt->d.stmt_exp.val;
+ if(isa(predicate->type, env->gwion->type[et_bool]) < 0) {
+ char explain[strlen(predicate->type->name) + 7];
+ sprintf(explain, "found `{/+}%s{0}`", predicate->type->name);
+ gwerr_basic("Invalid `{/+}when{0}` predicate expression type", explain, "use `{/+}bool{0}`",
+ env->name, tdef->when->pos, 0);
+ char from[strlen(tdef->type->name) + 39];
+ sprintf(from, "in `{/+}%s{0}` definition", tdef->type->name);
+ gwerr_secondary(from, env->name, tdef->pos);
+ if(env->context)
+ env->context->error++;
+ return GW_ERROR;
+ }
+ // we handle the return after, so that we don't get *cant' use implicit casting while defining it*
+ const Exp ret_id = new_prim_id(env->gwion->mp, insert_symbol("self"), tdef->when->pos);
+ ret_id->d.prim.value = new_value(env->gwion->mp, tdef->type, "self");
+ const Stmt ret = new_stmt_exp(env->gwion->mp, ae_stmt_return, ret_id, tdef->when->pos);
+ const Stmt_List ret_list = new_stmt_list(env->gwion->mp, ret, NULL);
+ ret_id->type = tdef->type;
+ body->next = ret_list;
+ tdef->when_def = fdef;
+ }
return (!is_fptr(env->gwion, tdef->type) && tdef->type->info->cdef) ?
check_class_def(env, tdef->type->info->cdef) : GW_OK;
}
if(!stmt->c2 || !stmt->c2->d.stmt_exp.val)
ERR_B(stmt_self(stmt)->pos, _("empty for loop condition..."
"...(note: explicitly use 'true' if it's the intent)"
- "...(e.g., 'for(; true;){ /*...*/ }')"))
+ "...(e.g., 'for(; true;){{ /*...*/ }')"))
return GW_OK;
}
CHECK_BB(typedef_complex(env, tdef, base))
} else
typedef_fptr(env, tdef, base);
- if(!tdef->distinct)
+ if(!tdef->distinct && !tdef->when)
scan0_implicit_similar(env, tdef->type, base);
set_tflag(tdef->type, tflag_typedef);
return GW_OK;
ANN m_bool scan1_type_def(const Env env, const Type_Def tdef) {
if(!tdef->type)
tdef->type = nspc_lookup_type0(env->curr, tdef->xid);
+ if(tdef->when)
+ CHECK_BB(scan1_exp(env, tdef->when))
return (!is_fptr(env->gwion, tdef->type) && tdef->type->info->cdef) ?
scan1_cdef(env, tdef->type) : GW_OK;
}
do {
Nspc nspc = env->curr;
do if(nspc_lookup_value0(nspc, list->var_decl->xid))
- ERR_B(list->var_decl->pos, _("argument '%s' shadows a previuosly defined variable"),
+ ERR_B(list->var_decl->pos, _("argument '%s' shadows a previously defined variable"),
s_name(list->var_decl->xid))
while((nspc = nspc->parent));
} while((list = list->next));
return GW_OK;
}
+ANN static m_bool scan2_func_def_op(const Env env, const Func_Def f);
ANN m_bool scan2_type_def(const Env env, const Type_Def tdef) {
- if(!tdef->type->info->cdef) return GW_OK;
+ if(tdef->when)
+ CHECK_BB(scan2_exp(env, tdef->when))
+ if(!tdef->type->info->cdef)
+ return GW_OK;
return (!is_fptr(env->gwion, tdef->type) && tdef->type->info->cdef) ?
scan2_class_def(env, tdef->type->info->cdef) : GW_OK;
}
#! [contains] in function:
-fun void test() { <<< b >>>; }
+class C {
+ fun void test() {
+ <<< b >>>;
+ }
+}
#! [contains somewhere] stray in program
-**µ
+1**µ