From: Wolfgang Bumiller Date: Sun, 25 Jan 2015 08:24:26 +0000 (+0100) Subject: BROKEN: in the middle of converting ast nodes to c++ with constructors and methods X-Git-Tag: xonotic-v0.8.2~18 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=6149f6a1d09e6c7d5c1c1e7de7e38635c791f697;p=xonotic%2Fgmqcc.git BROKEN: in the middle of converting ast nodes to c++ with constructors and methods --- diff --git a/ast.cpp b/ast.cpp index bb3d9db..5705fdf 100644 --- a/ast.cpp +++ b/ast.cpp @@ -57,174 +57,162 @@ 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**); -/* It must not be possible to get here. */ -static GMQCC_NORETURN void _ast_node_destroy(ast_node *self) +/* Initialize main ast node aprts */ +ast_node::ast_node(lex_ctx_t ctx, int node_type) +: m_context(ctx), + m_node_type(node_type), + m_keep_node(false), + m_side_effects(false) { - (void)self; - con_err("ast node missing destroy()\n"); - exit(EXIT_FAILURE); } -/* Initialize main ast node aprts */ -static void ast_node_init(ast_node *self, lex_ctx_t ctx, int node_type) +ast_node::~ast_node() { - self->m_context = ctx; - self->m_destroy = &_ast_node_destroy; - self->m_keep_node = false; - self->m_node_type = node_type; - self->m_side_effects = false; } /* weight and side effects */ -static void _ast_propagate_effects(ast_node *self, ast_node *other) +void ast_node::propagate_side_effects(ast_node *other) const { - if (other->m_side_effects) - self->m_side_effects = true; + other->m_side_effects = m_side_effects; } -#define ast_propagate_effects(s,o) _ast_propagate_effects(((ast_node*)(s)), ((ast_node*)(o))) /* General expression initialization */ -static void ast_expression_init(ast_expression *self, - ast_expression_codegen *codegen) -{ - self->m_codegen = codegen; - self->m_vtype = TYPE_VOID; - self->m_next = nullptr; - self->m_outl = nullptr; - self->m_outr = nullptr; - self->m_count = 0; - self->m_varparam = nullptr; - self->m_flags = 0; +ast_expression::ast_expression(lex_ctx_t ctx, int nodetype, qc_type type) +: ast_node(ctx, nodetype), + m_vtype(type) +{ if (OPTS_OPTION_BOOL(OPTION_COVERAGE)) - self->m_flags |= AST_FLAG_BLOCK_COVERAGE; + m_flags |= AST_FLAG_BLOCK_COVERAGE; } +ast_expression::ast_expression(lex_ctx_t ctx, int nodetype) +: ast_expression(ctx, nodetype, TYPE_VOID) +{} -static void ast_expression_delete(ast_expression *self) +ast_expression::~ast_expression() { - if (self->m_next) - ast_delete(self->m_next); - for (auto &it : self->m_type_params) - ast_delete(it); - if (self->m_varparam) - ast_delete(self->m_varparam); + if (m_next) + delete m_next; + if (m_varparam) + delete m_varparam; } -static void ast_expression_delete_full(ast_expression *self) +ast_expression::ast_expression(ast_copy_type_t, int nodetype, const ast_expression &other) +: ast_expression(other.m_context, nodetype) { - ast_expression_delete(self); - mem_d(self); + 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_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_value* ast_value_copy(const ast_value *self) -{ - ast_value *cp = ast_value_new(self->m_context, self->m_name, self->m_vtype); - if (self->m_next) { - cp->m_next = ast_type_copy(self->m_context, self->m_next); - } - const ast_expression *fromex = self; - ast_expression *selfex = cp; - selfex->m_count = fromex->m_count; - selfex->m_flags = fromex->m_flags; - for (auto &it : fromex->m_type_params) { - ast_value *v = ast_value_copy(it); - selfex->m_type_params.push_back(v); - } - return cp; -} +ast_expression::ast_expression(ast_copy_type_t, const ast_expression &other) +: ast_expression(other.m_context, TYPE_ast_expression) +{} -void ast_type_adopt_impl(ast_expression *self, const ast_expression *other) -{ - const ast_expression *fromex; - ast_expression *selfex; - self->m_vtype = other->m_vtype; - if (other->m_next) { - self->m_next = (ast_expression*)ast_type_copy(self->m_context, other->m_next); - } - fromex = other; - selfex = self; - selfex->m_count = fromex->m_count; - selfex->m_flags = fromex->m_flags; - for (auto &it : fromex->m_type_params) { - ast_value *v = ast_value_copy(it); - selfex->m_type_params.push_back(v); - } +ast_expression *ast_expression::shallow_type(lex_ctx_t ctx, qc_type vtype) { + auto expr = new ast_expression(ctx, TYPE_ast_expression); + expr->m_vtype = vtype; + return expr; } -static ast_expression* ast_shallow_type(lex_ctx_t ctx, qc_type vtype) +void ast_expression::adopt_type(const ast_expression &other) { - ast_instantiate(ast_expression, ctx, ast_expression_delete_full); - ast_expression_init(self, nullptr); - self->m_codegen = nullptr; - self->m_next = nullptr; - self->m_vtype = vtype; - return self; + m_vtype = other.m_vtype; + if (other.m_next) + m_next = new ast_expression(ast_copy_type, TYPE_ast_expression, *other.m_next); + m_count = other.m_count; + m_flags = other.m_flags; + m_type_params.clear(); + 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_type_copy(lex_ctx_t ctx, const ast_expression *ex) +bool ast_expression::compare_type(const ast_expression &other) const { - const ast_expression *fromex; - ast_expression *selfex; - - if (!ex) - return nullptr; - else - { - ast_instantiate(ast_expression, ctx, ast_expression_delete_full); - ast_expression_init(self, nullptr); - - fromex = ex; - selfex = self; - - /* This may never be codegen()d */ - selfex->m_codegen = nullptr; - - selfex->m_vtype = fromex->m_vtype; - if (fromex->m_next) - selfex->m_next = ast_type_copy(ctx, fromex->m_next); - else - selfex->m_next = nullptr; - - selfex->m_count = fromex->m_count; - selfex->m_flags = fromex->m_flags; - for (auto &it : fromex->m_type_params) { - ast_value *v = ast_value_copy(it); - selfex->m_type_params.push_back(v); - } - - return self; - } -} - -bool ast_compare_type(ast_expression *a, ast_expression *b) -{ - if (a->m_vtype == TYPE_NIL || - b->m_vtype == TYPE_NIL) + if (m_vtype == TYPE_NIL || + other.m_vtype == TYPE_NIL) return true; - if (a->m_vtype != b->m_vtype) + if (m_vtype != other.m_vtype) return false; - if (!a->m_next != !b->m_next) + if (!m_next != !other.m_next) return false; - if (a->m_type_params.size() != b->m_type_params.size()) + if (m_type_params.size() != other.m_type_params.size()) return false; - if ((a->m_flags & AST_FLAG_TYPE_MASK) != - (b->m_flags & AST_FLAG_TYPE_MASK) ) + if ((m_flags & AST_FLAG_TYPE_MASK) != + (other.m_flags & AST_FLAG_TYPE_MASK) ) { return false; } - if (a->m_type_params.size()) { + if (m_type_params.size()) { size_t i; - for (i = 0; i < a->m_type_params.size(); ++i) { - if (!ast_compare_type((ast_expression*)a->m_type_params[i], - (ast_expression*)b->m_type_params[i])) + for (i = 0; i < m_type_params.size(); ++i) { + if (!m_type_params[i]->compare_type(*other.m_type_params[i])) return false; } } - if (a->m_next) - return ast_compare_type(a->m_next, b->m_next); + if (m_next) + return m_next->compare_type(*other.m_next); return true; } -static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsize, size_t pos) +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) +{} + +ast_value::ast_value(ast_copy_type_t, const ast_value &other) +: ast_value(ast_copy_type, static_cast(other), other.m_name) +{} + +ast_value::ast_value(ast_copy_type_t, const ast_expression &other, const std::string &name) +: ast_expression(ast_copy_type, other), + m_name(name) +{} + +ast_value::ast_value(lex_ctx_t ctx, const std::string &name, qc_type t) +: ast_expression(ctx, TYPE_ast_value, t), + m_name(name) +{ + m_keep_node = true; // keep values, always + memset(&m_constval, 0, sizeof(m_constval)); +} + +ast_value::~ast_value() +{ + if (m_argcounter) + mem_d((void*)m_argcounter); + if (m_hasvalue) { + switch (m_vtype) + { + case TYPE_STRING: + mem_d((void*)m_constval.vstring); + break; + case TYPE_FUNCTION: + // unlink us from the function node + m_constval.vfunc->m_function_type = nullptr; + break; + // NOTE: delete function? currently collected in + // the parser structure + default: + 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) { + for (auto &it : m_initlist) + if (it.vstring) + mem_d(it.vstring); + } +} + +static size_t ast_type_to_string_impl(const ast_expression *e, char *buf, size_t bufsize, size_t pos) { const char *typestr; size_t typelen; @@ -270,13 +258,13 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi return pos; } buf[pos++] = '('; - pos = ast_type_to_string_impl((ast_expression*)(e->m_type_params[0]), buf, bufsize, pos); + pos = ast_type_to_string_impl(e->m_type_params[0].get(), buf, bufsize, pos); for (i = 1; i < e->m_type_params.size(); ++i) { if (pos + 2 >= bufsize) goto full; buf[pos++] = ','; buf[pos++] = ' '; - pos = ast_type_to_string_impl((ast_expression*)(e->m_type_params[i]), buf, bufsize, pos); + pos = ast_type_to_string_impl(e->m_type_params[i].get(), buf, bufsize, pos); } if (pos + 1 >= bufsize) goto full; @@ -310,105 +298,24 @@ full: return bufsize; } -void ast_type_to_string(ast_expression *e, char *buf, size_t bufsize) +void ast_type_to_string(const ast_expression *e, char *buf, size_t bufsize) { size_t pos = ast_type_to_string_impl(e, buf, bufsize-1, 0); buf[pos] = 0; } -static bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_value **out); -ast_value* ast_value_new(lex_ctx_t ctx, const char *name, qc_type t) -{ - ast_instantiate(ast_value, ctx, ast_value_delete); - ast_expression_init((ast_expression*)self, - (ast_expression_codegen*)&ast_value_codegen); - self->m_keep_node = true; /* keep */ - - self->m_name = name ? util_strdup(name) : nullptr; - self->m_vtype = t; - self->m_next = nullptr; - self->m_isfield = false; - self->m_cvq = CV_NONE; - self->m_hasvalue = false; - self->m_isimm = false; - self->m_inexact = false; - self->m_uses = 0; - memset(&self->m_constval, 0, sizeof(self->m_constval)); - - self->m_ir_v = nullptr; - self->m_ir_values = nullptr; - self->m_ir_value_count = 0; - - self->m_setter = nullptr; - self->m_getter = nullptr; - self->m_desc = nullptr; - - self->m_argcounter = nullptr; - self->m_intrinsic = false; - - return self; -} - -void ast_value_delete(ast_value* self) -{ - if (self->m_name) - mem_d((void*)self->m_name); - if (self->m_argcounter) - mem_d((void*)self->m_argcounter); - if (self->m_hasvalue) { - switch (self->m_vtype) - { - case TYPE_STRING: - mem_d((void*)self->m_constval.vstring); - break; - case TYPE_FUNCTION: - /* unlink us from the function node */ - self->m_constval.vfunc->m_function_type = nullptr; - break; - /* NOTE: delete function? currently collected in - * the parser structure - */ - default: - break; - } - } - if (self->m_ir_values) - mem_d(self->m_ir_values); - - if (self->m_desc) - mem_d(self->m_desc); - - // initlist imples an array which implies .next in the expression exists. - if (self->m_initlist.size() && self->m_next->m_vtype == TYPE_STRING) { - for (auto &it : self->m_initlist) - if (it.vstring) - mem_d(it.vstring); - } - - ast_expression_delete((ast_expression*)self); - self->~ast_value(); - mem_d(self); -} - -void ast_value_params_add(ast_value *self, ast_value *p) +void ast_value::add_param(ast_value *p) { - self->m_type_params.push_back(p); + m_type_params.emplace_back(p); } -bool ast_value_set_name(ast_value *self, const char *name) +ast_binary::ast_binary(lex_ctx_t ctx, int op, + ast_expression* left, ast_expression* right) +: ast_expression(ctx, TYPE_ast_binary), + m_op(op), + // m_left/m_right happen after the peephole step right below + m_right_first(false) { - if (self->m_name) - mem_d((void*)self->m_name); - self->m_name = util_strdup(name); - return !!self->m_name; -} - -ast_binary* ast_binary_new(lex_ctx_t ctx, int op, - ast_expression* left, ast_expression* right) -{ - ast_instantiate(ast_binary, ctx, ast_binary_delete); - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_binary_codegen); - if (ast_istype(right, ast_unary) && OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) { ast_unary *unary = ((ast_unary*)right); ast_expression *normal = unary->m_operand; @@ -427,86 +334,61 @@ ast_binary* ast_binary_new(lex_ctx_t ctx, int op, } } - self->m_op = op; - self->m_left = left; - self->m_right = right; - self->m_right_first = false; + m_left = left; + m_right = right; - ast_propagate_effects(self, left); - ast_propagate_effects(self, right); + propagate_side_effects(left); + propagate_side_effects(right); if (op >= INSTR_EQ_F && op <= INSTR_GT) - self->m_vtype = TYPE_FLOAT; + m_vtype = TYPE_FLOAT; else if (op == INSTR_AND || op == INSTR_OR) { if (OPTS_FLAG(PERL_LOGIC)) - ast_type_adopt(self, right); + adopt_type(*right); else - self->m_vtype = TYPE_FLOAT; + m_vtype = TYPE_FLOAT; } else if (op == INSTR_BITAND || op == INSTR_BITOR) - self->m_vtype = TYPE_FLOAT; + m_vtype = TYPE_FLOAT; else if (op == INSTR_MUL_VF || op == INSTR_MUL_FV) - self->m_vtype = TYPE_VECTOR; + m_vtype = TYPE_VECTOR; else if (op == INSTR_MUL_V) - self->m_vtype = TYPE_FLOAT; + m_vtype = TYPE_FLOAT; else - self->m_vtype = left->m_vtype; - - /* references all */ - self->m_refs = AST_REF_ALL; + m_vtype = left->m_vtype; - return self; + // references all + m_refs = AST_REF_ALL; } -void ast_binary_delete(ast_binary *self) +ast_binary::~ast_binary() { - if (self->m_refs & AST_REF_LEFT) ast_unref(self->m_left); - if (self->m_refs & AST_REF_RIGHT) ast_unref(self->m_right); - - ast_expression_delete((ast_expression*)self); - self->~ast_binary(); - mem_d(self); + if (m_refs & AST_REF_LEFT) ast_unref(m_left); + if (m_refs & AST_REF_RIGHT) ast_unref(m_right); } -ast_binstore* ast_binstore_new(lex_ctx_t ctx, int storop, int op, - ast_expression* left, ast_expression* right) +ast_binstore::ast_binstore(lex_ctx_t ctx, int storop, int mathop, + ast_expression* left, ast_expression* right) +: ast_expression(ctx, TYPE_ast_binstore), + m_opstore(storop), + m_opbin(mathop), + m_dest(left), + m_source(right), + m_keep_dest(false) { - ast_instantiate(ast_binstore, ctx, ast_binstore_delete); - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_binstore_codegen); - - self->m_side_effects = true; - - self->m_opstore = storop; - self->m_opbin = op; - self->m_dest = left; - self->m_source = right; - - self->m_keep_dest = false; - - ast_type_adopt(self, left); - return self; + m_side_effects = true; + adopt_type(*left); } -void ast_binstore_delete(ast_binstore *self) +ast_binstore::~ast_binstore() { - if (!self->m_keep_dest) - ast_unref(self->m_dest); - ast_unref(self->m_source); - ast_expression_delete((ast_expression*)self); - self->~ast_binstore(); - mem_d(self); + if (!m_keep_dest) + ast_unref(m_dest); + ast_unref(m_source); } -ast_unary* ast_unary_new(lex_ctx_t ctx, int op, - ast_expression *expr) +ast_unary* ast_unary::make(lex_ctx_t ctx, int op, ast_expression *expr) { - ast_instantiate(ast_unary, ctx, ast_unary_delete); - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_unary_codegen); - - self->m_op = op; - self->m_operand = expr; - - if (ast_istype(expr, ast_unary) && OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) { ast_unary *prev = (ast_unary*)((ast_unary*)expr)->m_operand; @@ -515,93 +397,76 @@ ast_unary* ast_unary_new(lex_ctx_t ctx, int op, prev = (ast_unary*)((ast_unary*)expr)->m_operand; if (ast_istype(prev, ast_unary)) { - ast_expression_delete((ast_expression*)self); - mem_d(self); ++opts_optimizationcount[OPTIM_PEEPHOLE]; return prev; } } - ast_propagate_effects(self, expr); + return new ast_unary(ctx, op, expr); +} +ast_unary::ast_unary(lex_ctx_t ctx, int op, ast_expression *expr) +: ast_expression(ctx, TYPE_ast_unary), + m_op(op), + m_operand(expr) +{ + propagate_side_effects(expr); if ((op >= INSTR_NOT_F && op <= INSTR_NOT_FNC) || op == VINSTR_NEG_F) { - self->m_vtype = TYPE_FLOAT; + m_vtype = TYPE_FLOAT; } else if (op == VINSTR_NEG_V) { - self->m_vtype = TYPE_VECTOR; + m_vtype = TYPE_VECTOR; } else { compile_error(ctx, "cannot determine type of unary operation %s", util_instr_str[op]); } - - return self; } -void ast_unary_delete(ast_unary *self) +ast_unary::~ast_unary() { - if (self->m_operand) ast_unref(self->m_operand); - ast_expression_delete((ast_expression*)self); - self->~ast_unary(); - mem_d(self); + if (m_operand) + ast_unref(m_operand); } -ast_return* ast_return_new(lex_ctx_t ctx, ast_expression *expr) +ast_return::ast_return(lex_ctx_t ctx, ast_expression *expr) +: ast_expression(ctx, TYPE_ast_return), + m_operand(expr) { - ast_instantiate(ast_return, ctx, ast_return_delete); - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_return_codegen); - - self->m_operand = expr; - if (expr) - ast_propagate_effects(self, expr); - - return self; + propagate_side_effects(expr); } -void ast_return_delete(ast_return *self) +ast_return::~ast_return() { - if (self->m_operand) - ast_unref(self->m_operand); - ast_expression_delete((ast_expression*)self); - self->~ast_return(); - mem_d(self); + if (m_operand) + ast_unref(m_operand); } -ast_entfield* ast_entfield_new(lex_ctx_t ctx, ast_expression *entity, ast_expression *field) +ast_entfield::ast_entfield(lex_ctx_t ctx, ast_expression *entity, ast_expression *field) +: ast_entfield(ctx, entity, field, field->m_next) { - if (field->m_vtype != TYPE_FIELD) { - compile_error(ctx, "ast_entfield_new with expression not of type field"); - return nullptr; - } - return ast_entfield_new_force(ctx, entity, field, field->m_next); + if (field->m_vtype != TYPE_FIELD) + compile_error(ctx, "ast_entfield with expression not of type field"); } -ast_entfield* ast_entfield_new_force(lex_ctx_t ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype) +ast_entfield::ast_entfield(lex_ctx_t ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype) +: ast_expression(ctx, TYPE_ast_entfield), + m_entity(entity), + m_field(field) { - ast_instantiate(ast_entfield, ctx, ast_entfield_delete); + propagate_side_effects(*m_entity); + propagate_side_effects(*m_field); if (!outtype) { - mem_d(self); - /* Error: field has no type... */ - return nullptr; + compile_error(ctx, "ast_entfield: field has no type"); + m_vtype = TYPE_VOID; } - - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_entfield_codegen); - - self->m_entity = entity; - self->m_field = field; - ast_propagate_effects(self, entity); - ast_propagate_effects(self, field); - - ast_type_adopt(self, outtype); - return self; + else + adopt_type(*outtype); } -void ast_entfield_delete(ast_entfield *self) +ast_entfield::~ast_entfield() { - ast_unref(self->m_entity); - ast_unref(self->m_field); - ast_expression_delete((ast_expression*)self); - self->~ast_entfield(); - mem_d(self); + ast_unref(m_entity); + ast_unref(m_field); } ast_member* ast_member_new(lex_ctx_t ctx, ast_expression *owner, unsigned int field, const char *name) @@ -632,7 +497,7 @@ ast_member* ast_member_new(lex_ctx_t ctx, ast_expression *owner, unsigned int fi self->m_rvalue = false; self->m_owner = owner; - ast_propagate_effects(self, owner); + self->propagate_side_effects(owner); self->m_field = field; if (name) @@ -683,8 +548,8 @@ ast_array_index* ast_array_index_new(lex_ctx_t ctx, ast_expression *array, ast_e self->m_array = array; self->m_index = index; - ast_propagate_effects(self, array); - ast_propagate_effects(self, index); + self->propagate_side_effects(array); + self->propagate_side_effects(index); ast_type_adopt(self, outtype); if (array->m_vtype == TYPE_FIELD && outtype->m_vtype == TYPE_ARRAY) { @@ -741,11 +606,11 @@ ast_ifthen* ast_ifthen_new(lex_ctx_t ctx, ast_expression *cond, ast_expression * self->m_cond = cond; self->m_on_true = ontrue; self->m_on_false = onfalse; - ast_propagate_effects(self, cond); + self->propagate_side_effects(cond); if (ontrue) - ast_propagate_effects(self, ontrue); + self->propagate_side_effects(ontrue); if (onfalse) - ast_propagate_effects(self, onfalse); + self->propagate_side_effects(onfalse); return self; } @@ -776,9 +641,9 @@ ast_ternary* ast_ternary_new(lex_ctx_t ctx, ast_expression *cond, ast_expression self->m_cond = cond; self->m_on_true = ontrue; self->m_on_false = onfalse; - ast_propagate_effects(self, cond); - ast_propagate_effects(self, ontrue); - ast_propagate_effects(self, onfalse); + self->propagate_side_effects(cond); + self->propagate_side_effects(ontrue); + self->propagate_side_effects(onfalse); if (ontrue->m_vtype == TYPE_NIL) exprtype = onfalse; @@ -820,15 +685,15 @@ ast_loop* ast_loop_new(lex_ctx_t ctx, self->m_post_not = post_not; if (initexpr) - ast_propagate_effects(self, initexpr); + self->propagate_side_effects(initexpr); if (precond) - ast_propagate_effects(self, precond); + self->propagate_side_effects(precond); if (postcond) - ast_propagate_effects(self, postcond); + self->propagate_side_effects(postcond); if (increment) - ast_propagate_effects(self, increment); + self->propagate_side_effects(increment); if (body) - ast_propagate_effects(self, body); + self->propagate_side_effects(body); return self; } @@ -875,7 +740,7 @@ ast_switch* ast_switch_new(lex_ctx_t ctx, ast_expression *op) self->m_operand = op; - ast_propagate_effects(self, op); + self->propagate_side_effects(op); return self; } @@ -1141,7 +1006,7 @@ ast_block* ast_block_new(lex_ctx_t ctx) bool ast_block_add_expr(ast_block *self, ast_expression *e) { - ast_propagate_effects(self, e); + self->propagate_side_effects(e); self->m_exprs.push_back(e); if (self->m_next) { ast_delete(self->m_next); diff --git a/ast.h b/ast.h index 8a437ab..4d8736c 100644 --- a/ast.h +++ b/ast.h @@ -101,29 +101,32 @@ typedef void ast_node_delete(ast_node*); struct ast_node { - //ast_node() = delete; - //ast_node(lex_ctx_t, int nodetype); - //virtual ~ast_node(); + ast_node() = delete; + ast_node(lex_ctx_t, int nodetype); + virtual ~ast_node(); lex_ctx_t m_context; /* I don't feel comfortable using keywords like 'delete' as names... */ - ast_node_delete *m_destroy; int m_node_type; /* keep_node: if a node contains this node, 'keep_node' * prevents its dtor from destroying this node as well. */ bool m_keep_node; bool m_side_effects; + + void propagate_side_effects(ast_node *other) const; }; -#define ast_delete(x) ( (x)->m_destroy((x)) ) #define ast_unref(x) do \ { \ if (! (x)->m_keep_node ) { \ - ast_delete(x); \ + delete (x); \ } \ } while(0) +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 @@ -144,27 +147,36 @@ typedef bool ast_expression_codegen(ast_expression*, * variables through the environment (or functions, constants...). */ struct ast_expression : ast_node { - ast_expression() {} + ast_expression() = delete; + 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&); + + static ast_expression *shallow_type(lex_ctx_t ctx, qc_type vtype); + + bool compare_type(const ast_expression &other) const; + void adopt_type(const ast_expression &other); - ast_expression_codegen *m_codegen; - qc_type m_vtype; - ast_expression *m_next; + qc_type m_vtype = TYPE_VOID; + ast_expression *m_next = nullptr; /* arrays get a member-count */ - size_t m_count; - std::vector m_type_params; + size_t m_count = 0; + std::vector> m_type_params; - ast_flag_t m_flags; + ast_flag_t m_flags = 0; /* void foo(string...) gets varparam set as a restriction * for variadic parameters */ - ast_expression *m_varparam; + ast_expression *m_varparam = nullptr; /* The codegen functions should store their output values * so we can call it multiple times without re-evaluating. * Store lvalue and rvalue seperately though. So that * ast_entfield for example can generate both if required. */ - ir_value *m_outl; - ir_value *m_outr; + ir_value *m_outl = nullptr; + ir_value *m_outr = nullptr; }; /* Value @@ -186,16 +198,26 @@ union basic_value_t { struct ast_value : ast_expression { - const char *m_name; - const char *m_desc; + ast_value() = delete; + ast_value(lex_ctx_t ctx, const std::string &name, qc_type qctype); + ~ast_value(); + + ast_value(ast_copy_type_t, const ast_expression&, const std::string&); + 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*); + + std::string m_name; + std::string m_desc; - const char *m_argcounter; + const char *m_argcounter = nullptr; - int m_cvq; /* const/var qualifier */ - bool m_isfield; /* this declares a field */ - bool m_isimm; /* an immediate, not just const */ - bool m_hasvalue; - bool m_inexact; /* inexact coming from folded expression */ + int m_cvq = CV_NONE; /* const/var qualifier */ + bool m_isfield = false; /* this declares a field */ + bool m_isimm = false; /* an immediate, not just const */ + bool m_hasvalue = false; + bool m_inexact = false; /* inexact coming from folded expression */ basic_value_t m_constval; /* for TYPE_ARRAY we have an optional vector * of constants when an initializer list @@ -204,41 +226,23 @@ struct ast_value : ast_expression std::vector m_initlist; /* usecount for the parser */ - size_t m_uses; + size_t m_uses = 0; - ir_value *m_ir_v; - ir_value **m_ir_values; - size_t m_ir_value_count; + ir_value *m_ir_v = nullptr; + ir_value **m_ir_values = nullptr; + size_t m_ir_value_count = 0; /* ONLY for arrays in progs version up to 6 */ - ast_value *m_setter; - ast_value *m_getter; + ast_value *m_setter = nullptr; + ast_value *m_getter = nullptr; - bool m_intrinsic; /* true if associated with intrinsic */ + bool m_intrinsic = false; /* true if associated with intrinsic */ }; -ast_value* ast_value_new(lex_ctx_t ctx, const char *name, qc_type qctype); -ast_value* ast_value_copy(const ast_value *self); -/* This will NOT delete an underlying ast_function */ -void ast_value_delete(ast_value*); - -bool ast_value_set_name(ast_value*, const char *name); - -/* -bool ast_value_codegen(ast_value*, ast_function*, bool lvalue, ir_value**); -bool ast_local_codegen(ast_value *self, ir_function *func, bool isparam); -*/ - bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield); -void ast_value_params_add(ast_value*, ast_value*); - -bool ast_compare_type(ast_expression *a, ast_expression *b); -ast_expression* ast_type_copy(lex_ctx_t ctx, const ast_expression *ex); -#define ast_type_adopt(a, b) ast_type_adopt_impl((ast_expression*)(a), (ast_expression*)(b)) -void ast_type_adopt_impl(ast_expression *self, const ast_expression *other); -void ast_type_to_string(ast_expression *e, char *buf, size_t bufsize); +void ast_type_to_string(const ast_expression *e, char *buf, size_t bufsize); enum ast_binary_ref { AST_REF_NONE = 0, @@ -254,16 +258,16 @@ enum ast_binary_ref { */ struct ast_binary : ast_expression { + ast_binary() = delete; + ast_binary(lex_ctx_t ctx, int op, ast_expression *l, ast_expression *r); + ~ast_binary(); + int m_op; ast_expression *m_left; ast_expression *m_right; ast_binary_ref m_refs; bool m_right_first; }; -ast_binary* ast_binary_new(lex_ctx_t ctx, - int op, - ast_expression *left, - ast_expression *right); /* Binstore * @@ -272,6 +276,10 @@ ast_binary* ast_binary_new(lex_ctx_t ctx, */ struct ast_binstore : ast_expression { + ast_binstore() = delete; + ast_binstore(lex_ctx_t ctx, int storeop, int mathop, ast_expression *l, ast_expression *r); + ~ast_binstore(); + int m_opstore; int m_opbin; ast_expression *m_dest; @@ -291,12 +299,14 @@ ast_binstore* ast_binstore_new(lex_ctx_t ctx, */ struct ast_unary : ast_expression { + ast_unary() = delete; + ~ast_unary(); 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); }; -ast_unary* ast_unary_new(lex_ctx_t ctx, - int op, - ast_expression *expr); /* Return * @@ -306,10 +316,11 @@ ast_unary* ast_unary_new(lex_ctx_t ctx, */ struct ast_return : ast_expression { + ast_return() = delete; + ast_return(lex_ctx_t ctx, ast_expression *expr); + ~ast_return(); ast_expression *m_operand; }; -ast_return* ast_return_new(lex_ctx_t ctx, - ast_expression *expr); /* Entity-field * @@ -326,13 +337,15 @@ ast_return* ast_return_new(lex_ctx_t ctx, */ struct ast_entfield : ast_expression { - /* The entity can come from an expression of course. */ + ast_entfield() = delete; + 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(); + // 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 */ + // As can the field, it just must result in a value of TYPE_FIELD ast_expression *m_field; }; -ast_entfield* ast_entfield_new(lex_ctx_t ctx, ast_expression *entity, ast_expression *field); -ast_entfield* ast_entfield_new_force(lex_ctx_t ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype); /* Member access: * diff --git a/parser.cpp b/parser.cpp index 7845a86..fcb782c 100644 --- a/parser.cpp +++ b/parser.cpp @@ -4376,7 +4376,7 @@ static ast_value* parser_create_array_setter_proto(parser_t *parser, ast_value * fval->m_next = (ast_expression*)ast_value_new(array->m_context, "", TYPE_VOID); index = ast_value_new(array->m_context, "index", TYPE_FLOAT); - value = ast_value_copy((ast_value*)array->m_next); + value = ast_value_from_type((ast_value*)array->m_next); if (!index || !value) { parseerror(parser, "failed to create locals for array accessor"); @@ -4442,7 +4442,7 @@ static bool parser_create_array_field_setter(parser_t *parser, ast_value *array, entity = ast_value_new(array->m_context, "entity", TYPE_ENTITY); index = ast_value_new(array->m_context, "index", TYPE_FLOAT); - value = ast_value_copy((ast_value*)array->m_next); + value = ast_value_from_type((ast_value*)array->m_next); if (!entity || !index || !value) { parseerror(parser, "failed to create locals for array accessor"); goto cleanup; @@ -4790,7 +4790,7 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va /* generate the basic type value */ if (cached_typedef) { - var = ast_value_copy(cached_typedef); + var = ast_value_from_type(cached_typedef); ast_value_set_name(var, ""); } else var = ast_value_new(ctx, "", parser_token(parser)->constval.t); @@ -4826,7 +4826,7 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va /* store the base if requested */ if (storebase) { - *storebase = ast_value_copy(var); + *storebase = ast_value_from_type(var); if (isfield) { tmp = ast_value_new(ctx, "", TYPE_FIELD); tmp->m_next = (ast_expression*)*storebase; @@ -5795,7 +5795,7 @@ another: parseerror(parser, "expected another variable"); break; } - var = ast_value_copy(basetype); + var = ast_value_from_type(basetype); cleanvar = true; ast_value_set_name(var, parser_tokval(parser)); if (!parser_next(parser)) {