Lumesh Syntax Manual 1 (Basic Syntax)
I. Variables and Types
1. Variable Declaration and Assignment
Declare Variables: Use the
let
keyword, supporting multiple variable declarations. Types are automatically assigned based on the value.let x = 10 # Single variable
let a, b = 1, "hello" # Multiple variable assignments (the number of expressions on the right must match)
let a, b, c = 1 # Uniform assignment for multiple variables
let a = b = 1 # Chained assignment for multiple variablesAssignment Operators:
=
: Regular assignment.:=
: Delayed assignment (stores the expression as a reference).
x := 2 + 3 # Delayed evaluation, stores the expression rather than the result
echo x # Outputs the expression: 2 + 3
eval x # Outputs the result: 5Delete Variables: Use
del
.del x
Using Variables: Optional
$
, directly useecho a x
.
Strict mode requires $: echo $x
- Check Variable Type:
let a = 10
type a # Integer
type a == "Integer" # True
Edge Cases:
- In strict mode (
-s
), variables must be initialized; otherwise, an error will occur. - When declaring multiple variables, the number of expressions on the right must match the number of variables on the left or be a single value; otherwise, a
SyntaxError
will be thrown.
2. Data Types
Basic Types
Type | Example |
---|---|
Variable | x , $a |
Integer | 42 , -3 |
Float | 3.14 , -0.5 , 10% |
String | "Hello\n" , 'raw' |
Boolean | True , False |
List (Array) | [1, "a", True] |
Map (Dictionary) | {name: "Alice", age: 30} |
Range | 1..8 , 1..<10 |
Regex | r'^\w+' |
Time | t'2025-5-20' |
File Size | 4K , 5T |
Null | None |
Complex Types
Type | Example |
---|---|
Function | fn add(x,y){return x+y} |
Lambda | let add = (x,y) -> x + y |
Built-in Library | Math.floor |
Scope Rules
- Lambda and function definitions create a child environment scope.
- Child environments inherit parent environment variables without modifying the parent scope.
Strings
Single quotes denote raw strings.
Double quotes support text escaping (e.g.,
\n
), Unicode escaping (e.g.,\u{2614}
), and ANSI escaping (e.g.,\033[34m
).Backticks denote template strings, supporting
$var
variable substitution and${var}
sub-expression execution capture, as well as ANSI escape characters.print "Hello\nworld!\u{2614}"
Hello # Outputs two lines, \n is escaped to a newline
world!☔ # Unicode escape, \u{2614} is the umbrella character
let str2 = 'Hello\nworld!'
Hello\nworld! # Outputs one line, including the raw form of \n
let a = [1,2,5]
print `a is $a, and a[0] is ${a[0]}`
print "\033[31mRed msg\033[m" # Outputs red "Red msg"Variable substitution within backticks is more efficient than sub-expression capture; it is recommended to use the former unless necessary.
Edge Cases:
The
\
in single-quoted strings is treated literally (e.g.,'Line\n'
outputsLine\n
).
Undefined escape sequences will throw an error, such as:echo "Hello\_"
[PARSE FAILED] syntax error: invalid string escape sequence `\_`
|
1 | echo "Hello\_"
|
File Size Type:
Composed of an integer followed by a unit, supporting the following units:
"B" "K" "M" "G" "T" "P"
Lumesh will automatically recognize the unit and output in a human-readable format, for example:
print 3050M 1038B 3000G
# Output
2.98G 1K 2.93T
File size types can participate in calculations.
For example:
1M > 30K # Returns True
Fs.ls -l | where(size > 20K) # Filter files larger than 20K
Date and Time Type
For example: Fs.parse('2025-5-20')
Date and time types can participate in calculations.
For example:
Fs.parse('2025-5-20') > Fs.parse('2025-1-20') # Returns True |
For specific operations, please refer to the built-in function time
module.
Percentage
Written as a percentage, it will automatically be recognized as a float.
print 37% 2% + 3 |
The percentage sign immediately following a number denotes a percentage, while a space followed by % denotes a modulus operation.
II. Operators
1. Operator Classification and Precedence
Precedence from high to low (the higher the number, the higher the precedence)
Precedence | Operator/Structure | Example/Description |
---|---|---|
13 | Parentheses () |
(a + b) * c |
12 | Unary Operators ! , - , __.. |
!flag , -5 |
11 | Exponentiation ^ |
2 ^ 3 |
10 | Multiplication/Division/Modulus * , / , % , _*.. |
a * b % c |
9 | Addition/Subtraction + , - , _+.. |
a + b - c |
8 | Comparison == , != , > etc. |
a > b |
7 | Logical AND && |
cond1 && cond2 |
6 | Logical OR ` | |
5 | Conditional Operator ? : |
cond ? t : f |
4 | Lambda Expression | x -> x + 1 |
3 | Error Handling ?: ?. |
3 / 0 ?: 1 |
2 | Pipeline ` | ` |
Redirection << >> >! |
date >> /tmp/day.txt |
|
1 | Assignment = , := |
x = 5 , let y := 10 |
Pipelines and redirections are on the same level, while logical operations have higher precedence than pipelines and redirections.
2. Space Rules
Operator Type | Requires Spaces | Example |
---|---|---|
Regular Operators | Spaces on both sides | a + b , x <= 10 |
In non-strict mode, some symbols can omit spaces | a+b , x<=10 , a=5 |
|
- and / should have spaces |
b-3 is a string, 3- b is subtraction |
|
Custom Operators | Must start with an underscore and have spaces on both sides | x _*+ y , a _?= b |
Suffix operators must start with double underscores and have spaces | x __*+ |
|
Prefix Operators | Space before or at the start, no space after | !x , -7 |
Infix Operators | No spaces before or after | dict.key , 1..9 |
Suffix Operators | No spaces before or after | func(a) , array[i] , 10M |
Future deprecation, not recommended | a++ , a-- |
a--
is recommended to be replaced with a -= 1
Because --
is commonly used for parameter passing in shells, it is not advisable to use a--
or a++
.
Custom Operators
Custom operators start with
_
and can only contain symbols, not numbers or letters.Custom unary operators start with
__
, such as__+
, with precedence equal to unary operators. They can only be used as suffix operators.Custom addition-level operators start with
_+
, such as_+%
, with precedence equal to+
and-
.Custom multiplication-level operators start with
_*
, such as_*-
, with precedence equal to*
and/
.let __++ = x -> x + 1;
3 __++
Edge Cases:
x++y
is illegal, whilex+++y
is legal.
3. Special Operators
==
Type-equal comparison.~=
Value-equal comparison.~~
String regex match.~:
Contains (can be used for strings, arrays, ranges, dictionaries (to check for a specified key)).!~~
String regex not match.!~:
Does not contain.
Examples:
5 == "5" # False |
4. Overloaded Operators
Addition +
Numbers
Number + Number = High-precision addition
1 + 2.5 # → 3.5
Number + String = Value addition
1 + "2.5" # → 3.5
Number + List = Sum together
1 + [2.5, 3] # → 6.5
Strings
String + String = String concatenation
"1" + 2.5 # → "12.5"
String + List = Concatenation
"1" + [2, 3] # → "123"
Ranges
- Range + Integer = Range expansion (positive from the tail, negative from the head)
0..8 + 2 # → 0..10
0..8 + (-2) # → 2..8
Lists
List + List = List merging
[1, 2] + [3, 4, 5] # → [1, 2, 3, 4, 5]
List + Other = Insert value into the list
[1] + 2.5 # → [1, 2.5]
Maps
Map + Map = Map merging
{a: b} + {c: d} # → {a: b, c: d}
Map + Other = Insert value into the map
{a: b} + c # → {a: b, c: c}
Other cases will throw an exception.
Subtraction -
Numbers
Number - Number = High-precision subtraction
1 - 2.5 # → -1.5
Number - String = Value subtraction
1 - "2.5" # → -1.5
Strings
String - String = String removal (first occurrence)
"i am lume" - "a" # → "i m lume"
String - Float = String removal (first occurrence)
"i am lume v4.2" - 4.2 # → "i am lume v"
String - Integer = String removal (positive from the tail, negative from the head)
"98101" - 1 # → "9801"
"98101" - (-2) # → "101"Exceeding the length will return an empty string.
Ranges
- Range - Integer = Range scaling (positive from the tail, negative from the head)
0..8 - 2 # → 0..6
0..8 - (-2) # → -2..8
Lists
List - List = List difference
[1, 2, 3, 4, 5] - [3, 4, 5] # → [1, 2]
List - Other = List removal
[1, 2, 3] - 2 # → [1, 3]
Maps
Map - Map = Map difference
{a: b, c: d} - {c: d} # → {a: b}
Map - Other = Remove key from the map
{a: b, c: d} - c # → {a: b}
Other cases will throw an exception.
Multiplication *
Numbers
- Number * Number = Number multiplication
2 * 2.5 # → 5
- Number * String = Value multiplication
2 * "2.5" # → 5
Strings
String * Integer = String repetition
"2" * 5 # → "22222"
List * List = Matrix multiplication
[[1, 2, 3], [4, 5, 6]] * [[7, 8], [9, 10], [11, 12]]
# → Returns
+----------+
| C0 C1 |
+==========+
| 58 64 |
| 139 154 |
+----------+Matrix multiplication requires correct dimensions.
If there are missing elements internally, calculations will be filled with 0.List * Number = Each element multiplication
[1, 2, 3] * 2.5 # → [2.5, 5, 7.5]
Division /
Numbers
- Number / Number = Number division
5 / 2 # → 2
5 / 2.0 # → 2.5 - Number / String = Value division
5 / "2" # → 2
5.0 / "2.5" # → 2
Lists
- List / Number = Each element division
[2, 4, 6] / 2 # → [1, 2, 3]
Other +=
-=
*=
/=
Only applicable to numerical operations.
For uninitialized variables, they are automatically initialized to 0.
Unlike arithmetic operations, non-numeric types will return None instead of throwing an exception.
For example:
a += 1 # → 1 |
Edge Cases:
- Division by zero will throw an error.
5. Implicit Type Conversion
When performing operations between numbers, automatic conversion to higher precision types occurs.
When adding different types of data, it always attempts to automatically convert to the type of the first data.
# Non-strict mode |
III. Ranges, Lists, and Maps
1. Ranges
Range expressions
Ranges use..<
(left-closed, right-open) or..
(closed range), with no spaces on either side.
Supports variable expansion.0..<10 # Excludes 10
0..10 # Includes 10
a..bRange expressions support stepping:
:step
0..6:2 # Represents step of 2: [0, 2, 4, 6]
Can be used for loops, containment checks, array creation, etc.
let r = 0..8
for i in r {...} # More efficient than looping directly over an array
r ~: 5 # Check if it contains an element
List.from(r) # Convert to an array
2. Lists (Arrays)
Lists are represented with
[]
. The elements inside are ordered.They can also be created directly from ranges using
...
or...<
.0...5 # Outputs [0, 1, 2, 3, 4]
# Equivalent to
List.from(0..5)
Two dots ..
..<
create ranges, while three dots ...
...<
create arrays.
Indexing is done using
.
or[i]
.let arr = [10, "a", True]
Indexing and Slicing
# Basic indexing
arr.1
arr[0] # → 10
# Slicing operations
arr[1:3] # → ["a", True] (left-closed, right-open)
arr[::2] # → [10, True] (step of 2)
arr[-1:] # → True (slicing supports negative indexing)Complex Nesting
# Complex nesting
[1, 24, 5, [5, 6, 8]][3][1] # Displays 6
# # Modify elements
# arr[2] = 3.14 # → [10, "a", 3.14]Advanced Operations
Refer to the list module.
Edge Cases:
- Accessing an out-of-bounds array index will trigger an
out of bounds
error. - Array slicing supports negative indices, counting from the end.
- Indexing a non-indexable object will trigger the following error:
[ERROR] type error: expected indexable type (list/dict/string), found symbol
3. Maps (Dictionaries)
Maps are represented with
{}
.let mydict = {name: "Alice", age: 30}
# Allows shorthand:
let a = b = 3,
{a, b}
{
a,
b,
} # Allows trailing commas, allows multi-line writing
{a, } # A single key-value's comma cannot be omittedDictionary Indexing
# Basic access
mydict["name"] # → "Alice"
mydict.name # → "Alice" (shorthand)
mydict@name # → "Alice" (shorthand)
# Dynamic key support
let key = "ag" + "e"
dict[key] # → 30
# Nested access
let data = {user: mydict}
data.user.age # → 30Advanced Operations
Refer to the map module.
Edge Cases:
Scenario | Behavior |
---|---|
Accessing a non-existent array index | Triggers [ERROR] key x not found in map error |
Indexing a non-dictionary object | Triggers [ERROR] not valid index option error |
Indexing an undefined symbol | Returns a string, as file name operations are common in shell |
Indexing an undefined symbol | Returns a string, as file name operations are common in shell |
IV. Statements
Statement Blocks
Represented with{}
. Generally used for control flow statements.Statement Groups (Sub-command Capture)
Use parentheses to represent sub-commands; sub-commands do not create new processes and do not isolate variable scopes.
echo (len [5, 6])
Statements
Separate with;
orenter
.
Newline:
;
or enter.Continuation: Use
\
+ newline for multi-line writing.let long_expr = 3 \
+ 5 # Equivalent to "3 + 5"
let long_str = "Hello
World" # Equivalent to "Hello\n World"Note: Content within quotes does not require a continuation character.
- Comments
Comments start with#
.
V. Control Structures
Conditional Statements
If Condition
Supports nesting:
if cond1 { ... } else if cond2 { ... } else { ... }
Does not use the then
keyword; code blocks are wrapped in {}
.
if True {1} else {if False {2} else {3}} |
Match Statement
Replaces the switch statement in bash.
Supports matching multiple options in one branch, separated by commas.
Supports regex matching, which needs to be wrapped in ‘’ or “”.
Supports literal matching directly, which will not be interpreted as a variable.
To improve matching efficiency, it is recommended to only write regex in quotes; ordinary strings should be written as literals.
let fruit = "apple" |
Loop Statements
Repeat Loop
repeat 10 {a += 1} # Outputs [1, 2...10] |
For Loop
for i in 0..5 { # Outputs 0, 1, 2, 3, 4 |
Supports * expansion.
While Loop
let count = 0 |
Loop Loop
let count = 0 |
Statement Expressions
Control statements can also be used as expressions:
let a = if b > 0 {5} else {-5}
Conditional expressions
a = c > 0 ? t : f
Supports nesting.
For information on functions, commands, pipelines, error handling, etc., please continue reading:
For information on function libraries, please read: