Skip to content
Snippets Groups Projects
fml.c 4.31 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include <stdio.h>
    
    #include <string.h>
    #include <stddef.h>
    #include <ctype.h>
    
    michal's avatar
    michal committed
    
    
    #include "arena.h"
    #include "parser.h"
    
    #include "ast_interpreter.h"
    
    #include "bc_interpreter.h"
    
    michal's avatar
    michal committed
    
    
    #define AST_INTERPRETER_COMMAND "ast_interpret"
    
    #define BC_INTERPRETER_COMMAND "bc_interpret"
    
    #define RUN "run"
    
    #define HEAP_SIZE_COMMAND "--heap-size"
    #define HEAP_LOG_COMMAND "--heap-log"
    
    
    #define DEFAULT_HEAP_SIZE 550
    
    
    int main ( int argc, char **argv ) {
    	if ( argc < 2 ) {
    
    		fprintf( stderr, "Input error: expected at least one argument\n" );
    
      size_t heap_size = DEFAULT_HEAP_SIZE;
      char * log_file = NULL;
    
    
      u8 ast_interpreter = 0;
      u8 bc_interpreter = 0;
    
      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;
    
        } 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 ) {
    
    Michal Štěpánek's avatar
    Michal Štěpánek committed
          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 ] );
    
      if ( flag || f <= 0 ) 
    
      FILE * fp = fopen ( argv [ f ], "r" );
    
      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 );
    
        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;
    	  }
    
    Michal Štěpánek's avatar
    Michal Štěpánek committed
        bc = generate_bc ( ast );
    
    	  arena_destroy( &arena );
      }
    
      if ( bc_interpreter ) {
    
          file_str = (Str) { .len = bc . len, .str = bc . str };
    
        VM vm;
        vm_init ( &vm, heap_size * 1024 * 1024 );
    
        vm_destroy ( &vm );
    
      if ( bc_compiler ) {
        if ( ! bc_interpreter )
    
          for ( size_t i = 0; i < bc . len; ++i ) {
    
            printf ( "%c", bc . str [ i ] );
    
    Michal Štěpánek's avatar
    Michal Štěpánek committed
        string_destroy ( & bc );
    
      free ( buffer );