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::Document::Language::Class - Class Definition in the SPVM Language

Description

This document describes class definition in the SPVM language.

Class

A class defines its class type, its class variables, its fields and its methods.

The object can be created from a class using new operator.

Class Definition

The class keyword defines a class. A class has a class block.

  # Class definition
  class CLASS_NAME {
  
  }

The class name must follow the naming rule of the class name.

Examples:

  # Class definition
  class Point {
  
  }

Class attributes are written after :.

  class CLASS_NAME : CLASS_ATTRIBUTE {
  
  }
  
  class CLASS_NAME : CLASS_ATTRIBUTE1 CLASS_ATTRIBUTE2 CLASS_ATTRIBUTE3 {
  
  }

Compilation Errors:

If more than one class is defined in a class file, a compilation error occurs.

Examples:

  # Class attributes
  class Point : public {
  
  }

  class Point : public pointer {
  
  }

Version Declaration

The version keyword declares the version string of a module.

  version VERSION_STRING;

The operand VERSION_STRING is a version string.

A version string is the string type.

It is composed of numbers 0-9, ..

The following checks are performed.

The version string is saved to the version information of the module.

Compilation Errors:

If the version string has already been declared, a compilation error occurs.

A character in a version string must be a number or .. Otherwise a compilation error occurs.

The number of . in a version string must be less than or equal to 1. Otherwise a compilation error occurs.

A version string must begin with a number. Otherwise a compilation error occurs.

A version string must end with a number. Otherwise a compilation error occurs.

The number of . in a version string must be less than or equal to 1. Otherwise a compilation error occurs.

The length of characters after . in a version string must be divisible by 3. Otherwise a compilation error occurs.

A version number must be able to be parsed by the strtod C function. Otherwise a compilation error occurs.

Examples:

  class Foo {
    version "1";
  }
  
  class Foo {
    version "20080903";
  }
  
  class Foo {
    version "1.001";
  }
  
  class Foo {
    version "10.001003";
  }
  

Version String

The version string is the string represented version of a module.

It is declared by the version declaration.

Version Number

The version number is a floating point number created by the following way.

A "Version Declaration" in version string is converted to a floating point number by the strtod C function.

Class Attributes

The list of class attributes.

Class Attributes Descriptions
public This class is public. In other classes, this class can be used as I of new operator.
private This class is private. In other classes, this class cannot be used as I of new operator. This is default.
protected This class is protected. In other classes except for the child classes, this class cannot be used as I of new operator.
interface_t This class is an interface type. The class definition is interpreted as an interface definiton.
mulnum_t This class is a multi-numeric type. The class definition is interpreted as an multi-numeric type definiton.
pointer The class is a pointer class.
precompile Perform precompile to all methods in this class, except for getter methods, setter methods, and enumurations.

Compilation Errors:

Only one of class attributes private, protected or public can be specified. Otherwise a compilation error occurs.

If more than one of interface_t, mulnum_t, and pointer are specified, a compilation error occurs.

Pointer Class

The pointer class is the class that has the class attribute pointer.

  # Pointer Class
  class Foo : pointer {
  
  }

The type of a pointer class is the class type.

An object of a pointer class has the pointer to a native address.

Anon Class

The anon class is the class that do not has its class name.

  class {
  
  }

But internally an anon class has its name, such as eval::anon::0.

An anon class is also defined by the anon method.

A anon class for an anon method has its unique class name corresponding to the class name, the line number and the position of columns the anon class is defined.

A anon class for an anon method has the same access control as its outmost class.

A anon class for an anon method has the same alias names as its outmost class.

Examples:

  # Anon class
  class {
    static method sum : int ($num1 : int, $num2 : int) {
      return $num1 + $num2;
    }
  }
  
  # Anon method
  class Foo::Bar {
    method sum : void () {
      my $anon_method = method : string () {
        
      }
   }
  }
  
  # The name of the anon class
  Foo::Bar::anon::3::23;

Outmost Class

An outmost class is the outmost defined class.

The outmost class is Foo::Bar in the following example.

  class Foo::Bar {
    static method baz : void () {
      my $outmost_class_name = __PACKAGE__;
      
      my $cb = method : void () {
        my $outmost_class_name = __PACKAGE__;
      };
    }
  }

Class File Name

A class must be written in the following class file.

Change :: to /. Add ".spvm" at the end.

  SPVM/Foo.spvm
  SPVM/Foo/Bar.spvm
  SPVM/Foo/Bar/Baz.spvm

use Statement

The use statemenet loads a class.

  use Foo;

Classes are loaded at compile-time.

The use statemenet must be defined directly under the class definition.

  class Foo {
    use Foo;
  }

