Basic Syntax
This section explains the basic syntax of LuneScript. Based on Lua's grammar, extensions have been made to enhance safety through static typing.
Comments
C++ style comments can be used in LuneScript.
//: Comment until the end of the line (single-line comment)/* ... */: Multi-line comment
// This is a single-line comment
let val = 1; // Can be written in the middle of a line
/*
This is
a multi-line
comment
*/
// (floor division) operator from Lua 5.3 is treated as a comment in LuneScript.
To perform floor division, divide between int types, use explicit casting, or use appropriate
functions.
Variable Declarations
Variables are declared using the let keyword. Since LuneScript is a statically
typed language, variables have types.
Basic Declarations
let val: int = 1;
Specify :Type after the variable name. It is common to initialize a variable at the same time as
declaration.
If the type of the initial value differs from the declared type, it results in a compilation error.
// Error: Cannot assign a real value to an int variable
let param: int = 1.5;
Type Inference
If an initial value is provided, the type declaration can be omitted. The compiler infers the type from the value on the right-hand side.
let val1 = 10; // Inferred as int
let val2 = 1.5; // Inferred as real
let val3 = "test"; // Inferred as str
let val4 = true; // Inferred as bool
You mainly need to explicit the type in cases like:
- When giving
nilas an initial value to a nilable type (T!) variable:let val: int! = nil; - When defining an empty list or map:
let list: List<int> = []; - When you want to receive a variable with a superclass type:
let obj: SuperClass = new SubClass();
Mutable and Immutable
Variables declared with let are Immutable by default. They cannot be
reassigned.
To declare a variable that can be reassigned, use the mut keyword.
let mut count = 0;
count = count + 1; // OK
let fixed = 10;
// fixed = 20; // Error: Immutable variable cannot be modified
Initialization by Flow Analysis (Uninitialized Variable Detection)
In LuneScript, you don't have to initialize a variable at the time of declaration, but it must be initialized before it is referenced.
The compiler performs flow analysis to check if a variable is initialized in all execution paths (Uninitialized Variable Detection).
fn check( flag: bool ) {
let val: int;
if flag {
val = 10;
} else {
val = 20;
}
// OK because it is initialized in all paths
print( val );
}
If a path exists where the variable is not initialized, a compilation error occurs.
fn errorCase( flag: bool ) {
let val: int;
if flag {
val = 10;
}
// Since there is no else clause, it is not initialized if flag is false
// print( val ); // Error: variable 'val' may be uninitialized
}
This initialization via flow analysis is "delayed initialization", and the mut declaration is
not required (since it is assigned only once).
Scope Blocks
The part enclosed in curly braces { ... } becomes a scope block. Variables declared inside a
block cannot be accessed from outside that block.
let outer = 1;
{
let inner = 2;
print( outer, inner ); // 1 2
}
// print( inner ); // Error: 'inner' is undefined
In LuneScript, you cannot define a variable with the same name as one already defined in an outer scope (shadowing).
This constraint prevents accidental reference errors.
let val = 1;
{
// Error: shadowing symbol of val
// let val = 2;
}