aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--evaluate.c119
-rw-r--r--expression.c99
-rw-r--r--expression.h6
-rw-r--r--parse.c9
-rw-r--r--parse.h2
-rw-r--r--show-parse.c19
6 files changed, 124 insertions, 130 deletions
diff --git a/evaluate.c b/evaluate.c
index e20d5d1..ffad21f 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -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 *);
diff --git a/parse.c b/parse.c
index f0156ce..b34d54a 100644
--- a/parse.c
+++ b/parse.c
@@ -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);
diff --git a/parse.h b/parse.h
index 6909efe..f7d3392 100644
--- a/parse.h
+++ b/parse.h
@@ -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(" >");
}