SPVM is developed little by little

SPVM is the language to speed up numerical operation and array operation in Perl.
SPVM is deveoped little by little. I don't know it will be success to embded SPVM to Perl , but I introduce SPVM in this entry.


SPVM-solo

SPVM means Static Perl Virtual Matchine. This is Perlish static typed language.

Today I will introduce the test script. All variables have a static type and automatic type conversion is not done. Variable declaration can be omitted because it has type inference. It is designed to be same as Perl language as possible.

package Main {

  sub main () : int {
    my $num1 = 2;
    my $num2 = 5;
    
    my $num3 = sum($num1, $num2);
    
    std::println_int($num3);
    
    return 0;
  }

  sub sum ($num1 : int, $num2 : int) : int {
    my $num3 = $num1 + $num2;
    
    return $num3;
  }
}

The output result is as follows.

7

Looking at the file "Test.spvm", you can see the functions currently implemented.

use Test::EnumA;
use Test::EnumB;
use Test::EnumC;
use Test::EnumD;
use Test::Simple;
use Test::Minimal;

package Test {
  sub main($mvar : int) : int {
    std::println_int(Test::EnumD->THREE);
    std::println_int(Test::EnumD->FORE);
    
    std::println_int(std::test_call1(4));
    
    # Core functions
    {
      std::print_byte((byte)1);
      std::print_short((short)1);
      std::print_int(1);
      std::print_long(1L);
      std::print_float(1f);
      std::print_double(1.0);
      std::println("end");
    }

    {
      my $nums = malloc int[258];
      my $len = len $nums;
      for (my $i = 0; $i < $len; $i++) {
        $nums[$i] = $i;
      }

      for (my $i = 0; $i < $len; $i++) {
        $nums[$i] = $i;
      }
    }
    
    {
      my $nums = malloc int[2000000];
      my $len = len $nums;
      my $i = 0;
      for ($i = 0; $i < $len; $i = $i + 1) {
        $nums[$i] = $i;
      }
      std::println_int($i);
      std::println_int($nums[$i - 1]);
    }
    
    # Object to get long field is undef
    #{
    #  my $obj : Test::Minimal;
    #  $obj{x} = 1L;
    #}

    # Object to get long field is undef
    #{
    #  my $obj : Test::Minimal;
    #  $obj{x};
    #}

    # Index is out of range
    #{
    #  my $nums = malloc int[3];
    #  $nums[3] = 1;
    #}
    
    # Index is out of range
    #{
    #  my $nums = malloc int[3];
    #  $nums[-1] = 3;
    #}

    # Array is undef
    #{
    #  my $nums : int[];
    #  $nums[0] = 1;
    #}

    # Index is out of range
    #{
    #  my $nums = malloc int[3];
    #  $nums[3];
    #}
    
    # Index is out of range
    #{
    #  my $nums = malloc int[3];
    #  $nums[-1];
    #}
    
    # Array is undef
    #{
    #  my $nums : int[];
    #  $nums[0];
    #}
    
    {
      my $string : string = "abc";
    }
    
    {
      my $strings : string[] = malloc string[5];
      $strings[0] = "abc";
      $strings[1] = "ppp";
      
      std::println($strings[1]);
    }
    
    {
      malloc Test::Minimal;
    }
    
    {
      my $obj1 = malloc Test::Minimal;
      
      my $obj2 : Test::Minimal;
      
      my $obj3 : Test::Minimal = undef;
    }
    
    # Increment byte
    {
      my $num = (byte)1;
      $num++;
      std::println_byte($num);
    }
    
    # Increment short 
    {
      my $num = (short)1;
      $num++;
      std::println_short($num);
    }
    
    # increment int
    {
      my $var = 4;
      $var++;
      $var--;
      --$var;
      ++$var;
    }
    
    # Increment long
    {
      my $var = (long)4;
      $var++;
      $var--;
      --$var;
      ++$var;
    }
    
    try {
      sum0(1, 2);
      
      3;
      
      sum0(3, 4);
      
      1;
    } catch ($error : byte[]) {
      sum0(5, 6);
      2;
    }
    
    {
      my $nums = malloc int[3];
      $nums[0] = 1;
      $nums[1] = 2;
      $nums[2] = 3;
      
      my $total = std::sum_int($nums);
      std::println_int($total);
    }

    {
      my $string = "ace";
      
      std::println($string);
    }
    
    {
      my $num = (byte)3;
      std::println_byte($num);
      
      my $num2 = (long)1 + (long)$num;
      
      std::println_long($num2);
    }
    
    # get and set field
    {
      my $m = malloc Test::Minimal;
      
      $m{x} = 2L;
      $m{y} = 3L;
      
      std::println_long($m{x});
      std::println_long($m{y});
    }

    # Free when assignment
    {
      my $m = malloc Test::Minimal;
      $m = malloc Test::Minimal;
    }

    # left is object, right is undef
    {
      my $obj : Test::Minimal = undef;
    }
    
    if (1) {
      2;
      if (3) {
        4;
      }
      elsif (8) {
        9;
      }
      else {
        5;
      }
    }
    else {
      6;
    }
    7;
    
    std::println_int(sum0(1, 1));
    std::println_int(sum2(1, 2));

    # Constant float
    std::println_float(0.3f);
    std::println_float(1f);
    std::println_float(2f);
    std::println_float(1.2f);
    
    # Constant double
    std::println_double(0d);
    std::println_double(1d);
    std::println_double(1.2);

    # Constant int
    std::println_int(-2147483648);
    std::println_int(-32769);
    std::println_int(-32768);
    std::println_int(-129);
    std::println_int(-128);
    std::println_int(-2);
    std::println_int(-1);
    std::println_int(0);
    std::println_int(1);
    std::println_int(2);
    std::println_int(3);
    std::println_int(4);
    std::println_int(5);
    std::println_int(6);
    std::println_int(127);
    std::println_int(128);
    std::println_int(255);
    std::println_int(256);
    std::println_int(32767);
    std::println_int(32768);
    std::println_int(65535);
    std::println_int(65536);
    std::println_int(2147483647);
    
    # Constant long
    std::println_long(-1L);
    std::println_long(0L);
    std::println_long(1L);
    std::println_long(2L);
    std::println_long(9223372036854775807L);
    std::println_long(-9223372036854775807L);
    std::println_long(-2147483648L);
    std::println_long(-32769L);
    std::println_long(-32768L);
    std::println_long(-129L);
    std::println_long(-128L);
    std::println_long(-2L);
    std::println_long(-1L);
    std::println_long(0L);
    std::println_long(1L);
    std::println_long(2L);
    std::println_long(3L);
    std::println_long(4L);
    std::println_long(5L);
    std::println_long(6L);
    std::println_long(127L);
    std::println_long(128L);
    std::println_long(255L);
    std::println_long(256L);
    std::println_long(32767L);
    std::println_long(32768L);
    std::println_long(65535L);
    std::println_long(65536L);
    std::println_long(2147483647L);
    std::println_long(0xFFL);
    
    "abc";
    
    # Table switch int
    {
      my $num = 3;
      
      switch($num) {
        case Test::EnumD->THREE:
          std::println_int(1);
        case Test::EnumD->FORE:
          std::println_int(2);
        case 5:
          std::println_int(3);
        default:
          std::println_int(5);
      }
    }

    # Lookup switch int
    {
      my $num = 3;
      switch ($num) {
        case 1:
          std::println_int(1);
        case 3:
          std::println_int(2);
        case 10000:
          std::println_int(2);
        default:
          std::println_int(5);
      }
    }
    
    # {
    #   my $num = 5;
    #   switch($num) {
    #     default:
    #       std::println_int(5);
    #   }
    # }
    
    # my $num;
    # my $num1 = undef;
    
    if (1) {
      3;
      if (2) {
        4;
      }
      5;
    }
    6;

    my $simple3 : Test::Simple = malloc Test::Simple;
    
    std::println_int($simple3->get_x());
    $simple3->get_x;
    
    $simple3{y} = 2;
    $simple3{x};
    $simple3{y};

    my $simple2 : Test::Simple = malloc Test::Simple;
    
    if (1) { }
    
    if (1 == 1) {
    
    }

    if (1 != 1) {
    
    }

    if (1 <= 1) {
    
    }

    if (1 < 1) {
    
    }

    if (1 >= 1) {
    
    }

    if (1 > 1) {
    
    }

    if (!1) { }
    
    if (1L) { }
    if (1.5) { }
    if ($simple2) { }
    
    if (undef) {
    
    }
    
    if ($simple2 == undef) {
      
    }

    if (undef == $simple2) {
      
    }
    
    if (undef == undef) {
    
    }
    if (undef != undef) {
    
    }
    
    if (5L || 6L) {
    
    }

    if (5L && 6L) {
    
    }
    if (!1L) {
    
    }
    
    if (1L > 2L) {
      3L;
      4L;
    };
    5L;

    if (1.2 > 2.0) {};
    if (1.2 >= 2.0) {};
    if (1.2 < 2.0) {};
    if (1.2 <= 2.0) {};

    if (1.2 == 1.0) { }
    if (1.2 != 2.0) { };

    if (1 > 2) {};
    if (1 >= 2) {};
    if (1 < 2) {};
    if (1 <= 2) {};

    if (1 == 1) { }
    if (1 != 2) { };

    {
      my $nums = malloc int[3];
      $nums[0] = 13;
      $nums[1] = 14;
      std::println_int($nums[0]);
      std::println_int($nums[1]);
    }
    
    {
      my $nums : long[] = malloc long[3];
      $nums[0] = 11L;
      $nums[1] = 12L;
      std::println_long($nums[0]);
      std::println_long($nums[1]);
      std::println_int(len $nums);
      my $nums_length : int = len $nums;
    }
    
    my $simple : Test::Simple = malloc Test::Simple;
    
    
    my $v1 : int;
    my $v2 : int;
    my $v3 : int;
    
    $v3 = $v2 = $v1 = 5;
    
    100;
    1000;
    1 << 2;
    1 >> 2;
    1 >>> 2;
    
    Test::EnumA::ONE();
    Test::EnumA::TWO();
    
    Test::EnumA->ONE();
    Test::EnumA->ONE;
    
    # Basic operation byte
    {
    
    }
    
    # Basic operation short
    {
    
    }
    
    # Basic operation int
    {
      1 ^ 4;
      1 & 2;
      1 | 2;
      -3 + +2;
      3 - (1 + 2);
      5 + 19;
      1 + 2;
      1 - 2;
      1 * 2;
      1 / 3;
      4 % 6;
    }
    
    # Basic operation long
    {
      1L ^ 4L;
      1L & 2L;
      1L | 2L;
      -3L + +2L;
      3L - (1L + 2L);
      5L + 19L;
      1L + 2L;
      1L - 2L;
      1L * 2L;
      1L / 3L;
      4L % 6L;
    }
    
    1.2 / 3.0;
    1.2f / 3.0f;
    1.2 * 4.0;
    1.2f * 4.0f;
    1.2 + 3.0;
    1.2f + 3.0f;
    1.2 - 3.0;
    1.2f - 3.0f;
    
    # Compare long
    {
      if (1L > 2L) {};
      if (1L >= 2L) {};
      if (1L < 2L) {};
      if (1L <= 2L) {};
      if (1L == 1L) { }
      if (1L != 2L) { };
    }
    
    my $bar : double = (double)1;
    undef;
    
    Test::sum0(1, 2);
    sum0(1, 2);
    
    test1();
    
    while (1) {
      1;
      last;
    }
    
    # for (my $i : int = 0; $i < 5; $i = $i + 1) {
    #   1;
    #   last;
    #   next;
    # }

    {
      my $num0 = (byte)0;
      my $num1 = (byte)1;
      my $num2 = (byte)2;
      my $num3 = $num0 + $num1 + $num2;
      std::println_byte($num3);
    }

    {
      my $num0 = (short)0;
      my $num1 = (short)1;
      my $num2 = (short)2;
      my $num3 = $num0 + $num1 + $num2;
      std::println_short($num3);
    }


    # die "ERROR";
    
    return $mvar + 3;
  }
  
  sub test1 () : int {
    my $num0 = 1;
    my $num1 = 2;
    my $num2 = 3;
    my $num3 = 4;
    my $num4 = 5;
    
    return 0;
  }
  
  sub sum4($num1 : long, $num2 : long) : long {
    return $num1 + $num2;
  }
  
  sub sum3 ($simple : Test::Simple, $foo : long, $bar : float) : int {
    
    if (3) {
    
    }
    
    if (3) {
      1;
    }
    elsif (4) {
      4;
    }
    else {
      
    }

    if (3) {
      1;
    }
    elsif (4) {
      4;
    }
    elsif (5) {
    
    }
    else {
      
    }
    
    if (1) {
      
    }
    else {
      
    }

    return 2;
  }
  
  sub sum1 ($num1 : long, $num2 : long) : long {
    return $num1 + $num2;
  }
  sub sum0($num1 : int, $num2 : int) : int {
    return $num1 + $num2;
  }
  
  sub sum2 ($num1 : int, $num2 : int) : int {
    # die "Error";
    
    my $num3 = sum0($num1, $num2);
    
    return $num3 + 3;
  }

  sub increfcount($test : Test::Minimal, $num : int) : int {
    
    my $aaa = malloc Test::Minimal;
  }

  sub decinctest ($num1 : Test::Minimal, $num2 : int, $num3 : Test::Minimal) : int {
    {
      my $num4 = malloc Test::Minimal;
      my $num5 = malloc Test::Minimal;
    }
    return 2;
  }

  sub return_object() : Test::Minimal {
    my $obj0 = malloc Test::Minimal;
    {
      my $obj1 = malloc Test::Minimal;
      
      my $obj2 : Test::Minimal;
      
      my $obj3 : Test::Minimal = undef;

      return $obj2;
    }
  }

}

Leave a comment

About Yuki Kimoto

user-pic I'm Yuki Kimoto, Japanese Perl programmer.I create Perl modules and applications. GitPrep, SPVM, DBIx::Custom, Validator::Custom, Test::Mojo, Mojolicious::Plugin::AutoRoute, etc.