typedef struct ast_label_s ast_label;
typedef struct ast_goto_s ast_goto;
typedef struct ast_argpipe_s ast_argpipe;
+typedef struct ast_intrinsic_s ast_intrinsic;
enum {
TYPE_ast_node, /* 0 */
TYPE_ast_switch, /* 18 */
TYPE_ast_label, /* 19 */
TYPE_ast_goto, /* 20 */
- TYPE_ast_argpipe /* 21 */
+ TYPE_ast_argpipe, /* 21 */
+ TYPE_ast_intrinsic /* 22 */
};
#define ast_istype(x, t) ( ((ast_node*)x)->nodetype == (TYPE_##t) )
ast_function *vfunc;
ast_value *vfield;
} basic_value_t;
+
struct ast_value_s
{
ast_expression expression;
*/
struct ast_member_s
{
- ast_expression expression;
+ ast_expression expression;
ast_expression *owner;
unsigned int field;
const char *name;
*/
struct ast_array_index_s
{
- ast_expression expression;
+ ast_expression expression;
ast_expression *array;
ast_expression *index;
};
*/
struct ast_argpipe_s
{
- ast_expression expression;
+ ast_expression expression;
ast_expression *index;
};
ast_argpipe* ast_argpipe_new(lex_ctx_t ctx, ast_expression *index);
*/
struct ast_store_s
{
- ast_expression expression;
+ ast_expression expression;
int op;
ast_expression *dest;
ast_expression *source;
*/
struct ast_ifthen_s
{
- ast_expression expression;
+ ast_expression expression;
ast_expression *cond;
/* It's all just 'expressions', since an ast_block is one too. */
ast_expression *on_true;
*/
struct ast_ternary_s
{
- ast_expression expression;
+ ast_expression expression;
ast_expression *cond;
/* It's all just 'expressions', since an ast_block is one too. */
ast_expression *on_true;
*/
struct ast_loop_s
{
- ast_expression expression;
+ ast_expression expression;
ast_expression *initexpr;
ast_expression *precond;
ast_expression *postcond;
*/
struct ast_breakcont_s
{
- ast_expression expression;
- bool is_continue;
- unsigned int levels;
+ ast_expression expression;
+ bool is_continue;
+ unsigned int levels;
};
ast_breakcont* ast_breakcont_new(lex_ctx_t ctx, bool iscont, unsigned int levels);
} ast_switch_case;
struct ast_switch_s
{
- ast_expression expression;
+ ast_expression expression;
ast_expression *operand;
ast_switch_case *cases;
*/
struct ast_label_s
{
- ast_expression expression;
- const char *name;
- ir_block *irblock;
- ast_goto **gotos;
+ ast_expression expression;
+ const char *name;
+ ir_block *irblock;
+ ast_goto **gotos;
+
/* means it has not yet been defined */
- bool undefined;
+ bool undefined;
};
ast_label* ast_label_new(lex_ctx_t ctx, const char *name, bool undefined);
*/
struct ast_goto_s
{
- ast_expression expression;
- const char *name;
- ast_label *target;
- ir_block *irblock_from;
+ ast_expression expression;
+ const char *name;
+ ast_label *target;
+ ir_block *irblock_from;
};
ast_goto* ast_goto_new(lex_ctx_t ctx, const char *name);
*/
struct ast_call_s
{
- ast_expression expression;
+ ast_expression expression;
ast_expression *func;
- ast_expression* *params;
+ ast_expression **params;
ast_expression *va_count;
};
ast_call* ast_call_new(lex_ctx_t ctx,
*/
struct ast_block_s
{
- ast_expression expression;
+ ast_expression expression;
ast_value* *locals;
ast_expression* *exprs;
*/
struct ast_function_s
{
- ast_node node;
+ ast_node node;
ast_value *vtype;
const char *name;
*/
static void con_enablecolor(void) {
if (console.handle_err == stderr || console.handle_err == stdout)
- console.color_err = true; /*!!(isatty(STDERR_FILENO));*/
+ console.color_err = !!(isatty(STDERR_FILENO));
if (console.handle_out == stderr || console.handle_out == stdout)
- console.color_out = true; /*!!(isatty(STDOUT_FILENO));*/
+ console.color_out = !!(isatty(STDOUT_FILENO));
}
/*
static ast_value *value = NULL;
if (!value) {
- ast_value *arg1 = ast_value_new (parser_ctx(parser), "x", TYPE_FLOAT);
+ ast_value *arg1 = ast_value_new (parser_ctx(parser), "x", TYPE_FLOAT);
ast_value *local = ast_value_new (parser_ctx(parser), "local", TYPE_FLOAT);
ast_block *body = ast_block_new (parser_ctx(parser));
ast_function *func = NULL;
return (ast_expression*)value;
}
+static ast_expression *intrin_debug_typestring(parser_t *parser) {
+ (void)parser;
+ return (ast_expression*)0x1;
+}
+
static intrin_t intrinsics[] = {
- {&intrin_exp, "__builtin_exp", "exp"},
- {&intrin_mod, "__builtin_mod", "mod"},
- {&intrin_pow, "__builtin_pow", "pow"},
- {&intrin_isnan, "__builtin_isnan", "isnan"}
+ {&intrin_exp, "__builtin_exp", "exp"},
+ {&intrin_mod, "__builtin_mod", "mod"},
+ {&intrin_pow, "__builtin_pow", "pow"},
+ {&intrin_isnan, "__builtin_isnan", "isnan"},
+ {&intrin_debug_typestring, "__builtin_debug_typestring", ""}
};
void intrin_intrinsics_destroy(parser_t *parser) {
/*size_t i;*/
(void)parser;
util_htdel(intrin_intrinsics());
-#if 0
- for (i = 0; i < sizeof(intrinsics)/sizeof(intrin_t); i++)
- ast_value_delete( (ast_value*) intrinsics[i].intrin(parser));
-#endif
}
/* register the intrinsics in the hashtable for O(1) lookup */
if (!init) {
for (i = 0; i < sizeof(intrinsics)/sizeof(*intrinsics); i++)
- util_htset(intrin_intrinsics(), intrinsics[i].alias, &intrinsics[i]);
+ util_htset(intrin_intrinsics(), intrinsics[i].name, &intrinsics[i]);
init = true; /* only once */
}
return ((intrin_t*)find)->intrin(parser);
}
+ /*
+ * check aliases now to see if there is an implementation of it.
+ */
+ for (i = 0; i < sizeof(intrinsics) / sizeof(*intrinsics); i++)
+ if (!strcmp(intrinsics[i].alias, name))
+ return intrinsics[i].intrin(parser);
+
parseerror(parser, "need function: `%s` compiler depends on it", name);
return NULL;
}
#define PARSER_HT_SIZE 512
#define TYPEDEF_HT_SIZE 512
-static ast_expression * const intrinsic_debug_typestring = (ast_expression*)0x1;
-
static void parser_enterblock(parser_t *parser);
static bool parser_leaveblock(parser_t *parser);
static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e);
return false;
}
- fun = sy->out[fid].out;
-
- if (fun == intrinsic_debug_typestring) {
+ /*
+ * TODO handle this at the intrinsic level with an ast_intrinsic
+ * node and codegen.
+ */
+ if ((fun = sy->out[fid].out) == intrin_debug_typestring(parser)) {
char ty[1024];
if (fid+2 != vec_size(sy->out) ||
vec_last(sy->out).block)
vec_shrinkby(sy->out, 1);
return true;
}
-
call = ast_call_new(sy->ops[vec_size(sy->ops)].ctx, fun);
+
if (!call)
return false;
/* a_vector.{x,y,z} */
if (!vec_size(sy->ops) ||
!vec_last(sy->ops).etype ||
- operators[vec_last(sy->ops).etype-1].id != opid1('.') ||
- (prev >= intrinsic_debug_typestring &&
- prev <= intrinsic_debug_typestring))
+ operators[vec_last(sy->ops).etype-1].id != opid1('.'))
{
/* When adding more intrinsics, fix the above condition */
prev = NULL;
if (!var && !strcmp(parser_tokval(parser), "__FUNC__"))
var = (ast_expression*)fold_constgen_string(parser->fold, parser->function->name, false);
if (!var) {
- /* intrinsics */
- if (!strcmp(parser_tokval(parser), "__builtin_debug_typestring")) {
- var = (ast_expression*)intrinsic_debug_typestring;
- }
- /* now we try for the real intrinsic hashtable. If the string
+ /*
+ * now we try for the real intrinsic hashtable. If the string
* begins with __builtin, we simply skip past it, otherwise we
* use the identifier as is.
*/
- else if (!strncmp(parser_tokval(parser), "__builtin_", 10)) {
- var = intrin_func(parser, parser_tokval(parser) + 10 /* skip __builtin */);
+ if (!strncmp(parser_tokval(parser), "__builtin_", 10)) {
+ var = intrin_func(parser, parser_tokval(parser));
}
if (!var) {