Compilation Errors:

If the class does not exist, a compilation error occurs.

alias Statement

The alias statemenet creates an alias name for a class name.

  # Create alias
  alias Foo::Bar as FB;

FB is used as Foo::Bar alias in class method calls.

  # This means Foo::Bar->sum(1, 2);
  FB->sum(1, 2);

alias syntax must be defined directly under the class definition.

  class Foo {
    alias Foo::Bar as FB;
  }

You can create an alias at the same time as loading a class by the use statement.

  use Foo::Bar as FB;

require Statement

If the require statement that loads a class only if it exists in the class path, and if it does not exist, the block does not exist.

It was designed to implement a part of features of "#ifdef" in the C language.

  if (require Foo) {
  
  }

if require Statement can be followed by else Statement.

  if (require Foo) {
  
  }
  else {
  
  }

Note that elsif Statement cannot be followed.

Let's look at an example. if Foo does not exist, no a compilation error occurs and it is assumed that there is no if block

Therefore, "$foo = new Foo;" does not result in a compilation error because it is assumed that there is no if block.

In the other hand, the else block exists, so a warning is issued.

  my $foo : object;
  if (require Foo) {
    $foo = new Foo;
  }
  else {
    warn "Warning: Can't load Foo";
  }

allow Statement

Private methods, private fields, and private class variables cannot be accessed except from the current class.

A private class cannot be OPERAND of the new operator except from the current class.

The allow statemenet allows the private access from the other classes.

  allow CLASS_NAME;

The allow statemenet must be defined directory under the class definition.

The class that is OPERAND of the allow statemenet is loaded by the same way as the use statement.

Examples:

  # Allowing private access
  class Foo {
    allow Bar;
  }

interface Statement

The interface statement guarantees the following things.

  interface INTERFACE_NAME;

1. If the class has methods that are definied the the interface, each method must have the Method Compatibility of each interface method in the interface definition.

2. The class must have methods that defined as required interface methods in the the interface.

Compilation Errors:

If not, a compilation error occurs.

Examples:

  class Point {
    interface Stringable;
    
    method to_string : string () {
      my $x = $self->x;
      my $y = $self->y;
      
      my $string = "($x,$y)";
      
      return $string;
    }
  }
  
  my $stringable = (Stringable)Point->new(1, 2);
  my $string = $stringable->to_string;

Inheritance

A class inherits a class using the extends keyword.

  class CLASS_NAME extends PARENT_CLASS_NAME {
    
  }

The parts of the definitions of the fields of the all super classes are copied to the class.

The copied parts of the definitions are the field name, the type, the access controll.

The the definitions of the interfaces of the all super classes are copied to the class.

The copied order is from the beginning of the super class at the top level to the current class.

The class can call instance methods of the super classes. The searching order is from the current class to the super class at the top level.

Compilation Errors:

The parant class must be a class type. Otherwise a compilation error occurs.

The name of the parant class must be different from the name of the class. Otherwise a compilation error occurs.

The all super classes must be different from its own class. Otherwise a compilation error occurs.

The field that name is the same as the field of the super class cannnot be defined. Otherwise a compilation error occurs.

Examples:

  class Point3D extends Point {
    
    has z : rw protected int;
    
    static method new : Point3D ($x : int = 0, $y : int = 0, $z : int = 0) {
      my $self = new Point3D;
      
      $self->{x} = $x;
      $self->{y} = $y;
      $self->{z} = $z;
      
      return $self;
    }
    
    method clear : void () {
      $self->SUPER::clear;
      $self->{z} = 0;
    }
    
    method to_string : string () {
      my $x = $self->x;
      my $y = $self->y;
      my $z = $self->z;
      
      my $string = "($x,$y,$z)";
      
      return $string;
    }
    
    method clone : object () {
      my $self_clone = Point3D->new($self->x, $self->y, $self->z);
      
      return $self_clone;
    }
  }

Interface

The interface syntax is described.

Interface Definition

An interface is defined using a class definition with a "Class Attributes" in class attribute interface_t.

  class Stringable: interface_t {
    required method to_string : string ();
    method foo : int ($num : long);
  }

An interface can have interface methods. An interface method does not need its method block.

An interface can have required interface methods by using the method attribute required.

The type of the interface is the interface type.

An interface can have interface statements.

  class TestCase::Pointable : interface_t {
    interface Stringable;
    
    method x : int ();
    method y : int();
    method to_string : string ();
  }

An interface method can have its method block.

  class Stringable: interface_t {
    method to_string : string ();
    method call_to_string : string () {
      return "foo " . $self->to_string;
    }
  }

