if(is_type_integer(cnst->expression.datatype)) {
fprintf(out, "%d", cnst->v.int_value);
+ } else if(is_type_floating(cnst->expression.datatype)) {
+ fprintf(out, "%Lf", cnst->v.float_value);
}
}
fputs(expression->symbol->string, out);
}
+static void print_conditional(const conditional_expression_t *expression)
+{
+ fputs("(", out);
+ print_expression(expression->condition);
+ fputs(" ? ", out);
+ print_expression(expression->true_expression);
+ fputs(" : ", out);
+ print_expression(expression->false_expression);
+ fputs(")", out);
+}
+
void print_expression(const expression_t *expression)
{
switch(expression->type) {
case EXPR_BUILTIN_SYMBOL:
print_builtin_symbol((const builtin_symbol_expression_t*) expression);
break;
-
case EXPR_CONDITIONAL:
+ print_conditional((const conditional_expression_t*) expression);
+ break;
+
case EXPR_OFFSETOF:
case EXPR_STATEMENT:
case EXPR_SELECT:
fputs(");\n", out);
}
-static void print_for_statemenet(const for_statement_t *statement)
+static void print_for_statement(const for_statement_t *statement)
{
- fprintf(out, "for(TODO) ");
+ fputs("for(", out);
+ if(statement->context.declarations != NULL) {
+ assert(statement->initialisation == NULL);
+ print_declaration(statement->context.declarations);
+ if(statement->context.declarations->next != NULL) {
+ panic("multiple declarations in for statement not supported yet");
+ }
+ } else if(statement->initialisation) {
+ print_expression(statement->initialisation);
+ }
+ fputs("; ", out);
+ if(statement->condition != NULL) {
+ print_expression(statement->condition);
+ }
+ fputs("; ", out);
+ if(statement->step != NULL) {
+ print_expression(statement->step);
+ }
+ fputs(")", out);
print_statement(statement->body);
}
print_do_while_statement((const do_while_statement_t*) statement);
break;
case STATEMENT_FOR:
- print_for_statemenet((const for_statement_t*) statement);
+ print_for_statement((const for_statement_t*) statement);
break;
case STATEMENT_INVALID:
fprintf(out, "*invalid statement*");
static int lookahead_bufpos;
static struct obstack environment_obstack;
static environment_entry_t **environment_stack = NULL;
+static context_t *global_context = NULL;
static context_t *context = NULL;
static declaration_t *last_declaration = NULL;
static struct obstack temp_obst;
static type_t *type_int = NULL;
+static type_t *type_double = NULL;
static type_t *type_const_char = NULL;
static type_t *type_string = NULL;
static type_t *type_void = NULL;
const_t *cnst = allocate_ast_zero(sizeof(cnst[0]));
cnst->expression.type = EXPR_CONST;
- cnst->expression.datatype = type_int;
+ cnst->expression.datatype = type_double;
cnst->v.float_value = token.v.floatvalue;
next_token();
return (expression_t*) cnst;
}
+static declaration_t *create_implicit_function(symbol_t *symbol,
+ const source_position_t source_position)
+{
+ method_type_t *method_type = allocate_type_zero(sizeof(method_type));
+
+ method_type->type.type = TYPE_METHOD;
+ method_type->result_type = type_int;
+ method_type->unspecified_parameters = true;
+
+ type_t *type = typehash_insert((type_t*) method_type);
+ if(type != (type_t*) method_type) {
+ obstack_free(type_obst, method_type);
+ }
+
+ declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0]));
+
+ declaration->storage_class = STORAGE_CLASS_EXTERN;
+ declaration->type = type;
+ declaration->symbol = symbol;
+ declaration->source_position = source_position;
+
+ /* we have to violate the environment push/pop rules here and assign
+ * the declaration directly to its symbol and append it to the
+ * global context */
+ assert(symbol->declaration == NULL);
+ symbol->declaration = declaration;
+ declaration->next = global_context->declarations;
+ global_context->declarations = declaration;
+
+ return declaration;
+}
+
static expression_t *parse_reference(void)
{
reference_expression_t *ref = allocate_ast_zero(sizeof(ref[0]));
ref->expression.type = EXPR_REFERENCE;
ref->symbol = token.v.symbol;
- declaration_t *declaration = ref->symbol->declaration;
+ declaration_t *declaration = ref->symbol->declaration;
+ source_position_t source_position = token.source_position;
next_token();
if(declaration == NULL) {
#ifndef STRICT_C99
- /* is it an implicitely defined function */
+ /* an implicitely defined function */
if(token.type == '(') {
parser_print_prefix_pos(token.source_position);
fprintf(stderr, "warning: implicit declaration of function '%s'\n",
ref->symbol->string);
- /* TODO: do this correctly */
+
+ declaration = create_implicit_function(ref->symbol,
+ source_position);
+ } else
+#endif
+ {
+ parser_print_error_prefix();
+ fprintf(stderr, "unknown symbol '%s' found.\n", ref->symbol->string);
return (expression_t*) ref;
}
-#endif
-
- parser_print_error_prefix();
- fprintf(stderr, "unknown symbol '%s' found.\n", ref->symbol->string);
- } else {
- ref->declaration = declaration;
- ref->expression.datatype = declaration->type;
}
+ ref->declaration = declaration;
+ ref->expression.datatype = declaration->type;
return (expression_t*) ref;
}
{
translation_unit_t *unit = allocate_ast_zero(sizeof(unit[0]));
+ assert(global_context == NULL);
+ global_context = &unit->context;
+
assert(context == NULL);
set_context(&unit->context);
context = NULL;
last_declaration = NULL;
+ assert(global_context == &unit->context);
+ global_context = NULL;
+
return unit;
}
obstack_init(&temp_obst);
type_int = make_atomic_type(ATOMIC_TYPE_INT, 0);
+ type_double = make_atomic_type(ATOMIC_TYPE_DOUBLE, 0);
type_size_t = make_atomic_type(ATOMIC_TYPE_UINT, 0);
type_const_char = make_atomic_type(ATOMIC_TYPE_CHAR, TYPE_QUALIFIER_CONST);
type_void = make_atomic_type(ATOMIC_TYPE_VOID, 0);