SrivijayaScript
SrivijayaScript is a Java-equivalent programming language for Timeline 284436. It is designed by PSTF in timeline 1, and by Yang Luhe, a Malaysian Han Chinese, in timeline 284436.
The document in timeline 284436 was written by Yang Luhe, Brian Goldenberg, Tsujou Sakura-Kitoshi, and Vasily Andreyevich Vostvarokanokin.
Volume 1: Basic Syntax
Our First Program
# HelloWorld.svj
public class Main {
function main (String argV[], Int argC) @ Void => {
print("Hello, SrivijayaScript!")
}
}
Chapter 1: Basic Syntax
A SrivijayaScript program can be considered a collection of objects, which work together by calling each other's methods. Below is a brief introduction to the concepts of classes, objects, methods, and instance variables.
- Object: An object is an instance of a class, having both state and behavior. For example, a dog is an object, with states such as color, name, and breed; behaviors include wagging its tail, barking, eating, etc.
- Class: A class is a template that describes the behavior and state of a type of object.
- Method: A method is a behavior; a class can have many methods. Logical operations, data modifications, and all actions are performed within methods.
- Instance Variable: Each object has unique instance variables, and the state of the object is determined by the values of these instance variables.
In general, the program uses the Main function of the Main class as the program entry point. If there is no Main class, the first top-level line of code (without any indentation and is not a class/function/struct definition or a no-operation) serves as the program entry point. Although SrivijayaScript supports top-level code, we still recommend that you write a main program class with a main method inside, just like Java in Timeline 1, especially for large projects.
Back to the first program.
~ HelloWorld.svj
public class Main {
function main (String argV[], Int argC) @ Void => {
print("Hello, SrivijayaScript!")
}
}
The comment at top with filename will be the filename that when saving. And then, you can use this to compile and execute the program.
> srivijaya compile HelloWorld.svj --charset: UTF-8;warning: allowed;full-message: true;extra-message: true; Compilation completed. > srivijaya execute HelloWorld Hello, SrivijayaScript!
When writing SrivijayaScript programs, the following points should be noted:
- Case sensitivity: SrivijayaScript is case-sensitive, which means that the identifiers Hello and hello are different.
- Class names: For all classes, the first letter of the class name should be capitalized. If the class name consists of multiple words, the first letter of each word should be capitalized, for example, MyFirstSrivijayaScriptClass.
- Method names: All method names should start with a lowercase letter. If a method name contains multiple words, underscores should be used to separate any spaces between the subsequent words.
Chapter 2: Class and Object
Classes and objects are the most important parts of SrivijayaScript programs. As an object-oriented programming language, it supports the following basic concepts:
- Class:
- Defines the blueprint for objects, including attributes and methods.
- Example: public class Car { ... }
- Object:
- An instance of a class, having state and behavior.
- Example: Car myCar = new Car()
- Inheritance:
- A class can inherit the attributes and methods of another class.
- Example: public class Dog inherit Animal { ... }
- Encapsulation:
- Makes the state (fields) of an object private and accessed through public methods.
- Example: private String name; function getName() @ String => { return name }
- Polymorphism:
- Objects can behave in different forms, mainly achieved through method overloading and method overriding.
- Example:
- Method overloading: function add(Int a, Int b) @ Int => { ... } and public add(Float a, Float b) @ Float => { ... }
- Method overriding: @Override function makeSound() @ Void { print("Meow") }
- Abstraction:
- Uses abstract classes and interfaces to define methods that must be implemented without providing concrete implementations.
- Example:
- Abstract class: public abstract class Shape { abstract function draw() @ Void; }
- Interface: public interface Animal { function eat() @ Void; }
- Interface:
- Defines the methods that a class must implement, supporting multiple inheritance.
- Example: public interface Drivable { function drive() @ Void; }
- Method:
- Defines the behavior of a class, contained in functions within the class.
- Example: function displayInfo() @ Void { print("Info") }
- Method Overloading:
- The same class can have multiple methods with the same name but different parameters.
- Example:
public class MathUtils { function add(Int a, Int b) @ Int => { return a + b; } function add(Float a, Float b) @ Float => { return a + b; } }
In this section, we focus on the concepts of objects and classes.
- Object: An object is an instance of a class, having state and behavior. For example, a dog is an object, with states like color, name, and breed, and behaviors like wagging its tail, barking, eating, etc.
- Class: A class is a template that describes the behaviors and states of a type of object.
As an example, Let's take a look at this program part.
class Rectangle (length: Float, width: Float) {
function get_circumference(this, length, width) @ Float => {
return (length + width) * 2 # C=2(a+b)
}
function get_area(this, length, width) @ Float => {
return length * width # S=ab
}
}
public class Main () {
function main (String argV[], Int argC) @ Void => {
Rectangle rect_1 = Rectangle(12, 8)
print(rect_1.get_area(rect_1.length, rect_1.width))
}
}
A class can contain the following types of variables:
- Local variables: Variables defined within a method, constructor, or block of statements are called local variables. The declaration and initialization of the variable occur within the method, and the variable is automatically destroyed after the method ends.
- Member variables: Member variables are variables defined within a class but outside the body of methods. These variables are instantiated when an object is created. Member variables can be accessed by methods, constructors, and specific blocks of statements in the class.
- Class variables: Class variables are also declared within the class but outside the body of methods, and they must be declared as static.
A class can have multiple methods. In the example above, both get_circumference and get_area are methods of the Rectangle class.
We have embedded the definition of the class constructor directly into the class definition itself. A class must be followed by all its internal parameters (class attributes) after the class name. Class attributes are public by default, but it is allowed to set them as private or assign the class a computed attribute. The keyword for referencing itself within the class is my.
Objects are created based on classes. Creating an object requires the following two steps:
- Declaration: Declare an object, including the object's name and type.
- Instantiation: Use ClassName(*args, **kwargs) to create an object and initialize it.
In the final part of this section, we will learn the declaration rules for source files. Special attention should be paid to these rules when defining multiple classes in a source file along with import statements and package statements.
- A source file can have only one public class
- A source file can have multiple non-public classes
- If the source file's name is not specified in the first line with a comment, it should match the name of the public class. For example: if the public class in the source file is named Employee, then the source file should be named Employee.java (not doing so will not cause a compilation error, but you probably don’t want to name all your files Main).
- If a class is defined in a package, then the package statement should be at the top of the source file.
- If the source file contains import statements, they should be placed between the package statement and the class definitions. If there is no package statement, then import statements should be at the very beginning of the source file. (Unless this import is a conditional import statement, meaning the specified package is only imported under certain conditions.)
- Import statements and package statements apply to all classes defined in the source file. Different classes in the same source file cannot have different package declarations.
Classes have several access levels, and they also come in different types: abstract classes and final classes, etc. These will be introduced in the access control chapter.
In addition to the types mentioned above, SrivijayaScript also has some special classes, such as inner classes and anonymous classes.
Chapter 3: Data and Variable
Data Types
Currently, SrivijayaScript has these data types:
- Integer. The default integer has no restrictions, which imitates Python and Teiwaz. Normal value is 0.
- Byte. A byte is a special type of integer, and its range of values is [-128, 128).
- Short integer. Its value range is [-32768, 32768).
- Medium integer. Its value range is [-2147483648, 2147483648).
- Long integer. Its value range is [-263, 263).
- Very long integer. Its value range is [-2127, 2127). This is supported only if the environment variable USE128BIT is True.
- Rune. A rune is a Unicode character. Its minimum value is 0x0000, the values that cannot be reached are in the range 0xD800 to 0xDFFF (surrogate range), and its maximum value is 0x10FFFF. Rune is enclosed in single quote. Normal value is "NUL" character.
- String. A string is a serie of Runes enclosed in double quote. Escape allowed, and sextuple quote for Document (multiline string). f"xxx" for formatted string, and r"xxx" for raw string. Normal value is "".
- Logical values. A logical value is just a marker and can only participate in logical operations, with only two literals: true and false. Any expression that holds returns true, while an expression that does not hold (including empty expressions, such as 0, 0.0, empty string, empty list, ∅(a set with nothing inside, equivalent to
S{}), NULL, empty dictionary(D{}), etc.) returns false. Normal value is false. - Decimal. Decimals, also called floating-point numbers, are any numbers that are not integers, such as 0.5. The precision of decimals is infinite, so situations like '0.1 plus 0.2 equals 0.30000000000000004' do not occur. Normal value is 0.0.
- Referencing variables. In SrivijayaScript, variables of reference types (including classes, arrays, etc.) are very similar to C/C++ pointers. A reference type points to an object, and a variable that points to an object is a reference variable. These variables are specified as a particular type when declared, such as Employee, Puppy, etc. Once a variable is declared, its type cannot be changed. Objects and arrays are all reference data types. The default value of all reference types is null. A reference variable can be used to refer to any type that is compatible with it.
- List. List and array are two completely different concepts. The construction of a list completely imitates Teiwaz, and the literal difference between arrays and lists is that an array has an A in front of the square brackets and the variables inside are all of the same type.
Identifier Regularization
- Identifiers can and may only be composed of characters from the following character sets: uppercase Latin letters (including extended), lowercase Latin letters (including extended), numbers, underscore, dollar sign, Greek letters, Cyrillic letters, Armenian letters, GB/T 2312 Character Set for Information Exchange of Chinese Characters (Basic Set), GB/T 12345 Character Set for Information Exchange of Chinese Characters (Auxiliary Set), GB 7589-87 Character Set for Information Exchange of Chinese Characters (Second Auxiliary Set), GB/T 13131 Character Set for Information Exchange of Chinese Characters (Third Auxiliary Set), GB 7590-87 Character Set for Information Exchange of Chinese Characters (Fourth Auxiliary Set), GB/T 13132 Character Set for Information Exchange of Chinese Characters (Fifth Auxiliary Set), GB/T 16500-1998 Character Set for Information Exchange of Chinese Characters (Seventh Auxiliary Set), GB/T 12052-1989 Character Set for Information Exchange of Korean Characters, GB/T 16500-1998 Character Set for Information Exchange of Chinese Characters (Seventh Auxiliary Set), GB/T 15564-1995 Character Set for Graphical Television Broadcasting Chinese Characters Hong Kong Subset, Commonly Used Characters of Big5, Less Commonly Used Characters of Big5, JIS X 0213 (Level 1 and Level 2) 7-bit and 8-bit Two-Byte Information Exchange Code Extended Kanji Set (Level 1 and Level 2), JIS X 0213 (Level 3) 7-bit and 8-bit Two-Byte Information Exchange Code Extended Kanji Set (Level 3), JIS X 0213 (Level 4) 7-bit and 8-bit Two-Byte Information Exchange Code Extended Kanji Set (Level 4), KS X 1001 Code Set for Korean Character Exchange (Hangul and Hanja) and KS X 1027 Extended Hanja List characters, Japanese kana (excluding extended and Manyō kana), Hangul characters, and "letters."
- Identifiers must not start with a number.
- In general, the identifiers for variable names and function names should be all lowercase with underscores, the identifiers for constants should be all uppercase with underscores, and the identifiers for structures and classes (including file names, module names, and package names) should be written in camel case.
- Identifiers are normalized according to NFC rules. This means that the Kelvin temperature scale and the uppercase letter K are the same character.
- Identifiers must not conflict with keywords or reserved words.
- Identifiers are case-sensitive.
Variable
To create a variable, you can write this:
[var_accessibility var_mutability] var_type var_name [= var_value];
The variable types supported by SrivijayaScript are:
Local Variables: Local variables are variables declared inside a method, constructor, or block. They are destroyed after the method, constructor, or block in which they are declared finishes executing. Local variables need to be initialized when declared; otherwise, it may lead to some unexpected results.
Instance Variables: Instance variables are declared in a class but outside any method, constructor, or block. They belong to instances of the class, and each instance of the class has its own copy. If not explicitly initialized, instance variables are assigned default values (numeric types as 0, boolean as false, and object reference types as null).
Static Variables or Class Variables: Class variables are declared in a class using the static keyword. They belong to the class rather than instances, and all instances of the class share the same class variable value. Class variables are initialized when the class is loaded and are only initialized once. In summary, static variables are class-related variables that have uniqueness and shareability, and can be used to store data needed by the entire program, but attention needs to be paid to the timing of initialization and the distinction from constants.
Parameter Variables: Parameters are variables declared in methods or constructors to receive values passed when the method or constructor is called. The scope of parameter variables is limited to the method.
Global Variables: Global variables are variables declared in the top-level code of a program. They are destroyed when the program ends and can be used inside any class, function, or method.
Constants: Constants are also related to classes, but they are variables modified with the constant keyword, and once assigned a value, they cannot be changed. Unlike static variables, the value of a constant is determined at compile time, while the value of a static variable can change at runtime. Additionally, constants are usually used to store some fixed values, such as mathematical constants, configuration information, etc., whereas static variables are usually used to store variable data, such as counters, global states, etc.
In SrivijayaScript, access modifiers can be used to protect access to classes, variables, methods, and constructors. Java supports four different access levels.
- default (nothing is written): visible within the same package, no modifier is used. Applicable objects: classes, interfaces, variables, methods.
- private: visible within the same class. Applicable objects: variables, methods. Note: cannot modify classes (outer classes).
- public: visible to all classes. Applicable objects: classes, interfaces, variables, methods.
- protected: visible to classes in the same package and all subclasses. Applicable objects: variables, methods. Note: cannot modify classes (outer classes).
We can illustrate access levels using the following table:
| Modifier | Current Class | Current Package | Subclass within Same Package | Subclass within Different Package | Other Packages |
|---|---|---|---|---|---|
| public | Y | Y | Y | Y | Y |
| protected | Y | Y | Y | If and only if the subclass and the superclass are in the same package | N |
| default | Y | Y | Y | N | N |
| private | Y | N | N | N | N |
Chapter 4: Control Flow
While loop
While loop is the most basic loop. It shows like this:
while (condition) {
# I'm code
}
As long as the condition continues to hold, the code will keep executing until the condition no longer holds. The loop body will be executed at least 0 times, because it checks the condition before executing the loop body.
Do-while loop
do {
# I'm code
} while (condition);
It is similar to the while loop above, but the loop body will be executed at least once because the loop body is executed before the condition is checked.
For loop
for (initialization ; condition ; accumulation) {
# I'm code
}
The following points are noted about the for loop:
- The initialization step is executed first. You can declare a type, but you can initialize one or more loop control variables, or it can be an empty statement.
- Then, the boolean expression is evaluated. If it is true, the loop body is executed. If it is false, the loop terminates and the statements after the loop body begin to execute.
- After executing the loop once, the loop control variable is updated.
- The boolean expression is evaluated again. The loop executes the above process.
Enhanced For Loop for Lists and Arrays
for (type iterator : container) {
# I'm code
}
If the iterable container is a list, then the iteration variable must be of auto type (automatically inferred).
Breaking out
break;
Break out this layer of loop.
continue
Continue the next round of current loop.
If-Elseif-Else condition
if (condition1) {
# code 1
}
elseif (condition1) {
# code 2
}
else {
# code 3
}
If the condition is met, the code inside the if is executed; otherwise, other conditions are checked. If none of the conditions are met, the code inside else is executed.
An if statement can be followed by elseif…else statements, which can detect multiple possible situations.
When using if, else if, and else statements, you need to pay attention to the following points:
- An if statement can have at most 1 else statement, and the else statement comes after all the elseif statements.
- An if statement can have several elseif statements, which must come before the else statement.
- Once one of the elseif statements evaluates to true, the other elseif and else statements will be skipped.
Switch-case-default statement
switch(expression){
case value :
//Do Something
break; //Optional
case value :
//Do Something
break; //Optional
//You can have arbitary number of case statements.
default : //Optional
//Do Something
}
The switch-case statement has the following rules:
- The variable types in a switch statement can be: Int, Float, Rune, or String. Since Bool only has true and false states, it can be completely handled with if-else statements, and switch-case-default is not necessary.
- A switch statement can have multiple case statements. Each case is followed by a value to compare and a colon.
- The data type of the value in a case statement must match the variable's data type and can only be a constant or a literal constant.
- When the variable's value is equal to the value in a case statement, the statements following that case start executing until a break statement appears, which exits the switch statement.
- When a break statement is encountered, the switch statement terminates, and the program jumps to the statements following the switch. Case statements do not have to include a break statement. If no break statement appears, the program will continue executing the next case statement until a break is encountered.
- A switch statement can include a default branch, which is generally the last branch of the switch statement (it can be in any position, but it is recommended to be last). The default branch executes when no case values match the variable's value. The default branch does not require a break statement.
- When executing a switch case, matching is performed first. If a match is successful, the current case's value is returned, and then whether execution continues or exits depends on the presence of a break statement.
Chapter 5: Functions and Methods
A function, or method, is a collection of statements. It can be created in top-level code (predefined functions) or within a class (methods). It has the following four advantages:
- Makes the program shorter and clearer.
- Facilitates program maintenance.
- Can improve the efficiency of program development.
- Enhances code reusability.
A method consists of a method header and a method body. Below are all parts of a method:
- Modifiers: Modifiers are optional and tell the compiler how to call the method. They define the access type of the method.
- Return type: A method may return a value. returnValueType is the data type of the method's return value. Some methods perform the required operations but do not return a value. In this case, returnValueType is the keyword void.
- Method name: This is the actual name of the method. The method name and the parameter list together form the method signature.
- Parameter types: Parameters act like placeholders. When the method is called, values are passed to the parameters. These values are called arguments or variables. The parameter list refers to the types, order, and number of parameters of the method. Parameters are optional, and a method can have no parameters. Of course, parameters can be keyword arguments (in the format
functionName(parameterName = parameterValue)), which can prevent some quirky results, such as a user named 'Confirmed User' with a group 'Harry'. - Method body: The method body contains the specific statements that define the functionality of the method.
To create a method, you can write this:
modifier function method_name(type *args, type **kwargs) @ returning_type => {
...
method_body
...
return return_value;
}
When a program calls a method, control is transferred to the called method. Control is returned to the program when the return statement of the called method is executed or when the closing brace of the method body is reached. When a method returns a value, the method call is usually treated as a value. Void is a null type, which indicates in the method's return type that the method is a subroutine (does not return a value). Even so, to exit this method, a return statement that returns nothing should be used (although Void already indicates that it returns nothing).
Chapter 6: I/O
In the previous five chapters, we learned how to write some simple programs. Next, we will learn how to perform input and output.
Output
You may have already noticed that we used the print function in the previous programs. Now, let's talk about output in detail.
function print(Auto *args, Auto **kwargs, String seperator = " ", String final_output = "\r\n",
OutputStream file = System.stdout, Bool flush = false) @ Void;
This is the original declaration of the print function. It will output a series of values separated by a separator (default is a space), and append a final_output (default is CRLF) to the specified output stream (default is the current standard output), and specify whether to force flush the buffer (default is not to flush).
function printLn(String line, OutputStream file = System.stdout, Bool flush = false) @ Void;
This one prints just a line of string.
Input
And then, input.
function getChar() @ Rune .|IOFault|.; function read() @ Auto .|IOFault|.; function readLn() @ String .|IOFault|.; function input() @ String .!IOFault!.;
Their functions are: reading a character; reading content up to a whitespace character; reading a line of text; and reading until EOF.
Chapter 7: Error Handling
Error handling is a very critical part, as it ensures the robustness of the program. Without error handling, if a bunch of error messages are just thrown out directly, laypeople may not understand what exactly happened, and some malicious individuals (especially destructive hackers) might even use this information to attack the program.
There are many causes of exceptions, usually including the following major categories:
- The user entered illegal data.
- The file to be opened does not exist.
- The connection was interrupted during network communication, or an SVM memory overflow occurred.
Some of these exceptions are caused by user errors, some are caused by program errors, and others are caused by physical errors.
To handle an error, you can write this:
try (optional resource declaration) {
# Something risky
} catch (Exception e) {
# Error handling
} else {
# Successful
} finally {
# Runned anyway
}
To raise an error, you can write this:
throw Exception ("Errmsg")
This table shows some common exceptions and errors.
| Name | Returning Value in Hexadecimal (Not decimal | !) | Description |
|---|---|---|---|
| ArithmeticFault | 1 | Some very stupid mathematical mistakes, such as dividing any number by 0, or solving sin(x) = 2. | |
| IndexOutOfBoundFault | 2 | When accessing an array, if an index greater than or equal to the array's length (array and list indices start from 0) is accessed, or if a negative index is accessed (for list access, an index of -n represents the nth element from the end), this exception will be thrown. | |
| ValueFault | 3 | The value passed in is not a valid value. | |
| TypeFault | 4 | There is a problem when converting types, such as attempting to convert a constant type (such as an integer) into an iterable type (such as a list). | |
| UnsupportedOperationFault | 5 | Literally unsupported operations. | |
| NoSuchVarFault | A | No such variable/constant. | |
| NoSuchMethodFault | B | No such method/function/subroutine. | |
| IOFault | 12 (18 in decimal) | Some input/output errors, such as file corruption, empty files, interrupted or timed-out input/output, exceptions during object serialization or deserialization, encoding confusion (but usually it only results in garbled characters like 锟斤拷), etc. | |
| StackError | C0000001 | A stack overflow or stack underflow occurs when the program runs. Generally speaking, only those with the suffix Fault that are inherited are Exceptions, which can be detected at compile time, while those with the suffix Error are usually runtime errors, or even environmental errors. | |
| MemoryError | C0000002 | The pointer is pointing to a memory cell that should not be accessed, or the attempt to access the memory cell is denied. | |
| SecurityFault | C0000003 | An exception thrown by the security manager indicates the presence of a security violation. | |
| InternalSystemError | C0000006 | There is a problem with the environment configuration of the internal system. Please check whether your SrivijayaScript environment is properly equipped. | |
| FatalError | 1BF52 | Fatal error. Please reinstall SrivijayaScript immediately, without hesitation. | |
| ManualExitFault | FFFFFFFF | The user interrupted the program themselves. Generally, when this error is thrown, a prompt message will pop up asking whether to continue running the program. If the user inputs 'y', it will continue execution. If the user inputs 'n', the program will exit. No input is treated as 'n'. |
Volume 2: Advanced Syntax
Coming Soon.