SPVM::D...e::Class(3)

πŸ“¦ version 0.990125, in alpine 3.24

πŸ’– SPVM::D...e::Class(3) πŸ’–

User Contributed Perl Documentation

✨ Name ✨

SPVM::Document::Language::Class - Classes in the SPVM Language

🌸 Description 🌸

This doc is literally all about classes, bestie. πŸ’…

πŸ‘‘ Class πŸ‘‘

SPVM is an object-oriented programming language, and it has class syntax β€” periodt. This section is the class-syntax tour.

If you want the grammar tea, see SPVM::Document::Language::SyntaxParsing for the grammar of the SPVM language. 🫢

πŸŽ€ Class Definition πŸŽ€

The class keyword defines a class type. Iconic behavior, honestly.

class CLASS_NAME {

}

class CLASS_NAME;

class CLASS_NAME : ATTRIBUTES {

}

class CLASS_NAME : ATTRIBUTES;

CLASS_NAME is a class name.

ATTRIBUTES is one of:

ATTRIBUTES ATTRIBUTE
ATTRIBUTE

ATTRIBUTE is a class attribute.

A class type is also simply called a class.

The new operator creates an object from a class. ✨

Compilation Errors:

  • CLASS_NAME must be a class name. Otherwise, a compilation error occurs.
  • If more than one class is defined in a class file, a compilation error occurs.

Examples:

# Examepls of class definitions
class Point {

}

πŸ¦‹ Class Attributes πŸ¦‹

The List of Class Attributes:

Compilation Errors:

  • Only one of private, protected or public must be specified. Otherwise, a compilation error occurs.
  • If more than one of interface_t, mulnum_t, and pointer are specified, a compilation error occurs.

Examples:

# Examples of class attributes
class Point : public {

}

class Point : public pointer {

}

πŸ’œ Pointer Class πŸ’œ

The pointer class is a class with the pointer class attribute.

class CLASS_NAME : pointer {

}

An object of a pointer class has the pointer to a native address that is normally a pointer to a C language struct, or a C++ language struct or class. No cap, that's the pointer vibe.

Examples:

# Examples of the pointer attribute
class Foo : pointer {

}

🌈 Class File 🌈

A class file is a file where a class is defined.

The name of a class file is the same as a class name, but all :: are replaced to / and .spvm is added at the end of it.

# Foo
Foo.spvm

# Foo::Bar
Foo/Bar.spvm

# Foo::Bar::Baz
Foo/Bar/Baz.spvm

Compilation Errors:

  • A class definition must be written in its corresponding class file. Otherwise, a compilation error occurs.

⭐ version Statement ⭐

The version statement declares the version of a class.

version VERSION_STRING;

This statement declares the version of a class given version string VERSION_STRING.

Compilation Errors:

  • If the version has already been declared, a compilation error occurs.
  • VERSION_STRING must be a version string. Otherwise, a compilation error occurs.

Examples:

class MyClass {
  version "1.001";
}

class MyClass {
  version "10.001003";
}

πŸ“ Version String πŸ“

The version string is the string that represents version of a class.

A version string must be written by the following rules:

  • The type of a version string is string type.
  • It consists of "0-9", ".".
  • The count of "." is less than or equal to 1.
  • It begins with "0-9".
  • It ends with "0-9".
  • The count of "0-9" after "." is divisible by 3.
  • It is able to be parsed by the strtod function in the C language.

Compilation Errors:

  • If a version string is not valid, a compilation error occurs.

Examples:

# Examples of version strings
"1.001"
"10.001003"
"1"
"10000"

🧚 Version Number 🧚

A version number is a floating point number created from a version string using the strtod function in the C language.

Examples:

# Examples of version numbers

# "1.001"
1.001

# "10.001003"
10.001003

🌟 version_from Statement 🌟

The version_from statement allows you to make the version of the current class dependent on another class.

version_from CLASS_NAME;

CLASS_NAME is a class name.

It means the version of the current class is considered to be the same as the version of the class specified by CLASS_NAME.

The class specified by CLASS_NAME is loaded by use statement.

Compilation Errors:

  • If version_from has already been declared, a compilation error occurs.

Examples:

class MyClass::Foo {
  version_from MyClass;
}

class MyClass {
  version "1.001";
}

πŸ’– use Statement πŸ’–

The use statement loads a class.

use BASIC_TYPE;
use BASIC_TYPE as CLASS_NAME;

This statement searches for the type BASIC_TYPE in class search directories from the beginning, and if found, loads the type.

BASIC_TYPE is a class type, an interface type, or a multi-numeric type.

See require statement about how to load a type without causing a compile error when loading fails,

The following use statement with as:

use BASIC_TYPE as CLASS_NAME;

is expanded to the following code using alias statement.

use BASIC_TYPE;
alias BASIC_TYPE as CLASS_NAME

Compilation Errors:

  • BASIC_TYPE must be a class name. Otherwise, a compilation error occurs.
  • CLASS_NAME must be a class name. Otherwise, a compilation error occurs.
  • If BASIC_TYPE does not found, a compilation error occurs.

Examples:

# Examples of use statement
class MyClass {
  use Foo;
}

class MyClass {
  use Sys::Socket::Constant as SOCKET;
}

πŸŽ€ Class Search Directories πŸŽ€

Class search directories are directories in which classes are searched for.

These are set outside the program.

Directories set by -I option of spvm command and spvmcc command are added to class search directories.

And directories with /SPVM added to the end of each value of Perl's @INC (https://perldoc.perl.org/perlvar#@INC) are added to the end of the class search directories. 🫢

🌸 Default Loaded Classes 🌸

The following classes are loaded by default:

  • Byte
  • Short
  • Int
  • Long
  • Float
  • Double
  • Bool
  • Error
  • Error::System
  • Error::NotSupported
  • Error::Compile
  • CommandInfo
  • Address
  • Error::Compile
  • SPVM
  • Error::MethodCallNotPermitted
  • Stringable
  • Countable
  • CallerInfo

πŸ¦‹ alias Statement πŸ¦‹

The alias statement creates a class alias name for a type.

alias BASIC_TYPE as CLASS_NAME;

This statement creates a class alias name CLASS_NAME for a type BASIC_TYPE.

BASIC_TYPE is a class type, an interface type, or a multi-numeric type.

Compilation Errors:

  • BASIC_TYPE must be a class name. Otherwise, a compilation error occurs.
  • CLASS_NAME must be a class name. Otherwise, a compilation error occurs.

Examples:

class MyClass {
  use Sys::Socket::Constant;
  alias Sys::Socket::Constant as SOCKET;

