#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)); \
}
/* 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;
}
{
if (self->next)
ast_delete(self->next);
- for (auto &it : self->params)
+ for (auto &it : self->type_params)
ast_delete(it);
if (self->varparam)
ast_delete(self->varparam);
ast_value* ast_value_copy(const ast_value *self)
{
- const ast_expression *fromex;
- ast_expression *selfex;
- ast_value *cp = ast_value_new(self->expression.node.context, self->name, self->expression.vtype);
- if (self->expression.next) {
- cp->expression.next = ast_type_copy(self->expression.node.context, self->expression.next);
+ ast_value *cp = ast_value_new(self->context, self->name, self->vtype);
+ if (self->next) {
+ cp->next = ast_type_copy(self->context, self->next);
}
- fromex = &self->expression;
- selfex = &cp->expression;
+ const ast_expression *fromex = self;
+ ast_expression *selfex = cp;
selfex->count = fromex->count;
selfex->flags = fromex->flags;
- for (auto &it : fromex->params) {
+ for (auto &it : fromex->type_params) {
ast_value *v = ast_value_copy(it);
- selfex->params.push_back(v);
+ selfex->type_params.push_back(v);
}
return cp;
}
selfex = self;
selfex->count = fromex->count;
selfex->flags = fromex->flags;
- for (auto &it : fromex->params) {
+ for (auto &it : fromex->type_params) {
ast_value *v = ast_value_copy(it);
- selfex->params.push_back(v);
+ selfex->type_params.push_back(v);
}
}
-static ast_expression* ast_shallow_type(lex_ctx_t ctx, int vtype)
+static ast_expression* ast_shallow_type(lex_ctx_t ctx, qc_type vtype)
{
ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
ast_expression_init(self, nullptr);
selfex->count = fromex->count;
selfex->flags = fromex->flags;
- for (auto &it : fromex->params) {
+ for (auto &it : fromex->type_params) {
ast_value *v = ast_value_copy(it);
- selfex->params.push_back(v);
+ selfex->type_params.push_back(v);
}
return self;
return false;
if (!a->next != !b->next)
return false;
- if (a->params.size() != b->params.size())
+ if (a->type_params.size() != b->type_params.size())
return false;
if ((a->flags & AST_FLAG_TYPE_MASK) !=
(b->flags & AST_FLAG_TYPE_MASK) )
{
return false;
}
- if (a->params.size()) {
+ if (a->type_params.size()) {
size_t i;
- for (i = 0; i < a->params.size(); ++i) {
- if (!ast_compare_type((ast_expression*)a->params[i],
- (ast_expression*)b->params[i]))
+ for (i = 0; i < a->type_params.size(); ++i) {
+ if (!ast_compare_type((ast_expression*)a->type_params[i],
+ (ast_expression*)b->type_params[i]))
return false;
}
}
pos = ast_type_to_string_impl(e->next, buf, bufsize, pos);
if (pos + 2 >= bufsize)
goto full;
- if (e->params.empty()) {
+ if (e->type_params.empty()) {
buf[pos++] = '(';
buf[pos++] = ')';
return pos;
}
buf[pos++] = '(';
- pos = ast_type_to_string_impl((ast_expression*)(e->params[0]), buf, bufsize, pos);
- for (i = 1; i < e->params.size(); ++i) {
+ pos = ast_type_to_string_impl((ast_expression*)(e->type_params[0]), buf, bufsize, pos);
+ for (i = 1; i < e->type_params.size(); ++i) {
if (pos + 2 >= bufsize)
goto full;
buf[pos++] = ',';
buf[pos++] = ' ';
- pos = ast_type_to_string_impl((ast_expression*)(e->params[i]), buf, bufsize, pos);
+ pos = ast_type_to_string_impl((ast_expression*)(e->type_params[i]), buf, bufsize, pos);
}
if (pos + 1 >= bufsize)
goto full;
}
static bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_value **out);
-ast_value* ast_value_new(lex_ctx_t ctx, const char *name, int t)
+ast_value* ast_value_new(lex_ctx_t ctx, const char *name, qc_type t)
{
ast_instantiate(ast_value, ctx, ast_value_delete);
ast_expression_init((ast_expression*)self,
(ast_expression_codegen*)&ast_value_codegen);
- self->expression.node.keep = true; /* keep */
+ self->keep_node = true; /* keep */
self->name = name ? util_strdup(name) : nullptr;
- self->expression.vtype = t;
- self->expression.next = nullptr;
+ self->vtype = t;
+ self->next = nullptr;
self->isfield = false;
self->cvq = CV_NONE;
self->hasvalue = false;
if (self->argcounter)
mem_d((void*)self->argcounter);
if (self->hasvalue) {
- switch (self->expression.vtype)
+ switch (self->vtype)
{
case TYPE_STRING:
mem_d((void*)self->constval.vstring);
break;
case TYPE_FUNCTION:
/* unlink us from the function node */
- self->constval.vfunc->vtype = nullptr;
+ self->constval.vfunc->function_type = nullptr;
break;
/* NOTE: delete function? currently collected in
* the parser structure
mem_d(self->desc);
// initlist imples an array which implies .next in the expression exists.
- if (self->initlist.size() && self->expression.next->vtype == TYPE_STRING) {
+ if (self->initlist.size() && self->next->vtype == TYPE_STRING) {
for (auto &it : self->initlist)
if (it.vstring)
mem_d(it.vstring);
void ast_value_params_add(ast_value *self, ast_value *p)
{
- self->expression.params.push_back(p);
+ self->type_params.push_back(p);
}
bool ast_value_set_name(ast_value *self, const char *name)
ast_propagate_effects(self, right);
if (op >= INSTR_EQ_F && op <= INSTR_GT)
- self->expression.vtype = TYPE_FLOAT;
+ self->vtype = TYPE_FLOAT;
else if (op == INSTR_AND || op == INSTR_OR) {
if (OPTS_FLAG(PERL_LOGIC))
ast_type_adopt(self, right);
else
- self->expression.vtype = TYPE_FLOAT;
+ self->vtype = TYPE_FLOAT;
}
else if (op == INSTR_BITAND || op == INSTR_BITOR)
- self->expression.vtype = TYPE_FLOAT;
+ self->vtype = TYPE_FLOAT;
else if (op == INSTR_MUL_VF || op == INSTR_MUL_FV)
- self->expression.vtype = TYPE_VECTOR;
+ self->vtype = TYPE_VECTOR;
else if (op == INSTR_MUL_V)
- self->expression.vtype = TYPE_FLOAT;
+ self->vtype = TYPE_FLOAT;
else
- self->expression.vtype = left->vtype;
+ self->vtype = left->vtype;
/* references all */
self->refs = AST_REF_ALL;
ast_propagate_effects(self, expr);
if ((op >= INSTR_NOT_F && op <= INSTR_NOT_FNC) || op == VINSTR_NEG_F) {
- self->expression.vtype = TYPE_FLOAT;
+ self->vtype = TYPE_FLOAT;
} else if (op == VINSTR_NEG_V) {
- self->expression.vtype = TYPE_VECTOR;
+ self->vtype = TYPE_VECTOR;
} else {
compile_error(ctx, "cannot determine type of unary operation %s", util_instr_str[op]);
}
}
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_member_codegen);
- self->expression.node.keep = true; /* keep */
+ self->keep_node = true; /* keep */
if (owner->vtype == TYPE_VECTOR) {
- self->expression.vtype = TYPE_FLOAT;
- self->expression.next = nullptr;
+ self->vtype = TYPE_FLOAT;
+ self->next = nullptr;
} else {
- self->expression.vtype = TYPE_FIELD;
- self->expression.next = ast_shallow_type(ctx, TYPE_FLOAT);
+ self->vtype = TYPE_FIELD;
+ self->next = ast_shallow_type(ctx, TYPE_FLOAT);
}
self->rvalue = false;
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);
ast_type_adopt(self, outtype);
if (array->vtype == TYPE_FIELD && outtype->vtype == TYPE_ARRAY) {
- if (self->expression.vtype != TYPE_ARRAY) {
+ if (self->vtype != TYPE_ARRAY) {
compile_error(ast_ctx(self), "array_index node on type");
ast_array_index_delete(self);
return nullptr;
}
self->array = outtype;
- self->expression.vtype = TYPE_FIELD;
+ self->vtype = TYPE_FIELD;
}
return self;
ast_instantiate(ast_argpipe, ctx, ast_argpipe_delete);
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_argpipe_codegen);
self->index = index;
- self->expression.vtype = TYPE_NOEXPR;
+ self->vtype = TYPE_NOEXPR;
return self;
}
ast_instantiate(ast_label, ctx, ast_label_delete);
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_label_codegen);
- self->expression.vtype = TYPE_NOEXPR;
+ self->vtype = TYPE_NOEXPR;
self->name = util_strdup(name);
self->irblock = nullptr;
bool retval = true;
const ast_expression *func = self->func;
size_t count = self->params.size();
- if (count > func->params.size())
- count = func->params.size();
+ if (count > func->type_params.size())
+ count = func->type_params.size();
for (i = 0; i < count; ++i) {
if (ast_istype(self->params[i], ast_argpipe)) {
compile_error(ast_ctx(self), "argpipe must be the last parameter to a function call");
return false;
}
- if (!ast_call_check_vararg(self, va_type, (ast_expression*)func->params[i]))
+ if (!ast_call_check_vararg(self, va_type, (ast_expression*)func->type_params[i]))
retval = false;
}
- else if (!ast_compare_type(self->params[i], (ast_expression*)(func->params[i])))
+ else if (!ast_compare_type(self->params[i], (ast_expression*)(func->type_params[i])))
{
ast_type_to_string(self->params[i], tgot, sizeof(tgot));
- ast_type_to_string((ast_expression*)func->params[i], texp, sizeof(texp));
+ ast_type_to_string((ast_expression*)func->type_params[i], texp, sizeof(texp));
compile_error(ast_ctx(self), "invalid type for parameter %u in function call: expected %s, got %s",
(unsigned int)(i+1), texp, tgot);
/* we don't immediately return */
}
}
count = self->params.size();
- if (count > func->params.size() && func->varparam) {
+ if (count > func->type_params.size() && func->varparam) {
for (; i < count; ++i) {
if (ast_istype(self->params[i], ast_argpipe)) {
/* warn about type safety instead */
{
ast_propagate_effects(self, e);
self->exprs.push_back(e);
- if (self->expression.next) {
- ast_delete(self->expression.next);
- self->expression.next = nullptr;
+ if (self->next) {
+ ast_delete(self->next);
+ self->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)
void ast_block_set_type(ast_block *self, ast_expression *from)
{
- if (self->expression.next)
- ast_delete(self->expression.next);
+ if (self->next)
+ ast_delete(self->next);
ast_type_adopt(self, from);
}
if (!vtype) {
compile_error(ast_ctx(self), "internal error: ast_function_new condition 0");
goto cleanup;
- } else if (vtype->hasvalue || vtype->expression.vtype != TYPE_FUNCTION) {
+ } else if (vtype->hasvalue || vtype->vtype != TYPE_FUNCTION) {
compile_error(ast_ctx(self), "internal error: ast_function_new condition %i %i type=%i (probably 2 bodies?)",
(int)!vtype,
(int)vtype->hasvalue,
- vtype->expression.vtype);
+ vtype->vtype);
goto cleanup;
}
- self->vtype = vtype;
- self->name = name ? util_strdup(name) : nullptr;
+ self->function_type = vtype;
+ self->name = name ? util_strdup(name) : nullptr;
self->labelcount = 0;
self->builtin = 0;
{
if (self->name)
mem_d((void*)self->name);
- if (self->vtype) {
- /* ast_value_delete(self->vtype); */
- self->vtype->hasvalue = false;
- self->vtype->constval.vfunc = nullptr;
+ if (self->function_type) {
+ /* ast_value_delete(self->function_type); */
+ self->function_type->hasvalue = false;
+ self->function_type->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);
+ ast_unref(self->function_type);
}
for (auto &it : self->static_names)
mem_d(it);
out->outtype = self->next->vtype;
}
-#define codegen_output_type(a,o) (_ast_codegen_output_type(&((a)->expression),(o)))
+#define codegen_output_type(a,o) (_ast_codegen_output_type(static_cast<ast_expression*>((a)),(o)))
bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_value **out)
{
(void)func;
(void)lvalue;
- if (self->expression.vtype == TYPE_NIL) {
+ if (self->vtype == TYPE_NIL) {
*out = func->ir_func->owner->nil;
return true;
}
- /* NOTE: This is the codegen for a variable used in an expression.
+ /* NOTE: This is the codegen for a variable used in an
* It is not the codegen to generate the value. For this purpose,
* ast_local_codegen and ast_global_codegen are to be used before this
* is executed. ast_function_codegen should take care of its locals,
size_t count = self->initlist.size();
size_t i;
- if (count > self->expression.count) {
+ if (count > self->count) {
compile_error(ast_ctx(self), "too many elements in initializer");
- count = self->expression.count;
+ count = self->count;
}
- else if (count < self->expression.count) {
+ else if (count < self->count) {
/* add this?
compile_warning(ast_ctx(self), "not all elements are initialized");
*/
}
for (i = 0; i != count; ++i) {
- switch (self->expression.next->vtype) {
+ switch (self->next->vtype) {
case TYPE_FLOAT:
if (!ir_value_set_float(self->ir_values[i], self->initlist[i].vfloat))
return false;
return false;
break;
default:
- compile_error(ast_ctx(self), "TODO: global constant type %i", self->expression.vtype);
+ compile_error(ast_ctx(self), "TODO: global constant type %i", self->vtype);
break;
}
}
static bool check_array(ast_value *self, ast_value *array)
{
- if (array->expression.flags & AST_FLAG_ARRAY_INIT && array->initlist.empty()) {
+ if (array->flags & AST_FLAG_ARRAY_INIT && array->initlist.empty()) {
compile_error(ast_ctx(self), "array without size: %s", self->name);
return false;
}
/* we are lame now - considering the way QC works we won't tolerate arrays > 1024 elements */
- if (!array->expression.count || array->expression.count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE)) {
- compile_error(ast_ctx(self), "Invalid array of size %lu", (unsigned long)array->expression.count);
+ if (!array->count || array->count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE)) {
+ compile_error(ast_ctx(self), "Invalid array of size %lu", (unsigned long)array->count);
return false;
}
return true;
{
ir_value *v = nullptr;
- if (self->expression.vtype == TYPE_NIL) {
+ if (self->vtype == TYPE_NIL) {
compile_error(ast_ctx(self), "internal error: trying to generate a variable of TYPE_NIL");
return false;
}
- if (self->hasvalue && self->expression.vtype == TYPE_FUNCTION)
+ if (self->hasvalue && self->vtype == TYPE_FUNCTION)
{
- ir_function *func = ir_builder_create_function(ir, self->name, self->expression.next->vtype);
+ ir_function *func = ir_builder_create_function(ir, self->name, self->next->vtype);
if (!func)
return false;
func->context = ast_ctx(self);
self->constval.vfunc->ir_func = func;
self->ir_v = func->value;
- if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+ if (self->flags & AST_FLAG_INCLUDE_DEF)
self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
- if (self->expression.flags & AST_FLAG_ERASEABLE)
+ if (self->flags & AST_FLAG_ERASEABLE)
self->ir_v->flags |= IR_FLAG_ERASABLE;
- if (self->expression.flags & AST_FLAG_BLOCK_COVERAGE)
+ if (self->flags & AST_FLAG_BLOCK_COVERAGE)
func->flags |= IR_FLAG_BLOCK_COVERAGE;
/* The function is filled later on ast_function_codegen... */
return true;
}
- if (isfield && self->expression.vtype == TYPE_FIELD) {
- ast_expression *fieldtype = self->expression.next;
+ if (isfield && self->vtype == TYPE_FIELD) {
+ ast_expression *fieldtype = self->next;
if (self->hasvalue) {
compile_error(ast_ctx(self), "TODO: constant field pointers with value");
size_t namelen;
ast_expression *elemtype;
- int vtype;
+ qc_type vtype;
ast_value *array = (ast_value*)fieldtype;
if (!ast_istype(fieldtype, ast_value)) {
if (!check_array(self, array))
return false;
- elemtype = array->expression.next;
+ elemtype = array->next;
vtype = elemtype->vtype;
v = ir_builder_create_field(ir, self->name, vtype);
v->locked = true;
array->ir_v = self->ir_v = v;
- if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+ if (self->flags & AST_FLAG_INCLUDE_DEF)
self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
- if (self->expression.flags & AST_FLAG_ERASEABLE)
+ if (self->flags & AST_FLAG_ERASEABLE)
self->ir_v->flags |= IR_FLAG_ERASABLE;
namelen = strlen(self->name);
name = (char*)mem_a(namelen + 16);
util_strncpy(name, self->name, namelen);
- array->ir_values = (ir_value**)mem_a(sizeof(array->ir_values[0]) * array->expression.count);
+ array->ir_values = (ir_value**)mem_a(sizeof(array->ir_values[0]) * array->count);
array->ir_values[0] = v;
- for (ai = 1; ai < array->expression.count; ++ai) {
+ for (ai = 1; ai < array->count; ++ai) {
util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
array->ir_values[ai] = ir_builder_create_field(ir, name, vtype);
if (!array->ir_values[ai]) {
array->ir_values[ai]->context = ast_ctx(self);
array->ir_values[ai]->unique_life = true;
array->ir_values[ai]->locked = true;
- if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+ if (self->flags & AST_FLAG_INCLUDE_DEF)
self->ir_values[ai]->flags |= IR_FLAG_INCLUDE_DEF;
}
mem_d(name);
}
else
{
- v = ir_builder_create_field(ir, self->name, self->expression.next->vtype);
+ v = ir_builder_create_field(ir, self->name, self->next->vtype);
if (!v)
return false;
v->context = ast_ctx(self);
self->ir_v = v;
- if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+ if (self->flags & AST_FLAG_INCLUDE_DEF)
self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
- if (self->expression.flags & AST_FLAG_ERASEABLE)
+ if (self->flags & AST_FLAG_ERASEABLE)
self->ir_v->flags |= IR_FLAG_ERASABLE;
}
return true;
}
- if (self->expression.vtype == TYPE_ARRAY) {
+ if (self->vtype == TYPE_ARRAY) {
size_t ai;
char *name;
size_t namelen;
- ast_expression *elemtype = self->expression.next;
- int vtype = elemtype->vtype;
+ ast_expression *elemtype = self->next;
+ qc_type vtype = elemtype->vtype;
- if (self->expression.flags & AST_FLAG_ARRAY_INIT && !self->expression.count) {
+ if (self->flags & AST_FLAG_ARRAY_INIT && !self->count) {
compile_error(ast_ctx(self), "array `%s' has no size", self->name);
return false;
}
v->unique_life = true;
v->locked = true;
- if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+ if (self->flags & AST_FLAG_INCLUDE_DEF)
v->flags |= IR_FLAG_INCLUDE_DEF;
- if (self->expression.flags & AST_FLAG_ERASEABLE)
+ if (self->flags & AST_FLAG_ERASEABLE)
self->ir_v->flags |= IR_FLAG_ERASABLE;
namelen = strlen(self->name);
name = (char*)mem_a(namelen + 16);
util_strncpy(name, self->name, namelen);
- self->ir_values = (ir_value**)mem_a(sizeof(self->ir_values[0]) * self->expression.count);
+ self->ir_values = (ir_value**)mem_a(sizeof(self->ir_values[0]) * self->count);
self->ir_values[0] = v;
- for (ai = 1; ai < self->expression.count; ++ai) {
+ for (ai = 1; ai < self->count; ++ai) {
util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
self->ir_values[ai] = ir_builder_create_global(ir, name, vtype);
if (!self->ir_values[ai]) {
self->ir_values[ai]->context = ast_ctx(self);
self->ir_values[ai]->unique_life = true;
self->ir_values[ai]->locked = true;
- if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+ if (self->flags & AST_FLAG_INCLUDE_DEF)
self->ir_values[ai]->flags |= IR_FLAG_INCLUDE_DEF;
}
mem_d(name);
/* Arrays don't do this since there's no "array" value which spans across the
* whole thing.
*/
- v = ir_builder_create_global(ir, self->name, self->expression.vtype);
+ v = ir_builder_create_global(ir, self->name, self->vtype);
if (!v) {
compile_error(ast_ctx(self), "ir_builder_create_global failed on `%s`", self->name);
return false;
v->cvq = self->cvq;
self->ir_v = v;
- if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+ if (self->flags & AST_FLAG_INCLUDE_DEF)
self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
- if (self->expression.flags & AST_FLAG_ERASEABLE)
+ if (self->flags & AST_FLAG_ERASEABLE)
self->ir_v->flags |= IR_FLAG_ERASABLE;
/* initialize */
if (self->hasvalue) {
- switch (self->expression.vtype)
+ switch (self->vtype)
{
case TYPE_FLOAT:
if (!ir_value_set_float(v, self->constval.vfloat))
goto error;
break;
default:
- compile_error(ast_ctx(self), "TODO: global constant type %i", self->expression.vtype);
+ compile_error(ast_ctx(self), "TODO: global constant type %i", self->vtype);
break;
}
}
return true;
error: /* clean up */
- if(v) ir_value_delete(v);
+ if (v) delete v;
return false;
}
{
ir_value *v = nullptr;
- if (self->expression.vtype == TYPE_NIL) {
+ if (self->vtype == TYPE_NIL) {
compile_error(ast_ctx(self), "internal error: trying to generate a variable of TYPE_NIL");
return false;
}
- if (self->hasvalue && self->expression.vtype == TYPE_FUNCTION)
+ if (self->hasvalue && self->vtype == TYPE_FUNCTION)
{
/* Do we allow local functions? I think not...
* this is NOT a function pointer atm.
return false;
}
- if (self->expression.vtype == TYPE_ARRAY) {
+ if (self->vtype == TYPE_ARRAY) {
size_t ai;
char *name;
size_t namelen;
- ast_expression *elemtype = self->expression.next;
- int vtype = elemtype->vtype;
+ ast_expression *elemtype = self->next;
+ qc_type vtype = elemtype->vtype;
func->flags |= IR_FLAG_HAS_ARRAYS;
- if (param && !(self->expression.flags & AST_FLAG_IS_VARARG)) {
+ if (param && !(self->flags & AST_FLAG_IS_VARARG)) {
compile_error(ast_ctx(self), "array-parameters are not supported");
return false;
}
if (!check_array(self, self))
return false;
- self->ir_values = (ir_value**)mem_a(sizeof(self->ir_values[0]) * self->expression.count);
+ self->ir_values = (ir_value**)mem_a(sizeof(self->ir_values[0]) * self->count);
if (!self->ir_values) {
compile_error(ast_ctx(self), "failed to allocate array values");
return false;
util_strncpy(name, self->name, namelen);
self->ir_values[0] = v;
- for (ai = 1; ai < self->expression.count; ++ai) {
+ for (ai = 1; ai < self->count; ++ai) {
util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
self->ir_values[ai] = ir_function_create_local(func, name, vtype, param);
if (!self->ir_values[ai]) {
}
else
{
- v = ir_function_create_local(func, self->name, self->expression.vtype, param);
+ v = ir_function_create_local(func, self->name, self->vtype, param);
if (!v)
return false;
codegen_output_type(self, v);
* I suppose the IR will have to deal with this
*/
if (self->hasvalue) {
- switch (self->expression.vtype)
+ switch (self->vtype)
{
case TYPE_FLOAT:
if (!ir_value_set_float(v, self->constval.vfloat))
goto error;
break;
default:
- compile_error(ast_ctx(self), "TODO: global constant type %i", self->expression.vtype);
+ compile_error(ast_ctx(self), "TODO: global constant type %i", self->vtype);
break;
}
}
return true;
error: /* clean up */
- ir_value_delete(v);
+ delete v;
return false;
}
bool warn = OPTS_WARN(WARN_USED_UNINITIALIZED);
if (!self->setter || !self->getter)
return true;
- for (i = 0; i < self->expression.count; ++i) {
+ for (i = 0; i < self->count; ++i) {
if (!self->ir_values) {
compile_error(ast_ctx(self), "internal error: no array values generated for `%s`", self->name);
return false;
compile_error(ast_ctx(self), "internal error: not all array values have been generated for `%s`", self->name);
return false;
}
- if (self->ir_values[i]->life) {
+ if (!self->ir_values[i]->life.empty()) {
compile_error(ast_ctx(self), "internal error: function containing `%s` already generated", self->name);
return false;
}
return false;
}
}
- for (i = 0; i < self->expression.count; ++i) {
- vec_free(self->ir_values[i]->life);
- }
+ for (i = 0; i < self->count; ++i)
+ self->ir_values[i]->life.clear();
opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
return true;
}
}
/* fill the parameter list */
- ec = &self->vtype->expression;
- for (auto &it : ec->params) {
- if (it->expression.vtype == TYPE_FIELD)
- vec_push(irf->params, it->expression.next->vtype);
+ ec = self->function_type;
+ for (auto &it : ec->type_params) {
+ if (it->vtype == TYPE_FIELD)
+ vec_push(irf->params, it->next->vtype);
else
- vec_push(irf->params, it->expression.vtype);
+ vec_push(irf->params, it->vtype);
if (!self->builtin) {
if (!ast_local_codegen(it, self->ir_func, true))
return false;
if (self->varargs) {
if (!ast_local_codegen(self->varargs, self->ir_func, true))
return false;
- irf->max_varargs = self->varargs->expression.count;
+ irf->max_varargs = self->varargs->count;
}
if (self->builtin) {
ir_value *sub;
if (!ast_local_codegen(self->argc, self->ir_func, true))
return false;
- cgen = self->argc->expression.codegen;
+ cgen = self->argc->codegen;
if (!(*cgen)((ast_expression*)(self->argc), self, false, &va_count))
return false;
- cgen = self->fixedparams->expression.codegen;
+ cgen = self->fixedparams->codegen;
if (!(*cgen)((ast_expression*)(self->fixedparams), self, false, &fixed))
return false;
sub = ir_block_create_binop(self->curblock, ast_ctx(self),
}
for (auto &it : self->blocks) {
- cgen = it->expression.codegen;
+ cgen = it->codegen;
if (!(*cgen)((ast_expression*)it, self, false, &dummy))
return false;
}
/* TODO: check return types */
if (!self->curblock->final)
{
- if (!self->vtype->expression.next ||
- self->vtype->expression.next->vtype == TYPE_VOID)
+ if (!self->function_type->next ||
+ self->function_type->next->vtype == TYPE_VOID)
{
return ir_block_create_return(self->curblock, ast_ctx(self), nullptr);
}
else if (vec_size(self->curblock->entries) || self->curblock == irf->first)
{
if (self->return_value) {
- cgen = self->return_value->expression.codegen;
+ cgen = self->return_value->codegen;
if (!(*cgen)((ast_expression*)(self->return_value), self, false, &dummy))
return false;
return ir_block_create_return(self->curblock, ast_ctx(self), dummy);
}
else if (compile_warning(ast_ctx(self), WARN_MISSING_RETURN_VALUES,
"control reaches end of non-void function (`%s`) via %s",
- self->name, self->curblock->label))
+ self->name, self->curblock->label.c_str()))
{
return false;
}
return false;
}
- if (self->expression.outr) {
- *out = self->expression.outr;
+ if (self->outr) {
+ *out = self->outr;
return true;
}
return false;
}
- self->expression.outr = *out;
+ self->outr = *out;
return true;
}
ast_value *idx = 0;
ast_array_index *ai = nullptr;
- if (lvalue && self->expression.outl) {
- *out = self->expression.outl;
+ if (lvalue && self->outl) {
+ *out = self->outl;
return true;
}
- if (!lvalue && self->expression.outr) {
- *out = self->expression.outr;
+ if (!lvalue && self->outr) {
+ *out = self->outr;
return true;
}
return false;
}
- cgen = idx->expression.codegen;
+ cgen = idx->codegen;
if (!(*cgen)((ast_expression*)(idx), func, false, &iridx))
return false;
- cgen = arr->setter->expression.codegen;
+ cgen = arr->setter->codegen;
if (!(*cgen)((ast_expression*)(arr->setter), func, true, &funval))
return false;
return false;
ir_call_param(call, iridx);
ir_call_param(call, right);
- self->expression.outr = right;
+ self->outr = right;
}
else
{
/* lvalue! */
if (!(*cgen)((ast_expression*)(self->dest), func, true, &left))
return false;
- self->expression.outl = left;
+ self->outl = left;
cgen = self->source->codegen;
/* rvalue! */
if (!ir_block_create_store_op(func->curblock, ast_ctx(self), self->op, left, right))
return false;
- self->expression.outr = right;
+ self->outr = right;
}
/* Theoretically, an assinment returns its left side as an
return false;
}
- if (self->expression.outr) {
- *out = self->expression.outr;
+ if (self->outr) {
+ *out = self->outr;
return true;
}
size_t merge_id;
/* prepare end-block */
- merge_id = vec_size(func->ir_func->blocks);
+ merge_id = func->ir_func->blocks.size();
merge = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_merge"));
/* generate the left expression */
if (!ir_block_create_jump(func->curblock, ast_ctx(self), merge))
return false;
- vec_remove(func->ir_func->blocks, merge_id, 1);
- vec_push(func->ir_func->blocks, merge);
+ func->ir_func->blocks.erase(func->ir_func->blocks.begin() + merge_id);
+ func->ir_func->blocks.emplace_back(merge);
func->curblock = merge;
phi = ir_block_create_phi(func->curblock, ast_ctx(self),
ast_function_label(func, "sce_value"),
- self->expression.vtype);
+ self->vtype);
ir_phi_add(phi, from_left, left);
ir_phi_add(phi, from_right, right);
*out = ir_phi_value(phi);
}
}
- self->expression.outr = *out;
+ self->outr = *out;
codegen_output_type(self, *out);
return true;
}
self->op, left, right);
if (!*out)
return false;
- self->expression.outr = *out;
+ self->outr = *out;
codegen_output_type(self, *out);
return true;
ast_array_index *ai = nullptr;
ir_value *iridx = nullptr;
- if (lvalue && self->expression.outl) {
- *out = self->expression.outl;
+ if (lvalue && self->outl) {
+ *out = self->outl;
return true;
}
- if (!lvalue && self->expression.outr) {
- *out = self->expression.outr;
+ if (!lvalue && self->outr) {
+ *out = self->outr;
return true;
}
/* for a binstore we need both an lvalue and an rvalue for the left side */
/* rvalue of destination! */
if (ai) {
- cgen = idx->expression.codegen;
+ cgen = idx->codegen;
if (!(*cgen)((ast_expression*)(idx), func, false, &iridx))
return false;
}
/* now the binary */
bin = ir_block_create_binop(func->curblock, ast_ctx(self), ast_function_label(func, "binst"),
self->opbin, leftr, right);
- self->expression.outr = bin;
-
+ self->outr = bin;
if (ai) {
/* we need to call the setter */
return false;
}
- cgen = arr->setter->expression.codegen;
+ cgen = arr->setter->codegen;
if (!(*cgen)((ast_expression*)(arr->setter), func, true, &funval))
return false;
return false;
ir_call_param(call, iridx);
ir_call_param(call, bin);
- self->expression.outr = bin;
+ self->outr = bin;
} else {
/* now store them */
cgen = self->dest->codegen;
/* lvalue of destination */
if (!(*cgen)((ast_expression*)(self->dest), func, true, &leftl))
return false;
- self->expression.outl = leftl;
+ self->outl = leftl;
if (!ir_block_create_store_op(func->curblock, ast_ctx(self), self->opstore, leftl, bin))
return false;
- self->expression.outr = bin;
+ self->outr = bin;
}
/* Theoretically, an assinment returns its left side as an
return false;
}
- if (self->expression.outr) {
- *out = self->expression.outr;
+ if (self->outr) {
+ *out = self->outr;
return true;
}
self->op, operand);
if (!*out)
return false;
- self->expression.outr = *out;
+ self->outr = *out;
return true;
}
return false;
}
- if (self->expression.outr) {
+ if (self->outr) {
compile_error(ast_ctx(self), "internal error: ast_return cannot be reused, it bears no result!");
return false;
}
- self->expression.outr = (ir_value*)1;
+ self->outr = (ir_value*)1;
if (self->operand) {
cgen = self->operand->codegen;
* value in a temp.
*/
- if (lvalue && self->expression.outl) {
- *out = self->expression.outl;
+ if (lvalue && self->outl) {
+ *out = self->outl;
return true;
}
- if (!lvalue && self->expression.outr) {
- *out = self->expression.outr;
+ if (!lvalue && self->outr) {
+ *out = self->outr;
return true;
}
ent, field);
} else {
*out = ir_block_create_load_from_ent(func->curblock, ast_ctx(self), ast_function_label(func, "efv"),
- ent, field, self->expression.vtype);
+ ent, field, self->vtype);
/* Done AFTER error checking:
codegen_output_type(self, *out);
*/
if (!*out) {
compile_error(ast_ctx(self), "failed to create %s instruction (output type %s)",
(lvalue ? "ADDRESS" : "FIELD"),
- type_name[self->expression.vtype]);
+ type_name[self->vtype]);
return false;
}
if (!lvalue)
codegen_output_type(self, *out);
if (lvalue)
- self->expression.outl = *out;
+ self->outl = *out;
else
- self->expression.outr = *out;
+ self->outr = *out;
/* Hm that should be it... */
return true;
compile_error(ast_ctx(self), "not an l-value (member access)");
return false;
}
- if (self->expression.outl) {
- *out = self->expression.outl;
+ if (self->outl) {
+ *out = self->outl;
return true;
}
}
*out = ir_value_vector_member(vec, self->field);
- self->expression.outl = *out;
+ self->outl = *out;
return (*out != nullptr);
}
ast_value *arr;
ast_value *idx;
- if (!lvalue && self->expression.outr) {
- *out = self->expression.outr;
+ if (!lvalue && self->outr) {
+ *out = self->outr;
return true;
}
- if (lvalue && self->expression.outl) {
- *out = self->expression.outl;
+ if (lvalue && self->outl) {
+ *out = self->outl;
return true;
}
if (!(*cgen)((ast_expression*)(self->index), func, false, &iridx))
return false;
- cgen = arr->getter->expression.codegen;
+ cgen = arr->getter->codegen;
if (!(*cgen)((ast_expression*)(arr->getter), func, true, &funval))
return false;
ir_call_param(call, iridx);
*out = ir_call_value(call);
- self->expression.outr = *out;
- (*out)->vtype = self->expression.vtype;
+ self->outr = *out;
+ (*out)->vtype = self->vtype;
codegen_output_type(self, *out);
return true;
}
- if (idx->expression.vtype == TYPE_FLOAT) {
+ if (idx->vtype == TYPE_FLOAT) {
unsigned int arridx = idx->constval.vfloat;
if (arridx >= self->array->count)
{
}
*out = arr->ir_values[arridx];
}
- else if (idx->expression.vtype == TYPE_INTEGER) {
+ else if (idx->vtype == TYPE_INTEGER) {
unsigned int arridx = idx->constval.vint;
if (arridx >= self->array->count)
{
compile_error(ast_ctx(self), "array indexing here needs an integer constant");
return false;
}
- (*out)->vtype = self->expression.vtype;
+ (*out)->vtype = self->vtype;
codegen_output_type(self, *out);
return true;
}
ir_block *ontrue_endblock = nullptr;
ir_block *onfalse_endblock = nullptr;
ir_block *merge = nullptr;
- int fold = 0;
+ int folded = 0;
/* We don't output any value, thus also don't care about r/lvalue */
(void)out;
(void)lvalue;
- if (self->expression.outr) {
+ if (self->outr) {
compile_error(ast_ctx(self), "internal error: ast_ifthen cannot be reused, it bears no result!");
return false;
}
- self->expression.outr = (ir_value*)1;
+ self->outr = (ir_value*)1;
/* generate the condition */
cgen = self->cond->codegen;
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 */
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)
* may still happen, thus we remember a created ir_value and simply return one
* if it already exists.
*/
- if (self->expression.outr) {
- *out = self->expression.outr;
+ if (self->outr) {
+ *out = self->outr;
return true;
}
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"));
}
/* create PHI */
- phi = ir_block_create_phi(merge, ast_ctx(self), ast_function_label(func, "phi"), self->expression.vtype);
+ phi = ir_block_create_phi(merge, ast_ctx(self), ast_function_label(func, "phi"), self->vtype);
if (!phi) {
compile_error(ast_ctx(self), "internal error: failed to generate phi node");
return false;
ir_phi_add(phi, ontrue_out, trueval);
ir_phi_add(phi, onfalse_out, falseval);
- self->expression.outr = ir_phi_value(phi);
- *out = self->expression.outr;
+ self->outr = ir_phi_value(phi);
+ *out = self->outr;
codegen_output_type(self, *out);
(void)lvalue;
(void)out;
- if (self->expression.outr) {
+ if (self->outr) {
compile_error(ast_ctx(self), "internal error: ast_loop cannot be reused, it bears no result!");
return false;
}
- self->expression.outr = (ir_value*)1;
+ self->outr = (ir_value*)1;
/* NOTE:
* Should we ever need some kind of block ordering, better make this function
bpostcond = end_bpostcond = nullptr;
}
- bout_id = vec_size(func->ir_func->blocks);
+ bout_id = func->ir_func->blocks.size();
bout = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "after_loop"));
if (!bout)
return false;
}
/* Move 'bout' to the end */
- vec_remove(func->ir_func->blocks, bout_id, 1);
- vec_push(func->ir_func->blocks, bout);
+ func->ir_func->blocks.erase(func->ir_func->blocks.begin() + bout_id);
+ func->ir_func->blocks.emplace_back(bout);
return true;
}
return false;
}
- if (self->expression.outr) {
+ if (self->outr) {
compile_error(ast_ctx(self), "internal error: ast_breakcont cannot be reused!");
return false;
}
- self->expression.outr = (ir_value*)1;
+ self->outr = (ir_value*)1;
if (self->is_continue)
target = func->continueblocks[func->continueblocks.size()-1-self->levels];
return false;
}
- if (self->expression.outr) {
+ if (self->outr) {
compile_error(ast_ctx(self), "internal error: ast_switch cannot be reused!");
return false;
}
- self->expression.outr = (ir_value*)1;
+ self->outr = (ir_value*)1;
(void)lvalue;
(void)out;
return false;
}
- bout_id = vec_size(func->ir_func->blocks);
+ bout_id = func->ir_func->blocks.size();
bout = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "after_switch"));
if (!bout)
return false;
return false;
bcase = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "case"));
- bnot_id = vec_size(func->ir_func->blocks);
+ bnot_id = func->ir_func->blocks.size();
bnot = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "not_case"));
if (!bcase || !bnot)
return false;
/* enter the else and move it down */
func->curblock = bnot;
- vec_remove(func->ir_func->blocks, bnot_id, 1);
- vec_push(func->ir_func->blocks, bnot);
+ func->ir_func->blocks.erase(func->ir_func->blocks.begin() + bnot_id);
+ func->ir_func->blocks.emplace_back(bnot);
} else {
/* The default case */
/* Remember where to fall through from: */
func->breakblocks.pop_back();
/* Move 'bout' to the end, it's nicer */
- vec_remove(func->ir_func->blocks, bout_id, 1);
- vec_push(func->ir_func->blocks, bout);
+ func->ir_func->blocks.erase(func->ir_func->blocks.begin() + bout_id);
+ func->ir_func->blocks.emplace_back(bout);
return true;
}
compile_error(ast_ctx(self), "not an l-value (state operation)");
return false;
}
- if (self->expression.outr) {
+ if (self->outr) {
compile_error(ast_ctx(self), "internal error: ast_state cannot be reused!");
return false;
}
return false;
}
- self->expression.outr = (ir_value*)1;
+ self->outr = (ir_value*)1;
return true;
}
return false;
}
- if (self->expression.outr) {
- *out = self->expression.outr;
+ if (self->outr) {
+ *out = self->outr;
return true;
}
ir_call_param(callinstr, it);
*out = ir_call_value(callinstr);
- self->expression.outr = *out;
+ self->outr = *out;
codegen_output_type(self, *out);