Skip to content

Tutorial

Yuki Kimoto edited this page Feb 23, 2024 · 11 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);

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