mem_d(self);
}
+bool ast_member_set_name(ast_member *self, const char *name)
+{
+ if (self->name)
+ mem_d((void*)self->name);
+ self->name = util_strdup(name);
+ return !!self->name;
+}
+
ast_array_index* ast_array_index_new(lex_ctx ctx, ast_expression *array, ast_expression *index)
{
ast_expression *outtype;
mem_d(self);
}
-ast_breakcont* ast_breakcont_new(lex_ctx ctx, bool iscont)
+ast_breakcont* ast_breakcont_new(lex_ctx ctx, bool iscont, unsigned int levels)
{
ast_instantiate(ast_breakcont, ctx, ast_breakcont_delete);
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_breakcont_codegen);
self->is_continue = iscont;
+ self->levels = levels;
return self;
}
self->ir_func = NULL;
self->curblock = NULL;
- self->breakblock = NULL;
- self->continueblock = NULL;
+ self->breakblocks = NULL;
+ self->continueblocks = NULL;
vtype->hasvalue = true;
vtype->constval.vfunc = self;
for (i = 0; i < vec_size(self->blocks); ++i)
ast_delete(self->blocks[i]);
vec_free(self->blocks);
+ vec_free(self->breakblocks);
+ vec_free(self->continueblocks);
mem_d(self);
}
{
(void)func;
(void)lvalue;
+ if (self->expression.vtype == TYPE_NIL) {
+ *out = func->ir_func->owner->nil;
+ return true;
+ }
/* NOTE: This is the codegen for a variable used in an expression.
* It is not the codegen to generate the value. For this purpose,
* ast_local_codegen and ast_global_codegen are to be used before this
* on all the globals.
*/
if (!self->ir_v) {
- char typename[1024];
- ast_type_to_string((ast_expression*)self, typename, sizeof(typename));
- compile_error(ast_ctx(self), "ast_value used before generated %s %s", typename, self->name);
+ char tname[1024]; /* typename is reserved in C++ */
+ ast_type_to_string((ast_expression*)self, tname, sizeof(tname));
+ compile_error(ast_ctx(self), "ast_value used before generated %s %s", tname, self->name);
return false;
}
*out = self->ir_v;
{
ir_value *v = NULL;
+ if (self->expression.vtype == TYPE_NIL) {
+ compile_error(ast_ctx(self), "internal error: trying to generate a variable of TYPE_NIL");
+ return false;
+ }
+
if (self->hasvalue && self->expression.vtype == TYPE_FUNCTION)
{
ir_function *func = ir_builder_create_function(ir, self->name, self->expression.next->expression.vtype);
}
v->context = ast_ctx(self);
v->unique_life = true;
+ v->locked = true;
array->ir_v = self->ir_v = v;
namelen = strlen(self->name);
}
array->ir_values[ai]->context = ast_ctx(self);
array->ir_values[ai]->unique_life = true;
+ array->ir_values[ai]->locked = true;
}
mem_d(name);
}
}
v->context = ast_ctx(self);
v->unique_life = true;
+ v->locked = true;
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;
}
mem_d(name);
}
bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
{
ir_value *v = NULL;
+
+ if (self->expression.vtype == TYPE_NIL) {
+ compile_error(ast_ctx(self), "internal error: trying to generate a variable of TYPE_NIL");
+ return false;
+ }
+
if (self->hasvalue && self->expression.vtype == TYPE_FUNCTION)
{
/* Do we allow local functions? I think not...
ast_expression_common *elemtype = &self->expression.next->expression;
int vtype = elemtype->vtype;
+ func->flags |= IR_FLAG_HAS_ARRAYS;
+
if (param) {
compile_error(ast_ctx(self), "array-parameters are not supported");
return false;
}
v->context = ast_ctx(self);
v->unique_life = true;
+ v->locked = true;
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;
}
}
else
ir_block *bcontinue = NULL;
ir_block *bbreak = NULL;
- ir_block *old_bcontinue = NULL;
- ir_block *old_bbreak = NULL;
-
ir_block *tmpblock = NULL;
(void)lvalue;
/* enter */
func->curblock = bbody;
- old_bbreak = func->breakblock;
- old_bcontinue = func->continueblock;
- func->breakblock = bbreak;
- func->continueblock = bcontinue;
- if (!func->continueblock)
- func->continueblock = bbody;
+ vec_push(func->breakblocks, bbreak);
+ if (bcontinue)
+ vec_push(func->continueblocks, bcontinue);
+ else
+ vec_push(func->continueblocks, bbody);
/* generate */
if (self->body) {
}
end_bbody = func->curblock;
- func->breakblock = old_bbreak;
- func->continueblock = old_bcontinue;
+ vec_pop(func->breakblocks);
+ vec_pop(func->continueblocks);
}
/* post-loop-condition */
self->expression.outr = (ir_value*)1;
if (self->is_continue)
- target = func->continueblock;
+ target = func->continueblocks[vec_size(func->continueblocks)-1-self->levels];
else
- target = func->breakblock;
+ target = func->breakblocks[vec_size(func->breakblocks)-1-self->levels];
if (!target) {
compile_error(ast_ctx(self), "%s is lacking a target block", (self->is_continue ? "continue" : "break"));
ir_value *dummy = NULL;
ir_value *irop = NULL;
- ir_block *old_break = NULL;
ir_block *bout = NULL;
ir_block *bfall = NULL;
size_t bout_id;
return false;
/* setup the break block */
- old_break = func->breakblock;
- func->breakblock = bout;
+ vec_push(func->breakblocks, bout);
/* Now create all cases */
for (c = 0; c < vec_size(self->cases); ++c) {
func->curblock = bout;
/* restore the break block */
- func->breakblock = old_break;
+ vec_pop(func->breakblocks);
/* Move 'bout' to the end, it's nicer */
vec_remove(func->ir_func->blocks, bout_id, 1);
if (self->irblock_from) {
/* we already tried once, this is the callback */
self->irblock_from->final = false;
- if (!ir_block_create_jump(self->irblock_from, ast_ctx(self), self->target->irblock)) {
+ if (!ir_block_create_goto(self->irblock_from, ast_ctx(self), self->target->irblock)) {
compile_error(ast_ctx(self), "failed to generate goto to `%s`", self->name);
return false;
}
}
else
{
- if (!ir_block_create_jump(func->curblock, ast_ctx(self), self->target->irblock)) {
+ if (!ir_block_create_goto(func->curblock, ast_ctx(self), self->target->irblock)) {
compile_error(ast_ctx(self), "failed to generate goto to `%s`", self->name);
return false;
}