  SOCKET->AF_INET;
}

πŸ’œ allow Statement πŸ’œ

The allow statement allows a type private accesses to the current class.

allow BASIC_TYPE;

By default, objects of private classes cannot be created by new operator from other classes.

And private methods, private fields, and private class variables cannot be accessed from other classes.

This statement allows the type BASIC_TYPE private accesses to the current class.

BASIC_TYPE is loaded by use statement.

Examples:

# Allowing private access
class MyClass {
  allow SomeClass;
}

🌈 Inheritance 🌈

A class inherits a class using the extends keyword.

class CLASS_NAME extends PARENT_CLASS_NAME {

}

The class CLASS_NAME that inherits the parent class PARENT_CLASS_NAME is defined.

The field definitions of the parent class PARENT_CLASS_NAME are added to the end of the field definitions of the class CLASS_NAME to the end of its fields.

The interface statements of the parent class PARENT_CLASS_NAME are added to the end of interface statements of the class CLASS_NAME.

The instance of the class CLASS_NAME can call instance methods of the parent class PARENT_CLASS_NAME and its super classes.

Compilation Errors:

  • The parent class PARENT_CLASS_NAME must be a class type. Otherwise, a compilation error occurs.
  • The name of the parent 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 cannot be defined. Otherwise, a compilation error occurs.
  • The class CLASS_NAME interpreted by an interface must satisfy interface requirement to the parent class PARENT_CLASS_NAME. 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 ⭐

This section describes interfaces.

πŸŽ€ Interface Definition πŸŽ€

A class definition with the interface_t class attribute defines an interface type.

class CLASS_NAME : interface_t {

}

An interface type is also simply called an interface.

Objects cannot be created from interface types.

Normally, an interface has interface methods.

Compilation Errors:

  • An interface cannot have field definitions. If so, a compilation error occurs.
  • An interface cannot have class variable definitions. If so, a compilation error occurs.

Examples:

# Examples of interface definitions
class TestCase::Pointable : interface_t {
  interface Stringable;

  method x : int ();
  method y : int();
  method to_string : string ();
}

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

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

πŸ’… interface Statement πŸ’…

The interface statement checks if the current class satisfies interface requirement to an interface.

πŸ’– Interface

interface BASIC_TYPE;

BASIC_TYPE gets loaded by a use statement β€” that's the whole vibe, it's how the class pulls in the interface it's promising to be.

⚠️ Compilation error tea: BASIC_TYPE has to actually be an interface type. If it's not β€” boom, compilation error. Also, your current class must satisfy the interface requirement for the interface type BASIC_TYPE, otherwise… you guessed it, compilation error. The compiler is not letting that slide, fr fr.

Example, bestie:

# Examples of interface statement
class Point {
  interface Stringable;

  method to_string : string () {
    my $x = $self->x;
    my $y = $self->y;

    my $string = "($x,$y)";

    return $string;
  }
}

πŸ¦‹ Anon Class

Okay so an anon class is literally a class where you never name it. No name, just vibes. Anonymous. Iconic behaviour honestly.

✨ Anon Class Definition

Here's the syntax, it's giving minimalism:

class {

}

An anon class cannot be defined in a class file. Nope, not happening. It can only be defined in source code that's compiled by the compile_anon_class compiler native API.

An anon class still has a class name though β€” autogenerated cuties like "eval::anon_class::0", "eval::anon_class::1", "eval::anon_class::2".

eval::anon_class::123

Examples:

# Examples of the anon class definition
class {
  static method sum : int ($num1 : int, $num2 : int) {
    return $num1 + $num2;
  }
}

πŸ‘‘ Anon Method Class

An anon method class is the class that gets defined by an anon method operator. Sneaky little class factory, lowkey.

πŸŽ€ Anon Method Class Definition

The anon method class definition has this syntax:

ANON_METHOD_CLASS_FIELD_DEFINITION METHOD_DEFINITION

ANON_METHOD_CLASS_FIELD_DEFINITION is an anon method class field definition.

METHOD_DEFINITION is a method definition.

The anon method class definition defines the class that this method belongs to. Like, the method gets a whole class of its own β€” main character energy.

The name of this class is a string that joins the outmost class, the string "anon_method", the line number, and the position of columns where the anon method class definition is written β€” all glued together with "::".

MyClass::anon_method::3::23

An anon method class has the same access control as its outmost class. Same alias names too. It's literally inheriting the whole look.

⚠️ Compilation errors, heads up: - The method name of METHOD_DEFINITION must be an empty string. Otherwise, compilation error. - The method must be an instance method. Otherwise, compilation error. No static shenanigans.

Examples:

# Examples of the anon method definition
class Foo::Bar {
  method my_method : void () {
    my $comparator = (Comparator)method : int ($x1 : object, $x2 : object) {
      my $point1 = (Point)$x1;
      my $point2 = (Point)$x2;

      return $point1->x <=> $point2->x;
    };
  }
}

🌸 Anon Method Class Field Definition

An anon method class field definition defines the fields of an anon class β€” and that anon class is a part of the anon method class definition. Nested cuties.

[ANON_METHOD_CLASS_FIELD_DEFINITION_ITEM1, ANON_METHOD_CLASS_FIELD_DEFINITION_ITEM, ANON_METHOD_CLASS_FIELD_DEFINITION_ITEMn]

ANON_METHOD_CLASS_FIELD_DEFINITION_ITEM is one of:

has FIELD_NAME : TYPE
has FIELD_NAME : TYPE = OPERAND
VAR : TYPE
VAR : TYPE = OPERAND

has FIELD_NAME : ATTRIBUTE1 ATTRIBUTE2 ATTRIBUTEn TYPE
has FIELD_NAME : ATTRIBUTE1 ATTRIBUTE2 ATTRIBUTEn TYPE = OPERAND
VAR : ATTRIBUTE1 ATTRIBUTE2 ATTRIBUTEn TYPE
VAR : ATTRIBUTE1 ATTRIBUTE2 ATTRIBUTEn TYPE = OPERAND

FIELD_NAME is a field name.

TYPE is a type.

OPERAND is an operator.

"VAR : TYPE = OPERAND" gets expanded to "has FIELD_NAME : TYPE = OPERAND". The FIELD_NAME is the same as the name of VAR, but the "$" is removed. And VAR is declared at the top of this anon method and set to the value of its corresponding field. Cute, right? It's giving "shortcut".

"VAR : TYPE" is the same as above, but it expands to "has FIELD_NAME : TYPE = VAR".

ATTRIBUTE is a field attribute.

