#include "gmqcc.h"
#include "ast.h"
-#include "parser.h"
+#include "fold.h"
+//#include "parser.h"
#define ast_instantiate(T, ctx, destroyfn) \
T* self = (T*)mem_a(sizeof(T)); \
if (!self) { \
- return NULL; \
+ return nullptr; \
} \
new (self) T(); \
ast_node_init((ast_node*)self, ctx, TYPE_##T); \
}
/* Initialize main ast node aprts */
-static void ast_node_init(ast_node *self, lex_ctx_t ctx, int nodetype)
+static void ast_node_init(ast_node *self, lex_ctx_t ctx, int node_type)
{
self->context = ctx;
- self->destroy = &_ast_node_destroy;
- self->keep = false;
- self->nodetype = nodetype;
+ self->destroy = &_ast_node_destroy;
+ self->keep_node = false;
+ self->node_type = node_type;
self->side_effects = false;
}
{
self->codegen = codegen;
self->vtype = TYPE_VOID;
- self->next = NULL;
- self->outl = NULL;
- self->outr = NULL;
+ self->next = nullptr;
+ self->outl = nullptr;
+ self->outr = nullptr;
self->count = 0;
- self->varparam = NULL;
+ self->varparam = nullptr;
self->flags = 0;
if (OPTS_OPTION_BOOL(OPTION_COVERAGE))
self->flags |= AST_FLAG_BLOCK_COVERAGE;
{
const ast_expression *fromex;
ast_expression *selfex;
- ast_value *cp = ast_value_new(self->expression.node.context, self->name, self->expression.vtype);
+ ast_value *cp = ast_value_new(self->expression.context, self->name, self->expression.vtype);
if (self->expression.next) {
- cp->expression.next = ast_type_copy(self->expression.node.context, self->expression.next);
+ cp->expression.next = ast_type_copy(self->expression.context, self->expression.next);
}
fromex = &self->expression;
selfex = &cp->expression;
static ast_expression* ast_shallow_type(lex_ctx_t ctx, int vtype)
{
ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
- ast_expression_init(self, NULL);
- self->codegen = NULL;
- self->next = NULL;
+ ast_expression_init(self, nullptr);
+ self->codegen = nullptr;
+ self->next = nullptr;
self->vtype = vtype;
return self;
}
ast_expression *selfex;
if (!ex)
- return NULL;
+ return nullptr;
else
{
ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
- ast_expression_init(self, NULL);
+ ast_expression_init(self, nullptr);
fromex = ex;
selfex = self;
/* This may never be codegen()d */
- selfex->codegen = NULL;
+ selfex->codegen = nullptr;
selfex->vtype = fromex->vtype;
if (fromex->next)
selfex->next = ast_type_copy(ctx, fromex->next);
else
- selfex->next = NULL;
+ selfex->next = nullptr;
selfex->count = fromex->count;
selfex->flags = fromex->flags;
ast_instantiate(ast_value, ctx, ast_value_delete);
ast_expression_init((ast_expression*)self,
(ast_expression_codegen*)&ast_value_codegen);
- self->expression.node.keep = true; /* keep */
+ self->expression.keep_node = true; /* keep */
- self->name = name ? util_strdup(name) : NULL;
+ self->name = name ? util_strdup(name) : nullptr;
self->expression.vtype = t;
- self->expression.next = NULL;
+ self->expression.next = nullptr;
self->isfield = false;
self->cvq = CV_NONE;
self->hasvalue = false;
self->inexact = false;
self->uses = 0;
memset(&self->constval, 0, sizeof(self->constval));
- self->initlist = NULL;
- self->ir_v = NULL;
- self->ir_values = NULL;
+ self->ir_v = nullptr;
+ self->ir_values = nullptr;
self->ir_value_count = 0;
- self->setter = NULL;
- self->getter = NULL;
- self->desc = NULL;
+ self->setter = nullptr;
+ self->getter = nullptr;
+ self->desc = nullptr;
- self->argcounter = NULL;
+ self->argcounter = nullptr;
self->intrinsic = false;
return self;
break;
case TYPE_FUNCTION:
/* unlink us from the function node */
- self->constval.vfunc->vtype = NULL;
+ self->constval.vfunc->vtype = nullptr;
break;
/* NOTE: delete function? currently collected in
* the parser structure
if (self->desc)
mem_d(self->desc);
- if (self->initlist) {
- if (self->expression.next->vtype == TYPE_STRING) {
- /* strings are allocated, free them */
- size_t i, len = vec_size(self->initlist);
- /* in theory, len should be expression.count
- * but let's not take any chances */
- for (i = 0; i < len; ++i) {
- if (self->initlist[i].vstring)
- mem_d(self->initlist[i].vstring);
- }
- }
- vec_free(self->initlist);
+ // initlist imples an array which implies .next in the expression exists.
+ if (self->initlist.size() && self->expression.next->vtype == TYPE_STRING) {
+ for (auto &it : self->initlist)
+ if (it.vstring)
+ mem_d(it.vstring);
}
ast_expression_delete((ast_expression*)self);
{
if (field->vtype != TYPE_FIELD) {
compile_error(ctx, "ast_entfield_new with expression not of type field");
- return NULL;
+ return nullptr;
}
return ast_entfield_new_force(ctx, entity, field, field->next);
}
if (!outtype) {
mem_d(self);
/* Error: field has no type... */
- return NULL;
+ return nullptr;
}
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_entfield_codegen);
ast_instantiate(ast_member, ctx, ast_member_delete);
if (field >= 3) {
mem_d(self);
- return NULL;
+ return nullptr;
}
if (owner->vtype != TYPE_VECTOR &&
owner->vtype != TYPE_FIELD) {
compile_error(ctx, "member-access on an invalid owner of type %s", type_name[owner->vtype]);
mem_d(self);
- return NULL;
+ return nullptr;
}
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_member_codegen);
- self->expression.node.keep = true; /* keep */
+ self->expression.keep_node = true; /* keep */
if (owner->vtype == TYPE_VECTOR) {
self->expression.vtype = TYPE_FLOAT;
- self->expression.next = NULL;
+ self->expression.next = nullptr;
} else {
self->expression.vtype = TYPE_FIELD;
self->expression.next = ast_shallow_type(ctx, TYPE_FLOAT);
if (name)
self->name = util_strdup(name);
else
- self->name = NULL;
+ self->name = nullptr;
return self;
}
void ast_member_delete(ast_member *self)
{
- /* The owner is always an ast_value, which has .keep=true,
+ /* The owner is always an ast_value, which has .keep_node=true,
* also: ast_members are usually deleted after the owner, thus
* this will cause invalid access
ast_unref(self->owner);
if (!outtype) {
mem_d(self);
/* Error: field has no type... */
- return NULL;
+ return nullptr;
}
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_array_index_codegen);
if (self->expression.vtype != TYPE_ARRAY) {
compile_error(ast_ctx(self), "array_index node on type");
ast_array_index_delete(self);
- return NULL;
+ return nullptr;
}
self->array = outtype;
self->expression.vtype = TYPE_FIELD;
if (!ontrue && !onfalse) {
/* because it is invalid */
mem_d(self);
- return NULL;
+ return nullptr;
}
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_ifthen_codegen);
{
ast_expression *exprtype = ontrue;
ast_instantiate(ast_ternary, ctx, ast_ternary_delete);
- /* This time NEITHER must be NULL */
+ /* This time NEITHER must be nullptr */
if (!ontrue || !onfalse) {
mem_d(self);
- return NULL;
+ return nullptr;
}
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_ternary_codegen);
void ast_ternary_delete(ast_ternary *self)
{
/* the if()s are only there because computed-gotos can set them
- * to NULL
+ * to nullptr
*/
if (self->cond) ast_unref(self->cond);
if (self->on_true) ast_unref(self->on_true);
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_switch_codegen);
self->operand = op;
- self->cases = NULL;
ast_propagate_effects(self, op);
void ast_switch_delete(ast_switch *self)
{
- size_t i;
ast_unref(self->operand);
- for (i = 0; i < vec_size(self->cases); ++i) {
- if (self->cases[i].value)
- ast_unref(self->cases[i].value);
- ast_unref(self->cases[i].code);
+ for (auto &it : self->cases) {
+ if (it.value)
+ ast_unref(it.value);
+ ast_unref(it.code);
}
- vec_free(self->cases);
ast_expression_delete((ast_expression*)self);
mem_d(self);
self->expression.vtype = TYPE_NOEXPR;
self->name = util_strdup(name);
- self->irblock = NULL;
+ self->irblock = nullptr;
self->undefined = undefined;
return self;
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_goto_codegen);
self->name = util_strdup(name);
- self->target = NULL;
- self->irblock_from = NULL;
+ self->target = nullptr;
+ self->irblock_from = nullptr;
return self;
}
if (!funcexpr->next) {
compile_error(ctx, "not a function");
mem_d(self);
- return NULL;
+ return nullptr;
}
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_call_codegen);
ast_side_effects(self) = true;
self->func = funcexpr;
- self->va_count = NULL;
+ self->va_count = nullptr;
ast_type_adopt(self, funcexpr->next);
self->exprs.push_back(e);
if (self->expression.next) {
ast_delete(self->expression.next);
- self->expression.next = NULL;
+ self->expression.next = nullptr;
}
ast_type_adopt(self, e);
return true;
void ast_block_collect(ast_block *self, ast_expression *expr)
{
self->collect.push_back(expr);
- expr->node.keep = true;
+ expr->keep_node = true;
}
void ast_block_delete(ast_block *self)
}
self->vtype = vtype;
- self->name = name ? util_strdup(name) : NULL;
- self->blocks = NULL;
+ self->name = name ? util_strdup(name) : nullptr;
self->labelcount = 0;
self->builtin = 0;
- self->ir_func = NULL;
- self->curblock = NULL;
-
- self->breakblocks = NULL;
- self->continueblocks = NULL;
+ self->ir_func = nullptr;
+ self->curblock = nullptr;
vtype->hasvalue = true;
vtype->constval.vfunc = self;
- self->varargs = NULL;
- self->argc = NULL;
- self->fixedparams = NULL;
- self->return_value = NULL;
-
- self->static_names = NULL;
+ self->varargs = nullptr;
+ self->argc = nullptr;
+ self->fixedparams = nullptr;
+ self->return_value = nullptr;
self->static_count = 0;
return self;
cleanup:
mem_d(self);
- return NULL;
+ return nullptr;
}
void ast_function_delete(ast_function *self)
{
- size_t i;
if (self->name)
mem_d((void*)self->name);
if (self->vtype) {
/* ast_value_delete(self->vtype); */
self->vtype->hasvalue = false;
- self->vtype->constval.vfunc = NULL;
+ self->vtype->constval.vfunc = nullptr;
/* We use unref - if it was stored in a global table it is supposed
* to be deleted from *there*
*/
ast_unref(self->vtype);
}
- for (i = 0; i < vec_size(self->static_names); ++i)
- mem_d(self->static_names[i]);
- vec_free(self->static_names);
- for (i = 0; i < vec_size(self->blocks); ++i)
- ast_delete(self->blocks[i]);
- vec_free(self->blocks);
- vec_free(self->breakblocks);
- vec_free(self->continueblocks);
+ for (auto &it : self->static_names)
+ mem_d(it);
+ for (auto &it : self->blocks)
+ ast_delete(it);
if (self->varargs)
ast_delete(self->varargs);
if (self->argc)
!OPTS_OPTION_BOOL(OPTION_DUMPFIN) &&
!OPTS_OPTION_BOOL(OPTION_DEBUG))
{
- return NULL;
+ return nullptr;
}
id = (self->labelcount++);
/*********************************************************************/
/* AST codegen part
- * by convention you must never pass NULL to the 'ir_value **out'
+ * by convention you must never pass nullptr to the 'ir_value **out'
* parameter. If you really don't care about the output, pass a dummy.
* But I can't imagine a pituation where the output is truly unnecessary.
*/
static bool ast_global_array_set(ast_value *self)
{
- size_t count = vec_size(self->initlist);
+ size_t count = self->initlist.size();
size_t i;
if (count > self->expression.count) {
static bool check_array(ast_value *self, ast_value *array)
{
- if (array->expression.flags & AST_FLAG_ARRAY_INIT && !array->initlist) {
+ if (array->expression.flags & AST_FLAG_ARRAY_INIT && array->initlist.empty()) {
compile_error(ast_ctx(self), "array without size: %s", self->name);
return false;
}
bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
{
- ir_value *v = NULL;
+ ir_value *v = nullptr;
if (self->expression.vtype == TYPE_NIL) {
compile_error(ast_ctx(self), "internal error: trying to generate a variable of TYPE_NIL");
static bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
{
- ir_value *v = NULL;
+ ir_value *v = nullptr;
if (self->expression.vtype == TYPE_NIL) {
compile_error(ast_ctx(self), "internal error: trying to generate a variable of TYPE_NIL");
ast_expression *ec;
ast_expression_codegen *cgen;
- size_t i;
-
(void)ir;
irf = self->ir_func;
return false;
}
- if (!vec_size(self->blocks)) {
+ if (self->blocks.empty()) {
compile_error(ast_ctx(self), "function `%s` has no body", self->name);
return false;
}
}
}
- for (i = 0; i < vec_size(self->blocks); ++i) {
- cgen = self->blocks[i]->expression.codegen;
- if (!(*cgen)((ast_expression*)self->blocks[i], self, false, &dummy))
+ for (auto &it : self->blocks) {
+ cgen = it->expression.codegen;
+ if (!(*cgen)((ast_expression*)it, self, false, &dummy))
return false;
}
if (!self->vtype->expression.next ||
self->vtype->expression.next->vtype == TYPE_VOID)
{
- return ir_block_create_return(self->curblock, ast_ctx(self), NULL);
+ return ir_block_create_return(self->curblock, ast_ctx(self), nullptr);
}
else if (vec_size(self->curblock->entries) || self->curblock == irf->first)
{
{
return false;
}
- return ir_block_create_return(self->curblock, ast_ctx(self), NULL);
+ return ir_block_create_return(self->curblock, ast_ctx(self), nullptr);
}
}
return true;
return true;
}
- /* output is NULL at first, we'll have each expression
+ /* output is nullptr at first, we'll have each expression
* assign to out output, thus, a comma-operator represention
* using an ast_block will return the last generated value,
* so: (b, c) + a executed both b and c, and returns c,
* which is then added to a.
*/
- *out = NULL;
+ *out = nullptr;
/* generate locals */
for (auto &it : self->locals) {
bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_value **out)
{
ast_expression_codegen *cgen;
- ir_value *left = NULL;
- ir_value *right = NULL;
+ ir_value *left = nullptr;
+ ir_value *right = nullptr;
ast_value *arr;
ast_value *idx = 0;
- ast_array_index *ai = NULL;
+ ast_array_index *ai = nullptr;
if (lvalue && self->expression.outl) {
*out = self->expression.outl;
idx = (ast_value*)ai->index;
if (ast_istype(ai->index, ast_value) && idx->hasvalue && idx->cvq == CV_CONST)
- ai = NULL;
+ ai = nullptr;
}
if (ai) {
bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, ir_value **out)
{
ast_expression_codegen *cgen;
- ir_value *leftl = NULL, *leftr, *right, *bin;
+ ir_value *leftl = nullptr, *leftr, *right, *bin;
ast_value *arr;
ast_value *idx = 0;
- ast_array_index *ai = NULL;
- ir_value *iridx = NULL;
+ ast_array_index *ai = nullptr;
+ ir_value *iridx = nullptr;
if (lvalue && self->expression.outl) {
*out = self->expression.outl;
idx = (ast_value*)ai->index;
if (ast_istype(ai->index, ast_value) && idx->hasvalue && idx->cvq == CV_CONST)
- ai = NULL;
+ ai = nullptr;
}
/* for a binstore we need both an lvalue and an rvalue for the left side */
ast_expression_codegen *cgen;
ir_value *operand;
- *out = NULL;
+ *out = nullptr;
/* In the context of a return operation, we don't actually return
* anything...
if (!ir_block_create_return(func->curblock, ast_ctx(self), operand))
return false;
} else {
- if (!ir_block_create_return(func->curblock, ast_ctx(self), NULL))
+ if (!ir_block_create_return(func->curblock, ast_ctx(self), nullptr))
return false;
}
*out = ir_value_vector_member(vec, self->field);
self->expression.outl = *out;
- return (*out != NULL);
+ return (*out != nullptr);
}
bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lvalue, ir_value **out)
bool ast_argpipe_codegen(ast_argpipe *self, ast_function *func, bool lvalue, ir_value **out)
{
- *out = NULL;
+ *out = nullptr;
if (lvalue) {
compile_error(ast_ctx(self), "argpipe node: not an lvalue");
return false;
ir_block *cond;
ir_block *ontrue;
ir_block *onfalse;
- ir_block *ontrue_endblock = NULL;
- ir_block *onfalse_endblock = NULL;
- ir_block *merge = NULL;
- int fold = 0;
+ ir_block *ontrue_endblock = nullptr;
+ ir_block *onfalse_endblock = nullptr;
+ ir_block *merge = nullptr;
+ int folded = 0;
/* We don't output any value, thus also don't care about r/lvalue */
(void)out;
cond = func->curblock;
/* try constant folding away the condition */
- if ((fold = fold_cond_ifthen(condval, func, self)) != -1)
- return fold;
+ if ((folded = fold::cond_ifthen(condval, func, self)) != -1)
+ return folded;
if (self->on_true) {
/* create on-true block */
/* we now need to work from the current endpoint */
ontrue_endblock = func->curblock;
} else
- ontrue = NULL;
+ ontrue = nullptr;
/* on-false path */
if (self->on_false) {
/* we now need to work from the current endpoint */
onfalse_endblock = func->curblock;
} else
- onfalse = NULL;
+ onfalse = nullptr;
/* Merge block were they all merge in to */
if (!ontrue || !onfalse || !ontrue_endblock->final || !onfalse_endblock->final)
ir_instr *phi;
ir_block *cond = func->curblock;
- ir_block *cond_out = NULL;
- ir_block *ontrue, *ontrue_out = NULL;
- ir_block *onfalse, *onfalse_out = NULL;
+ ir_block *cond_out = nullptr;
+ ir_block *ontrue, *ontrue_out = nullptr;
+ ir_block *onfalse, *onfalse_out = nullptr;
ir_block *merge;
- int fold = 0;
+ int folded = 0;
/* Ternary can never create an lvalue... */
if (lvalue)
cond_out = func->curblock;
/* try constant folding away the condition */
- if ((fold = fold_cond_ternary(condval, func, self)) != -1)
- return fold;
+ if ((folded = fold::cond_ternary(condval, func, self)) != -1)
+ return folded;
/* create on-true block */
ontrue = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "tern_T"));
{
ast_expression_codegen *cgen;
- ir_value *dummy = NULL;
- ir_value *precond = NULL;
- ir_value *postcond = NULL;
+ ir_value *dummy = nullptr;
+ ir_value *precond = nullptr;
+ ir_value *postcond = nullptr;
/* Since we insert some jumps "late" so we have blocks
* ordered "nicely", we need to keep track of the actual end-blocks
* of expressions to add the jumps to.
*/
- ir_block *bbody = NULL, *end_bbody = NULL;
- ir_block *bprecond = NULL, *end_bprecond = NULL;
- ir_block *bpostcond = NULL, *end_bpostcond = NULL;
- ir_block *bincrement = NULL, *end_bincrement = NULL;
- ir_block *bout = NULL, *bin = NULL;
+ ir_block *bbody = nullptr, *end_bbody = nullptr;
+ ir_block *bprecond = nullptr, *end_bprecond = nullptr;
+ ir_block *bpostcond = nullptr, *end_bpostcond = nullptr;
+ ir_block *bincrement = nullptr, *end_bincrement = nullptr;
+ ir_block *bout = nullptr, *bin = nullptr;
/* let's at least move the outgoing block to the end */
size_t bout_id;
/* 'break' and 'continue' need to be able to find the right blocks */
- ir_block *bcontinue = NULL;
- ir_block *bbreak = NULL;
+ ir_block *bcontinue = nullptr;
+ ir_block *bbreak = nullptr;
- ir_block *tmpblock = NULL;
+ ir_block *tmpblock = nullptr;
(void)lvalue;
(void)out;
end_bprecond = func->curblock;
} else {
- bprecond = end_bprecond = NULL;
+ bprecond = end_bprecond = nullptr;
}
/* Now the next blocks won't be ordered nicely, but we need to
return false;
bcontinue = bincrement; /* increment comes before the pre-loop-condition */
} else {
- bincrement = end_bincrement = NULL;
+ bincrement = end_bincrement = nullptr;
}
if (self->postcond) {
return false;
bcontinue = bpostcond; /* postcond comes before the increment */
} else {
- bpostcond = end_bpostcond = NULL;
+ bpostcond = end_bpostcond = nullptr;
}
bout_id = vec_size(func->ir_func->blocks);
/* enter */
func->curblock = bbody;
- vec_push(func->breakblocks, bbreak);
+ func->breakblocks.push_back(bbreak);
if (bcontinue)
- vec_push(func->continueblocks, bcontinue);
+ func->continueblocks.push_back(bcontinue);
else
- vec_push(func->continueblocks, bbody);
+ func->continueblocks.push_back(bbody);
/* generate */
if (self->body) {
}
end_bbody = func->curblock;
- vec_pop(func->breakblocks);
- vec_pop(func->continueblocks);
+ func->breakblocks.pop_back();
+ func->continueblocks.pop_back();
}
/* post-loop-condition */
{
ir_block *target;
- *out = NULL;
+ *out = nullptr;
if (lvalue) {
compile_error(ast_ctx(self), "break/continue expression is not an l-value");
self->expression.outr = (ir_value*)1;
if (self->is_continue)
- target = func->continueblocks[vec_size(func->continueblocks)-1-self->levels];
+ target = func->continueblocks[func->continueblocks.size()-1-self->levels];
else
- target = func->breakblocks[vec_size(func->breakblocks)-1-self->levels];
+ target = func->breakblocks[func->breakblocks.size()-1-self->levels];
if (!target) {
compile_error(ast_ctx(self), "%s is lacking a target block", (self->is_continue ? "continue" : "break"));
{
ast_expression_codegen *cgen;
- ast_switch_case *def_case = NULL;
- ir_block *def_bfall = NULL;
- ir_block *def_bfall_to = NULL;
+ ast_switch_case *def_case = nullptr;
+ ir_block *def_bfall = nullptr;
+ ir_block *def_bfall_to = nullptr;
bool set_def_bfall_to = false;
- ir_value *dummy = NULL;
- ir_value *irop = NULL;
- ir_block *bout = NULL;
- ir_block *bfall = NULL;
+ ir_value *dummy = nullptr;
+ ir_value *irop = nullptr;
+ ir_block *bout = nullptr;
+ ir_block *bfall = nullptr;
size_t bout_id;
- size_t c;
char typestr[1024];
uint16_t cmpinstr;
if (!(*cgen)((ast_expression*)(self->operand), func, false, &irop))
return false;
- if (!vec_size(self->cases))
+ if (self->cases.empty())
return true;
cmpinstr = type_eq_instr[irop->vtype];
return false;
/* setup the break block */
- vec_push(func->breakblocks, bout);
+ func->breakblocks.push_back(bout);
/* Now create all cases */
- for (c = 0; c < vec_size(self->cases); ++c) {
+ for (auto &it : self->cases) {
ir_value *cond, *val;
ir_block *bcase, *bnot;
size_t bnot_id;
- ast_switch_case *swcase = &self->cases[c];
+ ast_switch_case *swcase = ⁢
if (swcase->value) {
/* A regular case */
/* The default case */
/* Remember where to fall through from: */
def_bfall = bfall;
- bfall = NULL;
+ bfall = nullptr;
/* remember which case it was */
def_case = swcase;
/* And the next case will be remembered */
func->curblock = bout;
/* restore the break block */
- vec_pop(func->breakblocks);
+ func->breakblocks.pop_back();
/* Move 'bout' to the end, it's nicer */
vec_remove(func->ir_func->blocks, bout_id, 1);
return false;
}
- *out = NULL;
+ *out = nullptr;
if (lvalue) {
compile_error(ast_ctx(self), "internal error: ast_label cannot be an lvalue");
return false;
bool ast_goto_codegen(ast_goto *self, ast_function *func, bool lvalue, ir_value **out)
{
- *out = NULL;
+ *out = nullptr;
if (lvalue) {
compile_error(ast_ctx(self), "internal error: ast_goto cannot be an lvalue");
return false;
compile_error(ast_ctx(self), "internal error: ast_state cannot be reused!");
return false;
}
- *out = NULL;
+ *out = nullptr;
cgen = self->framenum->codegen;
if (!(*cgen)((ast_expression*)(self->framenum), func, false, &frameval))
bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value **out)
{
ast_expression_codegen *cgen;
- ir_value **params;
- ir_instr *callinstr;
- size_t i;
+ std::vector<ir_value*> params;
+ ir_instr *callinstr;
- ir_value *funval = NULL;
+ ir_value *funval = nullptr;
/* return values are never lvalues */
if (lvalue) {
if (!funval)
return false;
- params = NULL;
-
/* parameters */
for (auto &it : self->params) {
ir_value *param;
cgen = it->codegen;
if (!(*cgen)(it, func, false, ¶m))
- goto error;
+ return false;
if (!param)
- goto error;
- vec_push(params, param);
+ return false;
+ params.push_back(param);
}
/* varargs counter */
ast_function_label(func, "call"),
funval, !!(self->func->flags & AST_FLAG_NORETURN));
if (!callinstr)
- goto error;
+ return false;
- for (i = 0; i < vec_size(params); ++i) {
- ir_call_param(callinstr, params[i]);
- }
+ for (auto &it : params)
+ ir_call_param(callinstr, it);
*out = ir_call_value(callinstr);
self->expression.outr = *out;
codegen_output_type(self, *out);
- vec_free(params);
return true;
-error:
- vec_free(params);
- return false;
}