-
Notifications
You must be signed in to change notification settings - Fork 14
Tutorial
This tutorial describes how to use the SPVM language for beginners.
SPVM is a CPAN module. SPVM can be installed from CPAN.
cpanm SPVM
or
cpan SPVM
Create a SPVM class. The name is SPVM::MyMath
.
Create the SPVM/MyMath.spvm
file in the lib
directory. The extension of a SPVM class is spvm
.
Write the following code.
# lib/SPVM/MyMath.spvm
class MyMath {
static method sum : int ($nums : int[]) {
my $total = 0;
for (my $i = 0; $i < @$nums; $i++) {
$total += $nums->[$i];
}
return $total;
}
}
The class
keyword defines a class.
# Class Definition
class MyMath {
}
See also Class in SPVM document.
The method
keyword defines a method.
Define a class method using the static
attribute.
class MyMath {
# Class method definition
static method sum : int ($nums : int[]) {
}
}
The sum method returns a value of the int
type. The int
type is signed 32bit integer type.
int
See also Types in SPVM document.
int[]
type in arguments in the sum method is the int array type.
int[]
The my
keyword declares a local variable(a lexical variable in Perl).
my $total : int = 0;
SPVM has type inference, so you can omit types.
my $total = 0;
0 is an integer literal.
my $total = 0;
SPVM has the following literals.
# Integer literal
123
123_456_789
# Floating point literal
1.32
1.32f
# Character literal
'a'
'c'
# String literal
"Hello World!"
See also Lexical Tokenization in SPVM document.
Look at the condition part @$nums
in the for loop.
for (my $i = 0; $i < @$nums; $i++) {
$total += $nums->[$i];
}
@
is the array length operator to get the length of an array.
The incremental operator ++
increments a value by 1.
$i++
The syntax of getting array element gets an element in an array.
$nums->[$i]
See the following code.
$total += $nums->[$i];
This is same as the following the additon operator and the assignment Operator.
$total = $total + $nums->[$i];
See the for statement.
for (my $i = 0; $i < @$nums; $i++) {
$total += $nums->[$i];
}
See also Statements in SPVM document.
See the return statement.
return $total;
Create sum.pl
file and write the following code. This is a Perl program.
use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/lib";
use SPVM 'MyMath';
# Call method
my $total = SPVM::MyMath->sum([3, 6, 8, 9]);
print "Total: $total\n";
# Call method with packed data
my $nums_packed = pack('l*', 3, 6, 8, 9);
my $api = SPVM::api();
my $spvm_nums = $api->new_int_array_from_bin($nums_packed);
my $total_packed = SPVM::MyMath->sum($spvm_nums);
print "Total Packed: $total_packed\n";
The lib
directory is added to library searching pathes using lib
module.
use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/lib";
The use
function given SPVM
and a SPVM class name loads a SPVM class.
use SPVM 'MyMath';
Call a SPVM method.
# Call method
my $total = SPVM::MyMath->sum([3, 6, 8, 9]);
a Perl array reference is converted to a SPVM int array.
See also Exchange API in SPVM document.
The returned SPVM int value is converted to a Perl scalar.
Packed binary data can be passed. The new_int_array_from_bin
method in SPVM exchange APIs creates a SPVM int array from packed binary data.
# Call method with packed data
my $nums_packed = pack('l*', 3, 6, 8, 9);
my $api = SPVM::api();
my $spvm_nums = $api->new_int_array_from_bin($nums_packed);
my $total_packed = SPVM::MyMath->sum($spvm_nums);
ByteList, ShortList, IntList, LongList, FloatList, DoubleList, StringList, List classes are dynamic array classes.
use IntList;
my $nums_list = IntList->new([1, 2, 3]);
$nums_list->push(4);
$nums_list->unshift(0);
my $last = $nums_list->pop;
my $first = $nums_list->shift;
my $length = $nums_list->length;
my $nums = $nums_list->to_array;
Hash class is a associated array class.
my $person = Hash->new;
$person->set(name => "Yuki");
$person->set(age => 30);
$person->set(height => 173.2);
my $person = Hash->new({name => "Yuki", age => 30, height => 173.2});
my $name = (string)$person->get("name");
my $name = $person->get_string("name");
my $age = (int)$person->get("age");
my $age = $person->get_int("age");
my $height = (double)$person->get("height");
my $height = $person->get_double("height");
A method can be compiled to a machine code using the precompile
attribute.
# lib/SPVM/MyMath.spvm
class MyMath {
precompile static method sum : int ($nums : int[]) {
my $total = 0;
for (my $i = 0; $i < @$nums; $i++) {
$total += $nums->[$i];
}
return $total;
}
}
Environment Variable SPVM_BUILD_DIR
must be set for precompiled methods.
# bash example
export SPVM_BUILD_DIR=~/.spvm_build
Create a SPVM native class to call C/C++ functions.
The native
attribute indicates the method is a native method.
Write a SVPM class in lib/SPVM/MyMath.spvm
.
class MyMath {
native static method sum_native : int ($nums : int[]);
}
Write a C source code in lib/SPVM/MyMath.c
.
#include "spvm_native.h"
int32_t SPVM__SPVM__MyMath__sum_native(SPVM_ENV* env, SPVM_VALUE* stack) {
void* sv_nums = stack[0].oval;
int32_t length = env->length(env, stack, sv_nums);
int32_t* nums = env->get_elems_int(env, stack, sv_nums);
int32_t total = 0;
for (int32_t i = 0; i < length; i++) {
total += nums[i];
}
stack[0].ival = total;
return 0;
}
Write a config file in lib/SPVM/MyMath.config
for a native class.
use strict;
use warnings;
use SPVM::Builder::Config;
my $config = SPVM::Builder::Config->new_gnu99(file => __FILE__);
$config;
Call a native method from Perl.
# sum_native.pl
use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/lib";
use SPVM 'MyMath';
# Call native method
my $total_native = SPVM::MyMath->sum_native([3, 6, 8, 9]);
print "Total Native: $total_native\n";
Environment Variable SPVM_BUILD_DIR
must be set for precompiled methods and native methods.
# bash example
export SPVM_BUILD_DIR=~/.spvm_build
SVPM can bind functions of C/C++/CUDA.
At first, see Native Class and Native APIs in SPVM document.
The following example binds C functions to SPVM.
See also the following examples.