⚠️ Compilation errors caused by Field Definition could occur. So like, behave.

Examples β€” three flavours, pick your fave:

# Examples of the anon method class field definition
class Foo::Bar {
  method my_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};

      say "$foo";
      say "$bar";
    };
  }
}

# More simple
class Foo::Bar {
  method my_method : void () {
    my $foo = 1;
    my $bar = 5L;

    my $comparator = (Comparator)[$foo : int, $bar : long] method : int ($x1 : object, $x2 : object) {
      say "$foo";
      say "$bar";
    };
  }
}

# Change variable names
class Foo::Bar {
  method my_method : void () {
    my $foo = 1;
    my $bar = 5L;

    my $comparator = (Comparator)[$foo_x : int = $foo, $bar_x : long = $bar] method : int ($x1 : object, $x2 : object) {
      say "$foo_x";
      say "$bar_x";
    };
  }
}

🌈 Outmost Class

An outmost class is the outmost defined class. Basically it's the same thing as the class defined by a class definition. The outermost layer of the onion. πŸ§…

class OutmostClass {

}

Examples:

# Examples of the outmost class
class MyClass {
  static method my_method : void () {

    # The __PACKAGE__ operator returns the outmost class "MyClass".
    my $outmost_class_name = __PACKAGE__;

    # Anon method
    my $cb = method : void () {

      # The __PACKAGE__ operator returns the outmost class "MyClass".
      my $outmost_class_name = __PACKAGE__;
    };
  }
}

See how __PACKAGE__ keeps pointing at MyClass even from inside the anon method? That's the outmost class doing its job. Consistent queen. πŸ’…


πŸ”₯ Multi-Numeric Type Definition

A multi-numeric type gets defined by a class definition that has the "mulnum_t" class attribute.

class CLASS_NAME : mulnum_t {

  has FIELD_NAME1 : NUMERIC_TYPE;
  has FIELD_NAME2 : NUMERIC_TYPE;
  has FIELD_NAMEn : NUMERIC_TYPE;
}

Rules of the game, no skips:

  • A multi-numeric field must have at least one field.
  • The type of a field must be a numeric type.
  • The types of all fields must be the same. Every single one, periodt.
  • The length of fields must be less than or equal to 255.
  • CLASS_NAME must end with a multi-numeric type suffix corresponding to the type of the fields.
  • FIELD_LENGTH of the multi-numeric type suffix must be the same as the length of the fields.
  • TYPE_SUFFIX of the multi-numeric type suffix must correspond to the type of the fields.
  • A multi-numeric type cannot have instance methods. None. Zero.
  • A multi-numeric type cannot have class variables. Also none.
⚠️ Compilation errors: if the definition of the multi-numeric type is invalid, a compilation error occurs. The compiler said what it said.

Examples:

# Examples of the multi-numeric type definition
class Complex_2f : mulnum_t {
  re : float;
  im : float;
}

class Complex_2d : mulnum_t {
  re : double;
  im : double;
}

class Quaternion_4f : mulnum_t {
  re : float;
  i : float;
  j : float;
  k : float;
}

class Quaternion_4d : mulnum_t {
  re : double;
  i : double;
  j : double;
  k : double;
}

⭐ Multi-Numeric Type Suffix

The multi-numeric type must end with this suffix:

_(non-spaces)FIELD_LENGTH(non-spaces)TYPE_SUFFIX

FIELD_LENGTH is the length of fields.

TYPE_SUFFIX is a type suffix.

The List of Type Suffixes: β€” and that's it, bestie, the list prints out empty in this doc, so there's literally nothing to list here πŸ’€

Examples:

# Examples of the multi-numeric type suffix
_2f;
_2d;
_4f;
_4d;

πŸ“ Enumeration

Enumeration is a syntax that defines 32-bit integers that belong to a class. Little ints with a home. 🏠

πŸ’œ Enumeration Definition

The "enum" keyword defines an enumeration:

enum {
  ITEM1,
  ITEM2,
  ITEMn
}

A "," after the last enumeration item is allowed. Trailing comma girlies, you're safe.

enum {
  ITEM1,
  ITEM2,
  ITEM3,
}

ITEM is one of:

NAME
NAME = VALUE

NAME is a method name.

VALUE is an integer literal within int type. VALUE gets converted to the value of int type.

If VALUE of ITEM1 is omitted, it's set to 0.

If VALUE of ITEMn is omitted, it's set to the value of the previous item plus 1.

The return type of the method is int type.

Every enumeration item gets converted into a method definition that defines a class method returning the value of that enumeration item. It's a glow-up, honestly.

# Definition of an enumeration
class MyClass {
  enum {
    NAME = 5,
  }
}

# This are replaced with a definition of a class method
class MyClass {
  static method NAME : int () { return 5; }
}

(That comment's grammar is kept verbatim from the source, don't come for me πŸ™ˆ)

See also "Inline Expansion of Method Call to Get an Enuemration Value". (Also verbatim, spelling and all β€” iykyk.)

⚠️ Compilation errors: - NAME must be a method name. Otherwise, a compilation error occurs. - VALUE must be an integer literal within int type. Otherwise, a compilation error occurs.

Examples:

# Examples of enumerations
class MyClass {
  enum {
    FLAG1,
    FLAG2,
    FLAG3,
  }

  static method main : void () {
    my $flag1 = MyClass->FLAG1;
  }
}

class MyClass {
  enum {
    FLAG1,
    FLAG2 = 2,
    FLAG3,
  }
}

πŸŽ€ Enumeration Attributes

The List of Enumeration Attributes: β€” again, this list comes through empty in the source, so there's nothing printed here to show you 🫢

⚠️ Compilation errors: one of "private", "protected" and "public" must be specified. Otherwise, a compilation error occurs. Pick one, bestie, the compiler isn't accepting "whatever feels right".

πŸ’– Class Variable πŸ’–

ok so a class variable is a global variable that belongs to a class. think of it as the class's shared locker β€” everybody in the class can get to it πŸ—„οΈβœ¨

✨ Class Variable Definition ✨

the our keyword is the one that defines a class variable, no cap:

our CLASS_VARIABLE_NAME : OPT_ATTRIBUTES TYPE;
  • CLASS_VARIABLE_NAME β€” the class variable's name, and it's gotta be a name that does not contain "::".
  • TYPE β€” a type.
  • OPT_ATTRIBUTES β€” one of these two moods:
EMPTY
ATTRIBUTES

EMPTY means, like, nothing exists. ATTRIBUTES is one of:

ATTRIBUTES ATTRIBUTE
ATTRIBUTE

