package SPVM::Builder::ScriptInfo; use strict; use warnings; use Carp 'confess'; use JSON::PP; use File::Basename 'basename'; use SPVM::Builder; use SPVM::Builder::CC; use SPVM::Builder::Util; # Fields sub builder { my $self = shift; if (@_) { $self->{builder} = $_[0]; return $self; } else { return $self->{builder}; } } sub class_name { my $self = shift; if (@_) { $self->{class_name} = $_[0]; return $self; } else { return $self->{class_name}; } } sub script_name { my $self = shift; if (@_) { $self->{script_name} = $_[0]; return $self; } else { return $self->{script_name}; } } sub compiler { my $self = shift; if (@_) { $self->{compiler} = $_[0]; return $self; } else { return $self->{compiler}; } } sub runtime { my $self = shift; if (@_) { $self->{runtime} = $_[0]; return $self; } else { return $self->{runtime}; } } # Class Methods sub new { my $class = shift; my $self = bless {@_}, $class; my $class_name = $self->{class_name}; my $script_name = $self->{script_name}; unless (defined $script_name || defined $class_name) { confess("The \"script_name\" option or the \"class_name\" option must be defined."); } # New SPVM::Builder object my $builder = SPVM::Builder->new; $self->{builder} = $builder; my $compiler = SPVM::Builder::Native::Compiler->new; $compiler->add_include_dir($_) for @{$builder->include_dirs}; $self->{compiler} = $compiler; $self->compile; return $self; } # Instance Methods sub compile { my ($self) = @_; # Builder my $builder = $self->builder; my $class_name = $self->{class_name}; my $script_name = $self->{script_name}; my $source; if (defined $script_name) { open my $fh, '<', $script_name or confess "Can't open file \"$script_name\":$!"; $source = do { undef $/; <$fh> }; } my $compiler = $self->compiler; $compiler->set_start_file(__FILE__); $compiler->set_start_line(__LINE__ + 1); my $anon_class_name; eval { $class_name ? $compiler->compile($class_name) : $compiler->compile_anon_class($source) }; if ($@) { my $error_messages = $compiler->get_error_messages; for my $error_message (@$error_messages) { print STDERR "$error_message\n"; } exit(255); } my $runtime = $compiler->get_runtime; $self->runtime($runtime); } sub get_class_names { my ($self) = @_; my $runtime = $self->runtime; my $category = [ 4, # SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_MULNUM 6, # SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_CLASS 7, # SPVM_NATIVE_C_BASIC_TYPE_CATEGORY_INTERFACE ]; my $basic_types = [grep { $_->get_name !~ /::anon_class::/ && $_->get_name !~ /::anon_method::/ } @{$runtime->get_basic_types({category => $category})}]; my $class_names = [map { $_->get_name } @$basic_types]; return $class_names; } sub has_config_file { my ($self, $class_name) = @_; unless (defined $class_name) { confess("The class name \$class_name must be defined."); } my $config_file = SPVM::Builder::Util::search_config_file($class_name); my $has_config_file = defined $config_file; return $has_config_file; } sub is_resource_loader { my ($self, $class_name) = @_; unless (defined $class_name) { confess("The class name \$class_name must be defined."); } my $config_file = SPVM::Builder::Util::search_config_file($class_name); my $is_resource_loader = 0; if (defined $config_file && -f $config_file) { my $config = SPVM::Builder::Config->load_config($config_file, []); my $resource_names = $config->get_resource_names; if (@$resource_names) { $is_resource_loader = 1; } } return $is_resource_loader; } sub get_config_file { my ($self, $class_name) = @_; unless (defined $class_name) { confess("The class name \$class_name must be defined."); } my $config_file = SPVM::Builder::Util::search_config_file($class_name); unless ($config_file) { confess("The config file for the class \"$class_name\" is not found."); } return $config_file; } sub get_config_content { my ($self, $class_name) = @_; my $config_file = $self->get_config_file($class_name); my $config_content = SPVM::Builder::Util::slurp_binary($config_file); return $config_content; } sub get_config { my ($self, $class_name) = @_; my $config_file = $self->get_config_file($class_name); my $config = SPVM::Builder::Config->load_config($config_file, []); return $config; } 1; =head1 Name SPVM::Builder::ScriptInfo - Script Information =head1 Description The SPVM::Builder::ScriptInfo class has methods to manipulate SPVM script information. =head1 Usage my $config_info = SPVM::Builder::ScriptInfo->new(class_name => "Foo"); =head1 Class Methods =head2 new my $config_info = SPVM::Builder::ScriptInfo->new(%options); Creates an L<SPVM::Builder::ScriptInfo> object given options %options, and returns it. The class specified by C<class_name> option or C<script_name> option is compiled and the runtime is generated. C<class_name> option or C<script_name> option must be defined. Options: =over 2 =item * C<class_name> A class name. =item * C<script_name> A script name. =back Exceptions: The "class_name" option or the "script_name" option must be defined. Otherwise, an exception is thrown. =head1 Instance Methods =head2 get_class_names my $class_names = $config_info->get_class_names; Returns the names of all classes, interfaces, and multi-numeric types except for anon classes and anon classes generated by anon methods. =head2 has_config_file my $has_config_file = $config_info->has_config_file($class_name); If the class given by the class name has a config file, returns 1, otherwise returns 0. Exceptions: The class name $class_name must be defined. Otherwise, an exception is thrown. =head2 is_resource_loader my $is_resource_loader = $config_info->is_resource_loader($class_name); If the class given by the class name $class_name is a class that load resources, returns 1, otherwise returns 0. Exceptions: The class name $class_name must be defined. Otherwise, an exception is thrown. =head2 get_config_file my $config_file = $config_info->get_config_file($class_name); Returns the file path of the config for the class given by the class name $class_name. Exceptions: The class name $class_name must be defined. Otherwise, an exception is thrown. The config file for the class "%s" is not found. Otherwise, an exception is thrown. =head2 get_config_content my $config_content = $config_info->get_config_content($class_name); Returns the content of the config for the class given by the class name $class_name. Exceptions: Exceptions thrown by L</"get_config_file"> method could be thrown. =head2 get_config my $config = $config_info->get_config($class_name); Returns a L<config|SPVM::Builder::Config> object for the class given by the class name $class_name. Exceptions: Exceptions thrown by L</"get_config_file"> method could be thrown. =head1 Copyright & License Copyright (c) 2023 Yuki Kimoto MIT License