From: Dale Weiler Date: Mon, 16 Dec 2013 23:35:31 +0000 (-0500) Subject: Perliminary stuff for any/all ranges. This doesn't do anything, important, just some... X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=014ea8e80ed6412aee4b0f898363b401076fc622;p=xonotic%2Fgmqcc.git Perliminary stuff for any/all ranges. This doesn't do anything, important, just some pseudo structure and documentation. --- diff --git a/ast.c b/ast.c index e10bbed..0ee4a21 100644 --- a/ast.c +++ b/ast.c @@ -75,6 +75,8 @@ static void ast_binstore_delete(ast_binstore*); 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) @@ -918,6 +920,27 @@ void ast_switch_delete(ast_switch *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); @@ -3266,6 +3289,30 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va 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; diff --git a/ast.h b/ast.h index 936a587..122af2f 100644 --- a/ast.h +++ b/ast.h @@ -51,6 +51,7 @@ typedef struct ast_member_s ast_member; 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; @@ -98,10 +99,11 @@ enum { 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) ) @@ -537,6 +539,38 @@ struct ast_switch_s 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'