The Perl and Raku Conference 2025: Greenville, South Carolina - June 27-29 Learn more

use strict;
use Carp 'confess';
use File::Basename 'basename';
# 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