Skip to content

Tutorial

Yuki Kimoto edited this page Aug 24, 2024 · 13 revisions

SPVM Tutorial

This tutorial describes how to use the SPVM language for beginners.

Installing SPVM

SPVM is a CPAN module. SPVM can be installed from CPAN.

cpanm SPVM

or

cpan SPVM

Getting Started

Creating SPVM classes

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;
  }
}

Class Definition

The class keyword defines a class.

# Class Definition
class MyMath {

}

See also Class in SPVM document.

Method Definition

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[]) {
    
  }
}

Numeric Types

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.

Array Types

int[] type in arguments in the sum method is the int array type.

int[]

Local Variable Declaration

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;

Integer Literal

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.

Getting Array Length

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.

Increment Operator

The incremental operator ++ increments a value by 1.

$i++

Getting Array Element

The syntax of getting array element gets an element in an array.

$nums->[$i]

Addition Operator

See the following code.

$total += $nums->[$i];

This is same as the following the additon operator and the assignment Operator.

$total = $total + $nums->[$i];

for Statement

See the for statement.

for (my $i = 0; $i < @$nums; $i++) {
  $total += $nums->[$i];
}

See also Statements in SPVM document.

return Statement

See the return statement.

return $total;

Call SPVM Methods from Perl

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";

Adding library pathes

The lib directory is added to library searching pathes using lib module.

use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/lib";

Loading SPVM classes

The use function given SPVM and a SPVM class name loads a SPVM class.

use SPVM 'MyMath';

Call SPVM Methods

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.

Call SPVM Methods with packed data

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);

Data Structures

Dynamic Arrays

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

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");

How To Improve SPVM Performance

Method Precompiling

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

Native Classes

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

How To Bind C/C++/CUDA Libraries to SPVM

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.

Bind C functions to SPVM

See also the following examples.

Documents

Commands

Modules

Examples

Wiki