F diff --git a/CMakeLists.txt b/CMakeLists.txt
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
include_directories(src/frontend/lex)
include_directories(src/frontend/lex/automatas)
include_directories(src/frontend/parse)
+
include_directories(src/semantics)
include_directories(src/semantics/identifiers)
include_directories(src/semantics/memory)
include_directories(src/semantics/value)
include_directories(src/semantics/constraints)
+ include_directories(src/semantics/program)
+
include_directories(src/debug)
include_directories(src/debug/wobler)
include_directories(src/misc)
- include_directories(src/program)
+ include_directories(src/environment)
+ include_directories(src/environment/command_arguments)
+ include_directories(src/environment/error)
set(SOURCES
src/misc/map.c
src/misc/queue.c
src/misc/stack.c
- src/program/gcc_arguments.c
- src/program/gcc_error.c
- src/program/program.c
+ src/environment/command_arguments/gcc_arguments.c
+ src/environment/error/gcc_error.c
+ src/semantics/program/program.c
src/semantics/ast.c
src/semantics/constraints/expression_constraints.c
src/semantics/constraints/initialiser_constraints.c
F diff --git a/README b/README
deleted file mode 100644
--- a/README
+++ /dev/null
- 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
- --print-ast
- prints 'ast' of the program after parsing
F diff --git a/README.txt b/README.txt
new file mode 100644
--- /dev/null
+++ b/README.txt
+ What is Wonky:
+ Wonky is supposed to be a c99 compiler. Sadly at the moment it does not compile to machine code, or asm.
+
+ What can I do with it?
+ Nothing interesting at the moment.
+
+ How to build it:
+ Use cmake out of the repository, for example /tmp/build
+ You can compile wonky with make and run tests with make test
+
+ How to contibute:
+ If you have added code or documentation you can send it to me
+ via email gts@volconst.com
+
+ Wonky C99 compiler command line arguments
+ --print-tokens
+ prints the tokens after preprocessing
+ --print-ast
+ prints 'ast' of the program after parsing
+ --compile-asm or -asm
+ outputs asm to stdout. Mostly NOPs and segfaults at the moment.
F diff --git a/doc/arch.txt b/doc/arch.txt
new file mode 100644
--- /dev/null
+++ b/doc/arch.txt
+ Wonky follows the standart architecture
+ of a parsing and lexing frontend followed by a
+ code generation backend.
+
+ Currently there is no middle end -
+ the intermideate representation and
+ optimisations done on it. It is a goal
+ to make one.
+
+
+ Parsing and semantics are separated.
+
+ Constraint checks are separated from whatever
+ has constraint checks in the hope of preserving
+ code readability. ( Not fully implemented )
+
+
+ ASTs are a very fragile part of the design.
+ Adding node types is very difficult, because
+ their use is scattered accross the whole program.
+ This was done to simplify code organisation, but
+ did not work out. Will refactor them so that
+ the functions that use them are in them ( very
+ C++ like ). This or rely on IR to serve as a
+ mask to the asts.
F diff --git a/doc/build.txt b/doc/build.txt
new file mode 100644
--- /dev/null
+++ b/doc/build.txt
+ Wonky is currently build using cmake
+ It defaults to building with debug symbols and
+ no optimisations.
+
+ If you want to add a source file for
+ compiling you must add it to the SOURCE
+ var, and if it's located in new directory
+ you must run include_directories on it.
+
+ The only complex thing the cmake script
+ compiling a different object for the
+ normal assert and the debug assert that
+ the wobler uses and linking them to
+ wonky and wobler correctly.
F diff --git a/doc/hier.txt b/doc/hier.txt
new file mode 100644
--- /dev/null
+++ b/doc/hier.txt
+ The source of Wonky is scattered many different
+ directories with the hope of preserving tidiness.
+ They should be self explanatory, but here is a
+ list ( that is probabbly incomplete and out of date )
+ so you know how to interpret the names
+
+ doc - documentation dir
+ tests - test .c files dir
+ src - root source dir
+ src/backend - source proccessing code dir
+ src/frontend - code generation code dir
+ src/debug - functions for asserts and wobler dir
+ src/misc - non compiler specific data structures dir
+ src/environment - deals with the host system, I/O and command line args
+ src/semantics - data structures specific to the compiler and code that
+ deals with them
+
F diff --git a/doc/tests.txt b/doc/tests.txt
new file mode 100644
--- /dev/null
+++ b/doc/tests.txt
+ make test
+
+ Tests are mainly done with asserts in the source code.
+ Wonky uses wonky_assert. There asserts are triggered
+ by lexing and parsing the .c files in the tests directory
+
+ There is an in house testing system named
+ the wobler. It's currently located in src/debug/wobler.
+
+ It links to a different assert function implementation
+ that lets it continue on with tests after an assertion
+ fail.
+
+ If you want to add tests you need to put them into
+ the tests tld, the you must add it to the tests array
+ ( currently in src/debug/wobler/wobler_tests.h )
F diff --git a/doc/todo.txt b/doc/todo.txt
new file mode 100644
--- /dev/null
+++ b/doc/todo.txt
+ Add #pragma, #line and whatever preprocessing directives
+ are still undone.
+ Create a custom allocation system.
+ Implement the const expression evaluation stuff
+ Add asm compilation stuff.
F diff --git a/src/environment/command_arguments/gcc_arguments.c b/src/environment/command_arguments/gcc_arguments.c
new file mode 100644
--- /dev/null
+++ b/src/environment/command_arguments/gcc_arguments.c
+ #ifndef WONKY_ARGUMENTS_C
+ #define WONKY_ARGUMENTS_C WONKY_ARGUMENTS_C
+ #include <gcc_arguments.h>
+
+
+
+ struct Command_Arguments* parse_command_arguments(char **argv)
+ {
+ struct Command_Arguments *ret;
+ struct Queue *source_names;
+
+ ret=malloc(sizeof(struct Command_Arguments));
+ ret->print_ast=ret->print_tokens=ret->transpile_to_js=ret->is_quiet=ret->compile_to_intel_asm=0;
+ ret->output_file=ret->javascript_extern_file=NULL;
+
+ source_names=malloc(sizeof(struct Queue));
+ Queue_Init(source_names);
+
+ ret->error_message=NULL;
+
+ /*we skip the first element(the program name)*/
+ for(++argv;*argv;++argv)
+ {
+ if(gstr_cmp(*argv,"--print-tokens"))
+ {
+ ret->print_tokens=1;
+ }else if(gstr_cmp(*argv,"--print-ast"))
+ {
+ ret->print_ast=1;
+ }else if(gstr_cmp(*argv,"--quiet") || gstr_cmp(*argv,"-q"))
+ {
+ ret->is_quiet=1;
+ if(ret->print_ast || ret->print_tokens)
+ {
+ ret->error_message="print and quiet conflict. Aborting";
+ break;
+ }
+ }else if(gstr_cmp(*argv,"--transpile_to_js") || gstr_cmp(*argv,"-js"))
+ {
+ ret->transpile_to_js=1;
+ }else if(gstr_cmp(*argv,"--compile-asm") || gstr_cmp(*argv,"-asm"))
+ {
+ ret->compile_to_intel_asm=1;
+ }else if(gstr_cmp(*argv,"-o"))
+ {
+ ++argv;
+ if(*argv==NULL)
+ {
+ ret->error_message="expected a filename after -o. Aborting";
+ break;
+ }else
+ {
+ ret->output_file=fopen(*argv,"w");
+ if(ret->output_file==NULL)
+ {
+ ret->error_message="Couldn't open file for output. Aborting";
+ break;
+ }
+ }
+ }else if(gstr_cmp(*argv,"--make-extern-file"))
+ {
+ ret->javascript_extern_file=fopen(*argv,"w");
+ if(ret->javascript_extern_file==NULL)
+ {
+ ret->error_message="Couldn't open file for extern dump. Aborting";
+ break;
+ }
+ }else if(gstr_cmp(*argv,"--add-html"))
+ {
+ ret->insert_html=1;
+ }else
+ {
+ Queue_Push(source_names,*argv);
+ }
+ }
+
+ ret->source_names=malloc((source_names->size+1)*sizeof(char*) );
+ ret->source_names[source_names->size]=NULL;
+ while(source_names->size)
+ {
+ ret->source_names[source_names->size-1]=(char*)source_names->first->data;
+ Queue_Pop(source_names);
+ }
+ free(source_names);
+ if(ret->transpile_to_js && ret->output_file==NULL)
+ {
+ ret->output_file=fopen("a.js","w");
+ if(ret==NULL)
+ ret->error_message="Couldn't open file for output. Aborting";
+ }
+ return ret;
+ }
+
+
+ void delete_command_arguments(struct Command_Arguments *args)
+ {
+ if(args->output_file!=NULL)
+ fclose(args->output_file);
+ if(args->javascript_extern_file!=NULL)
+ fclose(args->javascript_extern_file);
+
+ free(args->source_names);
+ free(args);
+ }
+
+ #endif
F diff --git a/src/environment/command_arguments/gcc_arguments.h b/src/environment/command_arguments/gcc_arguments.h
new file mode 100644
--- /dev/null
+++ b/src/environment/command_arguments/gcc_arguments.h
+ #ifndef WONKY_ARGUMENTS_H
+ #define WONKY_ARGUMENTS_H WONKY_ARGUMENTS_H
+ #include <gcc_arguments.hh>
+ #include <queue.h>
+ #include <gcc_string.h>
+ #include <stdio.h>
+ #include <common.h>
+
+
+ struct Command_Arguments
+ {
+ char **source_names;
+ char print_tokens:1;
+ char print_ast:1;
+ char is_quiet:1;
+ char transpile_to_js:1;
+ char insert_html:1;
+ char compile_to_intel_asm:1;
+
+
+ FILE* output_file;
+ FILE* javascript_extern_file;
+
+
+ char *error_message;
+ };
+
+ struct Command_Arguments* parse_command_arguments(char **argv);
+ void delete_command_arguments(struct Command_Arguments *args);
+
+ #endif
F diff --git a/src/environment/command_arguments/gcc_arguments.hh b/src/environment/command_arguments/gcc_arguments.hh
new file mode 100644
--- /dev/null
+++ b/src/environment/command_arguments/gcc_arguments.hh
+ #ifndef WONKY_ARGUMENTS_HH
+ #define WONKY_ARGUMENTS_HH WONKY_ARGUMENTS_HH
+
+
+ struct Command_Arguments;
+
+
+ #endif
F diff --git a/src/environment/error/gcc_error.c b/src/environment/error/gcc_error.c
new file mode 100644
--- /dev/null
+++ b/src/environment/error/gcc_error.c
+ #ifndef WONKY_ERROR_C
+ #define WONKY_ERROR_C WONKY_ERROR_C
+ #include <gcc_error.h>
+
+
+ /*
+ %T - type
+ %D - denoted
+ %t - token
+ */
+ struct Translation_Message* get_translation_message(const char *message_format,struct Translation_Data *translation_data,char *filename,size_t line,size_t column,va_list args)
+ {
+
+ size_t i;
+ const char *where_in_return_message=message_format;
+ const char *hold_return_string;
+ const char *hold_return_substring;
+
+ struct Translation_Message *ret;
+
+ hold_return_string=get_translation_message_location_prefix(filename,line,column);
+
+
+ for(i=0;i<1000 && message_format[i]!='\0';++i)
+ {
+ if(message_format[i]=='%')
+ {
+ switch(message_format[i+1])
+ {
+ case 't':
+ hold_return_substring=get_string_for_token_error(va_arg(args,struct token*),translation_data);
+ break;
+ case 'T':
+ hold_return_substring=get_string_for_type_error(va_arg(args,struct Type*),translation_data);
+ break;
+ case 'D':
+ hold_return_substring=get_string_for_denoted_error(va_arg(args,struct Denoted*),translation_data);
+ break;
+ default:
+ continue; /*goes to top for loop*/
+ }
+
+ hold_return_substring=gstr_append_and_consume(
+ gstr_dup(where_in_return_message,message_format+i,i+1),
+ hold_return_substring);
+ hold_return_string=gstr_append_and_consume(hold_return_string,hold_return_substring);
+
+ where_in_return_message=message_format+i+2;
+ ++i;
+
+ }
+ }
+
+ hold_return_string=gstr_append_and_consume(
+ hold_return_string,
+ gstr_dup(where_in_return_message,message_format+i,i+1)
+ );
+
+ ret=malloc(sizeof(struct Translation_Message));
+ ret->message=hold_return_string;
+ ret->line=line;
+ ret->column=column;
+ ret->filename=filename;
+
+ return ret;
+ }
+
+ void push_translation_message_inner(const char *prefix,const char *message_format,struct Translation_Data *translation_data,va_list args)
+ {
+ struct Translation_Message *hold_message;
+ char *filename=NULL;
+ size_t line=0;
+ size_t row=0;
+
+ if(translation_data->tokens->size>0)
+ {
+ struct token *hold_token;
+ hold_token=translation_data->tokens->first->data;
+ filename=(char*)hold_token->filename;
+ line=hold_token->line;
+ row=hold_token->column;
+ }
+
+ hold_message=get_translation_message(message_format,translation_data,filename,line,row,args);
+ hold_message->message=gstr_append_and_consume(gstr_to_heap(prefix),hold_message->message);
+ Queue_Push(translation_data->errors,hold_message);
+ }
+ void push_translation_error(const char *message_format,struct Translation_Data *translation_data, ...)
+ {
+ va_list args;
+ va_start(args,translation_data);
+ push_translation_message_inner("[Error] ",message_format,translation_data,args);
+ va_end(args);
+ }
+ void push_translation_note(const char *note_message,struct Translation_Data *translation_data, ...)
+ {
+ va_list args;
+ va_start(args,translation_data);
+ push_translation_message_inner("[Note] ",note_message,translation_data,args);
+ va_end(args);
+ }
+ void push_lexing_error(const char *error_message,struct Source_File *src,struct Translation_Data *translation_data, ...)
+ {
+ wonky_assert(SHOULD_NOT_REACH_HERE);
+ }
+ void push_lexing_note(const char *error_message,struct Source_File *src,struct Translation_Data *translation_data, ...)
+ {
+
+ wonky_assert(SHOULD_NOT_REACH_HERE);
+ }
+ void push_raw_translation_error(const char *error_message,size_t line,size_t column,const char *filename,struct Translation_Data *translation_data)
+ {
+ struct Translation_Message *hold_message;
+ hold_message=malloc(sizeof(struct Translation_Message));
+ hold_message->message=gstr_to_heap(error_message);
+ hold_message->filename=filename;
+ hold_message->line=line;
+ hold_message->column=column;
+
+ Queue_Push(translation_data->errors,hold_message);
+
+ }
+ void push_compile_error(const char *message,struct Compile_Data *compile_data)
+ {
+ Queue_Push(compile_data->errors,gstr_to_heap(message));
+ }
+ void push_compile_note(const char *message,struct Compile_Data *compile_data)
+ {
+ Queue_Push(compile_data->errors,gstr_to_heap(message));
+ }
+ char* get_string_for_type_error(struct Type *type,struct Translation_Data *translation_data)
+ {
+ char *ret;
+ struct Type *current;
+
+ ret=gstr_to_heap("");
+
+ current=type;
+
+ while(type_is_derivative(current))
+ {
+ switch(current->specifier)
+ {
+
+ case TS_POINTER:
+ ret=gstr_append_and_consume(gstr_to_heap("*"),ret);
+ current=((struct Type_Pointer*)current)->points_to;
+ break;
+ case TS_ARRAY:
+ ret=gstr_append_and_consume(gstr_to_heap("("),ret);
+ ret=gstr_append_and_consume(ret,gstr_to_heap(")[]"));
+ current=((struct Type_Array*)current)->is_array_of;
+ break;
+ case TS_FUNC: /*TODO*/
+ goto hack;
+ default:
+ wonky_assert(SHOULD_NOT_REACH_HERE);
+ }
+ }
+ hack:
+ switch(current->specifier)
+ {
+ case TS_DOUBLE:
+ ret=gstr_append_and_consume(gstr_to_heap("double"),ret);
+ break;
+ case TS_FLOAT:
+ ret=gstr_append_and_consume(gstr_to_heap("float"),ret);
+ break;
+ case TS_INT:
+ ret=gstr_append_and_consume(gstr_to_heap("int"),ret);
+ break;
+ case TS_CHAR:
+ ret=gstr_append_and_consume(gstr_to_heap("char"),ret);
+ break;
+ case TS_STRUCT:
+ ret=gstr_append_and_consume(gstr_to_heap("struct "),ret);
+ goto hack2;
+ case TS_UNION:
+ ret=gstr_append_and_consume(gstr_to_heap("struct "),ret);
+ hack2:
+ {
+ struct token *id;
+ id=((struct Type_Struct_Union*)current)->struct_union->id;
+
+ ret=gstr_append_and_consume(ret,gstr_dup(id->data,id->data+id->data_size,id->data_size+1));
+ }
+ break;
+ default:
+ ret=gstr_append_and_consume(gstr_to_heap("type"),ret);
+ }
+ return ret;
+ }
+ char* get_string_for_denoted_error(struct Denoted *denoted,struct Translation_Data *translation_data)
+ {
+ char *ret;
+
+ ret=gstr_to_heap("denoted");
+
+ return ret;
+ }
+ char* get_string_for_token_error(struct token *token,struct Translation_Data *translation_data)
+ {
+ char *ret;
+
+ ret=gstr_dup(token->data,token->data+token->data_size,token->data_size+1);
+
+ return ret;
+ }
+ char* get_translation_message_location_prefix(char *filename,size_t line,size_t column)
+ {
+ char *ret;
+ size_t filename_length;
+
+ if(filename!=NULL)
+ filename_length=gstrlen(filename);
+ else
+ filename_length=sizeof("NULL")+100;
+
+ ret=calloc(filename_length+64,1);
+
+ sprintf(ret,"%s %zu:%zu ",filename,line,column);
+ return ret;
+ }
+
+ void print_translation_error(FILE *out,struct Translation_Message *error)
+ {
+ fprintf(out,"%s\n",error->message);
+ }
+ void delete_translation_error(struct Translation_Message *translation_error)
+ {
+ free(translation_error);
+ }
+ void print_compile_errors(FILE *out,struct Queue *errors)
+ {
+ while(errors->size>0)
+ fputs(Queue_Pop(errors),out);
+ }
+ #endif
F diff --git a/src/environment/error/gcc_error.h b/src/environment/error/gcc_error.h
new file mode 100644
--- /dev/null
+++ b/src/environment/error/gcc_error.h
+ #ifndef WONKY_ERROR_H
+ #define WONKY_ERROR_H WONKY_ERROR_H
+ #include <gcc_error.hh>
+ #include <lexer.h>
+ #include <stdio.h>
+ #include <stdarg.h>
+ #include <queue.h>
+ #include <gcc_string.h>
+ #include <common.h>
+ #include <compile.h>
+
+
+ struct Translation_Message
+ {
+ const char *message;
+ size_t line,column;
+ const char *filename;
+ };
+
+
+ /*
+ %T print type - takes pointer to Type
+ %D denoted - takes pointer to Denoted
+ %t token - takes pointer to a token
+ */
+ struct Translation_Message* get_translation_message(const char *message_format,struct Translation_Data *translation_data,char *filename,size_t line,size_t column,va_list args);
+
+
+ void push_translation_message_inner(const char *prefix,const char *message_format,struct Translation_Data *translation_data,va_list args);
+ void push_translation_error(const char *message_format,struct Translation_Data *translation_data, ...);
+ void push_translation_note(const char *note_message,struct Translation_Data *translation_data, ...);
+
+ void push_lexing_error(const char *error_message,struct Source_File *src,struct Translation_Data *translation_data, ...);
+ void push_lexing_note(const char *error_message,struct Source_File *src,struct Translation_Data *translation_data, ...);
+
+ void push_raw_translation_error(const char *error_message,size_t line,size_t column,const char *filename,struct Translation_Data *translation_data);
+
+
+ void push_compile_error(const char *message,struct Compile_Data *compile_data);
+ void push_compile_note(const char *message,struct Compile_Data *compile_data);
+
+ char* get_string_for_type_error(struct Type *type,struct Translation_Data *translation_data);
+ char* get_string_for_denoted_error(struct Denoted *denoted,struct Translation_Data *translation_data);
+ char* get_string_for_token_error(struct token *token,struct Translation_Data *translation_data);
+ char* get_translation_message_location_prefix(char *filename,size_t line,size_t column);
+
+ void print_translation_error(FILE *out,struct Translation_Message *message);
+ void delete_translation_error(struct Translation_Message *message);
+
+
+ void print_compile_errors(FILE *out,struct Queue *errors);
+
+
+
+ /*
+
+ =====================================================================================================================
+ push_translation_error("Redeclaration of identifier %t",idptr);
+ push_translation_note("First declared here %L as %T",denoted->id->filename,denoted->id->line,denoted->type);
+
+ |
+ V
+
+ [Error] file line:column - Redeclaration of identifier a
+ [Note] file line:column - First declared as Type
+ =====================================================================================================================
+ push_translation_error("Usage of undeclared identifier %t at %L",idptr,idptr);
+
+ |
+ V
+
+ [Error] file line:column - Usage of undeclared identifier a at file:line
+ =====================================================================================================================
+ push_translation_error("Addition between incompatible types %T and %T",...);
+
+ |
+ V
+
+ [Error] file line:column - Addition between incomptatible types int and struct kek
+ =====================================================================================================================
+ */
+ #endif
F diff --git a/src/environment/error/gcc_error.hh b/src/environment/error/gcc_error.hh
new file mode 100644
--- /dev/null
+++ b/src/environment/error/gcc_error.hh
+ #ifndef WONKY_ERROR_H
+ #define WONKY_ERROR_H WONKY_ERROR_H
+
+
+ struct Translation_Error;
+ struct Output_Message;
+
+
+ #endif
F diff --git a/src/program/gcc_arguments.c b/src/program/gcc_arguments.c
deleted file mode 100644
--- a/src/program/gcc_arguments.c
+++ /dev/null
- #ifndef WONKY_ARGUMENTS_C
- #define WONKY_ARGUMENTS_C WONKY_ARGUMENTS_C
- #include <gcc_arguments.h>
-
-
-
- struct Command_Arguments* parse_command_arguments(char **argv)
- {
- struct Command_Arguments *ret;
- struct Queue *source_names;
-
- ret=malloc(sizeof(struct Command_Arguments));
- ret->print_ast=ret->print_tokens=ret->transpile_to_js=ret->is_quiet=ret->compile_to_intel_asm=0;
- ret->output_file=ret->javascript_extern_file=NULL;
-
- source_names=malloc(sizeof(struct Queue));
- Queue_Init(source_names);
-
- ret->error_message=NULL;
-
- /*we skip the first element(the program name)*/
- for(++argv;*argv;++argv)
- {
- if(gstr_cmp(*argv,"--print-tokens"))
- {
- ret->print_tokens=1;
- }else if(gstr_cmp(*argv,"--print-ast"))
- {
- ret->print_ast=1;
- }else if(gstr_cmp(*argv,"--quiet") || gstr_cmp(*argv,"-q"))
- {
- ret->is_quiet=1;
- if(ret->print_ast || ret->print_tokens)
- {
- ret->error_message="print and quiet conflict. Aborting";
- break;
- }
- }else if(gstr_cmp(*argv,"--transpile_to_js") || gstr_cmp(*argv,"-js"))
- {
- ret->transpile_to_js=1;
- }else if(gstr_cmp(*argv,"--compile-asm") || gstr_cmp(*argv,"-asm"))
- {
- ret->compile_to_intel_asm=1;
- }else if(gstr_cmp(*argv,"-o"))
- {
- ++argv;
- if(*argv==NULL)
- {
- ret->error_message="expected a filename after -o. Aborting";
- break;
- }else
- {
- ret->output_file=fopen(*argv,"w");
- if(ret->output_file==NULL)
- {
- ret->error_message="Couldn't open file for output. Aborting";
- break;
- }
- }
- }else if(gstr_cmp(*argv,"--make-extern-file"))
- {
- ret->javascript_extern_file=fopen(*argv,"w");
- if(ret->javascript_extern_file==NULL)
- {
- ret->error_message="Couldn't open file for extern dump. Aborting";
- break;
- }
- }else if(gstr_cmp(*argv,"--add-html"))
- {
- ret->insert_html=1;
- }else
- {
- Queue_Push(source_names,*argv);
- }
- }
-
- ret->source_names=malloc((source_names->size+1)*sizeof(char*) );
- ret->source_names[source_names->size]=NULL;
- while(source_names->size)
- {
- ret->source_names[source_names->size-1]=(char*)source_names->first->data;
- Queue_Pop(source_names);
- }
- free(source_names);
- if(ret->transpile_to_js && ret->output_file==NULL)
- {
- ret->output_file=fopen("a.js","w");
- if(ret==NULL)
- ret->error_message="Couldn't open file for output. Aborting";
- }
- return ret;
- }
-
-
- void delete_command_arguments(struct Command_Arguments *args)
- {
- if(args->output_file!=NULL)
- fclose(args->output_file);
- if(args->javascript_extern_file!=NULL)
- fclose(args->javascript_extern_file);
-
- free(args->source_names);
- free(args);
- }
-
- #endif
F diff --git a/src/program/gcc_arguments.h b/src/program/gcc_arguments.h
deleted file mode 100644
--- a/src/program/gcc_arguments.h
+++ /dev/null
- #ifndef WONKY_ARGUMENTS_H
- #define WONKY_ARGUMENTS_H WONKY_ARGUMENTS_H
- #include <gcc_arguments.hh>
- #include <queue.h>
- #include <gcc_string.h>
- #include <stdio.h>
- #include <common.h>
-
-
- struct Command_Arguments
- {
- char **source_names;
- char print_tokens:1;
- char print_ast:1;
- char is_quiet:1;
- char transpile_to_js:1;
- char insert_html:1;
- char compile_to_intel_asm:1;
-
-
- FILE* output_file;
- FILE* javascript_extern_file;
-
-
- char *error_message;
- };
-
- struct Command_Arguments* parse_command_arguments(char **argv);
- void delete_command_arguments(struct Command_Arguments *args);
-
- #endif
F diff --git a/src/program/gcc_arguments.hh b/src/program/gcc_arguments.hh
deleted file mode 100644
--- a/src/program/gcc_arguments.hh
+++ /dev/null
- #ifndef WONKY_ARGUMENTS_HH
- #define WONKY_ARGUMENTS_HH WONKY_ARGUMENTS_HH
-
-
- struct Command_Arguments;
-
-
- #endif
F diff --git a/src/program/gcc_error.c b/src/program/gcc_error.c
deleted file mode 100644
--- a/src/program/gcc_error.c
+++ /dev/null
- #ifndef WONKY_ERROR_C
- #define WONKY_ERROR_C WONKY_ERROR_C
- #include <gcc_error.h>
-
-
- /*
- %T - type
- %D - denoted
- %t - token
- */
- struct Translation_Message* get_translation_message(const char *message_format,struct Translation_Data *translation_data,char *filename,size_t line,size_t column,va_list args)
- {
-
- size_t i;
- const char *where_in_return_message=message_format;
- const char *hold_return_string;
- const char *hold_return_substring;
-
- struct Translation_Message *ret;
-
- hold_return_string=get_translation_message_location_prefix(filename,line,column);
-
-
- for(i=0;i<1000 && message_format[i]!='\0';++i)
- {
- if(message_format[i]=='%')
- {
- switch(message_format[i+1])
- {
- case 't':
- hold_return_substring=get_string_for_token_error(va_arg(args,struct token*),translation_data);
- break;
- case 'T':
- hold_return_substring=get_string_for_type_error(va_arg(args,struct Type*),translation_data);
- break;
- case 'D':
- hold_return_substring=get_string_for_denoted_error(va_arg(args,struct Denoted*),translation_data);
- break;
- default:
- continue; /*goes to top for loop*/
- }
-
- hold_return_substring=gstr_append_and_consume(
- gstr_dup(where_in_return_message,message_format+i,i+1),
- hold_return_substring);
- hold_return_string=gstr_append_and_consume(hold_return_string,hold_return_substring);
-
- where_in_return_message=message_format+i+2;
- ++i;
-
- }
- }
-
- hold_return_string=gstr_append_and_consume(
- hold_return_string,
- gstr_dup(where_in_return_message,message_format+i,i+1)
- );
-
- ret=malloc(sizeof(struct Translation_Message));
- ret->message=hold_return_string;
- ret->line=line;
- ret->column=column;
- ret->filename=filename;
-
- return ret;
- }
-
- void push_translation_message_inner(const char *prefix,const char *message_format,struct Translation_Data *translation_data,va_list args)
- {
- struct Translation_Message *hold_message;
- char *filename=NULL;
- size_t line=0;
- size_t row=0;
-
- if(translation_data->tokens->size>0)
- {
- struct token *hold_token;
- hold_token=translation_data->tokens->first->data;
- filename=(char*)hold_token->filename;
- line=hold_token->line;
- row=hold_token->column;
- }
-
- hold_message=get_translation_message(message_format,translation_data,filename,line,row,args);
- hold_message->message=gstr_append_and_consume(gstr_to_heap(prefix),hold_message->message);
- Queue_Push(translation_data->errors,hold_message);
- }
- void push_translation_error(const char *message_format,struct Translation_Data *translation_data, ...)
- {
- va_list args;
- va_start(args,translation_data);
- push_translation_message_inner("[Error] ",message_format,translation_data,args);
- va_end(args);
- }
- void push_translation_note(const char *note_message,struct Translation_Data *translation_data, ...)
- {
- va_list args;
- va_start(args,translation_data);
- push_translation_message_inner("[Note] ",note_message,translation_data,args);
- va_end(args);
- }
- void push_lexing_error(const char *error_message,struct Source_File *src,struct Translation_Data *translation_data, ...)
- {
- wonky_assert(SHOULD_NOT_REACH_HERE);
- }
- void push_lexing_note(const char *error_message,struct Source_File *src,struct Translation_Data *translation_data, ...)
- {
-
- wonky_assert(SHOULD_NOT_REACH_HERE);
- }
- void push_raw_translation_error(const char *error_message,size_t line,size_t column,const char *filename,struct Translation_Data *translation_data)
- {
- struct Translation_Message *hold_message;
- hold_message=malloc(sizeof(struct Translation_Message));
- hold_message->message=gstr_to_heap(error_message);
- hold_message->filename=filename;
- hold_message->line=line;
- hold_message->column=column;
-
- Queue_Push(translation_data->errors,hold_message);
-
- }
- void push_compile_error(const char *message,struct Compile_Data *compile_data)
- {
- Queue_Push(compile_data->errors,gstr_to_heap(message));
- }
- void push_compile_note(const char *message,struct Compile_Data *compile_data)
- {
- Queue_Push(compile_data->errors,gstr_to_heap(message));
- }
- char* get_string_for_type_error(struct Type *type,struct Translation_Data *translation_data)
- {
- char *ret;
- struct Type *current;
-
- ret=gstr_to_heap("");
-
- current=type;
-
- while(type_is_derivative(current))
- {
- switch(current->specifier)
- {
-
- case TS_POINTER:
- ret=gstr_append_and_consume(gstr_to_heap("*"),ret);
- current=((struct Type_Pointer*)current)->points_to;
- break;
- case TS_ARRAY:
- ret=gstr_append_and_consume(gstr_to_heap("("),ret);
- ret=gstr_append_and_consume(ret,gstr_to_heap(")[]"));
- current=((struct Type_Array*)current)->is_array_of;
- break;
- case TS_FUNC: /*TODO*/
- goto hack;
- default:
- wonky_assert(SHOULD_NOT_REACH_HERE);
- }
- }
- hack:
- switch(current->specifier)
- {
- case TS_DOUBLE:
- ret=gstr_append_and_consume(gstr_to_heap("double"),ret);
- break;
- case TS_FLOAT:
- ret=gstr_append_and_consume(gstr_to_heap("float"),ret);
- break;
- case TS_INT:
- ret=gstr_append_and_consume(gstr_to_heap("int"),ret);
- break;
- case TS_CHAR:
- ret=gstr_append_and_consume(gstr_to_heap("char"),ret);
- break;
- case TS_STRUCT:
- ret=gstr_append_and_consume(gstr_to_heap("struct "),ret);
- goto hack2;
- case TS_UNION:
- ret=gstr_append_and_consume(gstr_to_heap("struct "),ret);
- hack2:
- {
- struct token *id;
- id=((struct Type_Struct_Union*)current)->struct_union->id;
-
- ret=gstr_append_and_consume(ret,gstr_dup(id->data,id->data+id->data_size,id->data_size+1));
- }
- break;
- default:
- ret=gstr_append_and_consume(gstr_to_heap("type"),ret);
- }
- return ret;
- }
- char* get_string_for_denoted_error(struct Denoted *denoted,struct Translation_Data *translation_data)
- {
- char *ret;
-
- ret=gstr_to_heap("denoted");
-
- return ret;
- }
- char* get_string_for_token_error(struct token *token,struct Translation_Data *translation_data)
- {
- char *ret;
-
- ret=gstr_dup(token->data,token->data+token->data_size,token->data_size+1);
-
- return ret;
- }
- char* get_translation_message_location_prefix(char *filename,size_t line,size_t column)
- {
- char *ret;
- size_t filename_length;
-
- if(filename!=NULL)
- filename_length=gstrlen(filename);
- else
- filename_length=sizeof("NULL")+100;
-
- ret=calloc(filename_length+64,1);
-
- sprintf(ret,"%s %zu:%zu ",filename,line,column);
- return ret;
- }
-
- void print_translation_error(FILE *out,struct Translation_Message *error)
- {
- fprintf(out,"%s\n",error->message);
- }
- void delete_translation_error(struct Translation_Message *translation_error)
- {
- free(translation_error);
- }
- void print_compile_errors(FILE *out,struct Queue *errors)
- {
- while(errors->size>0)
- fputs(Queue_Pop(errors),out);
- }
- #endif
F diff --git a/src/program/gcc_error.h b/src/program/gcc_error.h
deleted file mode 100644
--- a/src/program/gcc_error.h
+++ /dev/null
- #ifndef WONKY_ERROR_H
- #define WONKY_ERROR_H WONKY_ERROR_H
- #include <gcc_error.hh>
- #include <lexer.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include <queue.h>
- #include <gcc_string.h>
- #include <common.h>
- #include <compile.h>
-
-
- struct Translation_Message
- {
- const char *message;
- size_t line,column;
- const char *filename;
- };
-
-
- /*
- %T print type - takes pointer to Type
- %D denoted - takes pointer to Denoted
- %t token - takes pointer to a token
- */
- struct Translation_Message* get_translation_message(const char *message_format,struct Translation_Data *translation_data,char *filename,size_t line,size_t column,va_list args);
-
-
- void push_translation_message_inner(const char *prefix,const char *message_format,struct Translation_Data *translation_data,va_list args);
- void push_translation_error(const char *message_format,struct Translation_Data *translation_data, ...);
- void push_translation_note(const char *note_message,struct Translation_Data *translation_data, ...);
-
- void push_lexing_error(const char *error_message,struct Source_File *src,struct Translation_Data *translation_data, ...);
- void push_lexing_note(const char *error_message,struct Source_File *src,struct Translation_Data *translation_data, ...);
-
- void push_raw_translation_error(const char *error_message,size_t line,size_t column,const char *filename,struct Translation_Data *translation_data);
-
-
- void push_compile_error(const char *message,struct Compile_Data *compile_data);
- void push_compile_note(const char *message,struct Compile_Data *compile_data);
-
- char* get_string_for_type_error(struct Type *type,struct Translation_Data *translation_data);
- char* get_string_for_denoted_error(struct Denoted *denoted,struct Translation_Data *translation_data);
- char* get_string_for_token_error(struct token *token,struct Translation_Data *translation_data);
- char* get_translation_message_location_prefix(char *filename,size_t line,size_t column);
-
- void print_translation_error(FILE *out,struct Translation_Message *message);
- void delete_translation_error(struct Translation_Message *message);
-
-
- void print_compile_errors(FILE *out,struct Queue *errors);
-
-
-
- /*
-
- =====================================================================================================================
- push_translation_error("Redeclaration of identifier %t",idptr);
- push_translation_note("First declared here %L as %T",denoted->id->filename,denoted->id->line,denoted->type);
-
- |
- V
-
- [Error] file line:column - Redeclaration of identifier a
- [Note] file line:column - First declared as Type
- =====================================================================================================================
- push_translation_error("Usage of undeclared identifier %t at %L",idptr,idptr);
-
- |
- V
-
- [Error] file line:column - Usage of undeclared identifier a at file:line
- =====================================================================================================================
- push_translation_error("Addition between incompatible types %T and %T",...);
-
- |
- V
-
- [Error] file line:column - Addition between incomptatible types int and struct kek
- =====================================================================================================================
- */
- #endif
F diff --git a/src/program/gcc_error.hh b/src/program/gcc_error.hh
deleted file mode 100644
--- a/src/program/gcc_error.hh
+++ /dev/null
- #ifndef WONKY_ERROR_H
- #define WONKY_ERROR_H WONKY_ERROR_H
-
-
- struct Translation_Error;
- struct Output_Message;
-
-
- #endif
F diff --git a/src/program/program.c b/src/program/program.c
deleted file mode 100644
--- a/src/program/program.c
+++ /dev/null
- #ifndef WONKY_PROGRAM_C
- #define WONKY_PROGRAM_C WONKY_PROGRAM_C
- #/*Don't mind me*/include/*When I grow up I want to be a new line*/ <program.h>
-
-
- struct Program* get_program()
- {
- struct Program *ret;
- ret=malloc(sizeof(struct Program));
- ret->translation_units=malloc(sizeof(struct Queue));
- ret->source_files=malloc(sizeof(struct Queue));
- ret->errors=malloc(sizeof(struct Queue));
- ret->types=malloc(sizeof(struct Map));
- ret->external_linkage=get_linkage();
-
- Queue_Init(ret->translation_units);
- Queue_Init(ret->source_files);
- Queue_Init(ret->errors);
-
-
-
- Map_Init(ret->types);
-
- return ret;
- }
- struct Source_File* extract_source_file(FILE *in,struct Source_Name *name)
- {
- long file_size;
- struct Source_File *src;
-
-
- if(fseek(in,0,SEEK_END)==-1)
- return NULL;
- if((file_size=ftell(in))==-1)
- return NULL;
- if(fseek(in,0,SEEK_SET)==-1)
- return NULL;
-
- src=malloc(sizeof(struct Source_File));
-
- src->src_name=name;
-
- src->src=malloc(file_size+1);
- src->src_size=file_size;
-
- src->where_in_src=0;
-
- src->which_column=0;
- src->which_row=0;
- src->is_in_the_begining_of_line=1;
-
- src->src[file_size]='\0';
-
- fread(src->src,1,file_size,in);
- fclose(in);
- return src;
- }
- struct Translation_Data* get_translation_data(struct Map *types,struct Linkage *internal_linkage,struct Linkage *external_linkage)
- {
- struct Translation_Data *ret;
- ret=malloc(sizeof(struct Translation_Data));
- ret->tokens=malloc(sizeof(struct Queue));
- ret->errors=malloc(sizeof(struct Queue));
- ret->source_files=malloc(sizeof(struct Queue));
- Queue_Init(ret->tokens);
- Queue_Init(ret->errors);
- Queue_Init(ret->source_files);
-
- ret->macros=malloc(sizeof(struct Map));
- Map_Init(ret->macros);
-
- ret->types=types;
-
- ret->number_of_errors_when_last_checked=0;
-
- ret->external_linkage=external_linkage;
- ret->internal_linkage=internal_linkage;
-
- return ret;
- }
- struct Source_Name* get_source_name(char *filename,char *base)
- {
- struct Source_Name *ret;
- ret=malloc(sizeof(struct Source_Name));
- ret->base=gstrcpy(base);
- ret->filename=gstrcpy(filename);
- normalise_source_name(ret);
- return ret;
- }
- /*where_to_search ends in a NULL pointer*/
- struct Source_File* get_source_file(char *filename,char **where_to_search)
- {
- FILE *in;
- char *temp_name;
- char is_directory=0;
- struct Source_Name *name;
- struct Source_File *file;
-
- wonky_assert(where_to_search!=NULL);
- wonky_assert(*where_to_search!=NULL);
- do
- {
- temp_name=gstr_append(*where_to_search,filename);
- in=fopen(temp_name,"r");
- free(temp_name);
- if(in==NULL)
- continue;
-
- name=get_source_name(filename,*where_to_search);
- file=extract_source_file(in,name);
- if(file!=NULL)
- {
- return file;
- }else
- {
- delete_source_name(name);
- }
- }while(*(++where_to_search));
- return NULL;
- }
-
- /*this might cause compatability issues TODO*/
- void normalise_source_name(struct Source_Name *name)
- {
- size_t offset;
- size_t i;
- size_t last_slash;
- char *hold_base;
-
- for(last_slash=offset=0;name->filename[offset];++offset)
- {
- if(name->filename[offset]=='/')
- {
- last_slash=offset;
- }
- }
-
- if(last_slash==0)
- return;
-
- if(name->base==NULL)
- {
- offset=0;
- name->base=malloc(last_slash+1);
- name->base[last_slash]='\0';
- name->base[last_slash-1]='/';
-
- }else
- {
- offset=gstrlen((char*)name->base);
- hold_base=malloc(offset+last_slash+2);
- strmv(hold_base,(char*)name->base);
-
- hold_base[last_slash+offset]='/';
- hold_base[last_slash+offset+1]='\0';
- free((void*)name->base);
-
- name->base=hold_base;
- }
-
- for(i=0;i<last_slash;++i)
- name->base[offset+i]=name->filename[i];
-
-
- ++i;
- /*prune the filename*/
- offset=gstrlen(name->filename+i);
- hold_base=malloc(offset+1);
- strmv(hold_base,name->filename+i);
- free(name->filename);
- name->filename=hold_base;
-
-
- }
-
- struct Program* parse_program(char **base_source_names)
- {
- struct Source_File *base_file;
- struct Program *program;
- struct Translation_Data *hold_translation_data;
- char *this_directory[]={"./","",NULL};
-
- wonky_assert(base_source_names!=NULL);
-
- if(*base_source_names==NULL)
- {
- return NULL;
- }
-
- program=get_program();
- hold_translation_data=get_translation_data(program->types,get_linkage(),program->external_linkage);
- do
- {
- base_file=get_source_file(*base_source_names,this_directory);
- if(base_file==NULL)
- {
- /*TODO error*/
- free(base_file);
- continue;
- }else
- {
- Queue_Push(hold_translation_data->source_files,base_file);
- lex(base_file,hold_translation_data);
- if(!has_new_errors(hold_translation_data))
- {
- Queue_Push(program->translation_units,parse_translation_unit(hold_translation_data));
- }else
- {
- flush_tokens(hold_translation_data->tokens);
- }
- assimilate_translation_data(program,hold_translation_data);
- }
- }while(*(++base_source_names));
-
- delete_translation_data(hold_translation_data);
- return program;
- }
-
- void lex_program(struct Translation_Data *hold,struct Source_File *file)
- {
- Queue_Push(hold->source_files,file);
- lex(file,hold);
- }
-
-
- _Bool has_new_errors(struct Translation_Data *translation_data)
- {
- if(translation_data->errors->size != translation_data->number_of_errors_when_last_checked)
- {
- translation_data->number_of_errors_when_last_checked=translation_data->errors->size;
- return 1;
- }else
- {
- return 0;
- }
- }
-
- void delete_program(struct Program *program)
- {
- while(program->translation_units->size>0)
- delete_ast(Queue_Pop(program->translation_units));
- free(program->translation_units);
-
-
-
- while(program->source_files->size>0)
- delete_source_file(Queue_Pop(program->source_files));
- free(program->source_files);
-
-
- while(program->errors->size>0)
- delete_translation_error(Queue_Pop(program->errors));
- free(program->errors);
-
-
- delete_linkage(program->external_linkage);
-
- /*BEWARE*/
- Map_Map(program->types,delete_type);
- Map_Destroy(program->types);
- free(program->types);
-
- free(program);
-
- }
- void delete_translation_data(struct Translation_Data *translation_data)
- {
- wonky_assert(translation_data->tokens->size==0 &&
- translation_data->errors->size==0 &&
- translation_data->source_files->size==0);
- free(translation_data->tokens);
- free(translation_data->errors);
- free(translation_data->source_files);
-
- Map_Map(translation_data->macros,delete_macro);
- Map_Destroy(translation_data->macros);
- free(translation_data->macros);
-
- free(translation_data);
-
- }
- void assimilate_translation_data(struct Program *program,struct Translation_Data *translation_data)
- {
- Queue_Append(program->errors,translation_data->errors);
- Queue_Append(program->source_files,translation_data->source_files);
-
- flush_tokens(translation_data->tokens);
-
- Queue_Init(translation_data->errors);
- Queue_Init(translation_data->source_files);
-
- translation_data->number_of_errors_when_last_checked=0;
-
-
- }
- _Bool has_no_tokens(struct Translation_Data *translation_data)
- {
- return (translation_data->tokens->size)==0;
- }
- #endif
F diff --git a/src/program/program.h b/src/program/program.h
deleted file mode 100644
--- a/src/program/program.h
+++ /dev/null
- #ifndef WONKY_PROGRAM_H
- #define WONKY_PROGRAM_H WONKY_PROGRAM_H
-
-
- #include <program.hh>
- #include <queue.h>
- #include <scope.h>
- #include <lexer.h>
- #include <gcc_string.h>
- #include <gcc_arguments.h>
- #include <parse_translation_unit.h>
- #include <common.h>
- #include <ast.h>
-
-
- struct Program
- {
- struct Queue *translation_units;
- struct Queue *source_files;
- struct Queue *errors;
-
- /*
- the type node structures from
- all the translation units are stored here
- */
- struct Map *types;
-
- struct Linkage *external_linkage;
- };
- struct Translation_Data
- {
- struct Queue *tokens;
-
-
- struct Queue *errors;
- size_t number_of_errors_when_last_checked;
-
-
- struct Queue *source_files;
-
- struct Map *macros;
-
- /*passed from program struct*/
- struct Map *types;
- struct Linkage *external_linkage;
- struct Linkage *internal_linkage;
- /*end of passed from program struct*/
- };
-
- struct Program* get_program();
- struct Source_Name* get_source_name(char *filename,char *base);
-
- struct Source_File* extract_source_file(FILE *in,struct Source_Name *name);
- struct Source_File* get_source_file(char *filename,char **where_to_search);
- void normalise_source_name(struct Source_Name *name);
-
- struct Translation_Data* get_translation_data(struct Map *types,struct Linkage *internal_linkage,struct Linkage *external_linkage);
-
-
- struct Program* parse_program(char **base_source_names);
- void lex_program(struct Translation_Data *hold,struct Source_File *file);
- void entype_program(struct Program *program);
-
-
- _Bool has_new_errors(struct Translation_Data *translation_data);
- _Bool has_no_tokens(struct Translation_Data *translation_data);
-
- void delete_program(struct Program *program);
- void delete_translation_data(struct Translation_Data *translation_data);
- void destroy_translation_data(struct Translation_Data *translation_data);
- void assimilate_translation_data(struct Program *program,struct Translation_Data *translation_data);
-
- #endif
F diff --git a/src/program/program.hh b/src/program/program.hh
deleted file mode 100644
--- a/src/program/program.hh
+++ /dev/null
- #ifndef WONKY_PROGRAM_HH
- #define WONKY_PROGRAM_HH WONKY_PROGRAM_HH
-
- struct Program;
- struct Translation_Data;
-
-
- #endif
F diff --git a/src/semantics/program/program.c b/src/semantics/program/program.c
new file mode 100644
--- /dev/null
+++ b/src/semantics/program/program.c
+ #ifndef WONKY_PROGRAM_C
+ #define WONKY_PROGRAM_C WONKY_PROGRAM_C
+ #/*Don't mind me*/include/*When I grow up I want to be a new line*/ <program.h>
+
+
+ struct Program* get_program()
+ {
+ struct Program *ret;
+ ret=malloc(sizeof(struct Program));
+ ret->translation_units=malloc(sizeof(struct Queue));
+ ret->source_files=malloc(sizeof(struct Queue));
+ ret->errors=malloc(sizeof(struct Queue));
+ ret->types=malloc(sizeof(struct Map));
+ ret->external_linkage=get_linkage();
+
+ Queue_Init(ret->translation_units);
+ Queue_Init(ret->source_files);
+ Queue_Init(ret->errors);
+
+
+
+ Map_Init(ret->types);
+
+ return ret;
+ }
+ struct Source_File* extract_source_file(FILE *in,struct Source_Name *name)
+ {
+ long file_size;
+ struct Source_File *src;
+
+
+ if(fseek(in,0,SEEK_END)==-1)
+ return NULL;
+ if((file_size=ftell(in))==-1)
+ return NULL;
+ if(fseek(in,0,SEEK_SET)==-1)
+ return NULL;
+
+ src=malloc(sizeof(struct Source_File));
+
+ src->src_name=name;
+
+ src->src=malloc(file_size+1);
+ src->src_size=file_size;
+
+ src->where_in_src=0;
+
+ src->which_column=0;
+ src->which_row=0;
+ src->is_in_the_begining_of_line=1;
+
+ src->src[file_size]='\0';
+
+ fread(src->src,1,file_size,in);
+ fclose(in);
+ return src;
+ }
+ struct Translation_Data* get_translation_data(struct Map *types,struct Linkage *internal_linkage,struct Linkage *external_linkage)
+ {
+ struct Translation_Data *ret;
+ ret=malloc(sizeof(struct Translation_Data));
+ ret->tokens=malloc(sizeof(struct Queue));
+ ret->errors=malloc(sizeof(struct Queue));
+ ret->source_files=malloc(sizeof(struct Queue));
+ Queue_Init(ret->tokens);
+ Queue_Init(ret->errors);
+ Queue_Init(ret->source_files);
+
+ ret->macros=malloc(sizeof(struct Map));
+ Map_Init(ret->macros);
+
+ ret->types=types;
+
+ ret->number_of_errors_when_last_checked=0;
+
+ ret->external_linkage=external_linkage;
+ ret->internal_linkage=internal_linkage;
+
+ return ret;
+ }
+ struct Source_Name* get_source_name(char *filename,char *base)
+ {
+ struct Source_Name *ret;
+ ret=malloc(sizeof(struct Source_Name));
+ ret->base=gstrcpy(base);
+ ret->filename=gstrcpy(filename);
+ normalise_source_name(ret);
+ return ret;
+ }
+ /*where_to_search ends in a NULL pointer*/
+ struct Source_File* get_source_file(char *filename,char **where_to_search)
+ {
+ FILE *in;
+ char *temp_name;
+ char is_directory=0;
+ struct Source_Name *name;
+ struct Source_File *file;
+
+ wonky_assert(where_to_search!=NULL);
+ wonky_assert(*where_to_search!=NULL);
+ do
+ {
+ temp_name=gstr_append(*where_to_search,filename);
+ in=fopen(temp_name,"r");
+ free(temp_name);
+ if(in==NULL)
+ continue;
+
+ name=get_source_name(filename,*where_to_search);
+ file=extract_source_file(in,name);
+ if(file!=NULL)
+ {
+ return file;
+ }else
+ {
+ delete_source_name(name);
+ }
+ }while(*(++where_to_search));
+ return NULL;
+ }
+
+ /*this might cause compatability issues TODO*/
+ void normalise_source_name(struct Source_Name *name)
+ {
+ size_t offset;
+ size_t i;
+ size_t last_slash;
+ char *hold_base;
+
+ for(last_slash=offset=0;name->filename[offset];++offset)
+ {
+ if(name->filename[offset]=='/')
+ {
+ last_slash=offset;
+ }
+ }
+
+ if(last_slash==0)
+ return;
+
+ if(name->base==NULL)
+ {
+ offset=0;
+ name->base=malloc(last_slash+1);
+ name->base[last_slash]='\0';
+ name->base[last_slash-1]='/';
+
+ }else
+ {
+ offset=gstrlen((char*)name->base);
+ hold_base=malloc(offset+last_slash+2);
+ strmv(hold_base,(char*)name->base);
+
+ hold_base[last_slash+offset]='/';
+ hold_base[last_slash+offset+1]='\0';
+ free((void*)name->base);
+
+ name->base=hold_base;
+ }
+
+ for(i=0;i<last_slash;++i)
+ name->base[offset+i]=name->filename[i];
+
+
+ ++i;
+ /*prune the filename*/
+ offset=gstrlen(name->filename+i);
+ hold_base=malloc(offset+1);
+ strmv(hold_base,name->filename+i);
+ free(name->filename);
+ name->filename=hold_base;
+
+
+ }
+
+ struct Program* parse_program(char **base_source_names)
+ {
+ struct Source_File *base_file;
+ struct Program *program;
+ struct Translation_Data *hold_translation_data;
+ char *this_directory[]={"./","",NULL};
+
+ wonky_assert(base_source_names!=NULL);
+
+ if(*base_source_names==NULL)
+ {
+ return NULL;
+ }
+
+ program=get_program();
+ hold_translation_data=get_translation_data(program->types,get_linkage(),program->external_linkage);
+ do
+ {
+ base_file=get_source_file(*base_source_names,this_directory);
+ if(base_file==NULL)
+ {
+ /*TODO error*/
+ free(base_file);
+ continue;
+ }else
+ {
+ Queue_Push(hold_translation_data->source_files,base_file);
+ lex(base_file,hold_translation_data);
+ if(!has_new_errors(hold_translation_data))
+ {
+ Queue_Push(program->translation_units,parse_translation_unit(hold_translation_data));
+ }else
+ {
+ flush_tokens(hold_translation_data->tokens);
+ }
+ assimilate_translation_data(program,hold_translation_data);
+ }
+ }while(*(++base_source_names));
+
+ delete_translation_data(hold_translation_data);
+ return program;
+ }
+
+ void lex_program(struct Translation_Data *hold,struct Source_File *file)
+ {
+ Queue_Push(hold->source_files,file);
+ lex(file,hold);
+ }
+
+
+ _Bool has_new_errors(struct Translation_Data *translation_data)
+ {
+ if(translation_data->errors->size != translation_data->number_of_errors_when_last_checked)
+ {
+ translation_data->number_of_errors_when_last_checked=translation_data->errors->size;
+ return 1;
+ }else
+ {
+ return 0;
+ }
+ }
+
+ void delete_program(struct Program *program)
+ {
+ while(program->translation_units->size>0)
+ delete_ast(Queue_Pop(program->translation_units));
+ free(program->translation_units);
+
+
+
+ while(program->source_files->size>0)
+ delete_source_file(Queue_Pop(program->source_files));
+ free(program->source_files);
+
+
+ while(program->errors->size>0)
+ delete_translation_error(Queue_Pop(program->errors));
+ free(program->errors);
+
+
+ delete_linkage(program->external_linkage);
+
+ /*BEWARE*/
+ Map_Map(program->types,delete_type);
+ Map_Destroy(program->types);
+ free(program->types);
+
+ free(program);
+
+ }
+ void delete_translation_data(struct Translation_Data *translation_data)
+ {
+ wonky_assert(translation_data->tokens->size==0 &&
+ translation_data->errors->size==0 &&
+ translation_data->source_files->size==0);
+ free(translation_data->tokens);
+ free(translation_data->errors);
+ free(translation_data->source_files);
+
+ Map_Map(translation_data->macros,delete_macro);
+ Map_Destroy(translation_data->macros);
+ free(translation_data->macros);
+
+ free(translation_data);
+
+ }
+ void assimilate_translation_data(struct Program *program,struct Translation_Data *translation_data)
+ {
+ Queue_Append(program->errors,translation_data->errors);
+ Queue_Append(program->source_files,translation_data->source_files);
+
+ flush_tokens(translation_data->tokens);
+
+ Queue_Init(translation_data->errors);
+ Queue_Init(translation_data->source_files);
+
+ translation_data->number_of_errors_when_last_checked=0;
+
+
+ }
+ _Bool has_no_tokens(struct Translation_Data *translation_data)
+ {
+ return (translation_data->tokens->size)==0;
+ }
+ #endif
F diff --git a/src/semantics/program/program.h b/src/semantics/program/program.h
new file mode 100644
--- /dev/null
+++ b/src/semantics/program/program.h
+ #ifndef WONKY_PROGRAM_H
+ #define WONKY_PROGRAM_H WONKY_PROGRAM_H
+
+
+ #include <program.hh>
+ #include <queue.h>
+ #include <scope.h>
+ #include <lexer.h>
+ #include <gcc_string.h>
+ #include <gcc_arguments.h>
+ #include <parse_translation_unit.h>
+ #include <common.h>
+ #include <ast.h>
+
+
+ struct Program
+ {
+ struct Queue *translation_units;
+ struct Queue *source_files;
+ struct Queue *errors;
+
+ /*
+ the type node structures from
+ all the translation units are stored here
+ */
+ struct Map *types;
+
+ struct Linkage *external_linkage;
+ };
+ struct Translation_Data
+ {
+ struct Queue *tokens;
+
+
+ struct Queue *errors;
+ size_t number_of_errors_when_last_checked;
+
+
+ struct Queue *source_files;
+
+ struct Map *macros;
+
+ /*passed from program struct*/
+ struct Map *types;
+ struct Linkage *external_linkage;
+ struct Linkage *internal_linkage;
+ /*end of passed from program struct*/
+ };
+
+ struct Program* get_program();
+ struct Source_Name* get_source_name(char *filename,char *base);
+
+ struct Source_File* extract_source_file(FILE *in,struct Source_Name *name);
+ struct Source_File* get_source_file(char *filename,char **where_to_search);
+ void normalise_source_name(struct Source_Name *name);
+
+ struct Translation_Data* get_translation_data(struct Map *types,struct Linkage *internal_linkage,struct Linkage *external_linkage);
+
+
+ struct Program* parse_program(char **base_source_names);
+ void lex_program(struct Translation_Data *hold,struct Source_File *file);
+ void entype_program(struct Program *program);
+
+
+ _Bool has_new_errors(struct Translation_Data *translation_data);
+ _Bool has_no_tokens(struct Translation_Data *translation_data);
+
+ void delete_program(struct Program *program);
+ void delete_translation_data(struct Translation_Data *translation_data);
+ void destroy_translation_data(struct Translation_Data *translation_data);
+ void assimilate_translation_data(struct Program *program,struct Translation_Data *translation_data);
+
+ #endif
F diff --git a/src/semantics/program/program.hh b/src/semantics/program/program.hh
new file mode 100644
--- /dev/null
+++ b/src/semantics/program/program.hh
+ #ifndef WONKY_PROGRAM_HH
+ #define WONKY_PROGRAM_HH WONKY_PROGRAM_HH
+
+ struct Program;
+ struct Translation_Data;
+
+
+ #endif