The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

SPVM - Static Perl Virtual Machine. Fast Calculation, Fast Array Operation, and Easy C/C++ Binding.

SYNOPSIS

SPVM Module:

  # lib/MyMath.spvm
  package MyMath {
    sub sum : int ($nums : int[]) {
      
      my $total = 0;
      for (my $i = 0; $i < @$nums; $i++) {
        $total += $nums->[$i];
      }
      
      return $total;
    }
  }

Use SPVM Module from Perl

  use FindBin;
  use lib "$FindBin::Bin/lib";
  
  use SPVM 'MyMath';
  
  # Call subroutine
  my $total = MyMath->sum([3, 6, 8, 9]);

  print "Total: $total\n";
  
  # Call subroutine with packed data
  my $nums_packed = pack('l', 3, 6, 8, 9);
  my $total_packed = MyMath->sum($nums_pack);
  
  print "Total Packed: $total_packed\n";

Precompiled SPVM Subroutine. This means SPVM code is converted to Machine Code:

  # lib/MyMath.spvm
  package MyMath {
    precompile sub sum_precompile : int ($nums : int[]) {
      
      my $total = 0;
      for (my $i = 0; $i < @$nums; $i++) {
        $total += $nums->[$i];
      }
      
      return $total;
    }
  }

SPVM Native Subroutine. This means SPVM subroutine call C/C++ native subroutine:

  # lib/MyMath.spvm
  package MyMath {
    native sub sum_native : int ($nums : int[]); {
  }
  
  // lib/MyMath.c
  #include "spvm_native.h"
  
  int32_t SPNATIVE__MyMath__sum_native(SPVM_ENV* env, SPVM_VALUE* stack) {
    
    void* sv_nums = stack[0].oval;
    
    int32_t length = env->length(sv_nums);
    
    int32_t nums* env->get_elems_int(env, sv_nums);
    
    int32_t total = 0;
    for (int32_t i = 0; i < length; i++) {
      total += nums[i];
    }
    
    stack[0].ival = total;
    
    return SPVM_SUCCESS;
  }

DESCRIPTION

SPVM is Static Perl Virtual Machine. Provide fast calculation & easy C/C++ Binding.

Features:

  • Fast culcuration, Fast array operation, Small memory

  • Perl syntax, Static typing, Switch syntax, Have language specification

  • Enum, Type inference, Anon subroutine, Variable captures

  • Array initialization,

  • Reference count GC, Weaken reference, Module system

  • Exception, Package variable

  • Object oriented, Inteface, Value type, Value array type, Reference type

  • Easy way to C/C++ binding, Automatically Perl binding, C99 math functions

  • Shared Library, Precompile Subroutine into Machine code

  • Native API(C level api), C99 standard

DOCUMENT

Currently some ports of document are use Automatic translation, so not accurate and maybe difficult to read.

CORE MODULES

SPVM Core Modules.

EXAMPLES

How to use SPVM from Perl

SPVM Module:

  # lib/MyMath.spvm
  package MyMath {
    sub sum : int ($nums : int[]) {
      
      my $total = 0;
      for (my $i = 0; $i < @$nums; $i++) {
        $total += $nums->[$i];
      }
      
      return $total;
    }
  }

Use SPVM Module from Perl

  use FindBin;
  use lib "$FindBin::Bin/lib";
  
  use SPVM 'MyMath';
  
  # Call subroutine
  my $total = MyMath->sum([3, 6, 8, 9]);
  
  print $total . "\n";

Package Declaration

Package can contain field declaration, subroutine declaration.

  package Point {
    has x : int;
    has y : int;
    
    sub new : Point ($x : int, $y : int) {
      my $self = new Point;
      
      $self->{x} = $x;
      $self->{y} = $y;
      
      return $self;
    }
    sub clear ($self : self) {
      $self->{x} = 0;
      $self->{y} = 0;
    }
  }

Package can also contain package variable declaration and enumeration declaration and use declaration.

  package Foo {
    use Point;
    
    our $FOO : int;
    our $BAR : int;
    
    enum {
      FLAG1
      FLAG2;
    }
  }

Use Module

  use Point;

Field Declaration

  has x : int;
  has y : long;

Field is public by default.

You can make field private by private keyword.

  has x : private int;

Subroutine Declaration

  sub sub : int ($num1 : int, $num2 : int) {
    return $num1 + $num2;
  }

Variable Declaration

  my $num : int;
  my $nums : int[];

Exmpales:

  # Numeric Type
  my $value : byte;
  my $value : short;
  my $value : int;
  my $value : long;
  my $value : float;
  my $value : double;
  my $obj : Point;
  
  # Array Type
  my $values : byte[];
  my $values : short[];
  my $values : int[];
  my $values : long[];
  my $values : float[];
  my $values : double[];
  my $values : Point[];

  # Multiple Dimension Array Type
  my $values : byte[][];
  my $values : short[][];
  my $values : int[][];
  my $values : long[][];
  my $values : float[][];
  my $values : double[][];
  my $values : Point[][];
  

You can initialize variable.

  my $value : int = 1;

You can omit type name if initial value is exists. This is type inference.

  my $value = 1;

Type Inference

If the Type of right value is known, the type of left value is automatically decided.

  my $num = 2;
  my $obj = new Foo;
  my $values = new int[3];

Above is same as the following.

  my $num : int = 2;
  my $obj : Foo = new Foo;
  my $values : int[3] = new int[3];

C NativeAPI using SPVM

SPVM Module:

  # lib/MyMathNative.spvm
  package MyMathNative {
    
    # Sub Declaration
    native sub sum int ($nums : int[]);
  }

C Source File;

  // lib/MyMathNative.native.c
  #include <spvm_native.h>

  int32_t SPNATIVE__MyMathNative__sum(SPVM_ENV* env, SPVM_VALUE* stack) {
    
    // First argument
    void* sp_nums = stack[0].oval;
    
    // Array length
    int32_t length = env->len(env, sp_nums);
    
    // Elements pointer
    int32_t* nums = env->ielems(env, sp_nums);
    
    // Culcurate total
    int32_t total = 0;
    {
      int32_t i;
      for (i = 0; i < length; i++) {
        total += nums[i];
      }
    }
    
    // Return value is set to stack[0]
    stack[0].ival = total;
    
    // If function success, return SPVM_SUCCESS
    return SPVM_SUCCESS;
  }

Use NativeAPI Module from Perl:

  use FindBin;
  use lib "$FindBin::Bin/lib";
  
  # Use SPVM module
  use SPVM 'MyMathNative';
  
  # New SPVM int array
  my $sp_nums = SPVM::new_int_array([3, 6, 8, 9]);
  
  # Call SPVM subroutine
  my $total = MyMathNative->sum($sp_nums);
  
  print $total . "\n";

ENVIRONMENT VARIABLE

SPVM_BUILD_DIR

SPVM build directory for precompile and native subroutine.

If SPVM_BUILD_DIR environment variable is not set, SPVM can't compile precompile subroutine and native subroutine, and a exception occur. You see error message "SPVM_BUILD_DIR environment variable must be set ...".

In bash, you can set SPVM_BUILD_DIR to the following.

  export SPVM_BUILD_DIR=~/.spvm_build

In bash, you can set SPVM_BUILD_DIR to the following.

  export SPVM_BUILD_DIR=~/.spvm_build

CAUTION

SPVM 1.0 is First Major Release.

But Full backward compatibility is not guaranteed because SPVM is not used much in corporate work yet.

If SPVM has fatal bugs in the specification or implementation, the backward compatibility is broken and the bug will be fixed after discussion.

SUPPORT

If you have problems or find bugs, comment to GitHub Issue.

SPVM(GitHub).

AUTHOR

Yuki Kimoto <kimoto.yuki@gmail.com<gt>

CORE DEVELOPERS

moti<lt>motohiko.ave@gmail.com<gt>

CONTRIBUTERS

  • Mohammad S Anwar

  • akinomyoga

  • NAGAYASU Shinya

  • Reini Urban

  • chromatic

  • Kazutake Hiramatsu

COPYRIGHT & LICENSE

Copyright 2018-2020 Yuki Kimoto, all rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 243:

You forgot a '=back' before '=head1'