This method is only called by the static instance method call.

  $self->Stringable::call_to_string;

Compilation Errors:

An interface cannnot have field definitions. If so, an compilation error occurs.

An interface cannnot have class variable definitions. If so, an compilation error occurs.

Duck Typing

The duck typing is supported.

  class Stringable: interface_t {
    method to_string : string ();
  }

  class Point {
    
    method to_string : string () {
      my $x = $self->x;
      my $y = $self->y;
      
      my $string = "($x,$y)";
      
      return $string;
    }
  }
  
  my $stringable = (Stringable)Point->new(1, 2);
  my $string = $stringable->to_string;

The Point class have no interfaces, but An object of the Point class can be assigned to a Stringable interface because the to_string method in the Point class has the method compatibility of the to_string method in the Strigable interface.

Interface Requirement

(TODO)

This section describes assignment requirements used to check a return type and argument types for interface requirement.

Multi-Numeric Types Definition

A multi-numeric type is defined by the class definition that has the mulnum_t class attribute.

  # Continuous two 64bit floating point
  class Complex_2d : mulnum_t {
    re : double;
    im : double;
  }

The type of a field must be a numeric type.

The types of all fields must be the same types.

The length of the fields must be less than or equal to 255.

The multi-numeric type must end with the following suffix.

  _[FieldsLength][TypeSuffix]

The length of the fields in the suffix must be the same as the length of the fields.

The type suffix in the suffix must correspond to the numeric type that is explained in the multi-numeric type suffix.

See the multi-numeric type field access to get and set the field of the multi-numeric type.

Default Loaded Classes

The following classes are loaded by default. These classes are deeply related to the features of SPVM language itself, such as type conversion.

Enumeration

The enumeration is the syntx to defines constant values of the int type.

Enumeration Definition

The enum keyword defines an enumeration. An enumeration has definitions of constant values.

  # Enumeration Definition
  enum {
    FLAG1,
    FLAG2,
    FLAG3
  }

An enumeration must be defined directly under the class definition.

  class Foo {
    enum {
      FLAG1,
      FLAG2,
      FLAG3
    }
  }

The name given to an enumeration value must be a method name.

The first enumeration value is 0. The next enumeration value is incremented by 1, and this is continued in the same way.

In the above example, FLAG1 is 0, FALG2 is 1, and FLAG3 is 2.

The type of an enumeration value is the int type.

, after the last enumeration value can be allowed.

  enum {
    FLAG1,
    FLAG2,
    FLAG3,
  }

An enumeration value can be set by = explicitly.

  enum {
    FLAG1,
    FLAG2 = 4,
    FLAG3,
  }

In the above example, FLAG1 is 0, FALG2 is 4, and FLAG3 is 5.

An enumeration value is got by the class method call.

  Foo->FLAG1

Compilation Errors:

If an enumeration definition is invalid, a compilation error occurs.

Examples:

  class Foo {
    enum {
      FLAG1,
      FLAG2,
      FLAG3,
    }
  }

Enumeration Attributes

Attributes can be specified to an enumeration definition.

  private enum {
    FLAG1,
    FLAG2 = 4,
    FLAG3,
  }

The list of enumeration attributes:

Attributes Descriptions
private This enumeration is private. Each value of this enumeration can not be accessed from other classes.
protected This enumeration is protected. Each value of this enumeration can not be accessed from other classes except for the child classes.
public This enumeration is public. Each value of this enumeration can be accessed from other classes. This is default setting.

Compilation Errors:

Only one of enumeration attributes private, protected or public can be specified. Otherwise a compilation error occurs.

Class Variable

A class variable is a global variable that has the name space.

Class Variable Definition

our keyword defines a class variable.

  our CLASS_VARIABLE_NAME : TYPE;

A Class variable must be defined directly under the class definition.

The type must be a numeric type or an object type.

Class variable attributes can be specified.

  our CLASS_VARIABLE_NAME : ATTRIBUTE TYPE;
  our CLASS_VARIABLE_NAME : ATTRIBUTE1 ATTRIBUTE2 ATTRIBUTE3 TYPE;

Compilation Errors:

The class variable mame must follow the rule defined in the class variable name, and must not contain ::. Otherwise a compilation error occurs.

If a class name with the same name is defined, a compilation error occurs.

Examples:

  class Foo {
    our $NUM1 : byte;
    our $NUM2 : short;
    our $NUM3 : int;
    our $NUM4 : long;
    our $NUM5 : float;
    our $NUM6 : double;
  
    our $NUM_PUBLIC : public int;
    our $NUM_RO : ro int;
    our $NUM_WO : wo int;
    our $NUM_RW : rw int;
  }

