ast_node_init((ast_node*)self, ctx, TYPE_##T); \
( (ast_node*)self )->node.destroy = (ast_node_delete*)destroyfn
+
/* error handling */
static void asterror(lex_ctx ctx, const char *msg, ...)
{
self->node.destroy = &_ast_node_destroy;
self->node.keep = false;
self->node.nodetype = nodetype;
+ self->node.side_effects = false;
+}
+
+/* weight and side effects */
+static void _ast_propagate_effects(ast_node *self, ast_node *other)
+{
+ if (ast_side_effects(other))
+ ast_side_effects(self) = true;
}
+#define ast_propagate_effects(s,o) _ast_propagate_effects(((ast_node*)(s)), ((ast_node*)(o)))
/* General expression initialization */
static void ast_expression_init(ast_expression *self,
self->left = left;
self->right = right;
+ ast_propagate_effects(self, left);
+ ast_propagate_effects(self, right);
+
if (op >= INSTR_EQ_F && op <= INSTR_GT)
self->expression.vtype = TYPE_FLOAT;
else if (op == INSTR_AND || op == INSTR_OR ||
ast_instantiate(ast_binstore, ctx, ast_binstore_delete);
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_binstore_codegen);
+ ast_side_effects(self) = true;
+
self->opstore = storop;
self->opbin = op;
self->dest = left;
self->op = op;
self->operand = expr;
+ ast_propagate_effects(self, expr);
+
if (op >= INSTR_NOT_F && op <= INSTR_NOT_FNC) {
self->expression.vtype = TYPE_FLOAT;
} else
self->operand = expr;
+ if (expr)
+ ast_propagate_effects(self, expr);
+
return self;
}
self->entity = entity;
self->field = field;
+ ast_propagate_effects(self, entity);
+ ast_propagate_effects(self, field);
if (!ast_type_adopt(self, outtype)) {
ast_entfield_delete(self);
}
self->owner = owner;
+ ast_propagate_effects(self, owner);
+
self->field = field;
if (name)
self->name = util_strdup(name);
self->array = array;
self->index = index;
+ ast_propagate_effects(self, array);
+ ast_propagate_effects(self, index);
if (!ast_type_adopt(self, outtype)) {
ast_array_index_delete(self);
self->cond = cond;
self->on_true = ontrue;
self->on_false = onfalse;
+ ast_propagate_effects(self, cond);
+ if (ontrue)
+ ast_propagate_effects(self, ontrue);
+ if (onfalse)
+ ast_propagate_effects(self, onfalse);
return self;
}
self->cond = cond;
self->on_true = ontrue;
self->on_false = onfalse;
+ ast_propagate_effects(self, cond);
+ ast_propagate_effects(self, ontrue);
+ ast_propagate_effects(self, onfalse);
if (!ast_type_adopt(self, ontrue)) {
ast_ternary_delete(self);
self->increment = increment;
self->body = body;
+ if (initexpr)
+ ast_propagate_effects(self, initexpr);
+ if (precond)
+ ast_propagate_effects(self, precond);
+ if (postcond)
+ ast_propagate_effects(self, postcond);
+ if (increment)
+ ast_propagate_effects(self, increment);
+ if (body)
+ ast_propagate_effects(self, body);
+
return self;
}
self->operand = op;
self->cases = NULL;
+ ast_propagate_effects(self, op);
+
return self;
}
ast_instantiate(ast_call, ctx, ast_call_delete);
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_call_codegen);
+ ast_side_effects(self) = true;
+
self->params = NULL;
self->func = funcexpr;
ast_instantiate(ast_store, ctx, ast_store_delete);
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_store_codegen);
+ ast_side_effects(self) = true;
+
self->op = op;
self->dest = dest;
self->source = source;
return self;
}
+void ast_block_add_expr(ast_block *self, ast_expression *e)
+{
+ ast_propagate_effects(self, e);
+ vec_push(self->exprs, e);
+}
+
void ast_block_collect(ast_block *self, ast_expression *expr)
{
vec_push(self->collect, expr);