F diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txtsrc/debug/debug_type.csrc/debug/debug_value.csrc/debug/debug_ast.c+ src/debug/wonky_assert.csrc/frontend/lex/automatas/chonky.csrc/frontend/lex/automatas/chonky_jr.csrc/frontend/lex/lexer.cF diff --git a/README b/README --- a/README +++ b/README- C compiler+ How to build:+ Use cmake out of the repository, for example /tmp/build++ You can compile wonky with make and run tests with make test++ Wonky C99 compiler command line arguments--print-tokensprints the tokens after preprocessingF diff --git a/src/debug/debug_ast.c b/src/debug/debug_ast.c --- a/src/debug/debug_ast.c +++ b/src/debug/debug_ast.c#define WONKY_DEBUG_AST_C WONKY_DEBUG_AST_C#include <debug_ast.h>+ typedef _Bool (*debug_ast_function_ptr)(void*);+++ static debug_ast_function_ptr debug_ast_vector[AST_TYPE_END+1]=+ {+ [OP_COMMA]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_ADDITION]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_POINTER_ADDITION]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_SUBTRACTION]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_MUL]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_DIV]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_REMAINDER]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_COND]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_FUNCTION]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_ADD_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_SUBTRACT_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_MULTIPLY_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_REMAINDER_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_DIV_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_SHIFT_RIGHT_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_AND_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_XOR_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_PIPE_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_NOP]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_LOGICAL_OR]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_LOGICAL_AND]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_LOGICAL_NOT]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_BITWISE_OR]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_BITWISE_AND]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_BITWISE_XOR]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_BITWISE_NOT]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_ADDR_OF]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_DEREFERENCE]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_MEMBER_TROUGH_PTR]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_MEMBER]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_ARR_SUBSCRIPT]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_POSTFIX_INC]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_POSTFIX_DEC]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_PREFIX_INC]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_PREFIX_DEC]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_UNARY_PLUS]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_UNARY_MINUS]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_CAST]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_SIZEOF]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_SHIFT_LEFT]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_SHIFT_RIGHT]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_LESS_EQ]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_GREATER_EQ]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_LESS]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_GREATER]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_EQUAL]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_NOT_EQUAL]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_DESIGNATOR]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_CONSTANT]=(debug_ast_function_ptr)is_valid_ast_expression,+ [OP_STRING_LITERAL]=(debug_ast_function_ptr)is_valid_ast_expression,+ [ST_COMPOUND]=(debug_ast_function_ptr)is_valid_compound_statement,+ [ST_EXPRESSION]=(debug_ast_function_ptr)is_valid_ast_expression,+ [ST_SWITCH]=(debug_ast_function_ptr)is_valid_switch_statement,+ [ST_IF]=(debug_ast_function_ptr)is_valid_if_statement,+ [ST_WHILE]=(debug_ast_function_ptr)is_valid_while_statement,+ [ST_DO_WHILE]=(debug_ast_function_ptr)is_valid_do_while_statement,+ [ST_GOTO]=(debug_ast_function_ptr)is_valid_goto_statement,+ [ST_LABEL]=(debug_ast_function_ptr)is_valid_labeled_statement,+ [ST_CASE]=(debug_ast_function_ptr)is_valid_case_statement,+ [ST_DEFAULT]=(debug_ast_function_ptr)is_valid_default_statement,+ [ST_CONTINUE]=(debug_ast_function_ptr)is_valid_break_continue_statement,+ [ST_BREAK]=(debug_ast_function_ptr)is_valid_break_continue_statement,+ [ST_RETURN]=(debug_ast_function_ptr)is_valid_return_statement,+ [ST_FOR]=(debug_ast_function_ptr)is_valid_for_statement,+ [ST_OBJECT_DECLARATION]=(debug_ast_function_ptr)is_valid_object_declaration,+ [ST_TYPE_DEFINITION]=(debug_ast_function_ptr)is_valid_type_definition,+ [ST_FUNCTION_DEFINITION]=(debug_ast_function_ptr)is_valid_function_definition,+ [ST_FUNCTION_DECLARATION]=(debug_ast_function_ptr)is_valid_function_declaration,+ [TRANSLATION_UNIT]=(debug_ast_function_ptr)is_valid_translation_unit,+ [ERROR]=(debug_ast_function_ptr)is_valid_ast_error,+ };+_Bool is_valid_ast_enum(enum AST_Type ast_type){return ast_type>=0 && ast_type<AST_TYPE_END;}+ _Bool is_valid_ast_expression_enum(enum AST_Type ast_type)+ {+ return ast_type>AST_TYPE_EXPRESSION_START && ast_type<AST_TYPE_EXPRESSION_END;+ }_Bool is_valid_ast(struct AST *ast){- return ast==NULL || is_valid_ast_enum(ast->type);+ if(ast==NULL || !is_valid_ast_enum(ast->type) || debug_ast_vector[ast->type]==NULL)+ return 0;+ else+ return debug_ast_vector[ast->type];}_Bool is_valid_ast_expression(struct AST_Expression *expression){- if(expression==NULL || !is_valid_ast_enum(expression->type))+ if(expression==NULL || !is_valid_ast_expression_enum(expression->type))return 0;else- return 1;+ return is_valid_ast((struct AST*)expression);}_Bool is_valid_ast_error(struct AST_Error *error){- if(error==NULL || !is_valid_ast_enum(error->type))+ if(error==NULL || error->type!=ERROR)+ {return 0;- else- return 1;+ }else+ {+ if(error->error==NULL || is_valid_ast(error->error))+ return 1;+ else+ return 0;+ }}_Bool is_valid_binary_expression(struct AST_Binary_Expression *expression){- if(expression==NULL || !is_valid_ast_enum(expression->type))+ if(expression==NULL || !is_valid_ast_expression_enum(expression->type))return 0;else- return 1;+ {+ return is_valid_value(expression->value)+ &&+ is_valid_ast_expression(expression->left)+ &&+ is_valid_ast_expression(expression->right)+ ;+ }}_Bool is_valid_pointer_addition_expression(struct AST_Pointer_Addition_Expression *addition){- if(addition==NULL || !is_valid_ast_enum(addition->type))+ if(addition==NULL || addition->type!=OP_POINTER_ADDITION)return 0;else- return 1;+ {+ return is_valid_value(addition->value)+ &&+ is_valid_ast_expression(addition->pointer)+ &&+ is_valid_ast_expression(addition->integer)+ ;+ }}_Bool is_valid_conditional_expression(struct AST_Conditional_Expression *conditional_expression){- if(conditional_expression==NULL || !is_valid_ast_enum(conditional_expression->type))+ if(conditional_expression==NULL || conditional_expression->type!=OP_COND)return 0;else- return 1;+ {+ return is_valid_value(conditional_expression->value)+ &&+ is_valid_ast_expression(conditional_expression->left)+ &&+ is_valid_ast_expression(conditional_expression->center)+ &&+ is_valid_ast_expression(conditional_expression->right)+ ;+ }}_Bool is_valid_function_expression(struct AST_Function_Expression *function_call){- if(function_call==NULL || !is_valid_ast_enum(function_call->type))+ if(function_call==NULL || function_call->type!=OP_FUNCTION)return 0;- else if(!is_valid_ast_expression(function_call->id))+ else if(!is_valid_ast_expression(function_call->id) || !is_valid_value(function_call->value))return 0;else+ {+ size_t i;+ for(i=0;i<function_call->number_of_arguments;++i)+ if(!is_valid_ast_expression(function_call->arg_list[i]))+ return 0;return 1;+ }}_Bool is_valid_ast_constant(struct AST_Constant *constant){- if(constant==NULL || !is_valid_ast_enum(constant->type))+ if(constant==NULL || constant->type!=OP_CONSTANT)return 0;elsereturn 1;}_Bool is_valid_ast_string_literal(struct AST_String_Literal *literal){- if(literal==NULL || !is_valid_ast_enum(literal->type))+ if(literal==NULL || literal->type!=OP_STRING_LITERAL)return 0;elsereturn 1;}_Bool is_valid_ast_designator(struct AST_Designator *designator){- return 1;+ if(designator==NULL || designator->type!=OP_DESIGNATOR)+ return 0;+ else+ return is_valid_value(designator->value)+ &&+ is_valid_token(designator->id)+ ;}_Bool is_valid_unary_expression(struct AST_Unary_Expression *expression){- return 1;+ static _Bool unary_expressions[AST_TYPE_END]+ =+ {+ [OP_CAST]=1,+ [OP_DEREFERENCE]=1,+ [OP_ADDR_OF]=1,+ [OP_SIZEOF]=1,+ [OP_PREFIX_INC]=1,+ [OP_PREFIX_DEC]=1,+ [OP_POSTFIX_INC]=1,+ [OP_POSTFIX_DEC]=1,+ [OP_UNARY_PLUS]=1,+ [OP_UNARY_MINUS]=1,+ [OP_BITWISE_NOT]=1,+ [OP_LOGICAL_NOT]=1,+ };++ if(expression==NULL || !is_valid_expression_value_type(expression->type) || !unary_expressions[expression->type])+ return 0;+ else+ return is_valid_value(expression->value) && is_valid_ast_expression(expression->operand);}_Bool is_valid_labeled_statement(struct AST_Labeled_Statement *statement){- return 1;+ if(statement==NULL || !is_valid_ast_enum(statement->type))+ return 0;+ else+ return is_valid_denoted_statement(statement->label);}_Bool is_valid_case_statement(struct AST_Case_Statement *statement){- return 1;+ if(statement==NULL || !is_valid_ast_enum(statement->type))+ return 0;+ else+ return is_valid_ast(statement->statement) && is_valid_ast_expression(statement->control);}_Bool is_valid_default_statement(struct AST_Default_Statement *statement){- return 1;+ if(statement==NULL || !is_valid_ast_enum(statement->type))+ return 0;+ else+ return is_valid_ast(statement->statement);}_Bool is_valid_break_continue_statement(struct AST_Break_Continue_Statement *statement){- return 1;+ if(statement==NULL || !is_valid_ast_enum(statement->type))+ return 0;+ else+ return statement->parent!=NULL; /*we don't check parent*/}_Bool is_valid_compound_statement(struct AST_Compound_Statement *statement){- return 1;+ if(statement==NULL || !is_valid_ast_enum(statement->type))+ return 0;+ else+ {+ struct Queue_Node *it;+ for(it=statement->components.first;it!=NULL;it=it->prev)+ if(!is_valid_ast(it->data))+ return 0;++ return statement->scope!=NULL;+ }}_Bool is_valid_for_statement(struct AST_For_Statement *statement){- return 1;+ if(statement==NULL || !is_valid_ast_enum(statement->type))+ return 0;+ else+ {+ return is_valid_ast(statement->condition)+ &&+ is_valid_ast(statement->initialisation)+ &&+ is_valid_ast(statement->update)+ &&+ is_valid_ast(statement->body_statement)+ ;+ }}_Bool is_valid_while_statement(struct AST_While_Statement *statement){- return 1;+ if(statement==NULL || !is_valid_ast_enum(statement->type))+ return 0;+ else+ {+ return is_valid_ast(statement->condition)+ &&+ is_valid_ast(statement->body_statement)+ ;+ }}_Bool is_valid_do_while_statement(struct AST_Do_While_Statement *statement){- return 1;+ if(statement==NULL || statement->type!=ST_DO_WHILE)+ return 0;+ else+ {+ return is_valid_ast(statement->condition)+ &&+ is_valid_ast(statement->body_statement)+ ;+ }}_Bool is_valid_if_statement(struct AST_If_Statement *statement){- return 1;+ if(statement==NULL || !is_valid_ast_enum(statement->type))+ return 0;+ else+ {+ if(statement->else_statement!=NULL && !is_valid_ast(statement->else_statement))+ return 0;+ else+ return is_valid_ast(statement->condition)+ &&+ is_valid_ast(statement->body_statement)+ ;+ }}_Bool is_valid_goto_statement(struct AST_Goto_Statement *statement){- return 1;+ if(statement==NULL || !is_valid_ast_enum(statement->type))+ return 0;+ else+ {+ if(statement->label!=NULL && !is_valid_denoted_statement(statement->label))+ return 0;+ if(statement->previous_denoted_object!=NULL && !is_valid_denoted_object(statement->previous_denoted_object))+ return 0;+ return 1;+ }}_Bool is_valid_switch_statement(struct AST_Switch_Statement *statement){- return 1;+ if(statement==NULL || !is_valid_ast_enum(statement->type))+ return 0;+ else+ {+ return is_valid_ast_expression(statement->condition)+ &&+ is_valid_ast(statement->body_statement);+ }}_Bool is_valid_return_statement(struct AST_Return_Statement *statement){- return 1;+ if(statement==NULL || !is_valid_ast_enum(statement->type))+ return 0;+ else+ return is_valid_ast(statement->return_expression);}_Bool is_valid_type_definition(struct AST_Type_Definition *definition){- return 1;+ if(definition==NULL || !is_valid_ast_enum(definition->type))+ return 0;+ else+ return is_valid_denoted_type(definition->definition);}_Bool is_valid_object_declaration(struct AST_Object_Declaration *declaration){- return 1;+ if(declaration==NULL || !is_valid_ast_enum(declaration->type))+ return 0;+ else+ return is_valid_denoted_object(declaration->object) && is_valid_initialiser(declaration->initializer);}_Bool is_valid_function_definition(struct AST_Function_Definition *definition){- return 1;+ if(definition==NULL || !is_valid_ast_enum(definition->type))+ return 0;+ else+ return is_valid_denoted_function(definition->function) && is_valid_compound_statement(definition->body);}_Bool is_valid_function_declaration(struct AST_Function_Declaration *declaration){- return 1;+ if(declaration==NULL || !is_valid_ast_enum(declaration->type))+ return 0;+ else+ return is_valid_denoted_function(declaration->function);}_Bool is_valid_translation_unit(struct AST_Translation_Unit *unit){- return 1;+ if(unit==NULL || !is_valid_ast_enum(unit->type))+ return 0;+ else+ {+ struct Queue_Node *it;+ for(it=unit->components->first;it!=NULL;it=it->prev)+ if(!is_valid_ast(it->data))+ return 0;+ if(!is_valid_scope(unit->file_scope))+ return 0;++ if(!is_valid_linkage(unit->internal_linkage))+ return 0;++ return unit->static_declarations!=NULL;+ }}#endifF diff --git a/src/debug/debug_ast.h b/src/debug/debug_ast.h --- a/src/debug/debug_ast.h +++ b/src/debug/debug_ast.h#include <common.h>_Bool is_valid_ast_enum(enum AST_Type ast_type);- _Bool is_valid_ast(struct AST *ast);+ _Bool is_valid_ast_expression_enum(enum AST_Type ast_type);+ _Bool is_valid_ast(struct AST *ast);_Bool is_valid_ast_expression(struct AST_Expression *expression);_Bool is_valid_ast_error(struct AST_Error *error);_Bool is_valid_binary_expression(struct AST_Binary_Expression *expression);F diff --git a/src/debug/wobler/wobler.c b/src/debug/wobler/wobler.c --- a/src/debug/wobler/wobler.c +++ b/src/debug/wobler/wobler.c#include <wonky.h>#include <print.h>#include <stdio.h>+ #include <stdlib.h>#include <time.h>#include <float.h>void dump_program_messages(FILE *where,struct Program *program);void print_result(char *error_message,char **filenames,struct Program *program);+ void detect_abort();+ _Bool should_be_exiting_right_now;+static struct test_entry{char *filenames[100];stdout=fopen(log_dump_location,"w");stderr=stdout;+ atexit(detect_abort);fprintf(real_stdout,"THE WOBLER HAS AWOKEN!!\n\n");run_tests();fprintf(real_stdout,"\n");printf("\n");}++ void detect_abort()+ {+ if(!should_be_exiting_right_now)+ {+ printf("\n[ABORT ]\t");+ fprintf(real_stderr,"\n[ABORT ]\t");+ print_names(tests[current_test].filenames);+ }+ }F diff --git a/src/debug/wonky_assert.c b/src/debug/wonky_assert.c new file mode 100644 --- /dev/null +++ b/src/debug/wonky_assert.c+ #ifndef WONKY_ASSERT_C+ #define WONKY_ASSERT_C WONKY_ASSERT_C+ #include <wonky_assert.h>+++ void wonky_assert_function(_Bool assertion)+ {+ if(!assertion)+ {+ printf("Assertion failed %s\n",__func__);+ exit(1);+ }++ }++ #endifF diff --git a/src/debug/wonky_assert.h b/src/debug/wonky_assert.h new file mode 100644 --- /dev/null +++ b/src/debug/wonky_assert.h+ #if (!defined(WONKY_ASSERT_H) && !defined(NDEBUG)) || (!defined(WONKY_ASSERT_H) && defined(WONKY_ASSERT_C))+ #define WONKY_ASSERT_H WONKY_ASSERT_H+ #include <stdlib.h>+ #include <stdio.h>++ #define wonky_assert(assertion) wonky_assert_function(assertion)++ /*this is a hack to make the wobler work better*/+ void wonky_assert_function(_Bool assertion);+++ #elif !defined(WONKY_DEBUG)++ #define wonky_assert(assertion) ((void)0)++ #endifF diff --git a/src/semantics/ast.hh b/src/semantics/ast.hh --- a/src/semantics/ast.hh +++ b/src/semantics/ast.hh#define AS_AST_CONSTANT(x) ((struct AST_Constant*)(x))enum AST_Type{- OP_COMMA+ AST_TYPE_EXPRESSION_START+ ,OP_COMMA,OP_ADDITION,OP_POINTER_ADDITION,OP_SUBTRACTION,OP_MUL,OP_DIV,OP_REMAINDER,OP_COND,OP_FUNCTION,OP_ASSIGN,OP_ADD_ASSIGN,OP_SUBTRACT_ASSIGN,OP_MULTIPLY_ASSIGN,OP_REMAINDER_ASSIGN,OP_DIV_ASSIGN,OP_LESS,OP_GREATER,OP_EQUAL,OP_NOT_EQUAL,OP_DESIGNATOR,OP_CONSTANT,OP_STRING_LITERAL+ ,AST_TYPE_EXPRESSION_END,ST_COMPOUND,ST_EXPRESSION,ST_SWITCH,ST_IF,ST_WHILE,ST_DO_WHILE,ST_GOTO,ST_LABEL,ST_CASE,ST_DEFAULT,ST_CONTINUE,ST_BREAK,ST_RETURN,ST_FOR,ST_OBJECT_DECLARATION,ST_TYPE_DEFINITION,ST_FUNCTION_DEFINITIONF diff --git a/src/semantics/constraints/expression_constraints.c b/src/semantics/constraints/expression_constraints.c --- a/src/semantics/constraints/expression_constraints.c +++ b/src/semantics/constraints/expression_constraints.creturn 1;}else{- push_translation_error("constraint check violation in simple assignment expression",translation_data);+ push_translation_error("cannot assign %T to %T in simple assignment",translation_data,right_type,left_type);return 0;}//TODO ADD _BOOL TSF diff --git a/tests/test_declaration.c b/tests/test_declaration.c --- a/tests/test_declaration.c +++ b/tests/test_declaration.cint main(){struct A a;- a.a=a;+ a.a=1;a.b=(void*)0;return a.a;