/*
- * Copyright (C) 2012
+ * Copyright (C) 2012, 2013
* Wolfgang Bumiller
* Dale Weiler
*
ast_ternary* ast_ternary_new(lex_ctx ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse)
{
+ ast_expression *exprtype = ontrue;
ast_instantiate(ast_ternary, ctx, ast_ternary_delete);
/* This time NEITHER must be NULL */
if (!ontrue || !onfalse) {
ast_propagate_effects(self, ontrue);
ast_propagate_effects(self, onfalse);
- if (!ast_type_adopt(self, ontrue)) {
+ if (ontrue->expression.vtype == TYPE_NIL)
+ exprtype = onfalse;
+ if (!ast_type_adopt(self, exprtype)) {
ast_ternary_delete(self);
return NULL;
}
void ast_ternary_delete(ast_ternary *self)
{
- ast_unref(self->cond);
- ast_unref(self->on_true);
- ast_unref(self->on_false);
+ /* the if()s are only there because computed-gotos can set them
+ * to NULL
+ */
+ if (self->cond) ast_unref(self->cond);
+ if (self->on_true) ast_unref(self->on_true);
+ if (self->on_false) ast_unref(self->on_false);
ast_expression_delete((ast_expression*)self);
mem_d(self);
}
mem_d(self);
}
-ast_label* ast_label_new(lex_ctx ctx, const char *name)
+ast_label* ast_label_new(lex_ctx ctx, const char *name, bool undefined)
{
ast_instantiate(ast_label, ctx, ast_label_delete);
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_label_codegen);
- self->name = util_strdup(name);
- self->irblock = NULL;
- self->gotos = NULL;
+ self->expression.vtype = TYPE_NOEXPR;
+
+ self->name = util_strdup(name);
+ self->irblock = NULL;
+ self->gotos = NULL;
+ self->undefined = undefined;
return self;
}
self->constval.vfunc->ir_func = func;
self->ir_v = func->value;
+ if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+ self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
/* The function is filled later on ast_function_codegen... */
return true;
}
v->unique_life = true;
v->locked = true;
array->ir_v = self->ir_v = v;
+ if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+ self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
namelen = strlen(self->name);
name = (char*)mem_a(namelen + 16);
array->ir_values[ai]->context = ast_ctx(self);
array->ir_values[ai]->unique_life = true;
array->ir_values[ai]->locked = true;
+ if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+ self->ir_values[ai]->flags |= IR_FLAG_INCLUDE_DEF;
}
mem_d(name);
}
return false;
v->context = ast_ctx(self);
self->ir_v = v;
+ if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+ self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
}
return true;
}
v->context = ast_ctx(self);
v->unique_life = true;
v->locked = true;
+ if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+ v->flags |= IR_FLAG_INCLUDE_DEF;
namelen = strlen(self->name);
name = (char*)mem_a(namelen + 16);
self->ir_values[ai]->context = ast_ctx(self);
self->ir_values[ai]->unique_life = true;
self->ir_values[ai]->locked = true;
+ if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+ self->ir_values[ai]->flags |= IR_FLAG_INCLUDE_DEF;
}
mem_d(name);
}
/* link us to the ir_value */
v->cvq = self->cvq;
self->ir_v = v;
+ if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
+ self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
return true;
error: /* clean up */
}
self->expression.outr = *out;
+ codegen_output_type(self, *out);
return true;
}
if (!*out)
return false;
self->expression.outr = *out;
+ codegen_output_type(self, *out);
return true;
}
/* Here, now, we need a PHI node
* but first some sanity checking...
*/
- if (trueval->vtype != falseval->vtype) {
+ if (trueval->vtype != falseval->vtype && trueval->vtype != TYPE_NIL && falseval->vtype != TYPE_NIL) {
/* error("ternary with different types on the two sides"); */
+ compile_error(ast_ctx(self), "internal error: ternary operand types invalid");
return false;
}
/* create PHI */
- phi = ir_block_create_phi(merge, ast_ctx(self), ast_function_label(func, "phi"), trueval->vtype);
- if (!phi)
+ phi = ir_block_create_phi(merge, ast_ctx(self), ast_function_label(func, "phi"), self->expression.vtype);
+ if (!phi) {
+ compile_error(ast_ctx(self), "internal error: failed to generate phi node");
return false;
+ }
ir_phi_add(phi, ontrue_out, trueval);
ir_phi_add(phi, onfalse_out, falseval);
size_t i;
ir_value *dummy;
+ if (self->undefined) {
+ compile_error(ast_ctx(self), "internal error: ast_label never defined");
+ return false;
+ }
+
*out = NULL;
if (lvalue) {
compile_error(ast_ctx(self), "internal error: ast_label cannot be an lvalue");