X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=parser.cpp;h=c795e40a39c9c6dd6e8354b5a76e6d83ea394c0e;hp=fcb782c7ab04a0ad1458844571c869fce595b3a8;hb=e920766b10ebed3fc7fad0373aab6dde507e2341;hpb=90b5a6538a10f60d08ee3059b8f70e4e076dc30d diff --git a/parser.cpp b/parser.cpp index fcb782c..c795e40 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; } @@ -118,7 +139,7 @@ static ast_expression* parser_find_local(parser_t *parser, const char *name, siz hash = util_hthash(parser->htglobals, name); *isparam = false; - for (i = vec_size(parser->variables); i > upto;) { + for (i = parser->variables.size(); i > upto;) { --i; if ( (e = (ast_expression*)util_htgeth(parser->variables[i], name, hash)) ) return e; @@ -127,22 +148,30 @@ 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; ast_expression *v; - v = parser_find_local(parser, name, 0, &dummy); + v = parser_find_local(parser, name, PARSER_HT_LOCALS, &dummy); if (!v) v = parser_find_global(parser, 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; ast_value *e; hash = util_hthash(parser->typedefs[0], name); - for (i = vec_size(parser->typedefs); i > upto;) { + for (i = parser->typedefs.size(); i > upto;) { --i; if ( (e = (ast_value*)util_htgeth(parser->typedefs[i], name, hash)) ) return e; @@ -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,17 +282,38 @@ 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; } +static int store_op_for(ast_expression* expr) +{ + if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) && expr->m_vtype == TYPE_FIELD && expr->m_next->m_vtype == TYPE_VECTOR) { + if (ast_istype(expr, ast_entfield)) { + return type_storep_instr[TYPE_VECTOR]; + } else { + return type_store_instr[TYPE_VECTOR]; + } + } + + if (ast_istype(expr, ast_member) && ast_istype(((ast_member*)expr)->m_owner, ast_entfield)) { + return type_storep_instr[expr->m_vtype]; + } + + if (ast_istype(expr, ast_entfield)) { + return type_storep_instr[expr->m_vtype]; + } + + return type_store_instr[expr->m_vtype]; +} + static bool check_write_to(lex_ctx_t ctx, ast_expression *expr) { if (ast_istype(expr, ast_value)) { @@ -288,7 +342,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) const oper_info *op; lex_ctx_t ctx; ast_expression *out = nullptr; - ast_expression *exprs[3]; + ast_expression *exprs[3] = { 0, 0, 0 }; ast_block *blocks[3]; ast_binstore *asbinstore; size_t i, assignop, addop, subop; @@ -360,12 +414,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 +430,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 +456,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 +468,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 +497,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 +649,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 +716,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 +734,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 ); } @@ -695,10 +749,11 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) case opid2('|','|'): generated_op += 1; /* INSTR_OR */ + [[fallthrough]]; 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 +761,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 +772,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 +793,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 +813,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 +852,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) /* } */ ) /* } */ @@ -824,10 +879,13 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) case opid1('>'): generated_op += 1; /* INSTR_GT */ + [[fallthrough]]; case opid1('<'): generated_op += 1; /* INSTR_LT */ + [[fallthrough]]; case opid2('>', '='): generated_op += 1; /* INSTR_GE */ + [[fallthrough]]; case opid2('<', '='): generated_op += INSTR_LE; if (NotSameType(TYPE_FLOAT)) { @@ -863,15 +921,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) case opid1('='): if (ast_istype(exprs[0], ast_entfield)) { ast_expression *field = ((ast_entfield*)exprs[0])->m_field; - if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) && - exprs[0]->m_vtype == TYPE_FIELD && - exprs[0]->m_next->m_vtype == TYPE_VECTOR) - { - assignop = type_storep_instr[TYPE_VECTOR]; - } - else - assignop = type_storep_instr[exprs[0]->m_vtype]; - if (assignop == VINSTR_END || !ast_compare_type(field->m_next, exprs[1])) + assignop = store_op_for(exprs[0]); + 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)); @@ -888,22 +939,14 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } else { - if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) && - exprs[0]->m_vtype == TYPE_FIELD && - exprs[0]->m_next->m_vtype == TYPE_VECTOR) - { - assignop = type_store_instr[TYPE_VECTOR]; - } - else { - assignop = type_store_instr[exprs[0]->m_vtype]; - } + assignop = store_op_for(exprs[0]); if (assignop == VINSTR_END) { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); 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 +965,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 +981,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 +1007,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('+','='): @@ -991,20 +1034,17 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; } (void)check_write_to(ctx, exprs[0]); - if (ast_istype(exprs[0], ast_entfield)) - assignop = type_storep_instr[exprs[0]->m_vtype]; - else - assignop = type_store_instr[exprs[0]->m_vtype]; + assignop = store_op_for(exprs[0]); 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", @@ -1026,30 +1066,27 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; } (void)check_write_to(ctx, exprs[0]); - if (ast_istype(exprs[0], ast_entfield)) - assignop = type_storep_instr[exprs[0]->m_vtype]; - else - assignop = type_store_instr[exprs[0]->m_vtype]; + assignop = store_op_for(exprs[0]); 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: @@ -1070,18 +1107,15 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; } (void)check_write_to(ctx, exprs[0]); - if (ast_istype(exprs[0], ast_entfield)) - assignop = type_storep_instr[exprs[0]->m_vtype]; - else - assignop = type_store_instr[exprs[0]->m_vtype]; + assignop = store_op_for(exprs[0]); 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); @@ -1095,10 +1129,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) ty1, ty2); return false; } - if (ast_istype(exprs[0], ast_entfield)) - assignop = type_storep_instr[exprs[0]->m_vtype]; - else - assignop = type_store_instr[exprs[0]->m_vtype]; + assignop = store_op_for(exprs[0]); if (exprs[0]->m_vtype == TYPE_FLOAT) out = fold::binary(ctx, INSTR_BITAND, exprs[0], exprs[1]); else @@ -1107,11 +1138,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 +1169,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 +1232,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 +1243,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; @@ -1230,14 +1261,14 @@ static bool parser_close_call(parser_t *parser, shunt *sy) * intrinsic call and just evaluate it i.e constant fold it. */ if (fold && ast_istype(fun, ast_value) && ((ast_value*)fun)->m_intrinsic) { - ast_expression **exprs = nullptr; + std::vector exprs; ast_expression *foldval = nullptr; + exprs.reserve(paramcount); for (i = 0; i < paramcount; i++) - vec_push(exprs, sy->out[fid+1 + i].out); + exprs.push_back(sy->out[fid+1 + i].out); - if (!(foldval = parser->m_intrin.do_fold((ast_value*)fun, exprs))) { - vec_free(exprs); + if (!(foldval = parser->m_intrin.do_fold((ast_value*)fun, exprs.data()))) { goto fold_leave; } @@ -1247,13 +1278,12 @@ static bool parser_close_call(parser_t *parser, shunt *sy) */ sy->out[fid] = syexp(foldval->m_context, foldval); sy->out.erase(sy->out.end() - paramcount, sy->out.end()); - vec_free(exprs); return true; } 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 +1299,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 +1308,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 +1333,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 +1462,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 +1481,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 +1541,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 +1605,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 @@ -1635,13 +1665,16 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) } else { - if (ast_istype(var, ast_value)) { - ((ast_value*)var)->m_uses++; + // promote these to norefs + if (ast_istype(var, ast_value)) + { + ((ast_value *)var)->m_flags |= AST_FLAG_NOREF; } - else if (ast_istype(var, ast_member)) { - ast_member *mem = (ast_member*)var; + else if (ast_istype(var, ast_member)) + { + ast_member *mem = (ast_member *)var; if (ast_istype(mem->m_owner, ast_value)) - ((ast_value*)(mem->m_owner))->m_uses++; + ((ast_value *)mem->m_owner)->m_flags |= AST_FLAG_NOREF; } } sy->out.push_back(syexp(parser_ctx(parser), var)); @@ -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; } @@ -1960,11 +1993,11 @@ static ast_expression* parse_expression(parser_t *parser, bool stopatcomma, bool static void parser_enterblock(parser_t *parser) { - vec_push(parser->variables, util_htnew(PARSER_HT_SIZE)); - vec_push(parser->_blocklocals, vec_size(parser->_locals)); - vec_push(parser->typedefs, util_htnew(TYPEDEF_HT_SIZE)); - vec_push(parser->_blocktypedefs, vec_size(parser->_typedefs)); - vec_push(parser->_block_ctx, parser_ctx(parser)); + parser->variables.push_back(util_htnew(PARSER_HT_SIZE)); + parser->_blocklocals.push_back(parser->_locals.size()); + parser->typedefs.push_back(util_htnew(TYPEDEF_HT_SIZE)); + parser->_blocktypedefs.push_back(parser->_typedefs.size()); + parser->_block_ctx.push_back(parser_ctx(parser)); } static bool parser_leaveblock(parser_t *parser) @@ -1972,48 +2005,40 @@ static bool parser_leaveblock(parser_t *parser) bool rv = true; size_t locals, typedefs; - if (vec_size(parser->variables) <= PARSER_HT_LOCALS) { + if (parser->variables.size() <= PARSER_HT_LOCALS) { parseerror(parser, "internal error: parser_leaveblock with no block"); return false; } - util_htdel(vec_last(parser->variables)); + util_htdel(parser->variables.back()); - vec_pop(parser->variables); - if (!vec_size(parser->_blocklocals)) { + parser->variables.pop_back(); + if (!parser->_blocklocals.size()) { parseerror(parser, "internal error: parser_leaveblock with no block (2)"); return false; } - locals = vec_last(parser->_blocklocals); - vec_pop(parser->_blocklocals); - while (vec_size(parser->_locals) != locals) { - ast_expression *e = vec_last(parser->_locals); - ast_value *v = (ast_value*)e; - vec_pop(parser->_locals); - if (ast_istype(e, ast_value) && !v->m_uses) { - if (compile_warning(v->m_context, WARN_UNUSED_VARIABLE, "unused variable: `%s`", v->m_name)) - rv = false; - } - } + locals = parser->_blocklocals.back(); + parser->_blocklocals.pop_back(); + parser->_locals.resize(locals); - typedefs = vec_last(parser->_blocktypedefs); - while (vec_size(parser->_typedefs) != typedefs) { - ast_delete(vec_last(parser->_typedefs)); - vec_pop(parser->_typedefs); - } - util_htdel(vec_last(parser->typedefs)); - vec_pop(parser->typedefs); + typedefs = parser->_blocktypedefs.back(); + parser->_typedefs.resize(typedefs); + util_htdel(parser->typedefs.back()); + parser->typedefs.pop_back(); - vec_pop(parser->_block_ctx); + parser->_block_ctx.pop_back(); return rv; } static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e) { - vec_push(parser->_locals, e); - util_htset(vec_last(parser->variables), name, (void*)e); + parser->_locals.push_back(e); + util_htset(parser->variables.back(), 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) @@ -2021,6 +2046,9 @@ static void parser_addglobal(parser_t *parser, const char *name, ast_expression 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 +2065,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 +2081,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 +2097,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 +2161,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 +2180,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 +2237,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 +2289,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 +2333,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 +2362,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 +2385,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 +2458,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 { @@ -2489,8 +2512,7 @@ static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **ou parseerror(parser, "expected for-loop condition"); goto onerr; } - } - else if (!parser_next(parser)) { + } else if (!parser_next(parser)) { parseerror(parser, "expected for-loop condition"); goto onerr; } @@ -2501,7 +2523,6 @@ static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **ou if (!cond) goto onerr; } - /* move on to incrementor */ if (parser->tok != ';') { parseerror(parser, "expected semicolon after for-loop initializer"); @@ -2542,11 +2563,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 +2620,13 @@ 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; + parser->function->m_return_value->m_flags |= AST_FLAG_NOREF; } - 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 +2634,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 +2659,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 +2677,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 +2732,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 +3013,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 +3049,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 +3079,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 +3087,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,18 +3105,65 @@ 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 (!operand->compareType(*swcase.m_value)) { + char ty1[1024]; + char ty2[1024]; + + ast_type_to_string(swcase.m_value, ty1, sizeof ty1); + ast_type_to_string(operand, ty2, sizeof ty2); + + auto fnLiteral = [](ast_expression *expression) -> char* { + if (!ast_istype(expression, ast_value)) + return nullptr; + ast_value *value = (ast_value *)expression; + if (!value->m_hasvalue) + return nullptr; + char *string = nullptr; + basic_value_t *constval = &value->m_constval; + switch (value->m_vtype) + { + case TYPE_FLOAT: + util_asprintf(&string, "%.2f", constval->vfloat); + return string; + case TYPE_VECTOR: + util_asprintf(&string, "'%.2f %.2f %.2f'", + constval->vvec.x, + constval->vvec.y, + constval->vvec.z); + return string; + case TYPE_STRING: + util_asprintf(&string, "\"%s\"", constval->vstring); + return string; + default: + break; + } + return nullptr; + }; + + char *literal = fnLiteral(swcase.m_value); + if (literal) + compile_error(parser_ctx(parser), "incompatible type `%s` for switch case `%s` expected `%s`", ty1, literal, ty2); + else + compile_error(parser_ctx(parser), "incompatible type `%s` for switch case expected `%s`", ty1, ty2); + mem_d(literal); + delete switchnode; + return false; + } + if (!swcase.m_value) { - ast_delete(switchnode); + delete switchnode; parseerror(parser, "expected expression for case"); return false; } if (!OPTS_FLAG(RELAXED_SWITCH)) { if (!ast_istype(swcase.m_value, ast_value)) { /* || ((ast_value*)swcase.m_value)->m_cvq != CV_CONST) { */ + delete switchnode; parseerror(parser, "case on non-constant values need to be explicitly enabled via -frelaxed-switch"); ast_unref(operand); return false; @@ -3104,13 +3173,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 +3187,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 +3218,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 +3234,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 +3270,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 +3312,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 +3334,7 @@ static bool parse_goto(parser_t *parser, ast_expression **out) return false; } - *out = (ast_expression*)gt; + *out = gt; return true; } @@ -3392,8 +3461,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 +3548,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 +3572,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; } @@ -3548,9 +3617,9 @@ static bool parse_enum(parser_t *parser) bool flag = false; bool reverse = false; qcfloat_t num = 0; - ast_value **values = nullptr; ast_value *var = nullptr; ast_value *asvalue; + std::vector values; ast_expression *old; @@ -3592,7 +3661,7 @@ static bool parse_enum(parser_t *parser) break; } parseerror(parser, "expected identifier or `}`"); - goto onerror; + return false; } old = parser_find_field(parser, parser_tokval(parser)); @@ -3601,21 +3670,21 @@ static bool parse_enum(parser_t *parser) if (old) { parseerror(parser, "value `%s` has already been declared here: %s:%i", parser_tokval(parser), old->m_context.file, old->m_context.line); - goto onerror; + return false; } - var = ast_value_new(parser_ctx(parser), parser_tokval(parser), TYPE_FLOAT); - vec_push(values, var); + var = new ast_value(parser_ctx(parser), parser_tokval(parser), TYPE_FLOAT); + values.push_back(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"); - goto onerror; + return false; } if (parser->tok == ',') @@ -3624,12 +3693,12 @@ static bool parse_enum(parser_t *parser) break; if (parser->tok != '=') { parseerror(parser, "expected `=`, `}` or comma after identifier"); - goto onerror; + return false; } if (!parser_next(parser)) { parseerror(parser, "expected expression after `=`"); - goto onerror; + return false; } /* We got a value! */ @@ -3637,7 +3706,7 @@ static bool parse_enum(parser_t *parser) asvalue = (ast_value*)old; if (!ast_istype(old, ast_value) || asvalue->m_cvq != CV_CONST || !asvalue->m_hasvalue) { compile_error(var->m_context, "constant value or expression expected"); - goto onerror; + return false; } num = (var->m_constval.vfloat = asvalue->m_constval.vfloat) + 1; @@ -3645,38 +3714,33 @@ static bool parse_enum(parser_t *parser) break; if (parser->tok != ',') { parseerror(parser, "expected `}` or comma after expression"); - goto onerror; + return false; } } /* patch them all (for reversed attribute) */ if (reverse) { size_t i; - for (i = 0; i < vec_size(values); i++) - values[i]->m_constval.vfloat = vec_size(values) - i - 1; + for (i = 0; i < values.size(); i++) + values[i]->m_constval.vfloat = values.size() - i - 1; } if (parser->tok != '}') { parseerror(parser, "internal error: breaking without `}`"); - goto onerror; + return false; } if (!parser_next(parser) || parser->tok != ';') { parseerror(parser, "expected semicolon after enumeration"); - goto onerror; + return false; } if (!parser_next(parser)) { parseerror(parser, "parse error after enumeration"); - goto onerror; + return false; } - vec_free(values); return true; - -onerror: - vec_free(values); - return false; } static bool parse_block_into(parser_t *parser, ast_block *block) @@ -3703,8 +3767,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 +3789,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 +3802,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 +3811,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 +3828,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 +3926,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 +3981,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 +3993,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 +4015,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 +4066,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 +4075,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 +4109,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; } @@ -4095,7 +4159,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) parser->function = old; if (!parser_leaveblock(parser)) retval = false; - if (vec_size(parser->variables) != PARSER_HT_LOCALS) { + if (parser->variables.size() != PARSER_HT_LOCALS) { parseerror(parser, "internal error: local scopes left"); retval = false; } @@ -4109,7 +4173,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 +4196,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 +4236,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 +4302,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 +4362,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 +4389,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 +4434,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 +4461,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 +4499,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 +4520,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 +4548,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 +4571,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 +4593,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 +4602,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 +4642,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 +4660,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 +4688,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 +4704,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 +4718,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 +4729,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 +4740,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 +4751,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 +4763,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 +4849,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 +4867,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 +4885,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 +4904,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 +4925,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 +4945,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 +4963,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 +4974,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))) ) { + if ( (oldtype = parser_find_typedef(parser, typevar->m_name, parser->_blocktypedefs.back())) ) { 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); + parser->_typedefs.emplace_back(typevar); + util_htset(parser->typedefs.back(), typevar->m_name.c_str(), typevar); if (parser->tok != ';') { parseerror(parser, "expected semicolon after typedef"); @@ -4987,10 +5041,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 +5132,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 +5207,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,13 +5217,13 @@ 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")) { - var->m_uses++; + if (var->m_name == "end_sys_globals") { + var->m_flags |= AST_FLAG_NOREF; parser->crc_globals = parser->globals.size(); was_end = true; } - else if (!strcmp(var->m_name, "end_sys_fields")) { - var->m_uses++; + else if (var->m_name == "end_sys_fields") { + var->m_flags |= AST_FLAG_NOREF; parser->crc_fields = parser->fields.size(); was_end = true; } @@ -5194,7 +5248,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 +5282,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 +5291,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 +5336,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 && @@ -5301,7 +5353,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield } else /* it's not a global */ { - old = parser_find_local(parser, var->m_name, vec_size(parser->variables)-1, &isparam); + old = parser_find_local(parser, var->m_name, parser->variables.size()-1, &isparam); if (old && !isparam) { parseerror(parser, "local `%s` already declared here: %s:%i", var->m_name, old->m_context.file, (int)old->m_context.line); @@ -5320,7 +5372,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 { @@ -5331,9 +5383,8 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield } } - /* in a noref section we simply bump the usecount */ if (noref || parser->noref) - var->m_uses++; + var->m_flags |= AST_FLAG_NOREF; /* Part 2: * Create the global/local, and deal with vector types. @@ -5356,21 +5407,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 +5432,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 +5445,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 +5467,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(parser->variables.back(), 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(parser->variables.back(), me[i]->m_name.c_str(), (void*)(me[i])); + me[i]->m_name = 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 +5553,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 +5679,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 +5694,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 +5725,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(); @@ -5707,24 +5748,24 @@ skipvar: /* remove it from the current locals */ if (isvector) { for (i = 0; i < 3; ++i) { - vec_pop(parser->_locals); + parser->_locals.pop_back(); localblock->m_collect.pop_back(); } } /* do sanity checking, this function really needs refactoring */ - if (vec_last(parser->_locals) != (ast_expression*)var) + if (parser->_locals.back() != var) parseerror(parser, "internal error: unexpected change in local variable handling"); else - vec_pop(parser->_locals); + parser->_locals.pop_back(); if (localblock->m_locals.back() != var) parseerror(parser, "internal error: unexpected change in local variable handling (2)"); 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; } @@ -5744,7 +5785,10 @@ skipvar: var->m_cvq = CV_CONST; } if (cval == parser->nil) + { var->m_flags |= AST_FLAG_INITIALIZED; + var->m_flags |= AST_FLAG_NOREF; + } else { var->m_hasvalue = true; @@ -5762,15 +5806,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 +5839,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 +5859,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 +5986,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,28 +6003,79 @@ 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"); ir->m_code->crc = crc; } +parser_t::parser_t() + : lex(nullptr) + , tok(0) + , ast_cleaned(false) + , translated(0) + , crc_globals(0) + , crc_fields(0) + , function(nullptr) + , aliases(util_htnew(PARSER_HT_SIZE)) + , htfields(util_htnew(PARSER_HT_SIZE)) + , htglobals(util_htnew(PARSER_HT_SIZE)) + , assign_op(nullptr) + , noref(false) + , max_param_count(1) + // finish initializing the rest of the parser before initializing + // m_fold and m_intrin with the parser passed along + , m_fold() + , m_intrin() +{ + variables.push_back(htfields); + variables.push_back(htglobals); + typedefs.push_back(util_htnew(TYPEDEF_HT_SIZE)); + _blocktypedefs.push_back(0); + + lex_ctx_t empty_ctx; + empty_ctx.file = ""; + empty_ctx.line = 0; + empty_ctx.column = 0; + nil = new ast_value(empty_ctx, "nil", TYPE_NIL); + nil->m_cvq = CV_CONST; + if (OPTS_FLAG(UNTYPED_NIL)) + util_htset(htglobals, "nil", (void*)nil); + + const_vec[0] = new ast_value(empty_ctx, "", TYPE_NOEXPR); + const_vec[1] = new ast_value(empty_ctx, "", TYPE_NOEXPR); + const_vec[2] = new ast_value(empty_ctx, "", TYPE_NOEXPR); + + if (OPTS_OPTION_BOOL(OPTION_ADD_INFO)) { + reserved_version = new ast_value(empty_ctx, "reserved:version", TYPE_STRING); + reserved_version->m_cvq = CV_CONST; + reserved_version->m_hasvalue = true; + reserved_version->m_flags |= AST_FLAG_INCLUDE_DEF; + reserved_version->m_flags |= AST_FLAG_NOREF; + reserved_version->m_constval.vstring = util_strdup(GMQCC_FULL_VERSION_STRING); + } else { + reserved_version = nullptr; + } + + m_fold = fold(this); + m_intrin = intrin(this); +} + +parser_t::~parser_t() +{ + remove_ast(); +} + parser_t *parser_create() { parser_t *parser; - lex_ctx_t empty_ctx; size_t i; - parser = (parser_t*)mem_a(sizeof(parser_t)); + parser = new parser_t; if (!parser) return nullptr; - memset(parser, 0, sizeof(*parser)); - - // TODO: remove - new (parser) parser_t(); - for (i = 0; i < operator_count; ++i) { if (operators[i].id == opid1('=')) { parser->assign_op = operators+i; @@ -5989,43 +6084,10 @@ parser_t *parser_create() } if (!parser->assign_op) { con_err("internal error: initializing parser: failed to find assign operator\n"); - mem_d(parser); + delete parser; return nullptr; } - vec_push(parser->variables, parser->htfields = util_htnew(PARSER_HT_SIZE)); - vec_push(parser->variables, parser->htglobals = util_htnew(PARSER_HT_SIZE)); - vec_push(parser->typedefs, util_htnew(TYPEDEF_HT_SIZE)); - vec_push(parser->_blocktypedefs, 0); - - parser->aliases = util_htnew(PARSER_HT_SIZE); - - empty_ctx.file = ""; - empty_ctx.line = 0; - empty_ctx.column = 0; - parser->nil = ast_value_new(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); - - if (OPTS_OPTION_BOOL(OPTION_ADD_INFO)) { - parser->reserved_version = ast_value_new(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; - parser->reserved_version->m_constval.vstring = util_strdup(GMQCC_FULL_VERSION_STRING); - } else { - parser->reserved_version = nullptr; - } - - parser->m_fold = fold(parser); - parser->m_intrin = intrin(parser); return parser; } @@ -6081,54 +6143,42 @@ bool parser_compile_string(parser_t *parser, const char *name, const char *str, return parser_compile(parser); } -static void parser_remove_ast(parser_t *parser) +void parser_t::remove_ast() { - size_t i; - if (parser->ast_cleaned) + if (ast_cleaned) return; - parser->ast_cleaned = true; - for (auto &it : parser->accessors) { - ast_delete(it->m_constval.vfunc); + ast_cleaned = true; + for (auto &it : accessors) { + 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 : functions) delete it; + for (auto &it : globals) delete it; + for (auto &it : fields) delete it; - for (i = 0; i < vec_size(parser->variables); ++i) - util_htdel(parser->variables[i]); - vec_free(parser->variables); - vec_free(parser->_blocklocals); - vec_free(parser->_locals); + for (auto &it : variables) util_htdel(it); + variables.clear(); + _blocklocals.clear(); + _locals.clear(); - for (i = 0; i < vec_size(parser->_typedefs); ++i) - ast_delete(parser->_typedefs[i]); - vec_free(parser->_typedefs); - for (i = 0; i < vec_size(parser->typedefs); ++i) - util_htdel(parser->typedefs[i]); - vec_free(parser->typedefs); - vec_free(parser->_blocktypedefs); + _typedefs.clear(); + for (auto &it : typedefs) util_htdel(it); + typedefs.clear(); + _blocktypedefs.clear(); - vec_free(parser->_block_ctx); + _block_ctx.clear(); - ast_value_delete(parser->nil); + delete nil; - ast_value_delete(parser->const_vec[0]); - ast_value_delete(parser->const_vec[1]); - ast_value_delete(parser->const_vec[2]); + delete const_vec[0]; + delete const_vec[1]; + delete const_vec[2]; - if (parser->reserved_version) - ast_value_delete(parser->reserved_version); - - util_htdel(parser->aliases); -} + if (reserved_version) + delete reserved_version; -void parser_cleanup(parser_t *parser) -{ - parser_remove_ast(parser); - parser->~parser_t(); - mem_d(parser); + util_htdel(aliases); } static bool parser_set_coverage_func(parser_t *parser, ir_builder *ir) { @@ -6141,7 +6191,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 +6206,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 +6243,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; } @@ -6203,12 +6253,12 @@ bool parser_finish(parser_t *parser, const char *output) ast_expression *subtype; field->m_hasvalue = true; subtype = field->m_next; - ifld = ir_builder_create_field(ir, field->m_name, subtype->m_vtype); + ifld = ir->createField(field->m_name, subtype->m_vtype); if (subtype->m_vtype == TYPE_FIELD) ifld->m_fieldtype = subtype->m_next->m_vtype; else if (subtype->m_vtype == TYPE_FUNCTION) ifld->m_outtype = subtype->m_next->m_vtype; - (void)!ir_value_set_field(field->m_ir_v, ifld); + (void)!field->m_ir_v->setField(ifld); } } for (auto &it : parser->globals) { @@ -6216,12 +6266,12 @@ bool parser_finish(parser_t *parser, const char *output) if (!ast_istype(it, ast_value)) continue; asvalue = (ast_value*)it; - if (!asvalue->m_uses && !asvalue->m_hasvalue && asvalue->m_vtype != TYPE_FUNCTION) { + if (!(asvalue->m_flags & AST_FLAG_NOREF) && asvalue->m_cvq != CV_CONST && asvalue->m_vtype != TYPE_FUNCTION) { 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 +6283,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 +6320,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; } @@ -6305,31 +6354,38 @@ bool parser_finish(parser_t *parser, const char *output) generate_checksum(parser, ir); if (OPTS_OPTION_BOOL(OPTION_DUMP)) - ir_builder_dump(ir, con_out); + ir->dump(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; } } - parser_remove_ast(parser); + parser->remove_ast(); - if (compile_Werrors) { - con_out("*** there were warnings treated as errors\n"); - compile_show_werrors(); - retval = false; - } + auto fnCheckWErrors = [&retval]() { + if (compile_Werrors) { + con_out("*** there were warnings treated as errors\n"); + compile_show_werrors(); + retval = false; + } + }; + + fnCheckWErrors(); if (retval) { if (OPTS_OPTION_BOOL(OPTION_DUMPFIN)) - ir_builder_dump(ir, con_out); + ir->dump(con_out); - if (!ir_builder_generate(ir, output)) { + if (!ir->generate(output)) { con_out("*** failed to generate output file\n"); delete ir; return false; } + + // ir->generate can generate compiler warnings + fnCheckWErrors(); } delete ir; return retval;