#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stddef.h> #include <ctype.h> #include "arena.h" #include "parser.h" #include "ast_interpreter.h" #include "bc_interpreter.h" #include "bc_compiler.h" #define AST_INTERPRETER_COMMAND "ast_interpret" #define BC_INTERPRETER_COMMAND "bc_interpret" #define BC_COMPILER_COMMAND "bc_compile" #define RUN "run" #define HEAP_SIZE_COMMAND "--heap-size" #define HEAP_LOG_COMMAND "--heap-log" #define DEFAULT_HEAP_SIZE 100 int main ( int argc, char **argv ) { if ( argc < 2 ) { fprintf( stderr, "Input error: expected at least one argument\n" ); return 1; } size_t heap_size = DEFAULT_HEAP_SIZE; char * log_file = NULL; u8 flag = 0; u8 ast_interpreter = 0; u8 bc_interpreter = 0; u8 bc_compiler = 0; size_t len; int f = -1; for ( int arg = 1; arg < argc; ++arg ) { len = strlen ( argv [ arg ] ); for ( size_t j = 0; j < len; j++ ) argv [ arg ] [ j ] = tolower ( argv [ arg ] [ j ] ); if ( len == strlen ( AST_INTERPRETER_COMMAND ) && strncmp ( argv [ arg ], AST_INTERPRETER_COMMAND, len ) == 0 ) { ast_interpreter = 1; f = ++arg; } else if ( len == strlen ( BC_INTERPRETER_COMMAND ) && strncmp ( argv [ arg ], BC_INTERPRETER_COMMAND, len ) == 0 ) { bc_interpreter = 1; f = ++arg; } else if ( len == strlen ( BC_COMPILER_COMMAND ) && strncmp ( argv [ arg ], BC_COMPILER_COMMAND, len ) == 0 ) { bc_compiler = 1; f = ++arg; } else if ( len == strlen ( RUN ) && strncmp ( argv [ arg ], RUN, len ) == 0 ) { bc_interpreter = 1; bc_compiler = 1; size_t remaining_args = (size_t) argc - arg; for ( size_t opt = 0; opt < ( remaining_args > 2 ? 2 : remaining_args); ++opt ) { len = strlen ( argv [ ++arg ] ); if ( len == strlen ( HEAP_SIZE_COMMAND ) && strncmp ( argv [ arg ], HEAP_SIZE_COMMAND, len ) == 0 ) { heap_size = atoi ( argv [ ++arg ] ); if ( heap_size == 0 ) { fprintf( stderr, "Input error: invalid heap size %s.\n", argv [ arg ] ); flag = 2; } } else if ( len == strlen ( HEAP_LOG_COMMAND ) && strncmp ( argv [ arg ], HEAP_LOG_COMMAND, len ) == 0 ) { log_file = argv [ ++arg ]; } } f = ++arg; } else { fprintf( stderr, "Input error: unknown argument %s.\n", argv [ arg ] ); flag = 1; } } if ( flag || f <= 0 ) return 1; FILE * fp = fopen ( argv [ f ], "r" ); (void) log_file; if ( ! fp ) { fprintf ( stderr, "Input error: file does not exists.\n" ); return 1; } if ( fseek ( fp, 0, SEEK_END ) ) { fprintf ( stderr, "Input error: could not advance to the end of the file.\n" ); return 1; } int file_len = ftell ( fp ); if ( file_len < 0 ) { fprintf ( stderr, "Input error: could not count the size of the file.\n" ); return 1; } size_t flen = file_len; rewind ( fp ); u8 * buffer = malloc ( flen ); if ( fread ( buffer, 1, flen, fp ) != flen ) { fprintf ( stderr, "Input error: could not read to the file.\n" ); return 1; } fclose ( fp ); Str file_str = (Str) { .str = buffer, .len = flen }; if ( ast_interpreter ) { Arena arena; arena_init( &arena ); Ast *ast = parse_src ( &arena, file_str ); if ( ast == NULL ) { fprintf ( stderr, "Failed to parse source\n" ); arena_destroy ( &arena ); return 1; } ASTInterpreterState state; Heap heap; heap_init ( &heap, heap_size * 1024 * 1024, log_file ); state_init ( &state, &heap ); evaluate ( &state, ast ); state_destroy ( &state ); arena_destroy( &arena ); } String bc; if ( bc_compiler ) { Arena arena; arena_init( &arena ); Ast *ast = parse_src ( &arena, file_str ); if ( ast == NULL ) { fprintf ( stderr, "Failed to parse source\n" ); arena_destroy ( &arena ); return 1; } bc = generate_bc ( ast ); arena_destroy( &arena ); } if ( bc_interpreter ) { if ( bc_compiler ) file_str = (Str) { .len = bc . len, .str = bc . str }; VM vm; vm_init ( &vm, heap_size * 1024 * 1024, log_file ); vm_interpret ( &vm, file_str ); vm_destroy ( &vm ); } if ( bc_compiler ) { if ( ! bc_interpreter ) for ( size_t i = 0; i < bc . len; ++i ) { printf ( "%c", bc . str [ i ] ); } string_destroy ( & bc ); } free ( buffer ); return 0; }