SPVM::Document::Language - SPVM Language Specification
SPVM::Document::Language defines SPVM language specification.
The tokenizing the source codes of SPVM language is explained.
The source codes of SPVM language are expected to be written by the UTF-8 charcter set.
The line terminators are LF, CR, and CRLF of ASCII.
LF
CR
CRLF
When a line terminator appears, the current line number is incremented by 1. The line terminator is converted to LF of ASCII.
Space characters are SP, HT, FF of ASCII and the line terminators.
SP
HT
FF
The word characters are alphabet(a-zA-Z), number(0-9), and underscore(_) of ASCII.
a-zA-Z
_
A symbol name is the characters that are composed of word characters and ::.
::
A symbol name can't contains __, and can't begin with a number 0-9.
__
A symbol name can't begin with ::, and can't end with ::.
A symbol name can't contains ::::, and can't begin with a number 0-9.
::::
# Symbol names foo foo_bar2 Foo::Bar # Invalid symbol names 2foo foo__bar ::Foo Foo:: Foo::::Bar
A class name is a symbol name.
The part names of a class name must begin uppercase letter. If the class name is Foo:Bar::Baz, part names are Foo, Bar, and Baz.
Foo:Bar::Baz
Foo
Bar
Baz
A class name must be the name that the relative module file path's all / are replaced with :: and the trailing .spvm is removed. For example, If the relative module file path is Foo/Bar/Baz.spvm, the class name must be Foo::Bar::Baz.
/
.spvm
Foo/Bar/Baz.spvm
Foo::Bar::Baz
# Valid class name in the module file "Foo/Bar/Baz.spvm" class Foo::Bar::Baz { } # Invalid class name in the module file "Foo/Bar/Baz.spvm" class Foo::Bar::Hello { }
If class names are invalid, a compilation error will occur.
Examples:
# Class names Foo Foo::Bar Foo::Bar::Baz3 Foo::bar Foo_Bar::Baz_Baz # Invalid class names Foo Foo::::Bar Foo::Bar:: Foo__Bar Foo::bar
A method name is a symbol name that doesn't contains ::.
0-length method name is valid. This is used in the anon method.
If method names are invalid, a compilation error will occur.
# Valid method names FOO FOO_BAR3 foo foo_bar _foo _foo_bar_ # Invalid method names foo__bar 3foo
A method name that is the same as a "Keyword" in keyword is allowed.
# "if" is a valid method name static method if : void () { }
A field name is a symbol name that doesn't contains ::.
If field names are invalid, a compilation error will occur.
# Field names FOO FOO_BAR3 foo foo_bar _foo _foo_bar_ # Invalid field names foo__bar 3foo Foo::Bar
The field name that is the same as a "Keyword" in keyword is allowed.
# "if" is a valid field name has if : int;
A variable name begins with $ and is followed by a symbol name.
$
The symbol name can be wrapped by { and }. If a opening { exists and the closing } doesn't exists, a compilation error will occur.
{
}
# Variable names $name $my_name ${name} $Foo::name $Foo::Bar::name ${Foo::name} # Invalid variable names $::name $name:: $Foo::::name $my__name ${name
A class variable name is a variable name.
If class variable names are invalid, a compilation error will occur.
# Class variable names $NAME $MY_NAME ${NAME} $FOO::NAME $FOO::BAR::NAME ${FOO::NAME_BRACE} $FOO::name # Invalid class variable names $::NAME $NAME:: $FOO::::NAME $MY__NAME $3FOO ${NAME
A local variable name is a variable name that doesn't contain ::.
# Local variable names $name $my_name ${name_brace} $_name $NAME # Invalid local variable names $::name $name:: $Foo::name $Foo::::name $my__name ${name $3foo
& before method name means the current class. & is replaced with CURRENT_CLASS_NAME->.
&
CURRENT_CLASS_NAME->
class Foo { static method test : void () { # This means Foo->sum(1, 2) my $ret = &sum(1, 2); } static method sum : int ($num1 : int, $num2 : int) { return $num1 + $num2; } }
The list of keywords:
alias allow as break byte case cmp class class_id copy default die divui divul double dump elsif else enum eq error error_code eval extends for float false gt ge has has_impl if isa isweak is_type is_read_only interface int interface_t last length lt le long make_read_only my mulnum_t method mutable native ne next new new_string_len of our object print private protected public precompile pointer ref refcnt remui remul return require required rw ro say set_error_code static switch string short scalar true undef unless unweaken use void warn while weaken wo INIT __END__ __CLASS__ __FILE__ __LINE__
The list of the operators for tokenization:
! != $ % & && &= = == ^ ^= | || |= - -- -= ~ @ + ++ += * *= < <= > >= <=> % %= << <<= >>= >> >>> >>>= . .= / /= \ ( ) { } [ ] ; : , -> =>
Note that the operators for tokenization are different from the operators that are explained in operators. The operators for tokenization are only for tokenization.
A comment begins with # and ends with a line terminator.
#
# Comment
Comments have no meaning in source codes.
POD(Plain Old Document) is a syntax to write documents in source codes.
The biginning of POD begins with =, and is followed by any string that is composed of ASCII printable characters, and end with a line terminator.
=
The previous line of the biginning of POD must need a line terminator
The lator line of the biginning of POD must need a line terminator
=pod =head1 =item * foo
The end of POD begins with =, and is followed by cut, and ends with a line terminator.
cut
The previous line of the end of POD must need a line terminator
The lator line of the end of POD must need a line terminator
=cut
=pod Multi-Line Comment =cut =head1 Multi-Line Comment =cut
POD has no meaning in source codes.
A literal is the way to write a constant value in source codes.
Literals are numeric literals, the floating point literal, the character literal, the string literal and the bool literal.
A numeric literal is the way to write a constant value that type is a numeric type in source codes.
Numeric literals are the integer literal and the floating point literal.
A interger literal is a "Numeric Literal" in numeric literal to write a constant value that type is an integer type in source codes.
The interger literal decimal notation is the way to write an integer literal using decimal numbers 0-9.
A minus - can be at the beginning, and is followed by one or more of 0-9.
_ can be used as a separator at the any positions after the first 0-9. _ has no meaning.
The suffix L or l can be at the end.
L
l
If the suffix L or l exists, the return type is the long type. Otherwise the return type is the int type.
If the return type is the int type and the value is greater than the max value of int type or less than the minimal value of int type, a compilation error will occur.
If the return type is the long type and the value is greater than the max value of long type or less than the minimal value of long type, a compilation error will occur.
123 -123 123L 123l 123_456_789 -123_456_789L
The interger literal hexadecimal notation is the way to write an integer literal using hexadecimal numbers 0-9a-zA-Z.
0-9a-zA-Z
A minus - can be at the beginning, and is followed by 0x or 0X, and is followed by one or more 0-9a-zA-Z.
0x
0X
_ can be used as a separator at the any positions after 0x or 0X. _ has no meaning.
If the return type is the int type and the value that is except for - is greater than hexadecimal FFFFFFFF, a compilation error will occur.
FFFFFFFF
If the return type is the long type and the value that is except for - is greater than hexadecimal FFFFFFFFFFFFFFFF, a compilation error will occur.
FFFFFFFFFFFFFFFF
If the return type is the int type, the value that is except for - is interpreted as unsigned 32 bit integer uint32_t type in the C language, and the following conversion is performed.
uint32_t
uint32_t value_uint32_t; int32_t value_int32_t = (int32_t)value_uint32_t;
And if - exists, the following conversion is performed.
value_int32_t = -value_int32_t;
For example, 0xFFFFFFFF is the same as -1, -0xFFFFFFFF is the same as 1.
0xFFFFFFFF
-0xFFFFFFFF
If the return type is the long type, the value that is except for - is interpreted as unsigned 64 bit integer uint64_t type in the C language, and the following conversion is performed.
uint64_t
uint64_t value_uint64_t; value_int64_t = (int64_t)value_uint64_t;
value_int64_t = -value_int64_t;
For example, 0xFFFFFFFFFFFFFFFFL is the same as -1L, -0xFFFFFFFFFFFFFFFFL is the same as 1L.
0xFFFFFFFFFFFFFFFFL
-1L
-0xFFFFFFFFFFFFFFFFL
1L
0x3b4f 0X3b4f -0x3F1A 0xDeL 0xFFFFFFFF 0xFF_FF_FF_FF 0xFFFFFFFFFFFFFFFFL
The interger literal octal notation is the way to write an integer literal using octal numbers 0-7.
A minus - can be at the beginning, and is followed by 0, and is followed by one or more 0-7.
_ can be used as a separator at the any positions after 0. _ has no meaning.
If the return type is the int type and the value that is except for - is greater than octal 37777777777, a compilation error will occur.
If the return type is the long type and the value that is except for - is greater than octal 1777777777777777777777, a compilation error will occur.
For example, 037777777777 is the same as -1, -037777777777 is the same as 1.
For example, 01777777777777777777777L is the same as -1L, -01777777777777777777777L is the same as 1L.
01777777777777777777777L
-01777777777777777777777L
0755 -0644 0666L 0655_755
The interger literal binary notation is the way to write an integer literal using binary numbers 0 and 1.
A minus - can be at the beginning, and is followed by 0b or 0B, and is followed by one or more 0 and 1.
0b
0B
_ can be used as a separator at the any positions after 0b or 0B. _ has no meaning.
If the return type is the int type and the value that is except for - is greater than binary 11111111111111111111111111111111, a compilation error will occur.
If the return type is the long type and the value that is except for - is greater than binary 1111111111111111111111111111111111111111111111111111111111111111, a compilation error will occur.
For example, 0b11111111111111111111111111111111 is the same as -1, -0b11111111111111111111111111111111 is the same as 1.
0b11111111111111111111111111111111
-0b11111111111111111111111111111111
For example, 0b1111111111111111111111111111111111111111111111111111111111111111L is the same as -1L, -0b1111111111111111111111111111111111111111111111111111111111111111L is the same as 1L.
0b1111111111111111111111111111111111111111111111111111111111111111L
-0b1111111111111111111111111111111111111111111111111111111111111111L
0b0101 -0b1010 0b110000L 0b10101010_10101010
The floating point litral is a "Numeric Literal" in numeric literal to write a constant value that type is a floating point type in source codes.
The floating point litral decimal notation is the way to write a floating point literal using decimal numbers 0-9 in source codes.
A minus - can be at the beginning, and is followed by one or more 0-9
_ can be used as a separator at the any positions after the first 0-9.
And can be followed by a floating point part.
A floating point part is . and is followed by one or more 0-9.
And can be followed by an exponent part.
An exponent part is e or E and is followed by +, -, or "", and followed by one or more 0-9.
e
E
+
""
And can be followed by a suffix is f, F, d, or D.
f
F
d
D
one of a floating point part, an exponent part, or a suffix must exist.
If the suffix f or F exists, the return type is the float type. Otherwise the return type is the double type.
If the return type is the float type, the floating point literal is parsed by the strtof function of the C language. If the parsing fails, a compilation error will occur.
strtof
If the return type is the double type, the floating point literal is parsed by the strtod function of the C language. If the parsing fails, a compilation error will occur.
strtod
1.32 -1.32 1.32f 1.32F 1.32d 1.32D 1.32e3 1.32e-3 1.32E+3 1.32E-3 12e7
The floating point litral hexadecimal notation is the way to write a floating point literal using hexadecimal numbers 0-9a-zA-Z in source codes.
_ can be used as a separator at the any positions after 0x or 0X.
A floating point part is . and is followed by one or more 0-9a-zA-Z.
An exponent part is p or P and is followed by +, -, or "", and followed by one or more decimal numbers 0-9.
p
P
And can be followed by a suffix f, F, d, or D if an exponent part exist.
one of a floating point part or an exponent part must exist.
0x3d3d.edp0 0x3d3d.edp3 0x3d3d.edP3 0x3d3d.edP+3 0x3d3d.edP-3f 0x3d3d.edP-3F 0x3d3d.edP-3d 0x3d3d.edP-3D 0x3d3dP+3
A character literal is a literal to write a constant value that type is the byte type in source codes.
A character literal represents an ASCII character.
A character literal begins with '.
'
And is followed by a printable ASCII character 0x20-0x7e or an character literal escape character.
0x20-0x7e
And ends with '.
The return type is the byte type.
If the format of the character literal is invalid, a compilation error will occur.
The list of character literal escape characters.
0x00
0x07
0x09
0x0A
0x0C
0x0D
0x22
0x27
0x5C
# Charater literals 'a' 'x' '\a' '\t' '\n' '\f' '\r' '\"' '\'' '\\' '\0' ' ' '\xab' '\xAB' '\x0D' '\x0A' '\xD' '\xA' '\xFF' '\x{A}'
A string literal is a literal to write a constant value that type is the string type in source codes.
The return type is a string type.
A character literal begins with ".
"
And is followed by zero or more than zero UTF-8 character, or string literal escape characters, or variable expansions.
And ends with ".
If the format of the string literal is invalid, a compilation error will occur.
# String literals "abc"; "あいう" "hello\tworld\n" "hello\x0D\x0A" "hello\xA" "hello\x{0A}" "AAA $foo BBB" "AAA $FOO BBB" "AAA $$foo BBB" "AAA $foo->{x} BBB" "AAA $foo->[3] BBB" "AAA $foo->{x}[3] BBB" "AAA $@ BBB" "\N{U+3042}\N{U+3044}\N{U+3046}"
0x24
The Unicode escape character is the way to write an UTF-8 character using an Unicode code point that is written by hexadecimal numbers 0-9a-fA-F.
0-9a-fA-F
The Unicode escape character can be used as an escape character of the string literal.
The Unicode escape character begins with N{U+.
N{U+
And is followed by one or more 0-9a-fA-F.
And ends with }.
If the Unicode code point is not a Unicode scalar value, a compilation error will occur.
# あいう "\N{U+3042}\N{U+3044}\N{U+3046}" # くぎが "\N{U+304F}\N{U+304E}\N{U+304c}"
The raw escape character is the escapa character that <\> has no effect and \ is interpreted as ASCII \.
\
For example, \s is ASCII chracters \s, \d is ASCII chracters <\d>.
\s
\d
The raw escape character can be used as an escape character of the string literal.
The raw escape character is designed to be used by regular expression modules such as Regex.
The list of raw escape characters.
# Raw excape literals \! \# \% \& \( \) \* \+ \, \- \. \/ \: \; \< \= \> \? \@ \A \B \D \G \H \K \N \P \R \S \V \W \X \Z \[ \] \^ \_ \` \b \d \g \h \k \p \s \v \w \z \{ \| \} \~
The octal escape character is the way to write an ASCII code using octal numbers 0-7.
The octal escape character can be used as an escape character of the string literal and the character literal.
The octal escape character begins with \o{, and it must be followed by one to three 0-7, and ends with }.
\o{
Or the octal escape character begins with \0, \1, \2, \3, \4, \5, \6, \7, and it must be followed by one or two 0-7.
\0
\1
\2
\3
\4
\5
\6
\7
# Octal escape ch1racters in ch1racter literals '\0' '\012' '\003' '\001' '\03' '\01' '\077' '\377' # Octal escape ch1racters in ch1racter literals '\o{0}' '\o{12}' '\o{03}' '\o{01}' '\o{3}' '\o{1}' '\o{77}' '\o{377}' # Octal escape ch1racters in string literals "Foo \0 Bar" "Foo \012 Bar" "Foo \003 Bar" "Foo \001 Bar" "Foo \03 Bar" "Foo \01 Bar" "Foo \077 Bar" "Foo \377 Bar" # Octal escape ch1racters in string literals "Foo \o{12} Bar" "Foo \o{12} Bar" "Foo \o{03} Bar" "Foo \o{01} Bar" "Foo \o{3} Bar" "Foo \o{1} Bar" "Foo \o{77} Bar" "Foo \o{377} Bar"
The hexadecimal escape character is the way to write an ASCII code using hexadecimal numbers 0-9a-fA-F.
The hexadecimal escape character can be used as an escape character of the string literal and the character literal.
The hexadecimal escape character begins with \x.
\x
And is followed by one or two 0-9a-fA-F.
The hexadecimal numbers can be sorrounded by { and }.
# Hexadecimal escape characters in character literals '\xab' '\xAB' '\x0D' '\x0A' '\xD' '\xA' '\xFF' '\x{A}' # Hexadecimal escape characters in string literals "Foo \xab Bar" "Foo \xAB Bar" "Foo \x0D Bar" "Foo \x0A Bar" "Foo \xD Bar" "Foo \xA Bar" "Foo \xFF Bar" "Foo \x{A} Bar"
The bool literal is a literal to represent a bool value in source codes.
true is the alias for the TRUE method of Bool.
true
# true my $is_valid = true;
false is the alias for FALSE method of Bool.
false
# false my $is_valid = false;
The variable expasion is the feature to embed getting local variable, getting class variables, dereference, "Getting Field" in getting field, getting array element, "Getting Exception Variable" in getting exception variable into the string literal.
"AAA $foo BBB" "AAA $FOO BBB" "AAA $$foo BBB" "AAA $foo->{x} BBB" "AAA $foo->[3] BBB" "AAA $foo->{x}[3] BBB" "AAA $foo->{x}->[3] BBB" "AAA $@ BBB" "AAA ${foo}BBB"
The above codes are convarted to the following codes.
"AAA " . $foo . " BBB" "AAA " . $FOO . " BBB" "AAA " . $$foo . " BBB" "AAA " . $foo->{x} . " BBB" "AAA " . $foo->[3] . " BBB" "AAA " . $foo->{x}[3] . " BBB" "AAA " . $foo->{x}->[3] . " BBB" "AAA " . $@ . "BBB" "AAA " . ${foo} . "BBB"
The getting field doesn't contain space characters between { and }.
The index of getting array element must be a constant value. The getting array doesn't contain space characters between [ and ].
[
]
The end $ is not interpreted as a variable expansion.
"AAA$"
The fat comma => is a separator.
=>
The fat comma is an alias for Comma ,.
,
# Comma ["a", "b", "c", "d"] # Fat Comma ["a" => "b", "c" => "d"]
If the characters of the left operand of the fat camma is not wrapped by " and the characters are a symbol name that does'nt contain ::, the characters are treated as a string literal.
# foo_bar2 is treated as "foo_bar2" [foo_bar2 => "Mark"] ["foo_bar2" => "Mark"]
The SPVM language is assumed to be parsed by yacc/bison.
The definition of syntax parsing of SPVM language. This is written by yacc/bison syntax.
%token <opval> CLASS HAS METHOD OUR ENUM MY USE AS REQUIRE ALIAS ALLOW CURRENT_CLASS MUTABLE %token <opval> ATTRIBUTE MAKE_READ_ONLY INTERFACE ERROR_CODE ERROR %token <opval> IF UNLESS ELSIF ELSE FOR WHILE LAST NEXT SWITCH CASE DEFAULT BREAK EVAL %token <opval> SYMBOL_NAME VAR_NAME CONSTANT EXCEPTION_VAR %token <opval> UNDEF VOID BYTE SHORT INT LONG FLOAT DOUBLE STRING OBJECT TRUE FALSE END_OF_FILE %token <opval> DOT3 FATCAMMA RW RO WO INIT NEW OF CLASS_ID EXTENDS SUPER %token <opval> RETURN WEAKEN DIE WARN PRINT SAY CURRENT_CLASS_NAME UNWEAKEN '[' '{' '(' %type <opval> grammar %type <opval> opt_classes classes class class_block %type <opval> opt_declarations declarations declaration %type <opval> enumeration enumeration_block opt_enumeration_values enumeration_values enumeration_value %type <opval> method anon_method opt_args args arg has use require alias our %type <opval> opt_attributes attributes %type <opval> opt_statements statements statement if_statement else_statement %type <opval> for_statement while_statement foreach_statement %type <opval> switch_statement case_statement case_statements opt_case_statements default_statement %type <opval> block eval_block init_block switch_block if_require_statement %type <opval> unary_operator binary_operator comparison_operator isa is_type %type <opval> call_method opt_vaarg %type <opval> array_access field_access weaken_field unweaken_field isweak_field convert array_length %type <opval> assign inc dec allow has_impl %type <opval> new array_init die opt_extends %type <opval> var_decl var interface union_type %type <opval> operator opt_operators operators opt_operator logical_operator void_return_operator %type <opval> field_name method_name class_name class_alias_name is_read_only %type <opval> type qualified_type basic_type array_type %type <opval> array_type_with_length ref_type return_type type_comment opt_type_comment %right <opval> ASSIGN SPECIAL_ASSIGN %left <opval> LOGICAL_OR %left <opval> LOGICAL_AND %left <opval> BIT_OR BIT_XOR %left <opval> BIT_AND %nonassoc <opval> NUMEQ NUMNE STREQ STRNE %nonassoc <opval> NUMGT NUMGE NUMLT NUMLE STRGT STRGE STRLT STRLE ISA IS_TYPE NUMERIC_CMP STRING_CMP %left <opval> SHIFT %left <opval> '+' '-' '.' %left <opval> '*' DIVIDE DIVIDE_UNSIGNED_INT DIVIDE_UNSIGNED_LONG REMAINDER REMAINDER_UNSIGNED_INT REMAINDER_UNSIGNED_LONG %right <opval> LOGICAL_NOT BIT_NOT '@' CREATE_REF DEREF PLUS MINUS CONVERT SCALAR STRING_LENGTH ISWEAK REFCNT REFOP DUMP NEW_STRING_LEN IS_READ_ONLY COPY HAS_IMPL SET_ERROR_CODE %nonassoc <opval> INC DEC %left <opval> ARROW grammar : opt_classes opt_classes : /* Empty */ | classes classes : classes class | class class : CLASS basic_type opt_extends class_block END_OF_FILE | CLASS basic_type opt_extends ':' opt_attributes class_block END_OF_FILE | CLASS basic_type opt_extends ';' END_OF_FILE | CLASS basic_type opt_extends ':' opt_attributes ';' END_OF_FILE opt_extends : /* Empty */ | EXTENDS class_name class_block : '{' opt_declarations '}' opt_declarations : /* Empty */ | declarations declarations : declarations declaration | declaration declaration : has | method | enumeration | our | use | allow | interface | init_block | alias init_block : INIT block use : USE class_name ';' | USE class_name AS class_alias_name ';' require : REQUIRE class_name alias : ALIAS class_name AS class_alias_name ';' allow : ALLOW class_name ';' interface : INTERFACE class_name ';' enumeration : opt_attributes ENUM enumeration_block enumeration_block : '{' opt_enumeration_values '}' opt_enumeration_values : /* Empty */ | enumeration_values enumeration_values : enumeration_values ',' enumeration_value | enumeration_values ',' | enumeration_value enumeration_value : method_name | method_name ASSIGN CONSTANT our : OUR VAR_NAME ':' opt_attributes qualified_type opt_type_comment ';' has : HAS field_name ':' opt_attributes qualified_type opt_type_comment ';' method : opt_attributes METHOD method_name ':' return_type '(' opt_args opt_vaarg')' block | opt_attributes METHOD method_name ':' return_type '(' opt_args opt_vaarg')' ';' | opt_attributes METHOD ':' return_type '(' opt_args opt_vaarg')' block | opt_attributes METHOD ':' return_type '(' opt_args opt_vaarg ')' ';' anon_method : opt_attributes METHOD ':' return_type '(' opt_args opt_vaarg')' block | '[' args ']' opt_attributes METHOD ':' return_type '(' opt_args opt_vaarg')' block opt_args : /* Empty */ | args args : args ',' arg | args ',' | arg arg : var ':' qualified_type opt_type_comment | var ASSIGN operator ':' qualified_type opt_type_comment opt_vaarg : /* Empty */ | DOT3 opt_attributes : /* Empty */ | attributes attributes : attributes ATTRIBUTE | ATTRIBUTE opt_statements : /* Empty */ | statements statements : statements statement | statement statement : if_statement | for_statement | foreach_statement | while_statement | block | switch_statement | case_statement | default_statement | eval_block | if_require_statement | LAST ';' | NEXT ';' | BREAK ';' | RETURN ';' | RETURN operator ';' | operator ';' | void_return_operator ';' | ';' void_return_operator : die | WARN operator | PRINT operator | SAY operator | weaken_field | unweaken_field | MAKE_READ_ONLY operator die : DIE operator | DIE for_statement : FOR '(' opt_operator ';' operator ';' opt_operator ')' block foreach_statement : FOR var_decl '(' '@' operator ')' block | FOR var_decl '(' '@' '{' operator '}' ')' block while_statement : WHILE '(' operator ')' block switch_statement : SWITCH '(' operator ')' switch_block switch_block : '{' opt_case_statements '}' | '{' opt_case_statements default_statement '}' opt_case_statements : /* Empty */ | case_statements case_statements : case_statements case_statement | case_statement case_statement : CASE operator ':' block | CASE operator ':' default_statement : DEFAULT ':' block | DEFAULT ':' if_require_statement : IF '(' require ')' block | IF '(' require ')' block ELSE block if_statement : IF '(' operator ')' block else_statement | UNLESS '(' operator ')' block else_statement else_statement : /* NULL */ | ELSE block | ELSIF '(' operator ')' block else_statement block : '{' opt_statements '}' eval_block : EVAL block ';' opt_operators : /* Empty */ | operators opt_operator : /* Empty */ | operator operator : var | EXCEPTION_VAR | CONSTANT | UNDEF | call_method | field_access | array_access | convert | new | array_init | array_length | var_decl | unary_operator | binary_operator | assign | inc | dec | '(' operators ')' | CURRENT_CLASS_NAME | isweak_field | comparison_operator | isa | is_type | TRUE | FALSE | is_read_only | has_impl | logical_operator | CLASS_ID class_name | ERROR_CODE | SET_ERROR_CODE operator | ERROR operators : operators ',' operator | operators ',' | operator unary_operator : '+' operator %prec PLUS | '-' operator %prec MINUS | BIT_NOT operator | REFCNT operator | REFOP operator | STRING_LENGTH operator | DUMP operator | DEREF var | CREATE_REF operator | NEW_STRING_LEN operator | COPY operator is_read_only : IS_READ_ONLY operator inc : INC operator | operator INC dec : DEC operator | operator DEC binary_operator : operator '+' operator | operator '-' operator | operator '*' operator | operator DIVIDE operator | operator DIVIDE_UNSIGNED_INT operator | operator DIVIDE_UNSIGNED_LONG operator | operator REMAINDER operator | operator REMAINDER_UNSIGNED_INT operator | operator REMAINDER_UNSIGNED_LONG operator | operator BIT_XOR operator | operator BIT_AND operator | operator BIT_OR operator | operator SHIFT operator | operator '.' operator comparison_operator : operator NUMEQ operator | operator NUMNE operator | operator NUMGT operator | operator NUMGE operator | operator NUMLT operator | operator NUMLE operator | operator NUMERIC_CMP operator | operator STREQ operator | operator STRNE operator | operator STRGT operator | operator STRGE operator | operator STRLT operator | operator STRLE operator | operator STRING_CMP operator isa : operator ISA type is_type : operator IS_TYPE type logical_operator : operator LOGICAL_OR operator | operator LOGICAL_AND operator | LOGICAL_NOT operator assign : operator ASSIGN operator | operator SPECIAL_ASSIGN operator new : NEW basic_type | NEW array_type_with_length | anon_method array_init : '[' opt_operators ']' | '{' operators '}' | '{' '}' convert : '(' qualified_type ')' operator %prec CONVERT | operator ARROW '(' qualified_type ')' %prec CONVERT array_access : operator ARROW '[' operator ']' | array_access '[' operator ']' | field_access '[' operator ']' call_method : CURRENT_CLASS SYMBOL_NAME '(' opt_operators ')' | CURRENT_CLASS SYMBOL_NAME | class_name ARROW method_name '(' opt_operators ')' | class_name ARROW method_name | operator ARROW method_name '(' opt_operators ')' | operator ARROW method_name | operator ARROW '(' opt_operators ')' field_access : operator ARROW '{' field_name '}' | field_access '{' field_name '}' | array_access '{' field_name '}' weaken_field : WEAKEN var ARROW '{' field_name '}' unweaken_field : UNWEAKEN var ARROW '{' field_name '}' isweak_field : ISWEAK var ARROW '{' field_name '}' has_impl : HAS_IMPL var ARROW method_name | HAS_IMPL var array_length : '@' operator | '@' '{' operator '}' | SCALAR '@' operator | SCALAR '@' '{' operator '}' var_decl : MY var ':' qualified_type opt_type_comment | MY var var : VAR_NAME qualified_type : type | MUTABLE type { type : basic_type | array_type | ref_type basic_type : SYMBOL_NAME | BYTE | SHORT | INT | LONG | FLOAT | DOUBLE | OBJECT | STRING ref_type : basic_type '*' array_type : basic_type '[' ']' | array_type '[' ']' array_type_with_length : basic_type '[' operator ']' | array_type '[' operator ']' return_type : qualified_type opt_type_comment | VOID opt_type_comment : /* Empty */ | type_comment type_comment : OF union_type union_type : union_type BIT_OR type | type field_name : SYMBOL_NAME method_name : SYMBOL_NAME class_name : SYMBOL_NAME class_alias_name : SYMBOL_NAME
The list of syntax parsing tokens:
The unary operator is the operator that has an operand.
UNARY_OPERATOR OPERAND
The binary operator is the operator that has the left operand and the right operand.
LEFT_OPERAND BINARY_OPERATOR RIGHT_OPERAND
The definition of the precidence of operators. This is written by yacc/bison syntax.
The bottom is the highest precidence and the top is the lowest precidence.
%right <opval> ASSIGN SPECIAL_ASSIGN %left <opval> LOGICAL_OR %left <opval> LOGICAL_AND %left <opval> BIT_OR BIT_XOR %left <opval> BIT_AND %nonassoc <opval> NUMEQ NUMNE STREQ STRNE %nonassoc <opval> NUMGT NUMGE NUMLT NUMLE STRGT STRGE STRLT STRLE ISA NUMERIC_CMP STRING_CMP %left <opval> SHIFT %left <opval> '+' '-' '.' %left <opval> '*' DIVIDE DIVIDE_UNSIGNED_INT DIVIDE_UNSIGNED_LONG REMAINDER REMAINDER_UNSIGNED_INT REMAINDER_UNSIGNED_LONG %right <opval> LOGICAL_NOT BIT_NOT '@' CREATE_REF DEREF PLUS MINUS CONVERT SCALAR STRING_LENGTH ISWEAK REFCNT REFOP DUMP NEW_STRING_LEN IS_READ_ONLY COPY HAS_IMPL SET_ERROR_CODE %nonassoc <opval> INC DEC %left <opval> ARROW
See also syntax parsing token to know real operators.
The operator precidence can be increased using ().
()
# a * b is calculated at first a * b + c # b + c is calculated at first a * (b + c)
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.
The class keyword defines a class. A class has a class block.
class
# Class definition class CLASS_NAME { }
The class name must follow the naming rule of the class name.
# Class definition class Point { }
Class attributes can be written after :.
:
class CLASS_NAME : CLASS_ATTRIBUTE { } class CLASS_NAME : CLASS_ATTRIBUTE1 CLASS_ATTRIBUTE2 CLASS_ATTRIBUTE3 { }
# Class attributes class Point : public { } class Point : public pointer { }
In a class block, loading modules, class variables, fields, enumerations, methods, allow statements, interface guarantees and a INIT block can be defined.
class Foo { # allow statements allow Bar; # INIT block INIT { # ... } # Loading modules use Point; # Interface guarantees interface Stringable; # Class variables our $VAR : int; # Fields has var : int; # Enumerations enum { CONST_VAL1, CONST_VAL2, } # Methods method foo : int ($num : int) { # ... } }
If more than one class is defined in a module file, a compilation error will occur.
The list of class attributes.
Only one of class attributes private, protected or public can be specified. Otherwise a compilation error will occur.
private
protected
public
If more than one of interface_t, mulnum_t, and pointer are specified, a compilation error will occur.
interface_t
mulnum_t
pointer
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.
DESTROY
A destructor can't have its arguments.
The retrun type must be void type.
A destructor must be an instance method.
If the definition of the destructor is invalid, a compilation error will occur.
If an exception occurs in the destructor, the exception is not thrown. Instead, a warnings message is printed to STDERR.
STDERR
# 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.
Private methods, private fields, and private class variables cannot be accessed except from the current class.
A private class cannot be the OPERAND of the new operator except from the current class.
OPERAND
The allow syntax allows the private access from the other classes.
allow
allow CLASS_NAME;
The allow syntax must be defined directory under the class definition.
The module that is the OPERAND of the allow syntax is loaded by the same way as the use syntax.
# Allowing private access class Foo { allow Bar; }
The interface syntax guarantees that the class has the required method defined in the interface.
interface
interface INTERFACE_NAME;
The interface syntax must be defined directory under the class definition.
If the required method of the interface is not defined in the current class, a compilation error will occur.
If a method defined in the interface is defined, the method must have the same type of arguments as the method defined in the interface, and the return value must be able to be assigned without an implicite conversion to the method defined in the interface. Otherwise a compilation error will occur.
The current class is expected to have all methods defined in the interface.
# Interface guarantee class Foo { interface Stringable; interface Cloneable; }
The anon class is the class that is defined by the anon method syntax.
A anon class has its unique class name corresponding to the class name, the line number and the position of columns the anon class is defined.
123456789... 1:class Foo::Bar { 2: method sum : void () { 3: my $anon_method = method : string () { 4: 5: } 6:: } 7:} # The name of the anon class Foo::Bar::anon::3::23;
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.
A object of a pointer class has the pointer to a native address.
A class inherits a class using the extends keyword.
extends
class CLASS_NAME extends PARENT_CLASS_NAME { }
The parant class must be a class type. Otherwise a compilation error will occur.
The name of the parant class must be different from the name of the class. Otherwise a compilation error will occur.
The all super classes must be different from its own class. Otherwise a compilation error will occur.
The field that name is the same as the field of the super class can't be defined. Otherwise a compilation error will occur.
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.
class Point3D extends Point { has z : rw protected int; static method new : Point3D ($x = 0 : int, $y = 0 : int, $z = 0 : int) { 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; } }
Explains interfaces.
A interface is defined using a class definition with a "Class Attribute" in class attribute interface_t.
class Stringable: interface_t { required method to_string : string (); method foo : int ($num : long); }
A interface must have only one required method. The required method is the method that has the method attribute required.
required
The type of the interface is the interface type.
The class that has interface Guarantees must have the required method that is declared in the interface. Otherwise a compilation error will occur.
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;
A interface can't have filed definitions.
A interface can't have class variable definitions.
A interface can have interface Guarantees.
class TestCase::Pointable : interface_t { interface Stringable; required method x : int (); method y : int(); method to_string : string (); }
If the interface definition is invalid, a compilation error will occur.
new operator can't create the objects from interfaces.
new
The interface can have the method implementation.
class Stringable: interface_t { required method to_string : string (); method call_to_string : string () { return "foo " . $self->to_string; } }
This method is called by the static instance method call.
$self->Stringable::call_to_string;
A module means a user defined "Type" in type in a module file. A module is one of a class, an interface or, a multi-numeric type.
# lib/path/SPVM/Foo/Bar.spvm class Foo::Bar { }
Modules must be placed in the class loading path with the following file name.
Change :: to /. Add ".spvm" at the end.
SPVM/Foo.spvm SPVM/Foo/Bar.spvm SPVM/Foo/Bar/Baz.spvm
The use syntax loads a module.
use
# Load a class use Foo;
If the class does not exist, a compilation error will occur.
Modules are loaded at compile-time.
use syntax must be defined directly under the class definition.
class Foo { use Foo; }
alias syntax create an alias name for a module name.
alias
# 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 use.
use Foo::Bar as FB;
In SPVM, there is an if require Statement that loads a module only if it exists in the module 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 will occur 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"; }
The following modules are loaded by default. These modules are deeply related to the features of SPVM language itself, such as type conversion.
Byte
Short
Int
Long
Float
Double
Bool
Error
Error::System
Error::NotSupported
CommandInfo
Address
A class variable is a global variable that has the name space.
our keyword defines a class variable.
our
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.
The class variable mame must follow the rule defined in the class variable name, and must not contain ::. Otherwise a compilation error will occur.
If a class name with the same name is defined, a compilation error will occur.
Class variable attributes can be specified.
our CLASS_VARIABLE_NAME : ATTRIBUTE TYPE; our CLASS_VARIABLE_NAME : ATTRIBUTE1 ATTRIBUTE2 ATTRIBUTE3 TYPE;
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; }
The list of class variable attributes.
Only one of class variable attributes private, protected or public can be specified. Otherwise a compilation error will occur.
If more than one of ro, wo, and rw are specified, a compilation error will occur
ro
wo
rw
A class variable method is a method that gets and sets a class variable.
A class variable reader is a method to perform the getting 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 reader name is FOO.
FOO
Inline expantion to the getting class variable is performed on each class variable reader.
# Class variable reader class Foo { our $NUM : ro int; static method main : void { my $num = Foo->NUM; } }
A class variable writer is a method to perform the setting 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 writer name is SET_FOO.
SET_
SET_FOO
Inline expantion to the setting class variable is performed on each class variable writer.
# Class variable writer class Foo { our $NUM : wo int; static method main : void { Foo->SET_NUM(3); } }
Each class variable is initialized with the "Initial Value" in initial value just after the program starts.
This initial value can be changed by using the INIT block.
# Change the initial value of the class variable using INIT block. class Foo { our $VAR : int; INIT { $VAR = 3; } }
The class variable access is an operator to set or get a class variable.
See the getting class varialbe and the setting class varialbe.
Fields are the data that an object has.
The has keyword defines a field.
has
# 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; }
The field definition needs the type. The type must be a numeric type or an object type. Otherwise an compilation error will occur.
The field names must follows the rule of the field name. Otherwise an compilation error will occur.
Field names cannot be duplicated. If so, a compilation error will occur.
Field attributes can be specified.
The list of field attributes.
foo
set_
set_foo
Only one of field attributes private, protected or public can be specified. Otherwise a compilation error will occur.
If more than one of ro, wo, and rw are specified at the same time, a compilation error will occur
A field reader is an instance method. It has no arguments. The return type of a field reader is the same as its field type, except for the byte and short type.
byte
short
If the type of the field is the byte or short type, The return type of a field reader is the int type.
int
A field writer 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 writer is the int type.
Inline expansion to the field access except that the field type is the byte or short is performed on field reader and writer.
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; }
The field access is an operator to get or set the field.
INVOCANT->{FIELD_NAME}
The field access has three different syntax.
If the invocant is different from the following three field access, a compilation error will occur.
If the field name does not found, a compilation error will occur
The field access of the class.
my $point = new Point; $point->{x} = 1; my $x = $point->{x};
See "Getting Field" to get the field of the class.
See "Setting Field" to set the field of the class.
The field access of the multi-numeric type.
my $z : Complex_2d; $z->{re} = 1; my $re = $z->{re};
See "Getting Multi-Numeric Field" to get the field of the multi-numeric type.
See "Setting Multi-Numeric Field" to set the field of multi-numeric type.
The field access of the multi-numeric reference via derefernce.
my $z : Complex_2d; my $z_ref = \$z; $z_ref->{re} = 1; my $re = $z_ref->{re};
See "Getting Multi-Numeric Field via Dereference" to get the field of the multi-numeric reference via dereference.
See "Setting Multi-Numeric Field via Dereference" to set the field of the multi-numeric reference via dereference.
a.
The method keyword defines a class method or an instance method.
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.
The types of the arguments must be a numeric type, the multi-numeric type, an object type, or "Reference Type". Otherwise a compilation error will occur.
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 will occur.
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.
native
... after the type of the argument indicates the argument is a variable length argument. Only the last argument can become a variable length argument.
static method METHOD_NAME : RETURN_TYPE (ARG_NAME1 : ARG_TYPE1, ARG_NAME2 : ARG_TYPE2...) { }
The type of the variable length argument must be the array type.
A variable length argument can recieve multiple values.
# Definition of variable length argument static method sprintf : string ($format : string, $values : object[]...) { } # Pass multiple values to the a variable length argument sprintf("Value %d %f", 1, 2.0);
A variable length argument can recieve an array.
# Pass array to a variable lenght argument sprintf("Value %d %f", [(object)1, 2.0]);
If you want to treat the value as an individual element, cast it to type other than the array type..
sprintf("aaa %p", (object)[(object)1, 2.0]);
The optional argument is the syntax to specify optional arguments.
static method METHOD_NAME : RETURN_TYPE (ARG_NAME1 : ARG_TYPE1, ARG_NAME2 = DEFAULT_VALUE : ARG_TYPE2) { }
static method substr ($string : string, $offset : int, $length = -1 : int) { # ... } 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);
A class method is defined with the static keyword.
static
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);
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 are attributes used in a method definition.
A native method is the method that is written by native languages such as the C language, C++.
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 Module and SPVM Native API.
If the class has the precompile class attribute, the methods of the class are precompiled.
precompile
The source code of each precompiled method is translated to C source code and is compiled to the machine code such as MyMath.o.
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.
MyMath.so
MyMath.dll
MyMath.dylib
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.
~/.spvm_build
Constant Method is a Method that the return type is a numeric type and returns Constant Value.
static method foo : int () { return 5; } static method foo : long () { return 5L; } static method foo : float () { return 5.0f; } static method foo : double () { return 5.0; }
Inline Expansion optimization is performed on Constant Method.
Note that SPVM does not perform constant convolution optimization, so if a constant is calculated, it will not performe Inline Expansion.
# This is not Constant Method. Inline Expansion is not performed static method foo : int () { return 5 + 3; }
The enumeration is the syntax to define constant values of the int type.
The enum keyword defines an enumeration. An enumeration defines constant values.
enum
# Enumeration Definition enum { FLAG1, FLAG2, FLAG3 }
An enumeration must be defined directly under the class definition.
The first value of an enumeration begins with 0. The next value is incremented by 1, and this is continued in the same way. In this example, FLAG1 is 0, FALG2 is 1, and FLAG3 is 2.
FLAG1
FALG2
FLAG3
The type of a value of an enumeration is the int type.
, after the last value can be allowed.
enum { FLAG1, FLAG2, FLAG3, }
A value of an enumeration is implemented as a constant method.
static method FLAG1 : int () { return 0; } static method FLAG2 : int () { return 1; } static method FLAG3 : int () { return 2; }
The value can be set explicitly.
enum { FLAG1, FLAG2 = 4, FLAG3, }
In the above example, FLAG1 is 0, FALG2 is 4, and FLAG3 is 5.
If an enumeration definition is invalid, a compilation error will occur.
class Foo { enum { FLAG1, FLAG2, FLAG3, } }
Attributes can be specified to an enumeration definition.
private enum { FLAG1, FLAG2 = 4, FLAG3, }
The list of enumeration attributes:
Only one of enumeration attributes private, protected or public can be specified. Otherwise a compilation error will occur.
The value of the enumeration can be got using the class method call.
my $flag1 = Foo->FLAG1; my $flag2 = Foo->FLAG2; my $flag3 = Foo->FLAG3;
As special cases, the value of the enumeration can be used as the OPERAND of the case statement.
switch ($num) { case Foo->FLAG1: { # ... } case Foo->FLAG2: { # ... } case Foo->FLAG3: { # ... } default: { # ... } }
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 "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 "Local Variable 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.
The local variable is initialized by the "Initial Value" in initial value.
The local variable Access is an operator to access Local Variable to get or set the value.
See "Getting Local Variable" to get Local Variable value.
"Setting Local Variable" to get Local Variable value.
If "Class Variable" with the same name as the Local Variable exists, Program uses the variable as Local Variable, not "Class Variable".
A scope is the part that is surrounded by a scope block.
# Scope block { # Beginning of scope my $point = Point->new; # End of scope }
When a object that is not undef is assigned to a local variable, the reference count is incremented by 1.
At the end of scope, the reference count is decremented by 1. If the reference count becomes 0, the object will be destroyed.
See also garbage collection.
A block is the part that is enclosed by { and }.
Blocks are the class block, the enumeration block, and the scope blocks.
# Blocks { 1; } if (true) { } while (true) { } enum { ONE, TWO, } class Foo { }
A class block is a block.
# Class block class Point { }
A enumeration block is a block.
# Enumeration block enum { ONE, TWO, }
A scope block is the block that has the scope. Zero or more statements are written in a scope block.
Scope blocks are the simple block, the method block, the eval block, the if block, the elsif block, the else block, the for block, the while block and the switch 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.
The method block is a scope block.
# Method block static method foo : int () { }
The eval block is a scope block.
eval
# eval block eval { };
The if block is a scope block.
if
# if block if (CONDITION) { }
The elsif block is a scope block.
elsif
# elsif block elsif (CONDITION) { }
The else block is a scope block.
else
# else block else { }
The for block is a scope block.
for
# for Block for (my $i = 0; $i < 3; $i++) { }
The while block is a scope block.
while
# while block while (CONDITION) { }
The switch block is a scope block.
switch
# switch block switch (CONDITION) { }
The case block is a scope block.
case
# case block switch (CONDITION) { case CASE_VALUE1: { # ... } }
The default block is a scope block.
default
# default block switch (CONDITION) { default: { # ... } }
The INIT block is a block to be executed just after the program starts.
INIT
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.
Each class can have its INIT block.
The execution order of INIT blocks is not guaranteed.
class Foo { use Point; our $NUM : int; our $POINT : Point; # INIT block INIT { $NUM = 3; $POINT = Point->new; } }
SPVM has the string type. A string is created by "String Literal" "String Creating Operator" or "Type Convertion" to the string type.
# Create a string using a string literal my $string = "Hello"; # Create a string using a string creation operator my $string = new_string_len 3; # Create a string using the type cast to the string type my $bytes = [(byte)93, 94, 95]; my $string = (string)$bytes;
The each charcter can be get using ->[].
->[]
# String my $string = "Hello"; my $char0 = $string->[0]; my $char1 = $string->[1]; my $char2 = $string->[2];
By default, each character can't be set.
# a compilation error. $string_const->[0] = 'd';
If you use mutable type qualifier|/"mutable Type Qualifier", each character can be set.
mutable type qualifier|/"mutable Type Qualifier"
my $string_mut = (mutable string)$string; $string_mut->[0] = 'd';
The created string is one more last byte that value is \0 on the internal memory. Although this has no meaning from SPVM language, this has meaning from Native APIs.
The length of the string can be got using a string length operator
# Getting the length of the string my $message = "Hello"+ my $length = length $message;
An undefined value is represented by undef.
undef
An undefined value can be assigned to an object type.
In the level of native APIs, undef is defined as (void*)NULL.
(void*)NULL
An undefined value can be compared by the == operator and the != operator. An undefined value is guaranteed not to be equal to the any created object.
==
!=
The type of undef is undefined type
# Undefine values my $string : string = undef; if (undef) { } my $message = "Hello"; if ($message == undef) { }
The array is the data structure for multiple values.
There are the following types of array.
The numeric array is the array that the type of the element is the numeric type.
The object array is the array that the type of the element is the object type.
The multi-numeric array is the array that the type of the element is the multi-numeric type.
See "Creating Array" to create Array.
Array Access is an operator to access the element of Array to get or set the value.
ARRAY->[INDEX]
See "Getting Array Element" to get the element value of Array.
See "Setting Array Element" to set the element value of Array.
A multi-numeric value is a value that represents continuous multiple numeric values in memory.
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.
The list of the multi-numeric type suffix.
The multi-numeric type field access is an syntax to access the field of the multi-numeric value.
MULTI_NUMERIC_VALUE->{FIELD_NAME}
See "Getting Multi-Numeric Field" to get the field of the multi-numeric value.
See "Setting Multi-Numeric Field" to set the field of the multi-numeric value.
The multi-numeric values can be the elements of the array.
my $zs = new Complex_2d[3];
The elements of the multi-numeric array is continuous multi-numeric values.
| Complex_2d | Complex_2d | Complex_2d | | re | im | re | im | re | im |
The multi-numeric array access is a syntax to access the element of the multi-numeric array.
See "Getting Array Element" to get the element of the array.
See "Setting Array Element" to set the element of the array.
The reference is the address of a local variable on the memory.
The reference operator creates the reference of a local variable.
A reference is assigned to the "Reference Type" in reference type.
The operand of a reference operator must be the variable of a numeric type or a multi-numeric type.
# The reference of numeric type my $num : int; my $num_ref : int* = \$num; # The reference of multi-numeric type my $z : Complex_2d;; my $z_ref : Complex_2d* = \$z;
The reference type can be used as the types of the arguments of a method.
# Method Definition static method sum : void ($result_ref : int*, $num1 : int, $num2 : int) { $$result_ref = $num1 + $num2; } # Method Call my $num1 = 1; my $num2 = 2; my $result_ref = \$result; sum($result_ref, $num1, $num2);
The dereference is the operation to get the value from a reference.
A dereference operator perform a dereference.
# Get the value using a dereference my $num2 = $$num_ref; # Set the value using a dereference $$num_ref = 3; # Get the value of a multi-numeric type using a dereference my $z2 = $$z_ref; # Set the value of a multi-numeric type using a dereference $$z_ref = $z2;
In the referencec of multi-numeric types, the deference can be performed using the arrow operator ->.
->
# Get a field of a multi-numeric type using a dereference my $x = $z_ref->{re}; # Set a field of a multi-numeric type using a dereference $z_ref->{re} = 1;
SPVM language has data types.
See Data type - Wikipedia about data types.
The list of initial values.
0
The numeric type are the integer type and "Floating Point Type".
a numeric type has the type order. The order is "byte", "short", "int", "long", "float", "double" from the smallest.
Integral types are the following four types.
Note that SPVM has only singed integer types, and doesn't have unsigned integer types.
The integer type within int is the integer type within the int type.
In other words, the integer types within int are the byte type, the short type, and the int type.
byte type is the integer type that represents a signed 8-bit integer. This is the same type as int8_t type of the C language.
int8_t
short type is the integer type that represents a signed 16-bit integer. This is the same type as int16_t type of the C language.
int16_t
int type is is the integer type that represents signed 32-bit integer. This is the same as int32_t type of the C language.
int32_t
long type is the integer type that represents a signed 64-bit integer. This is the same type as int64_t type of the C language.
long
int64_t
Floating Point Type are the following two.
The float type is a floating point type that represents a single precision(32bit) floating point. This is the same type as float type of the C language.
float
The double type is a floating point type that represents a double precision(64bit) floating point. This is the same type as double type of the C language.
double
The class type is the type that can create the object using a new operator.
new ClassType;
Basic object types are the class type, the array type, the string type, and the any object type.
Object types are the basic object types and the array types.
A object type can be assigned to a any object type.
my $object: object = new Foo; my $object: object = "abc";
A numeric object type is the object type that is corresponding to the numeric type.
The list of numeric object types:
See also the boxing conversion and "Unboxing Conversion".
The undefined type is the type of undef value.
The interface type is a type that is defined using a class keyword and a class attribute interface_t.
class Stringable : interface_t { required method to_string : string (); }
See also "Interface".
Note that interface types are not class types although they are defined by class keyword.
Any Object Type is represented by "object". Designed to represent the "void *" Type in C.
my $object: object;
You can methodstitute the value of "Object Type" for Any Object Type.
my $object: object = new Foo; my $object: object = "abc"; my $object: object = new Foo [3];
void Type is a special Type that can only be used in the return type of the method definition and indicates the method has no return value.
void
The basic types are numeric types, multi-numeric types, the class type, the any object type, and the string type.
Another definition of basic types are the types that is not array types and can become the element of array types.
The array type is the type for the array. The array type is composed of the basic type and the dimension such as [], [][].
[]
[][]
# Numeric array int[] double[] # String array string [] # Class array Point[] # Any object array object[] # 2 dimensional array int[][] # 3 dimensional array int[][][]
The maximam value of dimesions is 255. Otherwise an compilation error will occur.
The array type is an object type.
The numeric array type is an array type for the array of the numeric type.
The list of the numeric array.
byte[]
short[]
int[]
long[]
float[]
double[]
Each element are initialized by the "Initial Value" in initial value when the creating array is performed.
The byte[] type is an array type that the element type is byte.
Object array types are the array type that the type of the element is an object type.
# Object array types my $points : Point[]; my $points_2dim : Point[][]; my $stringables : Stringable[]; my $strings : string[]; my $objects : object[];
String array types are the array type that the type of the element is the string type.
# String array types my $strings : string[];
Class array types are the array type that the type of the element is the class type.
# Class array types my $points : Point[];
Interface array types are the array type that the type of the element is the interface type.
# Interface array types my $stringables : Stringable[];
The multi-dimensional array type is the array type that the type of the element is an array type.
# Multi-dimensional array types my $nums_2dim : Int[][];
A multi-numeric array type is an array type that the basic type is a multi-numeric type.
The byte size of the element is the total byte size of the fields of the multi-numeric type.
For example, The byte size of the element of Complex_2d is 16 bytes (2 * 8 bytes).
The object of the multi-numeric array type can be created by the new operator.
my $complex_nums = new Complex_2d[10];
The any object array type object[] is the type that any object array type can be assigned.
object[]
# Any object array Type my $array : object[] = new Point[3]; my $array : object[] = new object[3]; my $array : object[] = new Point[][3];
If a invalid type is assigned, a compilation error will occur.
Any Object Array Type is an array type.
You can get the array length using the array length operator.
my $array : object[] = new Int[3]; # Getting the length of the element of Any Object Array Type my $length = @$array;
You can get and set the element using the get array element syntax and the set array element.
# Getting the element of any object array my $num = (Int)$array->[0]; # Setting the element of any object array $array->[0] = Int->new(5);
When setting the element of any object array, the element type is checked. If the dimension of the element is not the dimension of the array - 1, an exception is thrown.
The string type is a type for the "String".
string
string type can be qualified by "mutable Type Qualifier".
mutable string
# string type my $message : string = "Hello"; my $message : mutable string = new_string_len 256;
The multi-numeric type is the type to represent a multi-numeric value.
The multi-numeric type can be used as the type of the local variable declaration.
my $z : Complex_2d;
The value is initialized by the "Initial Value" in initial value.
The multi-numeric type can be used as an argument the type in the method definition.
The multi-numeric type can be used as the return type of the method definition.
static method add_double_complex : Complex_2d ($z1 : Complex_2d, $z2 : Complex_2d) { ... }
The multi-numeric type can be used as a basic type of the array type .
my $points = new Complex_2d[5];
The reference can be created for the value of the multi-numeric type.
my $z : Complex_2d; my $z_ref = \$z;
undef cannot be assigned to the multi-numeric type.
Reference Type is a Type that can store the address of a variable. Add * after a numeric type or the multi-numeric type You can define it.
*
my $num : int; my $num_ref : int* = \$num; my $z : Complex_2d; my $z_ref : Complex_2d* = \$z;
Only the address of the Local Variable acquired by "Reference Operator" can be assigned to the value of Reference Type.
If only Local Variable Declaration of Reference Type is performed, a compilation error will occur
Reference Type can be used as Type of the local variable declaration. The address of the Local Variable must be stored by the Reference Operator. In case of only Local Variable Declaration, a compilation error will occur
Reference Type can be used as Type of argument in the method definition.
Reference Type cannot be used as return value Type in the method definition.
Reference Type cannot be used as the field type in the class definition.
Reference Type cannot be used as the type of Class Variable in the class definition.
If the Reference Type is used at an Invalid location, a compilation error will occur
See "Reference" for a detailed explanation of Reference.
Reference Type are "Numeric Reference Type" and "Multi-Numeric Reference Type".
Numeric Reference Type means a numeric type for "Reference Type". Says.
Multi-Numeric Reference Type means "Reference Type" for the multi-numeric type variables. > Means.
Type qualifiers qualify the type.
QUALIFIER TYPE
The mutable type qualifier is used to allow to set the character of the string.
mutable
my $string : mutable string;
# Mutable string my $message = (mutable string)"abc"; $message->[0] = 'd';
Omitting the type when the local variable declaration by Type Inference can. Type Inference is always performed by the type on the Right side of Assignment Operator.
# int my $num = 1; # double my $num = 1.0; # Foo my $foo = new Foo;
The assignability at compile-time is explained.
The assignability is false, a compilation error will occur.
Explains the assignability to the numeric types.
If the nemric type order of the left operand is greater than or equal to the nemric type order of the right operand, the assignability is true.
If the nemric type order of the left operand is greater than the nemric type order of the right operand, the numeric widening conversion is performed.
# int to int my $num : int = 3; # byte to int my $num : int = (byte)5; # double to double my $num : double = 4.5; # float to double my $num : double = 4.5f;
If the nemric type order of the left operand is less than the nemric type order of the right operand, the assignability is conditional true.
The condition is that the right operand is a interger literal and the value is between the max and minimal value of the type of the left operand.
If the condition is ture, the numeric narrowing conversion is performed.
# int to byte my $num : byte = 127;
If the type of the left operand is a numeric type corresponding to the numeric object type of the right operand and the type of the right operand is a numeric object type, the assignability is true.
my $int : int = Int->new(3); my $double : double = Double->new(3.5);
If the type of the left operand is a numeric type and the type of the right operand is a any object type object, the assignability is true.
object
The unboxing conversion corresponding to the numeric type is performed.
my $int : int = (object)Int->new(3); my $double : double = (object)Double->new(3.5);
If the type of the left operand is a numeric type and the type of the right operand is other than the types described above, the assignability is false.
If the type of the left operand is a multi-numeric type and the type of the right operand is the same type of the left operand, the assignability is true.
Otherwise, the assignability is false.
my $z1 : Complex_2d; my $z2 : Complex_2d = $z1;
If the type of the left operand is a reference type and the type of the right operand is the same type of the left operand, the assignability is true.
my $num : int = 5; my $num_ref : int* = \num;
If the type of the left operand is the string type without the mutable type qualifier and the type of the right operand is the string type, the assignability is true.
If the type of the left operand is the string type with the mutable type qualifier and the type of the right operand is the string type with the mutable type qualifier, the assignability is true.
If the type of the left operand is the string type with the mutable type qualifier and the type of the right operand is the string type without the mutable type qualifier, the assignability is false.
If the type of the left operand is the string type and the type of the right operand is a numeric type or the undef type, the assignability is true.
If the type of the right operand is a numeric type, the numeric-to-string conversion is performed.
my $string : string = "abc"; my $num_string : string = 3; my $string : string = undef;
If the type of the left operand is a numeric object type and the type of the right operand is the same type of the left operand, a numeric type that is corresponding to the numeric object type, or the undef type, the assignability is true.
If the type of the right operand is a numeric type, the boxing conversion is performed.
my $num_object : Int = Int->new(3); my $num_object : Int = 3; my $num_object : Int = undef;
If the type of the left operand is a class type and the type of the right operand is the same type, or the undef type, the assignability is true.
If the type of the left operand is a super class of the type of the right operand, the assignability is true.
my $point : Point = Point->new; my $point : Point = undef;
If the type of the left operand is an interface type and the type of the right operand is the same type, or the undef type, the assignability is true.
If the type of the left operand is an interface type and the type of the right operand is a class type and the class has the same interface of the left operand, the assignability is true.
# Point has Stringable interface my $stringable : Stringable = Point->new(1, 2); my $stringable : Stringable = undef;
If the type of the left operand is the any object type and the type of the right operand is an object type, a numeric type or the undef type, the assignability is true.
my $object : object = Point->new; my $num_object : object = 3; my $object : object = undef;
If the type of the left operand is the undefined type, the assignability is false.
# The assignability is false undef = Point->new;
If the type of the left operand is a numeric array type and the type of the right operand is the same type of the left operand or the undef type, the assignability is true.
my $nums : int[] = new int[3]; my $nums : int[] = undef;
If the type of the left operand is a multi-numeric array type and the type of the right operand is the same type of the left operand or the undef type, the assignability is true.
my $nums : Complex_2d[] = new Complex_2d[3]; my $nums : Complex_2d[] = undef;
If the type of the left operand is a string array type and the type of the right operand is the same type of the left operand or the undef type, the assignability is true.
my $strings : string[] = ["abc", "def"]; my $strings : string[] = undef;
If the type of the left operand is a class array type and the type of the right operand is the same type of the left operand or the undef type, the assignability is true.
If the basic type of the left operand is an super class of the type of the right operand, the assignability is true.
my $points : Point[] = new Point[3]; my $points : Point[] = undef;
If the type of the left operand is an interface array type and the type of the right operand is the same type of the left operand or the undef type, the assignability is true.
If the type of the left operand is an interface array type and the type of the right operand is a class array type and its basic type can assign to the basic type of the left operand, the assignability is true.
my $stringables : Stringable[] = new Stringable[3]; my $stringables : Stringable[] = new Point[3]; my $stringables : Stringable[] = undef;
If the type of the left operand is the any object array type object[] and the type of the right operand is an object array type or the undef type, the assignability is true.
my $any_objects0 : object[]; my $any_objects : object[] = $any_objects0; my $points : Point[]; my $any_object : object[] = $points; my $any_object : object[] = undef; my $points_2dim : Point[][]; my $any_object : object[] = $points_2dim; my $stringables : Stringable[]; my $any_object : object[] = $stringables; my $strings : string[]; my $any_object : object[] = $strings;
If the type of the left operand is a multi-dimensional array type and the type of the right operand is the same type of the left operand or the undef type, the assignability is true.
If the type dimesion of the left operand is equal to the type dimension of the right operand, and the basic type of the left operand is a super class of the basic type of the right operand, the assignability is true.
If the type dimesion of the left operand is equal to the type dimension of the right operand, and the basic type of the right operand has the basic type of the left operand, the assignability is true.
([]...[] means two or more [])
[]...[]
my $points_2dim : Point[][]; my $muldim_array : Point[][] = $points_2dim; my $muldim_array : Point[][] = undef; my $strings_2dim : String[][]; my $muldim_array : Stringable[][] = $strings_2dim; { my $cb = method : string ($object : object) { my $point = (Point)$object; return $point->to_string; }; my $muldim_array : Stringer[][] = [[$cb]]; }
The castability at compile-time is explained.
The castability is false, a compilation error will occur.
The castability to the numeric types is explained.
If the type of the left operand is a numeric type and the type of the right operand is a numeric type, the castability is true.
If the nemric type order of the left operand is less than the nemric type order of the right operand, the numeric narrowing conversion is performed.
If the nemric type order of the left operand is equal to the nemric type order of the right operand, copying is performed.
# int to int my $num = (int)3; # byte to int my $num_byte : byte = 5; my $num = (int)5; # double to double my $num = (double)4.5; # float to double my $num = (double)4.5f; # int to byte my $num = (byte)127; # double to int my $num = (int)2.5;
If the type of the left operand is a numeric type corresponding to the numeric object type of the right operand and the type of the right operand is a numeric object type, the castability is true.
my $int = (int)Int->new(3); my $double = (double)Double->new(3.5);
If the type of the left operand is a numeric type and the type of the right operand is a any object type object, the castability is true.
my $object : object = Int->new(3); my $int = (int)$object; my $object : object = Double->new(3.5); my $double = (double)$object;
If the type of the left operand is a numeric type and the type of the right operand is other than the types described above, the castability is false.
If the type of the left operand is a multi-numeric type and the type of the right operand is the same type of the left operand, the castability is true.
Otherwise, the castability is false.
my $z1 : Complex_2d; my $z2 = (Complex_2d)$z1;
If the type of the left operand is a reference type and the type of the right operand is the same type of the left operand, the castability is true.
my $num : int = 5; my $num_ref = (int*)\num;
If the type of the left operand is the string type and the type of the right operand is the string type, the castability is true.
If the type of the left operand is the string type with the mutable type qualifier and the type of the right operand is the string type without the mutable type qualifier, the runtime type checking is performed.
If the type of the left operand is the string type and the type of the right operand is a numeric type, the undef type, or the any object type object, the castability is true.
If the type of the left operand is the string type and the type of the right operand is the any object type object, the castability is true and the runtime type checking is performed.
my $string = (string)"abc"; my $num_string = (string)3; my $string : string = undef;
If the type of the left operand is a numeric object type and the types of the right operands are the following cases:
If the type of the right operand is the same type of the left operand, a numeric type that is corresponding to the numeric object type, the any object type object, or the undef type, the castability is true.
The type of the right operand is other than above, the castability is false.
If the type of the left operand is the type of the right operand is the any object type object, the runtime type checking is performed.
my $num_object = (Int)Int->new(3); my $num_object = (Int)3; my $num_object = (Int)undef; my $object : object = Int->new(3); my $num_object = (Int)$object;
If the type of the left operand is a class type and the types of the right operands are the following cases:
If the type of the right operand is the same type, the any object type object, an interface type or the undef type, the castability is true.
If the type of the left operand is a super class of the type of right operand, the castability is true.
If the type of the right operand is a super class of the type of left operand, the castability is true.
If the type of the right operand is the any object type object or an interface type, the runtime type checking is performed.
my $point : Point = Point->new; my $stringable : Stringable; my $point = (Point)$stringable; my $stringer : Stringer; my $point = (Point)$stringer my $point = (Point)undef;
If the type of the left operand is an interface type, and the types of the right operands are the following cases:
If the type of the right operand is the same type, the any object type object , an interface type or the undef type, the castability is true.
If the type of the right operand is a class type and the class has the interface of the left operand, the castability is true.
If the type of the right operand is the any object type object, an interface type, the runtime type checking is performed.
my $stringable1 : Stringable; my $stringable2 = (Stringable)$stringable1; my $cloneable : Cloneable; my $stringable = (Stringable)$cloneable; my $stringable = (Stringable)Point->new(1, 2); my $object : object = Point->new(1, 2); my $stringable = (Stringable)Point->new(1, 2); my $stringable : Stringable = undef;
If the type of the left operand is the any object type and the types of the right operands are the following cases:
If the type of the right operand is an object type, a numeric type or the undef type, the castability is true.
If the type of the left operand is the byte[] type and the type of the right operand is the string type, the castability is true.
If the type of the left operand is a numeric array type and the types of the right operands are the following cases:
If the type of the right operand is the same type of the left operand, the any object type obejct or the undef type, the castability is true.
obejct
If the type of the left operand is the byte[] type and the type of the right operand is the string type, "String-to-byte[] Conversion" is performed.
If the type of the right operand is the any object type obejct, the runtime type checking is performed.
my $bytes = (byte[])"abc"; my $nums = (int[])new int[3]; my $object : object = new int[3]; my $nums = (int[])$object; my $nums = (int[])undef;
If the type of the left operand is a multi-numeric array type and the types of the right operands are the following cases:
my $nums = (Complex_2d[])new Complex_2d[3]; my $object : object = new Complex_2d[3]; my $nums = (Complex_2d[])$object; my $nums = (Complex_2d[])undef;
If the type of the left operand is a string array type and the types of the right operands are the following cases:
If the type of the right operand is the same type of the left operand, the any object type obejct, the any object array type obejct[] or the undef type, the castability is true.
obejct[]
If the type of the right operand is the any object type obejct, or the any object array type obejct[], the runtime type checking is performed.
my $strings = (string[])["abc", "def"]; my $object : object = ["abc", "def"]; my $strings = (string[])$object; my $objects : object[] = ["abc", "def"]; my $strings = (string[])$object; my $strings = (string[])undef;
If the type of the left operand is a class array type and the types of the right operands are the following cases:
If the basic type of the left operand is a super class of the basic type of the right operand, the castability is true.
If the basic type of the right operand is a super class of the basic type of the left operand, the castability is true.
my $points = (Point[])new Point[3]; my $object : object = new Point[3]; my $points = (Point[])$object; my $objects : object[] = new Point[3]; my $points = (Point[])$object; my $points = (Point[])undef;
If the type of the left operand is an interface array type and the types of the right operands are the following cases:
If the type of the right operand is a class array type and its basic type has the interface of the basic type of the left operand, the castability is true.
If the type of the right operand is the same type of the left operand, the castability is true.
If the type of the right operand is an differnt type of interface array type, the castability is also true.
If the type of the right operand is the any object type obejct, the any object array type obejct[] or the undef type, the castability is true.
If the type of the right operand is an differnt type of interface array type, the runtime type checking is performed.
my $stringables = (Stringable[])new Stringable[3]; my $stringables = (Stringable[])new Point[3]; my $stringables = (Stringable[])undef;
If the type of the left operand is the any object array type object[] and the types of the right operands are the following cases:
If the type of the right operand is an object array type or the undef type, the castability is true.
If the type of the right operand is an any object type, the castability is true.
If the type of the right operand is an any object type, the runtime type checking is performed.
my $any_object : object; my $any_objects = (object[])$any_object; my $any_objects0 : object[]; my $any_objects = (object[])$any_objects0; my $points : Point[]; my $any_object = (object[])$points; my $any_object = (object[])undef; my $points_2dim : Point[][]; my $any_object = (object[])$points_2dim; my $stringables : Stringable[]; my $any_object = (object[])$stringables; my $strings : string[]; my $any_object = (object[])$strings;
If the type of the left operand is a multi-dimensional array type and and the types of the right operands are the following cases:
If the type of the right operand is the same type of the left operand or the undef type, the castability is true.
If the type dimesion of the left operand is equal to the type dimension of the right operand, and the basic type of the left operand is a super class of the basic type of the right operand, the castability is true.
If the type dimesion of the left operand is equal to the type dimension of the right operand, and the basic type of the right operand is a super class of the basic type of the left operand, the castability is true.
If the basic type of the type of the left operand is an interface type and the basic type of the type of the right operand is a class type and the dimension of the type of the right operand is the same as the dimension of the type left oerand and the basic type of the type of the right operand has the interface of the basic type of the type of the left operand , the castability is true.
Type conversion is explained.
The explicite type conversion is the type conversion performed by a type cast expicitely.
# The explicte type conversion from long to int my $num = (int)123L; # The explicte type conversion from byte[] to string my $num = (string)new byte[3]; # The explicte type conversion from string to byte[] my $num = (byte[])"Hello";
The implicite type conversion is the type conversion performed implicitly when a value is assigned using assignment operator, pass an argument to a method using a method call, or set a return value using the return statement.
See "Assignability" if you know when implicite type conversion is performed.
# The implicite type conversion from int to double my $num : double = 5; # The implicite type conversion from double to Double my $num_object : Double = 5.1; # The implicite type conversion from Double to double my $num : double = Double->new(5.1); # The implicite type conversion from int to string my $string : string = 4;
The integer promotional conversion is a type conversion to convert an integer type within int to the int type using the numeric widening conversion.
The numeric widening conversion is a type conversion from a small-order numeric type to a large-order numeric type.
See also numeric types order abount the order of numeric type.
The return value of a converion are same as the return value of the type cast of the C language.
(TYPE)OPERAND
byte to short:
int8_t from = VALUE; int16_t to = (int16_t)from;
byte to int:
int8_t from = VALUE; int32_t to = (int32_t)from;
byte to long:
int8_t from = VALUE; int64_t to = (int64_t)from;
byte to float:
int8_t from = VALUE; float to = (float)from;
byte to double:
int8_t from = VALUE; double to = (double)from;
short to int:
int16_t from = VALUE; int32_t to = (int32_t)from;
short to long:
int16_t from = VALUE; int64_t to = (int64_t)from;
short to float:
int16_t from = VALUE; float to = (float)from;
short to double:
int16_t from = VALUE; double to = (double)from;
int to long:
int32_t from = VALUE; int64_t to = (int64_t)from;
int to float:
int32_t from = VALUE; float to = (float)from;
int to double:
int32_t from = VALUE; double to = (double)from;
long to float:
int64_t from = VALUE; float to = (float)from;
long to double:
int64_t from = VALUE; double to = (double)from;
The numeric widening conversion is performed in some of the type casts, the index of the array access, the length of the creating array, the OPERAND of the unary plus operator, the OPERAND of the unary minus operator, and the left and right operands of the shift operators.
The numeric narrowing conversion is a conversion from a wide numeric type to a narrow numeric type.
double to float:
double from = value; float to = (float)from;
double to long:
double from = value; int64_t to = (int64_t)from;
double to int:
double from = value; int32_t to = (int32_t)from;
double to short:
double from = value; int16_t to = (int16_t)from;
double to byte:
double from = value; int8_t to = (int8_t)from;
float to long:
float from = value; int64_t to = (int64_t)from;
float to int:
float from = value; int32_t to = (int32_t)from;
float to short:
float from = value; int16_t to = (int16_t)from;
float to byte:
float from = value; int8_t to = (int8_t)from;
long to int:
int64_t from = value; int32_t to = (int32_)from;
long to short:
int64_t from = value; int16_t to = (int16_t)from;
long to byte:
int64_t from = value; int8_t to = (int8_t)from;
int to short:
int32_t from = value; int16_t to = (int16_t)from;
int to byte:
short to byte:
int16_t from = value; int8_t to = (int8_t)from;
The numeric narrowing conversion is performed in some of the type casts.
The binary numeric conversion is a type conversion to upgrade the type of the left operand or the right operand of the binary operator that operands are numeric types.
The following rules apply in order.
1. If the left operand or the right operand is the double type, the OPERAND of the small type is converted to the big type using the numeric widening conversion.
2. If the left operand or the right operand is the float type, the OPERAND of the small type is converted to the big type using the numeric widening conversion.
3. If the left operand or the right operand is the long type, the OPERAND of the small type is converted to the big type using the numeric widening conversion.
4, Otherwise, both the left operand and the right operand are converted to the int type using the numeric widening conversion.
The numeric-to-string conversion is a type conversion from a numeric type to the string type.
# The numeric-to-string conversion my $byte = (byte)1; my $short = (short)2; my $int = 3; my $long = 4L; my $float = 2.5f; my $double = 3.3; # The string is 1. my $string_byte = (string)$byte; # The string is 2. my $string_short = (string)$short; # The string is 3. my $string_int = (string)$int; # The string is 4. my $string_long = (string)$long; # The string is "2.5" my $string_float = (string)$float; # The string is "3.3" my $string_double = (string)$double;
The String-to-byte[] conversion is a type conversion from the string Type to "byte[] Type".
# The String-to-byte[] conversion my $string : string = "Hello"; my $bytes : byte[] = (byte[])$string;
A new byte[] object is created and all characters in the string are copied to the elements of byte[] object.
The byte[]-to-string conversion is a type conversion from the byte[] type to the string Type.
# byte[]-to-string conversion my $bytes : byte[] = new byte[3]; $bytes->[0] = 'a'; $bytes->[1] = 'b'; $bytes->[2] = 'c'; my $string : string = (string)$bytes;
A new string is created and all elements in the byte[] object are copied to the characters of the string.
The boxing conversion is a type coversion to convert the value of numeric type to the corresponding numeric object type.
The unboxing conversion is a type coversion to convert the value of the numeric object type to the value of the corresponding numeric type.
The bool conversion is a type conversion that is performed on the conditional operand.
The type of the OPERAND of the bool conversion must be a numeric type, an object type or an reference type or the undef type. Otherwise a compilation error will occur.
The bool conversion returns the following value corresponding to the type of the condional operand.
If the type is the int type, return the value.
If the type is the undef, return 0.
If the type is the value returned by the TRUE method of Bool, return 1.
If the type is the value returned by the FALSE method of Bool, return 0.
If the type is an integer type within int, the integer promotional conversion is performed on the OPERAND.
And the following operation in the C language is performed on the OPERAND .
!!OPERAND
if (1) { # ok } if (0) { # not ok } if (1.5) { # ok } if (0.0) { # not ok } if (true) { # ok } if (Bool->TRUE) { # ok } if (false) { # not ok } if (Bool->FALSE) { # not ok } my $object = SPVM::Int->new(1); if ($object) { # ok } $object = undef; if ($object) { # not ok } my $value = 1; my $ref = \$value; if ($ref) { # ok } if (undef) { # not ok }
List of conditional operands:
The operand of the if statement:
if (CONDITION) { }
The operand of the unless statement:
unless (CONDITION) { }
The second operand of the for statement:
for (INITIALIZEATION;CONDITION;NEXT_VALUE;) { }
The operand of the while statement:
while (CONDITION) { }
The left and right operand of the logical AND operator:
CONDITION && CONDITION
The left and right operand of the logical OR operator:
CONDITION || CONDITION
The operand of the logical NOT operator:
!CONDITION
The runtime type cheking is the type cheking that is performed at runtime.
The type cast operators that operand is an object type performe the runtime type checking by the rule of the "Runtime Assignability" in runtime assignability.
The runtime assignability is the assignability at runtime.
The isa operator checks the "Runtime Assignability" in runtime assignability
The runtime assignability is false, an exception is thrown.
If the type of the distribution is an object type and the type of the source is undef, the runtime assignability is true.
If the type of the distribution is the same as the type of the source, the runtime assignability is true.
If the type of the distribution is the any object type object and the type of the source is an object type, the runtime assignability is true.
If the type of the distribution is the any object array type object[] and the type of the source is an object array type, the runtime assignability is true.
If the type of distribution is an class type, an class array type, an class multi-dimensional array type and the dimention of the type of the distribution is the same as the dimention of the type of the source and the basic type of distribution is a super class of the basic type of the source, the runtime assignability is true.
If the type of distribution is an interface type, an interface array type, an interface multi-dimensional array type and the dimention of the type of the distribution is the same as the dimention of the type of the source and the basic type of distribution has the interface of the basic type of the source, the runtime assignability is true.
The type comment syntax is supported. The type comment can be written after of keyword.
of
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;
If the type specified as the type comment is not found, a compilation error will occur.
Type comments have no meanings at runtime.
Statements are the list of the statement.
Statements are written direct under the scope block.
# Scope block { # Statements STATEMENT1 STATEMENT2 STATEMENT3 }
The conditional branch is explained in the following topics.
The if statement is a statement for conditional branch.
First, The bool conversion is performed on the condition.
Next, if the condition is not 0, the execution position jumps to the beginning of the if block. Otherwise jumps to the end of the if block.
The local variable declartion and the initialization in the condition of the if statement are allowed.
if (my $condition = 1) { }
This is parsed as the following code.
{ my $condition = 1; if ($condition) { } }
# if statement. my $flag = 1; if ($flag == 1) { print "One\n"; }
The elsif statement is a statement for conditional branch used with the if statement.
if (CONDITION1) { } elsif (CONDITION2) { }
If the condition 1 doesn't match, the execution position jumps to the end of the if block.
condition 1
Next, The bool conversion is performed on the condition 2.
condition 2
Next, if the condition 2 is not 0, the execution position jumps to the beginning of the elsif block. Otherwise jumps to the end of the elsif block
Multiple elsif statements are allowed.
if (CONDITION1) { } elsif (CONDITION2) { } elsif (CONDITION3) { }
The local variable declartion and the initialization in the condition of the elsif statement are allowed.
if (my $condition = 1) { } elsif (my $condition = 2) { }
{ my $condition = 1; if ($condition) { } else { my $condition = 2; if ($condition) { } } }
# elsif statement. my $flag = 2; if ($flag == 1) { print "One\n"; } elsif ($flag == 2) { print "Two\n"; }
The else statement is a statement for conditional branch used with the if statement or the elsif statement.
if (CONDITION) { } else { }
If the condition doesn't match, the execution position jumps to the end of the if block.
Next, the execution position jumps to the beginning of the else block.
The elsif statements with the else statement are allowed.
if (CONDITION1) { } elsif (CONDITION2) { } else { }
# else statement. my $flag = 3; if ($flag == 1) { print "One\n"; } elsif ($flag == 2) { print "Two\n"; } else { print "Other"; }
The unless statement is a statement for conditional branch that does the opposite of the if statement.
unless
The unless statement is the same as the following if Statement.
if (!CONDITION) { }
The unless statements with the elsif statement and the else statement are allowed.
unless (CONDITION1) { } elsif (CONDITION2) ( } else { }
# unless statement. my $flag = 1; unless ($flag == 0) { print "Not Zero\n"; }
The switch statement is a statement for conditional branch.
switch (CONDITION) { case CASE_VALUE1: { # ... } case CASE_VALUE2: { # ... } case CASE_VALUE3: { # ... } default: { # ... } }
The condition must be an integer type within int. Otherwise a compilation occur will occur.
The integer promotional conversion is performed on the condition.
The value of the case statement must be one of the character literal, the integer literal or the getting enumeration value.
If it is a character literal, the value is converted to the int type at compile-time.
The values of the case statements can't be duplicated. If so, a compilation error will occur.
If the condition matches the value of a case statement, the program jumps to the beginning of the case block.
If the condition doesn't match any case statements and the default statement exists, the program jumps to the beginning the default block.
If the condition doesn't match any case statements and the default statement doesn't exists, the program jumps to the end of the switch block.
The case statements and the default statement can be ommited.
The break statement jumps to the end of the switch block.
break
switch (CONDITION) { case CASE_VALUE1: { break; } case CASE_VALUE2: { break; } case CASE_VALUE3: { break; } default: { } }
If the last statment of the case block is not the break statement, a break statement is added to the end of the case block.
# The break statement is ommitted. switch (CONDITION) { case CASE_VALUE1: { } } # The above becomes the following. switch (CONDITION) { case CASE_VALUE1: { break; } }
Multiple case statements before a case block can be specified at once.
switch (CONDITION) { case CASE_VALUE1: case CASE_VALUE2: { # ... } }
# switch statement my $code = 2; my $flag = 1; switch ($code) { case 1: { print "1\n"; } case 2: { print "2\n"; } case 3: { if ($flag) { break; } print "3\n"; } case 4: case 5: { print "4 or 5\n"; } default: { print "Other\n"; } } # switch statement using enumeration class Foo { enum { ID1, ID2, ID3, } static method main : int () { my $value = 1; switch ($value) { case Foo->ID1: { print "1\n"; } case Foo->ID2: { print "2\n"; } case Foo->ID3: { if ($flag) { break; } print "3\n"; } default: { print "Other\n"; } } } }
The case statement is the statement that specifies a case value and a branch of a switch statement.
# The case statement switch (CONDITION) { case CASE_VALUE1: { # ... } }
The default statement is a statement that specifies a default branch of a switch statement.
# The default statement switch (CONDITION) { default: { # ... } }
The break statement is a statement to jump to the end of the switch block of the switch statement.
# The break statement break;
The while statement is a statement for loop.
Next, If the condition is 0, the program jumps to the end of the while block. Otherwise the program goes to the beginning of the while block.
When the program reaches the end of the while block, it jumps back to the while statement and evaluates the condition again.
# The while statement my $i = 0; while ($i < 5) { print "$i\n"; $i++; }
The last statement is used inside the while block. By The last statement, the program jumps to the end of the current while block.
# The last statement while (1) { # The program jumps to the end fo the current while block. last; }
The next statement is used inside the while block. By The last statement, the program goes back to the while statement of the current while block.
my $i = 0; while ($i < 5) { if ($i == 3) { $i++; # the program goes back to the while statement of the current while block. next; } print "$i\n"; $i++; }
The while statement is enclosed by an inbisible simple block.
# The while statement while (1) { } # The above is the same as the following. { while (1) { } }
The for Statement is a statement to write loop syntax easily.
# The for statement. for (INIT_STATEMENT; CONDITION; INCREMENT_STATEMENT) { }
The for statement is the alias for the while statement.
# The above for statemenet is the same as the following while statemenet. { INIT_STATEMENT; while (CONDITION) { # ... INCREMENT_STATEMENT; } }
Exampels:
# The for statement for (my $i = 0; $i < 5; $i++) { print "$i\n"; }
The for-each statement is a statement to write loop syntax easily for the simple iteration.
# The for-each statemenet for my VAR (@ARRAY) { } for my VAR (@{ARRAY}) { }
The above for-each statement is the same as the following the for statement.
for (my $i = 0; $i < @ARRAY; $i++) { my VAR = ARRAY->[$i]; }
Example:
# The for-each statemenet my $array = [1, 2, 3]; for my $element (@$array) { print "$elemenet\n"; }
The next statement is a statement to go back to the while statement of the current while block.
next
next;
See also the while statement.
The last statement is a statement to jump to the end of the current while block.
last
last;
The return statement is a statement to return a value.
return
// void return; // non-void return OPERAND;
If the return type of the current method is the void type, the OPERAND can't exist. If so, a compilation error will occur.
If the return type of the current method is the non-void type, the OPERAND must exist. Otherwise a compilation error will occur.
The type of the OPERAND must be able to assign to the return type of the current method. Otherwise a compilation error will occur.
The empty statement ; is a statement to do nothing.
;
# The empty statemenet ;
The operator statement is the statement to execute an operator.
A operation statement is composed of an operator and ;.
# The operator statemenet OPERATOR;
1; $var; 1 + 2; &foo(); my $num = 1 + 2;
The void returning operator statement is the statement to execute an void returning operator.
The statement is composed of void returning operator and ;.
VOID_RETURN_OPERATOR;
die "Error"; warn "Warning";
An operator performs an operation that process something and returns a value.
+OPERAND
The unary plus operator + returns the value of the OPERAND.
Compilation Errors:
The OPERAND must be a numeric type.
Type Conversion:
If the OPERAND is an integer type within int, the integer promotional conversion is performed on the OPERAND.
Return Type and Operand Types:
int (OPERAND : byte) int (OPERAND : short) int (OPERAND : int) long (OPERAND : long) float (OPERAND : float) double (OPERAND : double)
# The unary plus operator my $num = +10;
-OPERAND
The unary minus operator - returns the negative value of the OPERAND.
# A unary minus operator my $num = -10;
LEFT_OPERAND + RIGHT_OPERAND
The addition operator + calculates the addition of the LEFT_OPERAND and the RIGHT_OPERAND.
LEFT_OPERAND
RIGHT_OPERAND
The LEFT_OPERAND and the RIGHT_OPERAND must be a numeric type.
The binary numeric conversion is performed on LEFT_OPERAND and RIGHT_OPERAND.
RETURN_TYPE (OPERAND_LEFT : byte|short|int|long|float|double, OPERAND_RIGHT : byte|short|int|long|float|double)
The RETURN_TYPE is the type after the binary numeric conversion is performed.
RETURN_TYPE
The subtraction operator - is an operator to calculate the result of the subtraction of two numbers.
LEFT_OPERAND - RIGHT_OPERAND
The left operand and the right operand must be a numeric type. Otherwise a compilation error will occur.
the binary numeric conversion is performed on the left operand and the right operand.
The subtraction operator performs the operation that exactly same as the following operation in the C language.
x - y;
The return type of the subtraction operator is the type that the binary numeric conversion is performed.
The multiplication operator is an operator to calculate the result of multiplication of two numbers.
LEFT_OPERAND * RIGHT_OPERAND
The multiplication operator performs the operation that exactly same as the following operation in the C language.
x * y;
The return type of the multiplication operator is the type after the binary numeric conversion is performed.
The division operator / is an operator to culcurate the division of two numbers.
LEFT_OPERAND / RIGHT_OPERAND
The division operator performs the operation that exactly same as the following operation in the C language.
x / y;
The return type of the division operator is the type after the binary numeric conversion is performed.
If the two operands are integer types and the value of the right operand is 0, an exception is thrown.
The division unsigned int operator divui is an operator to culcurate the unsigned int division of two numbers.
divui
LEFT_OPERAND divui RIGHT_OPERAND
The left operand and the right operand must be an int type. Otherwise a compilation error will occur.
The division unsigned int operator performs the operation that exactly same as the following operation in the C language.
(uint32_t)x / (uint32_t)y;
The return type of the division operator is the int type.
If the value of the right operand is 0, an exception is thrown.
The division unsigned long operator divul is an operator to culcurate the unsigned long division of two numbers.
divul
LEFT_OPERAND divul RIGHT_OPERAND
The left operand and the right operand must be an long type. Otherwise a compilation error will occur.
The division unsigned long operator performs the operation that exactly same as the following operation in the C language.
(uint64_t)x / (uint64_t)y;
The return type of the division operator is the long type.
The remainder operator % is an operator to calculate a remainder of two numbers.
%
LEFT_OPERAND % RIGHT_OPERAND
The left operand and the right operand must be an integer type. Otherwise a compilation error will occur.
The remainder operator performs the operation that exactly same as the following operation in the C language.
x % y;
the return type of Remainder Operator is the type that the binary numeric conversion is performed.
If the right operand is 0, the remainder operator throw an exception.
The remainder unsigned int operator remui is an operator to calculate a unsigned int remainder of two numbers.
remui
LEFT_OPERAND remui RIGHT_OPERAND
The left operand and the right operand must be a int type. Otherwise a compilation error will occur.
The remainder unsigned int operator performs the operation that exactly same as the following operation in the C language.
(uint32_t)x % (uint32_t)y;
The return type of the remainder unsigned int operator is the int type.
If the value of the right operand is 0, an exception is thrown .
The remainder unsigned long operator remul is an operator to calculate a unsigned long remainder of two numbers.
remul
LEFT_OPERAND remul RIGHT_OPERAND
The left operand and the right operand must be a long type. Otherwise a compilation error will occur.
The remainder unsigned long operator performs the operation that exactly same as the following operation in the C language.
(ulong64_t)x % (ulong64_t)y;
The return type of the remainder unsigned long operator is the long type.
Increment operators are the pre-increment operator and post-increment operator.
The pre-increment operator adds 1 to the value of the OPERAND and returns the value after the incrementation.
# Pre-increment operator ++OPERAND
The type of the OPERAND must be a local variable, a class variable, a field access</a>, an array access, a dereference. Otherwise a compilation error will occur.
The pre-increment operator performs the same operation as the following.
(OPERAND = (TYPE_OF_OPERAND)(OPERAND + 1))
For example, if the type of the OPERAND is the byte type, the following operation is performed.
($num = (byte)($num + 1))
# Pre-increment of a local variable ++$num; # Pre-increment of a class variable ++$NUM; # Pre-increment of an element of an array ++$point->{x}; # Pre-increment of a field ++$nums->[0]; # Pre-increment of a dereferenced value ++$$num_ref;
The post-increment operator adds 1 to the value of the OPERAND and returns the value before the incrementation.
# Post-increment operator OPERAND++
The post-increment operator performs the same operation as the following.
(my TMP_VARIABLE = OPERAND, OPERAND = (TYPE_OF_OPERAND)(OPERAND + 1), TMP_VARIABLE)
(my $tmp = $num, $num = (byte)($num + 1), $tmp)
# Post-increment of a local variable $num++; # Post-increment of a class variable $NUM++; # Post-increment of an element of an array $point->{x}++; # Post-increment of a field $nums->[0]++; # Post-increment of a dereferenced value $$num_ref++;
Decrement operators are the pre-decrement operator and post-decrement operator.
The pre-decrement operator subtracts 1 to the value of the OPERAND and returns the value after the decrementation.
# Pre-decrement operator --OPERAND
The type of the OPERAND must be a local variable, a class variable, a field access, an array access, a dereference. Otherwise a compilation error will occur.
The pre-decrement operator performs the same operation as the following.
(OPERAND = (TYPE_OF_OPERAND)(OPERAND - 1))
($num = (byte)($num - 1))
# Pre-decrement of a local variable --$num; # Pre-decrement of a class variable --$NUM; # Pre-decrement of an element of an array --$point->{x}; # Pre-decrement of a field --$nums->[0]; # Pre-decrement of a dereferenced value --$$num_ref;
The post-decrement operator subtracts 1 to the value of the OPERAND and returns the value before the decrementation.
# Post-decrement operator OPERAND--
The post-decrement operator performs the same operation as the following.
(my TMP_VARIABLE = OPERAND, OPERAND = (TYPE_OF_OPERAND)(OPERAND - 1), TMP_VARIABLE)
(my $tmp = $num, $num = (byte)($num - 1), $tmp)
# Post-decrement of a local variable $num--; # Post-decrement of a class variable $NUM--; # Post-decrement of an element of an array $point->{x}--; # Post-decrement of a field $nums->[0]--; # Post-decrement of a dereferenced value $$num_ref--;
Bit operators are operators to perform bit operations.
Bit operators are the bit AND operator, the bit OR operator, or the bit NOT operator.
The bit AND operator & is an operator to performe a bit AND operation.
LEFT_OPERAND & RIGHT_OPERAND
The left operand and the right operand must be an "Integer Type" in integer type. Otherwise a compilation error will occur.
A binary numeric widening conversion is performed.
The return value is the same as the follwoing operation of the C language.
x & y;
The return type is the type after the binary numeric widening conversion is performed.
# The bit AND operator my $num1 = 0xff; my $num2 = 0x12; my $result = $num1 & $num2;
The bit OR operator | is an operator to performe a bit OR operation.
|
LEFT_OPERAND | RIGHT_OPERAND
x | y;
# The bit OR operator my $num1 = 0xff; my $num2 = 0x12; my $result = $num1 | $num2;
The bit NOT operator ~ is an operator to perform the bit NOT operation.
~
~OPERAND
The type of the OPERAND must is an integer type. Otherwise a compilation error will occur.
The numeric widening conversion is performed.
~x
The return type is the type that the numeric widening conversion is performed.
# The bit NOT operator my $num = ~0xFF0A;
Shift operators are operators that performs bit shift operations. These are "Left Shift Operator", "Arithmetic Right Shift Operator", and "Logical Right Shift Operator".
The left shift operator << is an operator to perform the left bit shift.
<<
LEFT_OPERAND << RIGHT_OPERAND
The left operand must be the integer type. Otherwise a compilation error will occur.
The "Numeric Widening Conversion" in numeric widening conversion is performed on the left operand.
The right operand must be the integer type except for the long type. Otherwise a compilation error will occur.
The "Numeric Widening Conversion" in numeric widening conversion is performed on the right operand.
The return type is the same as the type of the left operand.
The calculation result of the left shift operator is the same as the following calculation in the C language.
x << y;
The arithmetic right shift operator >> is an operator to perform the arithmetic right bit shift.
>>
LEFT_OPERAND >> RIGHT_OPERAND
The operation result of the arithmetic right shift Operator is the operation that exactly same as the following operation in the C language.
x >> y;
The logical right shift operator >>>is an operator to perform the logical right bit shift.
>>>
LEFT_OPERAND >>> RIGHT_OPERAND
The operation result of logical right shift Operator is the same as the following calculation in the C language.
// In the case that the left operand is a int type (uint32_t)x >> y; // In the case that the left operand is a long type (uint64_t)x >> y;
The comparison operator is the operator to compare the left operand and the right operand.
LEFT_OPERAND COMPARISON_OPERATOR RIGHT_OPERAND
Comparison operators are the numeric comparison operators, the string comparison operators, and the isa operator.
The numeric comparison operator is a comparison operator that is placed between The left operand and the right operand to compare the size of number or check the equqlity of objects. LEFT_OPERAND NUMERIC_COMPARISON_OPERATOR RIGHT_OPERAND
The list of numeric comparison operators.
The types of the left operand and the right operand must be comparable types. Otherwise a compilation error will occur.
In Numeric Type Comparison, the binary numeric conversion is performed for The left operand and the right operand.
the Numeric Comparison Operation is performed that exactly same as the following operation in the C language.
# Numeric Type Comparison, Object Type Comparison (int32_t)(x == y); (int32_t)(x != y); # Numeric Type Comparison (int32_t)(x > y); (int32_t)(x >= y); (int32_t)(x < y); (int32_t)(x <= y); (int32_t)(x > y ? 1 : x < y ? -1 : 0);
For Numeric Type Operation(==, !=, >, >=, <, <=), the int type Operation, "long Type" Operation, "float Type" Operation, the double type Operation is defined.
And Object Type Operation(==, !=) is defined.
The return type of the Numeric Comparison Operator is the int type.
The string comparison operator is a comparison operator to compare tow strings.
LEFT_OPERAND STRING_COMPARISON_OPERATOR RIGHT_OPERAND
The type of the left operand and the right operand must be the string type or byte[] type.
The return type is the int type. If the condition is satisfied, return 1, otherwise 0.
The list of string comparison operators.
The isa operator is a comparison operator to check whether the left operand can be assigned to the right type.
isa
LEFT_OPERAND isa RIGHT_TYPE
The return type is int type.
If the right type is a numeric type, the multi-numeric type, "Any Object Type", "Reference Type", it checks the assignability at compile-time.
If the assignability is true, it is replaced with 1. Otherwise it is replaced with 0.
If the right type is other type, it checks the runtime assignability at runtime. If the runtime assignability is true, it returns 1. Otherwise return 0.
if ($object isa Point) { } if ($object isa Point3D) { } if ($object isa Stringable) { } if ($value isa int) { }
The is_type operator is a comparison operator to check whether the type of the instance of the left operand is the right type.
is_type
LEFT_OPERAND is_type RIGHT_TYPE
If the type of the instance of the left operand is the right type, return 1. Otherwise return 0.
The left operand of the is_type operator must be an object type. Otherwise a compilation error will occur.
The right type of the is_type operator must be an object type. Otherwise a compilation error will occur.
The right type of the is_type operator can't be the any object type. If so, a compilation error will occur.
The right type of the is_type operator can't be the any object array type. If so, a compilation error will occur.
The right type of the is_type operator can't be an interface type. If so, a compilation error will occur.
if ($object is_type Point) { } if ($object is_type int[]) { } if ($object is_type Stringable[]) { }
The is_compile_type operator is a comparison operator to check whether the compilation-time type of the left operand is the right type.
is_compile_type
LEFT_OPERAND is_compile_type RIGHT_TYPE
If the compilation-time type of the left operand is the right type, return 1. Otherwise return 0.
{ my $value : int; if ($value is_compile_type int) { # Pass } } { my $object : object = new TestCase::Minimal; if ($object is_compile_type object) { # Pass } } { my $value : Stringer = method : string () { return "aaa"; }; if ($value is_compile_type Stringer) { # Pass } }
The ref operator is an operator to get the type name of the object.
ref
ref OPERAND
If the OPERAND is defined, it returns the type name of the object. If not, return undef.
The return type is the string type.
If the OPERAND is not an object type, a compilation error will occur.
# "Point" my $poitn = Point->new; my $type_name = ref $point;
The dump operator is an operator to get the string representation of the object.
dump
dump OPERAND
It returns the string representation of the object.
The string representation may be changed from SPVM version to version. Please don't use dump operator for the purpose of the data serialization.
The logical operators are the operators to perform logical operations.
The logical operators are the logical AND operator, the logical OR operator, and the logical NOT operator.
The logical AND operator && is a logical operator to perform a logical AND operation.
&&
LEFT_OPERAND && RIGHT_OPERAND
The left operand and the right operand must be an operator.
The return type of the logical AND operator is the int type.
Thg logical AND operator performs the bool conversion to the left operand. If the evaluated value is 0, return 0. Otherwise proceed to the evaluation of the right operand.
It performs the bool conversion to the right operand. If the evaluated value is 0, return 0. Otherwise return the evaluated value.
The logical OR operator || is a logical operator to performe a logical OR operation.
||
LEFT_OPERAND || RIGHT_OPERAND
The return type of the logical OR operator is the int type.
Thg logical OR operator performs the bool conversion to the left operand. If the evaluated value is not 0, return the evaluated value. Otherwise proceed to the evaluation of the right operand.
It performs the bool conversion to the right operand. If the evaluated value is not 0, return the evaluated value. Otherwise return 0.
The logical NOT operator ! is a logical operator to performe a logical NOT operation.
!
!OPERAND
The return type of the logical NOT operator is the int type.
Thg logical NOT operator performs the bool conversion to the OPERAND. If the evaluated value is 0, returns 1. Otherwise return 0.
String concatenation operator . is an operator to concat two strings.
LEFT_OPERAND . RIGHT_OPERAND
The left operand and the right operand must be a string type, "byte[] Type", or numeric type. Otherwise a compilation error will occur.
If the type of the OPERAND is numeric type, a numeric-to-string conversion is performed.
A string concatenation operator returns the result to concat two operands.
If both the left operand and the right operand are a string literal, the two string literals are concatenated at compile-time.
If the left operand or the right operand is undef, an exception occurs.
my $str = "abc" . "def"; my $str = "def" . 34; my $str = 123 . 456;
The assignment operator = is an operator to assign a value.
LEFT_OPERAND = RIGHTH_OPERAND
The assignment operator has different meanings depending on the left operand and the right operand.
See "Getting Local Variable" and "Setting Local Variable".
See "Getting Array Element" and "Setting Array Element".
See "Getting Field" and "Setting Field".
A special assignment operator is the alias for the combination of an operator and "Assignment Operator" =.
LEFT_OPERAND OPERATOR= RIGHTH_OPERAND
Above is the alias for the following code.
LEFT_OPERAND = (TYPE_OF_LEFT_OPERAND)(LEFT_OPERAND OPERATOR RIGHTH_OPERAND)
For example, See a byte case.
# Addition assignment operator $x += 1; # Above is the same as the following code. $x = (byte)($x + 1)
The following operators are used as the operators of the special assignment operators.
# Special assignment operators $x += 1; $x -= 1; $x *= 1; $x /= 1; $x &= 1; $x |= 1; $x ^= 1; $x %= 1; $x <<= 1; $x >>= 1; $x >>>= 1; $x .= "abc";
The array length operator is an operator to get the length of the array.
@OPERAND
The operand must be an operator that type is an the array type. Otherwise a compilation error will occur.
The array length operator returns the int type value that is the length of the array.
Array Length Operator returns the operator
# Getting the length of the array. my $nums = new byte[10]; my $length = @$nums; # Getting the length of the array with a scalar operator. This is exactly same as the avobe my $nums = new byte[10]; my $length = scalar @$nums;
Note that SPVM does not have the context different from Perl, and array length operators always return the length of the array.
The new_string_len operator is an operator to create a string with the length.
new_string_len
new_string_len OPERAND
The type of the OPERAND must be an integer type within int. Otherwise a compilation error will occur.
The integer promotional conversion is performed on the OPERAND.
The new_string_len operator returns a new string that length is the length specified by the OPERAND and all characters are \0.
The character just after the last character is \0. The string created by the new_string_len operator can be used as the C language string ending with \0.
The length specified by the OPERAND must be greater than or equal to 0. Otherwise an exception is thrown.
# New a string with the length my $message = new_string_len 5;
The copy operator is an operator to copy the object.
copy
copy OPERAND
The operand must be an operator that type is a object type. Otherwise a compilation error will occur.
If the type of operand is none of a string type, a numeric type, a multi-numeric type, An exception is thorwn.
The copy operator returns the copied object.
The return type is the same as the type of operand.
Read-only flag of the string is dropped.
# New a string with the length my $message = copy "abc";
The is_read_only is an operator to check if the string is read-only.
is_read_only
is_read_only OPERAND
The operand must be a string type. Otherwise a compilation error will occur.
If the string is read-only, the is_read_only operator returns 1, otherwise returns 0.
The return type is an int type.
# New a string with the length my $message = "Hello"; my $is_read_only = is_read_only $message;
The string length operator length is an operator to get the length of the string.
length
length OPERAND
The returned length is the byte size. Note that the length is not the count of UTF-8 characters.
The type of the OPERAND must be the string type. Otherwise a compilation error will occur.
The return type is the int type.
# Getting the string length. The length is 5. my $message = "Hello"; my $length = length $message; # Getting the string length of UTF-8. The length is 9. my $message = "あいう"; my $length = length $message;
The scalar operator is an Operator that returns the value of the OPERAND.
scalar
scalar OPERAND
The operand must be an "The array Length Operator". Otherwise a compilation error will occur.
# Getting the array length my $nums = new int[3]; foo(scalar @$nums); # This is exactlly same as the above. my $nums = new int[3]; foo(@$nums);
Note that the sclara operator exists only to reduce the confusion.
The isweak operator checks whether the field is weak reference
isweak
isweak OBJECT->{FIELD_NAME};
The type of the object must be the class type. Otherwise a compilation error will occur.
If the field name is not found, a compilation error will occur.
The type of the field targetted by the isweak operator is not an object type, a compilation error will occur.
If the field is weaken, the isweak operator returns 1, otherwise returns 0.
The return type of the isweak operator is the int type.
See "Weak Reference" to know the behavior of the isweak operator.
# isweak my $isweak = isweak $object->{point};
The has_impl operator checks the existence of the method implementation.
has_impl
has_impl OPERAND->METHOD_NAME has_impl OPERAND
The operand must the object that has a class type or an interface type. Otherwise a compilation error will occur.
If the class or the interface doesn't have the method declaration, a compilation error will occur.
The method name must be a method name. Otherwise a compilation error will occur.
If method name is not specified, the method name become "".
If the class or the interface has the method implementation, returns 1, otherwise returns 0.
my $stringable = (Stringable)Point->new(1, 2); if (has_impl $stringable->to_string) { # ... }
The getting local variable is an operator to get the value of the local variable.
$var
The return value is the value of the local variable.
The return type is the type of the local variable.
The setting local variable is an operator to set the value of "Local Variable" using the assignment operator.
$var = VALUE
The assignment of the value must satisfy the assignability. Otherwise a compilation error will occur.
The return value is the value after the assignment.
If the type of the assigned value is an object type, the reference count of the object is incremented by 1.
If an object has already been assigned to $var before the assignment, the reference count of the object is decremented by 1.
See the scope to know the garbage collection of local variables.
The getting class variable is an operator to get the value of the class variable.
$CLASS_NAME::CLASS_VARIABLE_NAME
CLASS_NAME:: can be omitted if the class variable belongs to the current class.
CLASS_NAME::
$CLASS_VARIABLE_NAME
If the class variable does not found, a compilation error will occur.
If the class variable is private and it is accessed outside of the class, a compilation error will occur.
class Foo { our $VAR : int; static method bar : int () { my $var1 = $Foo::VAR; my $var2 = $VAR; } }
Setting Class Variable operator is an operator to set "Class Variable" Value using the assignment operator.
$CLASS_NAME::CLASS_VARIABLE_NAME = VALUE
"CLASS_NAME::" can be omitted when the class Variable belongs to own "Class".
$CLASS_VARIABLE_NAME = VALUE
If the assignment does not satisfy the assignability, a compilation error will occur.
The return value is the value after the setting.
The return type is the type of the class variable.
If an object has already been assigned to $CLASS_VARIABLE_NAME before the assignment, the reference count of the object is decremented by 1.
class Foo { our $VAR : int; static method bar : int () { $Foo::VAR = 1; $VAR = 3; } }
The setting exception variable is an operator to get the value of the exception variable.
$@
The return value is the value of exception variable.
# Getting the exception variable my $message = $@;
The setting exception variable is an operator to set the value of "Exception Variable" using the assignment operator.
$@ = VALUE
The type of the assigned value must be the string Type.
The reference count of the assigned value is incremented by 1.
If an string has already been assigned to the exception variable before the assignment, the reference count of the string is decremented by 1.
$@ = "Error";
The getting field is an operator to get the field of the object. This is one syntax of the field access.
The type of invocant is a class type.
The retrun type is the type of the field.
my $point = Point->new; my $x = $point->{x};
The setting field is an operator to set the field of the object. This is one syntax of the field access.
INVOCANT->{FIELD_NAME} = VALUE
The return type is the field type.
If the type of assigned value is a basic object type, the reference count of the object is incremented by 1.
If an object has already been assigned to the field before the assignment, the reference count of that object is decremented by 1.
my $point = Point->new; $point->{x} = 1;
Getting Multi-Numeric Field operator is an operator to get Field of the multi-numeric value. This is one syntax of the field access.
The invocant is the multi-numeric type.
If the field names does not found in the "Class", a compilation error will occur
Getting Multi-Numeric Field operator returns the field value in the multi-numeric value.
my $z : Complex_2d; my $re = $z->{re};
Setting Multi-Numeric Field operator is an operator to set Field of the multi-numeric value using "Assignment Operator". This is one syntax of the field access.
INVOCANT->{FIELD_NAME} = RIGHT_OPERAND
If the field names does not found in the "Class", a compilation error will occur.
Setting Multi-Numeric Field operator returns the value of the field after setting.
The assignment must satisfy the assignability.
my $z : Complex_2d; $z->{re} = 2.5;
The getting array element is an operator to get the element of the array.
The array must be the array type.
The index must be an integer type within int. Otherwise a compilation occur will occur.
The integer promotional conversion is performed on the index.
The getting array element returns the element that is specifed by the index.
The return type is the type of the element.
The array must be defined. Otherwise an exception is thrown.
The index must be greater than or equal to 0. Otherwise an exception is thrown.
my $nums = new int[3]; my $num = $nums->[1]; my $points = new Point[3]; my $point = $points->[1]; my $objects : object[] = $points; my $object = (Point)$objects->[1];
The setting array element is an operator to set the element of the array using the assignment operator.
ARRAY->[INDEX] = RIGHT_OPERAND
The right operand must be assigned to the element of the array.
The setting array element returns the value of the element that is set.
If the right operand is an object type, the reference count of the object is incremented by 1.
If an object has already been assigned to the field before the assignment, the reference count of the object is decremented by 1.
my $nums = new int[3]; $nums->[1] = 3; my $points = new Point[3]; $points->[1] = Point->new(1, 2); my $objects : object[] = $points; $objects->[2] = Point->new(3, 5);
The new operator is an operator to create an object or an array.
The creating object is an operator to create an object using the new operator.
new CLASS_NAME;
The class name must be the name of the class defined by the class definition.
The fields of the created object are initialized by the initial value.
The reference count of the created object is 0. If the object is assigned to a local variable, a class variable, or a field by "Assignment Operator", the reference count is incremented by 1.
my $object = new Foo;
The creating array is an operator to create an array using the new operator.
new BasicType[LENGTH]
The type must be a basic type.
The length must be an integer type within int. Otherwise a compilation occur will occur.
The integer promotional conversion is performed on the length.
The length must be greater than or equal to 0. Otherwise an exception is thrown.
All elements of the array are initialized by the initial value.
The type of the created array is the array type.
my $nums = new int[3]; my $objects = new Foo[3]; my $objects = new object[3]; my $values = new Complex_2d[3]
Multi dimensional arrays can be created using the new operator.
new BasicType[][LENGTH] new BasicType[]...[][LENGTH]
# 2 dimentional int array my $nums = new int[][3]; # 3 dimentional int array my $nums = new int[][][3];
The max dimention is 255.
The array initialization is an operator to create an array and initialize the array easily.
[] [ELEMENT1, ELEMENT2, ELEMENT3]
The array initialization create an array that has the length of the elements.
And the array is initialized by the elements.
And the created array is returned.
The type of the created array is the type that 1 dimension is added to the type of the first element.
If no element is specified, the type of the create array becomes any object type.
# int array my $nums = [1, 2, 3]; # double array my $nums = [1.5, 2.6, 3.7]; # string array my $strings = ["foo", "bar", "baz"];
The first example is the same as the following codes.
# int array my $nums = new int[3]; $nums->[0] = 1; $nums->[1] = 2; $nums->[2] = 3;
The array initialization has another syntax using {}.
{}
{} {ELEMENT1, ELEMENT2, ELEMENT3, ELEMENT4}
This is the same as above array init syntax, but the type of the created array is always "Any Object Array Type" object[].
And if the length of the elements is odd number, a compilation error will occur.
# Key values empty my $key_values = {}; # Key values my $key_values = {foo => 1, bar => "Hello"};
The reference operator \ is the operator to create a reference.
\OPERAND
The operand must be a local variable that type is a numeric type or a multi-numeric type. Otherwise a compilation error will occur.
The return type is the reference type of the OPERAND.
# Create the reference of a numeric type my $num : int; my $num_ref : int* = \$num; # Create the reference of a multi-numeric type my $z : Complex_2d; my $z_ref : Complex_2d* = \$z;
The dereference operators are the operatoers to perform a deference.
Obtaining a value by Dereference is an operator to obtain the actual value from Reference. It was designed to realize the C joint operator *.
$VARIABLE
The variable Type must be Reference Type. Otherwise a compilation error will occur.
The value obtained by Dereference returns the operator.
my $num : int; my $num_ref : int* = \$num; my $num_deref : int = $$num_ref; my $z : Complex_2d; my $z_ref : Complex_2d* = \$z; my $z_deref : Complex_2d = $$z_ref;
Setting a value with Dereference is an operator to set the actual value from Reference. It was designed to realize the C joint operator *.
$VARIABLE = OPERAND
The type of operator must match the type of the variable when dereferenced. Otherwise a compilation error will occur.
Setting a value with Dereference returns the set value. This is the operator.
my $num : int; my $num_ref : int* = \$num; $$num_ref = 1; my $z : Complex_2d; my $z_ref : Complex_2d* = \$z; my $z2 : Complex_2d; $$z_ref = $z2;
Getting Multi-Numeric Field via Dereference operator is an operator to get Field of the multi-numeric value via "Dereference". This is one syntax of the field access
The invocant is "Multi-Numeric Reference Type".
The getting multi-numeric field via dereference operator returns the field value in the multi-numeric value.
my $z : Complex_2d; my $z_ref = \$z; my $re = $z_ref->{re};
The setting multi-numeric field via dereference operator is an operator to set Field of the multi-numeric value via "Dereference" using "Assignment Operator". This is one syntax of the field access.
The setting multi-numeric field via dereference operator returns the value of the field after setting.
my $z : Complex_2d; my $z_ref = \$z; $z_ref->{re} = 2.5;
The getting current class name __CLASS__ is an operator to get the current class name.
__CLASS__
class Foo::Bar { static method baz : void () { # Foo::Bar my $class_name = __CLASS__; } }
The getting current file name __FILE__ is an operator to get the current file name.
__FILE__
The current file name means the relative path from the base path of the module file. For example, if the class loaded path is /mypath and the class name is Foo::Bar, the absolute path is /mypath/SPVM/Foo/Bar.spvm and the relative path is SPVM/Foo/Bar.spvm. SPVM/Foo/Bar.spvm is the current file name.
/mypath
Foo::Bar
/mypath/SPVM/Foo/Bar.spvm
SPVM/Foo/Bar.spvm
# SPVM/Foo/Bar.spvm class Foo::Bar { static method baz : void () { # Get the current file name - SPVM/Foo/Bar.spvm my $file_name == __FILE__; } } class Foo::Bar2 { static method baz : void () { # Get the current file name - SPVM/Foo/Bar.spvm my $file_name == __FILE__; } }
The getting current line number __LINE__ is an operator to get the current line number of the current file.
__LINE__
class Foo::Bar { static method baz : void () { # Get the current line number - 4 my $line = __LINE__; } }
The anon method is an operator to define an anon calss and an instance method that doesn't has its method name.
It creates an object object from the anon class by the new operator and returns the object.
# Anon method method : TYPE (VAR1 : TYPE1, VAR2 : TYPE2, ...) { }
The way to define the method is the same as the method definition.
# 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; } }
The capture is a syntax to use externally defined local variables in an anon method.
# Capture [VAR1 : TYPE1, VAR2 : TYPE2, ...] method : TYPE (VAR1 : TYPE1, VAR2 : TYPE2, ...) { };
class Foo::Bar { method some_method : void () { # Externally defined local variables my $foo = 1; my $bar = 5L; # Capture my $comparator = (Comparator)[$foo : int, $bar : long] method : int ($x1 : object, $x2 : object) { print "$foo\n"; print "$bar\n"; }; } }
Externally defined local variables are implemented as fields of the anon class internally.
# Foo/Bar.spvm class Foo::Bar { method some_method : void () { # Externally defined local variables my $foo = 1; my $bar = 5L; # Capture 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) { print "$self->{foo}\n"; print "$self->{bar}\n"; } }
The class_id operator is an operator to get the class id from a class name.
class_id
class_id CLASS_NAME
The class name must be an existing class. Otherwise a compilation error occur.
The return value is the class id.
The error_code is an operator to get the value of the error code.
error_code
The set_error_code operator is an operator to set the value of the error code.
set_error_code
set_error_code OPERAND
The type of the OPERAND must be the int type.
The error operatoer is an operator to get the current error code.
error
This value is set to 0 at the beginning of the eval block.
If A exception is catched, the current error code is set to the value of error_code.
The type cast is the operator to perform an explicite type conversion.
# Type Cast (TYPE)OPERAND # Postfix Type Cast OPERAND->(TYPE)
If the type cast doesn't have the castability, a compilation error will occur.
A type cast performs a type conversion, merely copying, or copying with a runtime type checking.
The behaviors of type casts are explained in "Castability".
# The explicte type conversion from long to int my $num = (int)123L; # The explicte type conversion from byte[] to string my $num = (string)new byte[3]; # The explicte type conversion from string to byte[] my $num = (byte[])"Hello"; # Postfix type cast my $point = Point->new; my $stringable = $point->(Stringable);
The sequential operator , is an operator like the following.
(OPERAND1, OPERAND2, ..., OPERNADN)
The operands are evaluated from the left to the right, and return the evaluated value of the last operand.
Exampless:
# 3 is assigned to $foo my $foo = (1, 2, 3); # $x is 3, $ret is 5 my $x = 1; my $y = 2; my $ret = ($x += 2, $x + $y);
The void returning operator is the operation that return type is void.
Note that this is not an operator because the operator is defined as the operation that returns the value.
void returning operators are the warn operator, the die operator, the print operator, the make_read_only operator, the weaken operator, and the unweaken operator.
The warn operator is a void retruning operator to print a warning string to the standard error.
warn
warn OPERNAD;
The operand must be the string Type.
If the end character of the string is \n, warn statement prints the string itself.
\n
If not, the current file name and current line number are added to the end of the string.
If the value of the OPERAND is an undef, print "Warning: something's wrong".
The buffer of the standard error is flushed after the printing.
The die operator is a void retruning operator to throw an exception.
die
die OPERAND;
The operand must be the string type. If not a compilation error will occur.
You can specify the error message to the OPERAND.
# Throw an exception die "Error";
The error message is set to the exception variable $@.
If an exception is thrown, the program prints the error message to the standard error with the stack traces and finishes with error code 255.
The stack traces constain the class names, the method names, the file names and the line numbers.
Error from TestCase::Minimal->sum2 at SPVM/TestCase/Minimal.spvm line 1640 from TestCase->main at SPVM/TestCase.spvm line 1198
The exception can be catched using an eval block.
# Catch the exception eval { # Throw an exception die "Error"; }; # Check the exception if ($@) { # ... }
The print operator is a void retruning operator to print a string to the standard output.
print
print OPERAND;
The oeprand must be a string type.
If the value of the OPERAND is an undef, print nothing.
The say operator is a void retruning operator to print a string with a line break \n to the standard output.
say
say OPERAND;
If the value of the OPERAND is an undef, print \n.
The make_read_only operator is a void retruning operator to make the string read-only.
make_read_only
make_read_only OPERAND;
Read-only strings can't be cast to string type qualified by mutable.
# A string my $string = new_string_len 3; # Make the string read-only make_read_only $string; # The conversion to the string type qualified by mutable throw an exception. my $string_mut = (mutable string)$string;
The weaken operator is a void retruning operator to create a weak reference.
weaken
weaken OBJECT->{FIELD_NAME};
The type of the field targetted by the weaken statement is not an object type, a compilation error will occur.
See "Weak Reference" to know the behavior of the weaken statement.
# weaken weaken $object->{point};
The unweaken operator is a void retruning operator to unweakens a weak reference.
unweaken
unweaken OBJECT->{FIELD_NAME};
The type of the field targetted by the unweaken statement is not an object type, a compilation error will occur.
See "Weak Reference" to know the behavior of the unweaken statement.
# unweaken unweaken $object->{point};
The method call is an operator that calls a method.
A method defined as the class method can be called using the class method call.
ClassName->MethodName(ARGS1, ARGS2, ...);
If the number of arguments does not correct, a compilation error will occur.
If the types of arguments have no type compatible, a compilation error will occur.
my $ret = Foo->bar(1, 2, 3);
A method defined as the instance method can be called using the instance method call.
Instance->MethodName(ARGS1, ARGS2, ...);
The called method is resolved from the type of the instance.
$object->bar(5, 3. 6);
The SUPER:: qualifier calls the method of the super class of the current class.
SUPER::
$object->SUPER::bar(5, 3. 6);
A instance method can be called statically by specifing the calss name.
$point3d->Point::clear;
The items operator gets the stack length of the arguments passed to the method.
items
Note that the stack length of the arguments is different from the length of the arguments.
If the method call is the instance method call, the stack length of the arguments is the length of the arguments + 1 for the invocant.
If an argument is a multi-numeric type, the stack length of the argument becomes the length of the fields.
static method my_static_method : int ($args : int, $bar = 0 : int) { my $items = items; return $items; }; # 1 &my_static_method(1); # 2 &my_static_method(1, 2); static method my_instance_method : int ($args : int, $bar = 0 : int) { my $items = items; return $items; }; # 2 (1 + the invocant) &my_instance_method(1); # 3 (2 + the invocant) &my_instance_method(1, 2); static method my_mulnum_method : int ($z : Complex_2d, $bar = 0 : int) { my $items = items; return $items; }; # 2 (The length of the fields of Complex_2d) my $z : Complex_2d; &my_mulnum_method($z); # 3 (The length of the fields of Complex_2d + 1) my $z : Complex_2d; &my_mulnum_method($z, 2);
Explains exceptions.
You can throw an exception using the die statement.
You can catch an exception using an eval block.
eval { die "Error"; };
The undef is set to the exception variable $@ at the top of the eval block.
The error message is set to the exception variable $@ when the exception is thrown.
# Catch the exception eval { # Throw an exception die "Error"; }; # Check the error message if ($@) { # ... }
Exception Variable is a global variable that is represented by "$@"
See the setting class varialbe to get Exception Variable Value.
See "Setting Exception Variable" to set Exception Variable Value.
The object is destroyed when the reference count becomes 0.
If the object is an Array that has Object Type values as elements, the reference count of all Array elements that are not Undefined Value is decremented by 1 before Garbage Collection
When an object is a class type and has a field of Object Type, the reference count of the objects owned by all fields of Object Type that are not Undefined Value is decremented by 1 before Garbage Collection. If Weak Reference is set to the object saved in Field, Weak Reference is destroyed before the reference count is decremented by 1.
When the object has Back references of Weak Reference, Undefined Value is assigned to all fields registered as back References and all back References are deleted.
The above process is done recursively.
Weak Reference is a reference that does not increase the reference count. Weak Reference can be used to solve the problem of circular references.
SPVM has GC of the reference count Type. In the GC of the reference count Type, the object is automatically destroyed when the reference count becomes 0, but when the circular reference occurs, the reference count does not become 0 and the object is automatically destroyed. not.
This is an example when the field of the object is circularly referenced.
{ my $foo = new Foo; my $bar = new Bar; $foo->{bar} = $bar; $bar->{foo} = $foo; }
In this case, both objects are not destroyed when the Scope ends. This is because a circular reference has occurred and the reference count does not become 0.
Weak Reference is a function to correctly destroy objects when a circular reference occurs in a programming language that has the reference count GC.
In such a case, it is possible to release correctly by setting one Field to Weak Reference using the "weaken Operator" in weaken operator.
{ my $foo = new Foo; my $bar = new Bar; $foo->{bar} = $bar; $bar->{foo} = $foo; weaken $foo->{bar}; }
Before the weaken statement is executed, $foo has the reference count of 2 and $bar has the reference count of 2.
If there is no weaken statement, the reference count of $foo and the reference count of $bar will not be 0 and will not be destroyed even if the scope ends.
When a weaken statement is executed, $foo has the reference count of 2 and $bar has the reference count of 1.
When the Scope ends, the reference count of $bar is decremented by 1 and becomes 0, so it is destroyed correctly.
Even if there are 3 circular references, you can release them correctly by setting Weak Reference in 1 Field.
{ my $foo = new Foo; my $bar = new Bar; my $baz = new Baz; $foo->{bar} = $bar; $bar->{baz} = $baz; $baz->{foo} = $foo; weaken $foo->{bar}; }
As a syntax related to Weak Reference, Weak Reference can be destroyed the "weaken Operator" in weaken operator, and it can be confirmed whether Field is Weak Reference the isweak operator.
stdin, stdout, stderr in the C language is set to the binary mode on all systems.
stdin
stdout
stderr
This means the escape character of the string literal "\n" is not coverted to "\r\n" when it is got from stdin and it is printed to stdout and stderr.
"\n"
"\r\n"
stdin, stdout, stderr can be changed to the text mode using the native module, but don't do that.
You can see more examples in the following test codes.
Examples of SPVM
Copyright (c) 2023 Yuki Kimoto
MIT License
To install SPVM, copy and paste the appropriate command in to your terminal.
cpanm
cpanm SPVM
CPAN shell
perl -MCPAN -e shell install SPVM
For more information on module installation, please visit the detailed CPAN module installation guide.