Statements
A Luna program is basically a list of statements, called a Chunk.
Chunk
A list of statements with no seperator
Block
Just a list of statements like a Chunk, but it requires {
at the start and }
at the end.
Statement
A statement has a lot of variants, like let-bindings, function definitions, etc. But it also can as well just be a Block
Let Binding
This is what you define local variables with. The assignees can be simple identifiers or object/vector destructurings.
Examples: let a = 1
, let { name, age } = person
, let [first, second, third] = numbers
Let-Else Binding
Like a Let Binding, except if the assigned value is null
, the else block will be executed
let name = person.name else {
print("no name :(")
return null
}
Assign
This is how you assign new values to existing variables. The assignees can be simple identifiers or a field/index into an object/vector
Examples: a = 2
Assign Operation
Written the same way as Assign expect with any of the following assign operators, only one assignee and only one expression:
assign operators |
---|
+= |
-= |
*= |
/= |
^= |
%= |
Examples: a += 1
, b *= 2
Call
This is to call functions with arguments. The callee can either be a simple identifier or a field/index of an object/vector.
Examples: print("Hello, World!")
, self.add(1)
Self Call
Just like a Call only written with a :
followed by an identifier. This calls the function with the first argument being the value before the :
. This is used to call objects with themselfs for object-oriented design patterns.
Examples: vector:push(1)
, person:greet()
Function Definition
This is used to globally define functions with parameters.
Examples:
fn add(a, b) {
return a + b
}
Let-Function Definition
This is used to locally define functions with parameters in the current scope.
Examples:
let fn add(a, b) {
return a + b
}
If-Branch
Classical if-branch like any other. Has an optional else-case which can either be a block or another if-branch.
Examples:
if cond {
print("yay")
}
if cond {
print("yay")
} else {
print("nay")
}
if cond {
print("yay")
} else if cond2 {
print("semi-yay")
}
If-Branch
Assignes the right side of the equal to the parameter on the left and only enters the branch, if the value is not null
.
Examples:
if let name = person.name {
print(name)
}
if let name = person.name {
print(name)
} else {
print("anonymous")
}
if let name = person.name {
print(name)
} else if let nickname = person.nickname {
print(nickname)
}
Match
Classical match-case statement to check over multiple variants of one value.
Examples:
match cmd {
"exit" => { os.exit() }
cmd if cmd:len() > 0 => {
print("invalid command: %s":format(cmd))
}
cmd => {}
}
While-Loop
Classical while-loop like any other. body has to be a block
Examples:
while a < 10 {
a += 1
}
While-Let-Loop
Assigns the right side of the equals to parameter on the left side. If it is null
, the loop is exited.
Examples:
while let n = range:next() {
print(n)
}
For-Loop
Python-like for-loop that requires an iterable to be right of the in
keyword. Only one variable can be given for each iteration. An iterable can either be an user-object with a next
method, an object with the meta variable __next
which is a function, or just a function.
Examples:
for n in [1, 2, 3]:iter() {
print(n)
}
for key in keys(map) {
print(key, map[key])
}
Return
This is used to return a value to the caller and end execution of the current function.
Examples: return a + b
, return null
Break
This is used to break out of any loop.
Examples:
while true {
if a >= 10 {
break
}
a += 1
}
Continue
This is used to continue to the next iteration of the loop.
Examples:
for n in numbers:iter() {
if n == 5 {
continue
}
print(n)
}