and ATTRIBUTE is a class variable attribute πŸ’…

every single class variable gets initialized by its type's initial value. that's the vibe from the start ✨

you get the value of a class variable through the operation of getting a class variable, and you set it through the operation of setting a class variable. matching set, iykyk.

Compilation Errors (these will humble you πŸ’€):

  • CLASS_VARIABLE_NAME must be a class variable name that does not contain "::". otherwise, a compilation error occurs.
  • TYPE must be a numeric type or an object type.
  • ATTRIBUTE must be a class variable attribute. otherwise, a compilation error occurs.
  • if two or more class variables that have the same name are defined, a compilation error occurs.

Examples:

class MyClass {
  our $NUM_BYTE : byte;
  our $NUM_SHORT : short;
  our $NUM_INT : int;
  our $NUM_LONG : long;
  our $NUM_FLOAT : float;
  our $NUM_DOUBLE : double;
  our $POINT : Point;

  our $NUM_PUBLIC : public int;
  our $NUM_RO : ro int;
  our $NUM_RW : rw int;
}

look at all those lil variables living their best lives 😌

🌸 Class Variable Attributes 🌸

the list of class variable attributes:

(that's the list, bestie β€” it lives right there in the original πŸ‘‘)

Compilation Errors:

  • one of "private", "protected" and "public" must be specified. otherwise, a compilation error occurs.
  • one of "ro", "wo", and "rw" must be specified. otherwise, a compilation error occurs.

like, you have to pick one from each column. no indecisive energy allowed 🚫

πŸŽ€ Class Variable Getter Method πŸŽ€

a class variable getter method is a method that performs the operation of getting a class variable. it's the "gimme" method 🫢

  • it's a class method that has no arguments.
  • if the type of the class variable is byte type or short type, the return type is int type. otherwise, it's the same type as the class variable.
  • the method name is the same as the class variable name, but the "$" gets removed. so if your class variable is $FOO, the method name is "FOO" ✨

Examples:

# Examples of class variable getter methods
class MyClass {
  our $VALUE : ro int;

  static method main : void {
    my $num = Foo->VALUE;
  }
}

a user defined class variable getter can be defined with the get keyword:

class MyClass {
  our $VALUE : ro int
    get {
      return $VALUE;
    }
  ;
}

and yes, you can define a user defined getter and setter at the same time. two for one, we love efficiency πŸ’–

class MyClass {
  our $VALUE : rw int
    get {
      return $VALUE;
    }
    set {
      $VALUE = $_;
    }
  ;
}

πŸ’… Class Variable Setter Method πŸ’…

a class variable setter method is a method that performs the operation of setting a class variable. the "here, take this" method 😭

  • it's a class method that has an argument.
  • if the type of the class variable is byte type or short type, the argument type is int type. otherwise, it's the same type as the class variable.
  • the return type is void type.
  • the method name is the same as the class variable name, but the "$" is removed and "SET_" is added to the beginning of it. so if the class variable name is $FOO, the method name is "SET_FOO" πŸ‘‘

Examples:

# Examples of class variable setter methods
class MyClass {
  our $NUM : wo int;

  static method main : void {
    Foo->SET_NUM(3);
  }
}

a user defined class variable setter can be defined with the set keyword. the passed value gets assigned to $_:

class MyClass {
  our $VALUE : wo int
    set {
      $VALUE = $_;
    }
  ;
}

and the argument can be replaced if you're feeling fancy:

class MyClass {
  our $VALUE : wo int
    set ($VAL : object) {
      $VALUE = (int)$VAL;
    }
  ;
}

πŸ¦‹ Field πŸ¦‹

a field is a data member of a class. it's the class's own personal data, main character energy πŸ‘‘

⭐ Field Definition ⭐

the has keyword defines a field:

has FIELD_NAME : OPT_ATTRIBUTES TYPE;
  • FIELD_NAME β€” a field name.
  • TYPE β€” a type.
  • OPT_ATTRIBUTES β€” one of:
EMPTY
ATTRIBUTES

EMPTY means nothing exists (again). ATTRIBUTES is one of:

ATTRIBUTES ATTRIBUTE
ATTRIBUTE

and ATTRIBUTE is a field attribute 🌸

every field of an object gets initialized by its type's initial value when the object is created. fresh object, fresh fields ✨

the value of a field is got by the operation of getting a field, and set by the operation of setting a field.

Compilation Errors:

  • FIELD_NAME must be a field name. otherwise, a compilation error occurs.
  • TYPE must be a numeric type or an object type.
  • ATTRIBUTE must be a field attribute. otherwise, a compilation error occurs.
  • if two or more fields that have the same name are defined, a compilation error occurs.
  • if the field is already defined with a different type in the super class, a compilation error occurs. (inheritance said no πŸ’€)

Examples:

class MyClass {
  has num_byte : byte;
  has num_short : short;
  has num_int : int;
  has num_long : long;
  has num_float : float;
  has num_double : double;

  has num_public : public int;
  has num_ro : ro int;
  has num_rw : rw int;
}

🌈 Field Attributes 🌈

the list of field attributes:

(same deal β€” that's the list, it's right there in the original πŸŽ€)

Compilation Errors:

  • one of "private", "protected" and "public" must be specified. otherwise, a compilation error occurs.
  • one of "ro", "wo", and "rw" must be specified. otherwise, a compilation error occurs.

🧚 Field Getter Method 🧚

a field getter method is a method that performs the operation of getting a field.

  • it's an instance method that has no arguments.
  • if the type of the field is byte type or short type, the return type is int type. otherwise, it's the same type as the field.
  • the method name is the same as the field name. if the field name is "foo", the method name is "foo". yes, same name. iconic, no notes πŸ’…

Examples:

# Examples of field getter methods
class MyClass {
  has value : ro int;

  static method new {
    return new Foo;
  }

  static method main : void {
    my $foo = Foo->new;

    my $value = $foo->value;
  }
}

a user defined field getter can be defined with the get keyword:

class MyClass {
  has value : ro int
    get {
      return $self->{value};
    }
  ;
}

user defined getter and setter can be defined at once β€” combo move 🫢

class MyClass {
  has value : rw int
    get {
      return $self->{value};
    }
    set {
      $self->{value} = $_;
    }
  ;
}

πŸ”₯ Field Setter Method πŸ”₯

a field setter method is a method that performs the operation of setting a field.

  • it's an instance method that has an argument.
  • if the type of the field is byte type or short type, the argument type is int type. otherwise, it's the same type as the field.
  • the return type is void type.
  • the method name is the same as the field name, but "set_" is added to the beginning of it. if the field name is "foo", the method name is "set_foo" ⭐

Examples:

# Examples of field setter methods
class MyClass {
  has value : wo int;

  static method new {
    return new Foo;
  }

  static method main : void {
    my $foo = Foo->new;

    $foo->set_value(3);
  }
}

a user defined field setter can be defined with the set keyword. the passed value is assigned to $_:

class MyClass {
  has value : wo int
    set {
      $self->{value} = $_;
    }
  ;
}

the argument can be replaced:

class MyClass {
  has value : wo int
    set ($value : object) {
      $self->{value} = (int)$value;
    }
  ;
}

the return type can be replaced too:

class MyClass {
  has value : wo int
    set : MyClass ($value : object) {
      $self->{value} = (int)$value;
      return $self;
    }
  ;
}

and if there's no method block but a return type is specified, the default setter returns the invocant. it just hands you back the object. self-care 😌

class MyClass {
  has value : wo int
    set : MyClass
  ;
}

πŸ’œ Field Existence πŸ’œ

an object has field existence flags. lil checkboxes for every field βœ…

when a new object is created, these flags are zero.

when one of the field set operations is performed, this flag is set to 1.

# The field existence flag for "value" field is set to 1.
$object->{value} = 1;

you can check if a field exists using the exists operator:

my $exists = exists $object->{value};

you can delete a field using the delete operator:

delete $object->{value};

the field existence flag is set to 0, and the value of the field is set to 0 in the case of numeric types or undef in the case of object types. gone, reduced to atoms πŸ’€βœ¨


πŸŽ€ Method πŸŽ€

🌸 Method Definition 🌸

the method keyword defines a method:

OPT_ATTRIBUTES method METHOD_NAME : RETURN_TYPE (OPT_ARG_ITEMS) { }
OPT_ATTRIBUTES method METHOD_NAME : RETURN_TYPE (OPT_ARG_ITEMS);

OPT_ATTRIBUTES is one of:

EMPTY
ATTRIBUTES

EMPTY means nothing exists. ATTRIBUTES is one of:

ATTRIBUTES ATTRIBUTE
ATTRIBUTE

and ATTRIBUTE is a method attribute πŸ’…

  • METHOD_NAME β€” a method name.
  • RETURN_TYPE β€” a type.

OPT_ARG_ITEMS is one of:

EMPTY
ARG_ITEMS

EMPTY means nothing exists (you're sensing a pattern here, right? 😭). ARG_ITEMS is one of:

ARG_ITEMS , ARG_ITEM
ARG_ITEM

and ARG_ITEM is one of:

ARG_NAME : ARG_TYPE
ARG_NAME : ARG_TYPE = VALUE
  • ARG_NAME β€” a local variable name. the local variable specified by ARG_NAME is declared at the beginning of the method implementation.
  • ARG_TYPE β€” a type.
  • VALUE β€” a literal or "undef".

a method with the "static" method attribute is a class method. a method without the "static" method attribute is an instance method. that's the whole vibe check right there πŸ¦‹

an argument with VALUE is an optional argument. if a method call does not give a value to an optional argument, VALUE is given to the argument. it's got a backup plan built in 🫢

a interface method defined in an interface is an interface method.

a method with the "native" method attribute is a native method.

Compilation Errors:

  • the count of ARGS must be less than or equal to 255. otherwise, a compilation error occurs. (255 is the limit, bestie β€” do not test it πŸ’€)
  • ARG_TYPE must be a numeric type, a multi-numeric type, an object type, or a reference type. otherwise, a compilation error occurs.
  • RETURN_TYPE β€” has to be void type, a numeric type, a multi-numeric type, or an object type. Anything else? πŸ’€ compilation error, bestie.
  • Methods that aren't interface methods or native methods must have a method block. No block = compilation error, no cap.
  • VALUE has to satisfy the assignment requirement to ARG_TYPE. If it doesn't, compilation error, sorry 🫢
  • METHOD_NAME must not be "INIT". Try it and get a compilation error. Periodt.
  • A non-optional argument must not come after an optional argument. Do it anyway and boom πŸ’₯ compilation error.

Examples, because we love a visual:

class MyClass {
  # Class method
  static method substr : string ($string : string, $offset : int, $length : int = -1) {
    # ...
  }

  # Instance method
  method clear : void () {

  }
}

πŸŽ€ Method Attributes πŸŽ€

The List of Method Attributes:

Compilation Errors:

  • One of "private", "protected" and "public" must be specified. Otherwise, a compilation error occurs. Pick one, babes, you can't sit with all three πŸ’…
  • "required" must be specified to an interface method. Otherwise, a compilation error occurs.

Examples of each flavor:

# 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);

✨ Class Method ✨

A method defined with the "static" method attribute is a class method.

A class method can be called by a class method call. That's the whole vibe ✨


🌸 Instance Method 🌸

A method defined without the "static" method attribute is an instance method.

An instance method can be called by an instance method call. Main character energy, honestly πŸ‘‘


πŸ¦‹ Interface Method πŸ¦‹

An instance method defined in an interface is an interface method.

Normally, an interface method does not have a method block.

method my_method : int ();

But β€” plot twist β€” an interface method can have a method block:

method my_method : int () {

}

An interface method can have the "required" method attribute, which means classes must define a method with the same name that implements this interface method. Like, it's required required.

required method my_method : int ();

🧚 INIT Block 🧚

An "INIT" block is a special scope block to initialize class variables or perform setup tasks.

our $FOO : int;

INIT {
  $FOO = 1;
}

Multiple "INIT" blocks can be defined. Stack 'em up, bestie:

INIT {
  # First setup
}

INIT {
  # Second setup
}

All "INIT" blocks in a class are merged into a single INIT method at compile time. Iconic efficiency.


πŸ’œ INIT Method πŸ’œ

An "INIT" method is a special method that is automatically generated by the compiler. You don't write it, it just exists.

It consists of all INIT blocks in a class. If no "INIT" block exists, an empty "INIT" method is generated. Still shows up. Still doing the work (of nothing).

This method has no arguments and its return type is the "void" type.

The "INIT" methods of the parent class and classes loaded via use statements are called at the beginning of the "INIT" method of the current class.

Note that the execution order of "INIT" methods among different classes is not generally guaranteed. However, the "INIT" methods of Default Loaded Classes are guaranteed to be called before any user-defined "INIT" methods. So like, mostly chaos, but one specific bit of order πŸ’€

This method is automatically called after all classes are loaded, and before the first method in the program is called. It can also be called manually.

Examples, because examples ate:

# Examples of INIT blocks
class MyClass {
  use Point;

  our $NUM : int;
  our $STRING : string;
  our $POINT : Point;

  INIT {
    $NUM = 3;
    $STRING = "abc";
  }

  INIT {
    $POINT = Point->new(1, 2);
  }

  INIT {
    OtherClass->INIT;
  }
}

🌈 END Block 🌈

An "END" block is a special scope block to perform cleanup tasks.

END {
  # Cleanup tasks
}

Multiple "END" blocks can be defined:

END {
  # First cleanup
}

END {
  # Second cleanup
}

All "END" blocks in a class are merged into a single END method in reverse order (LIFO) at compile time. Last one in, first one out β€” she's organized πŸ’…


⭐ END Method ⭐

An "END" method is a special method that is automatically generated by the compiler.

It consists of all END blocks in a class. If no "END" block exists, an empty "END" method is generated.

This method has no arguments and its return type is the "void" type.

Note that the execution order of "END" methods among different classes is not generally guaranteed.

If an exception occurs in an "END" method, it is converted to a warning message and printed to "stderr", and the program continues its termination process. No drama in the cleanup phase, we just log it and go 😌

This method is automatically called when the program is about to terminate, just before class variables are destroyed. It can also be called manually.


πŸ’€ Destructor πŸ’€

A destructor is a method called just before an object is destroyed.

method DESTROY : void () {

}

A destructor is an instance method.

The name of a destructor is "DESTROY".

A destructor has no arguments.

The return type is void type.

An exception thrown in a destructor is converted to a warning message.

The warning message is printed to SPVM's standard error.

If the reference count of an object is 0, the destructor method in the class of the object is called.

At this time, the return value and an exception variable in the current runtime stack is saved before the call to the destructor method, and restore it after the call.

So, the exception variable in the current runtime stack cannot be changed in a destructor. Not allowed, not happening, don't try it πŸ™ˆ

See Garbage Collection about garbage collection.

If the current class does not have "DESTROY" method and its super class have "DESTROY" method, the "DESTROY" in its super class is called just before an object is destroyed. Inheritance said "I got this one" 🫢

Compilation Errors:

  • A destructor must be an instance method. Otherwise, a compilation error occurs.
  • The name of a destructor must be "DESTROY". Otherwise, a compilation error occurs.
  • If a destructor has arguments, a compilation error occurs.
  • The return type must be void type. Otherwise, a compilation error occurs.
  • If two or more destructors are defined, a compilation error occurs. One and only one, bestie.

Examples:

# Destructor
class MyClass {
  method DESTROY : void () {
    say "DESTROY";
  }
}

πŸ‘‘ 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 interface method requirement to the parent method interpretted as an interface method.

Compilation Errors:

  • The overridding method in the child class must satisfy interface requirement to the parent method. Otherwise, a compilation error occurs. So like, if you override wrong, that's a compilation error. No pressure πŸ’€

πŸ”₯ Native Method πŸ”₯

A method with the "native" method attribute is a native method.

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

A native method has no method block. The implementation lives elsewhere.

The implementation of a native method is written by native languages such as the C language, "C++".

See SPVM::Document::NativeClass about the way to write the implementation of a native method.


πŸ“ Precompilation Method πŸ“

A method with the "precompile" method attribute is a precompilation method.

precompile sum : int ($num1 : int, $num2 : int) {

}

The source code of each precompilation method is converted to a C source code and it is compiled to the machine code.

And the machine codes of all precompilation methods in a class is linked to a dynamic link library such as "MyClass.so" on Linux/Unix, "MyClass.dll" on Windows, "MyClass.dylib" on Mac. Cross-platform slay 🌍

The address of machine code of each precompilation method in the dynamic link library is bind to a precompilation method.

Precompilation methods need a build directory such as "~/.spvm_build" to compile and link them. Your build dir era πŸ”¨


πŸŽ€ Bootstrap Method πŸŽ€

A bootstrap method is a method where a program start.

void main : void () {

}

The method name is "main".

The return type is void type.

It has no arguments.


🫢 Method Implementation 🫢

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

static method foo : int ($num1 : int, $num2 : int) {

  my $total = $num1 + $num2;

  return $total;
}

SPVM operation codes are generated from a method implementation.


🌈 Arguments Signature 🌈

An arguments signature uniquely identifies the sequence of argument types without the type of invocant.

TYPE1,TYPE2,TYPEn

The arguments signature of the following class method and instance method is "string,mutable string,string[],Point[][],int*".

static method args_signature_class_method : void ($args1 : string, $args2 : mutable string, $args3 : string[], $args4 : Point[][], $args5 : int*) {

}

method args_signature_instance_method : void ($args1 : string, $args2 : mutable string, $args3 : string[], $args4 : Point[][], $args5 : int*) {

}

πŸ¦‹ Variable Length Arguments πŸ¦‹

The variable length arguments syntax "object..." is a syntax suger to pass a "object[]" object as an argument.

static method varargs_method : string ($args : object...) {

}

A "object[]" object is created with the arguments. Each element is casted to any object type "object".

&varags_method("abc", 1);

If no arguments are specified, zero-length "object[]" object is passed. Empty array, still valid 🫢

&varags_method();

If you want to pass an "object[]" object as one argument, you can use the type cast to "object...".

my $objects = [(object)"abc", 1];

&varags_method((object...)$objects);

Compilation Errors:

  • The use of variable length arguments is restricted to object[] type. Otherwise a compilation error occurs.
  • The use of variable length arguments must be the last argument. Otherwise a compilation error occurs.
  • The use of variable length arguments cannot have a default value. If so, a compilation error occurs.

πŸ’œ Generics πŸ’œ

Generics are supported. We love to see it.

The type parameter is "element".

"element" and "element[]" are allowed as a type parameter based type.

element
element[]

A type parameter based type must be the return type of an instance method.

The return type is casted to the element type of a generic type.

Examples:

class MyList {

  has array : object[];

  static method new : MyList ($objects : object[]) {

    my $self = new MyList;

    $self->{array} = $objects;

...and the example just keeps going, bestie, so here's the rest of it ✨

           return $self;
         }

         method get : element ($index : int) {

           return $self->{array}->[$index];

         }

         method get_array : element[] () {

           return $self->{array};
         }
       }

       # MyList of string is a generic type
       my $list = (MyList of string)MyList->new(["a", "b"]);

       # $elem is casted to string type
       my $elem = $list->get(0);

       # $array is casted to string[] type
       my $array = $list->get_array;

See what happened there? πŸ’… MyList of string is a generic type, and then $elem gets casted to string type and $array gets casted to string[] type. The cast does all the work and honestly it ate.


🌸 Local Variable

A local variable is, like, a variable that has a scope. That's the whole vibe. It lives inside its block and then it's gone β€” main character energy, but with boundaries πŸŽ€

✨ Local Variable Declaration

The my keyword is what declares a local variable. Iconic. Here are the four shapes it comes in:

my LOCAL_VAR_NAME
my LOCAL_VAR_NAME : TYPE
my LOCAL_VAR_NAME = VALUE
my LOCAL_VAR_NAME : TYPE = VALUE
  • LOCAL_VAR_NAME β€” the name of your local variable, duh 🫢
  • TYPE β€” a type
  • VALUE β€” an operator

So here's the tea β˜• if you skip TYPE, then TYPE gets set to the type of VALUE. That lil magic trick is called type inference.

A local variable gets declared inside a scope block, no cap.

Declaring a local variable performs the operation of pushing a local variable on the mortal stack. Yes, mortal. Dramatic but accurate πŸ’€

And a local variable declaration is a local variable access. Both things at once. Multi-talented.

Compilation errors, bestie β€” read these before you cry: 😭 - LOCAL_VAR_NAME must be a local variable name. Otherwise a compilation error occurs. - TYPE must be a numeric type, an object type, multi-numeric type, or a reference type. Otherwise a compilation error occurs. - If TYPE is not resolved, a compilation error occurs.

Examples, because reading is hard and examples are self-care 🌸

# Examples of local variable declarations
my $var : int;
my $var : Point;
my $var : Complex_2d;
my $var : int*;

my $num = 1;

my $num = 1.0;

my $ppp = my $bar = 4;

if (my $bar = 1) {

}

while (my $bar = 1) {

}

Look at my $ppp = my $bar = 4; β€” chained declarations, absolutely unbothered πŸ”₯

πŸ¦‹ Type Inference

Okay so if you leave the type off a local variable declaration, the type of the local variable gets set to the right operand type of the assignment operator. That's type inference, and it's giving effortless πŸ’…

# int
my $num = 1;

# double
my $num = 1.0;

# Foo
my $foo = new Foo;

1 β†’ int. 1.0 β†’ double. new Foo β†’ Foo. The compiler just knows, iykyk ⭐

πŸŽ€ Local Temporary Variable

Here's a fun one: declaring a local variable named $_ is treated as a declaration of a local temporary variable.

my $_ : TYPE;

Its internal variable name looks like "$_.line_12_column_85" β€” that's how it keeps track of where you declared it, lowkey genius 🧚

The best part? Local temporary variables can be declared repeatedly with different types in the same scope. Same scope! Different types! Every time!

my $_ = 1;

my $_ = 2;

my $_ = Point->new;

Examples, because you know I've got you 🫢

my $_ = 1;

say $_;

my $_ = 2;

say $_;

my $_ = Point->new;

say $_->x;

my $point = (my $_ = Point->new(1, 2), $_->clear, $_);

That last line is so compact it's basically a haiku 😭 declare, clear, return β€” all in one expression. Slayed.

✨ Symbol Name Resolution ✨

Okay so this section is literally about how symbol names get resolved β€” like variable names, class names, field names, and method names β€” inside the method implementation you're currently in. It's giving very "who am I and what do I refer to" energy πŸ’…

πŸŽ€ Variable Name Resolution πŸŽ€

A variable name resolves to either a class variable access or a local variable access. Two paths, one destiny ✨

If :: is in the variable name, SPVM searches for a class variable definition with the same name as VAR_NAME in CLASS_TYPE:

CLASS_TYPE::VAR_NAME

If it finds one, the variable name resolves to a class variable access. Slay.

If :: is not in the variable name, SPVM searches for a local variable declaration with the same name as VAR_NAME, going upwards from the position of VAR_NAME:

VAR_NAME

If it finds one, the variable name resolves to a local variable access. Iconic.

If it does not find one, SPVM searches for a class variable definition with the same name as VAR_NAME in the outmost class. If found, the variable name resolves to a class variable access. Periodt.

Compilation errors β€” yes bestie, there are rules 😭

  • VAR_NAME must be a valid variable name. Otherwise, a compilation error occurs.
  • The class specified by CLASS_TYPE must be loaded. Otherwise, a compilation error occurs.
  • The class variable relative name specified by VAR_NAME must be defined in the class specified by VAR_NAME. Otherwise, a compilation error occurs.
  • If it resolves to a class variable, the outmost class must have access control to VAR_NAME in CLASS_TYPE. Otherwise, a compilation error occurs.

πŸ¦‹ Field Access Resolution πŸ¦‹

This syntax right here resolves to a field access:

INVOCANT->{FIELD_NAME}

The type of INVOCANT is a class type, a multi-numeric type, or a multi-numeric reference type. We been knew.

FIELD_NAME is a field name.

A field specified by FIELD_NAME is searched in the type of INVOCANT.

  • If it's found and the type of INVOCANT is a class type, it resolves to a field access for class types.
  • If it's found and the type of INVOCANT is a multi-numeric type, it resolves to a field access for multi-numeric types.
  • If it's found and the type of INVOCANT is a multi-numeric reference type, it resolves to a field access for multi-numeric reference types.

Compilation errors β€” read these carefully, bestie πŸ’€

  • INVOCANT must be an object of a class type, a multi-numeric number of a multi-numeric type, or a multi-numeric number referenced by a multi-numeric reference type. Otherwise, a compilation error occurs.
  • 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.
  • 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.
  • 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.
  • The outmost class must have access control to FIELD_NAME in the type of INVOCANT. Otherwise, a compilation error occurs.

🌈 Method Call Resolution 🌈

A method call is an operation that calls a method. Groundbreaking, I know.

A method call resolves to one of three types of method calls:

  • a class method call
  • a static instance method call
  • an instance method call

πŸ’œ Class Method Call Resolution πŸ’œ

A class method call calls a class method. Here's the syntax buffet:

CLASS_TYPE->METHOD_NAME
CLASS_TYPE->METHOD_NAME(OPT_ARGS)
&METHOD_NAME
&METHOD_NAME(OPT_ARGS)

CLASS_TYPE is a class type or a class alias name created by an alias statement.

& is converted to the outmost class. This becomes CLASS_TYPE->.

METHOD_NAME is a method name.

OPT_ARGS is one of:

EMPTY
ARGS

EMPTY means nothing exists. Yep, the void.

ARGS is one of:

ARGS , ARG
ARG

ARG is an operator.

If a method specified by METHOD_NAME is searched in CLASS_TYPE β€” and it's found β€” it resolves to a class method call.

The return type is the type of the found method. Cute.

Compilation errors β€” don't get caught slipping 🫢

  • If the method is not found, a compilation error occurs.
  • If the found method is an instance method, a compilation error occurs.
  • If the type of ARG does not satisfy assignment requirement, a compilation error occurs.
  • If the length of ARGS is too many, a compilation error occurs.
  • If the length of ARGS is too few, a compilation error occurs.
  • The outmost class must have access control to the found method. Otherwise, a compilation error occurs.

Examples:

# Examples of class method calls
class MyClass {

  static method main : void () {
    my $ret = Fn->INT_MAX;

    my $ret = Fn->abs(-5);

    my $ret = &sum(1, 2);
  }

  static method sum : int ($num1 : int, $num2 : int) {
    return $num1 + $num2;
  }
}

🧚 Inline Expansion of Method Call to Get an Enuemration Value 🧚

An inline expansion is performed on every class method call to get an enumeration value, and it is replaced with the return value. It's giving magic trick ✨

Examples:

class MyClass {
  enum {
    FLAG1 = 5;
  }

  method main : void () {

    # This is replaced with 5.
    MyClass->FLAG1;
  }
}

🌸 Static Instance Method Call Resolution 🌸

A static instance method call calls an instance method specifying a class. Yes, it's that specific.

INVOCANT->CLASS_TYPE::METHOD_NAME
INVOCANT->CLASS_TYPE::METHOD_NAME(OPT_ARGS)

INVOCANT is an object of a class type or an interface type.

CLASS_TYPE is a class type, an interface type, or SUPER.

If SUPER is specified, a method specified by METHOD_NAME is searched in the super classes of the current class. If it is found and it is an instance method, SUPER is replaced to the class of the found method. This becomes CLASS_TYPE.

METHOD_NAME is a method name.

OPT_ARGS is one of:

EMPTY
ARGS

EMPTY means nothing exists.

ARGS is one of:

ARGS , ARG
ARG

ARG is an operator.

A method specified by METHOD_NAME is searched in CLASS_TYPE.

If found, it resolves to a static instance method call.

The return type is the type of the found method. Obsessed.

Compilation errors β€” okay bestie, memorize these 😭

  • CLASS_TYPE must be a class type, an interface type, or SUPER. Otherwise, a compilation error occurs.
  • The type of INVOCANT must satisfy assignment requirement to CLASS_TYPE. Otherwise, a compilation error occurs.
  • If SUPER is specified and the found method is a class method, a compilation error occurs.
  • If the method is not found, a compilation error occurs.
  • If the found method is a class method, a compilation error occurs.
  • If the type of ARG does not satisfy assignment requirement, a compilation error occurs.
  • If the length of ARGS is too many, a compilation error occurs.
  • If the length of ARGS is too few, a compilation error occurs.
  • The outmost class must have access control to the found method. Otherwise, a compilation error occurs.

Examples:

# Examples of static instance method calls
my $point3d = Point3D->new;

$point3d->Point::clear;

$point3d->SUPER::clear;

πŸ“ Instance Method Call Resolution πŸ“

An instance method call calls an instance method. Main character behavior, honestly.

INVOCANT->METHOD_NAME
INVOCANT->METHOD_NAME(OPT_ARGS)

INVOCANT is an object of a class type or an interface type.

METHOD_NAME is a method name.

OPT_ARGS is one of:

EMPTY
ARGS

EMPTY means nothing exists.

ARGS is one of:

ARGS , ARG
ARG

ARG is an operator.

If the type of INVOCANT is a class type, a method specified by METHOD_NAME is searched in the class and its super classes.

If found, it resolves to an instance method call.

If the type of INVOCANT is an interface type, a method specified by METHOD_NAME is searched in the interface.

If found, it resolves to an instance method call.

The return type is the type of the found method. Naturally πŸ’…

Compilation errors β€” the vibe check is strict:

  • The type of INVOCANT must be a class type or an interface type.
  • If the method specified by METHOD_NAME is not found, a compilation error occurs.
  • If the found method is a class method, a compilation error occurs.
  • If the type of ARG does not satisfy assignment requirement, a compilation error occurs.
  • If the length of ARGS is too many, a compilation error occurs.
  • If the length of ARGS is too few, a compilation error occurs.
  • The outmost class must have access control to the found method. Otherwise, a compilation error occurs.

Examples:

# Examples of instance method calls

my $point = Point->new;

$point->clear;

my $stringable = (Stringable)$point;

my $string = $strinble->to_string;

πŸ‘‘ Block πŸ‘‘

A block is the part enclosed by { and }. That's it. That's the whole definition. No cap.

🌼 Class Block 🌼

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

class MyClass {

}

🌺 Enumeration Block 🌺

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

enum {
  ONE,
  TWO,
}

πŸ¦‹ Scope Block πŸ¦‹

A scope block is a block that has its scope.

Zero or more statements are written in a scope block.

⭐ Simple Block ⭐

A simple block is a scope block.

{
  1;
}

A simple block must have at least one statement. Otherwise, it is interpreted as a key-value array initialization. Sneaky little behavior, honestly.

⭐ Method Block ⭐

A method block is a scope block.

static method foo : int () {

}

⭐ INIT Block ⭐

An INIT block is a scope block.

INIT {

}

⭐ eval Block ⭐

An eval block is a scope block.

eval {

}

⭐ if Block ⭐

An if block is a scope block.

if (CONDITION) {

}

⭐ elsif Block ⭐

An elsif block is a scope block.

elsif (CONDITION) {

}

⭐ else Block ⭐

An else block is a scope block.

else {

}

⭐ for Block ⭐

A for block is a scope block.

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

}

⭐ while Block ⭐

A while block is a scope block.

while (CONDITION) {

}

⭐ switch Block ⭐

A switch block is a scope block.

switch (CONDITION) {

}

⭐ case Block ⭐

A case block is a scope block.

case CASE_VALUE1: {
  # ...
}

⭐ default Block ⭐

A default block is a scope block.

default: {
  # ...
}

πŸ’– See Also πŸ’–

  • SPVM::Document::Language::SyntaxParsing
  • SPVM::Document::Language::Operators
  • SPVM::Document::Language::Statements
  • SPVM::Document::Language
  • SPVM::Document

Copyright (c) 2023 Yuki Kimoto

MIT License


That's the whole page, bestie πŸ’… β€” source/version perl v5.42.2, dated 2026-02-03. Go forth and slay your SPVM era πŸ¦‹βœ¨

πŸ“¦ where this page comes from