Class Variable Attributes

The list of class variable attributes.

Class Variable Attributes Descriptions
public The class variable is public. The class variable can be accessed from other classes.
private The class variable is private. The class variable cannnot be accessed from other classes. This is default setting.
protected The class variable is protected. The class variable cannnot be accessed from other classes except for the child classes.
ro The class variable has its getter method.
wo The class variable has its setter method.
rw The class variable has its getter method and setter method.

Compilation Errors:

Only one of class variable attributes private, protected or public can be specified. Otherwise a compilation error occurs.

If more than one of ro, wo, and rw are specified, a compilation error occurs

Class Variable Getter Method

A class variable getter method is a method to perform the operation of the getting a class variable.

It has no arguments. The return type is the same as the type of the class variable except that the type of the field is the byte type or the short type.

If the type of the class variable is the byte type or the short type, the return type is the int type.

It is defined by the ro or rw class variable attributes.

It is a method that name is the same as the class variable name removing $. For example, if the class variable name is $FOO, its getter method name is FOO.

Examples:

  # Class variable getter method
  class Foo {
    our $NUM : ro int;
    
    static method main : void {
      my $num = Foo->NUM;
    }
  }

Class Variable Setter Method

A class variable setter method is a method to perform the operation of the setting a class variable.

The return type is the void type.

It has an argument that type is the same as the type of the class variableexcept that the type of the field is the byte type or the short type.

If the type of the class variable is the byte type or the short type, the argument type is the int type.

It is defined by the wo or rw class variable attributes.

It is a method that name is the same as the class variable name removing $ and adding SET_ to the beginning. For example, if the class variable name is $FOO, its setter method name is SET_FOO.

Examples:

  # Class variable setter method
  class Foo {
    our $NUM : wo int;
    
    static method main : void {
      Foo->SET_NUM(3);
    }
  }

Field

Fields are the data that an object has.

Field Definition

The has keyword defines a field.

  # The field definition
  has FIELD_NAME : OPT_ATTRIBUTES TYPE;
  
  # An examples
  has name : string;
  has age : protected int;
  has max : protected rw int

The field is defined directly under the class block.

  class MyClass {
    has name : string;
  }

Field attributes can be specified.

Compilation Errors:

The field definition needs the type. The type must be a numeric type or an object type. Otherwise a compilation error occurs.

The field names must follows the rule of the field name. Otherwise a compilation error occurs.

Field names cannot be duplicated. If so, a compilation error occurs.

Field Attributes

The list of field attributes.

Field Attributes Descriptions
private This field is private. This field cannnot be accessed from other class. This is default setting.
protected This field is protected. This field cannnot be accessed from other class except for the child classes.
public This field is public. This field can be accessed from other class.
ro This field has its getter method. The getter method name is the same as the field name. For example, If the field names is foo, The getter method name is C.
wo This field has its setter method. The setter method name is the same as field names adding set_ to top. For example, If the field names is foo, The setter method name is set_foo.
rw This field has its getter method and its setter method.

A field getter method is an instance method. It has no arguments. The return type of a field getter method is the same as its field type, except for the byte and short type.

If the type of the field is the byte or short type, The return type of a field getter method is the int type.

A field setter method is an instance method. It has an argument. The type of the argument is the same as the field type. The return type is the void type.

If the type of the field is the byte or short type, The argument type of a field setter method is the int type.

Compilation Errors:

Only one of field attributes private, protected or public can be specified. Otherwise a compilation error occurs.

If more than one of ro, wo, and rw are specified at the same time, a compilation error occurs

Examples:

  class Foo {
    has num1 : byte;
    has num2 : short;
    has num3 : int;
    has num4 : long;
    has num5 : float;
    has num6 : double;
  
    has num_public : public int;
    has num_ro : ro int;
    has num_wo : wo int;
    has num_rw : rw int;
  }

Field Getter Method

A field getter method is a method to perform the operation of the getting a field.

It has no arguments. The return type is the same as the type of the field except that the type of the field is the byte type or the short type.

If the type of the field is the byte type or the short type, the return type is the int type.

It is defined by the ro or rw field attributes.

It is a method that name is the same as the field name.

Examples:

  # Field getter method
  class Foo {
    has num : ro int;
    
    static method new {
      return new Foo;
    }
    
    static method main : void {
      my $foo = Foo->new;
      
      my $num = $foo->num;
    }
  }

Field Setter Method

A field setter method is a method to perform the operation of the setting a field.

The return type is the void type.

It has an argument that type is the same as the type of the fieldexcept that the type of the field is the byte type or the short type.

If the type of the field is the byte type or the short type, the argument type is the int type.

