NAME

SPVM - Static Perl Virtual Machine. Fast calcuration & 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';

# New int array
my $sp_nums = SPVM::new_int_array([3, 6, 8, 9]);

# Call subroutine
my $total = MyMath->sum($sp_nums);

print $total . "\n";

DESCRIPTION

SPVM is Static Perl Virtual Machine. Provide fast calcuration & 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

  • Dynamic linking, Subroutine precompile, AOT compile(create exe file)

  • Native API(C level api), C99 standard

DOCUMENT

Standard Functions

print, warn, time

SPVM::CORE - Standard Functions

Standard Modules

SPVM::Byte, SPVM::Short, SPVM::Int, SPVM::Long, SPVM::Float, SPVM::Double, SPVM::Bool

Exchange API

SPVM::Document::ExchangeAPI - Exchange API is perl functions to exchange Perl data to SPVM data, and reverse.

Native API

SPVM::Document::NativeAPI - Native API is C level functions to manipulate SPVM data.

Extension

SPVM::Document::Extension - Extension is the way to C/C++ Binding to SPVM

Language Specification

SPVM::Document::Language - SPVM Language Specification

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

# New int array
my $sp_nums = SPVM::new_int_array([3, 6, 8, 9]);

# Call subroutine
my $total = MyMath->sum($sp_nums);

print $total . "\n";

See also SPVM::Document::ExchangeAPI.

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

Number Literal

Int Literal

Int Literal is composed of

[+|-][0x][0123456789abcdefABCDEF]...[L|f|d]

For example:

123
-123
0xff
0xFF
123L
123d

Default Number Literal Type is int.

# Type is int
123

You can use hex number literal by start 0x.

a, b, c, d, e, f, A, B, C, D, E, F is used as hex number.

0xAF
0xaf

You can use octal number literal by start 0.

0x177
0x777

You can use binary number literal by start 0b.

0b101
0b001

You can use under line _ in number literal. Under line is meanless, only for visuality.

123_456
0xAB_CD

You can use type specifier to specify integer leteral type.

  • L

    # Long
    123L
  • f

    # Float
    123f
  • d

    # Double
    123d

Floating Point Literal

If you use . in number literal, the number is floating point literal. Default type of floating point value is double.

1.23
-1.23

You can use E or e to specify exponential notation.

1.23E+12
1.23E-12
1.23e+12
1.23e-12

You can use type specifier to specify integer leteral type.

  • f

    # Float
    1.23f
  • d

    # Double
    1.23d

If you know more Type, see "Type" section.

String length

my $string_length = length "abc";

String Literal

String Literal is the following.

"abc"

Type of String literal is const byte[].

my $string : const byte[] = "abc";

string is short name of const byte[]. You can also write the following.

my $string : string = "abc";

If you use type inference, you can also write the follwoing.

my $string = "abc";

Escape Sequences

A character preceded by a backslash (\) is an escape sequence and has special meaning to the compiler. The following table shows the SPVM escape sequences:

[Escape Sequences]    [Escape Sequence	Description]
\t                    Insert a tab in the text at this point.
\b                    Insert a backspace in the text at this point.
\n                   	Insert a newline in the text at this point.
\r                    Insert a carriage return in the text at this point.
\f                    Insert a formfeed in the text at this point.
\'                    Insert a single quote character in the text at this point.
\"                    Insert a double quote character in the text at this point.
\\                    Insert a backslash character in the text at this point.

Undefined Literal

Undefined Literal is:

undef

Type

Numeric Type

Numeric types are byte, short, int, long, float, double.

[Type]  [Type Description]   [Type Bit Size]
byte    Integral type        8-bit
short   Integral type        16-bit
int     Integral type        32-bit
long    Integral type        64-bit
float   floating-point type  32-bit
double  floating-point type  64-bit

Numeric values do not share state with other numeric values.

The numeric types are the integral types and the floating-point types.

The integral types are byte, short, int, and long, whose values are 8-bit, 16-bit, 32-bit and 64-bit signed two's-complement integers.

The floating-point types are float, whose values include the 32-bit IEEE 754 floating-point numbers, and double, whose values include the 64-bit IEEE 754 floating-point numbers.

The values of the integral types are integers in the following ranges:

For byte, from -128 to 127, inclusive

For short, from -32768 to 32767, inclusive

For int, from -2147483648 to 2147483647, inclusive

For long, from -9223372036854775808 to 9223372036854775807, inclusive

Varialbe Definition

Varialbe Definition with Type is the following.

my $value : byte;
my $value : short;
my $value : int;
my $value : long;
my $value : float;
my $value : double;

If you know more Variable Declaration, see "Variable Declaration" section.

Array Type

Array Type describe multiple values.

[Type]         [Type Description]
byte[]         byte array
short[]        short array
int[]          int array array
long[]         long array
float[]        float array
doube[]        double array
PackageName[]  object array

