static bool ast_binstore_codegen(ast_binstore*, ast_function*, bool lvalue, ir_value**);
static void ast_binary_delete(ast_binary*);
static bool ast_binary_codegen(ast_binary*, ast_function*, bool lvalue, ir_value**);
+static void ast_range_delete(ast_range *);
+static bool ast_range_codegen(ast_range*, ast_function*, bool lvalue, ir_value**);
/* It must not be possible to get here. */
static GMQCC_NORETURN void _ast_node_destroy(ast_node *self)
mem_d(self);
}
+ast_range* ast_range_new(lex_ctx_t ctx, ast_expression *lower, ast_expression *upper) {
+ ast_instantiate(ast_range, ctx, ast_range_delete);
+ ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_range_codegen);
+
+ self->lower = lower;
+ self->upper = upper;
+
+ ast_propagate_effects(self, lower);
+ ast_propagate_effects(self, upper);
+
+ return self;
+}
+
+void ast_range_delete(ast_range *self) {
+ ast_unref(self->upper);
+ ast_unref(self->lower);
+
+ ast_expression_delete((ast_expression*)self);
+ mem_d(self);
+}
+
ast_label* ast_label_new(lex_ctx_t ctx, const char *name, bool undefined)
{
ast_instantiate(ast_label, ctx, ast_label_delete);
return true;
}
+bool ast_range_codegen(ast_range *self, ast_function *func, bool lvalue, ir_value **out) {
+ ast_expression_codegen *cgen = NULL;
+ ir_value *irupper = NULL;
+ ir_value *irlower = NULL;
+
+ if (lvalue) {
+ compile_error(ast_ctx(self), "range expression is not an l-value");
+ return false;
+ }
+
+ /* generate (lower .. upper) */
+ cgen = self->lower->codegen;
+ if (!(*cgen)((ast_expression*)(self->lower), func, false, &irlower))
+ return false;
+ cgen = self->upper->codegen;
+ if (!(*cgen)((ast_expression*)(self->upper), func, false, &irupper))
+ return false;
+
+ (void)lvalue;
+ (void)out;
+
+ return true;
+}
+
bool ast_label_codegen(ast_label *self, ast_function *func, bool lvalue, ir_value **out)
{
size_t i;
typedef struct ast_array_index_s ast_array_index;
typedef struct ast_breakcont_s ast_breakcont;
typedef struct ast_switch_s ast_switch;
+typedef struct ast_range_s ast_range;
typedef struct ast_label_s ast_label;
typedef struct ast_goto_s ast_goto;
typedef struct ast_argpipe_s ast_argpipe;
TYPE_ast_member, /* 15 */
TYPE_ast_array_index, /* 16 */
TYPE_ast_breakcont, /* 17 */
- TYPE_ast_switch, /* 18 */
- TYPE_ast_label, /* 19 */
- TYPE_ast_goto, /* 20 */
- TYPE_ast_argpipe /* 21 */
+ TYPE_ast_range, /* 18 */
+ TYPE_ast_switch, /* 19 */
+ TYPE_ast_label, /* 20 */
+ TYPE_ast_goto, /* 21 */
+ TYPE_ast_argpipe /* 22 */
};
#define ast_istype(x, t) ( ((ast_node*)x)->nodetype == (TYPE_##t) )
ast_switch* ast_switch_new(lex_ctx_t ctx, ast_expression *op);
+/*
+ * Ranges
+ *
+ * Used to implement any/all ranges, which are inclusive only.
+ * This any / all are range specifiers which change the semantics of
+ * how the range expression is dealt with. Because of the nature of ranges
+ * the whole expression it's used in needs to be rewrote. A table of how
+ * the rewrite works is provided below:
+ *
+ * (a == any b .. c) -> (a >= b && a <= c)
+ * (a == all b .. c) -> error (makes no sense)
+ * (a != any b .. c) -> error (makes no sense)
+ * (a != all b .. c) -> (a < b || a > c)
+ * (a <= any b .. c) -> (a <= c)
+ * (a <= all b .. c) -> (a <= b)
+ * (a >= any b .. c) -> (a >= b)
+ * (a >= all b .. c) -> (a >= c)
+ * (a < any b .. c) -> (a < c)
+ * (a < all b .. c) -> (a < b)
+ * (a > any b .. c) -> (a > b)
+ * (a > all b .. c) -> (a > c)
+ * (a <=> any b .. c) -> error (why would you even try)
+ * (a <=> all b .. c) -> error (why would you even try)
+ */
+struct ast_range_s {
+ ast_expression expression;
+ ast_expression *lower;
+ ast_expression *upper;
+};
+
+ast_range* ast_range_new(lex_ctx_t ctx, ast_expression *lower, ast_expression *upper);
+
/* Label nodes
*
* Introduce a label which can be used together with 'goto'