From: Wolfgang Bumiller Date: Fri, 30 Jan 2015 17:59:48 +0000 (+0100) Subject: ast conversion mostly finished X-Git-Tag: xonotic-v0.8.2~15 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=45236a644fb45ac9f61c3ef38bcab17b5004b095;p=xonotic%2Fgmqcc.git ast conversion mostly finished --- diff --git a/ast.cpp b/ast.cpp index df2d676..acf4928 100644 --- a/ast.cpp +++ b/ast.cpp @@ -10,53 +10,6 @@ #include "algo.h" -#define ast_instantiate(T, ctx, destroyfn) \ - T* self = new T; \ - if (!self) return nullptr; \ - ast_node_init(self, ctx, TYPE_##T); \ - self->m_destroy = (ast_node_delete*)destroyfn - -/* - * forward declarations, these need not be in ast.h for obvious - * static reasons. - */ -static bool ast_member_codegen(ast_member*, ast_function*, bool lvalue, ir_value**); -static void ast_array_index_delete(ast_array_index*); -static bool ast_array_index_codegen(ast_array_index*, ast_function*, bool lvalue, ir_value**); -static void ast_argpipe_delete(ast_argpipe*); -static bool ast_argpipe_codegen(ast_argpipe*, ast_function*, bool lvalue, ir_value**); -static void ast_store_delete(ast_store*); -static bool ast_store_codegen(ast_store*, ast_function*, bool lvalue, ir_value**); -static void ast_ifthen_delete(ast_ifthen*); -static bool ast_ifthen_codegen(ast_ifthen*, ast_function*, bool lvalue, ir_value**); -static void ast_ternary_delete(ast_ternary*); -static bool ast_ternary_codegen(ast_ternary*, ast_function*, bool lvalue, ir_value**); -static void ast_loop_delete(ast_loop*); -static bool ast_loop_codegen(ast_loop*, ast_function*, bool lvalue, ir_value**); -static void ast_breakcont_delete(ast_breakcont*); -static bool ast_breakcont_codegen(ast_breakcont*, ast_function*, bool lvalue, ir_value**); -static void ast_switch_delete(ast_switch*); -static bool ast_switch_codegen(ast_switch*, ast_function*, bool lvalue, ir_value**); -static void ast_label_delete(ast_label*); -static void ast_label_register_goto(ast_label*, ast_goto*); -static bool ast_label_codegen(ast_label*, ast_function*, bool lvalue, ir_value**); -static bool ast_goto_codegen(ast_goto*, ast_function*, bool lvalue, ir_value**); -static void ast_goto_delete(ast_goto*); -static void ast_call_delete(ast_call*); -static bool ast_call_codegen(ast_call*, ast_function*, bool lvalue, ir_value**); -static bool ast_block_codegen(ast_block*, ast_function*, bool lvalue, ir_value**); -static void ast_unary_delete(ast_unary*); -static bool ast_unary_codegen(ast_unary*, ast_function*, bool lvalue, ir_value**); -static void ast_entfield_delete(ast_entfield*); -static bool ast_entfield_codegen(ast_entfield*, ast_function*, bool lvalue, ir_value**); -static void ast_return_delete(ast_return*); -static bool ast_return_codegen(ast_return*, ast_function*, bool lvalue, ir_value**); -static void ast_binstore_delete(ast_binstore*); -static bool ast_binstore_codegen(ast_binstore*, ast_function*, bool lvalue, ir_value**); -static void ast_binary_delete(ast_binary*); -static bool ast_binary_codegen(ast_binary*, ast_function*, bool lvalue, ir_value**); -static bool ast_state_codegen(ast_state*, ast_function*, bool lvalue, ir_value**); - /* Initialize main ast node aprts */ ast_node::ast_node(lex_ctx_t ctx, int node_type) : m_context(ctx) @@ -71,7 +24,7 @@ ast_node::~ast_node() } /* weight and side effects */ -void ast_node::propagate_side_effects(ast_node *other) const +void ast_node::propagateSideEffects(ast_node *other) const { other->m_side_effects = m_side_effects; } @@ -96,34 +49,43 @@ ast_expression::~ast_expression() delete m_varparam; } +ast_expression::ast_expression(ast_copy_type_t, const ast_expression &other) + : ast_expression(ast_copy_type, other.m_context, other) +{} + +ast_expression::ast_expression(ast_copy_type_t, lex_ctx_t ctx, const ast_expression &other) + : ast_expression(ast_copy_type, TYPE_ast_expression, ctx, other) +{} + ast_expression::ast_expression(ast_copy_type_t, int nodetype, const ast_expression &other) - : ast_expression(other.m_context, nodetype) + : ast_expression(ast_copy_type, nodetype, other.m_context, other) +{} + +ast_expression::ast_expression(ast_copy_type_t, int nodetype, lex_ctx_t ctx, const ast_expression &other) + : ast_expression(ctx, nodetype) { m_vtype = other.m_vtype; m_count = other.m_count; m_flags = other.m_flags; if (other.m_next) - m_next = new ast_expression(ast_copy_type, TYPE_ast_expression, *other.m_next); + m_next = new ast_expression(ast_copy_type, *other.m_next); m_type_params.reserve(other.m_type_params.size()); for (auto &it : other.m_type_params) m_type_params.emplace_back(new ast_value(ast_copy_type, *it)); } -ast_expression::ast_expression(ast_copy_type_t, const ast_expression &other) - : ast_expression(other.m_context, TYPE_ast_expression) -{} -ast_expression *ast_expression::shallow_type(lex_ctx_t ctx, qc_type vtype) { +ast_expression *ast_expression::shallowType(lex_ctx_t ctx, qc_type vtype) { auto expr = new ast_expression(ctx, TYPE_ast_expression); expr->m_vtype = vtype; return expr; } -void ast_expression::adopt_type(const ast_expression &other) +void ast_expression::adoptType(const ast_expression &other) { m_vtype = other.m_vtype; if (other.m_next) - m_next = new ast_expression(ast_copy_type, TYPE_ast_expression, *other.m_next); + m_next = new ast_expression(ast_copy_type, *other.m_next); m_count = other.m_count; m_flags = other.m_flags; m_type_params.clear(); @@ -132,7 +94,7 @@ void ast_expression::adopt_type(const ast_expression &other) m_type_params.emplace_back(new ast_value(ast_copy_type, *it)); } -bool ast_expression::compare_type(const ast_expression &other) const +bool ast_expression::compareType(const ast_expression &other) const { if (m_vtype == TYPE_NIL || other.m_vtype == TYPE_NIL) @@ -151,27 +113,42 @@ bool ast_expression::compare_type(const ast_expression &other) const if (m_type_params.size()) { size_t i; for (i = 0; i < m_type_params.size(); ++i) { - if (!m_type_params[i]->compare_type(*other.m_type_params[i])) + if (!m_type_params[i]->compareType(*other.m_type_params[i])) return false; } } if (m_next) - return m_next->compare_type(*other.m_next); + return m_next->compareType(*other.m_next); return true; } +bool ast_expression::codegen(ast_function*, bool, ir_value**) { + compile_error(m_context, "ast_expression::codegen called!"); + abort(); + return false; +} + ast_value::ast_value(ast_copy_type_t, const ast_value &other, const std::string &name) : ast_value(ast_copy_type, static_cast(other), name) -{} +{ + m_keep_node = true; // keep values, always + memset(&m_constval, 0, sizeof(m_constval)); +} ast_value::ast_value(ast_copy_type_t, const ast_value &other) : ast_value(ast_copy_type, static_cast(other), other.m_name) -{} +{ + m_keep_node = true; // keep values, always + memset(&m_constval, 0, sizeof(m_constval)); +} ast_value::ast_value(ast_copy_type_t, const ast_expression &other, const std::string &name) - : ast_expression(ast_copy_type, other) + : ast_expression(ast_copy_type, TYPE_ast_value, other) , m_name(name) -{} +{ + m_keep_node = true; // keep values, always + memset(&m_constval, 0, sizeof(m_constval)); +} ast_value::ast_value(lex_ctx_t ctx, const std::string &name, qc_type t) : ast_expression(ctx, TYPE_ast_value, t) @@ -201,8 +178,6 @@ ast_value::~ast_value() break; } } - if (m_ir_values) - mem_d(m_ir_values); // initlist imples an array which implies .next in the expression exists. if (m_initlist.size() && m_next->m_vtype == TYPE_STRING) { @@ -304,7 +279,7 @@ void ast_type_to_string(const ast_expression *e, char *buf, size_t bufsize) buf[pos] = 0; } -void ast_value::add_param(ast_value *p) +void ast_value::addParam(ast_value *p) { m_type_params.emplace_back(p); } @@ -337,14 +312,14 @@ ast_binary::ast_binary(lex_ctx_t ctx, int op, m_left = left; m_right = right; - propagate_side_effects(left); - propagate_side_effects(right); + propagateSideEffects(left); + propagateSideEffects(right); if (op >= INSTR_EQ_F && op <= INSTR_GT) m_vtype = TYPE_FLOAT; else if (op == INSTR_AND || op == INSTR_OR) { if (OPTS_FLAG(PERL_LOGIC)) - adopt_type(*right); + adoptType(*right); else m_vtype = TYPE_FLOAT; } @@ -377,7 +352,7 @@ ast_binstore::ast_binstore(lex_ctx_t ctx, int storop, int mathop, , m_keep_dest(false) { m_side_effects = true; - adopt_type(*left); + adoptType(*left); } ast_binstore::~ast_binstore() @@ -410,7 +385,7 @@ ast_unary::ast_unary(lex_ctx_t ctx, int op, ast_expression *expr) , m_op(op) , m_operand(expr) { - propagate_side_effects(expr); + propagateSideEffects(expr); if ((op >= INSTR_NOT_F && op <= INSTR_NOT_FNC) || op == VINSTR_NEG_F) { m_vtype = TYPE_FLOAT; } else if (op == VINSTR_NEG_V) { @@ -431,7 +406,7 @@ ast_return::ast_return(lex_ctx_t ctx, ast_expression *expr) , m_operand(expr) { if (expr) - propagate_side_effects(expr); + propagateSideEffects(expr); } ast_return::~ast_return() @@ -452,15 +427,15 @@ ast_entfield::ast_entfield(lex_ctx_t ctx, ast_expression *entity, ast_expression , m_entity(entity) , m_field(field) { - propagate_side_effects(m_entity); - propagate_side_effects(m_field); + propagateSideEffects(m_entity); + propagateSideEffects(m_field); if (!outtype) { compile_error(ctx, "ast_entfield: field has no type"); m_vtype = TYPE_VOID; } else - adopt_type(*outtype); + adoptType(*outtype); } ast_entfield::~ast_entfield() @@ -498,10 +473,10 @@ ast_member::ast_member(lex_ctx_t ctx, ast_expression *owner, unsigned int field, m_next = nullptr; } else { m_vtype = TYPE_FIELD; - m_next = ast_shallow_type(ctx, TYPE_FLOAT); + m_next = ast_expression::shallowType(ctx, TYPE_FLOAT); } - propagate_side_effects(owner); + propagateSideEffects(owner); } ast_member::~ast_member() @@ -531,14 +506,14 @@ ast_array_index::ast_array_index(lex_ctx_t ctx, ast_expression *array, ast_expre , m_array(array) , m_index(index) { - propagate_side_effects(array); - propagate_side_effects(index); + propagateSideEffects(array); + propagateSideEffects(index); ast_expression *outtype = m_array->m_next; - adopt_type(*outtype); + adoptType(*outtype); if (array->m_vtype == TYPE_FIELD && outtype->m_vtype == TYPE_ARRAY) { - // FIXME: investigate - this is not possible after adopt_type + // FIXME: investigate - this is not possible after adoptType //if (m_vtype != TYPE_ARRAY) { // compile_error(self->m_context, "array_index node on type"); // ast_array_index_delete(self); @@ -578,7 +553,7 @@ ast_store::ast_store(lex_ctx_t ctx, int op, ast_expression *dest, ast_expression , m_source(source) { m_side_effects = true; - adopt_type(*dest); + adoptType(*dest); } ast_store::~ast_store() @@ -593,11 +568,11 @@ ast_ifthen::ast_ifthen(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontr , m_on_true(ontrue) , m_on_false(onfalse) { - propagate_side_effects(cond); + propagateSideEffects(cond); if (ontrue) - propagate_side_effects(ontrue); + propagateSideEffects(ontrue); if (onfalse) - propagate_side_effects(onfalse); + propagateSideEffects(onfalse); } ast_ifthen::~ast_ifthen() @@ -615,14 +590,14 @@ ast_ternary::ast_ternary(lex_ctx_t ctx, ast_expression *cond, ast_expression *on , m_on_true(ontrue) , m_on_false(onfalse) { - propagate_side_effects(cond); - propagate_side_effects(ontrue); - propagate_side_effects(onfalse); + propagateSideEffects(cond); + propagateSideEffects(ontrue); + propagateSideEffects(onfalse); if (ontrue->m_vtype == TYPE_NIL) - adopt_type(onfalse); + adoptType(*onfalse); else - adopt_type(ontrue); + adoptType(*ontrue); } ast_ternary::~ast_ternary() @@ -641,7 +616,7 @@ ast_loop::ast_loop(lex_ctx_t ctx, ast_expression *postcond, bool post_not, ast_expression *increment, ast_expression *body) - , ast_expression(ctx, TYPE_ast_loop) + : ast_expression(ctx, TYPE_ast_loop) , m_initexpr(initexpr) , m_precond(precond) , m_postcond(postcond) @@ -651,15 +626,15 @@ ast_loop::ast_loop(lex_ctx_t ctx, , m_post_not(post_not) { if (initexpr) - propagate_side_effects(initexpr); + propagateSideEffects(initexpr); if (precond) - propagate_side_effects(precond); + propagateSideEffects(precond); if (postcond) - propagate_side_effects(postcond); + propagateSideEffects(postcond); if (increment) - propagate_side_effects(increment); + propagateSideEffects(increment); if (body) - propagate_side_effects(body); + propagateSideEffects(body); } ast_loop::~ast_loop() @@ -676,180 +651,134 @@ ast_loop::~ast_loop() ast_unref(m_body); } -ast_breakcont* ast_breakcont_new(lex_ctx_t ctx, bool iscont, unsigned int levels) +ast_breakcont::ast_breakcont(lex_ctx_t ctx, bool iscont, unsigned int levels) + : ast_expression(ctx, TYPE_ast_breakcont) + , m_is_continue(iscont) + , m_levels(levels) { - ast_instantiate(ast_breakcont, ctx, ast_breakcont_delete); - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_breakcont_codegen); - - self->m_is_continue = iscont; - self->m_levels = levels; - - return self; } -void ast_breakcont_delete(ast_breakcont *self) +ast_breakcont::~ast_breakcont() { - ast_expression_delete((ast_expression*)self); - self->~ast_breakcont(); - mem_d(self); } -ast_switch* ast_switch_new(lex_ctx_t ctx, ast_expression *op) +ast_switch::ast_switch(lex_ctx_t ctx, ast_expression *op) + : ast_expression(ctx, TYPE_ast_switch) + , m_operand(op) { - ast_instantiate(ast_switch, ctx, ast_switch_delete); - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_switch_codegen); - - self->m_operand = op; - - self->propagate_side_effects(op); - - return self; + propagateSideEffects(op); } -void ast_switch_delete(ast_switch *self) +ast_switch::~ast_switch() { - ast_unref(self->m_operand); + ast_unref(m_operand); - for (auto &it : self->m_cases) { + for (auto &it : m_cases) { if (it.m_value) ast_unref(it.m_value); ast_unref(it.m_code); } - - ast_expression_delete((ast_expression*)self); - self->~ast_switch(); - mem_d(self); } -ast_label* ast_label_new(lex_ctx_t ctx, const char *name, bool undefined) +ast_label::ast_label(lex_ctx_t ctx, const std::string &name, bool undefined) + : ast_expression(ctx, TYPE_ast_label) + , m_name(name) + , m_irblock(nullptr) + , m_undefined(undefined) { - ast_instantiate(ast_label, ctx, ast_label_delete); - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_label_codegen); - - self->m_vtype = TYPE_NOEXPR; - - self->m_name = util_strdup(name); - self->m_irblock = nullptr; - self->m_undefined = undefined; - - return self; + m_vtype = TYPE_NOEXPR; } -void ast_label_delete(ast_label *self) +ast_label::~ast_label() { - mem_d((void*)self->m_name); - ast_expression_delete((ast_expression*)self); - self->~ast_label(); - mem_d(self); } -static void ast_label_register_goto(ast_label *self, ast_goto *g) +void ast_label::registerGoto(ast_goto *g) { - self->m_gotos.push_back(g); + m_gotos.push_back(g); } -ast_goto* ast_goto_new(lex_ctx_t ctx, const char *name) +ast_goto::ast_goto(lex_ctx_t ctx, const std::string &name) + : ast_expression(ctx, TYPE_ast_goto) + , m_name(name) + , m_target(nullptr) + , m_irblock_from(nullptr) { - ast_instantiate(ast_goto, ctx, ast_goto_delete); - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_goto_codegen); - - self->m_name = util_strdup(name); - self->m_target = nullptr; - self->m_irblock_from = nullptr; - - return self; } -void ast_goto_delete(ast_goto *self) +ast_goto::~ast_goto() { - mem_d((void*)self->m_name); - ast_expression_delete((ast_expression*)self); - self->~ast_goto(); - mem_d(self); } -void ast_goto_set_label(ast_goto *self, ast_label *label) +void ast_goto::setLabel(ast_label *label) { - self->m_target = label; + m_target = label; } -ast_state* ast_state_new(lex_ctx_t ctx, ast_expression *frame, ast_expression *think) +ast_state::ast_state(lex_ctx_t ctx, ast_expression *frame, ast_expression *think) + : ast_expression(ctx, TYPE_ast_expression) + , m_framenum(frame) + , m_nextthink(think) { - ast_instantiate(ast_state, ctx, ast_state_delete); - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_state_codegen); - self->m_framenum = frame; - self->m_nextthink = think; - return self; } -void ast_state_delete(ast_state *self) +ast_state::~ast_state() { - if (self->m_framenum) - ast_unref(self->m_framenum); - if (self->m_nextthink) - ast_unref(self->m_nextthink); - - ast_expression_delete((ast_expression*)self); - self->~ast_state(); - mem_d(self); + if (m_framenum) + ast_unref(m_framenum); + if (m_nextthink) + ast_unref(m_nextthink); } -ast_call* ast_call_new(lex_ctx_t ctx, - ast_expression *funcexpr) +ast_call *ast_call::make(lex_ctx_t ctx, ast_expression *funcexpr) { - ast_instantiate(ast_call, ctx, ast_call_delete); if (!funcexpr->m_next) { compile_error(ctx, "not a function"); - mem_d(self); return nullptr; } - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_call_codegen); - - self->m_side_effects = true; - - self->m_func = funcexpr; - self->m_va_count = nullptr; - - ast_type_adopt(self, funcexpr->m_next); + return new ast_call(ctx, funcexpr); +} - return self; +ast_call::ast_call(lex_ctx_t ctx, ast_expression *funcexpr) + : ast_expression(ctx, TYPE_ast_call) + , m_func(funcexpr) + , m_va_count(nullptr) +{ + m_side_effects = true; + adoptType(*funcexpr->m_next); } -void ast_call_delete(ast_call *self) +ast_call::~ast_call() { - for (auto &it : self->m_params) + for (auto &it : m_params) ast_unref(it); - if (self->m_func) - ast_unref(self->m_func); + if (m_func) + ast_unref(m_func); - if (self->m_va_count) - ast_unref(self->m_va_count); - - ast_expression_delete((ast_expression*)self); - self->~ast_call(); - mem_d(self); + if (m_va_count) + ast_unref(m_va_count); } -static bool ast_call_check_vararg(ast_call *self, ast_expression *va_type, ast_expression *exp_type) +bool ast_call::checkVararg(ast_expression *va_type, ast_expression *exp_type) const { char texp[1024]; char tgot[1024]; if (!exp_type) return true; - if (!va_type || !ast_compare_type(va_type, exp_type)) + if (!va_type || !va_type->compareType(*exp_type)) { if (va_type && exp_type) { ast_type_to_string(va_type, tgot, sizeof(tgot)); ast_type_to_string(exp_type, texp, sizeof(texp)); if (OPTS_FLAG(UNSAFE_VARARGS)) { - if (compile_warning(self->m_context, WARN_UNSAFE_TYPES, + if (compile_warning(m_context, WARN_UNSAFE_TYPES, "piped variadic argument differs in type: constrained to type %s, expected type %s", tgot, texp)) return false; } else { - compile_error(self->m_context, + compile_error(m_context, "piped variadic argument differs in type: constrained to type %s, expected type %s", tgot, texp); return false; @@ -859,12 +788,12 @@ static bool ast_call_check_vararg(ast_call *self, ast_expression *va_type, ast_e { ast_type_to_string(exp_type, texp, sizeof(texp)); if (OPTS_FLAG(UNSAFE_VARARGS)) { - if (compile_warning(self->m_context, WARN_UNSAFE_TYPES, + if (compile_warning(m_context, WARN_UNSAFE_TYPES, "piped variadic argument may differ in type: expected type %s", texp)) return false; } else { - compile_error(self->m_context, + compile_error(m_context, "piped variadic argument may differ in type: expected type %s", texp); return false; @@ -874,54 +803,54 @@ static bool ast_call_check_vararg(ast_call *self, ast_expression *va_type, ast_e return true; } -bool ast_call_check_types(ast_call *self, ast_expression *va_type) +bool ast_call::checkTypes(ast_expression *va_type) const { char texp[1024]; char tgot[1024]; size_t i; bool retval = true; - const ast_expression *func = self->m_func; - size_t count = self->m_params.size(); - if (count > func->m_type_params.size()) - count = func->m_type_params.size(); + + size_t count = m_params.size(); + if (count > m_func->m_type_params.size()) + count = m_func->m_type_params.size(); for (i = 0; i < count; ++i) { - if (ast_istype(self->m_params[i], ast_argpipe)) { + if (ast_istype(m_params[i], ast_argpipe)) { /* warn about type safety instead */ if (i+1 != count) { - compile_error(self->m_context, "argpipe must be the last parameter to a function call"); + compile_error(m_context, "argpipe must be the last parameter to a function call"); return false; } - if (!ast_call_check_vararg(self, va_type, (ast_expression*)func->m_type_params[i])) + if (!checkVararg(va_type, m_func->m_type_params[i].get())) retval = false; } - else if (!ast_compare_type(self->m_params[i], (ast_expression*)(func->m_type_params[i]))) + else if (!m_params[i]->compareType(*m_func->m_type_params[i])) { - ast_type_to_string(self->m_params[i], tgot, sizeof(tgot)); - ast_type_to_string((ast_expression*)func->m_type_params[i], texp, sizeof(texp)); - compile_error(self->m_context, "invalid type for parameter %u in function call: expected %s, got %s", + ast_type_to_string(m_params[i], tgot, sizeof(tgot)); + ast_type_to_string(m_func->m_type_params[i].get(), texp, sizeof(texp)); + compile_error(m_context, "invalid type for parameter %u in function call: expected %s, got %s", (unsigned int)(i+1), texp, tgot); /* we don't immediately return */ retval = false; } } - count = self->m_params.size(); - if (count > func->m_type_params.size() && func->m_varparam) { + count = m_params.size(); + if (count > m_func->m_type_params.size() && m_func->m_varparam) { for (; i < count; ++i) { - if (ast_istype(self->m_params[i], ast_argpipe)) { + if (ast_istype(m_params[i], ast_argpipe)) { /* warn about type safety instead */ if (i+1 != count) { - compile_error(self->m_context, "argpipe must be the last parameter to a function call"); + compile_error(m_context, "argpipe must be the last parameter to a function call"); return false; } - if (!ast_call_check_vararg(self, va_type, func->m_varparam)) + if (!checkVararg(va_type, m_func->m_varparam)) retval = false; } - else if (!ast_compare_type(self->m_params[i], func->m_varparam)) + else if (!m_params[i]->compareType(*m_func->m_varparam)) { - ast_type_to_string(self->m_params[i], tgot, sizeof(tgot)); - ast_type_to_string(func->m_varparam, texp, sizeof(texp)); - compile_error(self->m_context, "invalid type for variadic parameter %u in function call: expected %s, got %s", + ast_type_to_string(m_params[i], tgot, sizeof(tgot)); + ast_type_to_string(m_func->m_varparam, texp, sizeof(texp)); + compile_error(m_context, "invalid type for variadic parameter %u in function call: expected %s, got %s", (unsigned int)(i+1), texp, tgot); /* we don't immediately return */ retval = false; @@ -931,120 +860,95 @@ bool ast_call_check_types(ast_call *self, ast_expression *va_type) return retval; } -ast_block* ast_block_new(lex_ctx_t ctx) +ast_block::ast_block(lex_ctx_t ctx) + : ast_expression(ctx, TYPE_ast_block) { - ast_instantiate(ast_block, ctx, ast_block_delete); - ast_expression_init((ast_expression*)self, - (ast_expression_codegen*)&ast_block_codegen); - return self; } -bool ast_block_add_expr(ast_block *self, ast_expression *e) +ast_block::~ast_block() { - self->propagate_side_effects(e); - self->m_exprs.push_back(e); - if (self->m_next) { - ast_delete(self->m_next); - self->m_next = nullptr; - } - ast_type_adopt(self, e); - return true; + for (auto &it : m_exprs) ast_unref(it); + for (auto &it : m_locals) delete it; + for (auto &it : m_collect) delete it; } -void ast_block_collect(ast_block *self, ast_expression *expr) +void ast_block::setType(const ast_expression &from) { - self->m_collect.push_back(expr); - expr->m_keep_node = true; + if (m_next) + delete m_next; + adoptType(from); } -void ast_block_delete(ast_block *self) + +bool ast_block::addExpr(ast_expression *e) { - for (auto &it : self->m_exprs) ast_unref(it); - for (auto &it : self->m_locals) ast_delete(it); - for (auto &it : self->m_collect) ast_delete(it); - ast_expression_delete((ast_expression*)self); - self->~ast_block(); - mem_d(self); + propagateSideEffects(e); + m_exprs.push_back(e); + if (m_next) { + delete m_next; + m_next = nullptr; + } + adoptType(*e); + return true; } -void ast_block_set_type(ast_block *self, ast_expression *from) +void ast_block::collect(ast_expression *expr) { - if (self->m_next) - ast_delete(self->m_next); - ast_type_adopt(self, from); + m_collect.push_back(expr); + expr->m_keep_node = true; } -ast_function* ast_function_new(lex_ctx_t ctx, const char *name, ast_value *vtype) +ast_function *ast_function::make(lex_ctx_t ctx, const std::string &name, ast_value *vtype) { - ast_instantiate(ast_function, ctx, ast_function_delete); - if (!vtype) { - compile_error(self->m_context, "internal error: ast_function_new condition 0"); - goto cleanup; + compile_error(ctx, "internal error: ast_function_new condition 0"); + return nullptr; } else if (vtype->m_hasvalue || vtype->m_vtype != TYPE_FUNCTION) { - compile_error(self->m_context, "internal error: ast_function_new condition %i %i type=%i (probably 2 bodies?)", + compile_error(ctx, "internal error: ast_function_new condition %i %i type=%i (probably 2 bodies?)", (int)!vtype, (int)vtype->m_hasvalue, vtype->m_vtype); - goto cleanup; + return nullptr; } + return new ast_function(ctx, name, vtype); +} - self->m_function_type = vtype; - self->m_name = name ? util_strdup(name) : nullptr; - - self->m_labelcount = 0; - self->m_builtin = 0; - - self->m_ir_func = nullptr; - self->m_curblock = nullptr; - +ast_function::ast_function(lex_ctx_t ctx, const std::string &name, ast_value *vtype) + : ast_node(ctx, TYPE_ast_function) + , m_function_type(vtype) + , m_name(name) + , m_builtin(0) + , m_static_count(0) + , m_ir_func(nullptr) + , m_curblock(nullptr) + , m_labelcount(0) + , m_varargs(nullptr) + , m_argc(nullptr) + , m_fixedparams(nullptr) + , m_return_value(nullptr) +{ vtype->m_hasvalue = true; - vtype->m_constval.vfunc = self; - - self->m_varargs = nullptr; - self->m_argc = nullptr; - self->m_fixedparams = nullptr; - self->m_return_value = nullptr; - self->m_static_count = 0; + vtype->m_constval.vfunc = this; +} - return self; +ast_function::~ast_function() +{ + if (m_function_type) { + // ast_value_delete(m_function_type); + m_function_type->m_hasvalue = false; + m_function_type->m_constval.vfunc = nullptr; + // We use unref - if it was stored in a global table it is supposed + // to be deleted from *there* + ast_unref(m_function_type); + } -cleanup: - mem_d(self); - return nullptr; + if (m_fixedparams) + ast_unref(m_fixedparams); + if (m_return_value) + ast_unref(m_return_value); } -void ast_function_delete(ast_function *self) -{ - if (self->m_name) - mem_d((void*)self->m_name); - if (self->m_function_type) { - /* ast_value_delete(self->m_function_type); */ - self->m_function_type->m_hasvalue = false; - self->m_function_type->m_constval.vfunc = nullptr; - /* We use unref - if it was stored in a global table it is supposed - * to be deleted from *there* - */ - ast_unref(self->m_function_type); - } - for (auto &it : self->m_static_names) - mem_d(it); - // FIXME::DELME:: unique_ptr used on ast_block - //for (auto &it : self->m_blocks) - // ast_delete(it); - if (self->m_varargs) - ast_delete(self->m_varargs); - if (self->m_argc) - ast_delete(self->m_argc); - if (self->m_fixedparams) - ast_unref(self->m_fixedparams); - if (self->m_return_value) - ast_unref(self->m_return_value); - self->~ast_function(); - mem_d(self); -} - -const char* ast_function_label(ast_function *self, const char *prefix) +const char* ast_function::makeLabel(const char *prefix) { size_t id; size_t len; @@ -1057,10 +961,10 @@ const char* ast_function_label(ast_function *self, const char *prefix) return nullptr; } - id = (self->m_labelcount++); + id = (m_labelcount++); len = strlen(prefix); - from = self->m_labelbuf + sizeof(self->m_labelbuf)-1; + from = m_labelbuf + sizeof(m_labelbuf)-1; *from-- = 0; do { *from-- = (id%10) + '0'; @@ -1078,7 +982,7 @@ const char* ast_function_label(ast_function *self, const char *prefix) * But I can't imagine a pituation where the output is truly unnecessary. */ -static void _ast_codegen_output_type(ast_expression *self, ir_value *out) +static void codegen_output_type(ast_expression *self, ir_value *out) { if (out->m_vtype == TYPE_FIELD) out->m_fieldtype = self->m_next->m_vtype; @@ -1086,349 +990,339 @@ static void _ast_codegen_output_type(ast_expression *self, ir_value *out) out->m_outtype = self->m_next->m_vtype; } -#define codegen_output_type(a,o) (_ast_codegen_output_type(static_cast((a)),(o))) - -bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_value::codegen(ast_function *func, bool lvalue, ir_value **out) { (void)func; (void)lvalue; - if (self->m_vtype == TYPE_NIL) { + if (m_vtype == TYPE_NIL) { *out = func->m_ir_func->m_owner->m_nil; return true; } - /* NOTE: This is the codegen for a variable used in an - * It is not the codegen to generate the value. For this purpose, - * ast_local_codegen and ast_global_codegen are to be used before this - * is executed. ast_function_codegen should take care of its locals, - * and the ast-user should take care of ast_global_codegen to be used - * on all the globals. - */ - if (!self->m_ir_v) { + // NOTE: This is the codegen for a variable used in an expression. + // It is not the codegen to generate the value storage. For this purpose, + // generateLocal and generateGlobal are to be used before this + // is executed. ast_function::generateFunction should take care of its + // locals, and the ast-user should take care of generateGlobal to be used + // on all the globals. + if (!m_ir_v) { char tname[1024]; /* typename is reserved in C++ */ - ast_type_to_string((ast_expression*)self, tname, sizeof(tname)); - compile_error(self->m_context, "ast_value used before generated %s %s", tname, self->m_name); + ast_type_to_string(this, tname, sizeof(tname)); + compile_error(m_context, "ast_value used before generated %s %s", tname, m_name); return false; } - *out = self->m_ir_v; + *out = m_ir_v; return true; } -static bool ast_global_array_set(ast_value *self) +bool ast_value::setGlobalArray() { - size_t count = self->m_initlist.size(); + size_t count = m_initlist.size(); size_t i; - if (count > self->m_count) { - compile_error(self->m_context, "too many elements in initializer"); - count = self->m_count; + if (count > m_count) { + compile_error(m_context, "too many elements in initializer"); + count = m_count; } - else if (count < self->m_count) { + else if (count < m_count) { /* add this? - compile_warning(self->m_context, "not all elements are initialized"); + compile_warning(m_context, "not all elements are initialized"); */ } for (i = 0; i != count; ++i) { - switch (self->m_next->m_vtype) { + switch (m_next->m_vtype) { case TYPE_FLOAT: - if (!ir_value_set_float(self->m_ir_values[i], self->m_initlist[i].vfloat)) + if (!ir_value_set_float(m_ir_values[i], m_initlist[i].vfloat)) return false; break; case TYPE_VECTOR: - if (!ir_value_set_vector(self->m_ir_values[i], self->m_initlist[i].vvec)) + if (!ir_value_set_vector(m_ir_values[i], m_initlist[i].vvec)) return false; break; case TYPE_STRING: - if (!ir_value_set_string(self->m_ir_values[i], self->m_initlist[i].vstring)) + if (!ir_value_set_string(m_ir_values[i], m_initlist[i].vstring)) return false; break; case TYPE_ARRAY: /* we don't support them in any other place yet either */ - compile_error(self->m_context, "TODO: nested arrays"); + compile_error(m_context, "TODO: nested arrays"); return false; case TYPE_FUNCTION: /* this requiers a bit more work - similar to the fields I suppose */ - compile_error(self->m_context, "global of type function not properly generated"); + compile_error(m_context, "global of type function not properly generated"); return false; case TYPE_FIELD: - if (!self->m_initlist[i].vfield) { - compile_error(self->m_context, "field constant without vfield set"); + if (!m_initlist[i].vfield) { + compile_error(m_context, "field constant without vfield set"); return false; } - if (!self->m_initlist[i].vfield->m_ir_v) { - compile_error(self->m_context, "field constant generated before its field"); + if (!m_initlist[i].vfield->m_ir_v) { + compile_error(m_context, "field constant generated before its field"); return false; } - if (!ir_value_set_field(self->m_ir_values[i], self->m_initlist[i].vfield->m_ir_v)) + if (!ir_value_set_field(m_ir_values[i], m_initlist[i].vfield->m_ir_v)) return false; break; default: - compile_error(self->m_context, "TODO: global constant type %i", self->m_vtype); + compile_error(m_context, "TODO: global constant type %i", m_vtype); break; } } return true; } -static bool check_array(ast_value *self, ast_value *array) +bool ast_value::checkArray(const ast_value &array) const { - if (array->m_flags & AST_FLAG_ARRAY_INIT && array->m_initlist.empty()) { - compile_error(self->m_context, "array without size: %s", self->m_name); + if (array.m_flags & AST_FLAG_ARRAY_INIT && array.m_initlist.empty()) { + compile_error(m_context, "array without size: %s", m_name); return false; } - /* we are lame now - considering the way QC works we won't tolerate arrays > 1024 elements */ - if (!array->m_count || array->m_count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE)) { - compile_error(self->m_context, "Invalid array of size %lu", (unsigned long)array->m_count); + // we are lame now - considering the way QC works we won't tolerate arrays > 1024 elements + if (!array.m_count || array.m_count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE)) { + compile_error(m_context, "Invalid array of size %lu", (unsigned long)array.m_count); return false; } return true; } -bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) +bool ast_value::generateGlobal(ir_builder *ir, bool isfield) { - ir_value *v = nullptr; - - if (self->m_vtype == TYPE_NIL) { - compile_error(self->m_context, "internal error: trying to generate a variable of TYPE_NIL"); + if (m_vtype == TYPE_NIL) { + compile_error(m_context, "internal error: trying to generate a variable of TYPE_NIL"); return false; } - if (self->m_hasvalue && self->m_vtype == TYPE_FUNCTION) - { - ir_function *func = ir_builder_create_function(ir, self->m_name, self->m_next->m_vtype); - if (!func) - return false; - func->m_context = self->m_context; - func->m_value->m_context = self->m_context; - - self->m_constval.vfunc->m_ir_func = func; - self->m_ir_v = func->m_value; - if (self->m_flags & AST_FLAG_INCLUDE_DEF) - self->m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF; - if (self->m_flags & AST_FLAG_ERASEABLE) - self->m_ir_v->m_flags |= IR_FLAG_ERASABLE; - if (self->m_flags & AST_FLAG_BLOCK_COVERAGE) - func->m_flags |= IR_FLAG_BLOCK_COVERAGE; - /* The function is filled later on ast_function_codegen... */ - return true; - } + if (m_hasvalue && m_vtype == TYPE_FUNCTION) + return generateGlobalFunction(ir); - if (isfield && self->m_vtype == TYPE_FIELD) { - ast_expression *fieldtype = self->m_next; + if (isfield && m_vtype == TYPE_FIELD) + return generateGlobalField(ir); - if (self->m_hasvalue) { - compile_error(self->m_context, "TODO: constant field pointers with value"); - goto error; + ir_value *v = nullptr; + if (m_vtype == TYPE_ARRAY) { + v = prepareGlobalArray(ir); + if (!v) + return false; + } else { + // Arrays don't do this since there's no "array" value which spans across the + // whole thing. + v = ir_builder_create_global(ir, m_name, m_vtype); + if (!v) { + compile_error(m_context, "ir_builder_create_global failed on `%s`", m_name); + return false; } + codegen_output_type(this, v); + v->m_context = m_context; + } - if (fieldtype->m_vtype == TYPE_ARRAY) { - size_t ai; - char *name; - size_t namelen; - - ast_expression *elemtype; - qc_type vtype; - ast_value *array = (ast_value*)fieldtype; - - if (!ast_istype(fieldtype, ast_value)) { - compile_error(self->m_context, "internal error: ast_value required"); - return false; - } - - if (!check_array(self, array)) - return false; + /* link us to the ir_value */ + v->m_cvq = m_cvq; + m_ir_v = v; - elemtype = array->m_next; - vtype = elemtype->m_vtype; + if (m_flags & AST_FLAG_INCLUDE_DEF) + m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF; + if (m_flags & AST_FLAG_ERASEABLE) + m_ir_v->m_flags |= IR_FLAG_ERASABLE; - v = ir_builder_create_field(ir, self->m_name, vtype); - if (!v) { - compile_error(self->m_context, "ir_builder_create_global failed on `%s`", self->m_name); + /* initialize */ + if (m_hasvalue) { + switch (m_vtype) + { + case TYPE_FLOAT: + if (!ir_value_set_float(v, m_constval.vfloat)) + return false; + break; + case TYPE_VECTOR: + if (!ir_value_set_vector(v, m_constval.vvec)) + return false; + break; + case TYPE_STRING: + if (!ir_value_set_string(v, m_constval.vstring)) + return false; + break; + case TYPE_ARRAY: + if (!setGlobalArray()) + return false; + break; + case TYPE_FUNCTION: + compile_error(m_context, "global of type function not properly generated"); return false; - } - v->m_context = self->m_context; - v->m_unique_life = true; - v->m_locked = true; - array->m_ir_v = self->m_ir_v = v; - - if (self->m_flags & AST_FLAG_INCLUDE_DEF) - self->m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF; - if (self->m_flags & AST_FLAG_ERASEABLE) - self->m_ir_v->m_flags |= IR_FLAG_ERASABLE; - - namelen = strlen(self->m_name); - name = (char*)mem_a(namelen + 16); - util_strncpy(name, self->m_name, namelen); - - array->m_ir_values = (ir_value**)mem_a(sizeof(array->m_ir_values[0]) * array->m_count); - array->m_ir_values[0] = v; - for (ai = 1; ai < array->m_count; ++ai) { - util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai); - array->m_ir_values[ai] = ir_builder_create_field(ir, name, vtype); - if (!array->m_ir_values[ai]) { - mem_d(name); - compile_error(self->m_context, "ir_builder_create_global failed on `%s`", name); + /* Cannot generate an IR value for a function, + * need a pointer pointing to a function rather. + */ + case TYPE_FIELD: + if (!m_constval.vfield) { + compile_error(m_context, "field constant without vfield set"); return false; } - array->m_ir_values[ai]->m_context = self->m_context; - array->m_ir_values[ai]->m_unique_life = true; - array->m_ir_values[ai]->m_locked = true; - if (self->m_flags & AST_FLAG_INCLUDE_DEF) - self->m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF; - } - mem_d(name); - } - else - { - v = ir_builder_create_field(ir, self->m_name, self->m_next->m_vtype); - if (!v) - return false; - v->m_context = self->m_context; - self->m_ir_v = v; - if (self->m_flags & AST_FLAG_INCLUDE_DEF) - self->m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF; - - if (self->m_flags & AST_FLAG_ERASEABLE) - self->m_ir_v->m_flags |= IR_FLAG_ERASABLE; + if (!m_constval.vfield->m_ir_v) { + compile_error(m_context, "field constant generated before its field"); + return false; + } + if (!ir_value_set_field(v, m_constval.vfield->m_ir_v)) + return false; + break; + default: + compile_error(m_context, "TODO: global constant type %i", m_vtype); + break; } - return true; } - if (self->m_vtype == TYPE_ARRAY) { - size_t ai; - char *name; - size_t namelen; + return true; +} + +bool ast_value::generateGlobalFunction(ir_builder *ir) +{ + ir_function *func = ir_builder_create_function(ir, m_name, m_next->m_vtype); + if (!func) + return false; + func->m_context = m_context; + func->m_value->m_context = m_context; - ast_expression *elemtype = self->m_next; - qc_type vtype = elemtype->m_vtype; + m_constval.vfunc->m_ir_func = func; + m_ir_v = func->m_value; + if (m_flags & AST_FLAG_INCLUDE_DEF) + m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF; + if (m_flags & AST_FLAG_ERASEABLE) + m_ir_v->m_flags |= IR_FLAG_ERASABLE; + if (m_flags & AST_FLAG_BLOCK_COVERAGE) + func->m_flags |= IR_FLAG_BLOCK_COVERAGE; + // The function is filled later on ast_function::generateFunction... + return true; +} - if (self->m_flags & AST_FLAG_ARRAY_INIT && !self->m_count) { - compile_error(self->m_context, "array `%s' has no size", self->m_name); +bool ast_value::generateGlobalField(ir_builder *ir) +{ + ast_expression *fieldtype = m_next; + + if (m_hasvalue) { + compile_error(m_context, "TODO: constant field pointers with value"); + return false; + } + + if (fieldtype->m_vtype == TYPE_ARRAY) { + if (!ast_istype(fieldtype, ast_value)) { + compile_error(m_context, "internal error: ast_value required"); return false; } + ast_value *array = reinterpret_cast(fieldtype); - /* same as with field arrays */ - if (!check_array(self, self)) + if (!checkArray(*array)) return false; - v = ir_builder_create_global(ir, self->m_name, vtype); + ast_expression *elemtype = array->m_next; + qc_type vtype = elemtype->m_vtype; + + ir_value *v = ir_builder_create_field(ir, m_name, vtype); if (!v) { - compile_error(self->m_context, "ir_builder_create_global failed `%s`", self->m_name); + compile_error(m_context, "ir_builder_create_global failed on `%s`", m_name); return false; } - v->m_context = self->m_context; + v->m_context = m_context; v->m_unique_life = true; v->m_locked = true; - - if (self->m_flags & AST_FLAG_INCLUDE_DEF) - v->m_flags |= IR_FLAG_INCLUDE_DEF; - if (self->m_flags & AST_FLAG_ERASEABLE) - self->m_ir_v->m_flags |= IR_FLAG_ERASABLE; - - namelen = strlen(self->m_name); - name = (char*)mem_a(namelen + 16); - util_strncpy(name, self->m_name, namelen); - - self->m_ir_values = (ir_value**)mem_a(sizeof(self->m_ir_values[0]) * self->m_count); - self->m_ir_values[0] = v; - for (ai = 1; ai < self->m_count; ++ai) { - util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai); - self->m_ir_values[ai] = ir_builder_create_global(ir, name, vtype); - if (!self->m_ir_values[ai]) { - mem_d(name); - compile_error(self->m_context, "ir_builder_create_global failed `%s`", name); + array->m_ir_v = m_ir_v = v; + + if (m_flags & AST_FLAG_INCLUDE_DEF) + m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF; + if (m_flags & AST_FLAG_ERASEABLE) + m_ir_v->m_flags |= IR_FLAG_ERASABLE; + + const size_t namelen = m_name.length(); + std::unique_ptr name(new char[namelen+16]); + util_strncpy(name.get(), m_name.c_str(), namelen); + + array->m_ir_values.resize(array->m_count); + array->m_ir_values[0] = v; + for (size_t ai = 1; ai < array->m_count; ++ai) { + util_snprintf(name.get() + namelen, 16, "[%u]", (unsigned int)ai); + array->m_ir_values[ai] = ir_builder_create_field(ir, name.get(), vtype); + if (!array->m_ir_values[ai]) { + compile_error(m_context, "ir_builder_create_global failed on `%s`", name.get()); return false; } - self->m_ir_values[ai]->m_context = self->m_context; - self->m_ir_values[ai]->m_unique_life = true; - self->m_ir_values[ai]->m_locked = true; - if (self->m_flags & AST_FLAG_INCLUDE_DEF) - self->m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF; + array->m_ir_values[ai]->m_context = m_context; + array->m_ir_values[ai]->m_unique_life = true; + array->m_ir_values[ai]->m_locked = true; + if (m_flags & AST_FLAG_INCLUDE_DEF) + m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF; } - mem_d(name); } else { - /* Arrays don't do this since there's no "array" value which spans across the - * whole thing. - */ - v = ir_builder_create_global(ir, self->m_name, self->m_vtype); - if (!v) { - compile_error(self->m_context, "ir_builder_create_global failed on `%s`", self->m_name); + ir_value *v = ir_builder_create_field(ir, m_name, m_next->m_vtype); + if (!v) return false; - } - codegen_output_type(self, v); - v->m_context = self->m_context; + v->m_context = m_context; + m_ir_v = v; + if (m_flags & AST_FLAG_INCLUDE_DEF) + m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF; + + if (m_flags & AST_FLAG_ERASEABLE) + m_ir_v->m_flags |= IR_FLAG_ERASABLE; } + return true; +} - /* link us to the ir_value */ - v->m_cvq = self->m_cvq; - self->m_ir_v = v; +ir_value *ast_value::prepareGlobalArray(ir_builder *ir) +{ + ast_expression *elemtype = m_next; + qc_type vtype = elemtype->m_vtype; - if (self->m_flags & AST_FLAG_INCLUDE_DEF) - self->m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF; - if (self->m_flags & AST_FLAG_ERASEABLE) - self->m_ir_v->m_flags |= IR_FLAG_ERASABLE; + if (m_flags & AST_FLAG_ARRAY_INIT && !m_count) { + compile_error(m_context, "array `%s' has no size", m_name); + return nullptr; + } - /* initialize */ - if (self->m_hasvalue) { - switch (self->m_vtype) - { - case TYPE_FLOAT: - if (!ir_value_set_float(v, self->m_constval.vfloat)) - goto error; - break; - case TYPE_VECTOR: - if (!ir_value_set_vector(v, self->m_constval.vvec)) - goto error; - break; - case TYPE_STRING: - if (!ir_value_set_string(v, self->m_constval.vstring)) - goto error; - break; - case TYPE_ARRAY: - ast_global_array_set(self); - break; - case TYPE_FUNCTION: - compile_error(self->m_context, "global of type function not properly generated"); - goto error; - /* Cannot generate an IR value for a function, - * need a pointer pointing to a function rather. - */ - case TYPE_FIELD: - if (!self->m_constval.vfield) { - compile_error(self->m_context, "field constant without vfield set"); - goto error; - } - if (!self->m_constval.vfield->m_ir_v) { - compile_error(self->m_context, "field constant generated before its field"); - goto error; - } - if (!ir_value_set_field(v, self->m_constval.vfield->m_ir_v)) - goto error; - break; - default: - compile_error(self->m_context, "TODO: global constant type %i", self->m_vtype); - break; + /* same as with field arrays */ + if (!checkArray(*this)) + return nullptr; + + ir_value *v = ir_builder_create_global(ir, m_name, vtype); + if (!v) { + compile_error(m_context, "ir_builder_create_global failed `%s`", m_name); + return nullptr; + } + v->m_context = m_context; + v->m_unique_life = true; + v->m_locked = true; + + if (m_flags & AST_FLAG_INCLUDE_DEF) + v->m_flags |= IR_FLAG_INCLUDE_DEF; + if (m_flags & AST_FLAG_ERASEABLE) + m_ir_v->m_flags |= IR_FLAG_ERASABLE; + + const size_t namelen = m_name.length(); + std::unique_ptr name(new char[namelen+16]); + util_strncpy(name.get(), m_name.c_str(), namelen); + + m_ir_values.resize(m_count); + m_ir_values[0] = v; + for (size_t ai = 1; ai < m_count; ++ai) { + util_snprintf(name.get() + namelen, 16, "[%u]", (unsigned int)ai); + m_ir_values[ai] = ir_builder_create_global(ir, name.get(), vtype); + if (!m_ir_values[ai]) { + compile_error(m_context, "ir_builder_create_global failed `%s`", name.get()); + return nullptr; } + m_ir_values[ai]->m_context = m_context; + m_ir_values[ai]->m_unique_life = true; + m_ir_values[ai]->m_locked = true; + if (m_flags & AST_FLAG_INCLUDE_DEF) + m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF; } - return true; -error: /* clean up */ - if (v) delete v; - return false; + return v; } -static bool ast_local_codegen(ast_value *self, ir_function *func, bool param) +bool ast_value::generateLocal(ir_function *func, bool param) { - ir_value *v = nullptr; - - if (self->m_vtype == TYPE_NIL) { - compile_error(self->m_context, "internal error: trying to generate a variable of TYPE_NIL"); + if (m_vtype == TYPE_NIL) { + compile_error(m_context, "internal error: trying to generate a variable of TYPE_NIL"); return false; } - if (self->m_hasvalue && self->m_vtype == TYPE_FUNCTION) + if (m_hasvalue && m_vtype == TYPE_FUNCTION) { /* Do we allow local functions? I think not... * this is NOT a function pointer atm. @@ -1436,96 +1330,86 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param) return false; } - if (self->m_vtype == TYPE_ARRAY) { - size_t ai; - char *name; - size_t namelen; - - ast_expression *elemtype = self->m_next; + ir_value *v = nullptr; + if (m_vtype == TYPE_ARRAY) { + ast_expression *elemtype = m_next; qc_type vtype = elemtype->m_vtype; func->m_flags |= IR_FLAG_HAS_ARRAYS; - if (param && !(self->m_flags & AST_FLAG_IS_VARARG)) { - compile_error(self->m_context, "array-parameters are not supported"); + if (param && !(m_flags & AST_FLAG_IS_VARARG)) { + compile_error(m_context, "array-parameters are not supported"); return false; } /* we are lame now - considering the way QC works we won't tolerate arrays > 1024 elements */ - if (!check_array(self, self)) + if (!checkArray(*this)) return false; - self->m_ir_values = (ir_value**)mem_a(sizeof(self->m_ir_values[0]) * self->m_count); - if (!self->m_ir_values) { - compile_error(self->m_context, "failed to allocate array values"); - return false; - } - - v = ir_function_create_local(func, self->m_name, vtype, param); + m_ir_values.resize(m_count); + v = ir_function_create_local(func, m_name, vtype, param); if (!v) { - compile_error(self->m_context, "internal error: ir_function_create_local failed"); + compile_error(m_context, "internal error: ir_function_create_local failed"); return false; } - v->m_context = self->m_context; + v->m_context = m_context; v->m_unique_life = true; v->m_locked = true; - namelen = strlen(self->m_name); - name = (char*)mem_a(namelen + 16); - util_strncpy(name, self->m_name, namelen); + const size_t namelen = m_name.length(); + std::unique_ptr name(new char[namelen+16]); + util_strncpy(name.get(), m_name.c_str(), namelen); - self->m_ir_values[0] = v; - for (ai = 1; ai < self->m_count; ++ai) { - util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai); - self->m_ir_values[ai] = ir_function_create_local(func, name, vtype, param); - if (!self->m_ir_values[ai]) { - compile_error(self->m_context, "internal_error: ir_builder_create_global failed on `%s`", name); + m_ir_values[0] = v; + for (size_t ai = 1; ai < m_count; ++ai) { + util_snprintf(name.get() + namelen, 16, "[%u]", (unsigned int)ai); + m_ir_values[ai] = ir_function_create_local(func, name.get(), vtype, param); + if (!m_ir_values[ai]) { + compile_error(m_context, "internal_error: ir_builder_create_global failed on `%s`", name.get()); return false; } - self->m_ir_values[ai]->m_context = self->m_context; - self->m_ir_values[ai]->m_unique_life = true; - self->m_ir_values[ai]->m_locked = true; + m_ir_values[ai]->m_context = m_context; + m_ir_values[ai]->m_unique_life = true; + m_ir_values[ai]->m_locked = true; } - mem_d(name); } else { - v = ir_function_create_local(func, self->m_name, self->m_vtype, param); + v = ir_function_create_local(func, m_name, m_vtype, param); if (!v) return false; - codegen_output_type(self, v); - v->m_context = self->m_context; + codegen_output_type(this, v); + v->m_context = m_context; } - /* A constant local... hmmm... - * I suppose the IR will have to deal with this - */ - if (self->m_hasvalue) { - switch (self->m_vtype) + // A constant local... hmmm... + // I suppose the IR will have to deal with this + if (m_hasvalue) { + switch (m_vtype) { case TYPE_FLOAT: - if (!ir_value_set_float(v, self->m_constval.vfloat)) + if (!ir_value_set_float(v, m_constval.vfloat)) goto error; break; case TYPE_VECTOR: - if (!ir_value_set_vector(v, self->m_constval.vvec)) + if (!ir_value_set_vector(v, m_constval.vvec)) goto error; break; case TYPE_STRING: - if (!ir_value_set_string(v, self->m_constval.vstring)) + if (!ir_value_set_string(v, m_constval.vstring)) goto error; break; default: - compile_error(self->m_context, "TODO: global constant type %i", self->m_vtype); + compile_error(m_context, "TODO: global constant type %i", m_vtype); break; } } - /* link us to the ir_value */ - v->m_cvq = self->m_cvq; - self->m_ir_v = v; + // link us to the ir_value + v->m_cvq = m_cvq; + m_ir_v = v; - if (!ast_generate_accessors(self, func->m_owner)) + if (!generateAccessors(func->m_owner)) return false; return true; @@ -1534,172 +1418,164 @@ error: /* clean up */ return false; } -bool ast_generate_accessors(ast_value *self, ir_builder *ir) +bool ast_value::generateAccessors(ir_builder *ir) { size_t i; bool warn = OPTS_WARN(WARN_USED_UNINITIALIZED); - if (!self->m_setter || !self->m_getter) + if (!m_setter || !m_getter) return true; - for (i = 0; i < self->m_count; ++i) { - if (!self->m_ir_values) { - compile_error(self->m_context, "internal error: no array values generated for `%s`", self->m_name); - return false; - } - if (!self->m_ir_values[i]) { - compile_error(self->m_context, "internal error: not all array values have been generated for `%s`", self->m_name); + if (m_count && m_ir_values.empty()) { + compile_error(m_context, "internal error: no array values generated for `%s`", m_name); + return false; + } + for (i = 0; i < m_count; ++i) { + if (!m_ir_values[i]) { + compile_error(m_context, "internal error: not all array values have been generated for `%s`", m_name); return false; } - if (!self->m_ir_values[i]->m_life.empty()) { - compile_error(self->m_context, "internal error: function containing `%s` already generated", self->m_name); + if (!m_ir_values[i]->m_life.empty()) { + compile_error(m_context, "internal error: function containing `%s` already generated", m_name); return false; } } opts_set(opts.warn, WARN_USED_UNINITIALIZED, false); - if (self->m_setter) { - if (!ast_global_codegen (self->m_setter, ir, false) || - !ast_function_codegen(self->m_setter->m_constval.vfunc, ir) || - !ir_function_finalize(self->m_setter->m_constval.vfunc->m_ir_func)) + if (m_setter) { + if (!m_setter->generateGlobal(ir, false) || + !m_setter->m_constval.vfunc->generateFunction(ir) || + !ir_function_finalize(m_setter->m_constval.vfunc->m_ir_func)) { - compile_error(self->m_context, "internal error: failed to generate setter for `%s`", self->m_name); + compile_error(m_context, "internal error: failed to generate setter for `%s`", m_name); opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn); return false; } } - if (self->m_getter) { - if (!ast_global_codegen (self->m_getter, ir, false) || - !ast_function_codegen(self->m_getter->m_constval.vfunc, ir) || - !ir_function_finalize(self->m_getter->m_constval.vfunc->m_ir_func)) + if (m_getter) { + if (!m_getter->generateGlobal(ir, false) || + !m_getter->m_constval.vfunc->generateFunction(ir) || + !ir_function_finalize(m_getter->m_constval.vfunc->m_ir_func)) { - compile_error(self->m_context, "internal error: failed to generate getter for `%s`", self->m_name); + compile_error(m_context, "internal error: failed to generate getter for `%s`", m_name); opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn); return false; } } - for (i = 0; i < self->m_count; ++i) - self->m_ir_values[i]->m_life.clear(); + for (i = 0; i < m_count; ++i) + m_ir_values[i]->m_life.clear(); opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn); return true; } -bool ast_function_codegen(ast_function *self, ir_builder *ir) +bool ast_function::generateFunction(ir_builder *ir) { - ir_function *irf; - ir_value *dummy; - ast_expression *ec; - ast_expression_codegen *cgen; - (void)ir; - irf = self->m_ir_func; + ir_value *dummy; + + ir_function *irf = m_ir_func; if (!irf) { - compile_error(self->m_context, "internal error: ast_function's related ast_value was not generated yet"); + compile_error(m_context, "internal error: ast_function's related ast_value was not generated yet"); return false; } /* fill the parameter list */ - ec = self->m_function_type; - for (auto &it : ec->m_type_params) { + for (auto &it : m_function_type->m_type_params) { if (it->m_vtype == TYPE_FIELD) vec_push(irf->m_params, it->m_next->m_vtype); else vec_push(irf->m_params, it->m_vtype); - if (!self->m_builtin) { - if (!ast_local_codegen(it, self->m_ir_func, true)) + if (!m_builtin) { + if (!it->generateLocal(m_ir_func, true)) return false; } } - if (self->m_varargs) { - if (!ast_local_codegen(self->m_varargs, self->m_ir_func, true)) + if (m_varargs) { + if (!m_varargs->generateLocal(m_ir_func, true)) return false; - irf->m_max_varargs = self->m_varargs->m_count; + irf->m_max_varargs = m_varargs->m_count; } - if (self->m_builtin) { - irf->m_builtin = self->m_builtin; + if (m_builtin) { + irf->m_builtin = m_builtin; return true; } /* have a local return value variable? */ - if (self->m_return_value) { - if (!ast_local_codegen(self->m_return_value, self->m_ir_func, false)) + if (m_return_value) { + if (!m_return_value->generateLocal(m_ir_func, false)) return false; } - if (self->m_blocks.empty()) { - compile_error(self->m_context, "function `%s` has no body", self->m_name); + if (m_blocks.empty()) { + compile_error(m_context, "function `%s` has no body", m_name); return false; } - irf->m_first = self->m_curblock = ir_function_create_block(self->m_context, irf, "entry"); - if (!self->m_curblock) { - compile_error(self->m_context, "failed to allocate entry block for `%s`", self->m_name); + irf->m_first = m_curblock = ir_function_create_block(m_context, irf, "entry"); + if (!m_curblock) { + compile_error(m_context, "failed to allocate entry block for `%s`", m_name); return false; } - if (self->m_argc) { + if (m_argc) { ir_value *va_count; ir_value *fixed; ir_value *sub; - if (!ast_local_codegen(self->m_argc, self->m_ir_func, true)) + if (!m_argc->generateLocal(m_ir_func, true)) return false; - cgen = self->m_argc->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_argc), self, false, &va_count)) + if (!m_argc->codegen(this, false, &va_count)) return false; - cgen = self->m_fixedparams->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_fixedparams), self, false, &fixed)) + if (!m_fixedparams->codegen(this, false, &fixed)) return false; - sub = ir_block_create_binop(self->m_curblock, self->m_context, - ast_function_label(self, "va_count"), INSTR_SUB_F, + sub = ir_block_create_binop(m_curblock, m_context, + makeLabel("va_count"), INSTR_SUB_F, ir_builder_get_va_count(ir), fixed); if (!sub) return false; - if (!ir_block_create_store_op(self->m_curblock, self->m_context, INSTR_STORE_F, + if (!ir_block_create_store_op(m_curblock, m_context, INSTR_STORE_F, va_count, sub)) { return false; } } - for (auto &it : self->m_blocks) { - cgen = it->m_codegen; - if (!(*cgen)(it.get(), self, false, &dummy)) - return false; + for (auto &it : m_blocks) { + if (!it->codegen(this, false, &dummy)) + return false; } /* TODO: check return types */ - if (!self->m_curblock->m_final) + if (!m_curblock->m_final) { - if (!self->m_function_type->m_next || - self->m_function_type->m_next->m_vtype == TYPE_VOID) + if (!m_function_type->m_next || + m_function_type->m_next->m_vtype == TYPE_VOID) { - return ir_block_create_return(self->m_curblock, self->m_context, nullptr); + return ir_block_create_return(m_curblock, m_context, nullptr); } - else if (vec_size(self->m_curblock->m_entries) || self->m_curblock == irf->m_first) + else if (vec_size(m_curblock->m_entries) || m_curblock == irf->m_first) { - if (self->m_return_value) { - cgen = self->m_return_value->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_return_value), self, false, &dummy)) + if (m_return_value) { + if (!m_return_value->codegen(this, false, &dummy)) return false; - return ir_block_create_return(self->m_curblock, self->m_context, dummy); + return ir_block_create_return(m_curblock, m_context, dummy); } - else if (compile_warning(self->m_context, WARN_MISSING_RETURN_VALUES, + else if (compile_warning(m_context, WARN_MISSING_RETURN_VALUES, "control reaches end of non-void function (`%s`) via %s", - self->m_name, self->m_curblock->m_label.c_str())) + m_name.c_str(), m_curblock->m_label.c_str())) { return false; } - return ir_block_create_return(self->m_curblock, self->m_context, nullptr); + return ir_block_create_return(m_curblock, m_context, nullptr); } } return true; } -static bool starts_a_label(ast_expression *ex) +static bool starts_a_label(const ast_expression *ex) { while (ex && ast_istype(ex, ast_block)) { - ast_block *b = (ast_block*)ex; + auto b = reinterpret_cast(ex); ex = b->m_exprs[0]; } if (!ex) @@ -1713,19 +1589,19 @@ static bool starts_a_label(ast_expression *ex) * curly braces {...}. * While in the IR it represents a block in terms of control-flow. */ -bool ast_block_codegen(ast_block *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_block::codegen(ast_function *func, bool lvalue, ir_value **out) { /* We don't use this * Note: an ast-representation using the comma-operator * of the form: (a, b, c) = x should not assign to c... */ if (lvalue) { - compile_error(self->m_context, "not an l-value (code-block)"); + compile_error(m_context, "not an l-value (code-block)"); return false; } - if (self->m_outr) { - *out = self->m_outr; + if (m_outr) { + *out = m_outr; return true; } @@ -1738,55 +1614,51 @@ bool ast_block_codegen(ast_block *self, ast_function *func, bool lvalue, ir_valu *out = nullptr; /* generate locals */ - for (auto &it : self->m_locals) { - if (!ast_local_codegen(it, func->m_ir_func, false)) { + for (auto &it : m_locals) { + if (!it->generateLocal(func->m_ir_func, false)) { if (OPTS_OPTION_BOOL(OPTION_DEBUG)) - compile_error(self->m_context, "failed to generate local `%s`", it->m_name); + compile_error(m_context, "failed to generate local `%s`", it->m_name); return false; } } - for (auto &it : self->m_exprs) { - ast_expression_codegen *gen; + for (auto &it : m_exprs) { if (func->m_curblock->m_final && !starts_a_label(it)) { if (compile_warning(it->m_context, WARN_UNREACHABLE_CODE, "unreachable statement")) return false; continue; } - gen = it->m_codegen; - if (!(*gen)(it, func, false, out)) + if (!it->codegen(func, false, out)) return false; } - self->m_outr = *out; + m_outr = *out; return true; } -bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_store::codegen(ast_function *func, bool lvalue, ir_value **out) { - ast_expression_codegen *cgen; ir_value *left = nullptr; ir_value *right = nullptr; - ast_value *arr; ast_value *idx = 0; ast_array_index *ai = nullptr; - if (lvalue && self->m_outl) { - *out = self->m_outl; + if (lvalue && m_outl) { + *out = m_outl; return true; } - if (!lvalue && self->m_outr) { - *out = self->m_outr; + if (!lvalue && m_outr) { + *out = m_outr; return true; } - if (ast_istype(self->m_dest, ast_array_index)) + if (ast_istype(m_dest, ast_array_index)) { - ai = (ast_array_index*)self->m_dest; + ai = (ast_array_index*)m_dest; idx = (ast_value*)ai->m_index; if (ast_istype(ai->m_index, ast_value) && idx->m_hasvalue && idx->m_cvq == CV_CONST) @@ -1799,53 +1671,48 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu ir_instr *call; if (lvalue) { - compile_error(self->m_context, "array-subscript assignment cannot produce lvalues"); + compile_error(m_context, "array-subscript assignment cannot produce lvalues"); return false; } - arr = (ast_value*)ai->m_array; + auto arr = reinterpret_cast(ai->m_array); if (!ast_istype(ai->m_array, ast_value) || !arr->m_setter) { - compile_error(self->m_context, "value has no setter (%s)", arr->m_name); + compile_error(m_context, "value has no setter (%s)", arr->m_name); return false; } - cgen = idx->m_codegen; - if (!(*cgen)((ast_expression*)(idx), func, false, &iridx)) + if (!idx->codegen(func, false, &iridx)) return false; - cgen = arr->m_setter->m_codegen; - if (!(*cgen)((ast_expression*)(arr->m_setter), func, true, &funval)) + if (!arr->m_setter->codegen(func, true, &funval)) return false; - cgen = self->m_source->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_source), func, false, &right)) + if (!m_source->codegen(func, false, &right)) return false; - call = ir_block_create_call(func->m_curblock, self->m_context, ast_function_label(func, "store"), funval, false); + call = ir_block_create_call(func->m_curblock, m_context, func->makeLabel("store"), funval, false); if (!call) return false; ir_call_param(call, iridx); ir_call_param(call, right); - self->m_outr = right; + m_outr = right; } else { - /* regular code */ + // regular code - cgen = self->m_dest->m_codegen; - /* lvalue! */ - if (!(*cgen)((ast_expression*)(self->m_dest), func, true, &left)) + // lvalue! + if (!m_dest->codegen(func, true, &left)) return false; - self->m_outl = left; + m_outl = left; - cgen = self->m_source->m_codegen; /* rvalue! */ - if (!(*cgen)((ast_expression*)(self->m_source), func, false, &right)) + if (!m_source->codegen(func, false, &right)) return false; - if (!ir_block_create_store_op(func->m_curblock, self->m_context, self->m_op, left, right)) + if (!ir_block_create_store_op(func->m_curblock, m_context, m_op, left, right)) return false; - self->m_outr = right; + m_outr = right; } /* Theoretically, an assinment returns its left side as an @@ -1860,24 +1727,23 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu return true; } -bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_binary::codegen(ast_function *func, bool lvalue, ir_value **out) { - ast_expression_codegen *cgen; ir_value *left, *right; /* A binary operation cannot yield an l-value */ if (lvalue) { - compile_error(self->m_context, "not an l-value (binop)"); + compile_error(m_context, "not an l-value (binop)"); return false; } - if (self->m_outr) { - *out = self->m_outr; + if (m_outr) { + *out = m_outr; return true; } if ((OPTS_FLAG(SHORT_LOGIC) || OPTS_FLAG(PERL_LOGIC)) && - (self->m_op == INSTR_AND || self->m_op == INSTR_OR)) + (m_op == INSTR_AND || m_op == INSTR_OR)) { /* NOTE: The short-logic path will ignore right_first */ @@ -1889,24 +1755,23 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va /* prepare end-block */ merge_id = func->m_ir_func->m_blocks.size(); - merge = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "sce_merge")); + merge = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("sce_merge")); /* generate the left expression */ - cgen = self->m_left->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_left), func, false, &left)) + if (!m_left->codegen(func, false, &left)) return false; /* remember the block */ from_left = func->m_curblock; /* create a new block for the right expression */ - other = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "sce_other")); - if (self->m_op == INSTR_AND) { + other = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("sce_other")); + if (m_op == INSTR_AND) { /* on AND: left==true -> other */ - if (!ir_block_create_if(func->m_curblock, self->m_context, left, other, merge)) + if (!ir_block_create_if(func->m_curblock, m_context, left, other, merge)) return false; } else { /* on OR: left==false -> other */ - if (!ir_block_create_if(func->m_curblock, self->m_context, left, merge, other)) + if (!ir_block_create_if(func->m_curblock, m_context, left, merge, other)) return false; } /* use the likely flag */ @@ -1915,14 +1780,13 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va /* enter the right-expression's block */ func->m_curblock = other; /* generate */ - cgen = self->m_right->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_right), func, false, &right)) + if (!m_right->codegen(func, false, &right)) return false; /* remember block */ from_right = func->m_curblock; /* jump to the merge block */ - if (!ir_block_create_jump(func->m_curblock, self->m_context, merge)) + if (!ir_block_create_jump(func->m_curblock, m_context, merge)) return false; algo::shiftback(func->m_ir_func->m_blocks.begin() + merge_id, @@ -1933,9 +1797,9 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va //func->m_ir_func->m_blocks.emplace_back(merge); func->m_curblock = merge; - phi = ir_block_create_phi(func->m_curblock, self->m_context, - ast_function_label(func, "sce_value"), - self->m_vtype); + phi = ir_block_create_phi(func->m_curblock, m_context, + func->makeLabel("sce_value"), + m_vtype); ir_phi_add(phi, from_left, left); ir_phi_add(phi, from_right, right); *out = ir_phi_value(phi); @@ -1945,72 +1809,67 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va if (!OPTS_FLAG(PERL_LOGIC)) { /* cast-to-bool */ if (OPTS_FLAG(CORRECT_LOGIC) && (*out)->m_vtype == TYPE_VECTOR) { - *out = ir_block_create_unary(func->m_curblock, self->m_context, - ast_function_label(func, "sce_bool_v"), + *out = ir_block_create_unary(func->m_curblock, m_context, + func->makeLabel("sce_bool_v"), INSTR_NOT_V, *out); if (!*out) return false; - *out = ir_block_create_unary(func->m_curblock, self->m_context, - ast_function_label(func, "sce_bool"), + *out = ir_block_create_unary(func->m_curblock, m_context, + func->makeLabel("sce_bool"), INSTR_NOT_F, *out); if (!*out) return false; } else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && (*out)->m_vtype == TYPE_STRING) { - *out = ir_block_create_unary(func->m_curblock, self->m_context, - ast_function_label(func, "sce_bool_s"), + *out = ir_block_create_unary(func->m_curblock, m_context, + func->makeLabel("sce_bool_s"), INSTR_NOT_S, *out); if (!*out) return false; - *out = ir_block_create_unary(func->m_curblock, self->m_context, - ast_function_label(func, "sce_bool"), + *out = ir_block_create_unary(func->m_curblock, m_context, + func->makeLabel("sce_bool"), INSTR_NOT_F, *out); if (!*out) return false; } else { - *out = ir_block_create_binop(func->m_curblock, self->m_context, - ast_function_label(func, "sce_bool"), + *out = ir_block_create_binop(func->m_curblock, m_context, + func->makeLabel("sce_bool"), INSTR_AND, *out, *out); if (!*out) return false; } } - self->m_outr = *out; - codegen_output_type(self, *out); + m_outr = *out; + codegen_output_type(this, *out); return true; } - if (self->m_right_first) { - cgen = self->m_right->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_right), func, false, &right)) + if (m_right_first) { + if (!m_right->codegen(func, false, &right)) return false; - cgen = self->m_left->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_left), func, false, &left)) + if (!m_left->codegen(func, false, &left)) return false; } else { - cgen = self->m_left->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_left), func, false, &left)) + if (!m_left->codegen(func, false, &left)) return false; - cgen = self->m_right->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_right), func, false, &right)) + if (!m_right->codegen(func, false, &right)) return false; } - *out = ir_block_create_binop(func->m_curblock, self->m_context, ast_function_label(func, "bin"), - self->m_op, left, right); + *out = ir_block_create_binop(func->m_curblock, m_context, func->makeLabel("bin"), + m_op, left, right); if (!*out) return false; - self->m_outr = *out; - codegen_output_type(self, *out); + m_outr = *out; + codegen_output_type(this, *out); return true; } -bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_binstore::codegen(ast_function *func, bool lvalue, ir_value **out) { - ast_expression_codegen *cgen; ir_value *leftl = nullptr, *leftr, *right, *bin; ast_value *arr; @@ -2018,20 +1877,20 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i ast_array_index *ai = nullptr; ir_value *iridx = nullptr; - if (lvalue && self->m_outl) { - *out = self->m_outl; + if (lvalue && m_outl) { + *out = m_outl; return true; } - if (!lvalue && self->m_outr) { - *out = self->m_outr; + if (!lvalue && m_outr) { + *out = m_outr; return true; } - if (ast_istype(self->m_dest, ast_array_index)) + if (ast_istype(m_dest, ast_array_index)) { - ai = (ast_array_index*)self->m_dest; + ai = (ast_array_index*)m_dest; idx = (ast_value*)ai->m_index; if (ast_istype(ai->m_index, ast_value) && idx->m_hasvalue && idx->m_cvq == CV_CONST) @@ -2041,23 +1900,20 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i /* for a binstore we need both an lvalue and an rvalue for the left side */ /* rvalue of destination! */ if (ai) { - cgen = idx->m_codegen; - if (!(*cgen)((ast_expression*)(idx), func, false, &iridx)) + if (!idx->codegen(func, false, &iridx)) return false; } - cgen = self->m_dest->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_dest), func, false, &leftr)) + if (!m_dest->codegen(func, false, &leftr)) return false; /* source as rvalue only */ - cgen = self->m_source->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_source), func, false, &right)) + if (!m_source->codegen(func, false, &right)) return false; /* now the binary */ - bin = ir_block_create_binop(func->m_curblock, self->m_context, ast_function_label(func, "binst"), - self->m_opbin, leftr, right); - self->m_outr = bin; + bin = ir_block_create_binop(func->m_curblock, m_context, func->makeLabel("binst"), + m_opbin, leftr, right); + m_outr = bin; if (ai) { /* we need to call the setter */ @@ -2065,37 +1921,35 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i ir_instr *call; if (lvalue) { - compile_error(self->m_context, "array-subscript assignment cannot produce lvalues"); + compile_error(m_context, "array-subscript assignment cannot produce lvalues"); return false; } arr = (ast_value*)ai->m_array; if (!ast_istype(ai->m_array, ast_value) || !arr->m_setter) { - compile_error(self->m_context, "value has no setter (%s)", arr->m_name); + compile_error(m_context, "value has no setter (%s)", arr->m_name); return false; } - cgen = arr->m_setter->m_codegen; - if (!(*cgen)((ast_expression*)(arr->m_setter), func, true, &funval)) + if (!arr->m_setter->codegen(func, true, &funval)) return false; - call = ir_block_create_call(func->m_curblock, self->m_context, ast_function_label(func, "store"), funval, false); + call = ir_block_create_call(func->m_curblock, m_context, func->makeLabel("store"), funval, false); if (!call) return false; ir_call_param(call, iridx); ir_call_param(call, bin); - self->m_outr = bin; + m_outr = bin; } else { - /* now store them */ - cgen = self->m_dest->m_codegen; - /* lvalue of destination */ - if (!(*cgen)((ast_expression*)(self->m_dest), func, true, &leftl)) + // now store them + // lvalue of destination + if (!m_dest->codegen(func, true, &leftl)) return false; - self->m_outl = leftl; + m_outl = leftl; - if (!ir_block_create_store_op(func->m_curblock, self->m_context, self->m_opstore, leftl, bin)) + if (!ir_block_create_store_op(func->m_curblock, m_context, m_opstore, leftl, bin)) return false; - self->m_outr = bin; + m_outr = bin; } /* Theoretically, an assinment returns its left side as an @@ -2110,39 +1964,36 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i return true; } -bool ast_unary_codegen(ast_unary *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_unary::codegen(ast_function *func, bool lvalue, ir_value **out) { - ast_expression_codegen *cgen; ir_value *operand; /* An unary operation cannot yield an l-value */ if (lvalue) { - compile_error(self->m_context, "not an l-value (binop)"); + compile_error(m_context, "not an l-value (binop)"); return false; } - if (self->m_outr) { - *out = self->m_outr; + if (m_outr) { + *out = m_outr; return true; } - cgen = self->m_operand->m_codegen; /* lvalue! */ - if (!(*cgen)((ast_expression*)(self->m_operand), func, false, &operand)) + if (!m_operand->codegen(func, false, &operand)) return false; - *out = ir_block_create_unary(func->m_curblock, self->m_context, ast_function_label(func, "unary"), - self->m_op, operand); + *out = ir_block_create_unary(func->m_curblock, m_context, func->makeLabel("unary"), + m_op, operand); if (!*out) return false; - self->m_outr = *out; + m_outr = *out; return true; } -bool ast_return_codegen(ast_return *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_return::codegen(ast_function *func, bool lvalue, ir_value **out) { - ast_expression_codegen *cgen; ir_value *operand; *out = nullptr; @@ -2151,136 +2002,129 @@ bool ast_return_codegen(ast_return *self, ast_function *func, bool lvalue, ir_va * anything... */ if (lvalue) { - compile_error(self->m_context, "return-expression is not an l-value"); + compile_error(m_context, "return-expression is not an l-value"); return false; } - if (self->m_outr) { - compile_error(self->m_context, "internal error: ast_return cannot be reused, it bears no result!"); + if (m_outr) { + compile_error(m_context, "internal error: ast_return cannot be reused, it bears no result!"); return false; } - self->m_outr = (ir_value*)1; + m_outr = (ir_value*)1; - if (self->m_operand) { - cgen = self->m_operand->m_codegen; + if (m_operand) { /* lvalue! */ - if (!(*cgen)((ast_expression*)(self->m_operand), func, false, &operand)) + if (!m_operand->codegen(func, false, &operand)) return false; - if (!ir_block_create_return(func->m_curblock, self->m_context, operand)) + if (!ir_block_create_return(func->m_curblock, m_context, operand)) return false; } else { - if (!ir_block_create_return(func->m_curblock, self->m_context, nullptr)) + if (!ir_block_create_return(func->m_curblock, m_context, nullptr)) return false; } return true; } -bool ast_entfield_codegen(ast_entfield *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_entfield::codegen(ast_function *func, bool lvalue, ir_value **out) { - ast_expression_codegen *cgen; ir_value *ent, *field; - /* This function needs to take the 'lvalue' flag into account! - * As lvalue we provide a field-pointer, as rvalue we provide the - * value in a temp. - */ + // This function needs to take the 'lvalue' flag into account! + // As lvalue we provide a field-pointer, as rvalue we provide the + // value in a temp. - if (lvalue && self->m_outl) { - *out = self->m_outl; + if (lvalue && m_outl) { + *out = m_outl; return true; } - if (!lvalue && self->m_outr) { - *out = self->m_outr; + if (!lvalue && m_outr) { + *out = m_outr; return true; } - cgen = self->m_entity->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_entity), func, false, &ent)) + if (!m_entity->codegen(func, false, &ent)) return false; - cgen = self->m_field->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_field), func, false, &field)) + if (!m_field->codegen(func, false, &field)) return false; if (lvalue) { /* address! */ - *out = ir_block_create_fieldaddress(func->m_curblock, self->m_context, ast_function_label(func, "efa"), + *out = ir_block_create_fieldaddress(func->m_curblock, m_context, func->makeLabel("efa"), ent, field); } else { - *out = ir_block_create_load_from_ent(func->m_curblock, self->m_context, ast_function_label(func, "efv"), - ent, field, self->m_vtype); + *out = ir_block_create_load_from_ent(func->m_curblock, m_context, func->makeLabel("efv"), + ent, field, m_vtype); /* Done AFTER error checking: - codegen_output_type(self, *out); + codegen_output_type(this, *out); */ } if (!*out) { - compile_error(self->m_context, "failed to create %s instruction (output type %s)", + compile_error(m_context, "failed to create %s instruction (output type %s)", (lvalue ? "ADDRESS" : "FIELD"), - type_name[self->m_vtype]); + type_name[m_vtype]); return false; } if (!lvalue) - codegen_output_type(self, *out); + codegen_output_type(this, *out); if (lvalue) - self->m_outl = *out; + m_outl = *out; else - self->m_outr = *out; + m_outr = *out; - /* Hm that should be it... */ + // Hm that should be it... return true; } -bool ast_member_codegen(ast_member *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_member::codegen(ast_function *func, bool lvalue, ir_value **out) { - ast_expression_codegen *cgen; ir_value *vec; /* in QC this is always an lvalue */ - if (lvalue && self->m_rvalue) { - compile_error(self->m_context, "not an l-value (member access)"); + if (lvalue && m_rvalue) { + compile_error(m_context, "not an l-value (member access)"); return false; } - if (self->m_outl) { - *out = self->m_outl; + if (m_outl) { + *out = m_outl; return true; } - cgen = self->m_owner->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_owner), func, false, &vec)) + if (!m_owner->codegen(func, false, &vec)) return false; if (vec->m_vtype != TYPE_VECTOR && - !(vec->m_vtype == TYPE_FIELD && self->m_owner->m_next->m_vtype == TYPE_VECTOR)) + !(vec->m_vtype == TYPE_FIELD && m_owner->m_next->m_vtype == TYPE_VECTOR)) { return false; } - *out = ir_value_vector_member(vec, self->m_field); - self->m_outl = *out; + *out = ir_value_vector_member(vec, m_field); + m_outl = *out; return (*out != nullptr); } -bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_array_index::codegen(ast_function *func, bool lvalue, ir_value **out) { ast_value *arr; ast_value *idx; - if (!lvalue && self->m_outr) { - *out = self->m_outr; + if (!lvalue && m_outr) { + *out = m_outr; return true; } - if (lvalue && self->m_outl) { - *out = self->m_outl; + if (lvalue && m_outl) { + *out = m_outl; return true; } - if (!ast_istype(self->m_array, ast_value)) { - compile_error(self->m_context, "array indexing this way is not supported"); + if (!ast_istype(m_array, ast_value)) { + compile_error(m_context, "array indexing this way is not supported"); /* note this would actually be pointer indexing because the left side is * not an actual array but (hopefully) an indexable expression. * Once we get integer arithmetic, and GADDRESS/GSTORE/GLOAD instruction @@ -2289,89 +2133,84 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva return false; } - arr = (ast_value*)self->m_array; - idx = (ast_value*)self->m_index; + arr = reinterpret_cast(m_array); + idx = reinterpret_cast(m_index); - if (!ast_istype(self->m_index, ast_value) || !idx->m_hasvalue || idx->m_cvq != CV_CONST) { + if (!ast_istype(m_index, ast_value) || !idx->m_hasvalue || idx->m_cvq != CV_CONST) { /* Time to use accessor functions */ - ast_expression_codegen *cgen; ir_value *iridx, *funval; ir_instr *call; if (lvalue) { - compile_error(self->m_context, "(.2) array indexing here needs a compile-time constant"); + compile_error(m_context, "(.2) array indexing here needs a compile-time constant"); return false; } if (!arr->m_getter) { - compile_error(self->m_context, "value has no getter, don't know how to index it"); + compile_error(m_context, "value has no getter, don't know how to index it"); return false; } - cgen = self->m_index->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_index), func, false, &iridx)) + if (!m_index->codegen(func, false, &iridx)) return false; - cgen = arr->m_getter->m_codegen; - if (!(*cgen)((ast_expression*)(arr->m_getter), func, true, &funval)) + if (!arr->m_getter->codegen(func, true, &funval)) return false; - call = ir_block_create_call(func->m_curblock, self->m_context, ast_function_label(func, "fetch"), funval, false); + call = ir_block_create_call(func->m_curblock, m_context, func->makeLabel("fetch"), funval, false); if (!call) return false; ir_call_param(call, iridx); *out = ir_call_value(call); - self->m_outr = *out; - (*out)->m_vtype = self->m_vtype; - codegen_output_type(self, *out); + m_outr = *out; + (*out)->m_vtype = m_vtype; + codegen_output_type(this, *out); return true; } if (idx->m_vtype == TYPE_FLOAT) { unsigned int arridx = idx->m_constval.vfloat; - if (arridx >= self->m_array->m_count) + if (arridx >= m_array->m_count) { - compile_error(self->m_context, "array index out of bounds: %i", arridx); + compile_error(m_context, "array index out of bounds: %i", arridx); return false; } *out = arr->m_ir_values[arridx]; } else if (idx->m_vtype == TYPE_INTEGER) { unsigned int arridx = idx->m_constval.vint; - if (arridx >= self->m_array->m_count) + if (arridx >= m_array->m_count) { - compile_error(self->m_context, "array index out of bounds: %i", arridx); + compile_error(m_context, "array index out of bounds: %i", arridx); return false; } *out = arr->m_ir_values[arridx]; } else { - compile_error(self->m_context, "array indexing here needs an integer constant"); + compile_error(m_context, "array indexing here needs an integer constant"); return false; } - (*out)->m_vtype = self->m_vtype; - codegen_output_type(self, *out); + (*out)->m_vtype = m_vtype; + codegen_output_type(this, *out); return true; } -bool ast_argpipe_codegen(ast_argpipe *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_argpipe::codegen(ast_function *func, bool lvalue, ir_value **out) { *out = nullptr; if (lvalue) { - compile_error(self->m_context, "argpipe node: not an lvalue"); + compile_error(m_context, "argpipe node: not an lvalue"); return false; } (void)func; (void)out; - compile_error(self->m_context, "TODO: argpipe codegen not implemented"); + compile_error(m_context, "TODO: argpipe codegen not implemented"); return false; } -bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_ifthen::codegen(ast_function *func, bool lvalue, ir_value **out) { - ast_expression_codegen *cgen; - ir_value *condval; ir_value *dummy; @@ -2387,26 +2226,25 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va (void)out; (void)lvalue; - if (self->m_outr) { - compile_error(self->m_context, "internal error: ast_ifthen cannot be reused, it bears no result!"); + if (m_outr) { + compile_error(m_context, "internal error: ast_ifthen cannot be reused, it bears no result!"); return false; } - self->m_outr = (ir_value*)1; + m_outr = (ir_value*)1; /* generate the condition */ - cgen = self->m_cond->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_cond), func, false, &condval)) + if (!m_cond->codegen(func, false, &condval)) return false; /* update the block which will get the jump - because short-logic or ternaries may have changed this */ cond = func->m_curblock; /* try constant folding away the condition */ - if ((folded = fold::cond_ifthen(condval, func, self)) != -1) + if ((folded = fold::cond_ifthen(condval, func, this)) != -1) return folded; - if (self->m_on_true) { + if (m_on_true) { /* create on-true block */ - ontrue = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "ontrue")); + ontrue = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("ontrue")); if (!ontrue) return false; @@ -2414,8 +2252,7 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va func->m_curblock = ontrue; /* generate */ - cgen = self->m_on_true->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_on_true), func, false, &dummy)) + if (!m_on_true->codegen(func, false, &dummy)) return false; /* we now need to work from the current endpoint */ @@ -2424,9 +2261,9 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va ontrue = nullptr; /* on-false path */ - if (self->m_on_false) { + if (m_on_false) { /* create on-false block */ - onfalse = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "onfalse")); + onfalse = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("onfalse")); if (!onfalse) return false; @@ -2434,8 +2271,7 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va func->m_curblock = onfalse; /* generate */ - cgen = self->m_on_false->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_on_false), func, false, &dummy)) + if (!m_on_false->codegen(func, false, &dummy)) return false; /* we now need to work from the current endpoint */ @@ -2446,13 +2282,13 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va /* Merge block were they all merge in to */ if (!ontrue || !onfalse || !ontrue_endblock->m_final || !onfalse_endblock->m_final) { - merge = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "endif")); + merge = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("endif")); if (!merge) return false; /* add jumps ot the merge block */ - if (ontrue && !ontrue_endblock->m_final && !ir_block_create_jump(ontrue_endblock, self->m_context, merge)) + if (ontrue && !ontrue_endblock->m_final && !ir_block_create_jump(ontrue_endblock, m_context, merge)) return false; - if (onfalse && !onfalse_endblock->m_final && !ir_block_create_jump(onfalse_endblock, self->m_context, merge)) + if (onfalse && !onfalse_endblock->m_final && !ir_block_create_jump(onfalse_endblock, m_context, merge)) return false; /* Now enter the merge block */ @@ -2461,7 +2297,7 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va /* we create the if here, that way all blocks are ordered :) */ - if (!ir_block_create_if(cond, self->m_context, condval, + if (!ir_block_create_if(cond, m_context, condval, (ontrue ? ontrue : merge), (onfalse ? onfalse : merge))) { @@ -2471,10 +2307,8 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va return true; } -bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_ternary::codegen(ast_function *func, bool lvalue, ir_value **out) { - ast_expression_codegen *cgen; - ir_value *condval; ir_value *trueval, *falseval; ir_instr *phi; @@ -2495,8 +2329,8 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_ * may still happen, thus we remember a created ir_value and simply return one * if it already exists. */ - if (self->m_outr) { - *out = self->m_outr; + if (m_outr) { + *out = m_outr; return true; } @@ -2504,17 +2338,16 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_ /* generate the condition */ func->m_curblock = cond; - cgen = self->m_cond->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_cond), func, false, &condval)) + if (!m_cond->codegen(func, false, &condval)) return false; cond_out = func->m_curblock; /* try constant folding away the condition */ - if ((folded = fold::cond_ternary(condval, func, self)) != -1) + if ((folded = fold::cond_ternary(condval, func, this)) != -1) return folded; /* create on-true block */ - ontrue = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "tern_T")); + ontrue = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("tern_T")); if (!ontrue) return false; else @@ -2523,15 +2356,14 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_ func->m_curblock = ontrue; /* generate */ - cgen = self->m_on_true->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_on_true), func, false, &trueval)) + if (!m_on_true->codegen(func, false, &trueval)) return false; ontrue_out = func->m_curblock; } /* create on-false block */ - onfalse = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "tern_F")); + onfalse = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("tern_F")); if (!onfalse) return false; else @@ -2540,25 +2372,24 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_ func->m_curblock = onfalse; /* generate */ - cgen = self->m_on_false->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_on_false), func, false, &falseval)) + if (!m_on_false->codegen(func, false, &falseval)) return false; onfalse_out = func->m_curblock; } /* create merge block */ - merge = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "tern_out")); + merge = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("tern_out")); if (!merge) return false; /* jump to merge block */ - if (!ir_block_create_jump(ontrue_out, self->m_context, merge)) + if (!ir_block_create_jump(ontrue_out, m_context, merge)) return false; - if (!ir_block_create_jump(onfalse_out, self->m_context, merge)) + if (!ir_block_create_jump(onfalse_out, m_context, merge)) return false; /* create if instruction */ - if (!ir_block_create_if(cond_out, self->m_context, condval, ontrue, onfalse)) + if (!ir_block_create_if(cond_out, m_context, condval, ontrue, onfalse)) return false; /* Now enter the merge block */ @@ -2569,31 +2400,29 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_ */ if (trueval->m_vtype != falseval->m_vtype && trueval->m_vtype != TYPE_NIL && falseval->m_vtype != TYPE_NIL) { /* error("ternary with different types on the two sides"); */ - compile_error(self->m_context, "internal error: ternary operand types invalid"); + compile_error(m_context, "internal error: ternary operand types invalid"); return false; } /* create PHI */ - phi = ir_block_create_phi(merge, self->m_context, ast_function_label(func, "phi"), self->m_vtype); + phi = ir_block_create_phi(merge, m_context, func->makeLabel("phi"), m_vtype); if (!phi) { - compile_error(self->m_context, "internal error: failed to generate phi node"); + compile_error(m_context, "internal error: failed to generate phi node"); return false; } ir_phi_add(phi, ontrue_out, trueval); ir_phi_add(phi, onfalse_out, falseval); - self->m_outr = ir_phi_value(phi); - *out = self->m_outr; + m_outr = ir_phi_value(phi); + *out = m_outr; - codegen_output_type(self, *out); + codegen_output_type(this, *out); return true; } -bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_loop::codegen(ast_function *func, bool lvalue, ir_value **out) { - ast_expression_codegen *cgen; - ir_value *dummy = nullptr; ir_value *precond = nullptr; ir_value *postcond = nullptr; @@ -2620,11 +2449,11 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value (void)lvalue; (void)out; - if (self->m_outr) { - compile_error(self->m_context, "internal error: ast_loop cannot be reused, it bears no result!"); + if (m_outr) { + compile_error(m_context, "internal error: ast_loop cannot be reused, it bears no result!"); return false; } - self->m_outr = (ir_value*)1; + m_outr = (ir_value*)1; /* NOTE: * Should we ever need some kind of block ordering, better make this function @@ -2635,10 +2464,9 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value /* initexpr doesn't get its own block, it's pointless, it could create more blocks * anyway if for example it contains a ternary. */ - if (self->m_initexpr) + if (m_initexpr) { - cgen = self->m_initexpr->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_initexpr), func, false, &dummy)) + if (!m_initexpr->codegen(func, false, &dummy)) return false; } @@ -2648,9 +2476,9 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value /* The pre-loop condition needs its own block since we * need to be able to jump to the start of that expression. */ - if (self->m_precond) + if (m_precond) { - bprecond = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "pre_loop_cond")); + bprecond = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("pre_loop_cond")); if (!bprecond) return false; @@ -2661,8 +2489,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value func->m_curblock = bprecond; /* generate */ - cgen = self->m_precond->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_precond), func, false, &precond)) + if (!m_precond->codegen(func, false, &precond)) return false; end_bprecond = func->m_curblock; @@ -2673,8 +2500,8 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value /* Now the next blocks won't be ordered nicely, but we need to * generate them this early for 'break' and 'continue'. */ - if (self->m_increment) { - bincrement = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "loop_increment")); + if (m_increment) { + bincrement = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("loop_increment")); if (!bincrement) return false; bcontinue = bincrement; /* increment comes before the pre-loop-condition */ @@ -2682,8 +2509,8 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value bincrement = end_bincrement = nullptr; } - if (self->m_postcond) { - bpostcond = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "post_loop_cond")); + if (m_postcond) { + bpostcond = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("post_loop_cond")); if (!bpostcond) return false; bcontinue = bpostcond; /* postcond comes before the increment */ @@ -2692,15 +2519,15 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value } bout_id = func->m_ir_func->m_blocks.size(); - bout = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "after_loop")); + bout = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("after_loop")); if (!bout) return false; bbreak = bout; /* The loop body... */ - /* if (self->m_body) */ + /* if (m_body) */ { - bbody = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "loop_body")); + bbody = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("loop_body")); if (!bbody) return false; @@ -2714,9 +2541,8 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value func->m_continueblocks.push_back(bbody); /* generate */ - if (self->m_body) { - cgen = self->m_body->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_body), func, false, &dummy)) + if (m_body) { + if (!m_body->codegen(func, false, &dummy)) return false; } @@ -2726,28 +2552,26 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value } /* post-loop-condition */ - if (self->m_postcond) + if (m_postcond) { /* enter */ func->m_curblock = bpostcond; /* generate */ - cgen = self->m_postcond->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_postcond), func, false, &postcond)) + if (!m_postcond->codegen(func, false, &postcond)) return false; end_bpostcond = func->m_curblock; } /* The incrementor */ - if (self->m_increment) + if (m_increment) { /* enter */ func->m_curblock = bincrement; /* generate */ - cgen = self->m_increment->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_increment), func, false, &dummy)) + if (!m_increment->codegen(func, false, &dummy)) return false; end_bincrement = func->m_curblock; @@ -2766,7 +2590,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value else tmpblock = bout; */ - if (!ir_block_create_jump(bin, self->m_context, tmpblock)) + if (!ir_block_create_jump(bin, m_context, tmpblock)) return false; /* From precond */ @@ -2781,12 +2605,12 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value */ onfalse = bout; - if (self->m_pre_not) { + if (m_pre_not) { tmpblock = ontrue; ontrue = onfalse; onfalse = tmpblock; } - if (!ir_block_create_if(end_bprecond, self->m_context, precond, ontrue, onfalse)) + if (!ir_block_create_if(end_bprecond, m_context, precond, ontrue, onfalse)) return false; } @@ -2797,7 +2621,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value else if (bpostcond) tmpblock = bpostcond; else if (bprecond) tmpblock = bprecond; else tmpblock = bbody; - if (!end_bbody->m_final && !ir_block_create_jump(end_bbody, self->m_context, tmpblock)) + if (!end_bbody->m_final && !ir_block_create_jump(end_bbody, m_context, tmpblock)) return false; } @@ -2808,7 +2632,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value else if (bprecond) tmpblock = bprecond; else if (bbody) tmpblock = bbody; else tmpblock = bout; - if (!ir_block_create_jump(end_bincrement, self->m_context, tmpblock)) + if (!ir_block_create_jump(end_bincrement, m_context, tmpblock)) return false; } @@ -2825,12 +2649,12 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value */ onfalse = bout; - if (self->m_post_not) { + if (m_post_not) { tmpblock = ontrue; ontrue = onfalse; onfalse = tmpblock; } - if (!ir_block_create_if(end_bpostcond, self->m_context, postcond, ontrue, onfalse)) + if (!ir_block_create_if(end_bpostcond, m_context, postcond, ontrue, onfalse)) return false; } @@ -2838,49 +2662,47 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value algo::shiftback(func->m_ir_func->m_blocks.begin() + bout_id, func->m_ir_func->m_blocks.end()); // FIXME::DELME:: - //func->m_ir_func->m_blocks[bout_id].release(); // it's a vector> + //func->m_ir_func->m_blocks[bout_id].release(); // it's a vector> //func->m_ir_func->m_blocks.erase(func->m_ir_func->m_blocks.begin() + bout_id); //func->m_ir_func->m_blocks.emplace_back(bout); return true; } -bool ast_breakcont_codegen(ast_breakcont *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_breakcont::codegen(ast_function *func, bool lvalue, ir_value **out) { ir_block *target; *out = nullptr; if (lvalue) { - compile_error(self->m_context, "break/continue expression is not an l-value"); + compile_error(m_context, "break/continue expression is not an l-value"); return false; } - if (self->m_outr) { - compile_error(self->m_context, "internal error: ast_breakcont cannot be reused!"); + if (m_outr) { + compile_error(m_context, "internal error: ast_breakcont cannot be reused!"); return false; } - self->m_outr = (ir_value*)1; + m_outr = (ir_value*)1; - if (self->m_is_continue) - target = func->m_continueblocks[func->m_continueblocks.size()-1-self->m_levels]; + if (m_is_continue) + target = func->m_continueblocks[func->m_continueblocks.size()-1-m_levels]; else - target = func->m_breakblocks[func->m_breakblocks.size()-1-self->m_levels]; + target = func->m_breakblocks[func->m_breakblocks.size()-1-m_levels]; if (!target) { - compile_error(self->m_context, "%s is lacking a target block", (self->m_is_continue ? "continue" : "break")); + compile_error(m_context, "%s is lacking a target block", (m_is_continue ? "continue" : "break")); return false; } - if (!ir_block_create_jump(func->m_curblock, self->m_context, target)) + if (!ir_block_create_jump(func->m_curblock, m_context, target)) return false; return true; } -bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_switch::codegen(ast_function *func, bool lvalue, ir_value **out) { - ast_expression_codegen *cgen; - ast_switch_case *def_case = nullptr; ir_block *def_bfall = nullptr; ir_block *def_bfall_to = nullptr; @@ -2896,35 +2718,34 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va uint16_t cmpinstr; if (lvalue) { - compile_error(self->m_context, "switch expression is not an l-value"); + compile_error(m_context, "switch expression is not an l-value"); return false; } - if (self->m_outr) { - compile_error(self->m_context, "internal error: ast_switch cannot be reused!"); + if (m_outr) { + compile_error(m_context, "internal error: ast_switch cannot be reused!"); return false; } - self->m_outr = (ir_value*)1; + m_outr = (ir_value*)1; (void)lvalue; (void)out; - cgen = self->m_operand->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_operand), func, false, &irop)) + if (!m_operand->codegen(func, false, &irop)) return false; - if (self->m_cases.empty()) + if (m_cases.empty()) return true; cmpinstr = type_eq_instr[irop->m_vtype]; if (cmpinstr >= VINSTR_END) { - ast_type_to_string(self->m_operand, typestr, sizeof(typestr)); - compile_error(self->m_context, "invalid type to perform a switch on: %s", typestr); + ast_type_to_string(m_operand, typestr, sizeof(typestr)); + compile_error(m_context, "invalid type to perform a switch on: %s", typestr); return false; } bout_id = func->m_ir_func->m_blocks.size(); - bout = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "after_switch")); + bout = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("after_switch")); if (!bout) return false; @@ -2932,7 +2753,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va func->m_breakblocks.push_back(bout); /* Now create all cases */ - for (auto &it : self->m_cases) { + for (auto &it : m_cases) { ir_value *cond, *val; ir_block *bcase, *bnot; size_t bnot_id; @@ -2942,36 +2763,34 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va if (swcase->m_value) { /* A regular case */ /* generate the condition operand */ - cgen = swcase->m_value->m_codegen; - if (!(*cgen)((ast_expression*)(swcase->m_value), func, false, &val)) + if (!swcase->m_value->codegen(func, false, &val)) return false; /* generate the condition */ - cond = ir_block_create_binop(func->m_curblock, self->m_context, ast_function_label(func, "switch_eq"), cmpinstr, irop, val); + cond = ir_block_create_binop(func->m_curblock, m_context, func->makeLabel("switch_eq"), cmpinstr, irop, val); if (!cond) return false; - bcase = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "case")); + bcase = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("case")); bnot_id = func->m_ir_func->m_blocks.size(); - bnot = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "not_case")); + bnot = ir_function_create_block(m_context, func->m_ir_func, func->makeLabel("not_case")); if (!bcase || !bnot) return false; if (set_def_bfall_to) { set_def_bfall_to = false; def_bfall_to = bcase; } - if (!ir_block_create_if(func->m_curblock, self->m_context, cond, bcase, bnot)) + if (!ir_block_create_if(func->m_curblock, m_context, cond, bcase, bnot)) return false; /* Make the previous case-end fall through */ if (bfall && !bfall->m_final) { - if (!ir_block_create_jump(bfall, self->m_context, bcase)) + if (!ir_block_create_jump(bfall, m_context, bcase)) return false; } /* enter the case */ func->m_curblock = bcase; - cgen = swcase->m_code->m_codegen; - if (!(*cgen)((ast_expression*)swcase->m_code, func, false, &dummy)) + if (!swcase->m_code->codegen(func, false, &dummy)) return false; /* remember this block to fall through from */ @@ -2998,7 +2817,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va } /* Jump from the last bnot to bout */ - if (bfall && !bfall->m_final && !ir_block_create_jump(bfall, self->m_context, bout)) { + if (bfall && !bfall->m_final && !ir_block_create_jump(bfall, m_context, bout)) { /* astwarning(bfall->m_context, WARN_???, "missing break after last case"); */ @@ -3014,25 +2833,24 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va /* Insert the fallthrough jump */ if (def_bfall && !def_bfall->m_final) { - if (!ir_block_create_jump(def_bfall, self->m_context, bcase)) + if (!ir_block_create_jump(def_bfall, m_context, bcase)) return false; } /* Now generate the default code */ - cgen = def_case->m_code->m_codegen; - if (!(*cgen)((ast_expression*)def_case->m_code, func, false, &dummy)) + if (!def_case->m_code->codegen(func, false, &dummy)) return false; /* see if we need to fall through */ if (def_bfall_to && !func->m_curblock->m_final) { - if (!ir_block_create_jump(func->m_curblock, self->m_context, def_bfall_to)) + if (!ir_block_create_jump(func->m_curblock, m_context, def_bfall_to)) return false; } } /* Jump from the last bnot to bout */ - if (!func->m_curblock->m_final && !ir_block_create_jump(func->m_curblock, self->m_context, bout)) + if (!func->m_curblock->m_final && !ir_block_create_jump(func->m_curblock, m_context, bout)) return false; /* enter the outgoing block */ func->m_curblock = bout; @@ -3051,65 +2869,65 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va return true; } -bool ast_label_codegen(ast_label *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_label::codegen(ast_function *func, bool lvalue, ir_value **out) { ir_value *dummy; - if (self->m_undefined) { - compile_error(self->m_context, "internal error: ast_label never defined"); + if (m_undefined) { + compile_error(m_context, "internal error: ast_label never defined"); return false; } *out = nullptr; if (lvalue) { - compile_error(self->m_context, "internal error: ast_label cannot be an lvalue"); + compile_error(m_context, "internal error: ast_label cannot be an lvalue"); return false; } /* simply create a new block and jump to it */ - self->m_irblock = ir_function_create_block(self->m_context, func->m_ir_func, self->m_name); - if (!self->m_irblock) { - compile_error(self->m_context, "failed to allocate label block `%s`", self->m_name); + m_irblock = ir_function_create_block(m_context, func->m_ir_func, m_name.c_str()); + if (!m_irblock) { + compile_error(m_context, "failed to allocate label block `%s`", m_name); return false; } if (!func->m_curblock->m_final) { - if (!ir_block_create_jump(func->m_curblock, self->m_context, self->m_irblock)) + if (!ir_block_create_jump(func->m_curblock, m_context, m_irblock)) return false; } /* enter the new block */ - func->m_curblock = self->m_irblock; + func->m_curblock = m_irblock; /* Generate all the leftover gotos */ - for (auto &it : self->m_gotos) { - if (!ast_goto_codegen(it, func, false, &dummy)) + for (auto &it : m_gotos) { + if (!it->codegen(func, false, &dummy)) return false; } return true; } -bool ast_goto_codegen(ast_goto *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_goto::codegen(ast_function *func, bool lvalue, ir_value **out) { *out = nullptr; if (lvalue) { - compile_error(self->m_context, "internal error: ast_goto cannot be an lvalue"); + compile_error(m_context, "internal error: ast_goto cannot be an lvalue"); return false; } - if (self->m_target->m_irblock) { - if (self->m_irblock_from) { + if (m_target->m_irblock) { + if (m_irblock_from) { /* we already tried once, this is the callback */ - self->m_irblock_from->m_final = false; - if (!ir_block_create_goto(self->m_irblock_from, self->m_context, self->m_target->m_irblock)) { - compile_error(self->m_context, "failed to generate goto to `%s`", self->m_name); + m_irblock_from->m_final = false; + if (!ir_block_create_goto(m_irblock_from, m_context, m_target->m_irblock)) { + compile_error(m_context, "failed to generate goto to `%s`", m_name); return false; } } else { - if (!ir_block_create_goto(func->m_curblock, self->m_context, self->m_target->m_irblock)) { - compile_error(self->m_context, "failed to generate goto to `%s`", self->m_name); + if (!ir_block_create_goto(func->m_curblock, m_context, m_target->m_irblock)) { + compile_error(m_context, "failed to generate goto to `%s`", m_name); return false; } } @@ -3120,54 +2938,48 @@ bool ast_goto_codegen(ast_goto *self, ast_function *func, bool lvalue, ir_value * close this block in a sneaky way: */ func->m_curblock->m_final = true; - self->m_irblock_from = func->m_curblock; - ast_label_register_goto(self->m_target, self); + m_irblock_from = func->m_curblock; + m_target->registerGoto(this); } return true; } -#include -bool ast_state_codegen(ast_state *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_state::codegen(ast_function *func, bool lvalue, ir_value **out) { - ast_expression_codegen *cgen; - ir_value *frameval, *thinkval; if (lvalue) { - compile_error(self->m_context, "not an l-value (state operation)"); + compile_error(m_context, "not an l-value (state operation)"); return false; } - if (self->m_outr) { - compile_error(self->m_context, "internal error: ast_state cannot be reused!"); + if (m_outr) { + compile_error(m_context, "internal error: ast_state cannot be reused!"); return false; } *out = nullptr; - cgen = self->m_framenum->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_framenum), func, false, &frameval)) + if (!m_framenum->codegen(func, false, &frameval)) return false; if (!frameval) return false; - cgen = self->m_nextthink->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_nextthink), func, false, &thinkval)) + if (!m_nextthink->codegen(func, false, &thinkval)) return false; if (!frameval) return false; - if (!ir_block_create_state_op(func->m_curblock, self->m_context, frameval, thinkval)) { - compile_error(self->m_context, "failed to create STATE instruction"); + if (!ir_block_create_state_op(func->m_curblock, m_context, frameval, thinkval)) { + compile_error(m_context, "failed to create STATE instruction"); return false; } - self->m_outr = (ir_value*)1; + m_outr = (ir_value*)1; return true; } -bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value **out) +bool ast_call::codegen(ast_function *func, bool lvalue, ir_value **out) { - ast_expression_codegen *cgen; std::vector params; ir_instr *callinstr; @@ -3175,26 +2987,24 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value /* return values are never lvalues */ if (lvalue) { - compile_error(self->m_context, "not an l-value (function call)"); + compile_error(m_context, "not an l-value (function call)"); return false; } - if (self->m_outr) { - *out = self->m_outr; + if (m_outr) { + *out = m_outr; return true; } - cgen = self->m_func->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_func), func, false, &funval)) + if (!m_func->codegen(func, false, &funval)) return false; if (!funval) return false; /* parameters */ - for (auto &it : self->m_params) { + for (auto &it : m_params) { ir_value *param; - cgen = it->m_codegen; - if (!(*cgen)(it, func, false, ¶m)) + if (!it->codegen(func, false, ¶m)) return false; if (!param) return false; @@ -3202,22 +3012,21 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value } /* varargs counter */ - if (self->m_va_count) { + if (m_va_count) { ir_value *va_count; ir_builder *builder = func->m_curblock->m_owner->m_owner; - cgen = self->m_va_count->m_codegen; - if (!(*cgen)((ast_expression*)(self->m_va_count), func, false, &va_count)) + if (!m_va_count->codegen(func, false, &va_count)) return false; - if (!ir_block_create_store_op(func->m_curblock, self->m_context, INSTR_STORE_F, + if (!ir_block_create_store_op(func->m_curblock, m_context, INSTR_STORE_F, ir_builder_get_va_count(builder), va_count)) { return false; } } - callinstr = ir_block_create_call(func->m_curblock, self->m_context, - ast_function_label(func, "call"), - funval, !!(self->m_func->m_flags & AST_FLAG_NORETURN)); + callinstr = ir_block_create_call(func->m_curblock, m_context, + func->makeLabel("call"), + funval, !!(m_func->m_flags & AST_FLAG_NORETURN)); if (!callinstr) return false; @@ -3225,9 +3034,9 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value ir_call_param(callinstr, it); *out = ir_call_value(callinstr); - self->m_outr = *out; + m_outr = *out; - codegen_output_type(self, *out); + codegen_output_type(this, *out); return true; } diff --git a/ast.h b/ast.h index 354ce05..04f8c0e 100644 --- a/ast.h +++ b/ast.h @@ -95,10 +95,6 @@ enum { #define ast_istype(x, t) ( (x)->m_node_type == (TYPE_##t) ) -/* Node interface with common components - */ -typedef void ast_node_delete(ast_node*); - struct ast_node { ast_node() = delete; @@ -114,7 +110,7 @@ struct ast_node bool m_keep_node; bool m_side_effects; - void propagate_side_effects(ast_node *other) const; + void propagateSideEffects(ast_node *other) const; }; #define ast_unref(x) do \ @@ -127,15 +123,6 @@ struct ast_node enum class ast_copy_type_t { value }; static const ast_copy_type_t ast_copy_type = ast_copy_type_t::value; -/* Expression interface - * - * Any expression or block returns an ir_value, and needs - * to know the current function. - */ -typedef bool ast_expression_codegen(ast_expression*, - ast_function*, - bool lvalue, - ir_value**); /* TODO: the codegen function should take an output-type parameter * indicating whether a variable, type, label etc. is expected, and * an environment! @@ -151,13 +138,16 @@ struct ast_expression : ast_node { ast_expression(lex_ctx_t ctx, int nodetype, qc_type vtype); ast_expression(lex_ctx_t ctx, int nodetype); ~ast_expression(); - ast_expression(ast_copy_type_t, int nodetype, const ast_expression&); + ast_expression(ast_copy_type_t, const ast_expression&); + ast_expression(ast_copy_type_t, lex_ctx_t ctx, const ast_expression&); + ast_expression(ast_copy_type_t, int nodetype, const ast_expression&); + ast_expression(ast_copy_type_t, int nodetype, lex_ctx_t ctx, const ast_expression&); - static ast_expression *shallow_type(lex_ctx_t ctx, qc_type vtype); + static ast_expression *shallowType(lex_ctx_t ctx, qc_type vtype); - bool compare_type(const ast_expression &other) const; - void adopt_type(const ast_expression &other); + bool compareType(const ast_expression &other) const; + void adoptType(const ast_expression &other); qc_type m_vtype = TYPE_VOID; ast_expression *m_next = nullptr; @@ -177,6 +167,8 @@ struct ast_expression : ast_node { */ ir_value *m_outl = nullptr; ir_value *m_outr = nullptr; + + virtual bool codegen(ast_function *current, bool lvalue, ir_value **out); }; /* Value @@ -206,7 +198,13 @@ struct ast_value : ast_expression ast_value(ast_copy_type_t, const ast_value&); ast_value(ast_copy_type_t, const ast_value&, const std::string&); - void add_param(ast_value*); + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + + void addParam(ast_value*); + + bool generateGlobal(ir_builder*, bool isfield); + bool generateLocal(ir_function*, bool param); + bool generateAccessors(ir_builder*); std::string m_name; std::string m_desc; @@ -229,18 +227,22 @@ struct ast_value : ast_expression size_t m_uses = 0; ir_value *m_ir_v = nullptr; - ir_value **m_ir_values = nullptr; + std::vector m_ir_values; size_t m_ir_value_count = 0; /* ONLY for arrays in progs version up to 6 */ ast_value *m_setter = nullptr; ast_value *m_getter = nullptr; - bool m_intrinsic = false; /* true if associated with intrinsic */ -}; -bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield); +private: + bool generateGlobalFunction(ir_builder*); + bool generateGlobalField(ir_builder*); + ir_value *prepareGlobalArray(ir_builder*); + bool setGlobalArray(); + bool checkArray(const ast_value &array) const; +}; void ast_type_to_string(const ast_expression *e, char *buf, size_t bufsize); @@ -262,6 +264,8 @@ struct ast_binary : ast_expression ast_binary(lex_ctx_t ctx, int op, ast_expression *l, ast_expression *r); ~ast_binary(); + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + int m_op; ast_expression *m_left; ast_expression *m_right; @@ -280,6 +284,8 @@ struct ast_binstore : ast_expression ast_binstore(lex_ctx_t ctx, int storeop, int mathop, ast_expression *l, ast_expression *r); ~ast_binstore(); + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + int m_opstore; int m_opbin; ast_expression *m_dest; @@ -287,11 +293,6 @@ struct ast_binstore : ast_expression /* for &~= which uses the destination in a binary in source we can use this */ bool m_keep_dest; }; -ast_binstore* ast_binstore_new(lex_ctx_t ctx, - int storeop, - int op, - ast_expression *left, - ast_expression *right); /* Unary * @@ -301,9 +302,14 @@ struct ast_unary : ast_expression { ast_unary() = delete; ~ast_unary(); + + static ast_unary* make(lex_ctx_t ctx, int op, ast_expression *expr); + + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + int m_op; ast_expression *m_operand; - static ast_unary* make(lex_ctx_t ctx, int op, ast_expression *expr); + private: ast_unary(lex_ctx_t ctx, int op, ast_expression *expr); }; @@ -319,6 +325,9 @@ struct ast_return : ast_expression ast_return() = delete; ast_return(lex_ctx_t ctx, ast_expression *expr); ~ast_return(); + + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + ast_expression *m_operand; }; @@ -341,6 +350,9 @@ struct ast_entfield : ast_expression ast_entfield(lex_ctx_t ctx, ast_expression *entity, ast_expression *field); ast_entfield(lex_ctx_t ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype); ~ast_entfield(); + + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + // The entity can come from an expression of course. ast_expression *m_entity; // As can the field, it just must result in a value of TYPE_FIELD @@ -357,6 +369,8 @@ struct ast_member : ast_expression static ast_member *make(lex_ctx_t ctx, ast_expression *owner, unsigned int field, const std::string &name); ~ast_member(); + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + ast_expression *m_owner; unsigned int m_field; std::string m_name; @@ -381,6 +395,9 @@ struct ast_array_index : ast_expression { static ast_array_index* make(lex_ctx_t ctx, ast_expression *array, ast_expression *index); ~ast_array_index(); + + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + ast_expression *m_array; ast_expression *m_index; private: @@ -396,6 +413,9 @@ struct ast_argpipe : ast_expression { ast_argpipe() = delete; ast_argpipe(lex_ctx_t ctx, ast_expression *index); + + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + ~ast_argpipe(); ast_expression *m_index; }; @@ -410,6 +430,9 @@ struct ast_store : ast_expression ast_store() = delete; ast_store(lex_ctx_t ctx, int op, ast_expression *d, ast_expression *s); ~ast_store(); + + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + int m_op; ast_expression *m_dest; ast_expression *m_source; @@ -431,6 +454,9 @@ struct ast_ifthen : ast_expression ast_ifthen() = delete; ast_ifthen(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse); ~ast_ifthen(); + + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + ast_expression *m_cond; /* It's all just 'expressions', since an ast_block is one too. */ ast_expression *m_on_true; @@ -455,6 +481,9 @@ struct ast_ternary : ast_expression ast_ternary() = delete; ast_ternary(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse); ~ast_ternary(); + + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + ast_expression *m_cond; /* It's all just 'expressions', since an ast_block is one too. */ ast_expression *m_on_true; @@ -494,6 +523,9 @@ struct ast_loop : ast_expression ast_expression *increment, ast_expression *body); ~ast_loop(); + + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + ast_expression *m_initexpr; ast_expression *m_precond; ast_expression *m_postcond; @@ -513,10 +545,16 @@ struct ast_loop : ast_expression */ struct ast_breakcont : ast_expression { + ast_breakcont() = delete; + ast_breakcont(lex_ctx_t ctx, bool iscont, unsigned int levels); + ~ast_breakcont(); + + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + + bool m_is_continue; unsigned int m_levels; }; -ast_breakcont* ast_breakcont_new(lex_ctx_t ctx, bool iscont, unsigned int levels); /* Switch Statements * @@ -535,11 +573,16 @@ struct ast_switch_case { struct ast_switch : ast_expression { + ast_switch() = delete; + ast_switch(lex_ctx_t ctx, ast_expression *op); + ~ast_switch(); + + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + ast_expression *m_operand; std::vector m_cases; }; -ast_switch* ast_switch_new(lex_ctx_t ctx, ast_expression *op); /* Label nodes * @@ -547,15 +590,23 @@ ast_switch* ast_switch_new(lex_ctx_t ctx, ast_expression *op); */ struct ast_label : ast_expression { - const char *m_name; + ast_label() = delete; + ast_label(lex_ctx_t ctx, const std::string &name, bool undefined); + ~ast_label(); + + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + + std::string m_name; ir_block *m_irblock; std::vector m_gotos; /* means it has not yet been defined */ bool m_undefined; -}; -ast_label* ast_label_new(lex_ctx_t ctx, const char *name, bool undefined); +private: + void registerGoto(ast_goto*); + friend struct ast_goto; +}; /* GOTO nodes * @@ -563,25 +614,34 @@ ast_label* ast_label_new(lex_ctx_t ctx, const char *name, bool undefined); */ struct ast_goto : ast_expression { - const char *m_name; + ast_goto() = delete; + ast_goto(lex_ctx_t ctx, const std::string &name); + ~ast_goto(); + + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + + void setLabel(ast_label*); + + std::string m_name; ast_label *m_target; ir_block *m_irblock_from; }; -ast_goto* ast_goto_new(lex_ctx_t ctx, const char *name); -void ast_goto_set_label(ast_goto*, ast_label*); - /* STATE node * * For frame/think state updates: void foo() [framenum, nextthink] {} */ struct ast_state : ast_expression { + ast_state() = delete; + ast_state(lex_ctx_t ctx, ast_expression *frame, ast_expression *think); + ~ast_state(); + + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + ast_expression *m_framenum; ast_expression *m_nextthink; }; -ast_state* ast_state_new(lex_ctx_t ctx, ast_expression *frame, ast_expression *think); -void ast_state_delete(ast_state*); /* CALL node * @@ -595,29 +655,42 @@ void ast_state_delete(ast_state*); */ struct ast_call : ast_expression { + ast_call() = delete; + static ast_call *make(lex_ctx_t, ast_expression*); + ~ast_call(); + + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + + bool checkTypes(ast_expression *this_func_va_type) const; + ast_expression *m_func; std::vector m_params; ast_expression *m_va_count; + +private: + ast_call(lex_ctx_t ctx, ast_expression *funcexpr); + bool checkVararg(ast_expression *va_type, ast_expression *exp_type) const; }; -ast_call* ast_call_new(lex_ctx_t ctx, - ast_expression *funcexpr); -bool ast_call_check_types(ast_call*, ast_expression *this_func_va_type); /* Blocks * */ struct ast_block : ast_expression { + ast_block() = delete; + ast_block(lex_ctx_t ctx); + ~ast_block(); + + bool codegen(ast_function *current, bool lvalue, ir_value **out) override; + std::vector m_locals; std::vector m_exprs; std::vector m_collect; -}; -ast_block* ast_block_new(lex_ctx_t ctx); -void ast_block_delete(ast_block*); -void ast_block_set_type(ast_block*, ast_expression *from); -void ast_block_collect(ast_block*, ast_expression*); -bool GMQCC_WARN ast_block_add_expr(ast_block*, ast_expression*); + void setType(const ast_expression &from); + bool GMQCC_WARN addExpr(ast_expression*); + void collect(ast_expression*); +}; /* Function * @@ -628,49 +701,53 @@ bool GMQCC_WARN ast_block_add_expr(ast_block*, ast_expression*); * neither functions inside functions, nor lambdas, and function * pointers could just work with a name. However, this way could be * more flexible, and adds no real complexity. + * + * The destructor will NOT delete the underlying ast_value + * */ struct ast_function : ast_node { - ast_value *m_function_type; - const char *m_name; + ast_function() = delete; + static ast_function *make(lex_ctx_t ctx, const std::string &name, ast_value *vtype); + ~ast_function(); - int m_builtin; + const char* makeLabel(const char *prefix); + virtual bool generateFunction(ir_builder*); + + ast_value *m_function_type = nullptr; + std::string m_name; + + int m_builtin = 0; /* list of used-up names for statics without the count suffix */ - std::vector m_static_names; + std::vector m_static_names; /* number of static variables, by convention this includes the * ones without the count-suffix - remember this when dealing * with savegames. uint instead of size_t as %zu in printf is * C99, so no windows support. */ - unsigned int m_static_count; + unsigned int m_static_count = 0; - ir_function *m_ir_func; - ir_block *m_curblock; + ir_function *m_ir_func = nullptr; + ir_block *m_curblock = nullptr; std::vector m_breakblocks; std::vector m_continueblocks; - size_t m_labelcount; + size_t m_labelcount = 0; /* in order for thread safety - for the optional * channel abesed multithreading... keeping a buffer * here to use in ast_function_label. */ - char m_labelbuf[64]; std::vector> m_blocks; - ast_value *m_varargs; - ast_value *m_argc; - ast_value *m_fixedparams; - ast_value *m_return_value; -}; -ast_function* ast_function_new(lex_ctx_t ctx, const char *name, ast_value *vtype); -/* This will NOT delete the underlying ast_value */ -void ast_function_delete(ast_function*); -/* For "optimized" builds this can just keep returning "foo"... - * or whatever... - */ -const char* ast_function_label(ast_function*, const char *prefix); + std::unique_ptr m_varargs; + std::unique_ptr m_argc; + ast_value *m_fixedparams = nullptr; // these use unref() + ast_value *m_return_value = nullptr; -bool ast_function_codegen(ast_function *self, ir_builder *builder); -bool ast_generate_accessors(ast_value *asvalue, ir_builder *ir); +private: + ast_function(lex_ctx_t ctx, const std::string &name, ast_value *vtype); + + char m_labelbuf[64]; +}; /* * If the condition creates a situation where this becomes -1 size it means there are diff --git a/conout.cpp b/conout.cpp index 28d1a43..5eb81db 100644 --- a/conout.cpp +++ b/conout.cpp @@ -176,7 +176,7 @@ void vcompile_error(lex_ctx_t ctx, const char *msg, va_list ap) con_cvprintmsg(ctx, LVL_ERROR, "error", msg, ap); } -void compile_error(lex_ctx_t ctx, const char *msg, ...) +void compile_error_(lex_ctx_t ctx, const char *msg, ...) { va_list ap; va_start(ap, msg); @@ -215,7 +215,7 @@ bool GMQCC_WARN vcompile_warning(lex_ctx_t ctx, int warntype, const char *fmt, v return OPTS_WERROR(warntype) && OPTS_FLAG(BAIL_ON_WERROR); } -bool GMQCC_WARN compile_warning(lex_ctx_t ctx, int warntype, const char *fmt, ...) +bool GMQCC_WARN compile_warning_(lex_ctx_t ctx, int warntype, const char *fmt, ...) { bool r; va_list ap; diff --git a/fold.cpp b/fold.cpp index 306e5ca..81c6c3f 100644 --- a/fold.cpp +++ b/fold.cpp @@ -931,14 +931,14 @@ bool fold::generate(ir_builder *ir) { // generate globals for immediate folded values ast_value *cur; for (auto &it : m_imm_float) - if (!ast_global_codegen((cur = it), ir, false)) goto err; + if (!(cur = it)->generateGlobal(ir, false)) goto err; for (auto &it : m_imm_vector) - if (!ast_global_codegen((cur = it), ir, false)) goto err; + if (!(cur = it)->generateGlobal(ir, false)) goto err; for (auto &it : m_imm_string) - if (!ast_global_codegen((cur = it), ir, false)) goto err; + if (!(cur = it)->generateGlobal(ir, false)) goto err; return true; err: - con_out("failed to generate global %s\n", cur->m_name); + con_out("failed to generate global %s\n", cur->m_name.c_str()); delete ir; return false; } @@ -960,7 +960,7 @@ ast_expression *fold::constgen_float(qcfloat_t value, bool inexact) { if (!memcmp(&it->m_constval.vfloat, &value, sizeof(qcfloat_t))) return (ast_expression*)it; - ast_value *out = ast_value_new(ctx(), "#IMMEDIATE", TYPE_FLOAT); + ast_value *out = new ast_value(ctx(), "#IMMEDIATE", TYPE_FLOAT); out->m_cvq = CV_CONST; out->m_hasvalue = true; out->m_inexact = inexact; @@ -976,7 +976,7 @@ ast_expression *fold::constgen_vector(vec3_t value) { if (vec3_cmp(it->m_constval.vvec, value)) return (ast_expression*)it; - ast_value *out = ast_value_new(ctx(), "#IMMEDIATE", TYPE_VECTOR); + ast_value *out = new ast_value(ctx(), "#IMMEDIATE", TYPE_VECTOR); out->m_cvq = CV_CONST; out->m_hasvalue = true; out->m_constval.vvec = value; @@ -997,10 +997,10 @@ ast_expression *fold::constgen_string(const char *str, bool translate) { if (translate) { char name[32]; util_snprintf(name, sizeof(name), "dotranslate_%zu", m_parser->translated++); - out = ast_value_new(ctx(), name, TYPE_STRING); + out = new ast_value(ctx(), name, TYPE_STRING); out->m_flags |= AST_FLAG_INCLUDE_DEF; /* def needs to be included for translatables */ } else { - out = ast_value_new(ctx(), "#IMMEDIATE", TYPE_STRING); + out = new ast_value(ctx(), "#IMMEDIATE", TYPE_STRING); } out->m_cvq = CV_CONST; @@ -1014,6 +1014,10 @@ ast_expression *fold::constgen_string(const char *str, bool translate) { return (ast_expression*)out; } +ast_expression *fold::constgen_string(const std::string &str, bool translate) { + return constgen_string(str.c_str(), translate); +} + typedef union { void (*callback)(void); sfloat_t (*binary)(sfloat_state_t *, sfloat_t, sfloat_t); @@ -1069,11 +1073,11 @@ ast_expression *fold::op_mul_vec(vec3_t vec, ast_value *sel, const char *set) { if (!y && !z) { ast_expression *out; ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS]; - out = (ast_expression*)ast_member_new(ctx(), (ast_expression*)sel, set[0]-'x', nullptr); + out = ast_member::make(ctx(), (ast_expression*)sel, set[0]-'x', nullptr); out->m_keep_node = false; ((ast_member*)out)->m_rvalue = true; if (x != -1.0f) - return (ast_expression*)ast_binary_new(ctx(), INSTR_MUL_F, constgen_float(x, false), out); + return new ast_binary(ctx(), INSTR_MUL_F, constgen_float(x, false), out); } return nullptr; } @@ -1181,7 +1185,7 @@ ast_expression *fold::op_div(ast_value *a, ast_value *b) { bool inexact = check_except_float(&sfloat_div, a, b); return constgen_float(immvalue_float(a) / immvalue_float(b), inexact); } else if (fold_can_1(b)) { - return (ast_expression*)ast_binary_new( + return new ast_binary( ctx(), INSTR_MUL_F, (ast_expression*)a, @@ -1192,17 +1196,16 @@ ast_expression *fold::op_div(ast_value *a, ast_value *b) { if (fold_can_2(a, b)) { return constgen_vector(vec3_mulvf(ctx(), immvalue_vector(a), 1.0f / immvalue_float(b))); } else { - return (ast_expression*)ast_binary_new( + return new ast_binary( ctx(), INSTR_MUL_VF, (ast_expression*)a, (fold_can_1(b)) ? (ast_expression*)constgen_float(1.0f / immvalue_float(b), false) - : (ast_expression*)ast_binary_new( - ctx(), - INSTR_DIV_F, - (ast_expression*)m_imm_float[1], - (ast_expression*)b + : new ast_binary(ctx(), + INSTR_DIV_F, + (ast_expression*)m_imm_float[1], + (ast_expression*)b ) ); } @@ -1600,12 +1603,11 @@ ast_expression *fold::binary(lex_ctx_t ctx, int op, ast_expression *left, ast_ex ast_expression *ret = superfluous(left, right, op); if (ret) return ret; - return (ast_expression*)ast_binary_new(ctx, op, left, right); + return new ast_binary(ctx, op, left, right); } int fold::cond(ir_value *condval, ast_function *func, ast_ifthen *branch) { if (isfloat(condval) && fold_can_1(condval) && OPTS_OPTIMIZATION(OPTIM_CONST_FOLD_DCE)) { - ast_expression_codegen *cgen; ir_block *elide; ir_value *dummy; bool istrue = (immvalue_float(condval) != 0.0f && branch->m_on_true); @@ -1621,9 +1623,9 @@ int fold::cond(ir_value *condval, ast_function *func, ast_ifthen *branch) { return true; } - if (!(elide = ir_function_create_block(branch->m_context, func->m_ir_func, ast_function_label(func, ((istrue) ? "ontrue" : "onfalse"))))) + if (!(elide = ir_function_create_block(branch->m_context, func->m_ir_func, func->makeLabel((istrue) ? "ontrue" : "onfalse")))) return false; - if (!(*(cgen = path->m_codegen))((ast_expression*)path, func, false, &dummy)) + if (!path->codegen(func, false, &dummy)) return false; if (!ir_block_create_jump(func->m_curblock, branch->m_context, elide)) return false; diff --git a/fold.h b/fold.h index b29d422..1d096e8 100644 --- a/fold.h +++ b/fold.h @@ -32,6 +32,7 @@ struct fold { ast_expression *constgen_float(qcfloat_t value, bool inexact); ast_expression *constgen_vector(vec3_t value); ast_expression *constgen_string(const char *str, bool translate); + ast_expression *constgen_string(const std::string &str, bool translate); ast_value *imm_float(size_t index) const { return m_imm_float[index]; } ast_value *imm_vector(size_t index) const { return m_imm_vector[index]; } diff --git a/gmqcc.h b/gmqcc.h index 88cf7ff..4e3fb39 100644 --- a/gmqcc.h +++ b/gmqcc.h @@ -589,12 +589,28 @@ extern size_t compile_errors; extern size_t compile_Werrors; extern size_t compile_warnings; -void /********/ compile_error (lex_ctx_t ctx, /*LVL_ERROR*/ const char *msg, ...); +void /********/ compile_error_ (lex_ctx_t ctx, /*LVL_ERROR*/ const char *msg, ...); void /********/ vcompile_error (lex_ctx_t ctx, /*LVL_ERROR*/ const char *msg, va_list ap); -bool GMQCC_WARN compile_warning (lex_ctx_t ctx, int warntype, const char *fmt, ...); +bool GMQCC_WARN compile_warning_(lex_ctx_t ctx, int warntype, const char *fmt, ...); bool GMQCC_WARN vcompile_warning(lex_ctx_t ctx, int warntype, const char *fmt, va_list ap); void compile_show_werrors(void); +template +inline constexpr const T formatNormalize(const T argument) { return argument; } + +inline const char *formatNormalize(const std::string &argument) { + return argument.c_str(); +} + +template +inline bool GMQCC_WARN compile_warning(lex_ctx_t ctx, int warntype, const char *fmt, const Ts&... ts) { + return compile_warning_(ctx, warntype, fmt, formatNormalize(ts)...); +} +template +inline void /********/ compile_error (lex_ctx_t ctx, /*LVL_ERROR*/ const char *msg, const Ts&... ts) { + return compile_error_(ctx, msg, formatNormalize(ts)...); +} + /* ir.c */ /* TODO: cleanup */ enum store_type { diff --git a/intrin.cpp b/intrin.cpp index cc6250b..b37b50f 100644 --- a/intrin.cpp +++ b/intrin.cpp @@ -17,10 +17,10 @@ ast_function *intrin::value(ast_value **out, const char *name, qc_type vtype) { util_snprintf(buffer, sizeof(buffer), "__builtin_%s", name); util_snprintf(stype, sizeof(stype), "<%s>", type_name[vtype]); - value = ast_value_new(ctx(), buffer, TYPE_FUNCTION); + value = new ast_value(ctx(), buffer, TYPE_FUNCTION); value->m_intrinsic = true; - value->m_next = (ast_expression*)ast_value_new(ctx(), stype, vtype); - func = ast_function_new(ctx(), buffer, value); + value->m_next = new ast_value(ctx(), stype, vtype); + func = ast_function::make(ctx(), buffer, value); value->m_flags |= AST_FLAG_ERASEABLE; *out = value; @@ -29,7 +29,7 @@ ast_function *intrin::value(ast_value **out, const char *name, qc_type vtype) { void intrin::reg(ast_value *const value, ast_function *const func) { m_parser->functions.push_back(func); - m_parser->globals.push_back((ast_expression*)value); + m_parser->globals.push_back(value); } #define QC_POW_EPSILON 0.00001f @@ -38,7 +38,7 @@ ast_expression *intrin::nullfunc() { ast_value *val = nullptr; ast_function *func = value(&val, nullptr, TYPE_VOID); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::isfinite_() { @@ -48,33 +48,33 @@ ast_expression *intrin::isfinite_() { * } */ ast_value *val = nullptr; - ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT); + ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT); ast_function *func = value(&val, "isfinite", TYPE_FLOAT); - ast_call *callisnan = ast_call_new(ctx(), func_self("isnan", "isfinite")); - ast_call *callisinf = ast_call_new(ctx(), func_self("isinf", "isfinite")); - ast_block *block = ast_block_new(ctx()); + ast_call *callisnan = ast_call::make(ctx(), func_self("isnan", "isfinite")); + ast_call *callisinf = ast_call::make(ctx(), func_self("isinf", "isfinite")); + ast_block *block = new ast_block(ctx()); /* float x; */ - val->m_type_params.push_back(x); + val->m_type_params.emplace_back(x); /* = isnan(x); */ - callisnan->m_params.push_back((ast_expression*)x); + callisnan->m_params.push_back(x); /* = isinf(x); */ - callisinf->m_params.push_back((ast_expression*)x); + callisinf->m_params.push_back(x); /* return (! || ); */ block->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)ast_unary_new( + ast_unary::make( ctx(), INSTR_NOT_F, - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_OR, - (ast_expression*)callisnan, - (ast_expression*)callisinf + callisnan, + callisinf ) ) ) @@ -83,7 +83,7 @@ ast_expression *intrin::isfinite_() { func->m_blocks.emplace_back(block); reg(val, func); - return (ast_expression*)val;; + return val;; } ast_expression *intrin::isinf_() { @@ -93,43 +93,43 @@ ast_expression *intrin::isinf_() { * } */ ast_value *val = nullptr; - ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT); - ast_block *body = ast_block_new(ctx()); + ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT); + ast_block *body = new ast_block(ctx()); ast_function *func = value(&val, "isinf", TYPE_FLOAT); body->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_AND, - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_NE_F, - (ast_expression*)x, - (ast_expression*)m_fold->m_imm_float[0] + x, + m_fold->m_imm_float[0] ), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_EQ_F, - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_ADD_F, - (ast_expression*)x, - (ast_expression*)x + x, + x ), - (ast_expression*)x + x ) ) ) ); - val->m_type_params.push_back(x); + val->m_type_params.emplace_back(x); func->m_blocks.emplace_back(body); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::isnan_() { @@ -142,39 +142,39 @@ ast_expression *intrin::isnan_() { * } */ ast_value *val = nullptr; - ast_value *arg1 = ast_value_new(ctx(), "x",TYPE_FLOAT); - ast_value *local = ast_value_new(ctx(), "local", TYPE_FLOAT); - ast_block *body = ast_block_new(ctx()); + ast_value *arg1 = new ast_value(ctx(), "x",TYPE_FLOAT); + ast_value *local = new ast_value(ctx(), "local", TYPE_FLOAT); + ast_block *body = new ast_block(ctx()); ast_function *func = value(&val, "isnan", TYPE_FLOAT); body->m_locals.push_back(local); body->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)local, - (ast_expression*)arg1 + local, + arg1 ) ); body->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_NE_F, - (ast_expression*)arg1, - (ast_expression*)local + arg1, + local ) ) ); - val->m_type_params.push_back(arg1); + val->m_type_params.emplace_back(arg1); func->m_blocks.emplace_back(body); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::isnormal_() { @@ -184,25 +184,25 @@ ast_expression *intrin::isnormal_() { * } */ ast_value *val = nullptr; - ast_call *callisfinite = ast_call_new(ctx(), func_self("isfinite", "isnormal")); - ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT); - ast_block *body = ast_block_new(ctx()); + ast_call *callisfinite = ast_call::make(ctx(), func_self("isfinite", "isnormal")); + ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT); + ast_block *body = new ast_block(ctx()); ast_function *func = value(&val, "isnormal", TYPE_FLOAT); - val->m_type_params.push_back(x); - callisfinite->m_params.push_back((ast_expression*)x); + val->m_type_params.emplace_back(x); + callisfinite->m_params.push_back(x); /* return */ body->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)callisfinite + callisfinite ) ); func->m_blocks.emplace_back(body); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::signbit_() { @@ -212,33 +212,33 @@ ast_expression *intrin::signbit_() { * } */ ast_value *val = nullptr; - ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT); - ast_block *body = ast_block_new(ctx()); + ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT); + ast_block *body = new ast_block(ctx()); ast_function *func = value(&val, "signbit", TYPE_FLOAT); - val->m_type_params.push_back(x); + val->m_type_params.emplace_back(x); /* return (x < 0); */ body->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)ast_ternary_new( + new ast_ternary( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_LT, - (ast_expression*)x, - (ast_expression*)m_fold->m_imm_float[0] + x, + m_fold->m_imm_float[0] ), - (ast_expression*)m_fold->m_imm_float[1], - (ast_expression*)m_fold->m_imm_float[0] + m_fold->m_imm_float[1], + m_fold->m_imm_float[0] ) ) ); func->m_blocks.emplace_back(body); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::acosh_() { @@ -248,50 +248,50 @@ ast_expression *intrin::acosh_() { * } */ ast_value *val = nullptr; - ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT); - ast_call *calllog = ast_call_new(ctx(), func_self("log", "acosh")); - ast_call *callsqrt = ast_call_new(ctx(), func_self("sqrt", "acosh")); - ast_block *body = ast_block_new(ctx()); + ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT); + ast_call *calllog = ast_call::make(ctx(), func_self("log", "acosh")); + ast_call *callsqrt = ast_call::make(ctx(), func_self("sqrt", "acosh")); + ast_block *body = new ast_block(ctx()); ast_function *func = value(&val, "acosh", TYPE_FLOAT); - val->m_type_params.push_back(x); + val->m_type_params.emplace_back(x); /* = sqrt((x * x) - 1); */ callsqrt->m_params.push_back( - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_SUB_F, - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_MUL_F, - (ast_expression*)x, - (ast_expression*)x + x, + x ), - (ast_expression*)m_fold->m_imm_float[1] + m_fold->m_imm_float[1] ) ); /* = log(x + ); */ calllog->m_params.push_back( - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_ADD_F, - (ast_expression*)x, - (ast_expression*)callsqrt + x, + callsqrt ) ); /* return ; */ body->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)calllog + calllog ) ); func->m_blocks.emplace_back(body); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::asinh_() { @@ -301,50 +301,50 @@ ast_expression *intrin::asinh_() { * } */ ast_value *val = nullptr; - ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT); - ast_call *calllog = ast_call_new(ctx(), func_self("log", "asinh")); - ast_call *callsqrt = ast_call_new(ctx(), func_self("sqrt", "asinh")); - ast_block *body = ast_block_new(ctx()); + ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT); + ast_call *calllog = ast_call::make(ctx(), func_self("log", "asinh")); + ast_call *callsqrt = ast_call::make(ctx(), func_self("sqrt", "asinh")); + ast_block *body = new ast_block(ctx()); ast_function *func = value(&val, "asinh", TYPE_FLOAT); - val->m_type_params.push_back(x); + val->m_type_params.emplace_back(x); /* = sqrt((x * x) + 1); */ callsqrt->m_params.push_back( - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_ADD_F, - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_MUL_F, - (ast_expression*)x, - (ast_expression*)x + x, + x ), - (ast_expression*)m_fold->m_imm_float[1] + m_fold->m_imm_float[1] ) ); /* = log(x + ); */ calllog->m_params.push_back( - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_ADD_F, - (ast_expression*)x, - (ast_expression*)callsqrt + x, + callsqrt ) ); /* return ; */ body->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)calllog + calllog ) ); func->m_blocks.emplace_back(body); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::atanh_() { @@ -354,46 +354,46 @@ ast_expression *intrin::atanh_() { * } */ ast_value *val = nullptr; - ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT); - ast_call *calllog = ast_call_new(ctx(), func_self("log", "atanh")); - ast_block *body = ast_block_new(ctx()); + ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT); + ast_call *calllog = ast_call::make(ctx(), func_self("log", "atanh")); + ast_block *body = new ast_block(ctx()); ast_function *func = value(&val, "atanh", TYPE_FLOAT); - val->m_type_params.push_back(x); + val->m_type_params.emplace_back(x); /* = log((1 + x) / (1 - x)); */ calllog->m_params.push_back( - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_DIV_F, - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_ADD_F, - (ast_expression*)m_fold->m_imm_float[1], - (ast_expression*)x + m_fold->m_imm_float[1], + x ), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_SUB_F, - (ast_expression*)m_fold->m_imm_float[1], - (ast_expression*)x + m_fold->m_imm_float[1], + x ) ) ); /* return 0.5 * ; */ body->m_exprs.push_back( - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_MUL_F, - (ast_expression*)m_fold->constgen_float(0.5, false), - (ast_expression*)calllog + m_fold->constgen_float(0.5, false), + calllog ) ); func->m_blocks.emplace_back(body); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::exp_() { @@ -409,14 +409,14 @@ ast_expression *intrin::exp_() { * } */ ast_value *val = nullptr; - ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT); - ast_value *sum = ast_value_new(ctx(), "sum", TYPE_FLOAT); - ast_value *acc = ast_value_new(ctx(), "acc", TYPE_FLOAT); - ast_value *i = ast_value_new(ctx(), "i", TYPE_FLOAT); - ast_block *body = ast_block_new(ctx()); + ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT); + ast_value *sum = new ast_value(ctx(), "sum", TYPE_FLOAT); + ast_value *acc = new ast_value(ctx(), "acc", TYPE_FLOAT); + ast_value *i = new ast_value(ctx(), "i", TYPE_FLOAT); + ast_block *body = new ast_block(ctx()); ast_function *func = value(&val, "exp", TYPE_FLOAT); - val->m_type_params.push_back(x); + val->m_type_params.emplace_back(x); body->m_locals.push_back(sum); body->m_locals.push_back(acc); @@ -424,21 +424,21 @@ ast_expression *intrin::exp_() { /* sum = 1.0; */ body->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)sum, - (ast_expression*)m_fold->m_imm_float[1] + sum, + m_fold->m_imm_float[1] ) ); /* acc = 1.0; */ body->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)acc, - (ast_expression*)m_fold->m_imm_float[1] + acc, + m_fold->m_imm_float[1] ) ); @@ -447,49 +447,49 @@ ast_expression *intrin::exp_() { * sum += (acc *= x / i); */ body->m_exprs.push_back( - (ast_expression*)ast_loop_new( + new ast_loop( ctx(), /* i = 1; */ - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)i, - (ast_expression*)m_fold->m_imm_float[1] + i, + m_fold->m_imm_float[1] ), /* i < 200; */ - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_LT, - (ast_expression*)i, - (ast_expression*)m_fold->constgen_float(200.0f, false) + i, + m_fold->constgen_float(200.0f, false) ), false, nullptr, false, /* ++i; */ - (ast_expression*)ast_binstore_new( + new ast_binstore( ctx(), INSTR_STORE_F, INSTR_ADD_F, - (ast_expression*)i, - (ast_expression*)m_fold->m_imm_float[1] + i, + m_fold->m_imm_float[1] ), /* sum += (acc *= (x / i)) */ - (ast_expression*)ast_binstore_new( + new ast_binstore( ctx(), INSTR_STORE_F, INSTR_ADD_F, - (ast_expression*)sum, - (ast_expression*)ast_binstore_new( + sum, + new ast_binstore( ctx(), INSTR_STORE_F, INSTR_MUL_F, - (ast_expression*)acc, - (ast_expression*)ast_binary_new( + acc, + new ast_binary( ctx(), INSTR_DIV_F, - (ast_expression*)x, - (ast_expression*)i + x, + i ) ) ) @@ -498,15 +498,15 @@ ast_expression *intrin::exp_() { /* return sum; */ body->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)sum + sum ) ); func->m_blocks.emplace_back(body); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::exp2_() { @@ -516,27 +516,27 @@ ast_expression *intrin::exp2_() { * } */ ast_value *val = nullptr; - ast_call *callpow = ast_call_new(ctx(), func_self("pow", "exp2")); - ast_value *arg1 = ast_value_new(ctx(), "x", TYPE_FLOAT); - ast_block *body = ast_block_new(ctx()); + ast_call *callpow = ast_call::make(ctx(), func_self("pow", "exp2")); + ast_value *arg1 = new ast_value(ctx(), "x", TYPE_FLOAT); + ast_block *body = new ast_block(ctx()); ast_function *func = value(&val, "exp2", TYPE_FLOAT); - val->m_type_params.push_back(arg1); + val->m_type_params.emplace_back(arg1); - callpow->m_params.push_back((ast_expression*)m_fold->m_imm_float[3]); - callpow->m_params.push_back((ast_expression*)arg1); + callpow->m_params.push_back(m_fold->m_imm_float[3]); + callpow->m_params.push_back(arg1); /* return */ body->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)callpow + callpow ) ); func->m_blocks.emplace_back(body); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::expm1_() { @@ -546,32 +546,32 @@ ast_expression *intrin::expm1_() { * } */ ast_value *val = nullptr; - ast_call *callexp = ast_call_new(ctx(), func_self("exp", "expm1")); - ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT); - ast_block *body = ast_block_new(ctx()); + ast_call *callexp = ast_call::make(ctx(), func_self("exp", "expm1")); + ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT); + ast_block *body = new ast_block(ctx()); ast_function *func = value(&val, "expm1", TYPE_FLOAT); - val->m_type_params.push_back(x); + val->m_type_params.emplace_back(x); /* = exp(x); */ - callexp->m_params.push_back((ast_expression*)x); + callexp->m_params.push_back(x); /* return - 1; */ body->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_SUB_F, - (ast_expression*)callexp, - (ast_expression*)m_fold->m_imm_float[1] + callexp, + m_fold->m_imm_float[1] ) ) ); func->m_blocks.emplace_back(body); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::pow_() { @@ -620,23 +620,23 @@ ast_expression *intrin::pow_() { ast_function *func = value(&val, "pow", TYPE_FLOAT); /* prepare some calls for later */ - ast_call *callpow1 = ast_call_new(ctx(), (ast_expression*)val); /* for pow(base, -exp) */ - ast_call *callpow2 = ast_call_new(ctx(), (ast_expression*)val); /* for pow(vase, exp / 2) */ - ast_call *callsqrt1 = ast_call_new(ctx(), func_self("sqrt", "pow")); /* for sqrt(base) */ - ast_call *callsqrt2 = ast_call_new(ctx(), func_self("sqrt", "pow")); /* for sqrt(square) */ - ast_call *callfabs = ast_call_new(ctx(), func_self("fabs", "pow")); /* for fabs(mid - exp) */ + ast_call *callpow1 = ast_call::make(ctx(), val); /* for pow(base, -exp) */ + ast_call *callpow2 = ast_call::make(ctx(), val); /* for pow(vase, exp / 2) */ + ast_call *callsqrt1 = ast_call::make(ctx(), func_self("sqrt", "pow")); /* for sqrt(base) */ + ast_call *callsqrt2 = ast_call::make(ctx(), func_self("sqrt", "pow")); /* for sqrt(square) */ + ast_call *callfabs = ast_call::make(ctx(), func_self("fabs", "pow")); /* for fabs(mid - exp) */ /* prepare some blocks for later */ - ast_block *expgt1 = ast_block_new(ctx()); - ast_block *midltexp = ast_block_new(ctx()); - ast_block *midltexpelse = ast_block_new(ctx()); - ast_block *whileblock = ast_block_new(ctx()); + ast_block *expgt1 = new ast_block(ctx()); + ast_block *midltexp = new ast_block(ctx()); + ast_block *midltexpelse = new ast_block(ctx()); + ast_block *whileblock = new ast_block(ctx()); /* float pow(float base, float exp) */ - ast_value *base = ast_value_new(ctx(), "base", TYPE_FLOAT); - ast_value *exp = ast_value_new(ctx(), "exp", TYPE_FLOAT); + ast_value *base = new ast_value(ctx(), "base", TYPE_FLOAT); + ast_value *exp = new ast_value(ctx(), "exp", TYPE_FLOAT); /* { */ - ast_block *body = ast_block_new(ctx()); + ast_block *body = new ast_block(ctx()); /* * float result; @@ -646,12 +646,12 @@ ast_expression *intrin::pow_() { * float accumulate; * float mid; */ - ast_value *result = ast_value_new(ctx(), "result", TYPE_FLOAT); - ast_value *low = ast_value_new(ctx(), "low", TYPE_FLOAT); - ast_value *high = ast_value_new(ctx(), "high", TYPE_FLOAT); - ast_value *square = ast_value_new(ctx(), "square", TYPE_FLOAT); - ast_value *accumulate = ast_value_new(ctx(), "accumulate", TYPE_FLOAT); - ast_value *mid = ast_value_new(ctx(), "mid", TYPE_FLOAT); + ast_value *result = new ast_value(ctx(), "result", TYPE_FLOAT); + ast_value *low = new ast_value(ctx(), "low", TYPE_FLOAT); + ast_value *high = new ast_value(ctx(), "high", TYPE_FLOAT); + ast_value *square = new ast_value(ctx(), "square", TYPE_FLOAT); + ast_value *accumulate = new ast_value(ctx(), "accumulate", TYPE_FLOAT); + ast_value *mid = new ast_value(ctx(), "mid", TYPE_FLOAT); body->m_locals.push_back(result); body->m_locals.push_back(low); body->m_locals.push_back(high); @@ -659,25 +659,25 @@ ast_expression *intrin::pow_() { body->m_locals.push_back(accumulate); body->m_locals.push_back(mid); - val->m_type_params.push_back(base); - val->m_type_params.push_back(exp); + val->m_type_params.emplace_back(base); + val->m_type_params.emplace_back(exp); /* * if (exp == 0.0) * return 1; */ body->m_exprs.push_back( - (ast_expression*)ast_ifthen_new( + new ast_ifthen( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_EQ_F, - (ast_expression*)exp, - (ast_expression*)m_fold->m_imm_float[0] + exp, + m_fold->m_imm_float[0] ), - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)m_fold->m_imm_float[1] + m_fold->m_imm_float[1] ), nullptr ) @@ -688,29 +688,29 @@ ast_expression *intrin::pow_() { * return base; */ body->m_exprs.push_back( - (ast_expression*)ast_ifthen_new( + new ast_ifthen( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_EQ_F, - (ast_expression*)exp, - (ast_expression*)m_fold->m_imm_float[1] + exp, + m_fold->m_imm_float[1] ), - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)base + base ), nullptr ) ); /* = pow(base, -exp) */ - callpow1->m_params.push_back((ast_expression*)base); + callpow1->m_params.push_back(base); callpow1->m_params.push_back( - (ast_expression*)ast_unary_new( + ast_unary::make( ctx(), VINSTR_NEG_F, - (ast_expression*)exp + exp ) ); @@ -719,21 +719,21 @@ ast_expression *intrin::pow_() { * return 1.0 / ; */ body->m_exprs.push_back( - (ast_expression*)ast_ifthen_new( + new ast_ifthen( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_LT, - (ast_expression*)exp, - (ast_expression*)m_fold->m_imm_float[0] + exp, + m_fold->m_imm_float[0] ), - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_DIV_F, - (ast_expression*)m_fold->m_imm_float[1], - (ast_expression*)callpow1 + m_fold->m_imm_float[1], + callpow1 ) ), nullptr @@ -741,13 +741,13 @@ ast_expression *intrin::pow_() { ); /* = pow(base, exp / 2) */ - callpow2->m_params.push_back((ast_expression*)base); + callpow2->m_params.push_back(base); callpow2->m_params.push_back( - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_DIV_F, - (ast_expression*)exp, - (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */ + exp, + m_fold->m_imm_float[3] /* 2.0f */ ) ); @@ -758,21 +758,21 @@ ast_expression *intrin::pow_() { * } */ expgt1->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)result, - (ast_expression*)callpow2 + result, + callpow2 ) ); expgt1->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_MUL_F, - (ast_expression*)result, - (ast_expression*)result + result, + result ) ) ); @@ -783,15 +783,15 @@ ast_expression *intrin::pow_() { * } */ body->m_exprs.push_back( - (ast_expression*)ast_ifthen_new( + new ast_ifthen( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_GE, - (ast_expression*)exp, - (ast_expression*)m_fold->m_imm_float[1] + exp, + m_fold->m_imm_float[1] ), - (ast_expression*)expgt1, + expgt1, nullptr ) ); @@ -799,7 +799,7 @@ ast_expression *intrin::pow_() { /* * = sqrt(base) */ - callsqrt1->m_params.push_back((ast_expression*)base); + callsqrt1->m_params.push_back(base); /* * low = 0.0f; @@ -809,48 +809,48 @@ ast_expression *intrin::pow_() { * mid = high / 2.0f; */ body->m_exprs.push_back( - (ast_expression*)ast_store_new(ctx(), + new ast_store(ctx(), INSTR_STORE_F, - (ast_expression*)low, - (ast_expression*)m_fold->m_imm_float[0] + low, + m_fold->m_imm_float[0] ) ); body->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)high, - (ast_expression*)m_fold->m_imm_float[1] + high, + m_fold->m_imm_float[1] ) ); body->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)square, - (ast_expression*)callsqrt1 + square, + callsqrt1 ) ); body->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)accumulate, - (ast_expression*)square + accumulate, + square ) ); body->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)mid, - (ast_expression*)ast_binary_new( + mid, + new ast_binary( ctx(), INSTR_DIV_F, - (ast_expression*)high, - (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */ + high, + m_fold->m_imm_float[3] /* 2.0f */ ) ) ); @@ -862,20 +862,20 @@ ast_expression *intrin::pow_() { * } */ midltexp->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)low, - (ast_expression*)mid + low, + mid ) ); midltexp->m_exprs.push_back( - (ast_expression*)ast_binstore_new( + new ast_binstore( ctx(), INSTR_STORE_F, INSTR_MUL_F, - (ast_expression*)accumulate, - (ast_expression*)square + accumulate, + square ) ); @@ -886,24 +886,24 @@ ast_expression *intrin::pow_() { * } */ midltexpelse->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)high, - (ast_expression*)mid + high, + mid ) ); midltexpelse->m_exprs.push_back( - (ast_expression*)ast_binstore_new( + new ast_binstore( ctx(), INSTR_STORE_F, INSTR_MUL_F, - (ast_expression*)accumulate, - (ast_expression*)ast_binary_new( + accumulate, + new ast_binary( ctx(), INSTR_DIV_F, - (ast_expression*)m_fold->m_imm_float[1], - (ast_expression*)square + m_fold->m_imm_float[1], + square ) ) ); @@ -911,7 +911,7 @@ ast_expression *intrin::pow_() { /* * = sqrt(square) */ - callsqrt2->m_params.push_back((ast_expression*)square); + callsqrt2->m_params.push_back(square); /* * = { @@ -925,41 +925,41 @@ ast_expression *intrin::pow_() { * } */ whileblock->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)square, - (ast_expression*)callsqrt2 + square, + callsqrt2 ) ); whileblock->m_exprs.push_back( - (ast_expression*)ast_ifthen_new( + new ast_ifthen( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_LT, - (ast_expression*)mid, - (ast_expression*)exp + mid, + exp ), - (ast_expression*)midltexp, - (ast_expression*)midltexpelse + midltexp, + midltexpelse ) ); whileblock->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)mid, - (ast_expression*)ast_binary_new( + mid, + new ast_binary( ctx(), INSTR_DIV_F, - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_ADD_F, - (ast_expression*)low, - (ast_expression*)high + low, + high ), - (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */ + m_fold->m_imm_float[3] /* 2.0f */ ) ) ); @@ -968,11 +968,11 @@ ast_expression *intrin::pow_() { * = fabs(mid - exp) */ callfabs->m_params.push_back( - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_SUB_F, - (ast_expression*)mid, - (ast_expression*)exp + mid, + exp ) ); @@ -981,16 +981,16 @@ ast_expression *intrin::pow_() { * */ body->m_exprs.push_back( - (ast_expression*)ast_loop_new( + new ast_loop( ctx(), /* init */ nullptr, /* pre condition */ - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_GT, - (ast_expression*)callfabs, - (ast_expression*)m_fold->constgen_float(QC_POW_EPSILON, false) + callfabs, + m_fold->constgen_float(QC_POW_EPSILON, false) ), /* pre not */ false, @@ -1001,22 +1001,22 @@ ast_expression *intrin::pow_() { /* increment expression */ nullptr, /* code block */ - (ast_expression*)whileblock + whileblock ) ); /* return accumulate */ body->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)accumulate + accumulate ) ); /* } */ func->m_blocks.emplace_back(body); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::mod_() { @@ -1028,82 +1028,82 @@ ast_expression *intrin::mod_() { * } */ ast_value *val = nullptr; - ast_call *call = ast_call_new(ctx(), func_self("floor", "mod")); - ast_value *a = ast_value_new(ctx(), "a", TYPE_FLOAT); - ast_value *b = ast_value_new(ctx(), "b", TYPE_FLOAT); - ast_value *div = ast_value_new(ctx(), "div", TYPE_FLOAT); - ast_value *sign = ast_value_new(ctx(), "sign", TYPE_FLOAT); - ast_block *body = ast_block_new(ctx()); + ast_call *call = ast_call::make(ctx(), func_self("floor", "mod")); + ast_value *a = new ast_value(ctx(), "a", TYPE_FLOAT); + ast_value *b = new ast_value(ctx(), "b", TYPE_FLOAT); + ast_value *div = new ast_value(ctx(), "div", TYPE_FLOAT); + ast_value *sign = new ast_value(ctx(), "sign", TYPE_FLOAT); + ast_block *body = new ast_block(ctx()); ast_function *func = value(&val, "mod", TYPE_FLOAT); - val->m_type_params.push_back(a); - val->m_type_params.push_back(b); + val->m_type_params.emplace_back(a); + val->m_type_params.emplace_back(b); body->m_locals.push_back(div); body->m_locals.push_back(sign); /* div = a / b; */ body->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)div, - (ast_expression*)ast_binary_new( + div, + new ast_binary( ctx(), INSTR_DIV_F, - (ast_expression*)a, - (ast_expression*)b + a, + b ) ) ); /* sign = (div < 0.0f) ? -1 : 1; */ body->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)sign, - (ast_expression*)ast_ternary_new( + sign, + new ast_ternary( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_LT, - (ast_expression*)div, - (ast_expression*)m_fold->m_imm_float[0] + div, + m_fold->m_imm_float[0] ), - (ast_expression*)m_fold->m_imm_float[2], - (ast_expression*)m_fold->m_imm_float[1] + m_fold->m_imm_float[2], + m_fold->m_imm_float[1] ) ) ); /* floor(sign * div) */ call->m_params.push_back( - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_MUL_F, - (ast_expression*)sign, - (ast_expression*)div + sign, + div ) ); /* return a - b * sign * */ body->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_SUB_F, - (ast_expression*)a, - (ast_expression*)ast_binary_new( + a, + new ast_binary( ctx(), INSTR_MUL_F, - (ast_expression*)b, - (ast_expression*)ast_binary_new( + b, + new ast_binary( ctx(), INSTR_MUL_F, - (ast_expression*)sign, - (ast_expression*)call + sign, + call ) ) ) @@ -1112,7 +1112,7 @@ ast_expression *intrin::mod_() { func->m_blocks.emplace_back(body); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::fabs_() { @@ -1122,36 +1122,36 @@ ast_expression *intrin::fabs_() { * } */ ast_value *val = nullptr; - ast_value *arg1 = ast_value_new(ctx(), "x", TYPE_FLOAT); - ast_block *body = ast_block_new(ctx()); + ast_value *arg1 = new ast_value(ctx(), "x", TYPE_FLOAT); + ast_block *body = new ast_block(ctx()); ast_function *func = value(&val, "fabs", TYPE_FLOAT); body->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)ast_ternary_new( + new ast_ternary( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_LE, - (ast_expression*)arg1, - (ast_expression*)m_fold->m_imm_float[0] + arg1, + m_fold->m_imm_float[0] ), - (ast_expression*)ast_unary_new( + ast_unary::make( ctx(), VINSTR_NEG_F, - (ast_expression*)arg1 + arg1 ), - (ast_expression*)arg1 + arg1 ) ) ); - val->m_type_params.push_back(arg1); + val->m_type_params.emplace_back(arg1); func->m_blocks.emplace_back(body); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::epsilon_() { @@ -1163,67 +1163,67 @@ ast_expression *intrin::epsilon_() { * } */ ast_value *val = nullptr; - ast_value *eps = ast_value_new(ctx(), "eps", TYPE_FLOAT); - ast_block *body = ast_block_new(ctx()); + ast_value *eps = new ast_value(ctx(), "eps", TYPE_FLOAT); + ast_block *body = new ast_block(ctx()); ast_function *func = value(&val, "epsilon", TYPE_FLOAT); body->m_locals.push_back(eps); /* eps = 1.0f; */ body->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)eps, - (ast_expression*)m_fold->m_imm_float[0] + eps, + m_fold->m_imm_float[0] ) ); body->m_exprs.push_back( - (ast_expression*)ast_loop_new( + new ast_loop( ctx(), nullptr, nullptr, false, - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_NE_F, - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_ADD_F, - (ast_expression*)m_fold->m_imm_float[1], - (ast_expression*)ast_binary_new( + m_fold->m_imm_float[1], + new ast_binary( ctx(), INSTR_MUL_F, - (ast_expression*)eps, - (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */ + eps, + m_fold->m_imm_float[3] /* 2.0f */ ) ), - (ast_expression*)m_fold->m_imm_float[1] + m_fold->m_imm_float[1] ), false, nullptr, - (ast_expression*)ast_binstore_new( + new ast_binstore( ctx(), INSTR_STORE_F, INSTR_DIV_F, - (ast_expression*)eps, - (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */ + eps, + m_fold->m_imm_float[3] /* 2.0f */ ) ) ); /* return eps; */ body->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)eps + eps ) ); func->m_blocks.emplace_back(body); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::nan_() { @@ -1234,36 +1234,36 @@ ast_expression *intrin::nan_() { * } */ ast_value *val = nullptr; - ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT); + ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT); ast_function *func = value(&val, "nan", TYPE_FLOAT); - ast_block *block = ast_block_new(ctx()); + ast_block *block = new ast_block(ctx()); block->m_locals.push_back(x); block->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)x, - (ast_expression*)m_fold->m_imm_float[0] + x, + m_fold->m_imm_float[0] ) ); block->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_DIV_F, - (ast_expression*)x, - (ast_expression*)x + x, + x ) ) ); func->m_blocks.emplace_back(block); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::inf_() { @@ -1275,10 +1275,10 @@ ast_expression *intrin::inf_() { * } */ ast_value *val = nullptr; - ast_value *x = ast_value_new(ctx(), "x", TYPE_FLOAT); - ast_value *y = ast_value_new(ctx(), "y", TYPE_FLOAT); + ast_value *x = new ast_value(ctx(), "x", TYPE_FLOAT); + ast_value *y = new ast_value(ctx(), "y", TYPE_FLOAT); ast_function *func = value(&val, "inf", TYPE_FLOAT); - ast_block *block = ast_block_new(ctx()); + ast_block *block = new ast_block(ctx()); size_t i; block->m_locals.push_back(x); @@ -1287,30 +1287,30 @@ ast_expression *intrin::inf_() { /* to keep code size down */ for (i = 0; i <= 1; i++) { block->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)((i == 0) ? x : y), - (ast_expression*)m_fold->m_imm_float[i] + ((i == 0) ? x : y), + m_fold->m_imm_float[i] ) ); } block->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_DIV_F, - (ast_expression*)x, - (ast_expression*)y + x, + y ) ) ); func->m_blocks.emplace_back(block); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::ln_() { @@ -1380,34 +1380,34 @@ ast_expression *intrin::ln_() { */ ast_value *val = nullptr; - ast_value *power = ast_value_new(ctx(), "power", TYPE_FLOAT); - ast_value *base = ast_value_new(ctx(), "base",TYPE_FLOAT); - ast_value *whole= ast_value_new(ctx(), "whole", TYPE_FLOAT); - ast_value *nth = ast_value_new(ctx(), "nth", TYPE_FLOAT); - ast_value *sign = ast_value_new(ctx(), "sign", TYPE_FLOAT); - ast_value *A_i = ast_value_new(ctx(), "A_i", TYPE_FLOAT); - ast_value *B_i = ast_value_new(ctx(), "B_i", TYPE_FLOAT); - ast_value *A_iminus1 = ast_value_new(ctx(), "A_iminus1", TYPE_FLOAT); - ast_value *B_iminus1 = ast_value_new(ctx(), "B_iminus1", TYPE_FLOAT); - ast_value *b_iplus1 = ast_value_new(ctx(), "b_iplus1", TYPE_FLOAT); - ast_value *A_iplus1 = ast_value_new(ctx(), "A_iplus1", TYPE_FLOAT); - ast_value *B_iplus1 = ast_value_new(ctx(), "B_iplus1", TYPE_FLOAT); - ast_value *eps = ast_value_new(ctx(), "eps", TYPE_FLOAT); - ast_value *base2 = ast_value_new(ctx(), "base2", TYPE_FLOAT); - ast_value *n2 = ast_value_new(ctx(), "n2",TYPE_FLOAT); - ast_value *newbase2 = ast_value_new(ctx(), "newbase2", TYPE_FLOAT); - ast_block *block = ast_block_new(ctx()); - ast_block *plt1orblt1 = ast_block_new(ctx()); // (power <= 1.0f || base <= 1.0f) - ast_block *plt1 = ast_block_new(ctx()); // (power < 1.0f) - ast_block *blt1 = ast_block_new(ctx()); // (base< 1.0f) - ast_block *forloop = ast_block_new(ctx()); // for(;;) - ast_block *whileloop = ast_block_new(ctx()); // while (whole >= base) - ast_block *nestwhile= ast_block_new(ctx()); // while (whole >= newbase2) + ast_value *power = new ast_value(ctx(), "power", TYPE_FLOAT); + ast_value *base = new ast_value(ctx(), "base",TYPE_FLOAT); + ast_value *whole= new ast_value(ctx(), "whole", TYPE_FLOAT); + ast_value *nth = new ast_value(ctx(), "nth", TYPE_FLOAT); + ast_value *sign = new ast_value(ctx(), "sign", TYPE_FLOAT); + ast_value *A_i = new ast_value(ctx(), "A_i", TYPE_FLOAT); + ast_value *B_i = new ast_value(ctx(), "B_i", TYPE_FLOAT); + ast_value *A_iminus1 = new ast_value(ctx(), "A_iminus1", TYPE_FLOAT); + ast_value *B_iminus1 = new ast_value(ctx(), "B_iminus1", TYPE_FLOAT); + ast_value *b_iplus1 = new ast_value(ctx(), "b_iplus1", TYPE_FLOAT); + ast_value *A_iplus1 = new ast_value(ctx(), "A_iplus1", TYPE_FLOAT); + ast_value *B_iplus1 = new ast_value(ctx(), "B_iplus1", TYPE_FLOAT); + ast_value *eps = new ast_value(ctx(), "eps", TYPE_FLOAT); + ast_value *base2 = new ast_value(ctx(), "base2", TYPE_FLOAT); + ast_value *n2 = new ast_value(ctx(), "n2",TYPE_FLOAT); + ast_value *newbase2 = new ast_value(ctx(), "newbase2", TYPE_FLOAT); + ast_block *block = new ast_block(ctx()); + ast_block *plt1orblt1 = new ast_block(ctx()); // (power <= 1.0f || base <= 1.0f) + ast_block *plt1 = new ast_block(ctx()); // (power < 1.0f) + ast_block *blt1 = new ast_block(ctx()); // (base< 1.0f) + ast_block *forloop = new ast_block(ctx()); // for(;;) + ast_block *whileloop = new ast_block(ctx()); // while (whole >= base) + ast_block *nestwhile= new ast_block(ctx()); // while (whole >= newbase2) ast_function *func = value(&val, "ln", TYPE_FLOAT); size_t i; - val->m_type_params.push_back(power); - val->m_type_params.push_back(base); + val->m_type_params.emplace_back(power); + val->m_type_params.emplace_back(base); block->m_locals.push_back(whole); block->m_locals.push_back(nth); @@ -1420,21 +1420,21 @@ ast_expression *intrin::ln_() { /* sign = 1.0f; */ block->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)sign, - (ast_expression*)m_fold->m_imm_float[1] + sign, + m_fold->m_imm_float[1] ) ); /* eps = __builtin_epsilon(); */ block->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)eps, - (ast_expression*)ast_call_new( + eps, + ast_call::make( ctx(), func_self("__builtin_epsilon", "ln") ) @@ -1451,12 +1451,12 @@ ast_expression *intrin::ln_() { int j; for (j = 1; j >= 0; j--) { block->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)((j) ? ((i) ? B_iminus1 : A_i) + ((j) ? ((i) ? B_iminus1 : A_i) : ((i) ? A_iminus1 : B_i)), - (ast_expression*)m_fold->m_imm_float[j] + m_fold->m_imm_float[j] ) ); } @@ -1474,25 +1474,25 @@ ast_expression *intrin::ln_() { */ for (i = 0; i <= 1; i++) { ((i) ? blt1 : plt1)->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)((i) ? base : power), - (ast_expression*)ast_binary_new( + ((i) ? base : power), + new ast_binary( ctx(), INSTR_DIV_F, - (ast_expression*)m_fold->m_imm_float[1], - (ast_expression*)((i) ? base : power) + m_fold->m_imm_float[1], + ((i) ? base : power) ) ) ); plt1->m_exprs.push_back( - (ast_expression*)ast_binstore_new( + new ast_binstore( ctx(), INSTR_STORE_F, INSTR_MUL_F, - (ast_expression*)sign, - (ast_expression*)m_fold->m_imm_float[2] + sign, + m_fold->m_imm_float[2] ) ); } @@ -1508,27 +1508,27 @@ ast_expression *intrin::ln_() { * } */ plt1orblt1->m_exprs.push_back( - (ast_expression*)ast_ifthen_new( + new ast_ifthen( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_OR, - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_LE, - (ast_expression*)power, - (ast_expression*)m_fold->m_imm_float[0] + power, + m_fold->m_imm_float[0] ), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_LE, - (ast_expression*)base, - (ast_expression*)m_fold->m_imm_float[0] + base, + m_fold->m_imm_float[0] ) ), - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)ast_call_new( + ast_call::make( ctx(), func_self("__builtin_nan", "ln") ) @@ -1539,74 +1539,74 @@ ast_expression *intrin::ln_() { for (i = 0; i <= 1; i++) { plt1orblt1->m_exprs.push_back( - (ast_expression*)ast_ifthen_new( + new ast_ifthen( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_LT, - (ast_expression*)((i) ? base : power), - (ast_expression*)m_fold->m_imm_float[1] + ((i) ? base : power), + m_fold->m_imm_float[1] ), - (ast_expression*)((i) ? blt1 : plt1), + ((i) ? blt1 : plt1), nullptr ) ); } - block->m_exprs.push_back((ast_expression*)plt1orblt1); + block->m_exprs.push_back(plt1orblt1); /* whole = power; */ forloop->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)whole, - (ast_expression*)power + whole, + power ) ); /* nth = 0.0f; */ forloop->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)nth, - (ast_expression*)m_fold->m_imm_float[0] + nth, + m_fold->m_imm_float[0] ) ); /* base2 = base; */ whileloop->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)base2, - (ast_expression*)base + base2, + base ) ); /* n2 = 1.0f; */ whileloop->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)n2, - (ast_expression*)m_fold->m_imm_float[1] + n2, + m_fold->m_imm_float[1] ) ); /* newbase2 = base2 * base2; */ whileloop->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)newbase2, - (ast_expression*)ast_binary_new( + newbase2, + new ast_binary( ctx(), INSTR_MUL_F, - (ast_expression*)base2, - (ast_expression*)base2 + base2, + base2 ) ) ); @@ -1618,93 +1618,93 @@ ast_expression *intrin::ln_() { /* base2 = newbase2; */ nestwhile->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)base2, - (ast_expression*)newbase2 + base2, + newbase2 ) ); /* n2 *= 2; */ nestwhile->m_exprs.push_back( - (ast_expression*)ast_binstore_new( + new ast_binstore( ctx(), INSTR_STORE_F, INSTR_MUL_F, - (ast_expression*)n2, - (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */ + n2, + m_fold->m_imm_float[3] /* 2.0f */ ) ); /* newbase2 *= newbase2; */ nestwhile->m_exprs.push_back( - (ast_expression*)ast_binstore_new( + new ast_binstore( ctx(), INSTR_STORE_F, INSTR_MUL_F, - (ast_expression*)newbase2, - (ast_expression*)newbase2 + newbase2, + newbase2 ) ); /* while (whole >= newbase2) */ whileloop->m_exprs.push_back( - (ast_expression*)ast_loop_new( + new ast_loop( ctx(), nullptr, - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_GE, - (ast_expression*)whole, - (ast_expression*)newbase2 + whole, + newbase2 ), false, nullptr, false, nullptr, - (ast_expression*)nestwhile + nestwhile ) ); /* whole /= base2; */ whileloop->m_exprs.push_back( - (ast_expression*)ast_binstore_new( + new ast_binstore( ctx(), INSTR_STORE_F, INSTR_DIV_F, - (ast_expression*)whole, - (ast_expression*)base2 + whole, + base2 ) ); /* nth += n2; */ whileloop->m_exprs.push_back( - (ast_expression*)ast_binstore_new( + new ast_binstore( ctx(), INSTR_STORE_F, INSTR_ADD_F, - (ast_expression*)nth, - (ast_expression*)n2 + nth, + n2 ) ); /* while (whole >= base) */ forloop->m_exprs.push_back( - (ast_expression*)ast_loop_new( + new ast_loop( ctx(), nullptr, - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_GE, - (ast_expression*)whole, - (ast_expression*)base + whole, + base ), false, nullptr, false, nullptr, - (ast_expression*)whileloop + whileloop ) ); @@ -1714,11 +1714,11 @@ ast_expression *intrin::ln_() { /* b_iplus1 = nth; */ forloop->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)b_iplus1, - (ast_expression*)nth + b_iplus1, + nth ) ); @@ -1728,20 +1728,20 @@ ast_expression *intrin::ln_() { */ for (i = 0; i <= 1; i++) { forloop->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)((i) ? B_iplus1 : A_iplus1), - (ast_expression*)ast_binary_new( + ((i) ? B_iplus1 : A_iplus1), + new ast_binary( ctx(), INSTR_ADD_F, - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_MUL_F, - (ast_expression*)b_iplus1, - (ast_expression*) ((i) ? B_i : A_i) + b_iplus1, + ((i) ? B_i : A_i) ), - (ast_expression*)((i) ? B_iminus1 : A_iminus1) + ((i) ? B_iminus1 : A_iminus1) ) ) ); @@ -1753,11 +1753,11 @@ ast_expression *intrin::ln_() { */ for (i = 0; i <= 1; i++) { forloop->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)((i) ? B_iminus1 : A_iminus1), - (ast_expression*)((i) ? B_i : A_i) + ((i) ? B_iminus1 : A_iminus1), + ((i) ? B_i : A_i) ) ); } @@ -1768,11 +1768,11 @@ ast_expression *intrin::ln_() { */ for (i = 0; i <= 1; i++) { forloop->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)((i) ? B_i : A_i), - (ast_expression*)((i) ? B_iplus1 : A_iplus1) + ((i) ? B_i : A_i), + ((i) ? B_iplus1 : A_iplus1) ) ); } @@ -1782,20 +1782,20 @@ ast_expression *intrin::ln_() { * break; */ forloop->m_exprs.push_back( - (ast_expression*)ast_ifthen_new( + new ast_ifthen( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_LE, - (ast_expression*)whole, - (ast_expression*)ast_binary_new( + whole, + new ast_binary( ctx(), INSTR_ADD_F, - (ast_expression*)m_fold->m_imm_float[1], - (ast_expression*)eps + m_fold->m_imm_float[1], + eps ) ), - (ast_expression*)ast_breakcont_new( + new ast_breakcont( ctx(), false, 0 @@ -1810,43 +1810,43 @@ ast_expression *intrin::ln_() { */ for (i = 0; i <= 1; i++) { forloop->m_exprs.push_back( - (ast_expression*)ast_store_new( + new ast_store( ctx(), INSTR_STORE_F, - (ast_expression*)((i) ? base : power), - (ast_expression*)((i) ? whole : base) + ((i) ? base : power), + ((i) ? whole : base) ) ); } /* add the for loop block */ block->m_exprs.push_back( - (ast_expression*)ast_loop_new( + new ast_loop( ctx(), nullptr, /* for(; 1; ) ?? (can this be nullptr too?) */ - (ast_expression*)m_fold->m_imm_float[1], + m_fold->m_imm_float[1], false, nullptr, false, nullptr, - (ast_expression*)forloop + forloop ) ); /* return sign * A_i / B_il */ block->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), INSTR_MUL_F, - (ast_expression*)sign, - (ast_expression*)ast_binary_new( + sign, + new ast_binary( ctx(), INSTR_DIV_F, - (ast_expression*)A_i, - (ast_expression*)B_i + A_i, + B_i ) ) ) @@ -1854,31 +1854,31 @@ ast_expression *intrin::ln_() { func->m_blocks.emplace_back(block); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::log_variant(const char *name, float base) { ast_value *val = nullptr; - ast_call *callln = ast_call_new (ctx(), func_self("__builtin_ln", name)); - ast_value *arg1 = ast_value_new(ctx(), "x", TYPE_FLOAT); - ast_block *body = ast_block_new(ctx()); + ast_call *callln = ast_call::make(ctx(), func_self("__builtin_ln", name)); + ast_value *arg1 = new ast_value(ctx(), "x", TYPE_FLOAT); + ast_block *body = new ast_block(ctx()); ast_function *func = value(&val, name, TYPE_FLOAT); - val->m_type_params.push_back(arg1); + val->m_type_params.emplace_back(arg1); - callln->m_params.push_back((ast_expression*)arg1); - callln->m_params.push_back((ast_expression*)m_fold->constgen_float(base, false)); + callln->m_params.push_back(arg1); + callln->m_params.push_back(m_fold->constgen_float(base, false)); body->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)callln + callln ) ); func->m_blocks.emplace_back(body); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::log_() { @@ -1901,41 +1901,41 @@ ast_expression *intrin::shift_variant(const char *name, size_t instr) { * return floor(a [instr] pow(2, b)); */ ast_value *val = nullptr; - ast_call *callpow = ast_call_new(ctx(), func_self("pow", name)); - ast_call *callfloor = ast_call_new(ctx(), func_self("floor", name)); - ast_value *a = ast_value_new(ctx(), "a", TYPE_FLOAT); - ast_value *b = ast_value_new(ctx(), "b", TYPE_FLOAT); - ast_block *body = ast_block_new(ctx()); + ast_call *callpow = ast_call::make(ctx(), func_self("pow", name)); + ast_call *callfloor = ast_call::make(ctx(), func_self("floor", name)); + ast_value *a = new ast_value(ctx(), "a", TYPE_FLOAT); + ast_value *b = new ast_value(ctx(), "b", TYPE_FLOAT); + ast_block *body = new ast_block(ctx()); ast_function *func = value(&val, name, TYPE_FLOAT); - val->m_type_params.push_back(a); - val->m_type_params.push_back(b); + val->m_type_params.emplace_back(a); + val->m_type_params.emplace_back(b); /* = pow(2, b) */ - callpow->m_params.push_back((ast_expression*)m_fold->m_imm_float[3]); - callpow->m_params.push_back((ast_expression*)b); + callpow->m_params.push_back(m_fold->m_imm_float[3]); + callpow->m_params.push_back(b); /* = floor(a [instr] ) */ callfloor->m_params.push_back( - (ast_expression*)ast_binary_new( + new ast_binary( ctx(), instr, - (ast_expression*)a, - (ast_expression*)callpow + a, + callpow ) ); /* return */ body->m_exprs.push_back( - (ast_expression*)ast_return_new( + new ast_return( ctx(), - (ast_expression*)callfloor + callfloor ) ); func->m_blocks.emplace_back(body); reg(val, func); - return (ast_expression*)val; + return val; } ast_expression *intrin::lshift() { @@ -1998,14 +1998,14 @@ intrin::intrin(parser_t *parser) } ast_expression *intrin::do_fold(ast_value *val, ast_expression **exprs) { - if (!val || !val->m_name) + if (!val || !val->m_name.length()) return nullptr; static constexpr size_t kPrefixLength = 10; // "__builtin_" for (auto &it : m_intrinsics) { - if (!strcmp(val->m_name, it.name)) + if (val->m_name == it.name) return (vec_size(exprs) != it.args) ? nullptr - : m_fold->intrinsic(val->m_name + kPrefixLength, exprs); + : m_fold->intrinsic(val->m_name.c_str() + kPrefixLength, exprs); } return nullptr; } @@ -2027,7 +2027,7 @@ ast_expression *intrin::func_self(const char *name, const char *from) { /* try current first */ if ((find = parser_find_global(m_parser, name)) && ((ast_value*)find)->m_vtype == TYPE_FUNCTION) for (auto &it : m_parser->functions) - if (((ast_value*)find)->m_name && !strcmp(it->m_name, ((ast_value*)find)->m_name) && it->m_builtin < 0) + if (reinterpret_cast(find)->m_name.length() && it->m_name == reinterpret_cast(find)->m_name && it->m_builtin < 0) return find; /* try name second */ if ((find = func_try(offsetof(intrin_func_t, name), name))) diff --git a/parser.cpp b/parser.cpp index fcb782c..fd29f00 100644 --- a/parser.cpp +++ b/parser.cpp @@ -13,7 +13,9 @@ static void parser_enterblock(parser_t *parser); static bool parser_leaveblock(parser_t *parser); static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e); +static void parser_addlocal(parser_t *parser, const std::string &name, ast_expression *e); static void parser_addglobal(parser_t *parser, const char *name, ast_expression *e); +static void parser_addglobal(parser_t *parser, const std::string &name, ast_expression *e); static bool parse_typedef(parser_t *parser); static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofields, int qualifier, ast_value *cached_typedef, bool noref, bool is_static, uint32_t qflags, char *vstring); static ast_block* parse_block(parser_t *parser); @@ -26,7 +28,7 @@ static ast_value* parser_create_array_setter_proto(parser_t *parser, ast_value * static ast_value* parser_create_array_getter_proto(parser_t *parser, ast_value *array, const ast_expression *elemtype, const char *funcname); static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef, bool *is_vararg); -static void parseerror(parser_t *parser, const char *fmt, ...) +static void parseerror_(parser_t *parser, const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -34,8 +36,13 @@ static void parseerror(parser_t *parser, const char *fmt, ...) va_end(ap); } -/* returns true if it counts as an error */ -static bool GMQCC_WARN parsewarning(parser_t *parser, int warntype, const char *fmt, ...) +template +static inline void parseerror(parser_t *parser, const char *fmt, const Ts&... ts) { + return parseerror_(parser, fmt, formatNormalize(ts)...); +} + +// returns true if it counts as an error +static bool GMQCC_WARN parsewarning_(parser_t *parser, int warntype, const char *fmt, ...) { bool r; va_list ap; @@ -45,6 +52,11 @@ static bool GMQCC_WARN parsewarning(parser_t *parser, int warntype, const char * return r; } +template +static inline bool GMQCC_WARN parsewarning(parser_t *parser, int warntype, const char *fmt, const Ts&... ts) { + return parsewarning_(parser, warntype, fmt, formatNormalize(ts)...); +} + /********************************************************************** * parsing */ @@ -76,18 +88,23 @@ char *parser_strdup(const char *str) return util_strdup(str); } -static ast_expression* parser_find_field(parser_t *parser, const char *name) -{ - return ( ast_expression*)util_htget(parser->htfields, name); +static ast_expression* parser_find_field(parser_t *parser, const char *name) { + return (ast_expression*)util_htget(parser->htfields, name); +} +static ast_expression* parser_find_field(parser_t *parser, const std::string &name) { + return parser_find_field(parser, name.c_str()); } static ast_expression* parser_find_label(parser_t *parser, const char *name) { for (auto &it : parser->labels) - if (!strcmp(it->m_name, name)) - return (ast_expression*)it; + if (it->m_name == name) + return it; return nullptr; } +static inline ast_expression* parser_find_label(parser_t *parser, const std::string &name) { + return parser_find_label(parser, name.c_str()); +} ast_expression* parser_find_global(parser_t *parser, const char *name) { @@ -97,6 +114,10 @@ ast_expression* parser_find_global(parser_t *parser, const char *name) return (ast_expression*)util_htget(parser->htglobals, name); } +ast_expression* parser_find_global(parser_t *parser, const std::string &name) { + return parser_find_global(parser, name.c_str()); +} + static ast_expression* parser_find_param(parser_t *parser, const char *name) { ast_value *fun; @@ -104,8 +125,8 @@ static ast_expression* parser_find_param(parser_t *parser, const char *name) return nullptr; fun = parser->function->m_function_type; for (auto &it : fun->m_type_params) { - if (!strcmp(it->m_name, name)) - return (ast_expression*)it; + if (it->m_name == name) + return it.get(); } return nullptr; } @@ -127,6 +148,10 @@ static ast_expression* parser_find_local(parser_t *parser, const char *name, siz return parser_find_param(parser, name); } +static ast_expression* parser_find_local(parser_t *parser, const std::string &name, size_t upto, bool *isparam) { + return parser_find_local(parser, name.c_str(), upto, isparam); +} + static ast_expression* parser_find_var(parser_t *parser, const char *name) { bool dummy; @@ -136,6 +161,10 @@ static ast_expression* parser_find_var(parser_t *parser, const char *name) return v; } +static inline ast_expression* parser_find_var(parser_t *parser, const std::string &name) { + return parser_find_var(parser, name.c_str()); +} + static ast_value* parser_find_typedef(parser_t *parser, const char *name, size_t upto) { size_t i, hash; @@ -150,6 +179,10 @@ static ast_value* parser_find_typedef(parser_t *parser, const char *name, size_t return nullptr; } +static ast_value* parser_find_typedef(parser_t *parser, const std::string &name, size_t upto) { + return parser_find_typedef(parser, name.c_str(), upto); +} + struct sy_elem { size_t etype; /* 0 = expression, others are operators */ bool isparen; @@ -189,7 +222,7 @@ static sy_elem syblock(lex_ctx_t ctx, ast_block *v) { sy_elem e; e.etype = 0; e.off = 0; - e.out = (ast_expression*)v; + e.out = v; e.block = v; e.ctx = ctx; e.isparen = false; @@ -249,13 +282,13 @@ static bool rotate_entfield_array_index_nodes(ast_expression **out) oldindex = index; - index = ast_array_index_new(ctx, (ast_expression*)field, sub); - entfield = ast_entfield_new(ctx, entity, (ast_expression*)index); - *out = (ast_expression*)entfield; + index = ast_array_index::make(ctx, field, sub); + entfield = new ast_entfield(ctx, entity, index); + *out = entfield; oldindex->m_array = nullptr; oldindex->m_index = nullptr; - ast_delete(oldindex); + delete oldindex; return true; } @@ -360,12 +393,12 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) if (exprs[0]->m_vtype == TYPE_VECTOR && exprs[1]->m_vtype == TYPE_NOEXPR) { - if (exprs[1] == (ast_expression*)parser->const_vec[0]) - out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, nullptr); - else if (exprs[1] == (ast_expression*)parser->const_vec[1]) - out = (ast_expression*)ast_member_new(ctx, exprs[0], 1, nullptr); - else if (exprs[1] == (ast_expression*)parser->const_vec[2]) - out = (ast_expression*)ast_member_new(ctx, exprs[0], 2, nullptr); + if (exprs[1] == parser->const_vec[0]) + out = ast_member::make(ctx, exprs[0], 0, ""); + else if (exprs[1] == parser->const_vec[1]) + out = ast_member::make(ctx, exprs[0], 1, ""); + else if (exprs[1] == parser->const_vec[2]) + out = ast_member::make(ctx, exprs[0], 2, ""); else { compile_error(ctx, "access to invalid vector component"); return false; @@ -376,7 +409,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) compile_error(exprs[1]->m_context, "type error: right hand of member-operand should be an entity-field"); return false; } - out = (ast_expression*)ast_entfield_new(ctx, exprs[0], exprs[1]); + out = new ast_entfield(ctx, exprs[0], exprs[1]); } else if (exprs[0]->m_vtype == TYPE_VECTOR) { compile_error(exprs[1]->m_context, "vectors cannot be accessed this way"); @@ -402,7 +435,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) compile_error(exprs[1]->m_context, "index must be of type float, not %s", ty1); return false; } - out = (ast_expression*)ast_array_index_new(ctx, exprs[0], exprs[1]); + out = ast_array_index::make(ctx, exprs[0], exprs[1]); rotate_entfield_array_index_nodes(&out); break; @@ -414,17 +447,17 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return true; } if (blocks[0]) { - if (!ast_block_add_expr(blocks[0], exprs[1])) + if (!blocks[0]->addExpr(exprs[1])) return false; } else { - blocks[0] = ast_block_new(ctx); - if (!ast_block_add_expr(blocks[0], exprs[0]) || - !ast_block_add_expr(blocks[0], exprs[1])) + blocks[0] = new ast_block(ctx); + if (!blocks[0]->addExpr(exprs[0]) || + !blocks[0]->addExpr(exprs[1])) { return false; } } - ast_block_set_type(blocks[0], exprs[1]); + blocks[0]->setType(*exprs[1]); sy->out.push_back(syblock(ctx, blocks[0])); return true; @@ -443,32 +476,32 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; } if (exprs[0]->m_vtype == TYPE_FLOAT) - out = (ast_expression*)ast_unary_new(ctx, VINSTR_NEG_F, exprs[0]); + out = ast_unary::make(ctx, VINSTR_NEG_F, exprs[0]); else - out = (ast_expression*)ast_unary_new(ctx, VINSTR_NEG_V, exprs[0]); + out = ast_unary::make(ctx, VINSTR_NEG_V, exprs[0]); break; case opid2('!','P'): if (!(out = parser->m_fold.op(op, exprs))) { switch (exprs[0]->m_vtype) { case TYPE_FLOAT: - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, exprs[0]); + out = ast_unary::make(ctx, INSTR_NOT_F, exprs[0]); break; case TYPE_VECTOR: - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[0]); + out = ast_unary::make(ctx, INSTR_NOT_V, exprs[0]); break; case TYPE_STRING: if (OPTS_FLAG(TRUE_EMPTY_STRINGS)) - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, exprs[0]); + out = ast_unary::make(ctx, INSTR_NOT_F, exprs[0]); else - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[0]); + out = ast_unary::make(ctx, INSTR_NOT_S, exprs[0]); break; /* we don't constant-fold NOT for these types */ case TYPE_ENTITY: - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_ENT, exprs[0]); + out = ast_unary::make(ctx, INSTR_NOT_ENT, exprs[0]); break; case TYPE_FUNCTION: - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_FNC, exprs[0]); + out = ast_unary::make(ctx, INSTR_NOT_FNC, exprs[0]); break; default: compile_error(ctx, "invalid types used in expression: cannot logically negate type %s", @@ -595,11 +628,11 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) ast_call *call = nullptr; if (!mod) return false; /* can return null for missing floor */ - call = ast_call_new(parser_ctx(parser), mod); + call = ast_call::make(parser_ctx(parser), mod); call->m_params.push_back(exprs[0]); call->m_params.push_back(exprs[1]); - out = (ast_expression*)call; + out = call; } break; @@ -662,10 +695,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) if (!(out = parser->m_fold.op(op, exprs))) { ast_expression *shift = parser->m_intrin.func((op->id == opid2('<','<')) ? "__builtin_lshift" : "__builtin_rshift"); - ast_call *call = ast_call_new(parser_ctx(parser), shift); + ast_call *call = ast_call::make(parser_ctx(parser), shift); call->m_params.push_back(exprs[0]); call->m_params.push_back(exprs[1]); - out = (ast_expression*)call; + out = call; } break; @@ -680,14 +713,14 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) if(!(out = parser->m_fold.op(op, exprs))) { ast_expression *shift = parser->m_intrin.func((op->id == opid3('<','<','=')) ? "__builtin_lshift" : "__builtin_rshift"); - ast_call *call = ast_call_new(parser_ctx(parser), shift); + ast_call *call = ast_call::make(parser_ctx(parser), shift); call->m_params.push_back(exprs[0]); call->m_params.push_back(exprs[1]); - out = (ast_expression*)ast_store_new( + out = new ast_store( parser_ctx(parser), INSTR_STORE_F, exprs[0], - (ast_expression*)call + call ); } @@ -698,7 +731,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) case opid2('&','&'): generated_op += INSTR_AND; if (!(out = parser->m_fold.op(op, exprs))) { - if (OPTS_FLAG(PERL_LOGIC) && !ast_compare_type(exprs[0], exprs[1])) { + if (OPTS_FLAG(PERL_LOGIC) && !exprs[0]->compareType(*exprs[1])) { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); ast_type_to_string(exprs[1], ty2, sizeof(ty2)); compile_error(ctx, "invalid types for logical operation with -fperl-logic: %s and %s", ty1, ty2); @@ -706,9 +739,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } for (i = 0; i < 2; ++i) { if (OPTS_FLAG(CORRECT_LOGIC) && exprs[i]->m_vtype == TYPE_VECTOR) { - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[i]); + out = ast_unary::make(ctx, INSTR_NOT_V, exprs[i]); if (!out) break; - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out); + out = ast_unary::make(ctx, INSTR_NOT_F, out); if (!out) break; exprs[i] = out; out = nullptr; if (OPTS_FLAG(PERL_LOGIC)) { @@ -717,9 +750,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } } else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && exprs[i]->m_vtype == TYPE_STRING) { - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[i]); + out = ast_unary::make(ctx, INSTR_NOT_S, exprs[i]); if (!out) break; - out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out); + out = ast_unary::make(ctx, INSTR_NOT_F, out); if (!out) break; exprs[i] = out; out = nullptr; if (OPTS_FLAG(PERL_LOGIC)) { @@ -738,14 +771,14 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; } sy->paren.pop_back(); - if (!ast_compare_type(exprs[1], exprs[2])) { + if (!exprs[1]->compareType(*exprs[2])) { ast_type_to_string(exprs[1], ty1, sizeof(ty1)); ast_type_to_string(exprs[2], ty2, sizeof(ty2)); compile_error(ctx, "operands of ternary expression must have the same type, got %s and %s", ty1, ty2); return false; } if (!(out = parser->m_fold.op(op, exprs))) - out = (ast_expression*)ast_ternary_new(ctx, exprs[0], exprs[1], exprs[2]); + out = new ast_ternary(ctx, exprs[0], exprs[1], exprs[2]); break; case opid2('*', '*'): @@ -758,10 +791,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } if (!(out = parser->m_fold.op(op, exprs))) { - ast_call *gencall = ast_call_new(parser_ctx(parser), parser->m_intrin.func("pow")); + ast_call *gencall = ast_call::make(parser_ctx(parser), parser->m_intrin.func("pow")); gencall->m_params.push_back(exprs[0]); gencall->m_params.push_back(exprs[1]); - out = (ast_expression*)gencall; + out = gencall; } break; @@ -797,23 +830,23 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) if (!(out = parser->m_fold.op(op, exprs))) { /* This whole block is NOT fold_binary safe */ - ast_binary *eq = ast_binary_new(ctx, INSTR_EQ_F, exprs[0], exprs[1]); + ast_binary *eq = new ast_binary(ctx, INSTR_EQ_F, exprs[0], exprs[1]); eq->m_refs = AST_REF_NONE; /* if (lt) { */ - out = (ast_expression*)ast_ternary_new(ctx, - (ast_expression*)ast_binary_new(ctx, INSTR_LT, exprs[0], exprs[1]), + out = new ast_ternary(ctx, + new ast_binary(ctx, INSTR_LT, exprs[0], exprs[1]), /* out = -1 */ - (ast_expression*)parser->m_fold.imm_float(2), + parser->m_fold.imm_float(2), /* } else { */ /* if (eq) { */ - (ast_expression*)ast_ternary_new(ctx, (ast_expression*)eq, + new ast_ternary(ctx, eq, /* out = 0 */ - (ast_expression*)parser->m_fold.imm_float(0), + parser->m_fold.imm_float(0), /* } else { */ /* out = 1 */ - (ast_expression*)parser->m_fold.imm_float(1) + parser->m_fold.imm_float(1) /* } */ ) /* } */ @@ -871,7 +904,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } else assignop = type_storep_instr[exprs[0]->m_vtype]; - if (assignop == VINSTR_END || !ast_compare_type(field->m_next, exprs[1])) + if (assignop == VINSTR_END || !field->m_next->compareType(*exprs[1])) { ast_type_to_string(field->m_next, ty1, sizeof(ty1)); ast_type_to_string(exprs[1], ty2, sizeof(ty2)); @@ -903,7 +936,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) ast_type_to_string(exprs[1], ty2, sizeof(ty2)); compile_error(ctx, "invalid types in assignment: cannot assign %s to %s", ty2, ty1); } - else if (!ast_compare_type(exprs[0], exprs[1])) + else if (!exprs[0]->compareType(*exprs[1])) { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); ast_type_to_string(exprs[1], ty2, sizeof(ty2)); @@ -922,7 +955,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) /* When we're a vector of part of an entity field we use STOREP */ if (ast_istype(exprs[0], ast_member) && ast_istype(((ast_member*)exprs[0])->m_owner, ast_entfield)) assignop = INSTR_STOREP_F; - out = (ast_expression*)ast_store_new(ctx, assignop, exprs[0], exprs[1]); + out = new ast_store(ctx, assignop, exprs[0], exprs[1]); break; case opid3('+','+','P'): case opid3('-','-','P'): @@ -938,13 +971,13 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) addop = INSTR_SUB_F; (void)check_write_to(exprs[0]->m_context, exprs[0]); if (ast_istype(exprs[0], ast_entfield)) { - out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop, - exprs[0], - (ast_expression*)parser->m_fold.imm_float(1)); + out = new ast_binstore(ctx, INSTR_STOREP_F, addop, + exprs[0], + parser->m_fold.imm_float(1)); } else { - out = (ast_expression*)ast_binstore_new(ctx, INSTR_STORE_F, addop, - exprs[0], - (ast_expression*)parser->m_fold.imm_float(1)); + out = new ast_binstore(ctx, INSTR_STORE_F, addop, + exprs[0], + parser->m_fold.imm_float(1)); } break; case opid3('S','+','+'): @@ -964,19 +997,19 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } (void)check_write_to(exprs[0]->m_context, exprs[0]); if (ast_istype(exprs[0], ast_entfield)) { - out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop, - exprs[0], - (ast_expression*)parser->m_fold.imm_float(1)); + out = new ast_binstore(ctx, INSTR_STOREP_F, addop, + exprs[0], + parser->m_fold.imm_float(1)); } else { - out = (ast_expression*)ast_binstore_new(ctx, INSTR_STORE_F, addop, - exprs[0], - (ast_expression*)parser->m_fold.imm_float(1)); + out = new ast_binstore(ctx, INSTR_STORE_F, addop, + exprs[0], + parser->m_fold.imm_float(1)); } if (!out) return false; out = fold::binary(ctx, subop, out, - (ast_expression*)parser->m_fold.imm_float(1)); + parser->m_fold.imm_float(1)); break; case opid2('+','='): @@ -997,14 +1030,14 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) assignop = type_store_instr[exprs[0]->m_vtype]; switch (exprs[0]->m_vtype) { case TYPE_FLOAT: - out = (ast_expression*)ast_binstore_new(ctx, assignop, - (op->id == opid2('+','=') ? INSTR_ADD_F : INSTR_SUB_F), - exprs[0], exprs[1]); + out = new ast_binstore(ctx, assignop, + (op->id == opid2('+','=') ? INSTR_ADD_F : INSTR_SUB_F), + exprs[0], exprs[1]); break; case TYPE_VECTOR: - out = (ast_expression*)ast_binstore_new(ctx, assignop, - (op->id == opid2('+','=') ? INSTR_ADD_V : INSTR_SUB_V), - exprs[0], exprs[1]); + out = new ast_binstore(ctx, assignop, + (op->id == opid2('+','=') ? INSTR_ADD_V : INSTR_SUB_V), + exprs[0], exprs[1]); break; default: compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s", @@ -1032,24 +1065,24 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) assignop = type_store_instr[exprs[0]->m_vtype]; switch (exprs[0]->m_vtype) { case TYPE_FLOAT: - out = (ast_expression*)ast_binstore_new(ctx, assignop, - (op->id == opid2('*','=') ? INSTR_MUL_F : INSTR_DIV_F), - exprs[0], exprs[1]); + out = new ast_binstore(ctx, assignop, + (op->id == opid2('*','=') ? INSTR_MUL_F : INSTR_DIV_F), + exprs[0], exprs[1]); break; case TYPE_VECTOR: if (op->id == opid2('*','=')) { - out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF, - exprs[0], exprs[1]); + out = new ast_binstore(ctx, assignop, INSTR_MUL_VF, + exprs[0], exprs[1]); } else { out = fold::binary(ctx, INSTR_DIV_F, - (ast_expression*)parser->m_fold.imm_float(1), + parser->m_fold.imm_float(1), exprs[1]); if (!out) { compile_error(ctx, "internal error: failed to generate division"); return false; } - out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF, - exprs[0], out); + out = new ast_binstore(ctx, assignop, INSTR_MUL_VF, + exprs[0], out); } break; default: @@ -1075,13 +1108,13 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) else assignop = type_store_instr[exprs[0]->m_vtype]; if (exprs[0]->m_vtype == TYPE_FLOAT) - out = (ast_expression*)ast_binstore_new(ctx, assignop, - (op->id == opid2('^','=') ? VINSTR_BITXOR : op->id == opid2('&','=') ? INSTR_BITAND : INSTR_BITOR), - exprs[0], exprs[1]); + out = new ast_binstore(ctx, assignop, + (op->id == opid2('^','=') ? VINSTR_BITXOR : op->id == opid2('&','=') ? INSTR_BITAND : INSTR_BITOR), + exprs[0], exprs[1]); else - out = (ast_expression*)ast_binstore_new(ctx, assignop, - (op->id == opid2('^','=') ? VINSTR_BITXOR_V : op->id == opid2('&','=') ? VINSTR_BITAND_V : VINSTR_BITOR_V), - exprs[0], exprs[1]); + out = new ast_binstore(ctx, assignop, + (op->id == opid2('^','=') ? VINSTR_BITXOR_V : op->id == opid2('&','=') ? VINSTR_BITAND_V : VINSTR_BITOR_V), + exprs[0], exprs[1]); break; case opid3('&','~','='): /* This is like: a &= ~(b); @@ -1107,11 +1140,11 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; (void)check_write_to(ctx, exprs[0]); if (exprs[0]->m_vtype == TYPE_FLOAT) - asbinstore = ast_binstore_new(ctx, assignop, INSTR_SUB_F, exprs[0], out); + asbinstore = new ast_binstore(ctx, assignop, INSTR_SUB_F, exprs[0], out); else - asbinstore = ast_binstore_new(ctx, assignop, INSTR_SUB_V, exprs[0], out); + asbinstore = new ast_binstore(ctx, assignop, INSTR_SUB_V, exprs[0], out); asbinstore->m_keep_dest = true; - out = (ast_expression*)asbinstore; + out = asbinstore; break; case opid3('l', 'e', 'n'): @@ -1138,9 +1171,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } if (!(out = parser->m_fold.op(op, exprs))) { if (exprs[0]->m_vtype == TYPE_FLOAT) { - out = fold::binary(ctx, INSTR_SUB_F, (ast_expression*)parser->m_fold.imm_float(2), exprs[0]); + out = fold::binary(ctx, INSTR_SUB_F, parser->m_fold.imm_float(2), exprs[0]); } else { - out = fold::binary(ctx, INSTR_SUB_V, (ast_expression*)parser->m_fold.imm_vector(1), exprs[0]); + out = fold::binary(ctx, INSTR_SUB_V, parser->m_fold.imm_vector(1), exprs[0]); } } break; @@ -1201,7 +1234,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy) ast_type_to_string(sy->out.back().out, ty, sizeof(ty)); ast_unref(sy->out.back().out); sy->out[fid] = syexp(sy->out.back().out->m_context, - (ast_expression*)parser->m_fold.constgen_string(ty, false)); + parser->m_fold.constgen_string(ty, false)); sy->out.pop_back(); return true; } @@ -1212,8 +1245,8 @@ static bool parser_close_call(parser_t *parser, shunt *sy) * and than fruitfully fold them. */ #define fold_can_1(X) \ - (ast_istype(((ast_expression*)(X)), ast_value) && (X)->m_hasvalue && ((X)->m_cvq == CV_CONST) && \ - ((ast_expression*)(X))->m_vtype != TYPE_FUNCTION) + (ast_istype(((X)), ast_value) && (X)->m_hasvalue && ((X)->m_cvq == CV_CONST) && \ + ((X))->m_vtype != TYPE_FUNCTION) if (fid + 1 < sy->out.size()) ++paramcount; @@ -1253,7 +1286,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy) } fold_leave: - call = ast_call_new(sy->ops[sy->ops.size()].ctx, fun); + call = ast_call::make(sy->ops[sy->ops.size()].ctx, fun); if (!call) return false; @@ -1269,7 +1302,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy) for (i = 0; i < paramcount; ++i) call->m_params.push_back(sy->out[fid+1 + i].out); sy->out.erase(sy->out.end() - paramcount, sy->out.end()); - (void)!ast_call_check_types(call, parser->function->m_function_type->m_varparam); + (void)!call->checkTypes(parser->function->m_function_type->m_varparam); if (parser->max_param_count < paramcount) parser->max_param_count = paramcount; @@ -1278,12 +1311,12 @@ static bool parser_close_call(parser_t *parser, shunt *sy) if ((fun->m_flags & AST_FLAG_VARIADIC) && !(/*funval->m_cvq == CV_CONST && */ funval->m_hasvalue && funval->m_constval.vfunc->m_builtin)) { - call->m_va_count = (ast_expression*)parser->m_fold.constgen_float((qcfloat_t)paramcount, false); + call->m_va_count = parser->m_fold.constgen_float((qcfloat_t)paramcount, false); } } /* overwrite fid, the function, with a call */ - sy->out[fid] = syexp(call->m_context, (ast_expression*)call); + sy->out[fid] = syexp(call->m_context, call); if (fun->m_vtype != TYPE_FUNCTION) { parseerror(parser, "not a function (%s)", type_name[fun->m_vtype]); @@ -1303,7 +1336,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy) "-> it has been declared here: %s:%i", fun->m_context.file, fun->m_context.line); } - if (!fval->m_desc) { + if (!fval->m_desc.length()) { return !parsewarning(parser, WARN_DEPRECATED, "call to `%s` (which is marked deprecated)\n" "-> `%s` declared here: %s:%i", @@ -1432,8 +1465,8 @@ static ast_expression* parse_vararg_do(parser_t *parser) parseerror(parser, "expected comma after parameter index"); return nullptr; } - /* vararg piping: ...(start) */ - out = (ast_expression*)ast_argpipe_new(ctx, idx); + // vararg piping: ...(start) + out = new ast_argpipe(ctx, idx); return out; } @@ -1451,26 +1484,26 @@ static ast_expression* parse_vararg_do(parser_t *parser) if (parser->tok != ')') { ast_unref(idx); - ast_delete(typevar); + delete typevar; parseerror(parser, "expected closing paren"); return nullptr; } if (funtype->m_varparam && - !ast_compare_type((ast_expression*)typevar, (ast_expression*)funtype->m_varparam)) + !typevar->compareType(*funtype->m_varparam)) { char ty1[1024]; char ty2[1024]; - ast_type_to_string((ast_expression*)typevar, ty1, sizeof(ty1)); - ast_type_to_string((ast_expression*)funtype->m_varparam, ty2, sizeof(ty2)); + ast_type_to_string(typevar, ty1, sizeof(ty1)); + ast_type_to_string(funtype->m_varparam, ty2, sizeof(ty2)); compile_error(typevar->m_context, "function was declared to take varargs of type `%s`, requested type is: %s", ty2, ty1); } - out = (ast_expression*)ast_array_index_new(ctx, (ast_expression*)(parser->function->m_varargs), idx); - ast_type_adopt(out, typevar); - ast_delete(typevar); + out = ast_array_index::make(ctx, parser->function->m_varargs.get(), idx); + out->adoptType(*typevar); + delete typevar; return out; } @@ -1511,7 +1544,7 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) val = (ast_value*)parser->m_fold.constgen_string(parser_tokval(parser), true); if (!val) return false; - sy->out.push_back(syexp(parser_ctx(parser), (ast_expression*)val)); + sy->out.push_back(syexp(parser_ctx(parser), val)); if (!parser_next(parser) || parser->tok != ')') { parseerror(parser, "expected closing paren after translatable string"); @@ -1575,22 +1608,22 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) } if (prev && prev->m_vtype == TYPE_VECTOR && ctoken[0] >= 'x' && ctoken[0] <= 'z' && !ctoken[1]) { - var = (ast_expression*)parser->const_vec[ctoken[0]-'x']; + var = parser->const_vec[ctoken[0]-'x']; } else { var = parser_find_var(parser, parser_tokval(parser)); if (!var) var = parser_find_field(parser, parser_tokval(parser)); } if (!var && with_labels) { - var = (ast_expression*)parser_find_label(parser, parser_tokval(parser)); + var = parser_find_label(parser, parser_tokval(parser)); if (!with_labels) { - ast_label *lbl = ast_label_new(parser_ctx(parser), parser_tokval(parser), true); - var = (ast_expression*)lbl; + ast_label *lbl = new ast_label(parser_ctx(parser), parser_tokval(parser), true); + var = lbl; parser->labels.push_back(lbl); } } if (!var && !strcmp(parser_tokval(parser), "__FUNC__")) - var = (ast_expression*)parser->m_fold.constgen_string(parser->function->m_name, false); + var = parser->m_fold.constgen_string(parser->function->m_name, false); if (!var) { /* * now we try for the real intrinsic hashtable. If the string @@ -1894,7 +1927,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma { char *newstr = nullptr; util_asprintf(&newstr, "%s%s", last->m_constval.vstring, parser_tokval(parser)); - sy.out.back().out = (ast_expression*)parser->m_fold.constgen_string(newstr, false); + sy.out.back().out = parser->m_fold.constgen_string(newstr, false); mem_d(newstr); concatenated = true; } @@ -1999,7 +2032,7 @@ static bool parser_leaveblock(parser_t *parser) typedefs = vec_last(parser->_blocktypedefs); while (vec_size(parser->_typedefs) != typedefs) { - ast_delete(vec_last(parser->_typedefs)); + delete vec_last(parser->_typedefs); vec_pop(parser->_typedefs); } util_htdel(vec_last(parser->typedefs)); @@ -2015,12 +2048,18 @@ static void parser_addlocal(parser_t *parser, const char *name, ast_expression * vec_push(parser->_locals, e); util_htset(vec_last(parser->variables), name, (void*)e); } +static void parser_addlocal(parser_t *parser, const std::string &name, ast_expression *e) { + return parser_addlocal(parser, name.c_str(), e); +} static void parser_addglobal(parser_t *parser, const char *name, ast_expression *e) { parser->globals.push_back(e); util_htset(parser->htglobals, name, e); } +static void parser_addglobal(parser_t *parser, const std::string &name, ast_expression *e) { + return parser_addglobal(parser, name.c_str(), e); +} static ast_expression* process_condition(parser_t *parser, ast_expression *cond, bool *_ifnot) { @@ -2037,7 +2076,7 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond, if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->m_vtype == TYPE_STRING) { prev = cond; - cond = (ast_expression*)ast_unary_new(cond->m_context, INSTR_NOT_S, cond); + cond = ast_unary::make(cond->m_context, INSTR_NOT_S, cond); if (!cond) { ast_unref(prev); parseerror(parser, "internal error: failed to process condition"); @@ -2053,7 +2092,7 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond, { /* in perl-logic, AND and OR take care of the -fcorrect-logic */ prev = cond; - cond = (ast_expression*)ast_unary_new(cond->m_context, INSTR_NOT_V, cond); + cond = ast_unary::make(cond->m_context, INSTR_NOT_V, cond); if (!cond) { ast_unref(prev); parseerror(parser, "internal error: failed to process condition"); @@ -2069,7 +2108,7 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond, { cond = unary->m_operand; unary->m_operand = nullptr; - ast_delete(unary); + delete unary; ifnot = !ifnot; unary = (ast_unary*)cond; } @@ -2133,18 +2172,18 @@ static bool parse_if(parser_t *parser, ast_block *block, ast_expression **out) return false; } if (!ontrue) - ontrue = (ast_expression*)ast_block_new(parser_ctx(parser)); + ontrue = new ast_block(parser_ctx(parser)); /* check for an else */ if (!strcmp(parser_tokval(parser), "else")) { /* parse into the 'else' branch */ if (!parser_next(parser)) { parseerror(parser, "expected on-false branch after 'else'"); - ast_delete(ontrue); + delete ontrue; ast_unref(cond); return false; } if (!parse_statement_or_block(parser, &onfalse)) { - ast_delete(ontrue); + delete ontrue; ast_unref(cond); return false; } @@ -2152,16 +2191,16 @@ static bool parse_if(parser_t *parser, ast_block *block, ast_expression **out) cond = process_condition(parser, cond, &ifnot); if (!cond) { - if (ontrue) ast_delete(ontrue); - if (onfalse) ast_delete(onfalse); + if (ontrue) delete ontrue; + if (onfalse) delete onfalse; return false; } if (ifnot) - ifthen = ast_ifthen_new(ctx, cond, onfalse, ontrue); + ifthen = new ast_ifthen(ctx, cond, onfalse, ontrue); else - ifthen = ast_ifthen_new(ctx, cond, ontrue, onfalse); - *out = (ast_expression*)ifthen; + ifthen = new ast_ifthen(ctx, cond, ontrue, onfalse); + *out = ifthen; return true; } @@ -2209,7 +2248,7 @@ static bool parse_while(parser_t *parser, ast_block *block, ast_expression **out if (parser->breaks.back() != label || parser->continues.back() != label) { parseerror(parser, "internal error: label stack corrupted"); rv = false; - ast_delete(*out); + delete *out; *out = nullptr; } else { @@ -2261,8 +2300,8 @@ static bool parse_while_go(parser_t *parser, ast_block *block, ast_expression ** ast_unref(ontrue); return false; } - aloop = ast_loop_new(ctx, nullptr, cond, ifnot, nullptr, false, nullptr, ontrue); - *out = (ast_expression*)aloop; + aloop = new ast_loop(ctx, nullptr, cond, ifnot, nullptr, false, nullptr, ontrue); + *out = aloop; return true; } @@ -2305,12 +2344,7 @@ static bool parse_dowhile(parser_t *parser, ast_block *block, ast_expression **o if (parser->breaks.back() != label || parser->continues.back() != label) { parseerror(parser, "internal error: label stack corrupted"); rv = false; - /* - * Test for nullptr otherwise ast_delete dereferences null pointer - * and boom. - */ - if (*out) - ast_delete(*out); + delete *out; *out = nullptr; } else { @@ -2339,20 +2373,20 @@ static bool parse_dowhile_go(parser_t *parser, ast_block *block, ast_expression strcmp(parser_tokval(parser), "while")) { parseerror(parser, "expected 'while' and condition"); - ast_delete(ontrue); + delete ontrue; return false; } /* skip the 'while' and check for opening paren */ if (!parser_next(parser) || parser->tok != '(') { parseerror(parser, "expected 'while' condition in parenthesis"); - ast_delete(ontrue); + delete ontrue; return false; } /* parse into the expression */ if (!parser_next(parser)) { parseerror(parser, "expected 'while' condition after opening paren"); - ast_delete(ontrue); + delete ontrue; return false; } /* parse the condition */ @@ -2362,32 +2396,32 @@ static bool parse_dowhile_go(parser_t *parser, ast_block *block, ast_expression /* closing paren */ if (parser->tok != ')') { parseerror(parser, "expected closing paren after 'while' condition"); - ast_delete(ontrue); + delete ontrue; ast_unref(cond); return false; } /* parse on */ if (!parser_next(parser) || parser->tok != ';') { parseerror(parser, "expected semicolon after condition"); - ast_delete(ontrue); + delete ontrue; ast_unref(cond); return false; } if (!parser_next(parser)) { parseerror(parser, "parse error"); - ast_delete(ontrue); + delete ontrue; ast_unref(cond); return false; } cond = process_condition(parser, cond, &ifnot); if (!cond) { - ast_delete(ontrue); + delete ontrue; return false; } - aloop = ast_loop_new(ctx, nullptr, nullptr, false, cond, ifnot, nullptr, ontrue); - *out = (ast_expression*)aloop; + aloop = new ast_loop(ctx, nullptr, nullptr, false, cond, ifnot, nullptr, ontrue); + *out = aloop; return true; } @@ -2435,7 +2469,7 @@ static bool parse_for(parser_t *parser, ast_block *block, ast_expression **out) if (parser->breaks.back() != label || parser->continues.back() != label) { parseerror(parser, "internal error: label stack corrupted"); rv = false; - ast_delete(*out); + delete *out; *out = nullptr; } else { @@ -2542,11 +2576,11 @@ static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **ou if (!cond) goto onerr; } - aloop = ast_loop_new(ctx, initexpr, cond, ifnot, nullptr, false, increment, ontrue); - *out = (ast_expression*)aloop; + aloop = new ast_loop(ctx, initexpr, cond, ifnot, nullptr, false, increment, ontrue); + *out = aloop; if (!parser_leaveblock(parser)) { - ast_delete(aloop); + delete aloop; return false; } return true; @@ -2599,12 +2633,12 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou /* prepare the return value */ if (!retval) { - retval = ast_value_new(ctx, "#LOCAL_RETURN", TYPE_VOID); - ast_type_adopt(retval, expected->m_next); + retval = new ast_value(ctx, "#LOCAL_RETURN", TYPE_VOID); + retval->adoptType(*expected->m_next); parser->function->m_return_value = retval; } - if (!ast_compare_type(exp, (ast_expression*)retval)) { + if (!exp->compareType(*retval)) { char ty1[1024], ty2[1024]; ast_type_to_string(exp, ty1, sizeof(ty1)); ast_type_to_string(retval, ty2, sizeof(ty2)); @@ -2612,10 +2646,10 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou } /* store to 'return' local variable */ - var = (ast_expression*)ast_store_new( + var = new ast_store( ctx, type_store_instr[expected->m_next->m_vtype], - (ast_expression*)retval, exp); + retval, exp); if (!var) { ast_unref(exp); @@ -2637,12 +2671,12 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou return false; if (exp->m_vtype != TYPE_NIL && - exp->m_vtype != ((ast_expression*)expected)->m_next->m_vtype) + exp->m_vtype != (expected)->m_next->m_vtype) { parseerror(parser, "return with invalid expression"); } - ret = ast_return_new(ctx, exp); + ret = new ast_return(ctx, exp); if (!ret) { ast_unref(exp); return false; @@ -2655,9 +2689,9 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou { (void)!parsewarning(parser, WARN_MISSING_RETURN_VALUES, "return without value"); } - ret = ast_return_new(ctx, (ast_expression*)retval); + ret = new ast_return(ctx, retval); } - *out = (ast_expression*)ret; + *out = ret; return true; } @@ -2710,7 +2744,7 @@ static bool parse_break_continue(parser_t *parser, ast_block *block, ast_express if (!parser_next(parser)) parseerror(parser, "parse error"); - *out = (ast_expression*)ast_breakcont_new(ctx, is_continue, levels); + *out = new ast_breakcont(ctx, is_continue, levels); return true; } @@ -2991,7 +3025,7 @@ static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **ou if (parser->breaks.back() != label) { parseerror(parser, "internal error: label stack corrupted"); rv = false; - ast_delete(*out); + delete *out; *out = nullptr; } else { @@ -3027,24 +3061,24 @@ static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression * if (!operand) return false; - switchnode = ast_switch_new(ctx, operand); + switchnode = new ast_switch(ctx, operand); /* closing paren */ if (parser->tok != ')') { - ast_delete(switchnode); + delete switchnode; parseerror(parser, "expected closing paren after 'switch' operand"); return false; } /* parse over the opening paren */ if (!parser_next(parser) || parser->tok != '{') { - ast_delete(switchnode); + delete switchnode; parseerror(parser, "expected list of cases"); return false; } if (!parser_next(parser)) { - ast_delete(switchnode); + delete switchnode; parseerror(parser, "expected 'case' or 'default'"); return false; } @@ -3057,7 +3091,7 @@ static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression * typevar = parser_find_typedef(parser, parser_tokval(parser), 0); if (typevar || parser->tok == TOKEN_TYPENAME) { if (!parse_variable(parser, block, true, CV_NONE, typevar, false, false, 0, nullptr)) { - ast_delete(switchnode); + delete switchnode; return false; } continue; @@ -3065,11 +3099,11 @@ static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression * if (parse_qualifiers(parser, true, &cvq, &noref, &is_static, &qflags, nullptr)) { if (cvq == CV_WRONG) { - ast_delete(switchnode); + delete switchnode; return false; } if (!parse_variable(parser, block, true, cvq, nullptr, noref, is_static, qflags, nullptr)) { - ast_delete(switchnode); + delete switchnode; return false; } continue; @@ -3083,13 +3117,13 @@ static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression * if (!strcmp(parser_tokval(parser), "case")) { if (!parser_next(parser)) { - ast_delete(switchnode); + delete switchnode; parseerror(parser, "expected expression for case"); return false; } swcase.m_value = parse_expression_leave(parser, false, false, false); if (!swcase.m_value) { - ast_delete(switchnode); + delete switchnode; parseerror(parser, "expected expression for case"); return false; } @@ -3104,13 +3138,13 @@ static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression * else if (!strcmp(parser_tokval(parser), "default")) { swcase.m_value = nullptr; if (!parser_next(parser)) { - ast_delete(switchnode); + delete switchnode; parseerror(parser, "expected colon"); return false; } } else { - ast_delete(switchnode); + delete switchnode; parseerror(parser, "expected 'case' or 'default'"); return false; } @@ -3118,24 +3152,24 @@ static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression * /* Now the colon and body */ if (parser->tok != ':') { if (swcase.m_value) ast_unref(swcase.m_value); - ast_delete(switchnode); + delete switchnode; parseerror(parser, "expected colon"); return false; } if (!parser_next(parser)) { if (swcase.m_value) ast_unref(swcase.m_value); - ast_delete(switchnode); + delete switchnode; parseerror(parser, "expected statements or case"); return false; } - caseblock = ast_block_new(parser_ctx(parser)); + caseblock = new ast_block(parser_ctx(parser)); if (!caseblock) { if (swcase.m_value) ast_unref(swcase.m_value); - ast_delete(switchnode); + delete switchnode; return false; } - swcase.m_code = (ast_expression*)caseblock; + swcase.m_code = caseblock; switchnode->m_cases.push_back(swcase); while (true) { ast_expression *expr; @@ -3149,13 +3183,13 @@ static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression * } } if (!parse_statement(parser, caseblock, &expr, true)) { - ast_delete(switchnode); + delete switchnode; return false; } if (!expr) continue; - if (!ast_block_add_expr(caseblock, expr)) { - ast_delete(switchnode); + if (!caseblock->addExpr(expr)) { + delete switchnode; return false; } } @@ -3165,16 +3199,16 @@ static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression * /* closing paren */ if (parser->tok != '}') { - ast_delete(switchnode); + delete switchnode; parseerror(parser, "expected closing paren of case list"); return false; } if (!parser_next(parser)) { - ast_delete(switchnode); + delete switchnode; parseerror(parser, "parse error after switch"); return false; } - *out = (ast_expression*)switchnode; + *out = switchnode; return true; } @@ -3201,14 +3235,14 @@ static ast_expression *parse_goto_computed(parser_t *parser, ast_expression **si cond = tern->m_cond; tern->m_cond = nullptr; - ast_delete(tern); + delete tern; *side = nullptr; - return (ast_expression*)ast_ifthen_new(parser_ctx(parser), cond, on_true, on_false); + return new ast_ifthen(parser_ctx(parser), cond, on_true, on_false); } else if (ast_istype(*side, ast_label)) { - ast_goto *gt = ast_goto_new(parser_ctx(parser), ((ast_label*)*side)->m_name); - ast_goto_set_label(gt, ((ast_label*)*side)); + ast_goto *gt = new ast_goto(parser_ctx(parser), ((ast_label*)*side)->m_name); + gt->setLabel(reinterpret_cast(*side)); *side = nullptr; - return (ast_expression*)gt; + return gt; } return nullptr; } @@ -3243,15 +3277,15 @@ static bool parse_goto(parser_t *parser, ast_expression **out) } /* not computed goto */ - gt = ast_goto_new(parser_ctx(parser), parser_tokval(parser)); + gt = new ast_goto(parser_ctx(parser), parser_tokval(parser)); lbl = parser_find_label(parser, gt->m_name); if (lbl) { if (!ast_istype(lbl, ast_label)) { parseerror(parser, "internal error: label is not an ast_label"); - ast_delete(gt); + delete gt; return false; } - ast_goto_set_label(gt, (ast_label*)lbl); + gt->setLabel(reinterpret_cast(lbl)); } else parser->gotos.push_back(gt); @@ -3265,7 +3299,7 @@ static bool parse_goto(parser_t *parser, ast_expression **out) return false; } - *out = (ast_expression*)gt; + *out = gt; return true; } @@ -3392,8 +3426,8 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression * if (parser->tok == TOKEN_IDENT && (tdef = parser_find_typedef(parser, parser_tokval(parser), 0))) { - ast_type_to_string((ast_expression*)tdef, ty, sizeof(ty)); - con_out("__builtin_debug_printtype: `%s`=`%s`\n", tdef->m_name, ty); + ast_type_to_string(tdef, ty, sizeof(ty)); + con_out("__builtin_debug_printtype: `%s`=`%s`\n", tdef->m_name.c_str(), ty); if (!parser_next(parser)) { parseerror(parser, "parse error after __builtin_debug_printtype typename argument"); return false; @@ -3479,7 +3513,7 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression * inner = parse_block(parser); if (!inner) return false; - *out = (ast_expression*)inner; + *out = inner; return true; } else if (parser->tok == ':') @@ -3503,17 +3537,17 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression * label->m_undefined = false; } else { - label = ast_label_new(parser_ctx(parser), parser_tokval(parser), false); + label = new ast_label(parser_ctx(parser), parser_tokval(parser), false); parser->labels.push_back(label); } - *out = (ast_expression*)label; + *out = label; if (!parser_next(parser)) { parseerror(parser, "parse error after label"); return false; } for (i = 0; i < parser->gotos.size(); ++i) { - if (!strcmp(parser->gotos[i]->m_name, label->m_name)) { - ast_goto_set_label(parser->gotos[i], label); + if (parser->gotos[i]->m_name == label->m_name) { + parser->gotos[i]->setLabel(label); parser->gotos.erase(parser->gotos.begin() + i); --i; } @@ -3604,14 +3638,14 @@ static bool parse_enum(parser_t *parser) goto onerror; } - var = ast_value_new(parser_ctx(parser), parser_tokval(parser), TYPE_FLOAT); + var = new ast_value(parser_ctx(parser), parser_tokval(parser), TYPE_FLOAT); vec_push(values, var); var->m_cvq = CV_CONST; var->m_hasvalue = true; /* for flagged enumerations increment in POTs of TWO */ var->m_constval.vfloat = (flag) ? (num *= 2) : (num ++); - parser_addglobal(parser, var->m_name, (ast_expression*)var); + parser_addglobal(parser, var->m_name, var); if (!parser_next(parser)) { parseerror(parser, "expected `=`, `}` or comma after identifier"); @@ -3703,8 +3737,8 @@ static bool parse_block_into(parser_t *parser, ast_block *block) } if (!expr) continue; - if (!ast_block_add_expr(block, expr)) { - ast_delete(block); + if (!block->addExpr(expr)) { + delete block; block = nullptr; goto cleanup; } @@ -3725,11 +3759,11 @@ cleanup: static ast_block* parse_block(parser_t *parser) { ast_block *block; - block = ast_block_new(parser_ctx(parser)); + block = new ast_block(parser_ctx(parser)); if (!block) return nullptr; if (!parse_block_into(parser, block)) { - ast_block_delete(block); + delete block; return nullptr; } return block; @@ -3738,7 +3772,7 @@ static ast_block* parse_block(parser_t *parser) static bool parse_statement_or_block(parser_t *parser, ast_expression **out) { if (parser->tok == '{') { - *out = (ast_expression*)parse_block(parser); + *out = parse_block(parser); return !!*out; } return parse_statement(parser, nullptr, out, false); @@ -3747,15 +3781,15 @@ static bool parse_statement_or_block(parser_t *parser, ast_expression **out) static bool create_vector_members(ast_value *var, ast_member **me) { size_t i; - size_t len = strlen(var->m_name); + size_t len = var->m_name.length(); for (i = 0; i < 3; ++i) { char *name = (char*)mem_a(len+3); - memcpy(name, var->m_name, len); + memcpy(name, var->m_name.c_str(), len); name[len+0] = '_'; name[len+1] = 'x'+i; name[len+2] = 0; - me[i] = ast_member_new(var->m_context, (ast_expression*)var, i, name); + me[i] = ast_member::make(var->m_context, var, i, name); mem_d(name); if (!me[i]) break; @@ -3764,7 +3798,7 @@ static bool create_vector_members(ast_value *var, ast_member **me) return true; /* unroll */ - do { ast_member_delete(me[--i]); } while(i); + do { delete me[--i]; } while(i); return false; } @@ -3862,23 +3896,23 @@ static bool parse_function_body(parser_t *parser, ast_value *var) ast_value *thinkfunc; ast_expression *functype = fld_think->m_next; - thinkfunc = ast_value_new(parser_ctx(parser), parser_tokval(parser), functype->m_vtype); - if (!thinkfunc) { /* || !ast_type_adopt(thinkfunc, functype)*/ + thinkfunc = new ast_value(parser_ctx(parser), parser_tokval(parser), functype->m_vtype); + if (!thinkfunc) { /* || !thinkfunc->adoptType(*functype)*/ ast_unref(framenum); parseerror(parser, "failed to create implicit prototype for `%s`", parser_tokval(parser)); return false; } - ast_type_adopt(thinkfunc, functype); + thinkfunc->adoptType(*functype); if (!parser_next(parser)) { ast_unref(framenum); - ast_delete(thinkfunc); + delete thinkfunc; return false; } - parser_addglobal(parser, thinkfunc->m_name, (ast_expression*)thinkfunc); + parser_addglobal(parser, thinkfunc->m_name, thinkfunc); - nextthink = (ast_expression*)thinkfunc; + nextthink = thinkfunc; } else { nextthink = parse_expression_leave(parser, true, false, false); @@ -3917,7 +3951,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) has_frame_think = true; } - block = ast_block_new(parser_ctx(parser)); + block = new ast_block(parser_ctx(parser)); if (!block) { parseerror(parser, "failed to allocate block"); if (has_frame_think) { @@ -3929,12 +3963,12 @@ static bool parse_function_body(parser_t *parser, ast_value *var) if (has_frame_think) { if (!OPTS_FLAG(EMULATE_STATE)) { - ast_state *state_op = ast_state_new(parser_ctx(parser), framenum, nextthink); - if (!ast_block_add_expr(block, (ast_expression*)state_op)) { + ast_state *state_op = new ast_state(parser_ctx(parser), framenum, nextthink); + if (!block->addExpr(state_op)) { parseerror(parser, "failed to generate state op for [frame,think]"); ast_unref(nextthink); ast_unref(framenum); - ast_delete(block); + delete block; return false; } } else { @@ -3951,48 +3985,48 @@ static bool parse_function_body(parser_t *parser, ast_value *var) float frame_delta = 1.0f / (float)OPTS_OPTION_U32(OPTION_STATE_FPS); ctx = parser_ctx(parser); - self_frame = (ast_expression*)ast_entfield_new(ctx, gbl_self, fld_frame); - self_nextthink = (ast_expression*)ast_entfield_new(ctx, gbl_self, fld_nextthink); - self_think = (ast_expression*)ast_entfield_new(ctx, gbl_self, fld_think); + self_frame = new ast_entfield(ctx, gbl_self, fld_frame); + self_nextthink = new ast_entfield(ctx, gbl_self, fld_nextthink); + self_think = new ast_entfield(ctx, gbl_self, fld_think); - time_plus_1 = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F, - gbl_time, (ast_expression*)parser->m_fold.constgen_float(frame_delta, false)); + time_plus_1 = new ast_binary(ctx, INSTR_ADD_F, + gbl_time, parser->m_fold.constgen_float(frame_delta, false)); if (!self_frame || !self_nextthink || !self_think || !time_plus_1) { - if (self_frame) ast_delete(self_frame); - if (self_nextthink) ast_delete(self_nextthink); - if (self_think) ast_delete(self_think); - if (time_plus_1) ast_delete(time_plus_1); + if (self_frame) delete self_frame; + if (self_nextthink) delete self_nextthink; + if (self_think) delete self_think; + if (time_plus_1) delete time_plus_1; retval = false; } if (retval) { - store_frame = ast_store_new(ctx, INSTR_STOREP_F, self_frame, framenum); - store_nextthink = ast_store_new(ctx, INSTR_STOREP_F, self_nextthink, time_plus_1); - store_think = ast_store_new(ctx, INSTR_STOREP_FNC, self_think, nextthink); + store_frame = new ast_store(ctx, INSTR_STOREP_F, self_frame, framenum); + store_nextthink = new ast_store(ctx, INSTR_STOREP_F, self_nextthink, time_plus_1); + store_think = new ast_store(ctx, INSTR_STOREP_FNC, self_think, nextthink); if (!store_frame) { - ast_delete(self_frame); + delete self_frame; retval = false; } if (!store_nextthink) { - ast_delete(self_nextthink); + delete self_nextthink; retval = false; } if (!store_think) { - ast_delete(self_think); + delete self_think; retval = false; } if (!retval) { - if (store_frame) ast_delete(store_frame); - if (store_nextthink) ast_delete(store_nextthink); - if (store_think) ast_delete(store_think); + if (store_frame) delete store_frame; + if (store_nextthink) delete store_nextthink; + if (store_think) delete store_think; retval = false; } - if (!ast_block_add_expr(block, (ast_expression*)store_frame) || - !ast_block_add_expr(block, (ast_expression*)store_nextthink) || - !ast_block_add_expr(block, (ast_expression*)store_think)) + if (!block->addExpr(store_frame) || + !block->addExpr(store_nextthink) || + !block->addExpr(store_think)) { retval = false; } @@ -4002,7 +4036,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) parseerror(parser, "failed to generate code for [frame,think]"); ast_unref(nextthink); ast_unref(framenum); - ast_delete(block); + delete block; return false; } } @@ -4011,22 +4045,22 @@ static bool parse_function_body(parser_t *parser, ast_value *var) if (var->m_hasvalue) { if (!(var->m_flags & AST_FLAG_ACCUMULATE)) { parseerror(parser, "function `%s` declared with multiple bodies", var->m_name); - ast_block_delete(block); + delete block; goto enderr; } func = var->m_constval.vfunc; if (!func) { parseerror(parser, "internal error: nullptr function: `%s`", var->m_name); - ast_block_delete(block); + delete block; goto enderr; } } else { - func = ast_function_new(var->m_context, var->m_name, var); + func = ast_function::make(var->m_context, var->m_name, var); if (!func) { parseerror(parser, "failed to allocate function for `%s`", var->m_name); - ast_block_delete(block); + delete block; goto enderr; } parser->functions.push_back(func); @@ -4045,48 +4079,48 @@ static bool parse_function_body(parser_t *parser, ast_value *var) continue; } - if (!create_vector_members(it, me)) { - ast_block_delete(block); + if (!create_vector_members(it.get(), me)) { + delete block; goto enderrfn; } for (e = 0; e < 3; ++e) { - parser_addlocal(parser, me[e]->m_name, (ast_expression*)me[e]); - ast_block_collect(block, (ast_expression*)me[e]); + parser_addlocal(parser, me[e]->m_name, me[e]); + block->collect(me[e]); } } if (var->m_argcounter && !func->m_argc) { - ast_value *argc = ast_value_new(var->m_context, var->m_argcounter, TYPE_FLOAT); - parser_addlocal(parser, argc->m_name, (ast_expression*)argc); - func->m_argc = argc; + ast_value *argc = new ast_value(var->m_context, var->m_argcounter, TYPE_FLOAT); + parser_addlocal(parser, argc->m_name, argc); + func->m_argc.reset(argc); } if (OPTS_FLAG(VARIADIC_ARGS) && var->m_flags & AST_FLAG_VARIADIC && !func->m_varargs) { char name[1024]; - ast_value *varargs = ast_value_new(var->m_context, "reserved:va_args", TYPE_ARRAY); + ast_value *varargs = new ast_value(var->m_context, "reserved:va_args", TYPE_ARRAY); varargs->m_flags |= AST_FLAG_IS_VARARG; - varargs->m_next = (ast_expression*)ast_value_new(var->m_context, nullptr, TYPE_VECTOR); + varargs->m_next = new ast_value(var->m_context, "", TYPE_VECTOR); varargs->m_count = 0; - util_snprintf(name, sizeof(name), "%s##va##SET", var->m_name); + util_snprintf(name, sizeof(name), "%s##va##SET", var->m_name.c_str()); if (!parser_create_array_setter_proto(parser, varargs, name)) { - ast_delete(varargs); - ast_block_delete(block); + delete varargs; + delete block; goto enderrfn; } - util_snprintf(name, sizeof(name), "%s##va##GET", var->m_name); + util_snprintf(name, sizeof(name), "%s##va##GET", var->m_name.c_str()); if (!parser_create_array_getter_proto(parser, varargs, varargs->m_next, name)) { - ast_delete(varargs); - ast_block_delete(block); + delete varargs; + delete block; goto enderrfn; } - func->m_varargs = varargs; + func->m_varargs.reset(varargs); func->m_fixedparams = (ast_value*)parser->m_fold.constgen_float(var->m_type_params.size(), false); } parser->function = func; if (!parse_block_into(parser, block)) { - ast_block_delete(block); + delete block; goto enderrfn; } @@ -4109,7 +4143,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) enderrfn: (void)!parser_leaveblock(parser); parser->functions.pop_back(); - ast_function_delete(func); + delete func; var->m_constval.vfunc = nullptr; enderr: @@ -4132,29 +4166,29 @@ static ast_expression *array_accessor_split( lex_ctx_t ctx = array->m_context; if (!left || !right) { - if (left) ast_delete(left); - if (right) ast_delete(right); + if (left) delete left; + if (right) delete right; return nullptr; } - cmp = ast_binary_new(ctx, INSTR_LT, - (ast_expression*)index, - (ast_expression*)parser->m_fold.constgen_float(middle, false)); + cmp = new ast_binary(ctx, INSTR_LT, + index, + parser->m_fold.constgen_float(middle, false)); if (!cmp) { - ast_delete(left); - ast_delete(right); + delete left; + delete right; parseerror(parser, "internal error: failed to create comparison for array setter"); return nullptr; } - ifthen = ast_ifthen_new(ctx, (ast_expression*)cmp, left, right); + ifthen = new ast_ifthen(ctx, cmp, left, right); if (!ifthen) { - ast_delete(cmp); /* will delete left and right */ + delete cmp; /* will delete left and right */ parseerror(parser, "internal error: failed to create conditional jump for array setter"); return nullptr; } - return (ast_expression*)ifthen; + return ifthen; } static ast_expression *array_setter_node(parser_t *parser, ast_value *array, ast_value *index, ast_value *value, size_t from, size_t afterend) @@ -4172,39 +4206,39 @@ static ast_expression *array_setter_node(parser_t *parser, ast_value *array, ast if (value->m_vtype == TYPE_FIELD && value->m_next->m_vtype == TYPE_VECTOR) assignop = INSTR_STORE_V; - subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser->m_fold.constgen_float(from, false)); + subscript = ast_array_index::make(ctx, array, parser->m_fold.constgen_float(from, false)); if (!subscript) return nullptr; - st = ast_store_new(ctx, assignop, (ast_expression*)subscript, (ast_expression*)value); + st = new ast_store(ctx, assignop, subscript, value); if (!st) { - ast_delete(subscript); + delete subscript; return nullptr; } - block = ast_block_new(ctx); + block = new ast_block(ctx); if (!block) { - ast_delete(st); + delete st; return nullptr; } - if (!ast_block_add_expr(block, (ast_expression*)st)) { - ast_delete(block); + if (!block->addExpr(st)) { + delete block; return nullptr; } - ret = ast_return_new(ctx, nullptr); + ret = new ast_return(ctx, nullptr); if (!ret) { - ast_delete(block); + delete block; return nullptr; } - if (!ast_block_add_expr(block, (ast_expression*)ret)) { - ast_delete(block); + if (!block->addExpr(ret)) { + delete block; return nullptr; } - return (ast_expression*)block; + return block; } else { ast_expression *left, *right; size_t diff = afterend - from; @@ -4238,51 +4272,48 @@ static ast_expression *array_field_setter_node( if (value->m_vtype == TYPE_FIELD && value->m_next->m_vtype == TYPE_VECTOR) assignop = INSTR_STOREP_V; - subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser->m_fold.constgen_float(from, false)); + subscript = ast_array_index::make(ctx, array, parser->m_fold.constgen_float(from, false)); if (!subscript) return nullptr; - subscript->m_next = ast_type_copy(subscript->m_context, (ast_expression*)subscript); + subscript->m_next = new ast_expression(ast_copy_type, subscript->m_context, *subscript); subscript->m_vtype = TYPE_FIELD; - entfield = ast_entfield_new_force(ctx, - (ast_expression*)entity, - (ast_expression*)subscript, - (ast_expression*)subscript); + entfield = new ast_entfield(ctx, entity, subscript, subscript); if (!entfield) { - ast_delete(subscript); + delete subscript; return nullptr; } - st = ast_store_new(ctx, assignop, (ast_expression*)entfield, (ast_expression*)value); + st = new ast_store(ctx, assignop, entfield, value); if (!st) { - ast_delete(entfield); + delete entfield; return nullptr; } - block = ast_block_new(ctx); + block = new ast_block(ctx); if (!block) { - ast_delete(st); + delete st; return nullptr; } - if (!ast_block_add_expr(block, (ast_expression*)st)) { - ast_delete(block); + if (!block->addExpr(st)) { + delete block; return nullptr; } - ret = ast_return_new(ctx, nullptr); + ret = new ast_return(ctx, nullptr); if (!ret) { - ast_delete(block); + delete block; return nullptr; } - if (!ast_block_add_expr(block, (ast_expression*)ret)) { - ast_delete(block); + if (!block->addExpr(ret)) { + delete block; return nullptr; } - return (ast_expression*)block; + return block; } else { ast_expression *left, *right; size_t diff = afterend - from; @@ -4301,17 +4332,17 @@ static ast_expression *array_getter_node(parser_t *parser, ast_value *array, ast ast_return *ret; ast_array_index *subscript; - subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser->m_fold.constgen_float(from, false)); + subscript = ast_array_index::make(ctx, array, parser->m_fold.constgen_float(from, false)); if (!subscript) return nullptr; - ret = ast_return_new(ctx, (ast_expression*)subscript); + ret = new ast_return(ctx, subscript); if (!ret) { - ast_delete(subscript); + delete subscript; return nullptr; } - return (ast_expression*)ret; + return ret; } else { ast_expression *left, *right; size_t diff = afterend - from; @@ -4328,25 +4359,25 @@ static bool parser_create_array_accessor(parser_t *parser, ast_value *array, con ast_value *fval = nullptr; ast_block *body = nullptr; - fval = ast_value_new(array->m_context, funcname, TYPE_FUNCTION); + fval = new ast_value(array->m_context, funcname, TYPE_FUNCTION); if (!fval) { parseerror(parser, "failed to create accessor function value"); return false; } fval->m_flags &= ~(AST_FLAG_COVERAGE_MASK); - func = ast_function_new(array->m_context, funcname, fval); + func = ast_function::make(array->m_context, funcname, fval); if (!func) { - ast_delete(fval); + delete fval; parseerror(parser, "failed to create accessor function node"); return false; } - body = ast_block_new(array->m_context); + body = new ast_block(array->m_context); if (!body) { parseerror(parser, "failed to create block for array accessor"); - ast_delete(fval); - ast_delete(func); + delete fval; + delete func; return false; } @@ -4373,26 +4404,26 @@ static ast_value* parser_create_array_setter_proto(parser_t *parser, ast_value * if (!parser_create_array_accessor(parser, array, funcname, &fval)) return nullptr; func = fval->m_constval.vfunc; - fval->m_next = (ast_expression*)ast_value_new(array->m_context, "", TYPE_VOID); + fval->m_next = new ast_value(array->m_context, "", TYPE_VOID); - index = ast_value_new(array->m_context, "index", TYPE_FLOAT); - value = ast_value_from_type((ast_value*)array->m_next); + index = new ast_value(array->m_context, "index", TYPE_FLOAT); + value = new ast_value(ast_copy_type, *(ast_value*)array->m_next); if (!index || !value) { parseerror(parser, "failed to create locals for array accessor"); goto cleanup; } - (void)!ast_value_set_name(value, "value"); /* not important */ - fval->m_type_params.push_back(index); - fval->m_type_params.push_back(value); + value->m_name = "value"; // not important + fval->m_type_params.emplace_back(index); + fval->m_type_params.emplace_back(value); array->m_setter = fval; return fval; cleanup: - if (index) ast_delete(index); - if (value) ast_delete(value); - ast_delete(func); - ast_delete(fval); + if (index) delete index; + if (value) delete value; + delete func; + delete fval; return nullptr; } @@ -4400,15 +4431,15 @@ static bool parser_create_array_setter_impl(parser_t *parser, ast_value *array) { ast_expression *root = nullptr; root = array_setter_node(parser, array, - array->m_setter->m_type_params[0], - array->m_setter->m_type_params[1], + array->m_setter->m_type_params[0].get(), + array->m_setter->m_type_params[1].get(), 0, array->m_count); if (!root) { parseerror(parser, "failed to build accessor search tree"); return false; } - if (!ast_block_add_expr(array->m_setter->m_constval.vfunc->m_blocks[0].get(), root)) { - ast_delete(root); + if (!array->m_setter->m_constval.vfunc->m_blocks[0].get()->addExpr(root)) { + delete root; return false; } return true; @@ -4438,19 +4469,19 @@ static bool parser_create_array_field_setter(parser_t *parser, ast_value *array, if (!parser_create_array_accessor(parser, array, funcname, &fval)) return false; func = fval->m_constval.vfunc; - fval->m_next = (ast_expression*)ast_value_new(array->m_context, "", TYPE_VOID); + fval->m_next = new ast_value(array->m_context, "", TYPE_VOID); - entity = ast_value_new(array->m_context, "entity", TYPE_ENTITY); - index = ast_value_new(array->m_context, "index", TYPE_FLOAT); - value = ast_value_from_type((ast_value*)array->m_next); + entity = new ast_value(array->m_context, "entity", TYPE_ENTITY); + index = new ast_value(array->m_context, "index", TYPE_FLOAT); + value = new ast_value(ast_copy_type, *(ast_value*)array->m_next); if (!entity || !index || !value) { parseerror(parser, "failed to create locals for array accessor"); goto cleanup; } - (void)!ast_value_set_name(value, "value"); /* not important */ - fval->m_type_params.push_back(entity); - fval->m_type_params.push_back(index); - fval->m_type_params.push_back(value); + value->m_name = "value"; // not important + fval->m_type_params.emplace_back(entity); + fval->m_type_params.emplace_back(index); + fval->m_type_params.emplace_back(value); root = array_field_setter_node(parser, array, entity, index, value, 0, array->m_count); if (!root) { @@ -4459,14 +4490,14 @@ static bool parser_create_array_field_setter(parser_t *parser, ast_value *array, } array->m_setter = fval; - return ast_block_add_expr(func->m_blocks[0].get(), root); + return func->m_blocks[0].get()->addExpr(root); cleanup: - if (entity) ast_delete(entity); - if (index) ast_delete(index); - if (value) ast_delete(value); - if (root) ast_delete(root); - ast_delete(func); - ast_delete(fval); + if (entity) delete entity; + if (index) delete index; + if (value) delete value; + if (root) delete root; + delete func; + delete fval; return false; } @@ -4487,22 +4518,22 @@ static ast_value* parser_create_array_getter_proto(parser_t *parser, ast_value * if (!parser_create_array_accessor(parser, array, funcname, &fval)) return nullptr; func = fval->m_constval.vfunc; - fval->m_next = ast_type_copy(array->m_context, elemtype); + fval->m_next = new ast_expression(ast_copy_type, array->m_context, *elemtype); - index = ast_value_new(array->m_context, "index", TYPE_FLOAT); + index = new ast_value(array->m_context, "index", TYPE_FLOAT); if (!index) { parseerror(parser, "failed to create locals for array accessor"); goto cleanup; } - fval->m_type_params.push_back(index); + fval->m_type_params.emplace_back(index); array->m_getter = fval; return fval; cleanup: - if (index) ast_delete(index); - ast_delete(func); - ast_delete(fval); + if (index) delete index; + delete func; + delete fval; return nullptr; } @@ -4510,13 +4541,13 @@ static bool parser_create_array_getter_impl(parser_t *parser, ast_value *array) { ast_expression *root = nullptr; - root = array_getter_node(parser, array, array->m_getter->m_type_params[0], 0, array->m_count); + root = array_getter_node(parser, array, array->m_getter->m_type_params[0].get(), 0, array->m_count); if (!root) { parseerror(parser, "failed to build accessor search tree"); return false; } - if (!ast_block_add_expr(array->m_getter->m_constval.vfunc->m_blocks[0].get(), root)) { - ast_delete(root); + if (!array->m_getter->m_constval.vfunc->m_blocks[0].get()->addExpr(root)) { + delete root; return false; } return true; @@ -4532,7 +4563,7 @@ static bool parser_create_array_getter(parser_t *parser, ast_value *array, const static ast_value *parse_parameter_list(parser_t *parser, ast_value *var) { lex_ctx_t ctx = parser_ctx(parser); - std::vector params; + std::vector> params; ast_value *fval; bool first = true; bool variadic = false; @@ -4541,7 +4572,7 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var) /* for the sake of less code we parse-in in this function */ if (!parser_next(parser)) { - ast_delete(var); + delete var; parseerror(parser, "expected parameter list"); return nullptr; } @@ -4581,17 +4612,17 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var) } } } else { - params.push_back(param); + params.emplace_back(param); if (param->m_vtype >= TYPE_VARIANT) { char tname[1024]; /* typename is reserved in C++ */ - ast_type_to_string((ast_expression*)param, tname, sizeof(tname)); + ast_type_to_string(param, tname, sizeof(tname)); parseerror(parser, "type not supported as part of a parameter list: %s", tname); goto on_error; } /* type-restricted varargs */ if (parser->tok == TOKEN_DOTS) { variadic = true; - varparam = params.back(); + varparam = params.back().release(); params.pop_back(); if (!parser_next(parser) || (parser->tok != ')' && parser->tok != TOKEN_IDENT)) { parseerror(parser, "`...` must be the last parameter of a variadic function declaration"); @@ -4599,7 +4630,7 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var) } if (parser->tok == TOKEN_IDENT) { argcounter = util_strdup(parser_tokval(parser)); - ast_value_set_name(param, argcounter); + param->m_name = argcounter; if (!parser_next(parser) || parser->tok != ')') { parseerror(parser, "`...` must be the last parameter of a variadic function declaration"); goto on_error; @@ -4627,14 +4658,14 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var) } /* now turn 'var' into a function type */ - fval = ast_value_new(ctx, "", TYPE_FUNCTION); - fval->m_next = (ast_expression*)var; + fval = new ast_value(ctx, "", TYPE_FUNCTION); + fval->m_next = var; if (variadic) fval->m_flags |= AST_FLAG_VARIADIC; var = fval; var->m_type_params = move(params); - var->m_varparam = (ast_expression*)varparam; + var->m_varparam = varparam; var->m_argcounter = argcounter; return var; @@ -4643,10 +4674,8 @@ on_error: if (argcounter) mem_d(argcounter); if (varparam) - ast_delete(varparam); - ast_delete(var); - for (auto &it : params) - ast_delete(it); + delete varparam; + delete var; return nullptr; } @@ -4659,7 +4688,7 @@ static ast_value *parse_arraysize(parser_t *parser, ast_value *var) ctx = parser_ctx(parser); if (!parser_next(parser)) { - ast_delete(var); + delete var; parseerror(parser, "expected array-size"); return nullptr; } @@ -4670,7 +4699,7 @@ static ast_value *parse_arraysize(parser_t *parser, ast_value *var) if (!cexp || !ast_istype(cexp, ast_value)) { if (cexp) ast_unref(cexp); - ast_delete(var); + delete var; parseerror(parser, "expected array-size as constant positive integer"); return nullptr; } @@ -4681,8 +4710,8 @@ static ast_value *parse_arraysize(parser_t *parser, ast_value *var) cval = nullptr; } - tmp = ast_value_new(ctx, "", TYPE_ARRAY); - tmp->m_next = (ast_expression*)var; + tmp = new ast_value(ctx, "", TYPE_ARRAY); + tmp->m_next = var; var = tmp; if (cval) { @@ -4692,7 +4721,7 @@ static ast_value *parse_arraysize(parser_t *parser, ast_value *var) tmp->m_count = cval->m_constval.vfloat; else { ast_unref(cexp); - ast_delete(var); + delete var; parseerror(parser, "array-size must be a positive integer constant"); return nullptr; } @@ -4704,12 +4733,12 @@ static ast_value *parse_arraysize(parser_t *parser, ast_value *var) } if (parser->tok != ']') { - ast_delete(var); + delete var; parseerror(parser, "expected ']' after array-size"); return nullptr; } if (!parser_next(parser)) { - ast_delete(var); + delete var; parseerror(parser, "error after parsing array size"); return nullptr; } @@ -4790,14 +4819,14 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va /* generate the basic type value */ if (cached_typedef) { - var = ast_value_from_type(cached_typedef); - ast_value_set_name(var, ""); + var = new ast_value(ast_copy_type, *cached_typedef); + var->m_name = ""; } else - var = ast_value_new(ctx, "", parser_token(parser)->constval.t); + var = new ast_value(ctx, "", parser_token(parser)->constval.t); for (; morefields; --morefields) { - tmp = ast_value_new(ctx, "<.type>", TYPE_FIELD); - tmp->m_next = (ast_expression*)var; + tmp = new ast_value(ctx, "<.type>", TYPE_FIELD); + tmp->m_next = var; var = tmp; } @@ -4808,7 +4837,7 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va /* parse on */ if (!parser_next(parser)) { - ast_delete(var); + delete var; parseerror(parser, "parse error after typename"); return nullptr; } @@ -4826,10 +4855,10 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va /* store the base if requested */ if (storebase) { - *storebase = ast_value_from_type(var); + *storebase = new ast_value(ast_copy_type, *var); if (isfield) { - tmp = ast_value_new(ctx, "", TYPE_FIELD); - tmp->m_next = (ast_expression*)*storebase; + tmp = new ast_value(ctx, "", TYPE_FIELD); + tmp->m_next = *storebase; *storebase = tmp; } } @@ -4845,7 +4874,7 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va /* parse on */ if (!parser_next(parser)) { - ast_delete(var); + delete var; mem_d(name); parseerror(parser, "error after variable or field declaration"); return nullptr; @@ -4866,8 +4895,8 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va /* This is the point where we can turn it into a field */ if (isfield) { /* turn it into a field if desired */ - tmp = ast_value_new(ctx, "", TYPE_FIELD); - tmp->m_next = (ast_expression*)var; + tmp = new ast_value(ctx, "", TYPE_FIELD); + tmp->m_next = var; var = tmp; } @@ -4886,13 +4915,8 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va /* finally name it */ if (name) { - if (!ast_value_set_name(var, name)) { - ast_delete(var); - mem_d(name); - parseerror(parser, "internal error: failed to set name"); - return nullptr; - } - /* free the name, ast_value_set_name duplicates */ + var->m_name = name; + // free the name, ast_value_set_name duplicates mem_d(name); } @@ -4909,10 +4933,10 @@ static bool parse_typedef(parser_t *parser) if (!typevar) return false; - /* while parsing types, the ast_value's get named '' */ - if (!typevar->m_name || typevar->m_name[0] == '<') { + // while parsing types, the ast_value's get named '' + if (!typevar->m_name.length() || typevar->m_name[0] == '<') { parseerror(parser, "missing name in typedef"); - ast_delete(typevar); + delete typevar; return false; } @@ -4920,19 +4944,19 @@ static bool parse_typedef(parser_t *parser) parseerror(parser, "cannot define a type with the same name as a variable: %s\n" " -> `%s` has been declared here: %s:%i", typevar->m_name, old->m_context.file, old->m_context.line); - ast_delete(typevar); + delete typevar; return false; } if ( (oldtype = parser_find_typedef(parser, typevar->m_name, vec_last(parser->_blocktypedefs))) ) { parseerror(parser, "type `%s` has already been declared here: %s:%i", typevar->m_name, oldtype->m_context.file, oldtype->m_context.line); - ast_delete(typevar); + delete typevar; return false; } vec_push(parser->_typedefs, typevar); - util_htset(vec_last(parser->typedefs), typevar->m_name, typevar); + util_htset(vec_last(parser->typedefs), typevar->m_name.c_str(), typevar); if (parser->tok != ';') { parseerror(parser, "expected semicolon after typedef"); @@ -4987,10 +5011,10 @@ static bool parser_check_qualifiers(parser_t *parser, const ast_value *var, cons static bool create_array_accessors(parser_t *parser, ast_value *var) { char name[1024]; - util_snprintf(name, sizeof(name), "%s##SET", var->m_name); + util_snprintf(name, sizeof(name), "%s##SET", var->m_name.c_str()); if (!parser_create_array_setter(parser, var, name)) return false; - util_snprintf(name, sizeof(name), "%s##GET", var->m_name); + util_snprintf(name, sizeof(name), "%s##GET", var->m_name.c_str()); if (!parser_create_array_getter(parser, var, var->m_next, name)) return false; return true; @@ -5078,15 +5102,15 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield var = parse_typename(parser, &basetype, cached_typedef, nullptr); if (!var) { if (basetype) - ast_delete(basetype); + delete basetype; return false; } /* while parsing types, the ast_value's get named '' */ - if (!var->m_name || var->m_name[0] == '<') { + if (!var->m_name.length() || var->m_name[0] == '<') { parseerror(parser, "declaration does not declare anything"); if (basetype) - ast_delete(basetype); + delete basetype; return false; } @@ -5153,7 +5177,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield * Also: if there was a prototype, `var` will be deleted and set to `proto` which * is then filled with the previous definition and the parameter-names replaced. */ - if (!strcmp(var->m_name, "nil")) { + if (var->m_name == "nil") { if (OPTS_FLAG(UNTYPED_NIL)) { if (!localblock || !OPTS_FLAG(PERMISSIVE)) parseerror(parser, "name `nil` not allowed (try -fpermissive)"); @@ -5163,12 +5187,12 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield if (!localblock) { /* Deal with end_sys_ vars */ was_end = false; - if (!strcmp(var->m_name, "end_sys_globals")) { + if (var->m_name == "end_sys_globals") { var->m_uses++; parser->crc_globals = parser->globals.size(); was_end = true; } - else if (!strcmp(var->m_name, "end_sys_fields")) { + else if (var->m_name == "end_sys_fields") { var->m_uses++; parser->crc_fields = parser->fields.size(); was_end = true; @@ -5194,7 +5218,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield retval = false; goto cleanup; } - ast_delete(var); + delete var; var = nullptr; goto skipvar; /* @@ -5228,7 +5252,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield } proto = (ast_value*)old; proto->m_desc = var->m_desc; - if (!ast_compare_type((ast_expression*)proto, (ast_expression*)var)) { + if (!proto->compareType(*var)) { parseerror(parser, "conflicting types for `%s`, previous declaration was here: %s:%i", proto->m_name, proto->m_context.file, proto->m_context.line); @@ -5237,16 +5261,14 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield } /* we need the new parameter-names */ for (i = 0; i < proto->m_type_params.size(); ++i) - ast_value_set_name(proto->m_type_params[i], var->m_type_params[i]->m_name); + proto->m_type_params[i]->m_name = var->m_type_params[i]->m_name; if (!parser_check_qualifiers(parser, var, proto)) { retval = false; - if (proto->m_desc) - mem_d(proto->m_desc); proto = nullptr; goto cleanup; } proto->m_flags |= var->m_flags; - ast_delete(var); + delete var; var = proto; } else @@ -5284,7 +5306,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield */ if (proto->m_flags & AST_FLAG_FINAL_DECL) old->m_context = var->m_context; - ast_delete(var); + delete var; var = proto; } if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC && @@ -5320,7 +5342,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield goto cleanup; } if (OPTS_OPTION_U32(OPTION_STANDARD) != COMPILER_GMQCC) { - ast_delete(var); + delete var; if (ast_istype(old, ast_value)) var = proto = (ast_value*)old; else { @@ -5356,21 +5378,21 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield /* deal with global variables, fields, functions */ if (!nofields && var->m_vtype == TYPE_FIELD && parser->tok != '=') { var->m_isfield = true; - parser->fields.push_back((ast_expression*)var); - util_htset(parser->htfields, var->m_name, var); + parser->fields.push_back(var); + util_htset(parser->htfields, var->m_name.c_str(), var); if (isvector) { for (i = 0; i < 3; ++i) { - parser->fields.push_back((ast_expression*)me[i]); - util_htset(parser->htfields, me[i]->m_name, me[i]); + parser->fields.push_back(me[i]); + util_htset(parser->htfields, me[i]->m_name.c_str(), me[i]); } } } else { if (!(var->m_flags & AST_FLAG_ALIAS)) { - parser_addglobal(parser, var->m_name, (ast_expression*)var); + parser_addglobal(parser, var->m_name, var); if (isvector) { for (i = 0; i < 3; ++i) { - parser_addglobal(parser, me[i]->m_name, (ast_expression*)me[i]); + parser_addglobal(parser, me[i]->m_name.c_str(), me[i]); } } } else { @@ -5381,12 +5403,12 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield return false; } - if (!ast_compare_type((ast_expression*)var, find)) { + if (!var->compareType(*find)) { char ty1[1024]; char ty2[1024]; - ast_type_to_string(find, ty1, sizeof(ty1)); - ast_type_to_string((ast_expression*)var, ty2, sizeof(ty2)); + ast_type_to_string(find, ty1, sizeof(ty1)); + ast_type_to_string(var, ty2, sizeof(ty2)); compile_error(parser_ctx(parser), "incompatible types `%s` and `%s` for alias `%s`", ty1, ty2, var->m_name @@ -5394,19 +5416,19 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield return false; } - util_htset(parser->aliases, var->m_name, find); + util_htset(parser->aliases, var->m_name.c_str(), find); /* generate aliases for vector components */ if (isvector) { char *buffer[3]; - util_asprintf(&buffer[0], "%s_x", var->m_desc); - util_asprintf(&buffer[1], "%s_y", var->m_desc); - util_asprintf(&buffer[2], "%s_z", var->m_desc); + util_asprintf(&buffer[0], "%s_x", var->m_desc.c_str()); + util_asprintf(&buffer[1], "%s_y", var->m_desc.c_str()); + util_asprintf(&buffer[2], "%s_z", var->m_desc.c_str()); - util_htset(parser->aliases, me[0]->m_name, parser_find_global(parser, buffer[0])); - util_htset(parser->aliases, me[1]->m_name, parser_find_global(parser, buffer[1])); - util_htset(parser->aliases, me[2]->m_name, parser_find_global(parser, buffer[2])); + util_htset(parser->aliases, me[0]->m_name.c_str(), parser_find_global(parser, buffer[0])); + util_htset(parser->aliases, me[1]->m_name.c_str(), parser_find_global(parser, buffer[1])); + util_htset(parser->aliases, me[2]->m_name.c_str(), parser_find_global(parser, buffer[2])); mem_d(buffer[0]); mem_d(buffer[1]); @@ -5416,70 +5438,61 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield } } else { if (is_static) { - /* a static adds itself to be generated like any other global - * but is added to the local namespace instead - */ - char *defname = nullptr; - size_t prefix_len, ln; + // a static adds itself to be generated like any other global + // but is added to the local namespace instead + std::string defname; + size_t prefix_len; size_t sn, sn_size; - ln = strlen(parser->function->m_name); - vec_append(defname, ln, parser->function->m_name); + defname = parser->function->m_name; + defname.append(2, ':'); - vec_append(defname, 2, "::"); - /* remember the length up to here */ - prefix_len = vec_size(defname); + // remember the length up to here + prefix_len = defname.length(); - /* Add it to the local scope */ - util_htset(vec_last(parser->variables), var->m_name, (void*)var); + // Add it to the local scope + util_htset(vec_last(parser->variables), var->m_name.c_str(), (void*)var); - /* now rename the global */ - ln = strlen(var->m_name); - vec_append(defname, ln, var->m_name); - /* if a variable of that name already existed, add the - * counter value. - * The counter is incremented either way. - */ + // now rename the global + defname.append(var->m_name); + // if a variable of that name already existed, add the + // counter value. + // The counter is incremented either way. sn_size = parser->function->m_static_names.size(); for (sn = 0; sn != sn_size; ++sn) { - if (strcmp(parser->function->m_static_names[sn], var->m_name) == 0) + if (parser->function->m_static_names[sn] == var->m_name.c_str()) break; } if (sn != sn_size) { char *num = nullptr; int len = util_asprintf(&num, "#%u", parser->function->m_static_count); - vec_append(defname, len, num); + defname.append(num, 0, len); mem_d(num); } else - parser->function->m_static_names.push_back(util_strdup(var->m_name)); + parser->function->m_static_names.emplace_back(var->m_name); parser->function->m_static_count++; - ast_value_set_name(var, defname); + var->m_name = defname; - /* push it to the to-be-generated globals */ - parser->globals.push_back((ast_expression*)var); + // push it to the to-be-generated globals + parser->globals.push_back(var); - /* same game for the vector members */ + // same game for the vector members if (isvector) { + defname.erase(prefix_len); for (i = 0; i < 3; ++i) { - util_htset(vec_last(parser->variables), me[i]->m_name, (void*)(me[i])); - - vec_shrinkto(defname, prefix_len); - ln = strlen(me[i]->m_name); - vec_append(defname, ln, me[i]->m_name); - ast_member_set_name(me[i], defname); - - parser->globals.push_back((ast_expression*)me[i]); + util_htset(vec_last(parser->variables), me[i]->m_name.c_str(), (void*)(me[i])); + me[i]->m_name = move(defname + me[i]->m_name); + parser->globals.push_back(me[i]); } } - vec_free(defname); } else { localblock->m_locals.push_back(var); - parser_addlocal(parser, var->m_name, (ast_expression*)var); + parser_addlocal(parser, var->m_name, var); if (isvector) { for (i = 0; i < 3; ++i) { - parser_addlocal(parser, me[i]->m_name, (ast_expression*)me[i]); - ast_block_collect(localblock, (ast_expression*)me[i]); + parser_addlocal(parser, me[i]->m_name, me[i]); + localblock->collect(me[i]); } } } @@ -5511,24 +5524,24 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield goto cleanup; } - util_snprintf(name, sizeof(name), "%s##SETF", var->m_name); + util_snprintf(name, sizeof(name), "%s##SETF", var->m_name.c_str()); if (!parser_create_array_field_setter(parser, array, name)) goto cleanup; - telem = ast_type_copy(var->m_context, array->m_next); - tfield = ast_value_new(var->m_context, "<.type>", TYPE_FIELD); + telem = new ast_expression(ast_copy_type, var->m_context, *array->m_next); + tfield = new ast_value(var->m_context, "<.type>", TYPE_FIELD); tfield->m_next = telem; - util_snprintf(name, sizeof(name), "%s##GETFP", var->m_name); - if (!parser_create_array_getter(parser, array, (ast_expression*)tfield, name)) { - ast_delete(tfield); + util_snprintf(name, sizeof(name), "%s##GETFP", var->m_name.c_str()); + if (!parser_create_array_getter(parser, array, tfield, name)) { + delete tfield; goto cleanup; } - ast_delete(tfield); + delete tfield; } skipvar: if (parser->tok == ';') { - ast_delete(basetype); + delete basetype; if (!parser_next(parser)) { parseerror(parser, "error after variable declaration"); return false; @@ -5637,7 +5650,7 @@ skipvar: } else { - func = ast_function_new(var->m_context, var->m_name, var); + func = ast_function::make(var->m_context, var->m_name, var); if (!func) { parseerror(parser, "failed to allocate function for `%s`", var->m_name); break; @@ -5652,8 +5665,7 @@ skipvar: : (!parser_next(parser))) { parseerror(parser, "expected comma or semicolon"); - if (func) - ast_function_delete(func); + delete func; var->m_constval.vfunc = nullptr; break; } @@ -5684,7 +5696,7 @@ skipvar: if (!parse_function_body(parser, var)) break; - ast_delete(basetype); + delete basetype; for (auto &it : parser->gotos) parseerror(parser, "undefined label: `%s`", it->m_name); parser->gotos.clear(); @@ -5712,7 +5724,7 @@ skipvar: } } /* do sanity checking, this function really needs refactoring */ - if (vec_last(parser->_locals) != (ast_expression*)var) + if (vec_last(parser->_locals) != var) parseerror(parser, "internal error: unexpected change in local variable handling"); else vec_pop(parser->_locals); @@ -5721,10 +5733,10 @@ skipvar: else localblock->m_locals.pop_back(); /* push it to the to-be-generated globals */ - parser->globals.push_back((ast_expression*)var); + parser->globals.push_back(var); if (isvector) for (i = 0; i < 3; ++i) - parser->globals.push_back((ast_expression*)last_me[i]); + parser->globals.push_back(last_me[i]); folded_const = true; } @@ -5762,15 +5774,15 @@ skipvar: shunt sy; cvq = var->m_cvq; var->m_cvq = CV_NONE; - sy.out.push_back(syexp(var->m_context, (ast_expression*)var)); - sy.out.push_back(syexp(cexp->m_context, (ast_expression*)cexp)); + sy.out.push_back(syexp(var->m_context, var)); + sy.out.push_back(syexp(cexp->m_context, cexp)); sy.ops.push_back(syop(var->m_context, parser->assign_op)); if (!parser_sy_apply_operator(parser, &sy)) ast_unref(cexp); else { if (sy.out.size() != 1 && sy.ops.size() != 0) parseerror(parser, "internal error: leaked operands"); - if (!ast_block_add_expr(localblock, (ast_expression*)sy.out[0].out)) + if (!localblock->addExpr(sy.out[0].out)) break; } var->m_cvq = cvq; @@ -5795,9 +5807,9 @@ another: parseerror(parser, "expected another variable"); break; } - var = ast_value_from_type(basetype); + var = new ast_value(ast_copy_type, *basetype); cleanvar = true; - ast_value_set_name(var, parser_tokval(parser)); + var->m_name = parser_tokval(parser); if (!parser_next(parser)) { parseerror(parser, "error parsing variable declaration"); break; @@ -5815,22 +5827,22 @@ another: break; } - ast_delete(basetype); + delete basetype; return true; } if (cleanvar && var) - ast_delete(var); - ast_delete(basetype); + delete var; + delete basetype; return false; cleanup: - ast_delete(basetype); + delete basetype; if (cleanvar && var) - ast_delete(var); - if (me[0]) ast_member_delete(me[0]); - if (me[1]) ast_member_delete(me[1]); - if (me[2]) ast_member_delete(me[2]); + delete var; + delete me[0]; + delete me[1]; + delete me[2]; return retval; } @@ -5942,7 +5954,7 @@ static void generate_checksum(parser_t *parser, ir_builder *ir) crc = progdefs_crc_both(crc, "\tint\t"); break; } - crc = progdefs_crc_both(crc, value->m_name); + crc = progdefs_crc_both(crc, value->m_name.c_str()); crc = progdefs_crc_both(crc, ";\n"); } crc = progdefs_crc_both(crc, "} globalvars_t;\n\ntypedef struct\n{\n"); @@ -5959,7 +5971,7 @@ static void generate_checksum(parser_t *parser, ir_builder *ir) crc = progdefs_crc_both(crc, "\tint\t"); break; } - crc = progdefs_crc_both(crc, value->m_name); + crc = progdefs_crc_both(crc, value->m_name.c_str()); crc = progdefs_crc_both(crc, ";\n"); } crc = progdefs_crc_both(crc, "} entvars_t;\n\n"); @@ -6003,19 +6015,19 @@ parser_t *parser_create() empty_ctx.file = ""; empty_ctx.line = 0; empty_ctx.column = 0; - parser->nil = ast_value_new(empty_ctx, "nil", TYPE_NIL); + parser->nil = new ast_value(empty_ctx, "nil", TYPE_NIL); parser->nil->m_cvq = CV_CONST; if (OPTS_FLAG(UNTYPED_NIL)) util_htset(parser->htglobals, "nil", (void*)parser->nil); parser->max_param_count = 1; - parser->const_vec[0] = ast_value_new(empty_ctx, "", TYPE_NOEXPR); - parser->const_vec[1] = ast_value_new(empty_ctx, "", TYPE_NOEXPR); - parser->const_vec[2] = ast_value_new(empty_ctx, "", TYPE_NOEXPR); + parser->const_vec[0] = new ast_value(empty_ctx, "", TYPE_NOEXPR); + parser->const_vec[1] = new ast_value(empty_ctx, "", TYPE_NOEXPR); + parser->const_vec[2] = new ast_value(empty_ctx, "", TYPE_NOEXPR); if (OPTS_OPTION_BOOL(OPTION_ADD_INFO)) { - parser->reserved_version = ast_value_new(empty_ctx, "reserved:version", TYPE_STRING); + parser->reserved_version = new ast_value(empty_ctx, "reserved:version", TYPE_STRING); parser->reserved_version->m_cvq = CV_CONST; parser->reserved_version->m_hasvalue = true; parser->reserved_version->m_flags |= AST_FLAG_INCLUDE_DEF; @@ -6088,13 +6100,13 @@ static void parser_remove_ast(parser_t *parser) return; parser->ast_cleaned = true; for (auto &it : parser->accessors) { - ast_delete(it->m_constval.vfunc); + delete it->m_constval.vfunc; it->m_constval.vfunc = nullptr; - ast_delete(it); + delete it; } - for (auto &it : parser->functions) ast_delete(it); - for (auto &it : parser->globals) ast_delete(it); - for (auto &it : parser->fields) ast_delete(it); + for (auto &it : parser->functions) delete it; + for (auto &it : parser->globals) delete it; + for (auto &it : parser->fields) delete it; for (i = 0; i < vec_size(parser->variables); ++i) util_htdel(parser->variables[i]); @@ -6103,7 +6115,7 @@ static void parser_remove_ast(parser_t *parser) vec_free(parser->_locals); for (i = 0; i < vec_size(parser->_typedefs); ++i) - ast_delete(parser->_typedefs[i]); + delete parser->_typedefs[i]; vec_free(parser->_typedefs); for (i = 0; i < vec_size(parser->typedefs); ++i) util_htdel(parser->typedefs[i]); @@ -6112,14 +6124,14 @@ static void parser_remove_ast(parser_t *parser) vec_free(parser->_block_ctx); - ast_value_delete(parser->nil); + delete parser->nil; - ast_value_delete(parser->const_vec[0]); - ast_value_delete(parser->const_vec[1]); - ast_value_delete(parser->const_vec[2]); + delete parser->const_vec[0]; + delete parser->const_vec[1]; + delete parser->const_vec[2]; if (parser->reserved_version) - ast_value_delete(parser->reserved_version); + delete parser->reserved_version; util_htdel(parser->aliases); } @@ -6141,7 +6153,7 @@ static bool parser_set_coverage_func(parser_t *parser, ir_builder *ir) { func = nullptr; for (auto &it : parser->functions) { - if (!strcmp(it->m_name, "coverage")) { + if (it->m_name == "coverage") { func = it; break; } @@ -6156,7 +6168,7 @@ static bool parser_set_coverage_func(parser_t *parser, ir_builder *ir) { } cov = func->m_function_type; - expr = (ast_expression*)cov; + expr = cov; if (expr->m_vtype != TYPE_FUNCTION || expr->m_type_params.size()) { char ty[1024]; @@ -6193,8 +6205,8 @@ bool parser_finish(parser_t *parser, const char *output) ast_value *field = (ast_value*)it; hasvalue = field->m_hasvalue; field->m_hasvalue = false; - if (!ast_global_codegen((ast_value*)field, ir, true)) { - con_out("failed to generate field %s\n", field->m_name); + if (!reinterpret_cast(field)->generateGlobal(ir, true)) { + con_out("failed to generate field %s\n", field->m_name.c_str()); delete ir; return false; } @@ -6220,8 +6232,8 @@ bool parser_finish(parser_t *parser, const char *output) retval = retval && !compile_warning(asvalue->m_context, WARN_UNUSED_VARIABLE, "unused global: `%s`", asvalue->m_name); } - if (!ast_global_codegen(asvalue, ir, false)) { - con_out("failed to generate global %s\n", asvalue->m_name); + if (!asvalue->generateGlobal(ir, false)) { + con_out("failed to generate global %s\n", asvalue->m_name.c_str()); delete ir; return false; } @@ -6233,18 +6245,17 @@ bool parser_finish(parser_t *parser, const char *output) if (f->m_varargs) { if (parser->max_param_count > f->m_function_type->m_type_params.size()) { f->m_varargs->m_count = parser->max_param_count - f->m_function_type->m_type_params.size(); - if (!parser_create_array_setter_impl(parser, f->m_varargs)) { - con_out("failed to generate vararg setter for %s\n", f->m_name); + if (!parser_create_array_setter_impl(parser, f->m_varargs.get())) { + con_out("failed to generate vararg setter for %s\n", f->m_name.c_str()); delete ir; return false; } - if (!parser_create_array_getter_impl(parser, f->m_varargs)) { - con_out("failed to generate vararg getter for %s\n", f->m_name); + if (!parser_create_array_getter_impl(parser, f->m_varargs.get())) { + con_out("failed to generate vararg getter for %s\n", f->m_name.c_str()); delete ir; return false; } } else { - ast_delete(f->m_varargs); f->m_varargs = nullptr; } } @@ -6271,32 +6282,32 @@ bool parser_finish(parser_t *parser, const char *output) "uninitialized global: `%s`", asvalue->m_name); } - if (!ast_generate_accessors(asvalue, ir)) { + if (!asvalue->generateAccessors(ir)) { delete ir; return false; } } for (auto &it : parser->fields) { ast_value *asvalue = (ast_value*)it->m_next; - if (!ast_istype((ast_expression*)asvalue, ast_value)) + if (!ast_istype(asvalue, ast_value)) continue; if (asvalue->m_vtype != TYPE_ARRAY) continue; - if (!ast_generate_accessors(asvalue, ir)) { + if (!asvalue->generateAccessors(ir)) { delete ir; return false; } } if (parser->reserved_version && - !ast_global_codegen(parser->reserved_version, ir, false)) + !parser->reserved_version->generateGlobal(ir, false)) { con_out("failed to generate reserved::version"); delete ir; return false; } for (auto &f : parser->functions) { - if (!ast_function_codegen(f, ir)) { - con_out("failed to generate function %s\n", f->m_name); + if (!f->generateFunction(ir)) { + con_out("failed to generate function %s\n", f->m_name.c_str()); delete ir; return false; } @@ -6308,7 +6319,7 @@ bool parser_finish(parser_t *parser, const char *output) ir_builder_dump(ir, con_out); for (auto &it : parser->functions) { if (!ir_function_finalize(it->m_ir_func)) { - con_out("failed to finalize function %s\n", it->m_name); + con_out("failed to finalize function %s\n", it->m_name.c_str()); delete ir; return false; }