Array Type is a Object Type. You can create Array by new keyword.

my $values : int[] = new int[3];

If you know more Array Creating, see "New Array" section.

Multiple Dimention Array Type

Multiple Dimention Array Type is a Array Type.

Two Dimension Array Type

byte[][];
short[][];
int[][];
long[][];
float[][];
double[][];
PackageName[][];

Three Dimension Array Type

byte[][][];
short[][][];
int[][][];
long[][][];
float[][][];
double[][][];
PackageName[][][];

Max Dimension is 255.

You can create Multiple Dimension Array by new keyword.

my $values : int[][] = new int[][3];

This mean that Multiple Dimension Array is created, the multiple dimension array have 3 int[] type array. The elements is initialized by undef.

If you know Multiple Dimension Array Creating, see "New Multiple Dimention Array".

Package Type

If Package is defined, Package name is used as Type.

PackageName

If you know more Package Definition, see "Package Definition" section.

You can create Object by new subroutine. This is Default Constructor.

my $obj : PackageName = PackageName->new;

New Array

Array is created by new. Elements values is not initialized.

my $values = new byte[3];
my $values = new short[3];
my $values = new int[3];
my $values = new long[3];
my $values = new float[3];
my $values = new double[3];

Array Initialization

Array Initialization Syntax:

my $values = new int[] {1, 2, 3};
my $points = new Point[] {Point->new(), Point->new(), Point->new()};

Array Manipulation

Get Array Length

You can use the three ways to get Array Length.

@$values;
@{$values};
len $values;

Get and Set Array Element

Get Array Element:

# Get
$values->[0];

Set Array Element:

# Set
$values->[0] = 5;

Object Manipulation

Field Access

Get field:

# Get field
$object->{foo};

Set field:

# Set field;
$object->{foo} = 5;

Field value is private. You can only use Field Access from self package.

Condition branch

if (1) {

}
elsif (2) {

}
else {

}

Loop Syntax

for statement

my $values = new int[10];
for (my $i = 0; $i < @$values; $i++) {
  $values->[$i] = 0;
}

while statement

my $values = new int[10];
my $i = 0;
while ($i < @$values) {
  $values->[$i] = 0;
}

Comment

Comment:

# Comment

POD

Pod syntax:

=pod
  AAAA
  BBBB
=cut

__END__

Script Ending:

__END__

Exception

Throw Exception

Throw Exception:

croak "Error";

Catch Exception

Catch Exception:

eval {
  croak "Error";
};

Exception Message

if (my $error = $@) {
  
}

Exception message is assigned to $@.

Constructor

new operator

Constructor is new operator.

new Point;

new operator is private. new operator is only used in same package.

Constructor

If new subroutine is not defined, Default Constructor is defined automatically.

sub new ($class : class) { return new Point }

This is used from other package.

my $point = Point->new();

Destructor

Destructor.

package Foo {

  sub DESTROY : void ($self : Foo) {
    
  }
}

Enumeration

package Foo {
  enum {
    ONE,
    TWO,
    THREE
  }
  
  enum {
    FORE = 4,
    FIVE,
  }
}

Enumeration default value is 0. and up to 1, 2, 3 if value is not specified.

Weak Reference

weaken $foo->{bar};
weaken $foo->[0];

Extension native function

package TestCase::Extension {
  native sub sum : int ($num1 : int, $num2 : int);
}

Operators

Assign Operator

my $foo = 1;

Special Assign Operator

+=
-=
*=
/=
&=
|=
^=
%=
<<=
>>=
>>>=

Basic Operator

+
-
*
/
%

Comparison Operator

==
!=
>
<
<=
>=

Logical Operator

&&
||
!

Bit Operator

<<
>>
>>>
&
|
^
~

Increment/Decrement Operator

++
--

C Extension using SPVM

SPVM Module:

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

C Source File;

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

int32_t SPVM_NATIVE_MyMathNative__sum(SPVM_ENV* env, SPVM_VALUE* stack) {
  
  // First argument
  void* sp_nums = stack[0].oval;
  
  // Array length
  int32_t length = env->get_array_length(env, sp_nums);
  
  // Elements pointer
  int32_t* nums = env->get_int_array_elements(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 Extension 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";

See also SPVM::Document::Extension, SPVM::Document::NativeAPI.

NOTE

SPVM is before 1.0 under development! I will change implementation and specification without warnings.

SUPPORT

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

SPVM(GitHub).

AUTHOR

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

CORE DEVELOPER

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

CONTRIBUTERS

akinomyoga, NAGAYASU Shinya, Reini Urban, chromatic, Kazutake Hiramatsu

COPYRIGHT & LICENSE

MIT License

Copyright (c) [2018] [Yuki Kimoto]

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.