mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2024-11-23 20:33:05 +00:00
Merge branch 'union-replacement' into cooking
Conflicts: ast.c
This commit is contained in:
commit
2923b718e1
3 changed files with 308 additions and 322 deletions
274
ast.c
274
ast.c
|
@ -34,7 +34,7 @@
|
||||||
return NULL; \
|
return NULL; \
|
||||||
} \
|
} \
|
||||||
ast_node_init((ast_node*)self, ctx, TYPE_##T); \
|
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
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* forward declarations, these need not be in ast.h for obvious
|
* forward declarations, these need not be in ast.h for obvious
|
||||||
|
@ -85,11 +85,11 @@ static GMQCC_NORETURN void _ast_node_destroy(ast_node *self)
|
||||||
/* Initialize main ast node aprts */
|
/* Initialize main ast node aprts */
|
||||||
static void ast_node_init(ast_node *self, lex_ctx ctx, int nodetype)
|
static void ast_node_init(ast_node *self, lex_ctx ctx, int nodetype)
|
||||||
{
|
{
|
||||||
self->node.context = ctx;
|
self->context = ctx;
|
||||||
self->node.destroy = &_ast_node_destroy;
|
self->destroy = &_ast_node_destroy;
|
||||||
self->node.keep = false;
|
self->keep = false;
|
||||||
self->node.nodetype = nodetype;
|
self->nodetype = nodetype;
|
||||||
self->node.side_effects = false;
|
self->side_effects = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* weight and side effects */
|
/* weight and side effects */
|
||||||
|
@ -104,28 +104,28 @@ static void _ast_propagate_effects(ast_node *self, ast_node *other)
|
||||||
static void ast_expression_init(ast_expression *self,
|
static void ast_expression_init(ast_expression *self,
|
||||||
ast_expression_codegen *codegen)
|
ast_expression_codegen *codegen)
|
||||||
{
|
{
|
||||||
self->expression.codegen = codegen;
|
self->codegen = codegen;
|
||||||
self->expression.vtype = TYPE_VOID;
|
self->vtype = TYPE_VOID;
|
||||||
self->expression.next = NULL;
|
self->next = NULL;
|
||||||
self->expression.outl = NULL;
|
self->outl = NULL;
|
||||||
self->expression.outr = NULL;
|
self->outr = NULL;
|
||||||
self->expression.params = NULL;
|
self->params = NULL;
|
||||||
self->expression.count = 0;
|
self->count = 0;
|
||||||
self->expression.flags = 0;
|
self->flags = 0;
|
||||||
self->expression.varparam = NULL;
|
self->varparam = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ast_expression_delete(ast_expression *self)
|
static void ast_expression_delete(ast_expression *self)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
if (self->expression.next)
|
if (self->next)
|
||||||
ast_delete(self->expression.next);
|
ast_delete(self->next);
|
||||||
for (i = 0; i < vec_size(self->expression.params); ++i) {
|
for (i = 0; i < vec_size(self->params); ++i) {
|
||||||
ast_delete(self->expression.params[i]);
|
ast_delete(self->params[i]);
|
||||||
}
|
}
|
||||||
vec_free(self->expression.params);
|
vec_free(self->params);
|
||||||
if (self->expression.varparam)
|
if (self->varparam)
|
||||||
ast_delete(self->expression.varparam);
|
ast_delete(self->varparam);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ast_expression_delete_full(ast_expression *self)
|
static void ast_expression_delete_full(ast_expression *self)
|
||||||
|
@ -137,8 +137,8 @@ static void ast_expression_delete_full(ast_expression *self)
|
||||||
ast_value* ast_value_copy(const ast_value *self)
|
ast_value* ast_value_copy(const ast_value *self)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
const ast_expression_common *fromex;
|
const ast_expression *fromex;
|
||||||
ast_expression_common *selfex;
|
ast_expression *selfex;
|
||||||
ast_value *cp = ast_value_new(self->expression.node.context, self->name, self->expression.vtype);
|
ast_value *cp = ast_value_new(self->expression.node.context, self->name, self->expression.vtype);
|
||||||
if (self->expression.next) {
|
if (self->expression.next) {
|
||||||
cp->expression.next = ast_type_copy(self->expression.node.context, self->expression.next);
|
cp->expression.next = ast_type_copy(self->expression.node.context, self->expression.next);
|
||||||
|
@ -157,14 +157,14 @@ ast_value* ast_value_copy(const ast_value *self)
|
||||||
void ast_type_adopt_impl(ast_expression *self, const ast_expression *other)
|
void ast_type_adopt_impl(ast_expression *self, const ast_expression *other)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
const ast_expression_common *fromex;
|
const ast_expression *fromex;
|
||||||
ast_expression_common *selfex;
|
ast_expression *selfex;
|
||||||
self->expression.vtype = other->expression.vtype;
|
self->vtype = other->vtype;
|
||||||
if (other->expression.next) {
|
if (other->next) {
|
||||||
self->expression.next = (ast_expression*)ast_type_copy(ast_ctx(self), other->expression.next);
|
self->next = (ast_expression*)ast_type_copy(ast_ctx(self), other->next);
|
||||||
}
|
}
|
||||||
fromex = &other->expression;
|
fromex = other;
|
||||||
selfex = &self->expression;
|
selfex = self;
|
||||||
selfex->count = fromex->count;
|
selfex->count = fromex->count;
|
||||||
selfex->flags = fromex->flags;
|
selfex->flags = fromex->flags;
|
||||||
for (i = 0; i < vec_size(fromex->params); ++i) {
|
for (i = 0; i < vec_size(fromex->params); ++i) {
|
||||||
|
@ -177,17 +177,17 @@ static ast_expression* ast_shallow_type(lex_ctx ctx, int vtype)
|
||||||
{
|
{
|
||||||
ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
|
ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
|
||||||
ast_expression_init(self, NULL);
|
ast_expression_init(self, NULL);
|
||||||
self->expression.codegen = NULL;
|
self->codegen = NULL;
|
||||||
self->expression.next = NULL;
|
self->next = NULL;
|
||||||
self->expression.vtype = vtype;
|
self->vtype = vtype;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex)
|
ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
const ast_expression_common *fromex;
|
const ast_expression *fromex;
|
||||||
ast_expression_common *selfex;
|
ast_expression *selfex;
|
||||||
|
|
||||||
if (!ex)
|
if (!ex)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -196,8 +196,8 @@ ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex)
|
||||||
ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
|
ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
|
||||||
ast_expression_init(self, NULL);
|
ast_expression_init(self, NULL);
|
||||||
|
|
||||||
fromex = &ex->expression;
|
fromex = ex;
|
||||||
selfex = &self->expression;
|
selfex = self;
|
||||||
|
|
||||||
/* This may never be codegen()d */
|
/* This may never be codegen()d */
|
||||||
selfex->codegen = NULL;
|
selfex->codegen = NULL;
|
||||||
|
@ -221,30 +221,30 @@ ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex)
|
||||||
|
|
||||||
bool ast_compare_type(ast_expression *a, ast_expression *b)
|
bool ast_compare_type(ast_expression *a, ast_expression *b)
|
||||||
{
|
{
|
||||||
if (a->expression.vtype == TYPE_NIL ||
|
if (a->vtype == TYPE_NIL ||
|
||||||
b->expression.vtype == TYPE_NIL)
|
b->vtype == TYPE_NIL)
|
||||||
return true;
|
return true;
|
||||||
if (a->expression.vtype != b->expression.vtype)
|
if (a->vtype != b->vtype)
|
||||||
return false;
|
return false;
|
||||||
if (!a->expression.next != !b->expression.next)
|
if (!a->next != !b->next)
|
||||||
return false;
|
return false;
|
||||||
if (vec_size(a->expression.params) != vec_size(b->expression.params))
|
if (vec_size(a->params) != vec_size(b->params))
|
||||||
return false;
|
return false;
|
||||||
if ((a->expression.flags & AST_FLAG_TYPE_MASK) !=
|
if ((a->flags & AST_FLAG_TYPE_MASK) !=
|
||||||
(b->expression.flags & AST_FLAG_TYPE_MASK) )
|
(b->flags & AST_FLAG_TYPE_MASK) )
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (vec_size(a->expression.params)) {
|
if (vec_size(a->params)) {
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < vec_size(a->expression.params); ++i) {
|
for (i = 0; i < vec_size(a->params); ++i) {
|
||||||
if (!ast_compare_type((ast_expression*)a->expression.params[i],
|
if (!ast_compare_type((ast_expression*)a->params[i],
|
||||||
(ast_expression*)b->expression.params[i]))
|
(ast_expression*)b->params[i]))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (a->expression.next)
|
if (a->next)
|
||||||
return ast_compare_type(a->expression.next, b->expression.next);
|
return ast_compare_type(a->next, b->next);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,43 +264,43 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi
|
||||||
if (pos + 1 >= bufsize)
|
if (pos + 1 >= bufsize)
|
||||||
goto full;
|
goto full;
|
||||||
|
|
||||||
switch (e->expression.vtype) {
|
switch (e->vtype) {
|
||||||
case TYPE_VARIANT:
|
case TYPE_VARIANT:
|
||||||
util_strncpy(buf + pos, "(variant)", 9);
|
util_strncpy(buf + pos, "(variant)", 9);
|
||||||
return pos + 9;
|
return pos + 9;
|
||||||
|
|
||||||
case TYPE_FIELD:
|
case TYPE_FIELD:
|
||||||
buf[pos++] = '.';
|
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:
|
case TYPE_POINTER:
|
||||||
if (pos + 3 >= bufsize)
|
if (pos + 3 >= bufsize)
|
||||||
goto full;
|
goto full;
|
||||||
buf[pos++] = '*';
|
buf[pos++] = '*';
|
||||||
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)
|
if (pos + 1 >= bufsize)
|
||||||
goto full;
|
goto full;
|
||||||
buf[pos++] = ')';
|
buf[pos++] = ')';
|
||||||
return pos;
|
return pos;
|
||||||
|
|
||||||
case TYPE_FUNCTION:
|
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)
|
if (pos + 2 >= bufsize)
|
||||||
goto full;
|
goto full;
|
||||||
if (!vec_size(e->expression.params)) {
|
if (!vec_size(e->params)) {
|
||||||
buf[pos++] = '(';
|
buf[pos++] = '(';
|
||||||
buf[pos++] = ')';
|
buf[pos++] = ')';
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
buf[pos++] = '(';
|
buf[pos++] = '(';
|
||||||
pos = ast_type_to_string_impl((ast_expression*)(e->expression.params[0]), buf, bufsize, pos);
|
pos = ast_type_to_string_impl((ast_expression*)(e->params[0]), buf, bufsize, pos);
|
||||||
for (i = 1; i < vec_size(e->expression.params); ++i) {
|
for (i = 1; i < vec_size(e->params); ++i) {
|
||||||
if (pos + 2 >= bufsize)
|
if (pos + 2 >= bufsize)
|
||||||
goto full;
|
goto full;
|
||||||
buf[pos++] = ',';
|
buf[pos++] = ',';
|
||||||
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)
|
if (pos + 1 >= bufsize)
|
||||||
goto full;
|
goto full;
|
||||||
|
@ -308,18 +308,18 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi
|
||||||
return pos;
|
return pos;
|
||||||
|
|
||||||
case TYPE_ARRAY:
|
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)
|
if (pos + 1 >= bufsize)
|
||||||
goto full;
|
goto full;
|
||||||
buf[pos++] = '[';
|
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)
|
if (pos + 1 >= bufsize)
|
||||||
goto full;
|
goto full;
|
||||||
buf[pos++] = ']';
|
buf[pos++] = ']';
|
||||||
return pos;
|
return pos;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
typestr = type_name[e->expression.vtype];
|
typestr = type_name[e->vtype];
|
||||||
typelen = strlen(typestr);
|
typelen = strlen(typestr);
|
||||||
if (pos + typelen >= bufsize)
|
if (pos + typelen >= bufsize)
|
||||||
goto full;
|
goto full;
|
||||||
|
@ -402,7 +402,7 @@ void ast_value_delete(ast_value* self)
|
||||||
mem_d(self->desc);
|
mem_d(self->desc);
|
||||||
|
|
||||||
if (self->initlist) {
|
if (self->initlist) {
|
||||||
if (self->expression.next->expression.vtype == TYPE_STRING) {
|
if (self->expression.next->vtype == TYPE_STRING) {
|
||||||
/* strings are allocated, free them */
|
/* strings are allocated, free them */
|
||||||
size_t i, len = vec_size(self->initlist);
|
size_t i, len = vec_size(self->initlist);
|
||||||
/* in theory, len should be expression.count
|
/* in theory, len should be expression.count
|
||||||
|
@ -460,7 +460,7 @@ ast_binary* ast_binary_new(lex_ctx ctx, int op,
|
||||||
else if (op == INSTR_MUL_V)
|
else if (op == INSTR_MUL_V)
|
||||||
self->expression.vtype = TYPE_FLOAT;
|
self->expression.vtype = TYPE_FLOAT;
|
||||||
else
|
else
|
||||||
self->expression.vtype = left->expression.vtype;
|
self->expression.vtype = left->vtype;
|
||||||
|
|
||||||
/* references all */
|
/* references all */
|
||||||
self->refs = AST_REF_ALL;
|
self->refs = AST_REF_ALL;
|
||||||
|
@ -554,11 +554,11 @@ void ast_return_delete(ast_return *self)
|
||||||
|
|
||||||
ast_entfield* ast_entfield_new(lex_ctx ctx, ast_expression *entity, ast_expression *field)
|
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");
|
compile_error(ctx, "ast_entfield_new with expression not of type field");
|
||||||
return NULL;
|
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)
|
ast_entfield* ast_entfield_new_force(lex_ctx ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype)
|
||||||
|
@ -598,9 +598,9 @@ ast_member* ast_member_new(lex_ctx ctx, ast_expression *owner, unsigned int fiel
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (owner->expression.vtype != TYPE_VECTOR &&
|
if (owner->vtype != TYPE_VECTOR &&
|
||||||
owner->expression.vtype != TYPE_FIELD) {
|
owner->vtype != TYPE_FIELD) {
|
||||||
compile_error(ctx, "member-access on an invalid owner of type %s", type_name[owner->expression.vtype]);
|
compile_error(ctx, "member-access on an invalid owner of type %s", type_name[owner->vtype]);
|
||||||
mem_d(self);
|
mem_d(self);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -608,7 +608,7 @@ ast_member* ast_member_new(lex_ctx ctx, ast_expression *owner, unsigned int fiel
|
||||||
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_member_codegen);
|
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_member_codegen);
|
||||||
self->expression.node.keep = true; /* keep */
|
self->expression.node.keep = true; /* keep */
|
||||||
|
|
||||||
if (owner->expression.vtype == TYPE_VECTOR) {
|
if (owner->vtype == TYPE_VECTOR) {
|
||||||
self->expression.vtype = TYPE_FLOAT;
|
self->expression.vtype = TYPE_FLOAT;
|
||||||
self->expression.next = NULL;
|
self->expression.next = NULL;
|
||||||
} else {
|
} else {
|
||||||
|
@ -657,7 +657,7 @@ ast_array_index* ast_array_index_new(lex_ctx ctx, ast_expression *array, ast_exp
|
||||||
ast_expression *outtype;
|
ast_expression *outtype;
|
||||||
ast_instantiate(ast_array_index, ctx, ast_array_index_delete);
|
ast_instantiate(ast_array_index, ctx, ast_array_index_delete);
|
||||||
|
|
||||||
outtype = array->expression.next;
|
outtype = array->next;
|
||||||
if (!outtype) {
|
if (!outtype) {
|
||||||
mem_d(self);
|
mem_d(self);
|
||||||
/* Error: field has no type... */
|
/* Error: field has no type... */
|
||||||
|
@ -672,7 +672,7 @@ ast_array_index* ast_array_index_new(lex_ctx ctx, ast_expression *array, ast_exp
|
||||||
ast_propagate_effects(self, index);
|
ast_propagate_effects(self, index);
|
||||||
|
|
||||||
ast_type_adopt(self, outtype);
|
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) {
|
if (self->expression.vtype != TYPE_ARRAY) {
|
||||||
compile_error(ast_ctx(self), "array_index node on type");
|
compile_error(ast_ctx(self), "array_index node on type");
|
||||||
ast_array_index_delete(self);
|
ast_array_index_delete(self);
|
||||||
|
@ -746,7 +746,7 @@ ast_ternary* ast_ternary_new(lex_ctx ctx, ast_expression *cond, ast_expression *
|
||||||
ast_propagate_effects(self, ontrue);
|
ast_propagate_effects(self, ontrue);
|
||||||
ast_propagate_effects(self, onfalse);
|
ast_propagate_effects(self, onfalse);
|
||||||
|
|
||||||
if (ontrue->expression.vtype == TYPE_NIL)
|
if (ontrue->vtype == TYPE_NIL)
|
||||||
exprtype = onfalse;
|
exprtype = onfalse;
|
||||||
ast_type_adopt(self, exprtype);
|
ast_type_adopt(self, exprtype);
|
||||||
|
|
||||||
|
@ -916,7 +916,7 @@ ast_call* ast_call_new(lex_ctx ctx,
|
||||||
ast_expression *funcexpr)
|
ast_expression *funcexpr)
|
||||||
{
|
{
|
||||||
ast_instantiate(ast_call, ctx, ast_call_delete);
|
ast_instantiate(ast_call, ctx, ast_call_delete);
|
||||||
if (!funcexpr->expression.next) {
|
if (!funcexpr->next) {
|
||||||
compile_error(ctx, "not a function");
|
compile_error(ctx, "not a function");
|
||||||
mem_d(self);
|
mem_d(self);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -929,7 +929,7 @@ ast_call* ast_call_new(lex_ctx ctx,
|
||||||
self->func = funcexpr;
|
self->func = funcexpr;
|
||||||
self->va_count = NULL;
|
self->va_count = NULL;
|
||||||
|
|
||||||
ast_type_adopt(self, funcexpr->expression.next);
|
ast_type_adopt(self, funcexpr->next);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -959,14 +959,14 @@ bool ast_call_check_types(ast_call *self)
|
||||||
bool retval = true;
|
bool retval = true;
|
||||||
const ast_expression *func = self->func;
|
const ast_expression *func = self->func;
|
||||||
size_t count = vec_size(self->params);
|
size_t count = vec_size(self->params);
|
||||||
if (count > vec_size(func->expression.params))
|
if (count > vec_size(func->params))
|
||||||
count = vec_size(func->expression.params);
|
count = vec_size(func->params);
|
||||||
|
|
||||||
for (i = 0; i < count; ++i) {
|
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(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",
|
compile_error(ast_ctx(self), "invalid type for parameter %u in function call: expected %s, got %s",
|
||||||
(unsigned int)(i+1), texp, tgot);
|
(unsigned int)(i+1), texp, tgot);
|
||||||
/* we don't immediately return */
|
/* we don't immediately return */
|
||||||
|
@ -974,12 +974,12 @@ bool ast_call_check_types(ast_call *self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
count = vec_size(self->params);
|
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) {
|
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(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",
|
compile_error(ast_ctx(self), "invalid type for parameter %u in function call: expected %s, got %s",
|
||||||
(unsigned int)(i+1), texp, tgot);
|
(unsigned int)(i+1), texp, tgot);
|
||||||
/* we don't immediately return */
|
/* we don't immediately return */
|
||||||
|
@ -1043,7 +1043,7 @@ bool ast_block_add_expr(ast_block *self, ast_expression *e)
|
||||||
void ast_block_collect(ast_block *self, ast_expression *expr)
|
void ast_block_collect(ast_block *self, ast_expression *expr)
|
||||||
{
|
{
|
||||||
vec_push(self->collect, expr);
|
vec_push(self->collect, expr);
|
||||||
expr->expression.node.keep = true;
|
expr->node.keep = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ast_block_delete(ast_block *self)
|
void ast_block_delete(ast_block *self)
|
||||||
|
@ -1170,12 +1170,12 @@ static const char* ast_function_label(ast_function *self, const char *prefix)
|
||||||
* But I can't imagine a pituation where the output is truly unnecessary.
|
* But I can't imagine a pituation where the output is truly unnecessary.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void _ast_codegen_output_type(ast_expression_common *self, ir_value *out)
|
static void _ast_codegen_output_type(ast_expression *self, ir_value *out)
|
||||||
{
|
{
|
||||||
if (out->vtype == TYPE_FIELD)
|
if (out->vtype == TYPE_FIELD)
|
||||||
out->fieldtype = self->next->expression.vtype;
|
out->fieldtype = self->next->vtype;
|
||||||
if (out->vtype == TYPE_FUNCTION)
|
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)))
|
#define codegen_output_type(a,o) (_ast_codegen_output_type(&((a)->expression),(o)))
|
||||||
|
@ -1216,7 +1216,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
|
||||||
|
|
||||||
if (self->hasvalue && self->expression.vtype == TYPE_FUNCTION)
|
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)
|
if (!func)
|
||||||
return false;
|
return false;
|
||||||
func->context = ast_ctx(self);
|
func->context = ast_ctx(self);
|
||||||
|
@ -1238,14 +1238,14 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldtype->expression.vtype == TYPE_ARRAY) {
|
if (fieldtype->vtype == TYPE_ARRAY) {
|
||||||
size_t ai;
|
size_t ai;
|
||||||
char *name;
|
char *name;
|
||||||
size_t namelen;
|
size_t namelen;
|
||||||
|
|
||||||
ast_expression_common *elemtype;
|
ast_expression *elemtype;
|
||||||
int vtype;
|
int vtype;
|
||||||
ast_value *array = (ast_value*)fieldtype;
|
ast_value *array = (ast_value*)fieldtype;
|
||||||
|
|
||||||
if (!ast_istype(fieldtype, ast_value)) {
|
if (!ast_istype(fieldtype, ast_value)) {
|
||||||
compile_error(ast_ctx(self), "internal error: ast_value required");
|
compile_error(ast_ctx(self), "internal error: ast_value required");
|
||||||
|
@ -1256,7 +1256,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
|
||||||
if (!array->expression.count || array->expression.count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE))
|
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);
|
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;
|
vtype = elemtype->vtype;
|
||||||
|
|
||||||
v = ir_builder_create_field(ir, self->name, vtype);
|
v = ir_builder_create_field(ir, self->name, vtype);
|
||||||
|
@ -1295,7 +1295,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
|
||||||
}
|
}
|
||||||
else
|
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)
|
if (!v)
|
||||||
return false;
|
return false;
|
||||||
v->context = ast_ctx(self);
|
v->context = ast_ctx(self);
|
||||||
|
@ -1311,7 +1311,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
|
||||||
char *name;
|
char *name;
|
||||||
size_t namelen;
|
size_t namelen;
|
||||||
|
|
||||||
ast_expression_common *elemtype = &self->expression.next->expression;
|
ast_expression *elemtype = self->expression.next;
|
||||||
int vtype = elemtype->vtype;
|
int vtype = elemtype->vtype;
|
||||||
|
|
||||||
/* same as with field arrays */
|
/* same as with field arrays */
|
||||||
|
@ -1441,7 +1441,7 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
|
||||||
char *name;
|
char *name;
|
||||||
size_t namelen;
|
size_t namelen;
|
||||||
|
|
||||||
ast_expression_common *elemtype = &self->expression.next->expression;
|
ast_expression *elemtype = self->expression.next;
|
||||||
int vtype = elemtype->vtype;
|
int vtype = elemtype->vtype;
|
||||||
|
|
||||||
func->flags |= IR_FLAG_HAS_ARRAYS;
|
func->flags |= IR_FLAG_HAS_ARRAYS;
|
||||||
|
@ -1588,7 +1588,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
|
||||||
{
|
{
|
||||||
ir_function *irf;
|
ir_function *irf;
|
||||||
ir_value *dummy;
|
ir_value *dummy;
|
||||||
ast_expression_common *ec;
|
ast_expression *ec;
|
||||||
ast_expression_codegen *cgen;
|
ast_expression_codegen *cgen;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
|
@ -1605,7 +1605,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
|
||||||
for (i = 0; i < vec_size(ec->params); ++i)
|
for (i = 0; i < vec_size(ec->params); ++i)
|
||||||
{
|
{
|
||||||
if (ec->params[i]->expression.vtype == TYPE_FIELD)
|
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
|
else
|
||||||
vec_push(irf->params, ec->params[i]->expression.vtype);
|
vec_push(irf->params, ec->params[i]->expression.vtype);
|
||||||
if (!self->builtin) {
|
if (!self->builtin) {
|
||||||
|
@ -1670,7 +1670,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
|
||||||
if (!self->curblock->final)
|
if (!self->curblock->final)
|
||||||
{
|
{
|
||||||
if (!self->vtype->expression.next ||
|
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 ir_block_create_return(self->curblock, ast_ctx(self), NULL);
|
||||||
}
|
}
|
||||||
|
@ -1739,7 +1739,7 @@ bool ast_block_codegen(ast_block *self, ast_function *func, bool lvalue, ir_valu
|
||||||
return false;
|
return false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
gen = self->exprs[i]->expression.codegen;
|
gen = self->exprs[i]->codegen;
|
||||||
if (!(*gen)(self->exprs[i], func, false, out))
|
if (!(*gen)(self->exprs[i], func, false, out))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1803,7 +1803,7 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu
|
||||||
if (!(*cgen)((ast_expression*)(arr->setter), func, true, &funval))
|
if (!(*cgen)((ast_expression*)(arr->setter), func, true, &funval))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cgen = self->source->expression.codegen;
|
cgen = self->source->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
|
if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -1818,13 +1818,13 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu
|
||||||
{
|
{
|
||||||
/* regular code */
|
/* regular code */
|
||||||
|
|
||||||
cgen = self->dest->expression.codegen;
|
cgen = self->dest->codegen;
|
||||||
/* lvalue! */
|
/* lvalue! */
|
||||||
if (!(*cgen)((ast_expression*)(self->dest), func, true, &left))
|
if (!(*cgen)((ast_expression*)(self->dest), func, true, &left))
|
||||||
return false;
|
return false;
|
||||||
self->expression.outl = left;
|
self->expression.outl = left;
|
||||||
|
|
||||||
cgen = self->source->expression.codegen;
|
cgen = self->source->codegen;
|
||||||
/* rvalue! */
|
/* rvalue! */
|
||||||
if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
|
if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
|
||||||
return false;
|
return false;
|
||||||
|
@ -1876,7 +1876,7 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
|
||||||
merge = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_merge"));
|
merge = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_merge"));
|
||||||
|
|
||||||
/* generate the left expression */
|
/* generate the left expression */
|
||||||
cgen = self->left->expression.codegen;
|
cgen = self->left->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->left), func, false, &left))
|
if (!(*cgen)((ast_expression*)(self->left), func, false, &left))
|
||||||
return false;
|
return false;
|
||||||
/* remember the block */
|
/* remember the block */
|
||||||
|
@ -1899,7 +1899,7 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
|
||||||
/* enter the right-expression's block */
|
/* enter the right-expression's block */
|
||||||
func->curblock = other;
|
func->curblock = other;
|
||||||
/* generate */
|
/* generate */
|
||||||
cgen = self->right->expression.codegen;
|
cgen = self->right->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->right), func, false, &right))
|
if (!(*cgen)((ast_expression*)(self->right), func, false, &right))
|
||||||
return false;
|
return false;
|
||||||
/* remember block */
|
/* remember block */
|
||||||
|
@ -1962,11 +1962,11 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cgen = self->left->expression.codegen;
|
cgen = self->left->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->left), func, false, &left))
|
if (!(*cgen)((ast_expression*)(self->left), func, false, &left))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cgen = self->right->expression.codegen;
|
cgen = self->right->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->right), func, false, &right))
|
if (!(*cgen)((ast_expression*)(self->right), func, false, &right))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -2017,12 +2017,12 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i
|
||||||
if (!(*cgen)((ast_expression*)(idx), func, false, &iridx))
|
if (!(*cgen)((ast_expression*)(idx), func, false, &iridx))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cgen = self->dest->expression.codegen;
|
cgen = self->dest->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->dest), func, false, &leftr))
|
if (!(*cgen)((ast_expression*)(self->dest), func, false, &leftr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* source as rvalue only */
|
/* source as rvalue only */
|
||||||
cgen = self->source->expression.codegen;
|
cgen = self->source->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
|
if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -2060,7 +2060,7 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i
|
||||||
self->expression.outr = bin;
|
self->expression.outr = bin;
|
||||||
} else {
|
} else {
|
||||||
/* now store them */
|
/* now store them */
|
||||||
cgen = self->dest->expression.codegen;
|
cgen = self->dest->codegen;
|
||||||
/* lvalue of destination */
|
/* lvalue of destination */
|
||||||
if (!(*cgen)((ast_expression*)(self->dest), func, true, &leftl))
|
if (!(*cgen)((ast_expression*)(self->dest), func, true, &leftl))
|
||||||
return false;
|
return false;
|
||||||
|
@ -2099,7 +2099,7 @@ bool ast_unary_codegen(ast_unary *self, ast_function *func, bool lvalue, ir_valu
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cgen = self->operand->expression.codegen;
|
cgen = self->operand->codegen;
|
||||||
/* lvalue! */
|
/* lvalue! */
|
||||||
if (!(*cgen)((ast_expression*)(self->operand), func, false, &operand))
|
if (!(*cgen)((ast_expression*)(self->operand), func, false, &operand))
|
||||||
return false;
|
return false;
|
||||||
|
@ -2135,7 +2135,7 @@ bool ast_return_codegen(ast_return *self, ast_function *func, bool lvalue, ir_va
|
||||||
self->expression.outr = (ir_value*)1;
|
self->expression.outr = (ir_value*)1;
|
||||||
|
|
||||||
if (self->operand) {
|
if (self->operand) {
|
||||||
cgen = self->operand->expression.codegen;
|
cgen = self->operand->codegen;
|
||||||
/* lvalue! */
|
/* lvalue! */
|
||||||
if (!(*cgen)((ast_expression*)(self->operand), func, false, &operand))
|
if (!(*cgen)((ast_expression*)(self->operand), func, false, &operand))
|
||||||
return false;
|
return false;
|
||||||
|
@ -2170,11 +2170,11 @@ bool ast_entfield_codegen(ast_entfield *self, ast_function *func, bool lvalue, i
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cgen = self->entity->expression.codegen;
|
cgen = self->entity->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->entity), func, false, &ent))
|
if (!(*cgen)((ast_expression*)(self->entity), func, false, &ent))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cgen = self->field->expression.codegen;
|
cgen = self->field->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->field), func, false, &field))
|
if (!(*cgen)((ast_expression*)(self->field), func, false, &field))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -2222,12 +2222,12 @@ bool ast_member_codegen(ast_member *self, ast_function *func, bool lvalue, ir_va
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cgen = self->owner->expression.codegen;
|
cgen = self->owner->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->owner), func, false, &vec))
|
if (!(*cgen)((ast_expression*)(self->owner), func, false, &vec))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (vec->vtype != TYPE_VECTOR &&
|
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;
|
||||||
}
|
}
|
||||||
|
@ -2281,7 +2281,7 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cgen = self->index->expression.codegen;
|
cgen = self->index->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->index), func, false, &iridx))
|
if (!(*cgen)((ast_expression*)(self->index), func, false, &iridx))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -2303,7 +2303,7 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva
|
||||||
|
|
||||||
if (idx->expression.vtype == TYPE_FLOAT) {
|
if (idx->expression.vtype == TYPE_FLOAT) {
|
||||||
unsigned int arridx = idx->constval.vfloat;
|
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);
|
compile_error(ast_ctx(self), "array index out of bounds: %i", arridx);
|
||||||
return false;
|
return false;
|
||||||
|
@ -2312,7 +2312,7 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva
|
||||||
}
|
}
|
||||||
else if (idx->expression.vtype == TYPE_INTEGER) {
|
else if (idx->expression.vtype == TYPE_INTEGER) {
|
||||||
unsigned int arridx = idx->constval.vint;
|
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);
|
compile_error(ast_ctx(self), "array index out of bounds: %i", arridx);
|
||||||
return false;
|
return false;
|
||||||
|
@ -2353,7 +2353,7 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va
|
||||||
self->expression.outr = (ir_value*)1;
|
self->expression.outr = (ir_value*)1;
|
||||||
|
|
||||||
/* generate the condition */
|
/* generate the condition */
|
||||||
cgen = self->cond->expression.codegen;
|
cgen = self->cond->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->cond), func, false, &condval))
|
if (!(*cgen)((ast_expression*)(self->cond), func, false, &condval))
|
||||||
return false;
|
return false;
|
||||||
/* update the block which will get the jump - because short-logic or ternaries may have changed this */
|
/* update the block which will get the jump - because short-logic or ternaries may have changed this */
|
||||||
|
@ -2371,7 +2371,7 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va
|
||||||
func->curblock = ontrue;
|
func->curblock = ontrue;
|
||||||
|
|
||||||
/* generate */
|
/* generate */
|
||||||
cgen = self->on_true->expression.codegen;
|
cgen = self->on_true->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->on_true), func, false, &dummy))
|
if (!(*cgen)((ast_expression*)(self->on_true), func, false, &dummy))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -2391,7 +2391,7 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va
|
||||||
func->curblock = onfalse;
|
func->curblock = onfalse;
|
||||||
|
|
||||||
/* generate */
|
/* generate */
|
||||||
cgen = self->on_false->expression.codegen;
|
cgen = self->on_false->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->on_false), func, false, &dummy))
|
if (!(*cgen)((ast_expression*)(self->on_false), func, false, &dummy))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -2460,7 +2460,7 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
|
||||||
|
|
||||||
/* generate the condition */
|
/* generate the condition */
|
||||||
func->curblock = cond;
|
func->curblock = cond;
|
||||||
cgen = self->cond->expression.codegen;
|
cgen = self->cond->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->cond), func, false, &condval))
|
if (!(*cgen)((ast_expression*)(self->cond), func, false, &condval))
|
||||||
return false;
|
return false;
|
||||||
cond_out = func->curblock;
|
cond_out = func->curblock;
|
||||||
|
@ -2475,7 +2475,7 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
|
||||||
func->curblock = ontrue;
|
func->curblock = ontrue;
|
||||||
|
|
||||||
/* generate */
|
/* generate */
|
||||||
cgen = self->on_true->expression.codegen;
|
cgen = self->on_true->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->on_true), func, false, &trueval))
|
if (!(*cgen)((ast_expression*)(self->on_true), func, false, &trueval))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -2492,7 +2492,7 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
|
||||||
func->curblock = onfalse;
|
func->curblock = onfalse;
|
||||||
|
|
||||||
/* generate */
|
/* generate */
|
||||||
cgen = self->on_false->expression.codegen;
|
cgen = self->on_false->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->on_false), func, false, &falseval))
|
if (!(*cgen)((ast_expression*)(self->on_false), func, false, &falseval))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -2589,7 +2589,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
|
||||||
*/
|
*/
|
||||||
if (self->initexpr)
|
if (self->initexpr)
|
||||||
{
|
{
|
||||||
cgen = self->initexpr->expression.codegen;
|
cgen = self->initexpr->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->initexpr), func, false, &dummy))
|
if (!(*cgen)((ast_expression*)(self->initexpr), func, false, &dummy))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2613,7 +2613,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
|
||||||
func->curblock = bprecond;
|
func->curblock = bprecond;
|
||||||
|
|
||||||
/* generate */
|
/* generate */
|
||||||
cgen = self->precond->expression.codegen;
|
cgen = self->precond->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->precond), func, false, &precond))
|
if (!(*cgen)((ast_expression*)(self->precond), func, false, &precond))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -2667,7 +2667,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
|
||||||
|
|
||||||
/* generate */
|
/* generate */
|
||||||
if (self->body) {
|
if (self->body) {
|
||||||
cgen = self->body->expression.codegen;
|
cgen = self->body->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->body), func, false, &dummy))
|
if (!(*cgen)((ast_expression*)(self->body), func, false, &dummy))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2684,7 +2684,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
|
||||||
func->curblock = bpostcond;
|
func->curblock = bpostcond;
|
||||||
|
|
||||||
/* generate */
|
/* generate */
|
||||||
cgen = self->postcond->expression.codegen;
|
cgen = self->postcond->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->postcond), func, false, &postcond))
|
if (!(*cgen)((ast_expression*)(self->postcond), func, false, &postcond))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -2698,7 +2698,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
|
||||||
func->curblock = bincrement;
|
func->curblock = bincrement;
|
||||||
|
|
||||||
/* generate */
|
/* generate */
|
||||||
cgen = self->increment->expression.codegen;
|
cgen = self->increment->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->increment), func, false, &dummy))
|
if (!(*cgen)((ast_expression*)(self->increment), func, false, &dummy))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -2847,7 +2847,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
|
||||||
(void)lvalue;
|
(void)lvalue;
|
||||||
(void)out;
|
(void)out;
|
||||||
|
|
||||||
cgen = self->operand->expression.codegen;
|
cgen = self->operand->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->operand), func, false, &irop))
|
if (!(*cgen)((ast_expression*)(self->operand), func, false, &irop))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -2880,7 +2880,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
|
||||||
if (swcase->value) {
|
if (swcase->value) {
|
||||||
/* A regular case */
|
/* A regular case */
|
||||||
/* generate the condition operand */
|
/* generate the condition operand */
|
||||||
cgen = swcase->value->expression.codegen;
|
cgen = swcase->value->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(swcase->value), func, false, &val))
|
if (!(*cgen)((ast_expression*)(swcase->value), func, false, &val))
|
||||||
return false;
|
return false;
|
||||||
/* generate the condition */
|
/* generate the condition */
|
||||||
|
@ -2908,7 +2908,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
|
||||||
|
|
||||||
/* enter the case */
|
/* enter the case */
|
||||||
func->curblock = bcase;
|
func->curblock = bcase;
|
||||||
cgen = swcase->code->expression.codegen;
|
cgen = swcase->code->codegen;
|
||||||
if (!(*cgen)((ast_expression*)swcase->code, func, false, &dummy))
|
if (!(*cgen)((ast_expression*)swcase->code, func, false, &dummy))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -2953,7 +2953,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now generate the default code */
|
/* 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))
|
if (!(*cgen)((ast_expression*)def_case->code, func, false, &dummy))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -3078,7 +3078,7 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cgen = self->func->expression.codegen;
|
cgen = self->func->codegen;
|
||||||
if (!(*cgen)((ast_expression*)(self->func), func, false, &funval))
|
if (!(*cgen)((ast_expression*)(self->func), func, false, &funval))
|
||||||
return false;
|
return false;
|
||||||
if (!funval)
|
if (!funval)
|
||||||
|
@ -3092,7 +3092,7 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value
|
||||||
ir_value *param;
|
ir_value *param;
|
||||||
ast_expression *expr = self->params[i];
|
ast_expression *expr = self->params[i];
|
||||||
|
|
||||||
cgen = expr->expression.codegen;
|
cgen = expr->codegen;
|
||||||
if (!(*cgen)(expr, func, false, ¶m))
|
if (!(*cgen)(expr, func, false, ¶m))
|
||||||
goto error;
|
goto error;
|
||||||
if (!param)
|
if (!param)
|
||||||
|
@ -3104,7 +3104,7 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value
|
||||||
if (self->va_count) {
|
if (self->va_count) {
|
||||||
ir_value *va_count;
|
ir_value *va_count;
|
||||||
ir_builder *builder = func->curblock->owner->owner;
|
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))
|
if (!(*cgen)((ast_expression*)(self->va_count), func, false, &va_count))
|
||||||
return false;
|
return false;
|
||||||
if (!ir_block_create_store_op(func->curblock, ast_ctx(self), INSTR_STORE_F,
|
if (!ir_block_create_store_op(func->curblock, ast_ctx(self), INSTR_STORE_F,
|
||||||
|
@ -3116,7 +3116,7 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value
|
||||||
|
|
||||||
callinstr = ir_block_create_call(func->curblock, ast_ctx(self),
|
callinstr = ir_block_create_call(func->curblock, ast_ctx(self),
|
||||||
ast_function_label(func, "call"),
|
ast_function_label(func, "call"),
|
||||||
funval, !!(self->func->expression.flags & AST_FLAG_NORETURN));
|
funval, !!(self->func->flags & AST_FLAG_NORETURN));
|
||||||
if (!callinstr)
|
if (!callinstr)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
|
84
ast.h
84
ast.h
|
@ -29,8 +29,8 @@
|
||||||
* "main" ast node types for now.
|
* "main" ast node types for now.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef union ast_node_u ast_node;
|
typedef struct ast_node_common ast_node;
|
||||||
typedef union ast_expression_u ast_expression;
|
typedef struct ast_expression_common ast_expression;
|
||||||
|
|
||||||
typedef struct ast_value_s ast_value;
|
typedef struct ast_value_s ast_value;
|
||||||
typedef struct ast_function_s ast_function;
|
typedef struct ast_function_s ast_function;
|
||||||
|
@ -76,14 +76,14 @@ enum {
|
||||||
TYPE_ast_goto /* 20 */
|
TYPE_ast_goto /* 20 */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ast_istype(x, t) ( ((ast_node_common*)x)->nodetype == (TYPE_##t) )
|
#define ast_istype(x, t) ( ((ast_node*)x)->nodetype == (TYPE_##t) )
|
||||||
#define ast_ctx(node) (((ast_node_common*)(node))->context)
|
#define ast_ctx(node) (((ast_node*)(node))->context)
|
||||||
#define ast_side_effects(node) (((ast_node_common*)(node))->side_effects)
|
#define ast_side_effects(node) (((ast_node*)(node))->side_effects)
|
||||||
|
|
||||||
/* Node interface with common components
|
/* Node interface with common components
|
||||||
*/
|
*/
|
||||||
typedef void ast_node_delete(ast_node*);
|
typedef void ast_node_delete(ast_node*);
|
||||||
typedef struct
|
struct ast_node_common
|
||||||
{
|
{
|
||||||
lex_ctx context;
|
lex_ctx context;
|
||||||
/* I don't feel comfortable using keywords like 'delete' as names... */
|
/* I don't feel comfortable using keywords like 'delete' as names... */
|
||||||
|
@ -94,14 +94,14 @@ typedef struct
|
||||||
*/
|
*/
|
||||||
bool keep;
|
bool keep;
|
||||||
bool side_effects;
|
bool side_effects;
|
||||||
} ast_node_common;
|
};
|
||||||
|
|
||||||
#define ast_delete(x) (*( ((ast_node*)(x))->node.destroy ))((ast_node*)(x))
|
#define ast_delete(x) (*( ((ast_node*)(x))->destroy ))((ast_node*)(x))
|
||||||
#define ast_unref(x) do \
|
#define ast_unref(x) do \
|
||||||
{ \
|
{ \
|
||||||
if (! (((ast_node*)(x))->node.keep) ) { \
|
if (! (((ast_node*)(x))->keep) ) { \
|
||||||
ast_delete(x); \
|
ast_delete(x); \
|
||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
/* Expression interface
|
/* Expression interface
|
||||||
|
@ -123,9 +123,9 @@ typedef bool ast_expression_codegen(ast_expression*,
|
||||||
* type `expression`, so the ast_ident's codegen would search for
|
* type `expression`, so the ast_ident's codegen would search for
|
||||||
* variables through the environment (or functions, constants...).
|
* variables through the environment (or functions, constants...).
|
||||||
*/
|
*/
|
||||||
typedef struct
|
struct ast_expression_common
|
||||||
{
|
{
|
||||||
ast_node_common node;
|
ast_node node;
|
||||||
ast_expression_codegen *codegen;
|
ast_expression_codegen *codegen;
|
||||||
int vtype;
|
int vtype;
|
||||||
ast_expression *next;
|
ast_expression *next;
|
||||||
|
@ -144,7 +144,7 @@ typedef struct
|
||||||
*/
|
*/
|
||||||
ir_value *outl;
|
ir_value *outl;
|
||||||
ir_value *outr;
|
ir_value *outr;
|
||||||
} ast_expression_common;
|
};
|
||||||
#define AST_FLAG_VARIADIC (1<<0)
|
#define AST_FLAG_VARIADIC (1<<0)
|
||||||
#define AST_FLAG_NORETURN (1<<1)
|
#define AST_FLAG_NORETURN (1<<1)
|
||||||
#define AST_FLAG_INLINE (1<<2)
|
#define AST_FLAG_INLINE (1<<2)
|
||||||
|
@ -173,7 +173,7 @@ typedef union {
|
||||||
} basic_value_t;
|
} basic_value_t;
|
||||||
struct ast_value_s
|
struct ast_value_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
|
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *desc;
|
const char *desc;
|
||||||
|
@ -243,7 +243,7 @@ typedef enum ast_binary_ref_s {
|
||||||
*/
|
*/
|
||||||
struct ast_binary_s
|
struct ast_binary_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
|
|
||||||
int op;
|
int op;
|
||||||
ast_expression *left;
|
ast_expression *left;
|
||||||
|
@ -263,7 +263,7 @@ ast_binary* ast_binary_new(lex_ctx ctx,
|
||||||
*/
|
*/
|
||||||
struct ast_binstore_s
|
struct ast_binstore_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
|
|
||||||
int opstore;
|
int opstore;
|
||||||
int opbin;
|
int opbin;
|
||||||
|
@ -284,7 +284,7 @@ ast_binstore* ast_binstore_new(lex_ctx ctx,
|
||||||
*/
|
*/
|
||||||
struct ast_unary_s
|
struct ast_unary_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
|
|
||||||
int op;
|
int op;
|
||||||
ast_expression *operand;
|
ast_expression *operand;
|
||||||
|
@ -301,7 +301,7 @@ ast_unary* ast_unary_new(lex_ctx ctx,
|
||||||
*/
|
*/
|
||||||
struct ast_return_s
|
struct ast_return_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
ast_expression *operand;
|
ast_expression *operand;
|
||||||
};
|
};
|
||||||
ast_return* ast_return_new(lex_ctx ctx,
|
ast_return* ast_return_new(lex_ctx ctx,
|
||||||
|
@ -322,7 +322,7 @@ ast_return* ast_return_new(lex_ctx ctx,
|
||||||
*/
|
*/
|
||||||
struct ast_entfield_s
|
struct ast_entfield_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
/* The entity can come from an expression of course. */
|
/* The entity can come from an expression of course. */
|
||||||
ast_expression *entity;
|
ast_expression *entity;
|
||||||
/* As can the field, it just must result in a value of TYPE_FIELD */
|
/* As can the field, it just must result in a value of TYPE_FIELD */
|
||||||
|
@ -338,7 +338,7 @@ ast_entfield* ast_entfield_new_force(lex_ctx ctx, ast_expression *entity, ast_ex
|
||||||
*/
|
*/
|
||||||
struct ast_member_s
|
struct ast_member_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
ast_expression *owner;
|
ast_expression *owner;
|
||||||
unsigned int field;
|
unsigned int field;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -361,7 +361,7 @@ bool ast_member_set_name(ast_member*, const char *name);
|
||||||
*/
|
*/
|
||||||
struct ast_array_index_s
|
struct ast_array_index_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
ast_expression *array;
|
ast_expression *array;
|
||||||
ast_expression *index;
|
ast_expression *index;
|
||||||
};
|
};
|
||||||
|
@ -374,7 +374,7 @@ ast_array_index* ast_array_index_new(lex_ctx ctx, ast_expression *array, ast_exp
|
||||||
*/
|
*/
|
||||||
struct ast_store_s
|
struct ast_store_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
int op;
|
int op;
|
||||||
ast_expression *dest;
|
ast_expression *dest;
|
||||||
ast_expression *source;
|
ast_expression *source;
|
||||||
|
@ -395,7 +395,7 @@ ast_store* ast_store_new(lex_ctx ctx, int op,
|
||||||
*/
|
*/
|
||||||
struct ast_ifthen_s
|
struct ast_ifthen_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
ast_expression *cond;
|
ast_expression *cond;
|
||||||
/* It's all just 'expressions', since an ast_block is one too. */
|
/* It's all just 'expressions', since an ast_block is one too. */
|
||||||
ast_expression *on_true;
|
ast_expression *on_true;
|
||||||
|
@ -418,7 +418,7 @@ ast_ifthen* ast_ifthen_new(lex_ctx ctx, ast_expression *cond, ast_expression *on
|
||||||
*/
|
*/
|
||||||
struct ast_ternary_s
|
struct ast_ternary_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
ast_expression *cond;
|
ast_expression *cond;
|
||||||
/* It's all just 'expressions', since an ast_block is one too. */
|
/* It's all just 'expressions', since an ast_block is one too. */
|
||||||
ast_expression *on_true;
|
ast_expression *on_true;
|
||||||
|
@ -451,7 +451,7 @@ continue: // a 'continue' will jump here
|
||||||
*/
|
*/
|
||||||
struct ast_loop_s
|
struct ast_loop_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
ast_expression *initexpr;
|
ast_expression *initexpr;
|
||||||
ast_expression *precond;
|
ast_expression *precond;
|
||||||
ast_expression *postcond;
|
ast_expression *postcond;
|
||||||
|
@ -477,7 +477,7 @@ ast_loop* ast_loop_new(lex_ctx ctx,
|
||||||
*/
|
*/
|
||||||
struct ast_breakcont_s
|
struct ast_breakcont_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
bool is_continue;
|
bool is_continue;
|
||||||
unsigned int levels;
|
unsigned int levels;
|
||||||
};
|
};
|
||||||
|
@ -499,7 +499,7 @@ typedef struct {
|
||||||
} ast_switch_case;
|
} ast_switch_case;
|
||||||
struct ast_switch_s
|
struct ast_switch_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
|
|
||||||
ast_expression *operand;
|
ast_expression *operand;
|
||||||
ast_switch_case *cases;
|
ast_switch_case *cases;
|
||||||
|
@ -513,7 +513,7 @@ ast_switch* ast_switch_new(lex_ctx ctx, ast_expression *op);
|
||||||
*/
|
*/
|
||||||
struct ast_label_s
|
struct ast_label_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
const char *name;
|
const char *name;
|
||||||
ir_block *irblock;
|
ir_block *irblock;
|
||||||
ast_goto **gotos;
|
ast_goto **gotos;
|
||||||
|
@ -529,7 +529,7 @@ ast_label* ast_label_new(lex_ctx ctx, const char *name, bool undefined);
|
||||||
*/
|
*/
|
||||||
struct ast_goto_s
|
struct ast_goto_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
const char *name;
|
const char *name;
|
||||||
ast_label *target;
|
ast_label *target;
|
||||||
ir_block *irblock_from;
|
ir_block *irblock_from;
|
||||||
|
@ -550,7 +550,7 @@ void ast_goto_set_label(ast_goto*, ast_label*);
|
||||||
*/
|
*/
|
||||||
struct ast_call_s
|
struct ast_call_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
ast_expression *func;
|
ast_expression *func;
|
||||||
ast_expression* *params;
|
ast_expression* *params;
|
||||||
ast_expression *va_count;
|
ast_expression *va_count;
|
||||||
|
@ -564,7 +564,7 @@ bool ast_call_check_types(ast_call*);
|
||||||
*/
|
*/
|
||||||
struct ast_block_s
|
struct ast_block_s
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression expression;
|
||||||
|
|
||||||
ast_value* *locals;
|
ast_value* *locals;
|
||||||
ast_expression* *exprs;
|
ast_expression* *exprs;
|
||||||
|
@ -589,7 +589,7 @@ bool GMQCC_WARN ast_block_add_expr(ast_block*, ast_expression*);
|
||||||
*/
|
*/
|
||||||
struct ast_function_s
|
struct ast_function_s
|
||||||
{
|
{
|
||||||
ast_node_common node;
|
ast_node node;
|
||||||
|
|
||||||
ast_value *vtype;
|
ast_value *vtype;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -634,18 +634,4 @@ void ast_function_delete(ast_function*);
|
||||||
bool ast_function_codegen(ast_function *self, ir_builder *builder);
|
bool ast_function_codegen(ast_function *self, ir_builder *builder);
|
||||||
bool ast_generate_accessors(ast_value *asvalue, ir_builder *ir);
|
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
|
#endif
|
||||||
|
|
272
parser.c
272
parser.c
|
@ -585,7 +585,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
blocks[i] = sy->out[vec_size(sy->out)+i].block;
|
blocks[i] = sy->out[vec_size(sy->out)+i].block;
|
||||||
asvalue[i] = (ast_value*)exprs[i];
|
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 != 0 && op->id == opid2('?',':')) &&
|
||||||
!(i == 1 && op->id == opid1('.')))
|
!(i == 1 && op->id == opid1('.')))
|
||||||
{
|
{
|
||||||
|
@ -603,11 +603,11 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NotSameType(T) \
|
#define NotSameType(T) \
|
||||||
(exprs[0]->expression.vtype != exprs[1]->expression.vtype || \
|
(exprs[0]->vtype != exprs[1]->vtype || \
|
||||||
exprs[0]->expression.vtype != T)
|
exprs[0]->vtype != T)
|
||||||
#define CanConstFold1(A) \
|
#define CanConstFold1(A) \
|
||||||
(ast_istype((A), ast_value) && ((ast_value*)(A))->hasvalue && (((ast_value*)(A))->cvq == CV_CONST) &&\
|
(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) \
|
#define CanConstFold(A, B) \
|
||||||
(CanConstFold1(A) && CanConstFold1(B))
|
(CanConstFold1(A) && CanConstFold1(B))
|
||||||
#define ConstV(i) (asvalue[(i)]->constval.vvec)
|
#define ConstV(i) (asvalue[(i)]->constval.vvec)
|
||||||
|
@ -620,8 +620,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case opid1('.'):
|
case opid1('.'):
|
||||||
if (exprs[0]->expression.vtype == TYPE_VECTOR &&
|
if (exprs[0]->vtype == TYPE_VECTOR &&
|
||||||
exprs[1]->expression.vtype == TYPE_NOEXPR)
|
exprs[1]->vtype == TYPE_NOEXPR)
|
||||||
{
|
{
|
||||||
if (exprs[1] == (ast_expression*)parser->const_vec[0])
|
if (exprs[1] == (ast_expression*)parser->const_vec[0])
|
||||||
out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, NULL);
|
out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, NULL);
|
||||||
|
@ -634,14 +634,14 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (exprs[0]->expression.vtype == TYPE_ENTITY) {
|
else if (exprs[0]->vtype == TYPE_ENTITY) {
|
||||||
if (exprs[1]->expression.vtype != TYPE_FIELD) {
|
if (exprs[1]->vtype != TYPE_FIELD) {
|
||||||
compile_error(ast_ctx(exprs[1]), "type error: right hand of member-operand should be an entity-field");
|
compile_error(ast_ctx(exprs[1]), "type error: right hand of member-operand should be an entity-field");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
out = (ast_expression*)ast_entfield_new(ctx, exprs[0], exprs[1]);
|
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");
|
compile_error(ast_ctx(exprs[1]), "vectors cannot be accessed this way");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -652,15 +652,15 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case opid1('['):
|
case opid1('['):
|
||||||
if (exprs[0]->expression.vtype != TYPE_ARRAY &&
|
if (exprs[0]->vtype != TYPE_ARRAY &&
|
||||||
!(exprs[0]->expression.vtype == TYPE_FIELD &&
|
!(exprs[0]->vtype == TYPE_FIELD &&
|
||||||
exprs[0]->expression.next->expression.vtype == TYPE_ARRAY))
|
exprs[0]->next->vtype == TYPE_ARRAY))
|
||||||
{
|
{
|
||||||
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
|
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
|
||||||
compile_error(ast_ctx(exprs[0]), "cannot index value of type %s", ty1);
|
compile_error(ast_ctx(exprs[0]), "cannot index value of type %s", ty1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
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[0], ty1, sizeof(ty1));
|
||||||
compile_error(ast_ctx(exprs[1]), "index must be of type float, not %s", ty1);
|
compile_error(ast_ctx(exprs[1]), "index must be of type float, not %s", ty1);
|
||||||
return false;
|
return false;
|
||||||
|
@ -707,7 +707,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
out = exprs[0];
|
out = exprs[0];
|
||||||
break;
|
break;
|
||||||
case opid2('-','P'):
|
case opid2('-','P'):
|
||||||
switch (exprs[0]->expression.vtype) {
|
switch (exprs[0]->vtype) {
|
||||||
case TYPE_FLOAT:
|
case TYPE_FLOAT:
|
||||||
if (CanConstFold1(exprs[0]))
|
if (CanConstFold1(exprs[0]))
|
||||||
out = (ast_expression*)parser_const_float(parser, -ConstF(0));
|
out = (ast_expression*)parser_const_float(parser, -ConstF(0));
|
||||||
|
@ -727,13 +727,13 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
compile_error(ctx, "invalid types used in expression: cannot negate type %s",
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case opid2('!','P'):
|
case opid2('!','P'):
|
||||||
switch (exprs[0]->expression.vtype) {
|
switch (exprs[0]->vtype) {
|
||||||
case TYPE_FLOAT:
|
case TYPE_FLOAT:
|
||||||
if (CanConstFold1(exprs[0]))
|
if (CanConstFold1(exprs[0]))
|
||||||
out = (ast_expression*)parser_const_float(parser, !ConstF(0));
|
out = (ast_expression*)parser_const_float(parser, !ConstF(0));
|
||||||
|
@ -769,21 +769,21 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
compile_error(ctx, "invalid types used in expression: cannot logically negate type %s",
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case opid1('+'):
|
case opid1('+'):
|
||||||
if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
|
if (exprs[0]->vtype != exprs[1]->vtype ||
|
||||||
(exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
|
(exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
|
||||||
{
|
{
|
||||||
compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
|
compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
|
||||||
type_name[exprs[0]->expression.vtype],
|
type_name[exprs[0]->vtype],
|
||||||
type_name[exprs[1]->expression.vtype]);
|
type_name[exprs[1]->vtype]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch (exprs[0]->expression.vtype) {
|
switch (exprs[0]->vtype) {
|
||||||
case TYPE_FLOAT:
|
case TYPE_FLOAT:
|
||||||
if (CanConstFold(exprs[0], exprs[1]))
|
if (CanConstFold(exprs[0], exprs[1]))
|
||||||
{
|
{
|
||||||
|
@ -800,21 +800,21 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
|
compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
|
||||||
type_name[exprs[0]->expression.vtype],
|
type_name[exprs[0]->vtype],
|
||||||
type_name[exprs[1]->expression.vtype]);
|
type_name[exprs[1]->vtype]);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case opid1('-'):
|
case opid1('-'):
|
||||||
if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
|
if (exprs[0]->vtype != exprs[1]->vtype ||
|
||||||
(exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
|
(exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
|
||||||
{
|
{
|
||||||
compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
|
compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
|
||||||
type_name[exprs[1]->expression.vtype],
|
type_name[exprs[1]->vtype],
|
||||||
type_name[exprs[0]->expression.vtype]);
|
type_name[exprs[0]->vtype]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch (exprs[0]->expression.vtype) {
|
switch (exprs[0]->vtype) {
|
||||||
case TYPE_FLOAT:
|
case TYPE_FLOAT:
|
||||||
if (CanConstFold(exprs[0], exprs[1]))
|
if (CanConstFold(exprs[0], exprs[1]))
|
||||||
out = (ast_expression*)parser_const_float(parser, ConstF(0) - ConstF(1));
|
out = (ast_expression*)parser_const_float(parser, ConstF(0) - ConstF(1));
|
||||||
|
@ -829,27 +829,27 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
|
compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
|
||||||
type_name[exprs[1]->expression.vtype],
|
type_name[exprs[1]->vtype],
|
||||||
type_name[exprs[0]->expression.vtype]);
|
type_name[exprs[0]->vtype]);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case opid1('*'):
|
case opid1('*'):
|
||||||
if (exprs[0]->expression.vtype != exprs[1]->expression.vtype &&
|
if (exprs[0]->vtype != exprs[1]->vtype &&
|
||||||
!(exprs[0]->expression.vtype == TYPE_VECTOR &&
|
!(exprs[0]->vtype == TYPE_VECTOR &&
|
||||||
exprs[1]->expression.vtype == TYPE_FLOAT) &&
|
exprs[1]->vtype == TYPE_FLOAT) &&
|
||||||
!(exprs[1]->expression.vtype == TYPE_VECTOR &&
|
!(exprs[1]->vtype == TYPE_VECTOR &&
|
||||||
exprs[0]->expression.vtype == TYPE_FLOAT)
|
exprs[0]->vtype == TYPE_FLOAT)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
|
compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
|
||||||
type_name[exprs[1]->expression.vtype],
|
type_name[exprs[1]->vtype],
|
||||||
type_name[exprs[0]->expression.vtype]);
|
type_name[exprs[0]->vtype]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch (exprs[0]->expression.vtype) {
|
switch (exprs[0]->vtype) {
|
||||||
case TYPE_FLOAT:
|
case TYPE_FLOAT:
|
||||||
if (exprs[1]->expression.vtype == TYPE_VECTOR)
|
if (exprs[1]->vtype == TYPE_VECTOR)
|
||||||
{
|
{
|
||||||
if (CanConstFold(exprs[0], exprs[1]))
|
if (CanConstFold(exprs[0], exprs[1]))
|
||||||
out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(1), ConstF(0)));
|
out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(1), ConstF(0)));
|
||||||
|
@ -865,7 +865,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TYPE_VECTOR:
|
case TYPE_VECTOR:
|
||||||
if (exprs[1]->expression.vtype == TYPE_FLOAT)
|
if (exprs[1]->vtype == TYPE_FLOAT)
|
||||||
{
|
{
|
||||||
if (CanConstFold(exprs[0], exprs[1]))
|
if (CanConstFold(exprs[0], exprs[1]))
|
||||||
out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(0), ConstF(1)));
|
out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(0), ConstF(1)));
|
||||||
|
@ -881,7 +881,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
if (!vec.y && !vec.z) { /* 'n 0 0' * v */
|
if (!vec.y && !vec.z) { /* 'n 0 0' * v */
|
||||||
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
|
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
|
||||||
out = (ast_expression*)ast_member_new(ctx, exprs[1], 0, NULL);
|
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;
|
((ast_member*)out)->rvalue = true;
|
||||||
if (vec.x != 1)
|
if (vec.x != 1)
|
||||||
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.x), out);
|
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.x), out);
|
||||||
|
@ -889,7 +889,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
else if (!vec.x && !vec.z) { /* '0 n 0' * v */
|
else if (!vec.x && !vec.z) { /* '0 n 0' * v */
|
||||||
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
|
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
|
||||||
out = (ast_expression*)ast_member_new(ctx, exprs[1], 1, NULL);
|
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;
|
((ast_member*)out)->rvalue = true;
|
||||||
if (vec.y != 1)
|
if (vec.y != 1)
|
||||||
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.y), out);
|
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.y), out);
|
||||||
|
@ -897,7 +897,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
else if (!vec.x && !vec.y) { /* '0 n 0' * v */
|
else if (!vec.x && !vec.y) { /* '0 n 0' * v */
|
||||||
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
|
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
|
||||||
out = (ast_expression*)ast_member_new(ctx, exprs[1], 2, NULL);
|
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;
|
((ast_member*)out)->rvalue = true;
|
||||||
if (vec.z != 1)
|
if (vec.z != 1)
|
||||||
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.z), out);
|
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.z), out);
|
||||||
|
@ -910,7 +910,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
if (!vec.y && !vec.z) { /* v * 'n 0 0' */
|
if (!vec.y && !vec.z) { /* v * 'n 0 0' */
|
||||||
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
|
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
|
||||||
out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, NULL);
|
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;
|
((ast_member*)out)->rvalue = true;
|
||||||
if (vec.x != 1)
|
if (vec.x != 1)
|
||||||
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.x));
|
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.x));
|
||||||
|
@ -918,7 +918,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
else if (!vec.x && !vec.z) { /* v * '0 n 0' */
|
else if (!vec.x && !vec.z) { /* v * '0 n 0' */
|
||||||
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
|
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
|
||||||
out = (ast_expression*)ast_member_new(ctx, exprs[0], 1, NULL);
|
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;
|
((ast_member*)out)->rvalue = true;
|
||||||
if (vec.y != 1)
|
if (vec.y != 1)
|
||||||
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.y));
|
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.y));
|
||||||
|
@ -926,7 +926,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
else if (!vec.x && !vec.y) { /* v * '0 n 0' */
|
else if (!vec.x && !vec.y) { /* v * '0 n 0' */
|
||||||
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
|
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
|
||||||
out = (ast_expression*)ast_member_new(ctx, exprs[0], 2, NULL);
|
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;
|
((ast_member*)out)->rvalue = true;
|
||||||
if (vec.z != 1)
|
if (vec.z != 1)
|
||||||
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.z));
|
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.z));
|
||||||
|
@ -940,25 +940,25 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
|
compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
|
||||||
type_name[exprs[1]->expression.vtype],
|
type_name[exprs[1]->vtype],
|
||||||
type_name[exprs[0]->expression.vtype]);
|
type_name[exprs[0]->vtype]);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case opid1('/'):
|
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[0], ty1, sizeof(ty1));
|
||||||
ast_type_to_string(exprs[1], ty2, sizeof(ty2));
|
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);
|
compile_error(ctx, "invalid types used in expression: cannot divide tyeps %s and %s", ty1, ty2);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (exprs[0]->expression.vtype == TYPE_FLOAT) {
|
if (exprs[0]->vtype == TYPE_FLOAT) {
|
||||||
if (CanConstFold(exprs[0], exprs[1]))
|
if (CanConstFold(exprs[0], exprs[1]))
|
||||||
out = (ast_expression*)parser_const_float(parser, ConstF(0) / ConstF(1));
|
out = (ast_expression*)parser_const_float(parser, ConstF(0) / ConstF(1));
|
||||||
else
|
else
|
||||||
out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, exprs[0], exprs[1]);
|
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]))
|
if (CanConstFold(exprs[0], exprs[1]))
|
||||||
out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(0), 1.0/ConstF(1)));
|
out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(0), 1.0/ConstF(1)));
|
||||||
else {
|
else {
|
||||||
|
@ -988,8 +988,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
case opid1('%'):
|
case opid1('%'):
|
||||||
if (NotSameType(TYPE_FLOAT)) {
|
if (NotSameType(TYPE_FLOAT)) {
|
||||||
compile_error(ctx, "invalid types used in expression: cannot perform modulo operation between types %s and %s",
|
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[0]->vtype],
|
||||||
type_name[exprs[1]->expression.vtype]);
|
type_name[exprs[1]->vtype]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (CanConstFold(exprs[0], exprs[1])) {
|
if (CanConstFold(exprs[0], exprs[1])) {
|
||||||
|
@ -1017,8 +1017,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
case opid1('&'):
|
case opid1('&'):
|
||||||
if (NotSameType(TYPE_FLOAT)) {
|
if (NotSameType(TYPE_FLOAT)) {
|
||||||
compile_error(ctx, "invalid types used in expression: cannot perform bit operations between types %s and %s",
|
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[0]->vtype],
|
||||||
type_name[exprs[1]->expression.vtype]);
|
type_name[exprs[1]->vtype]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (CanConstFold(exprs[0], exprs[1]))
|
if (CanConstFold(exprs[0], exprs[1]))
|
||||||
|
@ -1074,7 +1074,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (i = 0; i < 2; ++i) {
|
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]);
|
out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[i]);
|
||||||
if (!out) break;
|
if (!out) break;
|
||||||
out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
|
out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
|
||||||
|
@ -1085,7 +1085,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
break;
|
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]);
|
out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[i]);
|
||||||
if (!out) break;
|
if (!out) break;
|
||||||
out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
|
out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
|
||||||
|
@ -1192,49 +1192,49 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
generated_op += INSTR_LE;
|
generated_op += INSTR_LE;
|
||||||
if (NotSameType(TYPE_FLOAT)) {
|
if (NotSameType(TYPE_FLOAT)) {
|
||||||
compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
|
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[0]->vtype],
|
||||||
type_name[exprs[1]->expression.vtype]);
|
type_name[exprs[1]->vtype]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
|
out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
|
||||||
break;
|
break;
|
||||||
case opid2('!', '='):
|
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",
|
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[0]->vtype],
|
||||||
type_name[exprs[1]->expression.vtype]);
|
type_name[exprs[1]->vtype]);
|
||||||
return false;
|
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;
|
break;
|
||||||
case opid2('=', '='):
|
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",
|
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[0]->vtype],
|
||||||
type_name[exprs[1]->expression.vtype]);
|
type_name[exprs[1]->vtype]);
|
||||||
return false;
|
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;
|
break;
|
||||||
|
|
||||||
case opid1('='):
|
case opid1('='):
|
||||||
if (ast_istype(exprs[0], ast_entfield)) {
|
if (ast_istype(exprs[0], ast_entfield)) {
|
||||||
ast_expression *field = ((ast_entfield*)exprs[0])->field;
|
ast_expression *field = ((ast_entfield*)exprs[0])->field;
|
||||||
if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
|
if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
|
||||||
exprs[0]->expression.vtype == TYPE_FIELD &&
|
exprs[0]->vtype == TYPE_FIELD &&
|
||||||
exprs[0]->expression.next->expression.vtype == TYPE_VECTOR)
|
exprs[0]->next->vtype == TYPE_VECTOR)
|
||||||
{
|
{
|
||||||
assignop = type_storep_instr[TYPE_VECTOR];
|
assignop = type_storep_instr[TYPE_VECTOR];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
assignop = type_storep_instr[exprs[0]->expression.vtype];
|
assignop = type_storep_instr[exprs[0]->vtype];
|
||||||
if (assignop == VINSTR_END || !ast_compare_type(field->expression.next, exprs[1]))
|
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));
|
ast_type_to_string(exprs[1], ty2, sizeof(ty2));
|
||||||
if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
|
if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
|
||||||
field->expression.next->expression.vtype == TYPE_FUNCTION &&
|
field->next->vtype == TYPE_FUNCTION &&
|
||||||
exprs[1]->expression.vtype == TYPE_FUNCTION)
|
exprs[1]->vtype == TYPE_FUNCTION)
|
||||||
{
|
{
|
||||||
(void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
|
(void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
|
||||||
"invalid types in assignment: cannot assign %s to %s", ty2, ty1);
|
"invalid types in assignment: cannot assign %s to %s", ty2, ty1);
|
||||||
|
@ -1246,13 +1246,13 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
|
if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
|
||||||
exprs[0]->expression.vtype == TYPE_FIELD &&
|
exprs[0]->vtype == TYPE_FIELD &&
|
||||||
exprs[0]->expression.next->expression.vtype == TYPE_VECTOR)
|
exprs[0]->next->vtype == TYPE_VECTOR)
|
||||||
{
|
{
|
||||||
assignop = type_store_instr[TYPE_VECTOR];
|
assignop = type_store_instr[TYPE_VECTOR];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assignop = type_store_instr[exprs[0]->expression.vtype];
|
assignop = type_store_instr[exprs[0]->vtype];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (assignop == VINSTR_END) {
|
if (assignop == VINSTR_END) {
|
||||||
|
@ -1265,8 +1265,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
|
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
|
||||||
ast_type_to_string(exprs[1], ty2, sizeof(ty2));
|
ast_type_to_string(exprs[1], ty2, sizeof(ty2));
|
||||||
if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
|
if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
|
||||||
exprs[0]->expression.vtype == TYPE_FUNCTION &&
|
exprs[0]->vtype == TYPE_FUNCTION &&
|
||||||
exprs[1]->expression.vtype == TYPE_FUNCTION)
|
exprs[1]->vtype == TYPE_FUNCTION)
|
||||||
{
|
{
|
||||||
(void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
|
(void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
|
||||||
"invalid types in assignment: cannot assign %s to %s", ty2, ty1);
|
"invalid types in assignment: cannot assign %s to %s", ty2, ty1);
|
||||||
|
@ -1283,7 +1283,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
case opid3('+','+','P'):
|
case opid3('+','+','P'):
|
||||||
case opid3('-','-','P'):
|
case opid3('-','-','P'):
|
||||||
/* prefix ++ */
|
/* prefix ++ */
|
||||||
if (exprs[0]->expression.vtype != TYPE_FLOAT) {
|
if (exprs[0]->vtype != TYPE_FLOAT) {
|
||||||
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
|
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
|
||||||
compile_error(ast_ctx(exprs[0]), "invalid type for prefix increment: %s", ty1);
|
compile_error(ast_ctx(exprs[0]), "invalid type for prefix increment: %s", ty1);
|
||||||
return false;
|
return false;
|
||||||
|
@ -1308,7 +1308,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
case opid3('S','+','+'):
|
case opid3('S','+','+'):
|
||||||
case opid3('S','-','-'):
|
case opid3('S','-','-'):
|
||||||
/* prefix ++ */
|
/* prefix ++ */
|
||||||
if (exprs[0]->expression.vtype != TYPE_FLOAT) {
|
if (exprs[0]->vtype != TYPE_FLOAT) {
|
||||||
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
|
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
|
||||||
compile_error(ast_ctx(exprs[0]), "invalid type for suffix increment: %s", ty1);
|
compile_error(ast_ctx(exprs[0]), "invalid type for suffix increment: %s", ty1);
|
||||||
return false;
|
return false;
|
||||||
|
@ -1340,8 +1340,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
break;
|
break;
|
||||||
case opid2('+','='):
|
case opid2('+','='):
|
||||||
case opid2('-','='):
|
case opid2('-','='):
|
||||||
if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
|
if (exprs[0]->vtype != exprs[1]->vtype ||
|
||||||
(exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
|
(exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
|
||||||
{
|
{
|
||||||
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
|
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
|
||||||
ast_type_to_string(exprs[1], ty2, sizeof(ty2));
|
ast_type_to_string(exprs[1], ty2, sizeof(ty2));
|
||||||
|
@ -1353,10 +1353,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
|
compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
|
||||||
}
|
}
|
||||||
if (ast_istype(exprs[0], ast_entfield))
|
if (ast_istype(exprs[0], ast_entfield))
|
||||||
assignop = type_storep_instr[exprs[0]->expression.vtype];
|
assignop = type_storep_instr[exprs[0]->vtype];
|
||||||
else
|
else
|
||||||
assignop = type_store_instr[exprs[0]->expression.vtype];
|
assignop = type_store_instr[exprs[0]->vtype];
|
||||||
switch (exprs[0]->expression.vtype) {
|
switch (exprs[0]->vtype) {
|
||||||
case TYPE_FLOAT:
|
case TYPE_FLOAT:
|
||||||
out = (ast_expression*)ast_binstore_new(ctx, assignop,
|
out = (ast_expression*)ast_binstore_new(ctx, assignop,
|
||||||
(op->id == opid2('+','=') ? INSTR_ADD_F : INSTR_SUB_F),
|
(op->id == opid2('+','=') ? INSTR_ADD_F : INSTR_SUB_F),
|
||||||
|
@ -1369,16 +1369,16 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
|
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[0]->vtype],
|
||||||
type_name[exprs[1]->expression.vtype]);
|
type_name[exprs[1]->vtype]);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case opid2('*','='):
|
case opid2('*','='):
|
||||||
case opid2('/','='):
|
case opid2('/','='):
|
||||||
if (exprs[1]->expression.vtype != TYPE_FLOAT ||
|
if (exprs[1]->vtype != TYPE_FLOAT ||
|
||||||
!(exprs[0]->expression.vtype == TYPE_FLOAT ||
|
!(exprs[0]->vtype == TYPE_FLOAT ||
|
||||||
exprs[0]->expression.vtype == TYPE_VECTOR))
|
exprs[0]->vtype == TYPE_VECTOR))
|
||||||
{
|
{
|
||||||
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
|
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
|
||||||
ast_type_to_string(exprs[1], ty2, sizeof(ty2));
|
ast_type_to_string(exprs[1], ty2, sizeof(ty2));
|
||||||
|
@ -1390,10 +1390,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
|
compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
|
||||||
}
|
}
|
||||||
if (ast_istype(exprs[0], ast_entfield))
|
if (ast_istype(exprs[0], ast_entfield))
|
||||||
assignop = type_storep_instr[exprs[0]->expression.vtype];
|
assignop = type_storep_instr[exprs[0]->vtype];
|
||||||
else
|
else
|
||||||
assignop = type_store_instr[exprs[0]->expression.vtype];
|
assignop = type_store_instr[exprs[0]->vtype];
|
||||||
switch (exprs[0]->expression.vtype) {
|
switch (exprs[0]->vtype) {
|
||||||
case TYPE_FLOAT:
|
case TYPE_FLOAT:
|
||||||
out = (ast_expression*)ast_binstore_new(ctx, assignop,
|
out = (ast_expression*)ast_binstore_new(ctx, assignop,
|
||||||
(op->id == opid2('*','=') ? INSTR_MUL_F : INSTR_DIV_F),
|
(op->id == opid2('*','=') ? INSTR_MUL_F : INSTR_DIV_F),
|
||||||
|
@ -1422,8 +1422,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
|
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[0]->vtype],
|
||||||
type_name[exprs[1]->expression.vtype]);
|
type_name[exprs[1]->vtype]);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
@ -1440,9 +1440,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
|
compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
|
||||||
}
|
}
|
||||||
if (ast_istype(exprs[0], ast_entfield))
|
if (ast_istype(exprs[0], ast_entfield))
|
||||||
assignop = type_storep_instr[exprs[0]->expression.vtype];
|
assignop = type_storep_instr[exprs[0]->vtype];
|
||||||
else
|
else
|
||||||
assignop = type_store_instr[exprs[0]->expression.vtype];
|
assignop = type_store_instr[exprs[0]->vtype];
|
||||||
out = (ast_expression*)ast_binstore_new(ctx, assignop,
|
out = (ast_expression*)ast_binstore_new(ctx, assignop,
|
||||||
(op->id == opid2('&','=') ? INSTR_BITAND : INSTR_BITOR),
|
(op->id == opid2('&','=') ? INSTR_BITAND : INSTR_BITOR),
|
||||||
exprs[0], exprs[1]);
|
exprs[0], exprs[1]);
|
||||||
|
@ -1460,9 +1460,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (ast_istype(exprs[0], ast_entfield))
|
if (ast_istype(exprs[0], ast_entfield))
|
||||||
assignop = type_storep_instr[exprs[0]->expression.vtype];
|
assignop = type_storep_instr[exprs[0]->vtype];
|
||||||
else
|
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]);
|
out = (ast_expression*)ast_binary_new(ctx, INSTR_BITAND, exprs[0], exprs[1]);
|
||||||
if (!out)
|
if (!out)
|
||||||
return false;
|
return false;
|
||||||
|
@ -1475,7 +1475,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case opid2('~', 'P'):
|
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));
|
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
|
||||||
compile_error(ast_ctx(exprs[0]), "invalid type for bit not: %s", ty1);
|
compile_error(ast_ctx(exprs[0]), "invalid type for bit not: %s", ty1);
|
||||||
return false;
|
return false;
|
||||||
|
@ -1571,7 +1571,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy)
|
||||||
|
|
||||||
if (ast_istype(fun, ast_value)) {
|
if (ast_istype(fun, ast_value)) {
|
||||||
funval = (ast_value*)fun;
|
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))
|
!(/*funval->cvq == CV_CONST && */ funval->hasvalue && funval->constval.vfunc->builtin))
|
||||||
{
|
{
|
||||||
call->va_count = (ast_expression*)parser_const_float(parser, (double)paramcount);
|
call->va_count = (ast_expression*)parser_const_float(parser, (double)paramcount);
|
||||||
|
@ -1581,18 +1581,18 @@ static bool parser_close_call(parser_t *parser, shunt *sy)
|
||||||
/* overwrite fid, the function, with a call */
|
/* overwrite fid, the function, with a call */
|
||||||
sy->out[fid] = syexp(call->expression.node.context, (ast_expression*)call);
|
sy->out[fid] = syexp(call->expression.node.context, (ast_expression*)call);
|
||||||
|
|
||||||
if (fun->expression.vtype != TYPE_FUNCTION) {
|
if (fun->vtype != TYPE_FUNCTION) {
|
||||||
parseerror(parser, "not a function (%s)", type_name[fun->expression.vtype]);
|
parseerror(parser, "not a function (%s)", type_name[fun->vtype]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fun->expression.next) {
|
if (!fun->next) {
|
||||||
parseerror(parser, "could not determine function return type");
|
parseerror(parser, "could not determine function return type");
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
ast_value *fval = (ast_istype(fun, ast_value) ? ((ast_value*)fun) : NULL);
|
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) {
|
if (!fval) {
|
||||||
return !parsewarning(parser, WARN_DEPRECATED,
|
return !parsewarning(parser, WARN_DEPRECATED,
|
||||||
"call to function (which is marked deprecated)\n",
|
"call to function (which is marked deprecated)\n",
|
||||||
|
@ -1612,22 +1612,22 @@ static bool parser_close_call(parser_t *parser, shunt *sy)
|
||||||
ast_ctx(fun).line);
|
ast_ctx(fun).line);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vec_size(fun->expression.params) != paramcount &&
|
if (vec_size(fun->params) != paramcount &&
|
||||||
!((fun->expression.flags & AST_FLAG_VARIADIC) &&
|
!((fun->flags & AST_FLAG_VARIADIC) &&
|
||||||
vec_size(fun->expression.params) < paramcount))
|
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)
|
if (fval)
|
||||||
return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
|
return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
|
||||||
"too %s parameters for call to %s: expected %i, got %i\n"
|
"too %s parameters for call to %s: expected %i, got %i\n"
|
||||||
" -> `%s` has been declared here: %s:%i",
|
" -> `%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);
|
fval->name, ast_ctx(fun).file, (int)ast_ctx(fun).line);
|
||||||
else
|
else
|
||||||
return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
|
return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
|
||||||
"too %s parameters for function call: expected %i, got %i\n"
|
"too %s parameters for function call: expected %i, got %i\n"
|
||||||
" -> it has been declared here: %s:%i",
|
" -> 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);
|
ast_ctx(fun).file, (int)ast_ctx(fun).line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1881,7 +1881,7 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels)
|
||||||
/* When adding more intrinsics, fix the above condition */
|
/* When adding more intrinsics, fix the above condition */
|
||||||
prev = NULL;
|
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'];
|
var = (ast_expression*)parser->const_vec[ctoken[0]-'x'];
|
||||||
} else {
|
} else {
|
||||||
|
@ -2363,13 +2363,13 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond,
|
||||||
ast_unary *unary;
|
ast_unary *unary;
|
||||||
ast_expression *prev;
|
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];
|
char ty[1024];
|
||||||
ast_type_to_string(cond, ty, sizeof(ty));
|
ast_type_to_string(cond, ty, sizeof(ty));
|
||||||
compile_error(ast_ctx(cond), "invalid type for if() condition: %s", 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;
|
prev = cond;
|
||||||
cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_S, cond);
|
cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_S, cond);
|
||||||
|
@ -2380,7 +2380,7 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond,
|
||||||
}
|
}
|
||||||
ifnot = !ifnot;
|
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 */
|
/* vector types need to be cast to true booleans */
|
||||||
ast_binary *bin = (ast_binary*)cond;
|
ast_binary *bin = (ast_binary*)cond;
|
||||||
|
@ -2911,8 +2911,8 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou
|
||||||
if (!exp)
|
if (!exp)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (exp->expression.vtype != TYPE_NIL &&
|
if (exp->vtype != TYPE_NIL &&
|
||||||
exp->expression.vtype != expected->expression.next->expression.vtype)
|
exp->vtype != ((ast_expression*)expected)->next->vtype)
|
||||||
{
|
{
|
||||||
parseerror(parser, "return with invalid expression");
|
parseerror(parser, "return with invalid expression");
|
||||||
}
|
}
|
||||||
|
@ -2925,7 +2925,7 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou
|
||||||
} else {
|
} else {
|
||||||
if (!parser_next(parser))
|
if (!parser_next(parser))
|
||||||
parseerror(parser, "parse error");
|
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");
|
(void)!parsewarning(parser, WARN_MISSING_RETURN_VALUES, "return without value");
|
||||||
}
|
}
|
||||||
ret = ast_return_new(ctx, NULL);
|
ret = ast_return_new(ctx, NULL);
|
||||||
|
@ -4067,9 +4067,9 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
|
||||||
/* qc allows the use of not-yet-declared functions here
|
/* qc allows the use of not-yet-declared functions here
|
||||||
* - this automatically creates a prototype */
|
* - this automatically creates a prototype */
|
||||||
ast_value *thinkfunc;
|
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)*/
|
if (!thinkfunc) { /* || !ast_type_adopt(thinkfunc, functype)*/
|
||||||
ast_unref(framenum);
|
ast_unref(framenum);
|
||||||
parseerror(parser, "failed to create implicit prototype for `%s`", parser_tokval(parser));
|
parseerror(parser, "failed to create implicit prototype for `%s`", parser_tokval(parser));
|
||||||
|
@ -4224,7 +4224,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
|
||||||
|
|
||||||
if (param->expression.vtype != TYPE_VECTOR &&
|
if (param->expression.vtype != TYPE_VECTOR &&
|
||||||
(param->expression.vtype != TYPE_FIELD ||
|
(param->expression.vtype != TYPE_FIELD ||
|
||||||
param->expression.next->expression.vtype != TYPE_VECTOR))
|
param->expression.next->vtype != TYPE_VECTOR))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -4354,7 +4354,7 @@ static ast_expression *array_setter_node(parser_t *parser, ast_value *array, ast
|
||||||
ast_store *st;
|
ast_store *st;
|
||||||
int assignop = type_store_instr[value->expression.vtype];
|
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;
|
assignop = INSTR_STORE_V;
|
||||||
|
|
||||||
subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from));
|
subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from));
|
||||||
|
@ -4420,7 +4420,7 @@ static ast_expression *array_field_setter_node(
|
||||||
ast_store *st;
|
ast_store *st;
|
||||||
int assignop = type_storep_instr[value->expression.vtype];
|
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;
|
assignop = INSTR_STOREP_V;
|
||||||
|
|
||||||
subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from));
|
subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from));
|
||||||
|
@ -5271,7 +5271,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
|
||||||
{
|
{
|
||||||
/* deal with other globals */
|
/* deal with other globals */
|
||||||
old = parser_find_global(parser, var->name);
|
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 */
|
/* This is a function which had a prototype */
|
||||||
if (!ast_istype(old, ast_value)) {
|
if (!ast_istype(old, ast_value)) {
|
||||||
|
@ -5379,7 +5379,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
|
||||||
if (var->expression.vtype == TYPE_VECTOR)
|
if (var->expression.vtype == TYPE_VECTOR)
|
||||||
isvector = true;
|
isvector = true;
|
||||||
else if (var->expression.vtype == TYPE_FIELD &&
|
else if (var->expression.vtype == TYPE_FIELD &&
|
||||||
var->expression.next->expression.vtype == TYPE_VECTOR)
|
var->expression.next->vtype == TYPE_VECTOR)
|
||||||
isvector = true;
|
isvector = true;
|
||||||
|
|
||||||
if (isvector) {
|
if (isvector) {
|
||||||
|
@ -5418,7 +5418,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (var->expression.vtype != find->expression.vtype) {
|
if (var->expression.vtype != find->vtype) {
|
||||||
char ty1[1024];
|
char ty1[1024];
|
||||||
char ty2[1024];
|
char ty2[1024];
|
||||||
|
|
||||||
|
@ -5567,7 +5567,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
|
||||||
}
|
}
|
||||||
else if (!localblock && !nofields &&
|
else if (!localblock && !nofields &&
|
||||||
var->expression.vtype == TYPE_FIELD &&
|
var->expression.vtype == TYPE_FIELD &&
|
||||||
var->expression.next->expression.vtype == TYPE_ARRAY)
|
var->expression.next->vtype == TYPE_ARRAY)
|
||||||
{
|
{
|
||||||
char name[1024];
|
char name[1024];
|
||||||
ast_expression *telem;
|
ast_expression *telem;
|
||||||
|
@ -5985,7 +5985,7 @@ static void generate_checksum(parser_t *parser)
|
||||||
if (!ast_istype(parser->fields[i], ast_value))
|
if (!ast_istype(parser->fields[i], ast_value))
|
||||||
continue;
|
continue;
|
||||||
value = (ast_value*)(parser->fields[i]);
|
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_FLOAT: crc = progdefs_crc_both(crc, "\tfloat\t"); break;
|
||||||
case TYPE_VECTOR: crc = progdefs_crc_both(crc, "\tvec3_t\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;
|
case TYPE_STRING: crc = progdefs_crc_both(crc, "\tstring_t\t"); break;
|
||||||
|
@ -6236,11 +6236,11 @@ bool parser_finish(parser_t *parser, const char *output)
|
||||||
ast_expression *subtype;
|
ast_expression *subtype;
|
||||||
field->hasvalue = true;
|
field->hasvalue = true;
|
||||||
subtype = field->expression.next;
|
subtype = field->expression.next;
|
||||||
ifld = ir_builder_create_field(ir, field->name, subtype->expression.vtype);
|
ifld = ir_builder_create_field(ir, field->name, subtype->vtype);
|
||||||
if (subtype->expression.vtype == TYPE_FIELD)
|
if (subtype->vtype == TYPE_FIELD)
|
||||||
ifld->fieldtype = subtype->expression.next->expression.vtype;
|
ifld->fieldtype = subtype->next->vtype;
|
||||||
else if (subtype->expression.vtype == TYPE_FUNCTION)
|
else if (subtype->vtype == TYPE_FUNCTION)
|
||||||
ifld->outtype = subtype->expression.next->expression.vtype;
|
ifld->outtype = subtype->next->vtype;
|
||||||
(void)!ir_value_set_field(field->ir_v, ifld);
|
(void)!ir_value_set_field(field->ir_v, ifld);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6328,7 +6328,7 @@ bool parser_finish(parser_t *parser, const char *output)
|
||||||
}
|
}
|
||||||
for (i = 0; i < vec_size(parser->fields); ++i) {
|
for (i = 0; i < vec_size(parser->fields); ++i) {
|
||||||
ast_value *asvalue;
|
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))
|
if (!ast_istype((ast_expression*)asvalue, ast_value))
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Reference in a new issue