# Copyright (c) 2023 Yuki Kimoto
# MIT License

class Native::Compiler : pointer {
  version_from SPVM;

  allow Native;
  
  use Native;
  use Native::Runtime;
  use Native::ClassFile;
  use Error::Compile;
  use Native::MethodCall;
  
  # Fields
  has runtime : Native::Runtime;
  
  # Class Methods
  native static method new : Native::Compiler ();
  
  private static method new_with_pointer : Native::Compiler ($pointer : Address, $options : object[] = undef) {
    
    my $self = new Native::Compiler;
    
    Fn->set_pointer($self, $pointer);
    
    return $self;
  }
  
  # Instance Methods
  native method compile : void ($class_name : string);
  
  native method get_runtime : Native::Runtime ();
  
  native method set_start_file : void ($start_file : string);
  
  native method set_start_line : void ($start_line : int);
  
  native method add_include_dir : void ($include_dir : string);
  
  native method prepend_include_dir : void ($include_dir : string);
  
  native method get_error_messages : string[] ();
  
  native method get_class_file : Native::ClassFile ($class_name : string);
  
  native method compile_anon_class : string ($source : string);
  
  method eval_string : string ($main_source : string) {
    
    unless ($main_source) {
      die "The main source \$main_source must be defined.";
    }
    
    my $source = "
class {
static method main : void () {
#line 1
$main_source
}
}
";
    
    my $anon_class_name = $self->compile_anon_class($source);
    
    Native->check_bootstrap_method($anon_class_name);
    
    Native::MethodCall->call_class_method($anon_class_name, "main");
  }
}