It is defined by the wo or rw field attributes.

It is a method that name is the same as the field name, but prepend set_ to it. For example, if the field name is foo, its setter method name is set_foo.

Examples:

  # Field setter method
  class Foo {
    has num : wo int;
    
    static method new {
      return new Foo;
    }
    
    static method main : void {
      my $foo = Foo->new;
      
      $foo->set_num(3);
    }
  }

Method

Method Definition

The method keyword defines a class method or an instance method.

  # Static method
  static method METHOD_NAME : RETURN_TYPE (ARG_NAME1 : ARG_TYPE1, ARG_NAME2 : ARG_TYPE2, ...) {
    
  }

  # Instance method
  method METHOD_NAME : RETURN_TYPE (ARG_NAME1 : ARG_TYPE1, ARG_NAME2 : ARG_TYPE2, ...) {
    
  }

Methods must be defined directly under the class definition.

Method names must be follow the rule of "Method Name".

The argument names must be follow the rule of "Local Variable Name".

The minimal length of arguments is 0. The max length of arguments is 255.

Defined methods can be called using "Method Call" syntax.

A method can have method attributes.

  ATTRIBUTES static method METHOD_NAME : RETURN_TYPE (ARG_NAME1 : ARG_TYPE1, ARG_NAME2 : ARG_TYPE2, ...) {
  
  }

A method has "Method Block" except for the case that the method has the native method attributes.

Compilation Errors:

The types of the arguments must be a numeric type, the multi-numeric type, an object type, or a reference type. Otherwise a compilation error occurs.

The type of the return value must be the void type, a numeric type, the multi-numeric type or an object type. Otherwise a compilation error occurs.

Optional Arguments

The optional argument is the syntax to specify optional arguments.

  static method METHOD_NAME : RETURN_TYPE (ARG_NAME1 : ARG_TYPE1, ARG_NAME2 : ARG_TYPE2 = DEFAULT_VALUE) {
  
  }
  
  # Deprecated
  static method METHOD_NAME : RETURN_TYPE (ARG_NAME1 : ARG_TYPE1, ARG_NAME2 = DEFAULT_VALUE : ARG_TYPE2) {
  
  }

Examples:

  static method substr ($string : string, $offset : int, $length : int = -1) {
    # ...
  }
  
  my $string = "abc";
  my $offset = 1;
  my $substr = &substr($string, $offset);
  
  # This is the same as the following code
  my $string = "abc";
  my $offset = 1;
  my $length = -1;
  my $substr = &substr($string, $offset, $length);
  

Class Method

A class method is defined with the static keyword.

  static method sum : int ($num1 : int, $num2 : int) {
    # ...
  }

A class method can be called from the class name.

  # Call a class method
  my $total = Foo->sum(1, 2);

If the class method is belong to the current class, a class method can be called using & syntax.

  # Call a class method using C<&>
  my $total = &sum(1, 2);

Instance Method

An instance method is defined without the static keyword.

  method add_chunk : void ($chunk : string) {
    # ...
  }

An instance method can be called from the object.

  # Call an instance method
  my $point = Point->new;
  $point->set_x(3);

Method Attributes

Method attributes are attributes used in a method definition.

Method Attributes Descriptions
private This method is private. This method can not be accessed from other classes.
protected This method is protected. This method can not be accessed from other classes except for the child classes.
public This method is public. This method can be accessed from other classes. This is default setting.
precompile This method is a precompile method.
native This method is a native method.
required This method is required.
If C and C attributes cannnot used together. C can be only used in a method of a L. Compilation Errors: Only one of method attributes C, C or C can be specified. Otherwise a compilation error occurs. If the specifed attribute is not found or the way to specify is invalid, a compilation error occurs. Examples: # private method private method : int sum ($num1 : int, $num2 : int) { return $num1 + $num2; } # precompile method precompile method : int sum ($num1 : int, $num2 : int) { return $num1 + $num2; } # native method native method : int sum ($num1 : int, $num2 : int);

INIT Block

The INIT block defines a INIT method to be executed just after the program starts.

  INIT {
    
  }

The INIT block must be defined directly under the class definition.

  class Foo {
    INIT {
      
    }
  }

Zero or more statements can be written in a INIT block.

  INIT {
    my $foo = 1 + 1;
    my $bar;
  }

The return statement cannot be written in INIT block.

If a INIT block is not defined in a class, a default empty INIT block is defined.

An INIT block is editted.

If a parent class exists, the INIT block of the parent class is called at the beginning of the INIT block.

