WONKY



LOG | FILES | OVERVIEW


F diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt
src/debug/debug_type.c
src/debug/debug_value.c
src/debug/debug_ast.c
+ src/debug/wonky_assert.c
src/frontend/lex/automatas/chonky.c
src/frontend/lex/automatas/chonky_jr.c
src/frontend/lex/lexer.c
F 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-tokens
prints the tokens after preprocessing
F 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;
else
return 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;
else
return 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;
+ }
}
#endif
F 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);
+ }
+
+ }
+
+ #endif
F 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)
+
+ #endif
F 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_DEFINITION
F 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.c
return 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 TS
F diff --git a/tests/test_declaration.c b/tests/test_declaration.c --- a/tests/test_declaration.c +++ b/tests/test_declaration.c
int main()
{
struct A a;
- a.a=a;
+ a.a=1;
a.b=(void*)0;
return a.a;