ast_value* ast_value_copy(const ast_value *self)
{
- const ast_expression *fromex;
- ast_expression *selfex;
- 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.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->type_params) {
ast_instantiate(ast_value, ctx, ast_value_delete);
ast_expression_init((ast_expression*)self,
(ast_expression_codegen*)&ast_value_codegen);
- self->expression.keep_node = 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);
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.type_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.keep_node = 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;
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;
{
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_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;
}
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");
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;
+ ast_expression *elemtype = self->next;
int 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;
}
}
{
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;
+ ast_expression *elemtype = self->next;
int 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;
}
}
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;
return false;
}
}
- for (i = 0; i < self->expression.count; ++i) {
+ for (i = 0; i < self->count; ++i) {
vec_free(self->ir_values[i]->life);
}
opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
}
/* fill the parameter list */
- ec = &self->function_type->expression;
+ ec = self->function_type;
for (auto &it : ec->type_params) {
- if (it->expression.vtype == TYPE_FIELD)
- vec_push(irf->params, it->expression.next->vtype);
+ 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->function_type->expression.next ||
- self->function_type->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);
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;
}
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;
}
(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;
* 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;
}
}
/* 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
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;
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);
ast_value *vfield;
};
-struct ast_value
+struct ast_value : ast_expression
{
- ast_expression expression;
-
const char *name;
const char *desc;
*
* A value-returning binary expression.
*/
-struct ast_binary
+struct ast_binary : ast_expression
{
- ast_expression expression;
int op;
ast_expression *left;
ast_expression *right;
* An assignment including a binary expression with the source as left operand.
* Eg. a += b; is a binstore { INSTR_STORE, INSTR_ADD, a, b }
*/
-struct ast_binstore
+struct ast_binstore : ast_expression
{
- ast_expression expression;
int opstore;
int opbin;
ast_expression *dest;
*
* Regular unary expressions: not,neg
*/
-struct ast_unary
+struct ast_unary : ast_expression
{
- ast_expression expression;
int op;
ast_expression *operand;
};
* will refuse to create further instructions.
* This should be honored by the parser.
*/
-struct ast_return
+struct ast_return : ast_expression
{
- ast_expression expression;
ast_expression *operand;
};
ast_return* ast_return_new(lex_ctx_t ctx,
* For this we will have to extend the codegen() functions with
* a flag saying whether or not we need an L or an R-value.
*/
-struct ast_entfield
+struct ast_entfield : ast_expression
{
- ast_expression expression;
/* The entity can come from an expression of course. */
ast_expression *entity;
/* As can the field, it just must result in a value of TYPE_FIELD */
* For now used for vectors. If we get structs or unions
* we can have them handled here as well.
*/
-struct ast_member
+struct ast_member : ast_expression
{
- ast_expression expression;
ast_expression *owner;
unsigned int field;
const char *name;
* In any case, accessing an element via a compiletime-constant index will
* result in quick access to that variable.
*/
-struct ast_array_index
+struct ast_array_index : ast_expression
{
- ast_expression expression;
ast_expression *array;
ast_expression *index;
};
*
* copy all varargs starting from a specific index
*/
-struct ast_argpipe
+struct ast_argpipe : ast_expression
{
- ast_expression expression;
ast_expression *index;
};
ast_argpipe* ast_argpipe_new(lex_ctx_t ctx, ast_expression *index);
* Stores left<-right and returns left.
* Specialized binary expression node
*/
-struct ast_store
+struct ast_store : ast_expression
{
- ast_expression expression;
int op;
ast_expression *dest;
ast_expression *source;
* output field though. For ternary expressions an ast_ternary will be
* added.
*/
-struct ast_ifthen
+struct ast_ifthen : ast_expression
{
- ast_expression expression;
ast_expression *cond;
/* It's all just 'expressions', since an ast_block is one too. */
ast_expression *on_true;
* This is the only ast_node beside ast_value which contains
* an ir_value. Theoretically we don't need to remember it though.
*/
-struct ast_ternary
+struct ast_ternary : ast_expression
{
- ast_expression expression;
ast_expression *cond;
/* It's all just 'expressions', since an ast_block is one too. */
ast_expression *on_true;
{inc};
}
*/
-struct ast_loop
+struct ast_loop : ast_expression
{
- ast_expression expression;
ast_expression *initexpr;
ast_expression *precond;
ast_expression *postcond;
/* Break/Continue
*/
-struct ast_breakcont
+struct ast_breakcont : ast_expression
{
- ast_expression expression;
- bool is_continue;
+ bool is_continue;
unsigned int levels;
};
ast_breakcont* ast_breakcont_new(lex_ctx_t ctx, bool iscont, unsigned int levels);
ast_expression *code;
};
-struct ast_switch
+struct ast_switch : ast_expression
{
- ast_expression expression;
ast_expression *operand;
std::vector<ast_switch_case> cases;
};
*
* Introduce a label which can be used together with 'goto'
*/
-struct ast_label
+struct ast_label : ast_expression
{
- ast_expression expression;
const char *name;
ir_block *irblock;
std::vector<ast_goto*> gotos;
*
* Go to a label, the label node is filled in at a later point!
*/
-struct ast_goto
+struct ast_goto : ast_expression
{
- ast_expression expression;
const char *name;
ast_label *target;
ir_block *irblock_from;
*
* For frame/think state updates: void foo() [framenum, nextthink] {}
*/
-struct ast_state
+struct ast_state : ast_expression
{
- ast_expression expression;
ast_expression *framenum;
ast_expression *nextthink;
};
* Additionally it contains a list of ast_expressions as parameters.
* Since calls can return values, an ast_call is also an ast_expression.
*/
-struct ast_call
+struct ast_call : ast_expression
{
- ast_expression expression;
ast_expression *func;
std::vector<ast_expression *> params;
ast_expression *va_count;
/* Blocks
*
*/
-struct ast_block
+struct ast_block : ast_expression
{
- ast_expression expression;
-
- std::vector<ast_value*> locals;
+ std::vector<ast_value*> locals;
std::vector<ast_expression*> exprs;
std::vector<ast_expression*> collect;
};
}
bool fold::immediate_true(ast_value *v) {
- switch (v->expression.vtype) {
+ switch (v->vtype) {
case TYPE_FLOAT:
return !!v->constval.vfloat;
case TYPE_INTEGER:
char name[32];
util_snprintf(name, sizeof(name), "dotranslate_%zu", m_parser->translated++);
out = ast_value_new(ctx(), name, TYPE_STRING);
- out->expression.flags |= AST_FLAG_INCLUDE_DEF; /* def needs to be included for translatables */
+ out->flags |= AST_FLAG_INCLUDE_DEF; /* def needs to be included for translatables */
} else {
out = ast_value_new(ctx(), "#IMMEDIATE", TYPE_STRING);
}
value = ast_value_new(ctx(), buffer, TYPE_FUNCTION);
value->intrinsic = true;
- value->expression.next = (ast_expression*)ast_value_new(ctx(), stype, vtype);
+ value->next = (ast_expression*)ast_value_new(ctx(), stype, vtype);
func = ast_function_new(ctx(), buffer, value);
- value->expression.flags |= AST_FLAG_ERASEABLE;
+ value->flags |= AST_FLAG_ERASEABLE;
*out = value;
return func;
ast_block *block = ast_block_new(ctx());
/* float x; */
- val->expression.type_params.push_back(x);
+ val->type_params.push_back(x);
/* <callisnan> = isnan(x); */
callisnan->params.push_back((ast_expression*)x);
)
);
- val->expression.type_params.push_back(x);
+ val->type_params.push_back(x);
func->blocks.push_back(body);
reg(val, func);
)
);
- val->expression.type_params.push_back(arg1);
+ val->type_params.push_back(arg1);
func->blocks.push_back(body);
reg(val, func);
ast_block *body = ast_block_new(ctx());
ast_function *func = value(&val, "isnormal", TYPE_FLOAT);
- val->expression.type_params.push_back(x);
+ val->type_params.push_back(x);
callisfinite->params.push_back((ast_expression*)x);
/* return <callisfinite> */
ast_block *body = ast_block_new(ctx());
ast_function *func = value(&val, "signbit", TYPE_FLOAT);
- val->expression.type_params.push_back(x);
+ val->type_params.push_back(x);
/* return (x < 0); */
body->exprs.push_back(
ast_block *body = ast_block_new(ctx());
ast_function *func = value(&val, "acosh", TYPE_FLOAT);
- val->expression.type_params.push_back(x);
+ val->type_params.push_back(x);
/* <callsqrt> = sqrt((x * x) - 1); */
callsqrt->params.push_back(
ast_block *body = ast_block_new(ctx());
ast_function *func = value(&val, "asinh", TYPE_FLOAT);
- val->expression.type_params.push_back(x);
+ val->type_params.push_back(x);
/* <callsqrt> = sqrt((x * x) + 1); */
callsqrt->params.push_back(
ast_block *body = ast_block_new(ctx());
ast_function *func = value(&val, "atanh", TYPE_FLOAT);
- val->expression.type_params.push_back(x);
+ val->type_params.push_back(x);
/* <callog> = log((1 + x) / (1 - x)); */
calllog->params.push_back(
ast_block *body = ast_block_new(ctx());
ast_function *func = value(&val, "exp", TYPE_FLOAT);
- val->expression.type_params.push_back(x);
+ val->type_params.push_back(x);
body->locals.push_back(sum);
body->locals.push_back(acc);
ast_block *body = ast_block_new(ctx());
ast_function *func = value(&val, "exp2", TYPE_FLOAT);
- val->expression.type_params.push_back(arg1);
+ val->type_params.push_back(arg1);
callpow->params.push_back((ast_expression*)m_fold->m_imm_float[3]);
callpow->params.push_back((ast_expression*)arg1);
ast_block *body = ast_block_new(ctx());
ast_function *func = value(&val, "expm1", TYPE_FLOAT);
- val->expression.type_params.push_back(x);
+ val->type_params.push_back(x);
/* <callexp> = exp(x); */
callexp->params.push_back((ast_expression*)x);
body->locals.push_back(accumulate);
body->locals.push_back(mid);
- val->expression.type_params.push_back(base);
- val->expression.type_params.push_back(exp);
+ val->type_params.push_back(base);
+ val->type_params.push_back(exp);
/*
* if (exp == 0.0)
ast_block *body = ast_block_new(ctx());
ast_function *func = value(&val, "mod", TYPE_FLOAT);
- val->expression.type_params.push_back(a);
- val->expression.type_params.push_back(b);
+ val->type_params.push_back(a);
+ val->type_params.push_back(b);
body->locals.push_back(div);
body->locals.push_back(sign);
)
);
- val->expression.type_params.push_back(arg1);
+ val->type_params.push_back(arg1);
func->blocks.push_back(body);
reg(val, func);
ast_function *func = value(&val, "ln", TYPE_FLOAT);
size_t i;
- val->expression.type_params.push_back(power);
- val->expression.type_params.push_back(base);
+ val->type_params.push_back(power);
+ val->type_params.push_back(base);
block->locals.push_back(whole);
block->locals.push_back(nth);
ast_block *body = ast_block_new(ctx());
ast_function *func = value(&val, name, TYPE_FLOAT);
- val->expression.type_params.push_back(arg1);
+ val->type_params.push_back(arg1);
callln->params.push_back((ast_expression*)arg1);
callln->params.push_back((ast_expression*)m_fold->constgen_float(base, false));
ast_block *body = ast_block_new(ctx());
ast_function *func = value(&val, name, TYPE_FLOAT);
- val->expression.type_params.push_back(a);
- val->expression.type_params.push_back(b);
+ val->type_params.push_back(a);
+ val->type_params.push_back(b);
/* <callpow> = pow(2, b) */
callpow->params.push_back((ast_expression*)m_fold->m_imm_float[3]);
ast_expression *intrin::func_self(const char *name, const char *from) {
ast_expression *find;
/* try current first */
- if ((find = parser_find_global(m_parser, name)) && ((ast_value*)find)->expression.vtype == TYPE_FUNCTION)
+ if ((find = parser_find_global(m_parser, name)) && ((ast_value*)find)->vtype == TYPE_FUNCTION)
for (auto &it : m_parser->functions)
if (((ast_value*)find)->name && !strcmp(it->name, ((ast_value*)find)->name) && it->builtin < 0)
return find;
if (!parser->function)
return nullptr;
fun = parser->function->function_type;
- for (auto &it : fun->expression.type_params) {
+ for (auto &it : fun->type_params) {
if (!strcmp(it->name, name))
return (ast_expression*)it;
}
for (i = 0; i < paramcount; ++i)
call->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->function_type->expression.varparam);
+ (void)!ast_call_check_types(call, parser->function->function_type->varparam);
if (parser->max_param_count < paramcount)
parser->max_param_count = paramcount;
}
/* overwrite fid, the function, with a call */
- sy->out[fid] = syexp(call->expression.context, (ast_expression*)call);
+ sy->out[fid] = syexp(call->context, (ast_expression*)call);
if (fun->vtype != TYPE_FUNCTION) {
parseerror(parser, "not a function (%s)", type_name[fun->vtype]);
return nullptr;
}
- if (funtype->expression.varparam &&
- !ast_compare_type((ast_expression*)typevar, (ast_expression*)funtype->expression.varparam))
+ if (funtype->varparam &&
+ !ast_compare_type((ast_expression*)typevar, (ast_expression*)funtype->varparam))
{
char ty1[1024];
char ty2[1024];
ast_type_to_string((ast_expression*)typevar, ty1, sizeof(ty1));
- ast_type_to_string((ast_expression*)funtype->expression.varparam, ty2, sizeof(ty2));
+ ast_type_to_string((ast_expression*)funtype->varparam, ty2, sizeof(ty2));
compile_error(ast_ctx(typevar),
"function was declared to take varargs of type `%s`, requested type is: %s",
ty2, ty1);
if (ast_istype(lexpr, ast_value)) {
ast_value *last = (ast_value*)lexpr;
if (last->isimm == true && last->cvq == CV_CONST &&
- last->hasvalue && last->expression.vtype == TYPE_STRING)
+ last->hasvalue && last->vtype == TYPE_STRING)
{
char *newstr = nullptr;
util_asprintf(&newstr, "%s%s", last->constval.vstring, parser_tokval(parser));
return false;
}
- if (type_store_instr[expected->expression.next->vtype] == VINSTR_END) {
+ if (type_store_instr[expected->next->vtype] == VINSTR_END) {
char ty1[1024];
- ast_type_to_string(expected->expression.next, ty1, sizeof(ty1));
+ ast_type_to_string(expected->next, ty1, sizeof(ty1));
parseerror(parser, "invalid return type: `%s'", ty1);
return false;
}
/* prepare the return value */
if (!retval) {
retval = ast_value_new(ctx, "#LOCAL_RETURN", TYPE_VOID);
- ast_type_adopt(retval, expected->expression.next);
+ ast_type_adopt(retval, expected->next);
parser->function->return_value = retval;
}
if (!ast_compare_type(exp, (ast_expression*)retval)) {
char ty1[1024], ty2[1024];
ast_type_to_string(exp, ty1, sizeof(ty1));
- ast_type_to_string(&retval->expression, ty2, sizeof(ty2));
+ ast_type_to_string(retval, ty2, sizeof(ty2));
parseerror(parser, "invalid type for return value: `%s', expected `%s'", ty1, ty2);
}
/* store to 'return' local variable */
var = (ast_expression*)ast_store_new(
ctx,
- type_store_instr[expected->expression.next->vtype],
+ type_store_instr[expected->next->vtype],
(ast_expression*)retval, exp);
if (!var) {
if (!parser_next(parser))
parseerror(parser, "parse error");
- if (!retval && expected->expression.next->vtype != TYPE_VOID)
+ if (!retval && expected->next->vtype != TYPE_VOID)
{
(void)!parsewarning(parser, WARN_MISSING_RETURN_VALUES, "return without value");
}
has_frame_think = false;
old = parser->function;
- if (var->expression.flags & AST_FLAG_ALIAS) {
+ if (var->flags & AST_FLAG_ALIAS) {
parseerror(parser, "function aliases cannot have bodies");
return false;
}
return false;
}
- if (!OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC) {
+ if (!OPTS_FLAG(VARIADIC_ARGS) && var->flags & AST_FLAG_VARIADIC) {
if (parsewarning(parser, WARN_VARIADIC_FUNCTION,
"variadic function with implementation will not be able to access additional parameters (try -fvariadic-args)"))
{
}
if (var->hasvalue) {
- if (!(var->expression.flags & AST_FLAG_ACCUMULATE)) {
+ if (!(var->flags & AST_FLAG_ACCUMULATE)) {
parseerror(parser, "function `%s` declared with multiple bodies", var->name);
ast_block_delete(block);
goto enderr;
parser_enterblock(parser);
- for (auto &it : var->expression.type_params) {
+ for (auto &it : var->type_params) {
size_t e;
ast_member *me[3];
- if (it->expression.vtype != TYPE_VECTOR &&
- (it->expression.vtype != TYPE_FIELD ||
- it->expression.next->vtype != TYPE_VECTOR))
+ if (it->vtype != TYPE_VECTOR &&
+ (it->vtype != TYPE_FIELD ||
+ it->next->vtype != TYPE_VECTOR))
{
continue;
}
func->argc = argc;
}
- if (OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC && !func->varargs) {
+ if (OPTS_FLAG(VARIADIC_ARGS) && var->flags & AST_FLAG_VARIADIC && !func->varargs) {
char name[1024];
ast_value *varargs = ast_value_new(ast_ctx(var), "reserved:va_args", TYPE_ARRAY);
- varargs->expression.flags |= AST_FLAG_IS_VARARG;
- varargs->expression.next = (ast_expression*)ast_value_new(ast_ctx(var), nullptr, TYPE_VECTOR);
- varargs->expression.count = 0;
+ varargs->flags |= AST_FLAG_IS_VARARG;
+ varargs->next = (ast_expression*)ast_value_new(ast_ctx(var), nullptr, TYPE_VECTOR);
+ varargs->count = 0;
util_snprintf(name, sizeof(name), "%s##va##SET", var->name);
if (!parser_create_array_setter_proto(parser, varargs, name)) {
ast_delete(varargs);
goto enderrfn;
}
util_snprintf(name, sizeof(name), "%s##va##GET", var->name);
- if (!parser_create_array_getter_proto(parser, varargs, varargs->expression.next, name)) {
+ if (!parser_create_array_getter_proto(parser, varargs, varargs->next, name)) {
ast_delete(varargs);
ast_block_delete(block);
goto enderrfn;
}
func->varargs = varargs;
- func->fixedparams = (ast_value*)parser->m_fold.constgen_float(var->expression.type_params.size(), false);
+ func->fixedparams = (ast_value*)parser->m_fold.constgen_float(var->type_params.size(), false);
}
parser->function = func;
ast_return *ret;
ast_array_index *subscript;
ast_store *st;
- int assignop = type_store_instr[value->expression.vtype];
+ int assignop = type_store_instr[value->vtype];
- if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR)
+ if (value->vtype == TYPE_FIELD && value->next->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));
ast_entfield *entfield;
ast_array_index *subscript;
ast_store *st;
- int assignop = type_storep_instr[value->expression.vtype];
+ int assignop = type_storep_instr[value->vtype];
- if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR)
+ if (value->vtype == TYPE_FIELD && value->next->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));
if (!subscript)
return nullptr;
- subscript->expression.next = ast_type_copy(ast_ctx(subscript), (ast_expression*)subscript);
- subscript->expression.vtype = TYPE_FIELD;
+ subscript->next = ast_type_copy(ast_ctx(subscript), (ast_expression*)subscript);
+ subscript->vtype = TYPE_FIELD;
entfield = ast_entfield_new_force(ctx,
(ast_expression*)entity,
parseerror(parser, "failed to create accessor function value");
return false;
}
- fval->expression.flags &= ~(AST_FLAG_COVERAGE_MASK);
+ fval->flags &= ~(AST_FLAG_COVERAGE_MASK);
func = ast_function_new(ast_ctx(array), funcname, fval);
if (!func) {
ast_function *func;
ast_value *fval;
- if (!ast_istype(array->expression.next, ast_value)) {
+ if (!ast_istype(array->next, ast_value)) {
parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type");
return nullptr;
}
if (!parser_create_array_accessor(parser, array, funcname, &fval))
return nullptr;
func = fval->constval.vfunc;
- fval->expression.next = (ast_expression*)ast_value_new(ast_ctx(array), "<void>", TYPE_VOID);
+ fval->next = (ast_expression*)ast_value_new(ast_ctx(array), "<void>", TYPE_VOID);
index = ast_value_new(ast_ctx(array), "index", TYPE_FLOAT);
- value = ast_value_copy((ast_value*)array->expression.next);
+ value = ast_value_copy((ast_value*)array->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->expression.type_params.push_back(index);
- fval->expression.type_params.push_back(value);
+ fval->type_params.push_back(index);
+ fval->type_params.push_back(value);
array->setter = fval;
return fval;
{
ast_expression *root = nullptr;
root = array_setter_node(parser, array,
- array->setter->expression.type_params[0],
- array->setter->expression.type_params[1],
- 0, array->expression.count);
+ array->setter->type_params[0],
+ array->setter->type_params[1],
+ 0, array->count);
if (!root) {
parseerror(parser, "failed to build accessor search tree");
return false;
ast_function *func;
ast_value *fval;
- if (!ast_istype(array->expression.next, ast_value)) {
+ if (!ast_istype(array->next, ast_value)) {
parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type");
return false;
}
if (!parser_create_array_accessor(parser, array, funcname, &fval))
return false;
func = fval->constval.vfunc;
- fval->expression.next = (ast_expression*)ast_value_new(ast_ctx(array), "<void>", TYPE_VOID);
+ fval->next = (ast_expression*)ast_value_new(ast_ctx(array), "<void>", TYPE_VOID);
entity = ast_value_new(ast_ctx(array), "entity", TYPE_ENTITY);
index = ast_value_new(ast_ctx(array), "index", TYPE_FLOAT);
- value = ast_value_copy((ast_value*)array->expression.next);
+ value = ast_value_copy((ast_value*)array->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->expression.type_params.push_back(entity);
- fval->expression.type_params.push_back(index);
- fval->expression.type_params.push_back(value);
+ fval->type_params.push_back(entity);
+ fval->type_params.push_back(index);
+ fval->type_params.push_back(value);
- root = array_field_setter_node(parser, array, entity, index, value, 0, array->expression.count);
+ root = array_field_setter_node(parser, array, entity, index, value, 0, array->count);
if (!root) {
parseerror(parser, "failed to build accessor search tree");
goto cleanup;
ast_value *fval;
ast_function *func;
- /* NOTE: checking array->expression.next rather than elemtype since
+ /* NOTE: checking array->next rather than elemtype since
* for fields elemtype is a temporary fieldtype.
*/
- if (!ast_istype(array->expression.next, ast_value)) {
+ if (!ast_istype(array->next, ast_value)) {
parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type");
return nullptr;
}
if (!parser_create_array_accessor(parser, array, funcname, &fval))
return nullptr;
func = fval->constval.vfunc;
- fval->expression.next = ast_type_copy(ast_ctx(array), elemtype);
+ fval->next = ast_type_copy(ast_ctx(array), elemtype);
index = ast_value_new(ast_ctx(array), "index", TYPE_FLOAT);
parseerror(parser, "failed to create locals for array accessor");
goto cleanup;
}
- fval->expression.type_params.push_back(index);
+ fval->type_params.push_back(index);
array->getter = fval;
return fval;
{
ast_expression *root = nullptr;
- root = array_getter_node(parser, array, array->getter->expression.type_params[0], 0, array->expression.count);
+ root = array_getter_node(parser, array, array->getter->type_params[0], 0, array->count);
if (!root) {
parseerror(parser, "failed to build accessor search tree");
return false;
}
} else {
params.push_back(param);
- if (param->expression.vtype >= TYPE_VARIANT) {
+ if (param->vtype >= TYPE_VARIANT) {
char tname[1024]; /* typename is reserved in C++ */
ast_type_to_string((ast_expression*)param, tname, sizeof(tname));
parseerror(parser, "type not supported as part of a parameter list: %s", tname);
}
}
- if (params.size() == 1 && params[0]->expression.vtype == TYPE_VOID)
+ if (params.size() == 1 && params[0]->vtype == TYPE_VOID)
params.clear();
/* sanity check */
/* now turn 'var' into a function type */
fval = ast_value_new(ctx, "<type()>", TYPE_FUNCTION);
- fval->expression.next = (ast_expression*)var;
+ fval->next = (ast_expression*)var;
if (variadic)
- fval->expression.flags |= AST_FLAG_VARIADIC;
+ fval->flags |= AST_FLAG_VARIADIC;
var = fval;
- var->expression.type_params = move(params);
- var->expression.varparam = (ast_expression*)varparam;
+ var->type_params = move(params);
+ var->varparam = (ast_expression*)varparam;
var->argcounter = argcounter;
return var;
}
tmp = ast_value_new(ctx, "<type[]>", TYPE_ARRAY);
- tmp->expression.next = (ast_expression*)var;
+ tmp->next = (ast_expression*)var;
var = tmp;
if (cval) {
- if (cval->expression.vtype == TYPE_INTEGER)
- tmp->expression.count = cval->constval.vint;
- else if (cval->expression.vtype == TYPE_FLOAT)
- tmp->expression.count = cval->constval.vfloat;
+ if (cval->vtype == TYPE_INTEGER)
+ tmp->count = cval->constval.vint;
+ else if (cval->vtype == TYPE_FLOAT)
+ tmp->count = cval->constval.vfloat;
else {
ast_unref(cexp);
ast_delete(var);
ast_unref(cexp);
} else {
- var->expression.count = -1;
- var->expression.flags |= AST_FLAG_ARRAY_INIT;
+ var->count = -1;
+ var->flags |= AST_FLAG_ARRAY_INIT;
}
if (parser->tok != ']') {
for (; morefields; --morefields) {
tmp = ast_value_new(ctx, "<.type>", TYPE_FIELD);
- tmp->expression.next = (ast_expression*)var;
+ tmp->next = (ast_expression*)var;
var = tmp;
}
*storebase = ast_value_copy(var);
if (isfield) {
tmp = ast_value_new(ctx, "<type:f>", TYPE_FIELD);
- tmp->expression.next = (ast_expression*)*storebase;
+ tmp->next = (ast_expression*)*storebase;
*storebase = tmp;
}
}
if (isfield) {
/* turn it into a field if desired */
tmp = ast_value_new(ctx, "<type:f>", TYPE_FIELD);
- tmp->expression.next = (ast_expression*)var;
+ tmp->next = (ast_expression*)var;
var = tmp;
}
cvq_to_str(proto->cvq));
}
}
- av = (var ->expression.flags & AST_FLAG_NORETURN);
- ao = (proto->expression.flags & AST_FLAG_NORETURN);
+ av = (var ->flags & AST_FLAG_NORETURN);
+ ao = (proto->flags & AST_FLAG_NORETURN);
if (!av != !ao) {
return !parsewarning(parser, WARN_DIFFERENT_ATTRIBUTES,
"`%s` declared with different attributes%s\n"
if (!parser_create_array_setter(parser, var, name))
return false;
util_snprintf(name, sizeof(name), "%s##GET", var->name);
- if (!parser_create_array_getter(parser, var, var->expression.next, name))
+ if (!parser_create_array_getter(parser, var, var->next, name))
return false;
return true;
}
return false;
}
array->initlist.push_back(v->constval);
- if (v->expression.vtype == TYPE_STRING) {
+ if (v->vtype == TYPE_STRING) {
array->initlist[i].vstring = util_strdupe(array->initlist[i].vstring);
++i;
}
}
*/
- if (array->expression.flags & AST_FLAG_ARRAY_INIT) {
- if (array->expression.count != (size_t)-1) {
+ if (array->flags & AST_FLAG_ARRAY_INIT) {
+ if (array->count != (size_t)-1) {
parseerror(parser, "array `%s' has already been initialized with %u elements",
- array->name, (unsigned)array->expression.count);
+ array->name, (unsigned)array->count);
}
- array->expression.count = array->initlist.size();
+ array->count = array->initlist.size();
if (!create_array_accessors(parser, array))
return false;
}
var->cvq = qualifier;
if (qflags & AST_FLAG_COVERAGE) /* specified in QC, drop our default */
- var->expression.flags &= ~(AST_FLAG_COVERAGE_MASK);
- var->expression.flags |= qflags;
+ var->flags &= ~(AST_FLAG_COVERAGE_MASK);
+ var->flags |= qflags;
/*
* store the vstring back to var for alias and
* deprecation messages.
*/
- if (var->expression.flags & AST_FLAG_DEPRECATED ||
- var->expression.flags & AST_FLAG_ALIAS)
+ if (var->flags & AST_FLAG_DEPRECATED ||
+ var->flags & AST_FLAG_ALIAS)
var->desc = vstring;
- if (parser_find_global(parser, var->name) && var->expression.flags & AST_FLAG_ALIAS) {
+ if (parser_find_global(parser, var->name) && var->flags & AST_FLAG_ALIAS) {
parseerror(parser, "function aliases cannot be forward declared");
retval = false;
goto cleanup;
parser->crc_fields = parser->fields.size();
was_end = true;
}
- if (was_end && var->expression.vtype == TYPE_FIELD) {
+ if (was_end && var->vtype == TYPE_FIELD) {
if (parsewarning(parser, WARN_END_SYS_FIELDS,
"global '%s' hint should not be a field",
parser_tokval(parser)))
}
}
- if (!nofields && var->expression.vtype == TYPE_FIELD)
+ if (!nofields && var->vtype == TYPE_FIELD)
{
/* deal with field declarations */
old = parser_find_field(parser, var->name);
{
/* deal with other globals */
old = parser_find_global(parser, var->name);
- if (old && var->expression.vtype == TYPE_FUNCTION && old->vtype == TYPE_FUNCTION)
+ if (old && var->vtype == TYPE_FUNCTION && old->vtype == TYPE_FUNCTION)
{
/* This is a function which had a prototype */
if (!ast_istype(old, ast_value)) {
goto cleanup;
}
/* we need the new parameter-names */
- for (i = 0; i < proto->expression.type_params.size(); ++i)
- ast_value_set_name(proto->expression.type_params[i], var->expression.type_params[i]->name);
+ for (i = 0; i < proto->type_params.size(); ++i)
+ ast_value_set_name(proto->type_params[i], var->type_params[i]->name);
if (!parser_check_qualifiers(parser, var, proto)) {
retval = false;
if (proto->desc)
proto = nullptr;
goto cleanup;
}
- proto->expression.flags |= var->expression.flags;
+ proto->flags |= var->flags;
ast_delete(var);
var = proto;
}
proto = nullptr;
goto cleanup;
}
- proto->expression.flags |= var->expression.flags;
+ proto->flags |= var->flags;
/* copy the context for finals,
* so the error can show where it was actually made 'final'
*/
- if (proto->expression.flags & AST_FLAG_FINAL_DECL)
+ if (proto->flags & AST_FLAG_FINAL_DECL)
ast_ctx(old) = ast_ctx(var);
ast_delete(var);
var = proto;
* Create the global/local, and deal with vector types.
*/
if (!proto) {
- if (var->expression.vtype == TYPE_VECTOR)
+ if (var->vtype == TYPE_VECTOR)
isvector = true;
- else if (var->expression.vtype == TYPE_FIELD &&
- var->expression.next->vtype == TYPE_VECTOR)
+ else if (var->vtype == TYPE_FIELD &&
+ var->next->vtype == TYPE_VECTOR)
isvector = true;
if (isvector) {
if (!localblock) {
/* deal with global variables, fields, functions */
- if (!nofields && var->expression.vtype == TYPE_FIELD && parser->tok != '=') {
+ if (!nofields && var->vtype == TYPE_FIELD && parser->tok != '=') {
var->isfield = true;
parser->fields.push_back((ast_expression*)var);
util_htset(parser->htfields, var->name, var);
}
}
else {
- if (!(var->expression.flags & AST_FLAG_ALIAS)) {
+ if (!(var->flags & AST_FLAG_ALIAS)) {
parser_addglobal(parser, var->name, (ast_expression*)var);
if (isvector) {
for (i = 0; i < 3; ++i) {
/* Part 2.2
* deal with arrays
*/
- if (var->expression.vtype == TYPE_ARRAY) {
- if (var->expression.count != (size_t)-1) {
+ if (var->vtype == TYPE_ARRAY) {
+ if (var->count != (size_t)-1) {
if (!create_array_accessors(parser, var))
goto cleanup;
}
}
else if (!localblock && !nofields &&
- var->expression.vtype == TYPE_FIELD &&
- var->expression.next->vtype == TYPE_ARRAY)
+ var->vtype == TYPE_FIELD &&
+ var->next->vtype == TYPE_ARRAY)
{
char name[1024];
ast_expression *telem;
ast_value *tfield;
- ast_value *array = (ast_value*)var->expression.next;
+ ast_value *array = (ast_value*)var->next;
- if (!ast_istype(var->expression.next, ast_value)) {
+ if (!ast_istype(var->next, ast_value)) {
parseerror(parser, "internal error: field element type must be an ast_value");
goto cleanup;
}
if (!parser_create_array_field_setter(parser, array, name))
goto cleanup;
- telem = ast_type_copy(ast_ctx(var), array->expression.next);
+ telem = ast_type_copy(ast_ctx(var), array->next);
tfield = ast_value_new(ast_ctx(var), "<.type>", TYPE_FIELD);
- tfield->expression.next = telem;
+ tfield->next = telem;
util_snprintf(name, sizeof(name), "%s##GETFP", var->name);
if (!parser_create_array_getter(parser, array, (ast_expression*)tfield, name)) {
ast_delete(tfield);
goto another;
/*
- if (!var || (!localblock && !nofields && basetype->expression.vtype == TYPE_FIELD)) {
+ if (!var || (!localblock && !nofields && basetype->vtype == TYPE_FIELD)) {
*/
if (!var) {
parseerror(parser, "missing comma or semicolon while parsing variables");
}
}
- if (parser->tok != '{' || var->expression.vtype != TYPE_FUNCTION) {
+ if (parser->tok != '{' || var->vtype != TYPE_FUNCTION) {
if (parser->tok != '=') {
parseerror(parser, "missing semicolon or initializer, got: `%s`", parser_tokval(parser));
break;
parseerror(parser, "cannot declare builtins within functions");
break;
}
- if (var->expression.vtype != TYPE_FUNCTION) {
+ if (var->vtype != TYPE_FUNCTION) {
parseerror(parser, "unexpected builtin number, '%s' is not a function", var->name);
break;
}
parseerror(parser, "builtin number must be a compile time constant");
break;
}
- if (number->expression.vtype == TYPE_INTEGER)
+ if (number->vtype == TYPE_INTEGER)
builtin_num = number->constval.vint;
- else if (number->expression.vtype == TYPE_FLOAT)
+ else if (number->vtype == TYPE_FLOAT)
builtin_num = number->constval.vfloat;
else {
ast_unref(number);
break;
}
}
- else if (var->expression.vtype == TYPE_ARRAY && parser->tok == '{')
+ else if (var->vtype == TYPE_ARRAY && parser->tok == '{')
{
if (localblock) {
/* Note that fteqcc and most others don't even *have*
if (!parse_array(parser, var))
break;
}
- else if (var->expression.vtype == TYPE_FUNCTION && (parser->tok == '{' || parser->tok == '['))
+ else if (var->vtype == TYPE_FUNCTION && (parser->tok == '{' || parser->tok == '['))
{
if (localblock) {
parseerror(parser, "cannot declare functions within functions");
var->cvq = CV_CONST;
}
if (cval == parser->nil)
- var->expression.flags |= AST_FLAG_INITIALIZED;
+ var->flags |= AST_FLAG_INITIALIZED;
else
{
var->hasvalue = true;
- if (cval->expression.vtype == TYPE_STRING)
+ if (cval->vtype == TYPE_STRING)
var->constval.vstring = parser_strdup(cval->constval.vstring);
- else if (cval->expression.vtype == TYPE_FIELD)
+ else if (cval->vtype == TYPE_FIELD)
var->constval.vfield = cval;
else
memcpy(&var->constval, &cval->constval, sizeof(var->constval));
/* a constant initialized to an inexact value should be marked inexact:
* const float x = <inexact>; should propagate the inexact flag
*/
- if (var->cvq == CV_CONST && var->expression.vtype == TYPE_FLOAT) {
+ if (var->cvq == CV_CONST && var->vtype == TYPE_FLOAT) {
if (cval && cval->hasvalue && cval->cvq == CV_CONST)
var->inexact = cval->inexact;
}
if (!ast_istype(parser->globals[i], ast_value))
continue;
value = (ast_value*)(parser->globals[i]);
- switch (value->expression.vtype) {
+ switch (value->vtype) {
case TYPE_FLOAT: crc = progdefs_crc_both(crc, "\tfloat\t"); break;
case TYPE_VECTOR: crc = progdefs_crc_both(crc, "\tvec3_t\t"); break;
case TYPE_STRING: crc = progdefs_crc_both(crc, "\tstring_t\t"); break;
if (!ast_istype(parser->fields[i], ast_value))
continue;
value = (ast_value*)(parser->fields[i]);
- switch (value->expression.next->vtype) {
+ switch (value->next->vtype) {
case TYPE_FLOAT: crc = progdefs_crc_both(crc, "\tfloat\t"); break;
case TYPE_VECTOR: crc = progdefs_crc_both(crc, "\tvec3_t\t"); break;
case TYPE_STRING: crc = progdefs_crc_both(crc, "\tstring_t\t"); break;
parser->reserved_version = ast_value_new(empty_ctx, "reserved:version", TYPE_STRING);
parser->reserved_version->cvq = CV_CONST;
parser->reserved_version->hasvalue = true;
- parser->reserved_version->expression.flags |= AST_FLAG_INCLUDE_DEF;
+ parser->reserved_version->flags |= AST_FLAG_INCLUDE_DEF;
parser->reserved_version->constval.vstring = util_strdup(GMQCC_FULL_VERSION_STRING);
} else {
parser->reserved_version = nullptr;
ir_value *ifld;
ast_expression *subtype;
field->hasvalue = true;
- subtype = field->expression.next;
+ subtype = field->next;
ifld = ir_builder_create_field(ir, field->name, subtype->vtype);
if (subtype->vtype == TYPE_FIELD)
ifld->fieldtype = subtype->next->vtype;
if (!ast_istype(it, ast_value))
continue;
asvalue = (ast_value*)it;
- if (!asvalue->uses && !asvalue->hasvalue && asvalue->expression.vtype != TYPE_FUNCTION) {
+ if (!asvalue->uses && !asvalue->hasvalue && asvalue->vtype != TYPE_FUNCTION) {
retval = retval && !compile_warning(ast_ctx(asvalue), WARN_UNUSED_VARIABLE,
"unused global: `%s`", asvalue->name);
}
*/
for (auto &f : parser->functions) {
if (f->varargs) {
- if (parser->max_param_count > f->function_type->expression.type_params.size()) {
- f->varargs->expression.count = parser->max_param_count - f->function_type->expression.type_params.size();
+ if (parser->max_param_count > f->function_type->type_params.size()) {
+ f->varargs->count = parser->max_param_count - f->function_type->type_params.size();
if (!parser_create_array_setter_impl(parser, f->varargs)) {
con_out("failed to generate vararg setter for %s\n", f->name);
ir_builder_delete(ir);
if (!ast_istype(it, ast_value))
continue;
ast_value *asvalue = (ast_value*)it;
- if (!(asvalue->expression.flags & AST_FLAG_INITIALIZED))
+ if (!(asvalue->flags & AST_FLAG_INITIALIZED))
{
if (asvalue->cvq == CV_CONST && !asvalue->hasvalue)
(void)!compile_warning(ast_ctx(asvalue), WARN_UNINITIALIZED_CONSTANT,
ast_value *asvalue = (ast_value*)it->next;
if (!ast_istype((ast_expression*)asvalue, ast_value))
continue;
- if (asvalue->expression.vtype != TYPE_ARRAY)
+ if (asvalue->vtype != TYPE_ARRAY)
continue;
if (!ast_generate_accessors(asvalue, ir)) {
ir_builder_delete(ir);