If classes are used by the use statement, the interface statement, and the allow statement, The INIT blocks in the classes are called in order after the above calling.

  # Before Editting
  class MyClass extends ParentClass {
    use Foo;
    use Bar;
    
    INIT {
      $POINT = Point->new(1, 2);
    }
  }

  # After Editting
  class MyClass extends ParentClass {
    use Point;
    use Fn;
    
    INIT {
      ParentClass->INIT;
      Point->INIT;
      Fn->INIT;
      
      $POINT = Point->new(1, 2);
    }
  }

An INIT block is automatically called only once.

The execution order of INIT blocks is not guaranteed. The INIT blocks in the "Default Loaded Classes" in default loaded class are called before INIT blocks of user defined classes.

Examples:

  class Foo {
    use Point;
    
    our $NUM : int;
    our $STRING : string;
    our $POINT : Point;
    
    # INIT block
    INIT {
      $NUM = 3;
      $STRING = "abc";
      
      $POINT = Point->new(1, 2);
    }
  }

Destructor

A class can have a destructor.

  method DESTROY : void () {
  
  }

The destructor is the method that is called when the object is destroyed by the garbage collection.

The name of the destructor must be DESTROY.

A destructor cannnot have its arguments.

The retrun type must be void type.

A destructor must be an instance method.

If an exception occurs in the destructor, the exception is not thrown. Instead, a warnings message is printed to STDERR.

Compilation Errors:

If the definition of the destructor is invalid, a compilation error occurs.

Examples:

  # Destructor
  class Foo {
    method DESTROY : void () {
      print "DESTROY";
    }
  }

The child class inherits the destructor of the parent class if the destructor of the current class doesn't eixst.

Method Override

An instance method in a parent class can be overridden by an instance method with the same name in a child class.

  class ChildClass extends ParentClass {
    # Method Override
    method clear : void () {
      # ...
    }
  }

  class ParentClass {
    
    method clear : void () {
      # ...
    }
  }

The overridding method in the child class must satisfy the interface requirement to the parent method.

Compilation Errors:

The overridding method in the child class must satisfy the interface requirement to the parent method, otherwise a compilation error occurs.

Anon Method

The anon method operator defines an anon calss that has an anon instance method.

And this operator creates an object which type is the anon class by the "new Operator" in new operator, and returns it.

  # Anon method
  method : TYPE  (VAR1 : TYPE1, VAR2 : TYPE2, ...) {
  
  }

The way to define the method is the same as the method definition.

Examples:

  # Anon method
  class Foo::Bar {
    method some_method : void () {
      my $comparator = (Comparator)method : int ($x1 : object, $x2 : object) {
        my $point1 = (Point)$x1;
        my $point2 = (Point)$x2;
        
        return $point1->x <=> $point2->x;
      };
    }
  }

See also Comparator.

The above example is the same as the following codes.

  # Foo/Bar.spvm
  class Foo::Bar {
    method some_method : void () {
      my $comparator = (Comparator)new Foo::Bar::anon::3::31;
    }
  }
  
  # Foo/Bar/anon/3/31.spvm
  class Foo::Bar::anon::3::31 : public {
    method : int ($x1 : object, $x2 : object) {
      my $point1 = (Point)$x1;
      my $point2 = (Point)$x2;
      
      return $point1->x <=> $point2->x;
    }
  }

Anon Method Field Definition

The anon method field definition is the syntax to define the field of the anon class of the anon method.

  # Anon method field definitions
  [has FIELD_NAME : TYPE1, has FIELD_NAME : TYPE2, ...] ANON_METHOD_DEFINITION
  
  # Anon method field definitions with field default values
  [has FIELD_NAME : TYPE1 = OPERAND1, has FIELD_NAME : TYPE2 = OPERAND2, ...] ANON_METHOD_DEFINITION
  
  [VAR1 : TYPE1, VAR2 : TYPE2, ...] ANON_METHOD_DEFINITION
  

Examples:

  class Foo::Bar {
    method some_method : void () {
      my $foo = 1;
      my $bar = 5L;
      
      my $comparator = (Comparator)[has foo : int = $foo, has bar : long = $bar] method : int ($x1 : object, $x2 : object) {
        my $foo = $self->{foo};
        my $bar = $self->{bar};
        
        print "$foo\n";
        print "$bar\n";
      };
    }
  }

Same as avobe but more simple:

  class Foo::Bar {
    method some_method : void () {
      my $foo = 1;
      my $bar = 5L;
      
      my $comparator = (Comparator)[$foo : int, $bar : long] method : int ($x1 : object, $x2 : object) {
        print "$foo\n";
        print "$bar\n";
      };
    }
  }

