return NULL; \
} \
ast_node_init((ast_node*)self, ctx, TYPE_##T); \
- ( (ast_node*)self )->node.destroy = (ast_node_delete*)destroyfn
+ ( (ast_node*)self )->destroy = (ast_node_delete*)destroyfn
/* It must not be possible to get here. */
/* Initialize main ast node aprts */
static void ast_node_init(ast_node *self, lex_ctx ctx, int nodetype)
{
- self->node.context = ctx;
- self->node.destroy = &_ast_node_destroy;
- self->node.keep = false;
- self->node.nodetype = nodetype;
- self->node.side_effects = false;
+ self->context = ctx;
+ self->destroy = &_ast_node_destroy;
+ self->keep = false;
+ self->nodetype = nodetype;
+ self->side_effects = false;
}
/* weight and side effects */
static void ast_expression_init(ast_expression *self,
ast_expression_codegen *codegen)
{
- self->expression.codegen = codegen;
- self->expression.vtype = TYPE_VOID;
- self->expression.next = NULL;
- self->expression.outl = NULL;
- self->expression.outr = NULL;
- self->expression.params = NULL;
- self->expression.count = 0;
- self->expression.flags = 0;
- self->expression.varparam = NULL;
+ self->codegen = codegen;
+ self->vtype = TYPE_VOID;
+ self->next = NULL;
+ self->outl = NULL;
+ self->outr = NULL;
+ self->params = NULL;
+ self->count = 0;
+ self->flags = 0;
+ self->varparam = NULL;
}
static void ast_expression_delete(ast_expression *self)
{
size_t i;
- if (self->expression.next)
- ast_delete(self->expression.next);
- for (i = 0; i < vec_size(self->expression.params); ++i) {
- ast_delete(self->expression.params[i]);
+ if (self->next)
+ ast_delete(self->next);
+ for (i = 0; i < vec_size(self->params); ++i) {
+ ast_delete(self->params[i]);
}
- vec_free(self->expression.params);
- if (self->expression.varparam)
- ast_delete(self->expression.varparam);
+ vec_free(self->params);
+ if (self->varparam)
+ ast_delete(self->varparam);
}
static void ast_expression_delete_full(ast_expression *self)
ast_value* ast_value_copy(const ast_value *self)
{
size_t i;
- const ast_expression_common *fromex;
- ast_expression_common *selfex;
+ 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);
void ast_type_adopt_impl(ast_expression *self, const ast_expression *other)
{
size_t i;
- const ast_expression_common *fromex;
- ast_expression_common *selfex;
- self->expression.vtype = other->expression.vtype;
- if (other->expression.next) {
- self->expression.next = (ast_expression*)ast_type_copy(ast_ctx(self), other->expression.next);
- }
- fromex = &other->expression;
- selfex = &self->expression;
+ const ast_expression *fromex;
+ ast_expression *selfex;
+ self->vtype = other->vtype;
+ if (other->next) {
+ self->next = (ast_expression*)ast_type_copy(ast_ctx(self), other->next);
+ }
+ fromex = other;
+ selfex = self;
selfex->count = fromex->count;
selfex->flags = fromex->flags;
for (i = 0; i < vec_size(fromex->params); ++i) {
{
ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
ast_expression_init(self, NULL);
- self->expression.codegen = NULL;
- self->expression.next = NULL;
- self->expression.vtype = vtype;
+ self->codegen = NULL;
+ self->next = NULL;
+ self->vtype = vtype;
return self;
}
ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex)
{
size_t i;
- const ast_expression_common *fromex;
- ast_expression_common *selfex;
+ const ast_expression *fromex;
+ ast_expression *selfex;
if (!ex)
return NULL;
ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
ast_expression_init(self, NULL);
- fromex = &ex->expression;
- selfex = &self->expression;
+ fromex = ex;
+ selfex = self;
/* This may never be codegen()d */
selfex->codegen = NULL;
bool ast_compare_type(ast_expression *a, ast_expression *b)
{
- if (a->expression.vtype == TYPE_NIL ||
- b->expression.vtype == TYPE_NIL)
+ if (a->vtype == TYPE_NIL ||
+ b->vtype == TYPE_NIL)
return true;
- if (a->expression.vtype != b->expression.vtype)
+ if (a->vtype != b->vtype)
return false;
- if (!a->expression.next != !b->expression.next)
+ if (!a->next != !b->next)
return false;
- if (vec_size(a->expression.params) != vec_size(b->expression.params))
+ if (vec_size(a->params) != vec_size(b->params))
return false;
- if ((a->expression.flags & AST_FLAG_TYPE_MASK) !=
- (b->expression.flags & AST_FLAG_TYPE_MASK) )
+ if ((a->flags & AST_FLAG_TYPE_MASK) !=
+ (b->flags & AST_FLAG_TYPE_MASK) )
{
return false;
}
- if (vec_size(a->expression.params)) {
+ if (vec_size(a->params)) {
size_t i;
- for (i = 0; i < vec_size(a->expression.params); ++i) {
- if (!ast_compare_type((ast_expression*)a->expression.params[i],
- (ast_expression*)b->expression.params[i]))
+ for (i = 0; i < vec_size(a->params); ++i) {
+ if (!ast_compare_type((ast_expression*)a->params[i],
+ (ast_expression*)b->params[i]))
return false;
}
}
- if (a->expression.next)
- return ast_compare_type(a->expression.next, b->expression.next);
+ if (a->next)
+ return ast_compare_type(a->next, b->next);
return true;
}
if (pos + 1 >= bufsize)
goto full;
- switch (e->expression.vtype) {
+ switch (e->vtype) {
case TYPE_VARIANT:
util_strncpy(buf + pos, "(variant)", 9);
return pos + 9;
case TYPE_FIELD:
buf[pos++] = '.';
- return ast_type_to_string_impl(e->expression.next, buf, bufsize, pos);
+ return ast_type_to_string_impl(e->next, buf, bufsize, pos);
case TYPE_POINTER:
if (pos + 3 >= bufsize)
goto full;
buf[pos++] = '*';
buf[pos++] = '(';
- pos = ast_type_to_string_impl(e->expression.next, buf, bufsize, pos);
+ pos = ast_type_to_string_impl(e->next, buf, bufsize, pos);
if (pos + 1 >= bufsize)
goto full;
buf[pos++] = ')';
return pos;
case TYPE_FUNCTION:
- pos = ast_type_to_string_impl(e->expression.next, buf, bufsize, pos);
+ pos = ast_type_to_string_impl(e->next, buf, bufsize, pos);
if (pos + 2 >= bufsize)
goto full;
- if (!vec_size(e->expression.params)) {
+ if (!vec_size(e->params)) {
buf[pos++] = '(';
buf[pos++] = ')';
return pos;
}
buf[pos++] = '(';
- pos = ast_type_to_string_impl((ast_expression*)(e->expression.params[0]), buf, bufsize, pos);
- for (i = 1; i < vec_size(e->expression.params); ++i) {
+ pos = ast_type_to_string_impl((ast_expression*)(e->params[0]), buf, bufsize, pos);
+ for (i = 1; i < vec_size(e->params); ++i) {
if (pos + 2 >= bufsize)
goto full;
buf[pos++] = ',';
buf[pos++] = ' ';
- pos = ast_type_to_string_impl((ast_expression*)(e->expression.params[i]), buf, bufsize, pos);
+ pos = ast_type_to_string_impl((ast_expression*)(e->params[i]), buf, bufsize, pos);
}
if (pos + 1 >= bufsize)
goto full;
return pos;
case TYPE_ARRAY:
- pos = ast_type_to_string_impl(e->expression.next, buf, bufsize, pos);
+ pos = ast_type_to_string_impl(e->next, buf, bufsize, pos);
if (pos + 1 >= bufsize)
goto full;
buf[pos++] = '[';
- pos += util_snprintf(buf + pos, bufsize - pos - 1, "%i", (int)e->expression.count);
+ pos += util_snprintf(buf + pos, bufsize - pos - 1, "%i", (int)e->count);
if (pos + 1 >= bufsize)
goto full;
buf[pos++] = ']';
return pos;
default:
- typestr = type_name[e->expression.vtype];
+ typestr = type_name[e->vtype];
typelen = strlen(typestr);
if (pos + typelen >= bufsize)
goto full;
mem_d(self->desc);
if (self->initlist) {
- if (self->expression.next->expression.vtype == TYPE_STRING) {
+ if (self->expression.next->vtype == TYPE_STRING) {
/* strings are allocated, free them */
size_t i, len = vec_size(self->initlist);
/* in theory, len should be expression.count
else if (op == INSTR_MUL_V)
self->expression.vtype = TYPE_FLOAT;
else
- self->expression.vtype = left->expression.vtype;
+ self->expression.vtype = left->vtype;
/* references all */
self->refs = AST_REF_ALL;
ast_entfield* ast_entfield_new(lex_ctx ctx, ast_expression *entity, ast_expression *field)
{
- if (field->expression.vtype != TYPE_FIELD) {
+ if (field->vtype != TYPE_FIELD) {
compile_error(ctx, "ast_entfield_new with expression not of type field");
return NULL;
}
- return ast_entfield_new_force(ctx, entity, field, field->expression.next);
+ return ast_entfield_new_force(ctx, entity, field, field->next);
}
ast_entfield* ast_entfield_new_force(lex_ctx ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype)
return NULL;
}
- if (owner->expression.vtype != TYPE_VECTOR &&
- owner->expression.vtype != TYPE_FIELD) {
- compile_error(ctx, "member-access on an invalid owner of type %s", type_name[owner->expression.vtype]);
+ if (owner->vtype != TYPE_VECTOR &&
+ owner->vtype != TYPE_FIELD) {
+ compile_error(ctx, "member-access on an invalid owner of type %s", type_name[owner->vtype]);
mem_d(self);
return NULL;
}
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_member_codegen);
self->expression.node.keep = true; /* keep */
- if (owner->expression.vtype == TYPE_VECTOR) {
+ if (owner->vtype == TYPE_VECTOR) {
self->expression.vtype = TYPE_FLOAT;
self->expression.next = NULL;
} else {
ast_expression *outtype;
ast_instantiate(ast_array_index, ctx, ast_array_index_delete);
- outtype = array->expression.next;
+ outtype = array->next;
if (!outtype) {
mem_d(self);
/* Error: field has no type... */
ast_propagate_effects(self, index);
ast_type_adopt(self, outtype);
- if (array->expression.vtype == TYPE_FIELD && outtype->expression.vtype == TYPE_ARRAY) {
+ if (array->vtype == TYPE_FIELD && outtype->vtype == TYPE_ARRAY) {
if (self->expression.vtype != TYPE_ARRAY) {
compile_error(ast_ctx(self), "array_index node on type");
ast_array_index_delete(self);
ast_propagate_effects(self, ontrue);
ast_propagate_effects(self, onfalse);
- if (ontrue->expression.vtype == TYPE_NIL)
+ if (ontrue->vtype == TYPE_NIL)
exprtype = onfalse;
ast_type_adopt(self, exprtype);
ast_expression *funcexpr)
{
ast_instantiate(ast_call, ctx, ast_call_delete);
- if (!funcexpr->expression.next) {
+ if (!funcexpr->next) {
compile_error(ctx, "not a function");
mem_d(self);
return NULL;
self->func = funcexpr;
self->va_count = NULL;
- ast_type_adopt(self, funcexpr->expression.next);
+ ast_type_adopt(self, funcexpr->next);
return self;
}
bool retval = true;
const ast_expression *func = self->func;
size_t count = vec_size(self->params);
- if (count > vec_size(func->expression.params))
- count = vec_size(func->expression.params);
+ if (count > vec_size(func->params))
+ count = vec_size(func->params);
for (i = 0; i < count; ++i) {
- if (!ast_compare_type(self->params[i], (ast_expression*)(func->expression.params[i])))
+ if (!ast_compare_type(self->params[i], (ast_expression*)(func->params[i])))
{
ast_type_to_string(self->params[i], tgot, sizeof(tgot));
- ast_type_to_string((ast_expression*)func->expression.params[i], texp, sizeof(texp));
+ ast_type_to_string((ast_expression*)func->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 = vec_size(self->params);
- if (count > vec_size(func->expression.params) && func->expression.varparam) {
+ if (count > vec_size(func->params) && func->varparam) {
for (; i < count; ++i) {
- if (!ast_compare_type(self->params[i], func->expression.varparam))
+ if (!ast_compare_type(self->params[i], func->varparam))
{
ast_type_to_string(self->params[i], tgot, sizeof(tgot));
- ast_type_to_string(func->expression.varparam, texp, sizeof(texp));
+ ast_type_to_string(func->varparam, 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 */
void ast_block_collect(ast_block *self, ast_expression *expr)
{
vec_push(self->collect, expr);
- expr->expression.node.keep = true;
+ expr->node.keep = true;
}
void ast_block_delete(ast_block *self)
* But I can't imagine a pituation where the output is truly unnecessary.
*/
-void _ast_codegen_output_type(ast_expression_common *self, ir_value *out)
+void _ast_codegen_output_type(ast_expression *self, ir_value *out)
{
if (out->vtype == TYPE_FIELD)
- out->fieldtype = self->next->expression.vtype;
+ out->fieldtype = self->next->vtype;
if (out->vtype == TYPE_FUNCTION)
- out->outtype = self->next->expression.vtype;
+ out->outtype = self->next->vtype;
}
#define codegen_output_type(a,o) (_ast_codegen_output_type(&((a)->expression),(o)))
if (self->hasvalue && self->expression.vtype == TYPE_FUNCTION)
{
- ir_function *func = ir_builder_create_function(ir, self->name, self->expression.next->expression.vtype);
+ ir_function *func = ir_builder_create_function(ir, self->name, self->expression.next->vtype);
if (!func)
return false;
func->context = ast_ctx(self);
goto error;
}
- if (fieldtype->expression.vtype == TYPE_ARRAY) {
+ if (fieldtype->vtype == TYPE_ARRAY) {
size_t ai;
char *name;
size_t namelen;
- ast_expression_common *elemtype;
- int vtype;
- ast_value *array = (ast_value*)fieldtype;
+ ast_expression *elemtype;
+ int vtype;
+ ast_value *array = (ast_value*)fieldtype;
if (!ast_istype(fieldtype, ast_value)) {
compile_error(ast_ctx(self), "internal error: ast_value required");
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);
- elemtype = &array->expression.next->expression;
+ elemtype = array->expression.next;
vtype = elemtype->vtype;
v = ir_builder_create_field(ir, self->name, vtype);
}
else
{
- v = ir_builder_create_field(ir, self->name, self->expression.next->expression.vtype);
+ v = ir_builder_create_field(ir, self->name, self->expression.next->vtype);
if (!v)
return false;
v->context = ast_ctx(self);
char *name;
size_t namelen;
- ast_expression_common *elemtype = &self->expression.next->expression;
+ ast_expression *elemtype = self->expression.next;
int vtype = elemtype->vtype;
/* same as with field arrays */
char *name;
size_t namelen;
- ast_expression_common *elemtype = &self->expression.next->expression;
+ ast_expression *elemtype = self->expression.next;
int vtype = elemtype->vtype;
func->flags |= IR_FLAG_HAS_ARRAYS;
{
ir_function *irf;
ir_value *dummy;
- ast_expression_common *ec;
+ ast_expression *ec;
ast_expression_codegen *cgen;
size_t i;
for (i = 0; i < vec_size(ec->params); ++i)
{
if (ec->params[i]->expression.vtype == TYPE_FIELD)
- vec_push(irf->params, ec->params[i]->expression.next->expression.vtype);
+ vec_push(irf->params, ec->params[i]->expression.next->vtype);
else
vec_push(irf->params, ec->params[i]->expression.vtype);
if (!self->builtin) {
if (!self->curblock->final)
{
if (!self->vtype->expression.next ||
- self->vtype->expression.next->expression.vtype == TYPE_VOID)
+ self->vtype->expression.next->vtype == TYPE_VOID)
{
return ir_block_create_return(self->curblock, ast_ctx(self), NULL);
}
return false;
continue;
}
- gen = self->exprs[i]->expression.codegen;
+ gen = self->exprs[i]->codegen;
if (!(*gen)(self->exprs[i], func, false, out))
return false;
}
if (!(*cgen)((ast_expression*)(arr->setter), func, true, &funval))
return false;
- cgen = self->source->expression.codegen;
+ cgen = self->source->codegen;
if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
return false;
{
/* regular code */
- cgen = self->dest->expression.codegen;
+ cgen = self->dest->codegen;
/* lvalue! */
if (!(*cgen)((ast_expression*)(self->dest), func, true, &left))
return false;
self->expression.outl = left;
- cgen = self->source->expression.codegen;
+ cgen = self->source->codegen;
/* rvalue! */
if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
return false;
merge = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_merge"));
/* generate the left expression */
- cgen = self->left->expression.codegen;
+ cgen = self->left->codegen;
if (!(*cgen)((ast_expression*)(self->left), func, false, &left))
return false;
/* remember the block */
/* enter the right-expression's block */
func->curblock = other;
/* generate */
- cgen = self->right->expression.codegen;
+ cgen = self->right->codegen;
if (!(*cgen)((ast_expression*)(self->right), func, false, &right))
return false;
/* remember block */
return true;
}
- cgen = self->left->expression.codegen;
+ cgen = self->left->codegen;
if (!(*cgen)((ast_expression*)(self->left), func, false, &left))
return false;
- cgen = self->right->expression.codegen;
+ cgen = self->right->codegen;
if (!(*cgen)((ast_expression*)(self->right), func, false, &right))
return false;
if (!(*cgen)((ast_expression*)(idx), func, false, &iridx))
return false;
}
- cgen = self->dest->expression.codegen;
+ cgen = self->dest->codegen;
if (!(*cgen)((ast_expression*)(self->dest), func, false, &leftr))
return false;
/* source as rvalue only */
- cgen = self->source->expression.codegen;
+ cgen = self->source->codegen;
if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
return false;
self->expression.outr = bin;
} else {
/* now store them */
- cgen = self->dest->expression.codegen;
+ cgen = self->dest->codegen;
/* lvalue of destination */
if (!(*cgen)((ast_expression*)(self->dest), func, true, &leftl))
return false;
return true;
}
- cgen = self->operand->expression.codegen;
+ cgen = self->operand->codegen;
/* lvalue! */
if (!(*cgen)((ast_expression*)(self->operand), func, false, &operand))
return false;
self->expression.outr = (ir_value*)1;
if (self->operand) {
- cgen = self->operand->expression.codegen;
+ cgen = self->operand->codegen;
/* lvalue! */
if (!(*cgen)((ast_expression*)(self->operand), func, false, &operand))
return false;
return true;
}
- cgen = self->entity->expression.codegen;
+ cgen = self->entity->codegen;
if (!(*cgen)((ast_expression*)(self->entity), func, false, &ent))
return false;
- cgen = self->field->expression.codegen;
+ cgen = self->field->codegen;
if (!(*cgen)((ast_expression*)(self->field), func, false, &field))
return false;
return true;
}
- cgen = self->owner->expression.codegen;
+ cgen = self->owner->codegen;
if (!(*cgen)((ast_expression*)(self->owner), func, false, &vec))
return false;
if (vec->vtype != TYPE_VECTOR &&
- !(vec->vtype == TYPE_FIELD && self->owner->expression.next->expression.vtype == TYPE_VECTOR))
+ !(vec->vtype == TYPE_FIELD && self->owner->next->vtype == TYPE_VECTOR))
{
return false;
}
return false;
}
- cgen = self->index->expression.codegen;
+ cgen = self->index->codegen;
if (!(*cgen)((ast_expression*)(self->index), func, false, &iridx))
return false;
if (idx->expression.vtype == TYPE_FLOAT) {
unsigned int arridx = idx->constval.vfloat;
- if (arridx >= self->array->expression.count)
+ if (arridx >= self->array->count)
{
compile_error(ast_ctx(self), "array index out of bounds: %i", arridx);
return false;
}
else if (idx->expression.vtype == TYPE_INTEGER) {
unsigned int arridx = idx->constval.vint;
- if (arridx >= self->array->expression.count)
+ if (arridx >= self->array->count)
{
compile_error(ast_ctx(self), "array index out of bounds: %i", arridx);
return false;
self->expression.outr = (ir_value*)1;
/* generate the condition */
- cgen = self->cond->expression.codegen;
+ cgen = self->cond->codegen;
if (!(*cgen)((ast_expression*)(self->cond), func, false, &condval))
return false;
/* update the block which will get the jump - because short-logic or ternaries may have changed this */
func->curblock = ontrue;
/* generate */
- cgen = self->on_true->expression.codegen;
+ cgen = self->on_true->codegen;
if (!(*cgen)((ast_expression*)(self->on_true), func, false, &dummy))
return false;
func->curblock = onfalse;
/* generate */
- cgen = self->on_false->expression.codegen;
+ cgen = self->on_false->codegen;
if (!(*cgen)((ast_expression*)(self->on_false), func, false, &dummy))
return false;
/* generate the condition */
func->curblock = cond;
- cgen = self->cond->expression.codegen;
+ cgen = self->cond->codegen;
if (!(*cgen)((ast_expression*)(self->cond), func, false, &condval))
return false;
cond_out = func->curblock;
func->curblock = ontrue;
/* generate */
- cgen = self->on_true->expression.codegen;
+ cgen = self->on_true->codegen;
if (!(*cgen)((ast_expression*)(self->on_true), func, false, &trueval))
return false;
func->curblock = onfalse;
/* generate */
- cgen = self->on_false->expression.codegen;
+ cgen = self->on_false->codegen;
if (!(*cgen)((ast_expression*)(self->on_false), func, false, &falseval))
return false;
*/
if (self->initexpr)
{
- cgen = self->initexpr->expression.codegen;
+ cgen = self->initexpr->codegen;
if (!(*cgen)((ast_expression*)(self->initexpr), func, false, &dummy))
return false;
}
func->curblock = bprecond;
/* generate */
- cgen = self->precond->expression.codegen;
+ cgen = self->precond->codegen;
if (!(*cgen)((ast_expression*)(self->precond), func, false, &precond))
return false;
/* generate */
if (self->body) {
- cgen = self->body->expression.codegen;
+ cgen = self->body->codegen;
if (!(*cgen)((ast_expression*)(self->body), func, false, &dummy))
return false;
}
func->curblock = bpostcond;
/* generate */
- cgen = self->postcond->expression.codegen;
+ cgen = self->postcond->codegen;
if (!(*cgen)((ast_expression*)(self->postcond), func, false, &postcond))
return false;
func->curblock = bincrement;
/* generate */
- cgen = self->increment->expression.codegen;
+ cgen = self->increment->codegen;
if (!(*cgen)((ast_expression*)(self->increment), func, false, &dummy))
return false;
(void)lvalue;
(void)out;
- cgen = self->operand->expression.codegen;
+ cgen = self->operand->codegen;
if (!(*cgen)((ast_expression*)(self->operand), func, false, &irop))
return false;
if (swcase->value) {
/* A regular case */
/* generate the condition operand */
- cgen = swcase->value->expression.codegen;
+ cgen = swcase->value->codegen;
if (!(*cgen)((ast_expression*)(swcase->value), func, false, &val))
return false;
/* generate the condition */
/* enter the case */
func->curblock = bcase;
- cgen = swcase->code->expression.codegen;
+ cgen = swcase->code->codegen;
if (!(*cgen)((ast_expression*)swcase->code, func, false, &dummy))
return false;
}
/* Now generate the default code */
- cgen = def_case->code->expression.codegen;
+ cgen = def_case->code->codegen;
if (!(*cgen)((ast_expression*)def_case->code, func, false, &dummy))
return false;
return true;
}
- cgen = self->func->expression.codegen;
+ cgen = self->func->codegen;
if (!(*cgen)((ast_expression*)(self->func), func, false, &funval))
return false;
if (!funval)
ir_value *param;
ast_expression *expr = self->params[i];
- cgen = expr->expression.codegen;
+ cgen = expr->codegen;
if (!(*cgen)(expr, func, false, ¶m))
goto error;
if (!param)
if (self->va_count) {
ir_value *va_count;
ir_builder *builder = func->curblock->owner->owner;
- cgen = self->va_count->expression.codegen;
+ cgen = self->va_count->codegen;
if (!(*cgen)((ast_expression*)(self->va_count), func, false, &va_count))
return false;
if (!ir_block_create_store_op(func->curblock, ast_ctx(self), INSTR_STORE_F,
callinstr = ir_block_create_call(func->curblock, ast_ctx(self),
ast_function_label(func, "call"),
- funval, !!(self->func->expression.flags & AST_FLAG_NORETURN));
+ funval, !!(self->func->flags & AST_FLAG_NORETURN));
if (!callinstr)
goto error;
* "main" ast node types for now.
*/
-typedef union ast_node_u ast_node;
-typedef union ast_expression_u ast_expression;
+typedef struct ast_node_common ast_node;
+typedef struct ast_expression_common ast_expression;
typedef struct ast_value_s ast_value;
typedef struct ast_function_s ast_function;
TYPE_ast_goto /* 20 */
};
-#define ast_istype(x, t) ( ((ast_node_common*)x)->nodetype == (TYPE_##t) )
-#define ast_ctx(node) (((ast_node_common*)(node))->context)
-#define ast_side_effects(node) (((ast_node_common*)(node))->side_effects)
+#define ast_istype(x, t) ( ((ast_node*)x)->nodetype == (TYPE_##t) )
+#define ast_ctx(node) (((ast_node*)(node))->context)
+#define ast_side_effects(node) (((ast_node*)(node))->side_effects)
/* Node interface with common components
*/
typedef void ast_node_delete(ast_node*);
-typedef struct
+struct ast_node_common
{
lex_ctx context;
/* I don't feel comfortable using keywords like 'delete' as names... */
*/
bool keep;
bool side_effects;
-} ast_node_common;
-
-#define ast_delete(x) (*( ((ast_node*)(x))->node.destroy ))((ast_node*)(x))
-#define ast_unref(x) do \
-{ \
- if (! (((ast_node*)(x))->node.keep) ) { \
- ast_delete(x); \
- } \
+};
+
+#define ast_delete(x) (*( ((ast_node*)(x))->destroy ))((ast_node*)(x))
+#define ast_unref(x) do \
+{ \
+ if (! (((ast_node*)(x))->keep) ) { \
+ ast_delete(x); \
+ } \
} while(0)
/* Expression interface
* type `expression`, so the ast_ident's codegen would search for
* variables through the environment (or functions, constants...).
*/
-typedef struct
+struct ast_expression_common
{
- ast_node_common node;
+ ast_node node;
ast_expression_codegen *codegen;
int vtype;
ast_expression *next;
*/
ir_value *outl;
ir_value *outr;
-} ast_expression_common;
+};
#define AST_FLAG_VARIADIC (1<<0)
#define AST_FLAG_NORETURN (1<<1)
#define AST_FLAG_INLINE (1<<2)
} basic_value_t;
struct ast_value_s
{
- ast_expression_common expression;
+ ast_expression expression;
const char *name;
const char *desc;
*/
struct ast_binary_s
{
- ast_expression_common expression;
+ ast_expression expression;
int op;
ast_expression *left;
*/
struct ast_binstore_s
{
- ast_expression_common expression;
+ ast_expression expression;
int opstore;
int opbin;
*/
struct ast_unary_s
{
- ast_expression_common expression;
+ ast_expression expression;
int op;
ast_expression *operand;
*/
struct ast_return_s
{
- ast_expression_common expression;
+ ast_expression expression;
ast_expression *operand;
};
ast_return* ast_return_new(lex_ctx ctx,
*/
struct ast_entfield_s
{
- ast_expression_common 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 */
*/
struct ast_member_s
{
- ast_expression_common expression;
+ ast_expression expression;
ast_expression *owner;
unsigned int field;
const char *name;
*/
struct ast_array_index_s
{
- ast_expression_common expression;
+ ast_expression expression;
ast_expression *array;
ast_expression *index;
};
*/
struct ast_store_s
{
- ast_expression_common expression;
+ ast_expression expression;
int op;
ast_expression *dest;
ast_expression *source;
*/
struct ast_ifthen_s
{
- ast_expression_common expression;
+ ast_expression expression;
ast_expression *cond;
/* It's all just 'expressions', since an ast_block is one too. */
ast_expression *on_true;
*/
struct ast_ternary_s
{
- ast_expression_common expression;
+ ast_expression expression;
ast_expression *cond;
/* It's all just 'expressions', since an ast_block is one too. */
ast_expression *on_true;
*/
struct ast_loop_s
{
- ast_expression_common expression;
+ ast_expression expression;
ast_expression *initexpr;
ast_expression *precond;
ast_expression *postcond;
*/
struct ast_breakcont_s
{
- ast_expression_common expression;
+ ast_expression expression;
bool is_continue;
unsigned int levels;
};
} ast_switch_case;
struct ast_switch_s
{
- ast_expression_common expression;
+ ast_expression expression;
ast_expression *operand;
ast_switch_case *cases;
*/
struct ast_label_s
{
- ast_expression_common expression;
+ ast_expression expression;
const char *name;
ir_block *irblock;
ast_goto **gotos;
*/
struct ast_goto_s
{
- ast_expression_common expression;
+ ast_expression expression;
const char *name;
ast_label *target;
ir_block *irblock_from;
*/
struct ast_call_s
{
- ast_expression_common expression;
+ ast_expression expression;
ast_expression *func;
ast_expression* *params;
ast_expression *va_count;
*/
struct ast_block_s
{
- ast_expression_common expression;
+ ast_expression expression;
ast_value* *locals;
ast_expression* *exprs;
*/
struct ast_function_s
{
- ast_node_common node;
+ ast_node node;
ast_value *vtype;
const char *name;
bool ast_function_codegen(ast_function *self, ir_builder *builder);
bool ast_generate_accessors(ast_value *asvalue, ir_builder *ir);
-/* Expression union
- */
-union ast_expression_u
-{
- ast_expression_common expression;
-};
-
-/* Node union
- */
-union ast_node_u
-{
- ast_node_common node;
-};
-
#endif
blocks[i] = sy->out[vec_size(sy->out)+i].block;
asvalue[i] = (ast_value*)exprs[i];
- if (exprs[i]->expression.vtype == TYPE_NOEXPR &&
+ if (exprs[i]->vtype == TYPE_NOEXPR &&
!(i != 0 && op->id == opid2('?',':')) &&
!(i == 1 && op->id == opid1('.')))
{
}
#define NotSameType(T) \
- (exprs[0]->expression.vtype != exprs[1]->expression.vtype || \
- exprs[0]->expression.vtype != T)
+ (exprs[0]->vtype != exprs[1]->vtype || \
+ exprs[0]->vtype != T)
#define CanConstFold1(A) \
(ast_istype((A), ast_value) && ((ast_value*)(A))->hasvalue && (((ast_value*)(A))->cvq == CV_CONST) &&\
- (A)->expression.vtype != TYPE_FUNCTION)
+ (A)->vtype != TYPE_FUNCTION)
#define CanConstFold(A, B) \
(CanConstFold1(A) && CanConstFold1(B))
#define ConstV(i) (asvalue[(i)]->constval.vvec)
return false;
case opid1('.'):
- if (exprs[0]->expression.vtype == TYPE_VECTOR &&
- exprs[1]->expression.vtype == TYPE_NOEXPR)
+ if (exprs[0]->vtype == TYPE_VECTOR &&
+ exprs[1]->vtype == TYPE_NOEXPR)
{
if (exprs[1] == (ast_expression*)parser->const_vec[0])
out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, NULL);
return false;
}
}
- else if (exprs[0]->expression.vtype == TYPE_ENTITY) {
- if (exprs[1]->expression.vtype != TYPE_FIELD) {
+ else if (exprs[0]->vtype == TYPE_ENTITY) {
+ if (exprs[1]->vtype != TYPE_FIELD) {
compile_error(ast_ctx(exprs[1]), "type error: right hand of member-operand should be an entity-field");
return false;
}
out = (ast_expression*)ast_entfield_new(ctx, exprs[0], exprs[1]);
}
- else if (exprs[0]->expression.vtype == TYPE_VECTOR) {
+ else if (exprs[0]->vtype == TYPE_VECTOR) {
compile_error(ast_ctx(exprs[1]), "vectors cannot be accessed this way");
return false;
}
break;
case opid1('['):
- if (exprs[0]->expression.vtype != TYPE_ARRAY &&
- !(exprs[0]->expression.vtype == TYPE_FIELD &&
- exprs[0]->expression.next->expression.vtype == TYPE_ARRAY))
+ if (exprs[0]->vtype != TYPE_ARRAY &&
+ !(exprs[0]->vtype == TYPE_FIELD &&
+ exprs[0]->next->vtype == TYPE_ARRAY))
{
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
compile_error(ast_ctx(exprs[0]), "cannot index value of type %s", ty1);
return false;
}
- if (exprs[1]->expression.vtype != TYPE_FLOAT) {
+ if (exprs[1]->vtype != TYPE_FLOAT) {
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
compile_error(ast_ctx(exprs[1]), "index must be of type float, not %s", ty1);
return false;
out = exprs[0];
break;
case opid2('-','P'):
- switch (exprs[0]->expression.vtype) {
+ switch (exprs[0]->vtype) {
case TYPE_FLOAT:
if (CanConstFold1(exprs[0]))
out = (ast_expression*)parser_const_float(parser, -ConstF(0));
break;
default:
compile_error(ctx, "invalid types used in expression: cannot negate type %s",
- type_name[exprs[0]->expression.vtype]);
+ type_name[exprs[0]->vtype]);
return false;
}
break;
case opid2('!','P'):
- switch (exprs[0]->expression.vtype) {
+ switch (exprs[0]->vtype) {
case TYPE_FLOAT:
if (CanConstFold1(exprs[0]))
out = (ast_expression*)parser_const_float(parser, !ConstF(0));
break;
default:
compile_error(ctx, "invalid types used in expression: cannot logically negate type %s",
- type_name[exprs[0]->expression.vtype]);
+ type_name[exprs[0]->vtype]);
return false;
}
break;
case opid1('+'):
- if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
- (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
+ if (exprs[0]->vtype != exprs[1]->vtype ||
+ (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
{
compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
- type_name[exprs[0]->expression.vtype],
- type_name[exprs[1]->expression.vtype]);
+ type_name[exprs[0]->vtype],
+ type_name[exprs[1]->vtype]);
return false;
}
- switch (exprs[0]->expression.vtype) {
+ switch (exprs[0]->vtype) {
case TYPE_FLOAT:
if (CanConstFold(exprs[0], exprs[1]))
{
break;
default:
compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
- type_name[exprs[0]->expression.vtype],
- type_name[exprs[1]->expression.vtype]);
+ type_name[exprs[0]->vtype],
+ type_name[exprs[1]->vtype]);
return false;
};
break;
case opid1('-'):
- if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
- (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
+ if (exprs[0]->vtype != exprs[1]->vtype ||
+ (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
{
compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
- type_name[exprs[1]->expression.vtype],
- type_name[exprs[0]->expression.vtype]);
+ type_name[exprs[1]->vtype],
+ type_name[exprs[0]->vtype]);
return false;
}
- switch (exprs[0]->expression.vtype) {
+ switch (exprs[0]->vtype) {
case TYPE_FLOAT:
if (CanConstFold(exprs[0], exprs[1]))
out = (ast_expression*)parser_const_float(parser, ConstF(0) - ConstF(1));
break;
default:
compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
- type_name[exprs[1]->expression.vtype],
- type_name[exprs[0]->expression.vtype]);
+ type_name[exprs[1]->vtype],
+ type_name[exprs[0]->vtype]);
return false;
};
break;
case opid1('*'):
- if (exprs[0]->expression.vtype != exprs[1]->expression.vtype &&
- !(exprs[0]->expression.vtype == TYPE_VECTOR &&
- exprs[1]->expression.vtype == TYPE_FLOAT) &&
- !(exprs[1]->expression.vtype == TYPE_VECTOR &&
- exprs[0]->expression.vtype == TYPE_FLOAT)
+ if (exprs[0]->vtype != exprs[1]->vtype &&
+ !(exprs[0]->vtype == TYPE_VECTOR &&
+ exprs[1]->vtype == TYPE_FLOAT) &&
+ !(exprs[1]->vtype == TYPE_VECTOR &&
+ exprs[0]->vtype == TYPE_FLOAT)
)
{
compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
- type_name[exprs[1]->expression.vtype],
- type_name[exprs[0]->expression.vtype]);
+ type_name[exprs[1]->vtype],
+ type_name[exprs[0]->vtype]);
return false;
}
- switch (exprs[0]->expression.vtype) {
+ switch (exprs[0]->vtype) {
case TYPE_FLOAT:
- if (exprs[1]->expression.vtype == TYPE_VECTOR)
+ if (exprs[1]->vtype == TYPE_VECTOR)
{
if (CanConstFold(exprs[0], exprs[1]))
out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(1), ConstF(0)));
}
break;
case TYPE_VECTOR:
- if (exprs[1]->expression.vtype == TYPE_FLOAT)
+ if (exprs[1]->vtype == TYPE_FLOAT)
{
if (CanConstFold(exprs[0], exprs[1]))
out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(0), ConstF(1)));
if (!vec.y && !vec.z) { /* 'n 0 0' * v */
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
out = (ast_expression*)ast_member_new(ctx, exprs[1], 0, NULL);
- out->expression.node.keep = false;
+ out->node.keep = false;
((ast_member*)out)->rvalue = true;
if (vec.x != 1)
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.x), out);
else if (!vec.x && !vec.z) { /* '0 n 0' * v */
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
out = (ast_expression*)ast_member_new(ctx, exprs[1], 1, NULL);
- out->expression.node.keep = false;
+ out->node.keep = false;
((ast_member*)out)->rvalue = true;
if (vec.y != 1)
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.y), out);
else if (!vec.x && !vec.y) { /* '0 n 0' * v */
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
out = (ast_expression*)ast_member_new(ctx, exprs[1], 2, NULL);
- out->expression.node.keep = false;
+ out->node.keep = false;
((ast_member*)out)->rvalue = true;
if (vec.z != 1)
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.z), out);
if (!vec.y && !vec.z) { /* v * 'n 0 0' */
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, NULL);
- out->expression.node.keep = false;
+ out->node.keep = false;
((ast_member*)out)->rvalue = true;
if (vec.x != 1)
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.x));
else if (!vec.x && !vec.z) { /* v * '0 n 0' */
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
out = (ast_expression*)ast_member_new(ctx, exprs[0], 1, NULL);
- out->expression.node.keep = false;
+ out->node.keep = false;
((ast_member*)out)->rvalue = true;
if (vec.y != 1)
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.y));
else if (!vec.x && !vec.y) { /* v * '0 n 0' */
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
out = (ast_expression*)ast_member_new(ctx, exprs[0], 2, NULL);
- out->expression.node.keep = false;
+ out->node.keep = false;
((ast_member*)out)->rvalue = true;
if (vec.z != 1)
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.z));
break;
default:
compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
- type_name[exprs[1]->expression.vtype],
- type_name[exprs[0]->expression.vtype]);
+ type_name[exprs[1]->vtype],
+ type_name[exprs[0]->vtype]);
return false;
};
break;
case opid1('/'):
- if (exprs[1]->expression.vtype != TYPE_FLOAT) {
+ if (exprs[1]->vtype != TYPE_FLOAT) {
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
ast_type_to_string(exprs[1], ty2, sizeof(ty2));
compile_error(ctx, "invalid types used in expression: cannot divide tyeps %s and %s", ty1, ty2);
return false;
}
- if (exprs[0]->expression.vtype == TYPE_FLOAT) {
+ if (exprs[0]->vtype == TYPE_FLOAT) {
if (CanConstFold(exprs[0], exprs[1]))
out = (ast_expression*)parser_const_float(parser, ConstF(0) / ConstF(1));
else
out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, exprs[0], exprs[1]);
}
- else if (exprs[0]->expression.vtype == TYPE_VECTOR) {
+ else if (exprs[0]->vtype == TYPE_VECTOR) {
if (CanConstFold(exprs[0], exprs[1]))
out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(0), 1.0/ConstF(1)));
else {
case opid1('%'):
if (NotSameType(TYPE_FLOAT)) {
compile_error(ctx, "invalid types used in expression: cannot perform modulo operation between types %s and %s",
- type_name[exprs[0]->expression.vtype],
- type_name[exprs[1]->expression.vtype]);
+ type_name[exprs[0]->vtype],
+ type_name[exprs[1]->vtype]);
return false;
}
if (CanConstFold(exprs[0], exprs[1])) {
case opid1('&'):
if (NotSameType(TYPE_FLOAT)) {
compile_error(ctx, "invalid types used in expression: cannot perform bit operations between types %s and %s",
- type_name[exprs[0]->expression.vtype],
- type_name[exprs[1]->expression.vtype]);
+ type_name[exprs[0]->vtype],
+ type_name[exprs[1]->vtype]);
return false;
}
if (CanConstFold(exprs[0], exprs[1]))
return false;
}
for (i = 0; i < 2; ++i) {
- if (OPTS_FLAG(CORRECT_LOGIC) && exprs[i]->expression.vtype == TYPE_VECTOR) {
+ if (OPTS_FLAG(CORRECT_LOGIC) && exprs[i]->vtype == TYPE_VECTOR) {
out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[i]);
if (!out) break;
out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
break;
}
}
- else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && exprs[i]->expression.vtype == TYPE_STRING) {
+ else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && exprs[i]->vtype == TYPE_STRING) {
out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[i]);
if (!out) break;
out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
generated_op += INSTR_LE;
if (NotSameType(TYPE_FLOAT)) {
compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
- type_name[exprs[0]->expression.vtype],
- type_name[exprs[1]->expression.vtype]);
+ type_name[exprs[0]->vtype],
+ type_name[exprs[1]->vtype]);
return false;
}
out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
break;
case opid2('!', '='):
- if (exprs[0]->expression.vtype != exprs[1]->expression.vtype) {
+ if (exprs[0]->vtype != exprs[1]->vtype) {
compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
- type_name[exprs[0]->expression.vtype],
- type_name[exprs[1]->expression.vtype]);
+ type_name[exprs[0]->vtype],
+ type_name[exprs[1]->vtype]);
return false;
}
- out = (ast_expression*)ast_binary_new(ctx, type_ne_instr[exprs[0]->expression.vtype], exprs[0], exprs[1]);
+ out = (ast_expression*)ast_binary_new(ctx, type_ne_instr[exprs[0]->vtype], exprs[0], exprs[1]);
break;
case opid2('=', '='):
- if (exprs[0]->expression.vtype != exprs[1]->expression.vtype) {
+ if (exprs[0]->vtype != exprs[1]->vtype) {
compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
- type_name[exprs[0]->expression.vtype],
- type_name[exprs[1]->expression.vtype]);
+ type_name[exprs[0]->vtype],
+ type_name[exprs[1]->vtype]);
return false;
}
- out = (ast_expression*)ast_binary_new(ctx, type_eq_instr[exprs[0]->expression.vtype], exprs[0], exprs[1]);
+ out = (ast_expression*)ast_binary_new(ctx, type_eq_instr[exprs[0]->vtype], exprs[0], exprs[1]);
break;
case opid1('='):
if (ast_istype(exprs[0], ast_entfield)) {
ast_expression *field = ((ast_entfield*)exprs[0])->field;
if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
- exprs[0]->expression.vtype == TYPE_FIELD &&
- exprs[0]->expression.next->expression.vtype == TYPE_VECTOR)
+ exprs[0]->vtype == TYPE_FIELD &&
+ exprs[0]->next->vtype == TYPE_VECTOR)
{
assignop = type_storep_instr[TYPE_VECTOR];
}
else
- assignop = type_storep_instr[exprs[0]->expression.vtype];
- if (assignop == VINSTR_END || !ast_compare_type(field->expression.next, exprs[1]))
+ assignop = type_storep_instr[exprs[0]->vtype];
+ if (assignop == VINSTR_END || !ast_compare_type(field->next, exprs[1]))
{
- ast_type_to_string(field->expression.next, ty1, sizeof(ty1));
+ ast_type_to_string(field->next, ty1, sizeof(ty1));
ast_type_to_string(exprs[1], ty2, sizeof(ty2));
if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
- field->expression.next->expression.vtype == TYPE_FUNCTION &&
- exprs[1]->expression.vtype == TYPE_FUNCTION)
+ field->next->vtype == TYPE_FUNCTION &&
+ exprs[1]->vtype == TYPE_FUNCTION)
{
(void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
"invalid types in assignment: cannot assign %s to %s", ty2, ty1);
else
{
if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
- exprs[0]->expression.vtype == TYPE_FIELD &&
- exprs[0]->expression.next->expression.vtype == TYPE_VECTOR)
+ exprs[0]->vtype == TYPE_FIELD &&
+ exprs[0]->next->vtype == TYPE_VECTOR)
{
assignop = type_store_instr[TYPE_VECTOR];
}
else {
- assignop = type_store_instr[exprs[0]->expression.vtype];
+ assignop = type_store_instr[exprs[0]->vtype];
}
if (assignop == VINSTR_END) {
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
ast_type_to_string(exprs[1], ty2, sizeof(ty2));
if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
- exprs[0]->expression.vtype == TYPE_FUNCTION &&
- exprs[1]->expression.vtype == TYPE_FUNCTION)
+ exprs[0]->vtype == TYPE_FUNCTION &&
+ exprs[1]->vtype == TYPE_FUNCTION)
{
(void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
"invalid types in assignment: cannot assign %s to %s", ty2, ty1);
case opid3('+','+','P'):
case opid3('-','-','P'):
/* prefix ++ */
- if (exprs[0]->expression.vtype != TYPE_FLOAT) {
+ if (exprs[0]->vtype != TYPE_FLOAT) {
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
compile_error(ast_ctx(exprs[0]), "invalid type for prefix increment: %s", ty1);
return false;
case opid3('S','+','+'):
case opid3('S','-','-'):
/* prefix ++ */
- if (exprs[0]->expression.vtype != TYPE_FLOAT) {
+ if (exprs[0]->vtype != TYPE_FLOAT) {
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
compile_error(ast_ctx(exprs[0]), "invalid type for suffix increment: %s", ty1);
return false;
break;
case opid2('+','='):
case opid2('-','='):
- if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
- (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
+ if (exprs[0]->vtype != exprs[1]->vtype ||
+ (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
{
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
ast_type_to_string(exprs[1], ty2, sizeof(ty2));
compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
}
if (ast_istype(exprs[0], ast_entfield))
- assignop = type_storep_instr[exprs[0]->expression.vtype];
+ assignop = type_storep_instr[exprs[0]->vtype];
else
- assignop = type_store_instr[exprs[0]->expression.vtype];
- switch (exprs[0]->expression.vtype) {
+ assignop = type_store_instr[exprs[0]->vtype];
+ switch (exprs[0]->vtype) {
case TYPE_FLOAT:
out = (ast_expression*)ast_binstore_new(ctx, assignop,
(op->id == opid2('+','=') ? INSTR_ADD_F : INSTR_SUB_F),
break;
default:
compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
- type_name[exprs[0]->expression.vtype],
- type_name[exprs[1]->expression.vtype]);
+ type_name[exprs[0]->vtype],
+ type_name[exprs[1]->vtype]);
return false;
};
break;
case opid2('*','='):
case opid2('/','='):
- if (exprs[1]->expression.vtype != TYPE_FLOAT ||
- !(exprs[0]->expression.vtype == TYPE_FLOAT ||
- exprs[0]->expression.vtype == TYPE_VECTOR))
+ if (exprs[1]->vtype != TYPE_FLOAT ||
+ !(exprs[0]->vtype == TYPE_FLOAT ||
+ exprs[0]->vtype == TYPE_VECTOR))
{
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
ast_type_to_string(exprs[1], ty2, sizeof(ty2));
compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
}
if (ast_istype(exprs[0], ast_entfield))
- assignop = type_storep_instr[exprs[0]->expression.vtype];
+ assignop = type_storep_instr[exprs[0]->vtype];
else
- assignop = type_store_instr[exprs[0]->expression.vtype];
- switch (exprs[0]->expression.vtype) {
+ assignop = type_store_instr[exprs[0]->vtype];
+ switch (exprs[0]->vtype) {
case TYPE_FLOAT:
out = (ast_expression*)ast_binstore_new(ctx, assignop,
(op->id == opid2('*','=') ? INSTR_MUL_F : INSTR_DIV_F),
break;
default:
compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
- type_name[exprs[0]->expression.vtype],
- type_name[exprs[1]->expression.vtype]);
+ type_name[exprs[0]->vtype],
+ type_name[exprs[1]->vtype]);
return false;
};
break;
compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
}
if (ast_istype(exprs[0], ast_entfield))
- assignop = type_storep_instr[exprs[0]->expression.vtype];
+ assignop = type_storep_instr[exprs[0]->vtype];
else
- assignop = type_store_instr[exprs[0]->expression.vtype];
+ assignop = type_store_instr[exprs[0]->vtype];
out = (ast_expression*)ast_binstore_new(ctx, assignop,
(op->id == opid2('&','=') ? INSTR_BITAND : INSTR_BITOR),
exprs[0], exprs[1]);
return false;
}
if (ast_istype(exprs[0], ast_entfield))
- assignop = type_storep_instr[exprs[0]->expression.vtype];
+ assignop = type_storep_instr[exprs[0]->vtype];
else
- assignop = type_store_instr[exprs[0]->expression.vtype];
+ assignop = type_store_instr[exprs[0]->vtype];
out = (ast_expression*)ast_binary_new(ctx, INSTR_BITAND, exprs[0], exprs[1]);
if (!out)
return false;
break;
case opid2('~', 'P'):
- if (exprs[0]->expression.vtype != TYPE_FLOAT) {
+ if (exprs[0]->vtype != TYPE_FLOAT) {
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
compile_error(ast_ctx(exprs[0]), "invalid type for bit not: %s", ty1);
return false;
if (ast_istype(fun, ast_value)) {
funval = (ast_value*)fun;
- if ((fun->expression.flags & AST_FLAG_VARIADIC) &&
+ if ((fun->flags & AST_FLAG_VARIADIC) &&
!(/*funval->cvq == CV_CONST && */ funval->hasvalue && funval->constval.vfunc->builtin))
{
call->va_count = (ast_expression*)parser_const_float(parser, (double)paramcount);
/* overwrite fid, the function, with a call */
sy->out[fid] = syexp(call->expression.node.context, (ast_expression*)call);
- if (fun->expression.vtype != TYPE_FUNCTION) {
- parseerror(parser, "not a function (%s)", type_name[fun->expression.vtype]);
+ if (fun->vtype != TYPE_FUNCTION) {
+ parseerror(parser, "not a function (%s)", type_name[fun->vtype]);
return false;
}
- if (!fun->expression.next) {
+ if (!fun->next) {
parseerror(parser, "could not determine function return type");
return false;
} else {
ast_value *fval = (ast_istype(fun, ast_value) ? ((ast_value*)fun) : NULL);
- if (fun->expression.flags & AST_FLAG_DEPRECATED) {
+ if (fun->flags & AST_FLAG_DEPRECATED) {
if (!fval) {
return !parsewarning(parser, WARN_DEPRECATED,
"call to function (which is marked deprecated)\n",
ast_ctx(fun).line);
}
- if (vec_size(fun->expression.params) != paramcount &&
- !((fun->expression.flags & AST_FLAG_VARIADIC) &&
- vec_size(fun->expression.params) < paramcount))
+ if (vec_size(fun->params) != paramcount &&
+ !((fun->flags & AST_FLAG_VARIADIC) &&
+ vec_size(fun->params) < paramcount))
{
- const char *fewmany = (vec_size(fun->expression.params) > paramcount) ? "few" : "many";
+ const char *fewmany = (vec_size(fun->params) > paramcount) ? "few" : "many";
if (fval)
return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
"too %s parameters for call to %s: expected %i, got %i\n"
" -> `%s` has been declared here: %s:%i",
- fewmany, fval->name, (int)vec_size(fun->expression.params), (int)paramcount,
+ fewmany, fval->name, (int)vec_size(fun->params), (int)paramcount,
fval->name, ast_ctx(fun).file, (int)ast_ctx(fun).line);
else
return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
"too %s parameters for function call: expected %i, got %i\n"
" -> it has been declared here: %s:%i",
- fewmany, (int)vec_size(fun->expression.params), (int)paramcount,
+ fewmany, (int)vec_size(fun->params), (int)paramcount,
ast_ctx(fun).file, (int)ast_ctx(fun).line);
}
}
/* When adding more intrinsics, fix the above condition */
prev = NULL;
}
- if (prev && prev->expression.vtype == TYPE_VECTOR && ctoken[0] >= 'x' && ctoken[0] <= 'z' && !ctoken[1])
+ if (prev && prev->vtype == TYPE_VECTOR && ctoken[0] >= 'x' && ctoken[0] <= 'z' && !ctoken[1])
{
var = (ast_expression*)parser->const_vec[ctoken[0]-'x'];
} else {
ast_unary *unary;
ast_expression *prev;
- if (cond->expression.vtype == TYPE_VOID || cond->expression.vtype >= TYPE_VARIANT) {
+ if (cond->vtype == TYPE_VOID || cond->vtype >= TYPE_VARIANT) {
char ty[1024];
ast_type_to_string(cond, ty, sizeof(ty));
compile_error(ast_ctx(cond), "invalid type for if() condition: %s", ty);
}
- if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->expression.vtype == TYPE_STRING)
+ if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->vtype == TYPE_STRING)
{
prev = cond;
cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_S, cond);
}
ifnot = !ifnot;
}
- else if (OPTS_FLAG(CORRECT_LOGIC) && cond->expression.vtype == TYPE_VECTOR)
+ else if (OPTS_FLAG(CORRECT_LOGIC) && cond->vtype == TYPE_VECTOR)
{
/* vector types need to be cast to true booleans */
ast_binary *bin = (ast_binary*)cond;
if (!exp)
return false;
- if (exp->expression.vtype != TYPE_NIL &&
- exp->expression.vtype != expected->expression.next->expression.vtype)
+ if (exp->vtype != TYPE_NIL &&
+ exp->vtype != ((ast_expression*)expected)->next->vtype)
{
parseerror(parser, "return with invalid expression");
}
} else {
if (!parser_next(parser))
parseerror(parser, "parse error");
- if (expected->expression.next->expression.vtype != TYPE_VOID) {
+ if (expected->expression.next->vtype != TYPE_VOID) {
(void)!parsewarning(parser, WARN_MISSING_RETURN_VALUES, "return without value");
}
ret = ast_return_new(ctx, NULL);
/* qc allows the use of not-yet-declared functions here
* - this automatically creates a prototype */
ast_value *thinkfunc;
- ast_expression *functype = fld_think->expression.next;
+ ast_expression *functype = fld_think->next;
- thinkfunc = ast_value_new(parser_ctx(parser), parser_tokval(parser), functype->expression.vtype);
+ thinkfunc = ast_value_new(parser_ctx(parser), parser_tokval(parser), functype->vtype);
if (!thinkfunc) { /* || !ast_type_adopt(thinkfunc, functype)*/
ast_unref(framenum);
parseerror(parser, "failed to create implicit prototype for `%s`", parser_tokval(parser));
if (param->expression.vtype != TYPE_VECTOR &&
(param->expression.vtype != TYPE_FIELD ||
- param->expression.next->expression.vtype != TYPE_VECTOR))
+ param->expression.next->vtype != TYPE_VECTOR))
{
continue;
}
ast_store *st;
int assignop = type_store_instr[value->expression.vtype];
- if (value->expression.vtype == TYPE_FIELD && value->expression.next->expression.vtype == TYPE_VECTOR)
+ if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR)
assignop = INSTR_STORE_V;
subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from));
ast_store *st;
int assignop = type_storep_instr[value->expression.vtype];
- if (value->expression.vtype == TYPE_FIELD && value->expression.next->expression.vtype == TYPE_VECTOR)
+ if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR)
assignop = INSTR_STOREP_V;
subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from));
{
/* deal with other globals */
old = parser_find_global(parser, var->name);
- if (old && var->expression.vtype == TYPE_FUNCTION && old->expression.vtype == TYPE_FUNCTION)
+ if (old && var->expression.vtype == TYPE_FUNCTION && old->vtype == TYPE_FUNCTION)
{
/* This is a function which had a prototype */
if (!ast_istype(old, ast_value)) {
if (var->expression.vtype == TYPE_VECTOR)
isvector = true;
else if (var->expression.vtype == TYPE_FIELD &&
- var->expression.next->expression.vtype == TYPE_VECTOR)
+ var->expression.next->vtype == TYPE_VECTOR)
isvector = true;
if (isvector) {
return false;
}
- if (var->expression.vtype != find->expression.vtype) {
+ if (var->expression.vtype != find->vtype) {
char ty1[1024];
char ty2[1024];
}
else if (!localblock && !nofields &&
var->expression.vtype == TYPE_FIELD &&
- var->expression.next->expression.vtype == TYPE_ARRAY)
+ var->expression.next->vtype == TYPE_ARRAY)
{
char name[1024];
ast_expression *telem;
if (!ast_istype(parser->fields[i], ast_value))
continue;
value = (ast_value*)(parser->fields[i]);
- switch (value->expression.next->expression.vtype) {
+ switch (value->expression.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;
ast_expression *subtype;
field->hasvalue = true;
subtype = field->expression.next;
- ifld = ir_builder_create_field(ir, field->name, subtype->expression.vtype);
- if (subtype->expression.vtype == TYPE_FIELD)
- ifld->fieldtype = subtype->expression.next->expression.vtype;
- else if (subtype->expression.vtype == TYPE_FUNCTION)
- ifld->outtype = subtype->expression.next->expression.vtype;
+ ifld = ir_builder_create_field(ir, field->name, subtype->vtype);
+ if (subtype->vtype == TYPE_FIELD)
+ ifld->fieldtype = subtype->next->vtype;
+ else if (subtype->vtype == TYPE_FUNCTION)
+ ifld->outtype = subtype->next->vtype;
(void)!ir_value_set_field(field->ir_v, ifld);
}
}
}
for (i = 0; i < vec_size(parser->fields); ++i) {
ast_value *asvalue;
- asvalue = (ast_value*)(parser->fields[i]->expression.next);
+ asvalue = (ast_value*)(parser->fields[i]->next);
if (!ast_istype((ast_expression*)asvalue, ast_value))
continue;