日本語

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.

// This is a single-line comment
let val = 1; // Can be written in the middle of a line

/*
  This is
  a multi-line
  comment
*/
Note that the // (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:

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
Prohibition of Shadowing:
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; 
}