The above example is the same as the following codes.

  # Foo/Bar.spvm
  class Foo::Bar {
    method some_method : void () {
      # Externally defined local variables
      my $foo = 1;
      my $bar = 5L;
      
      my $anon = new Foo::Bar::anon::5::61;
      $anon->{foo} = $foo;
      $anon->{bar} = $bar;
      
      my $comparator = (Comparator)$anon;
    }
  }
  
  # Foo/Bar/anon/5/61.spvm
  class Foo::Bar::anon::5::61 : public {
    has foo : public int;
    has bar : public long;
    
    method : int ($x1 : object, $x2 : object) {
      my $foo = $self->{foo};
      my $bar = $self->{bar};
      
      print "$foo\n";
      print "$bar\n";
    }
  }

Native Method

A native method is the method that is written by native languages such as the C language, C++.

A native method is defined by the native method attribute.

  native sum : int ($num1 : int, $num2 : int);

A native method doesn't have its method block.

About the way to write native methods, please see SPVM Native Class and SPVM Native API.

Precompilation Method

If the class has the precompile class attribute, the methods of the class are precompiled.

The source code of each precompiled method is translated to C source code and is compiled to the machine code such as MyMath.o.

And it is linked to a shared library such as MyMath.so on Linux/Unix, MyMath.dll on Windows, or MyMath.dylib on Mac.

And each function in the shared library is bind to the SPVM method.

Precompiled methods need the build directory such as ~/.spvm_build to compile and link them.

Bootstrap Method

A bootstrap method is the methods where the program start.

  void main : void () {
    
  }

The method name is main.

The return type is the void type.

It has no arguments.

Method Implementation

Normally a method has a method block. Statements can be written in a method block.

  # Method implementation
  static method foo : int ($num1 : int, $num2 : int) {
    
    my $total = $num1 + $num2;
    
    return $total;
  }

Local Variable

A local variable is a variable that has a scope.

Local Variable Declaration

Local Variable is a variable that is declared in "Scope Block". Local Variable has the scope. This is the same as Local Variable in C Language.

The local variable is declared using my "Keyword".

  my LOCAL_VARIABLE_NAME : TYPE;

The local variable name must be follow the rule of "Local Variable Name".

the type must be specified. Type must be a numeric type, an object type, the multi-numeric type, or a reference type.

  # Local Variable Declaration Examples
  my $var : int;
  my $var : Point;
  my $var : Complex_2d;
  my $var : int*;

The local variable is initialized by type initial value.

  # Initialized by 0
  my $num : int;
  
  # Initialized by 0
  my $num : double;
  
  # Initialized by undef
  my $point : Point;
  
  # x is initialized by 0. y is initialized by 0.
  my $z : Complex_2d;

The initialization of the local variable can be written at the same time as the local variable declaration.

  # Initialized by 1
  my $num : int = 1;
  
  # Initialized by 2.5
  my $num : double = 2.5;
  
  # Initialized by Point object
  my $point : Point = new Point;

The type can be omitted using the type inference,

  # Type inference - int
  my $num = 1;
  
  # Type inference - double
  my $num = 1.0;

The local variable declaration returns the value of the local variable. The return type is the type of the local variable.

  my $ppp = my $bar = 4;
  
  if (my $bar = 1) {
  
  }
  
  while (my $bar = 1) {
  
  }

See the scope about the scope of the local variable.

Type Inference

If the type of the local variable declaration is ommited, the type of the right operand of the assignment operator is set to it. This is called type inference.

  # int
  my $num = 1;
  
  # double
  my $num = 1.0;
  
  # Foo
  my $foo = new Foo;

Local Variable Access

The local variable access has the following syntax.

  $var

$var is a local variable name.

If local variables with the same name are declared in different scopes, the local variable declared in the inner scope is accessed.

If a class variable with the same name as a local variable is defined, the local variable is accessed.

See also "Getting a Local Variable" and "Setting a Local Variable" about the way to set and set a local variable.

Compilation Errors:

$var must be a valid local variable name, otherwise a compilation error occurs.

The declaration of $var must exists before $var, otherwise a compilation error occurs.

Class Variable Access

The class variable access has the following syntax.

  $VAR

$VAR is a class variable name.

If the class name is ommited, the class is set to the outmost class.

See also "Getting a Class Variable" and "Setting a Class Variable" about the way to set and set a class variable.

Compilation Errors:

$VAR must be a valid class variable name, otherwise a compilation error occurs.

The class specified by $VAR must be loaded, otherwise a compilation error occurs.

The class variable relative name specified by $VAR must be defined in the class specified by $VAR, otherwise a compilation error occurs.

The outmost class must be allowed access to $VAR, otherwise a compilation error occurs.

