diff options
| -rw-r--r-- | evaluate.c | 63 | ||||
| -rw-r--r-- | expression.c | 21 | ||||
| -rw-r--r-- | expression.h | 24 | ||||
| -rw-r--r-- | lib.c | 13 | ||||
| -rw-r--r-- | lib.h | 17 | ||||
| -rw-r--r-- | parse.h | 2 | ||||
| -rw-r--r-- | show-parse.c | 24 | ||||
| -rw-r--r-- | test-parsing.c | 2 |
8 files changed, 158 insertions, 8 deletions
@@ -146,6 +146,13 @@ static int evaluate_binop(struct expression *expr) return 0; } +static int evaluate_assignment(struct expression *expr) +{ + // FIXME! We need to cast and check the rigth side! + expr->ctype = expr->left->ctype; + return 1; +} + static int evaluate_preop(struct expression *expr) { struct symbol *ctype = expr->unop->ctype; @@ -289,6 +296,54 @@ static int evaluate_sizeof(struct expression *expr) return 1; } +static int evaluate_lvalue_expression(struct expression *expr) +{ + // FIXME! + return evaluate_expression(expr); +} + +static int evaluate_expression_list(struct expression_list *head) +{ + if (head) { + struct ptr_list *list = (struct ptr_list *)head; + do { + int i; + for (i = 0; i < list->nr; i++) { + struct expression *expr = (struct expression *)list->list[i]; + evaluate_expression(expr); + } + } while ((list = list->next) != (struct ptr_list *)head); + } + // FIXME! + return 1; +} + +static int evaluate_call(struct expression *expr) +{ + int args, fnargs; + struct symbol *ctype; + struct expression *fn = expr->fn; + struct expression_list *arglist = expr->args; + + if (!evaluate_expression(fn)) + return 0; + if (!evaluate_expression_list(arglist)) + return 0; + ctype = fn->ctype; + if (ctype->type != SYM_FN) { + warn(expr->token, "not a function"); + return 0; + } + args = expression_list_size(expr->args); + fnargs = symbol_list_size(ctype->arguments); + if (args < fnargs) + warn(expr->token, "not enough arguments for function"); + if (args > fnargs && !ctype->variadic) + warn(expr->token, "too many arguments for function"); + expr->ctype = ctype->ctype.base_type; + return 1; +} + int evaluate_expression(struct expression *expr) { if (!expr) @@ -307,6 +362,12 @@ int evaluate_expression(struct expression *expr) if (!evaluate_expression(expr->right)) return 0; return evaluate_binop(expr); + case EXPR_ASSIGNMENT: + if (!evaluate_lvalue_expression(expr->left)) + return 0; + if (!evaluate_expression(expr->right)) + return 0; + return evaluate_assignment(expr); case EXPR_PREOP: if (!evaluate_expression(expr->unop)) return 0; @@ -324,6 +385,8 @@ int evaluate_expression(struct expression *expr) return evaluate_sizeof(expr); case EXPR_DEREF: return evaluate_dereference(expr); + case EXPR_CALL: + return evaluate_call(expr); default: break; } diff --git a/expression.c b/expression.c index 0ca6c19e..0d3f66f7 100644 --- a/expression.c +++ b/expression.c @@ -93,6 +93,21 @@ struct token *primary_expression(struct token *token, struct expression **tree) return token; } +static struct token *expression_list(struct token *token, struct expression_list **list) +{ + while (!match_op(token, ')')) { + struct expression *expr = NULL; + token = assignment_expression(token, &expr); + if (!expr) + break; + add_expression(list, expr); + if (!match_op(token, ',')) + break; + token = token->next; + } + return token; +} + static struct token *postfix_expression(struct token *token, struct expression **tree) { struct expression *expr = NULL; @@ -142,8 +157,8 @@ static struct token *postfix_expression(struct token *token, struct expression * case '(': { /* Function call */ struct expression *call = alloc_expression(token, EXPR_CALL); call->op = '('; - call->left = expr; - token = comma_expression(token->next, &call->right); + call->fn = expr; + token = expression_list(token->next, &call->args); token = expect(token, ')', "in function call"); expr = call; continue; @@ -331,7 +346,7 @@ struct token *assignment_expression(struct token *token, struct expression **tre int i, op = token->special; for (i = 0; i < sizeof(assignments)/sizeof(int); i++) if (assignments[i] == op) { - struct expression * expr = alloc_expression(token, EXPR_BINOP); + struct expression * expr = alloc_expression(token, EXPR_ASSIGNMENT); expr->left = *tree; expr->op = op; *tree = expr; diff --git a/expression.h b/expression.h index 83dbc6a8..56a1d7df 100644 --- a/expression.h +++ b/expression.h @@ -8,11 +8,14 @@ * Declarations and helper functions for expression parsing. */ +struct expression_list; + enum expression_type { EXPR_CONSTANT, EXPR_VALUE, EXPR_SYMBOL, EXPR_BINOP, + EXPR_ASSIGNMENT, EXPR_DEREF, EXPR_PREOP, EXPR_POSTOP, @@ -28,27 +31,40 @@ struct expression { struct token *token; struct symbol *ctype; union { + // EXPR_VALUE long long value; + + // EXPR_UNOP, EXPR_PREOP and EXPR_POSTOP struct expression *unop; - struct statement *statement; + + // EXPR_SYMBOL struct symbol *symbol; + + // EXPR_STATEMENT + struct statement *statement; + + // EXPR_BINOP and EXPR_ASSIGNMENT struct binop_arg { struct expression *left, *right; }; + // EXPR_DEREF struct deref_arg { struct expression *deref; struct token *member; }; + // EXPR_CAST and EXPR_SIZEOF struct cast_arg { struct symbol *cast_type; struct expression *cast_expression; }; + // EXPR_CONDITIONAL struct conditional_expr { struct expression *conditional, *cond_true, *cond_false; }; - struct statement_struct { - struct symbol_list *syms; - struct statement_list *stmts; + // EXPR_CALL + struct call_expr { + struct expression *fn; + struct expression_list *args; }; }; }; @@ -163,6 +163,19 @@ ALLOCATOR(ident); ALLOCATOR(token); ALLOCATOR(symbol); ALLOCATOR(expression); ALLOCATOR(statement); ALLOCATOR(string); __ALLOCATOR(void, 0, , bytes); +int ptr_list_size(struct ptr_list *head) +{ + int nr = 0; + + if (head) { + struct ptr_list *list = head; + do { + nr += list->nr; + } while ((list = list->next) != head); + } + return nr; +} + void iterate(struct ptr_list *head, void (*callback)(void *, void *, int), void *data) { struct ptr_list *list = head; @@ -14,6 +14,8 @@ struct symbol; struct symbol_list; struct statement; struct statement_list; +struct expression; +struct expression_list; struct token *skip_to(struct token *, int); struct token *expect(struct token *, int, const char *); @@ -47,6 +49,11 @@ struct ptr_list { #define ITERATE_LAST 2 void iterate(struct ptr_list *,void (*callback)(void *, void *, int), void*); extern void add_ptr_list(struct ptr_list **, void *); +extern int ptr_list_size(struct ptr_list *); + +#define symbol_list_size(list) ptr_list_size((struct ptr_list *)(list)) +#define statement_list_size(list) ptr_list_size((struct ptr_list *)(list)) +#define expression_list_size(list) ptr_list_size((struct ptr_list *)(list)) static inline void add_symbol(struct symbol_list **list, struct symbol *sym) { @@ -58,6 +65,11 @@ static inline void add_statement(struct statement_list **list, struct statement add_ptr_list((struct ptr_list **)list, stmt); } +static inline void add_expression(struct expression_list **list, struct expression *expr) +{ + add_ptr_list((struct ptr_list **)list, expr); +} + static inline void symbol_iterate(struct symbol_list *list, void (*callback)(struct symbol *, void *, int), void *data) { iterate((struct ptr_list *)list, (void (*)(void *, void *, int))callback, data); @@ -68,4 +80,9 @@ static inline void statement_iterate(struct statement_list *list, void (*callbac iterate((struct ptr_list *)list, (void (*)(void *, void *, int))callback, data); } +static inline void expression_iterate(struct expression_list *list, void (*callback)(struct expression *, void *, int), void *data) +{ + iterate((struct ptr_list *)list, (void (*)(void *, void *, int))callback, data); +} + #endif @@ -25,7 +25,7 @@ enum statement_type { }; struct statement { - int type; + enum statement_type type; struct token *token; struct statement *next; union { diff --git a/show-parse.c b/show-parse.c index 8ac94500..b3badd2c 100644 --- a/show-parse.c +++ b/show-parse.c @@ -334,6 +334,18 @@ static void show_size(struct symbol *sym) printf("%d:%d", sym->bit_size, sym->alignment); } +static void show_one_expression(struct expression *expr, void *sep, int flags) +{ + show_expression(expr); + if (!(flags & ITERATE_LAST)) + printf("%s", (const char *)sep); +} + +void show_expression_list(struct expression_list *list, const char *sep) +{ + expression_iterate(list, show_one_expression, (void *)sep); +} + /* * Print out an expression */ @@ -347,6 +359,18 @@ void show_expression(struct expression *expr) show_type(expr->ctype); printf(") "); switch (expr->type) { + case EXPR_CALL: + show_expression(expr->fn); + printf("( "); + show_expression_list(expr->args, ", "); + printf(" )"); + break; + + case EXPR_ASSIGNMENT: + show_expression(expr->left); + printf(" %s ", show_special(expr->op)); + show_expression(expr->right); + break; case EXPR_BINOP: show_expression(expr->left); printf(" %s ", show_special(expr->op)); diff --git a/test-parsing.c b/test-parsing.c index b5ecb501..908a70cb 100644 --- a/test-parsing.c +++ b/test-parsing.c @@ -60,6 +60,8 @@ static void simplify_statement(struct statement *stmt, struct symbol *fn) evaluate_expression(stmt->case_to); simplify_statement(stmt->case_statement, fn); return; + default: + break; } } |
