self->expression.next = NULL;
self->expression.outl = NULL;
self->expression.outr = NULL;
- self->expression.variadic = false;
self->expression.params = NULL;
self->expression.count = 0;
+ self->expression.flags = 0;
}
static void ast_expression_delete(ast_expression *self)
}
fromex = &self->expression;
selfex = &cp->expression;
- selfex->variadic = fromex->variadic;
selfex->count = fromex->count;
+ selfex->flags = fromex->flags;
for (i = 0; i < vec_size(fromex->params); ++i) {
ast_value *v = ast_value_copy(fromex->params[i]);
if (!v) {
}
fromex = &other->expression;
selfex = &self->expression;
- selfex->variadic = fromex->variadic;
selfex->count = fromex->count;
+ selfex->flags = fromex->flags;
for (i = 0; i < vec_size(fromex->params); ++i) {
ast_value *v = ast_value_copy(fromex->params[i]);
if (!v)
else
selfex->next = NULL;
- selfex->variadic = fromex->variadic;
selfex->count = fromex->count;
+ selfex->flags = fromex->flags;
for (i = 0; i < vec_size(fromex->params); ++i) {
ast_value *v = ast_value_copy(fromex->params[i]);
if (!v) {
return false;
if (vec_size(a->expression.params) != vec_size(b->expression.params))
return false;
- if (a->expression.variadic != b->expression.variadic)
+ if (a->expression.flags != b->expression.flags)
return false;
if (vec_size(a->expression.params)) {
size_t i;
void ast_unary_delete(ast_unary *self)
{
- ast_unref(self->operand);
+ if (self->operand) ast_unref(self->operand);
ast_expression_delete((ast_expression*)self);
mem_d(self);
}
ast_loop* ast_loop_new(lex_ctx ctx,
ast_expression *initexpr,
- ast_expression *precond,
- ast_expression *postcond,
+ ast_expression *precond, bool pre_not,
+ ast_expression *postcond, bool post_not,
ast_expression *increment,
ast_expression *body)
{
self->increment = increment;
self->body = body;
+ self->pre_not = pre_not;
+ self->post_not = post_not;
+
if (initexpr)
ast_propagate_effects(self, initexpr);
if (precond)
size_t len;
char *from;
- if (!opts.dump && !opts.dumpfin)
+ if (!opts.dump && !opts.dumpfin && !opts.debug)
return NULL;
id = (self->labelcount++);
from = self->labelbuf + sizeof(self->labelbuf)-1;
*from-- = 0;
do {
- unsigned int digit = id % 10;
- *from = digit + '0';
+ *from-- = (id%10) + '0';
id /= 10;
} while (id);
+ ++from;
memcpy(from - len, prefix, len);
return from - len;
}
}
#define codegen_output_type(a,o) (_ast_codegen_output_type(&((a)->expression),(o)))
-#define codegen_output_type_expr(a,o) (_ast_codegen_output_type(a,(o)))
bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_value **out)
{
}
/* TODO: check return types */
- if (!self->curblock->is_return)
+ if (!self->curblock->final)
{
if (!self->vtype->expression.next ||
self->vtype->expression.next->expression.vtype == TYPE_VOID)
for (i = 0; i < vec_size(self->exprs); ++i)
{
- ast_expression_codegen *gen = self->exprs[i]->expression.codegen;
+ ast_expression_codegen *gen;
if (func->curblock->final && !ast_istype(self->exprs[i], ast_label)) {
- compile_error(ast_ctx(self->exprs[i]), "unreachable statement");
- return false;
+ if (compile_warning(ast_ctx(self->exprs[i]), WARN_UNREACHABLE_CODE, "unreachable statement"))
+ return false;
+ continue;
}
+ gen = self->exprs[i]->expression.codegen;
if (!(*gen)(self->exprs[i], func, false, out))
return false;
}
if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
return false;
- call = ir_block_create_call(func->curblock, ast_ctx(self), ast_function_label(func, "store"), funval);
+ call = ir_block_create_call(func->curblock, ast_ctx(self), ast_function_label(func, "store"), funval, false);
if (!call)
return false;
ir_call_param(call, iridx);
if (!(*cgen)((ast_expression*)(arr->setter), func, true, &funval))
return false;
- call = ir_block_create_call(func->curblock, ast_ctx(self), ast_function_label(func, "store"), funval);
+ call = ir_block_create_call(func->curblock, ast_ctx(self), ast_function_label(func, "store"), funval, false);
if (!call)
return false;
ir_call_param(call, iridx);
if (!(*cgen)((ast_expression*)(arr->getter), func, true, &funval))
return false;
- call = ir_block_create_call(func->curblock, ast_ctx(self), ast_function_label(func, "fetch"), funval);
+ call = ir_block_create_call(func->curblock, ast_ctx(self), ast_function_label(func, "fetch"), funval, false);
if (!call)
return false;
ir_call_param(call, iridx);
else if (bpostcond) ontrue = bpostcond;
else ontrue = bprecond;
onfalse = bout;
+ if (self->pre_not) {
+ tmpblock = ontrue;
+ ontrue = onfalse;
+ onfalse = tmpblock;
+ }
if (!ir_block_create_if(end_bprecond, ast_ctx(self), precond, ontrue, onfalse))
return false;
}
else if (bincrement) ontrue = bincrement;
else ontrue = bpostcond;
onfalse = bout;
+ if (self->post_not) {
+ tmpblock = ontrue;
+ ontrue = onfalse;
+ onfalse = tmpblock;
+ }
if (!ir_block_create_if(end_bpostcond, ast_ctx(self), postcond, ontrue, onfalse))
return false;
}
vec_push(params, param);
}
- callinstr = ir_block_create_call(func->curblock, ast_ctx(self), ast_function_label(func, "call"), funval);
+ callinstr = ir_block_create_call(func->curblock, ast_ctx(self),
+ ast_function_label(func, "call"),
+ funval, !!(self->func->expression.flags & AST_FLAG_NORETURN));
if (!callinstr)
goto error;