Element Access

The element access has the following syntax.

  ARRAY->[INDEX]

The type of the array ARRAY is an array type.

The type of the index INDEX is an integer type within int.

See also "Getting an Array Element" and "Setting an Array Element" about the way to set and set an array element.

Compilation Errors:

ARRAY must be an array type, otherwise a compilation error occurs.

INDEX must be an integer type within int, otherwise a compilation error occurs.

Character Access

The character access has the following syntax.

  STRING->[INDEX]

The type of the string STRING is the string type.

The type of the index INDEX is an integer type within int.

See also "Getting a Character" and "Setting a Character" about the way to set and set a character of a string.

Compilation Errors:

STRING must be the string type, otherwise a compilation error occurs.

INDEX must be an integer type within int, otherwise a compilation error occurs.

Field Access

The field access has the following syntax.

  INVOCANT->{FIELD_NAME}

INVOCANT is an object of a class type, a value of a multi-numeric type, a value of a multi-numeric reference type.

FIELD_NAME is a field name.

Compilation Errors:

INVOCANT must be an object of a class type, a value of a multi-numeric type, a value of a multi-numeric reference type, otherwise a compilation error occurs.

Depending on the type of INVOCANT, there are the following field access.

Field Access for Class Types

See "Getting a Field" and "Setting a Field" to get and set the value of the field of the class type.

Compilation Errors:

If the type of INVOCANT is a class type, the field specified by FIELD_NAME must be defined in the class, or its super classes, otherwise a compilation error occurs.

Field Access for Multi-Numeric Types

See "Getting a Multi-Numeric Field" and "Setting a Multi-Numeric Field" to get and set the value of the field of the multi-numeric type.

Compilation Errors:

If the type of INVOCANT is a multi-numeric type, the field specified by FIELD_NAME must be defined in the multi-numeric type, otherwise a compilation error occurs.

Field Access for Multi-Numeric Reference Types

See "Getting a Referenced Multi-Numeric Field" and "Setting a Referenced Multi-Numeric Field" to get and set the value of the field referenced by the multi-numeric reference type.

Compilation Errors:

If the type of INVOCANT is a multi-numeric reference type, the field specified by FIELD_NAME must be defined in the multi-numeric type referenced by the multi-numeric reference type, otherwise a compilation error occurs.

Block

A block is the part enclosed by { and }.

Class Block

A class block is a block used in a class definition.

  # Class block
  class Point {
  
  }

Enumeration Block

An enumeration block is a block used in a enumeration definition.

  # Enumeration block
  enum {
    ONE,
    TWO,
  }

Scope Block

The scope block has its scope. Zero or more statements are written in a scope block.

Simple Block

The simple block is a scope block.

  # Simple block
  {
    1;
  }

The simple block must have at least one statements. Otherwise it is intepreted as the array initialization.

Method Block

The method block is a scope block.

  # Method block
  static method foo : int () {
  
  }

The block of INIT method is a method block.

  INIT {
    
  }

eval Block

The eval block is a scope block.

  # eval block
  eval {
  
  }

if Block

The if block is a scope block.

  # if block
  if (CONDITION) {
  
  }

elsif Block

The elsif block is a scope block.

  # elsif block
  elsif (CONDITION) {
  
  }

else Block

The else block is a scope block.

  # else block
  else {
  
  }

for Block

The for block is a scope block.

  # for Block 
  for (my $i = 0; $i < 3; $i++) {
  
  }

while Block

The while block is a scope block.

  # while block
  while (CONDITION) {
  
  }

switch Block

The switch block is a scope block.

  # switch block
  switch (CONDITION) {
  
  }

case Block

The case block is a scope block.

  # case block
  switch (CONDITION) {
    case CASE_VALUE1: {
      # ...
    }
  }

default Block

The default block is a scope block.

  # default block
  switch (CONDITION) {
    default: {
      # ...
    }
  }

Type Comment

The type comment syntax is supported. The type comment can be written after of keyword.

  TYPE of TYPE
  TYPE of TYPE1|TYPE2
  TYPE of TYPE1|TYPE2|TYPE3

The type comment can be used the type of the field decralation, the class variable definition, the local variable declaration, and the return value and the types of arguments of the method definition.

  has points : List of Point;
  
  our $POINTS : List of Point;
  
  my $points : List of Point;
  
  static method foo : List of Point ($arg : List of Point) { ... }
  
  my $replace : object of string|Regex::Replacer;

Type comments have no meanings at runtime.

Compilation Errors:

If the type specified as the type comment is not found, a compilation error occurs.

Copyright & License

Copyright (c) 2023 Yuki Kimoto

MIT License