diff options
-rw-r--r-- | evaluate.c | 119 | ||||
-rw-r--r-- | expression.c | 99 | ||||
-rw-r--r-- | expression.h | 6 | ||||
-rw-r--r-- | parse.c | 9 | ||||
-rw-r--r-- | parse.h | 2 | ||||
-rw-r--r-- | show-parse.c | 19 |
6 files changed, 124 insertions, 130 deletions
@@ -46,84 +46,6 @@ static int evaluate_symbol(struct expression *expr) return 1; } -static int get_int_value(struct expression *expr, const char *str) -{ - unsigned long long value = 0; - unsigned int base = 10, digit, bits; - unsigned long modifiers, extramod; - - switch (str[0]) { - case 'x': - base = 18; // the -= 2 for the octal case will - str++; // skip the 'x' - /* fallthrough */ - case 'o': - str++; // skip the 'o' or 'x/X' - base -= 2; // the fall-through will make this 8 - } - while ((digit = hexval(*str)) < base) { - value = value * base + digit; - str++; - } - modifiers = 0; - for (;;) { - char c = *str++; - if (c == 'u' || c == 'U') { - modifiers |= MOD_UNSIGNED; - continue; - } - if (c == 'l' || c == 'L') { - if (modifiers & MOD_LONG) - modifiers |= MOD_LONGLONG; - modifiers |= MOD_LONG; - continue; - } - break; - } - - bits = BITS_IN_LONGLONG; - extramod = 0; - if (!(modifiers & MOD_LONGLONG)) { - if (value & (~0ULL << BITS_IN_LONG)) { - extramod = MOD_LONGLONG | MOD_LONG; - } else { - bits = BITS_IN_LONG; - if (!(modifiers & MOD_LONG)) { - if (value & (~0ULL << BITS_IN_INT)) { - extramod = MOD_LONG; - } else - bits = BITS_IN_INT; - } - } - } - if (!(modifiers & MOD_UNSIGNED)) { - if (value & (1ULL << (bits-1))) { - extramod |= MOD_UNSIGNED; - } - } - if (extramod) { - /* - * Special case: "int" gets promoted directly to "long" - * for normal decimal numbers.. - */ - modifiers |= extramod; - if (base == 10 && modifiers == MOD_UNSIGNED) { - modifiers = MOD_LONG; - if (BITS_IN_LONG == BITS_IN_INT) - modifiers = MOD_LONG | MOD_UNSIGNED; - } - warn(expr->pos, "value is so big it is%s%s%s", - (modifiers & MOD_UNSIGNED) ? " unsigned":"", - (modifiers & MOD_LONG) ? " long":"", - (modifiers & MOD_LONGLONG) ? " long":""); - } - - expr->type = EXPR_VALUE; - expr->ctype = ctype_integer(modifiers); - expr->value = value; - return 1; -} - static int evaluate_string(struct expression *expr) { struct symbol *sym = alloc_symbol(expr->pos, SYM_ARRAY); @@ -139,30 +61,6 @@ static int evaluate_string(struct expression *expr) return 1; } -static int evaluate_constant(struct expression *expr) -{ - struct token *token = expr->token; - - switch (token_type(token)) { - case TOKEN_INTEGER: - return get_int_value(expr, token->integer); - - case TOKEN_CHAR: - expr->type = EXPR_VALUE; - expr->ctype = &int_ctype; - expr->value = (char) token->character; - return 1; - - case TOKEN_STRING: - expr->ctype = &string_ctype; - return 1; - - default: - warn(expr->pos, "non-typed expression"); - } - return 0; -} - static struct symbol *bigger_int_type(struct symbol *left, struct symbol *right) { unsigned long lmod, rmod, mod; @@ -837,8 +735,6 @@ int evaluate_expression(struct expression *expr) return 1; switch (expr->type) { - case EXPR_CONSTANT: - return evaluate_constant(expr); case EXPR_VALUE: warn(expr->pos, "value expression without a type"); return 0; @@ -890,9 +786,15 @@ int evaluate_expression(struct expression *expr) warn(expr->pos, "bitfield generated by parser"); return 0; case EXPR_CONDITIONAL: - // FIXME!! Conditional expression + if (!evaluate_expression(expr->conditional) || + !evaluate_expression(expr->cond_true) || + !evaluate_expression(expr->cond_false)) + return 0; + + // FIXME!! Conditional expression type return 0; case EXPR_STATEMENT: + // FIXME!! Statement expression return 0; case EXPR_INITIALIZER: @@ -926,11 +828,8 @@ long long get_expression_value(struct expression *expr) } warn(expr->pos, "expression sizes not yet supported"); return 0; - case EXPR_CONSTANT: - evaluate_constant(expr); - if (expr->type == EXPR_VALUE) - return expr->value; - return 0; + case EXPR_VALUE: + return expr->value; case EXPR_SYMBOL: { struct symbol *sym = expr->symbol; if (!sym || !sym->ctype.base_type || sym->ctype.base_type->type != SYM_ENUM) { diff --git a/expression.c b/expression.c index b01891c..76526c1 100644 --- a/expression.c +++ b/expression.c @@ -19,6 +19,7 @@ #include "symbol.h" #include "scope.h" #include "expression.h" +#include "target.h" static int match_oplist(int op, ...) { @@ -41,7 +42,7 @@ struct token *parens_expression(struct token *token, struct expression **expr, c token = expect(token, '(', where); if (match_op(token, '{')) { struct expression *e = alloc_expression(token->pos, EXPR_STATEMENT); - struct statement *stmt = alloc_statement(token, STMT_COMPOUND); + struct statement *stmt = alloc_statement(token->pos, STMT_COMPOUND); *expr = e; e->statement = stmt; start_symbol_scope(); @@ -84,16 +85,106 @@ static struct token *string_expression(struct token *token, struct expression *e return next; } +static void get_int_value(struct expression *expr, const char *str) +{ + unsigned long long value = 0; + unsigned int base = 10, digit, bits; + unsigned long modifiers, extramod; + + switch (str[0]) { + case 'x': + base = 18; // the -= 2 for the octal case will + str++; // skip the 'x' + /* fallthrough */ + case 'o': + str++; // skip the 'o' or 'x/X' + base -= 2; // the fall-through will make this 8 + } + while ((digit = hexval(*str)) < base) { + value = value * base + digit; + str++; + } + modifiers = 0; + for (;;) { + char c = *str++; + if (c == 'u' || c == 'U') { + modifiers |= MOD_UNSIGNED; + continue; + } + if (c == 'l' || c == 'L') { + if (modifiers & MOD_LONG) + modifiers |= MOD_LONGLONG; + modifiers |= MOD_LONG; + continue; + } + break; + } + + bits = BITS_IN_LONGLONG; + extramod = 0; + if (!(modifiers & MOD_LONGLONG)) { + if (value & (~0ULL << BITS_IN_LONG)) { + extramod = MOD_LONGLONG | MOD_LONG; + } else { + bits = BITS_IN_LONG; + if (!(modifiers & MOD_LONG)) { + if (value & (~0ULL << BITS_IN_INT)) { + extramod = MOD_LONG; + } else + bits = BITS_IN_INT; + } + } + } + if (!(modifiers & MOD_UNSIGNED)) { + if (value & (1ULL << (bits-1))) { + extramod |= MOD_UNSIGNED; + } + } + if (extramod) { + /* + * Special case: "int" gets promoted directly to "long" + * for normal decimal numbers.. + */ + modifiers |= extramod; + if (base == 10 && modifiers == MOD_UNSIGNED) { + modifiers = MOD_LONG; + if (BITS_IN_LONG == BITS_IN_INT) + modifiers = MOD_LONG | MOD_UNSIGNED; + } + warn(expr->pos, "value is so big it is%s%s%s", + (modifiers & MOD_UNSIGNED) ? " unsigned":"", + (modifiers & MOD_LONG) ? " long":"", + (modifiers & MOD_LONGLONG) ? " long":""); + } + + expr->type = EXPR_VALUE; + expr->ctype = ctype_integer(modifiers); + expr->value = value; +} + struct token *primary_expression(struct token *token, struct expression **tree) { struct expression *expr = NULL; switch (token_type(token)) { - case TOKEN_INTEGER: case TOKEN_FP: + expr = alloc_expression(token->pos, EXPR_VALUE); + expr->ctype = &double_ctype; + expr->value = 0; + warn(token->pos, "FP values not yet implemented"); + token = token->next; + break; + case TOKEN_CHAR: - expr = alloc_expression(token->pos, EXPR_CONSTANT); - expr->token = token; + expr = alloc_expression(token->pos, EXPR_VALUE); + expr->ctype = &int_ctype; + expr->value = (unsigned char) token->character; + token = token->next; + break; + + case TOKEN_INTEGER: + expr = alloc_expression(token->pos, EXPR_VALUE); + get_int_value(expr, token->integer); token = token->next; break; diff --git a/expression.h b/expression.h index 8eb069e..078409f 100644 --- a/expression.h +++ b/expression.h @@ -11,7 +11,6 @@ struct expression_list; enum expression_type { - EXPR_CONSTANT, EXPR_VALUE, EXPR_STRING, EXPR_SYMBOL, @@ -39,9 +38,6 @@ struct expression { struct position pos; struct symbol *ctype; union { - // EXPR_CONSTANT - struct token *token; - // EXPR_VALUE unsigned long long value; @@ -131,7 +127,7 @@ static inline int lookup_type(struct token *token) } /* Statement parsing */ -struct statement *alloc_statement(struct token * token, int type); +struct statement *alloc_statement(struct position pos, int type); struct token *initializer(struct expression **tree, struct token *token); struct token *compound_statement(struct token *, struct statement *); @@ -21,10 +21,11 @@ #include "scope.h" #include "expression.h" -struct statement *alloc_statement(struct token * token, int type) +struct statement *alloc_statement(struct position pos, int type) { struct statement *stmt = __alloc_statement(0); stmt->type = type; + stmt->pos = pos; return stmt; } @@ -514,14 +515,14 @@ static struct statement *make_statement(struct expression *expr) if (!expr) return NULL; - stmt = alloc_statement(expr->token, STMT_EXPRESSION); + stmt = alloc_statement(expr->pos, STMT_EXPRESSION); stmt->expression = expr; return stmt; } struct token *statement(struct token *token, struct statement **tree) { - struct statement *stmt = alloc_statement(token, STMT_NONE); + struct statement *stmt = alloc_statement(token->pos, STMT_NONE); *tree = stmt; if (token_type(token) == TOKEN_IDENT) { @@ -828,7 +829,7 @@ static struct token *external_declaration(struct token *token, struct symbol_lis base_type = decl->ctype.base_type; if (base_type && base_type->type == SYM_FN && match_op(token, '{')) { - base_type->stmt = alloc_statement(token, STMT_COMPOUND); + base_type->stmt = alloc_statement(token->pos, STMT_COMPOUND); start_symbol_scope(); symbol_iterate(base_type->arguments, declare_argument, decl); token = compound_statement(token->next, base_type->stmt); @@ -26,7 +26,7 @@ enum statement_type { struct statement { enum statement_type type; - struct token *token; + struct position pos; struct statement *next; union { struct label_arg { diff --git a/show-parse.c b/show-parse.c index 790fa9f..220ee21 100644 --- a/show-parse.c +++ b/show-parse.c @@ -421,9 +421,6 @@ void show_expression(struct expression *expr) show_expression(expr->unop); printf(" %s ", show_special(expr->op)); break; - case EXPR_CONSTANT: - printf("%s", show_token(expr->token)); - break; case EXPR_SYMBOL: if (!expr->symbol) { warn(expr->pos, "undefined symbol '%s'", show_ident(expr->symbol_name)); @@ -478,9 +475,19 @@ void show_expression(struct expression *expr) } else { printf("[%d ... %d]: ", expr->idx_from, expr->idx_to); } - break; - default: - printf("WTF"); + break; + case EXPR_CONDITIONAL: + show_expression(expr->conditional); + printf(" ? "); + show_expression(expr->cond_true); + printf(" : "); + show_expression(expr->cond_false); + break; + case EXPR_STATEMENT: + printf("({\n\t"); + show_statement(expr->statement); + printf("\n})"); + break; } printf(" >"); } |