Skip to content

Arbiter Script Syntax


Arbiter scripts use the same Platypus language syntax as Pipeline.

Identifiers and Keywords

Identifiers

Identifiers are used to identify objects and can represent variables, functions, etc. Identifiers include keywords; custom identifiers cannot duplicate keywords.

Identifiers consist of numbers (0-9), letters (A-Z a-z), and underscores (_), but cannot start with a number and are case-sensitive. For example:

  • _abc
  • abc
  • abc1
  • abc_1_

If an identifier needs to start with a non-letter or non-underscore character, or contains special characters, it must be enclosed in backticks, such as:

  • 1abc
  • @some-variable
  • 这是一个表情包变量👍

Keywords

Keywords are words with special meanings, such as if, elif, else, for, in, break, continue, nil, etc., and cannot be used as variable names, constant names, or function names.

Comments

Use # as the line comment symbol; inline comments are not supported. For example:

# This is a line comment
a = 1 # This is a line comment

"""
This is a (multi-line) string, used as a comment
"""
a = 2

"String"
a = 3

Built-in Data Types

The value of a variable can change dynamically, but each value has a clear data type, which is divided into Basic Types and Composite Types.

Basic Types

Integer (int) Type

The integer type is a 64-bit signed integer, currently only supporting decimal representation, such as -1, 0, 1, +19.

Float (float) Type

The float type is a 64-bit signed floating-point number, currently only supporting decimal representation, such as -1.00001, 0.0, 1.0, +19.0.

Boolean (bool) Type

The boolean type has only two values: true and false.

String (str) Type

Strings can be defined with double or single quotes, and multi-line strings can be enclosed in triple double or single quotes, for example:

  • "hello world"
  • 'hello world'
  • Use """ to express multi-line strings
"""hello
world"""
  • Use ''' to express multi-line strings
'''
hello
world
'''

Composite Types

Composite types include map and list, which are reference types. Multiple variables can point to the same object, and no memory copy is performed during assignment.

Map Type

map is a key-value pair structure, where keys can only be strings, and values can be of any type. Elements are read and written through index expressions, for example:

a = {
  "1": [1, "2", 3, nil],
  "2": 1.1,
  "abc": nil,
  "def": true
}

# Since a["1"] is a list object, b only references the value of a["1"]
b = a["1"]

"""
Now a["1"][0] == 1.1
"""
b[0] = 1.1

List Type

list can store any number of values of any type, and elements are read and written through index expressions, for example:

a = [1, "2", 3.0, false, nil, {"a": 1}]

a = a[0] # a == 1

Operators

Platypus supports the following operators, listed in order of precedence from lowest to highest:

Precedence Symbol Associativity Description
1 `=` Right Assignment; named parameters; lowest precedence
1 `+=` Right Assignment, left operand = left operand + right operand
1 `-=` Right Assignment, left operand = left operand - right operand
1 `*=` Right Assignment, left operand = left operand * right operand
1 `/=` Right Assignment, left operand = left operand / right operand
1 `%=` Right Assignment, left operand = left operand % right operand
2 `||` Left Logical "OR"
3 `&&` Left Logical "AND"
4 `in` Left Check if key is in map; check if element is in list; check if substring is in string
5 `>=` Left Condition "greater than or equal to"
5 `>` Left Condition "greater than"
5 `!=` Left Condition "not equal to"
5 `==` Left Condition "equal to"
5 `<=` Left Condition "less than or equal to"
5 `<` Left Condition "less than"
6 `+` Left Arithmetic "addition"
6 `-` Left Arithmetic "subtraction"
7 `*` Left Arithmetic "multiplication"
7 `/` Left Arithmetic "division"
7 `%` Left Arithmetic "modulus"
8 `!` Right Unary operator; logical "negation", can be used with the 6 built-in data types
8 `+` Right Unary operator; positive sign, can be used to represent positive numbers
8 `-` Right Unary operator; negative sign, used to flip the sign or represent negative numbers
9 `[]` Left Subscript operator; can use list index or map key to get values
9 `()` Left Can change operator precedence; function call

Expressions

Platypus uses the comma , as the expression separator. Expressions can have values, while statements do not have values.

Literal Expressions

Literal values of various data types are expressions, such as integers 100, -1, 0, floats 1.1, boolean values true, false, etc.

Literal expressions for composite types are as follows:

  • List literal expressions
[1, true, "1", nil]
  • Map literal expressions
{
  "a": 1,
  "b": "2",
}

Call Expressions

The following is a function call to get the number of elements in a list:

len([1, 3, "5"])

Binary Expressions

Binary expressions consist of a binary operator and left and right operands.

In the current version, assignment expressions are considered binary expressions and have return values; however, since assignment expressions may cause issues, this syntax will be removed in the future, and assignment statements will be added instead.

# 0
2 / 5

# 0.4, the type of the left operand is promoted to float during calculation
2 / 5.0

# true
1 + 2 * 3 == 7 && 1 <= 2


# Due to the right associativity of the `=` operator, a = (b = 3), a == 3
b == 3;
a = b = 3

# Note: Since the assignment expression syntax will be deprecated, please replace it with assignment statements
b = 3
a = b

"a"   in  [1,"a"]   # true
"def" in  "abcdef"  # true
"a"   in  {"a": 1}  # true
"b"   in  {"a": 1}  # false

x = 1; y= [1]
x in y  # true

Index Expressions

Use the [] subscript operator to manipulate elements of list or map.

You can use index expressions to get or modify elements of list or map, or add elements to map. For lists, negative indices can be used.

Syntax Example:

a = [1, 2 ,3, -1.]
b = {"a": [-1], "b": 2}

a[-1] = -2
b["a"][-1] = a[-1]

# Result
# a: [1,2,3,-2]
# b: {"a":[-2],"b":2}

Parentheses Expressions

Parentheses expressions can change the precedence of operands in binary expressions but cannot change associativity:

# 1 + 2 * 3 == 7

(1 + 2) * 3  # == 9

Statements

All expressions in Platypus can be considered value statements. When an expression ends with the statement separator ; or \n, it is considered a statement. For example, the following script contains four statements:

len("abc")
1
a = 2; a + 2 * 3 % 2

Value Statements (Expression Statements)

An expression followed by a statement separator can be considered a value statement. The following are four valid statements:

# Float as a statement
1.;

# Function call expression as a statement
len("Hello World!"); len({"a": 1})

# Identifier as a statement
abc

Assignment Statements

Syntax Example:

key_a = "key-a"

# Identifier a as the left operand, assigning a list literal to a
a = [1, nil, 3]

# Index expression as the left operand
a[0] = 0
a[2] = {"key-b": "value-b"}
a[2][key_a] = 123

Conditional Statements

Similar to most programming languages, depending on whether the condition of if/elif is met, the corresponding block of statements is executed. If none are met, the else branch is executed.

if condition {

}
if condition {

} else {

}
if condition_1 {

} elif condition_2 {

} ... elif condition_n {

} else {

}

Currently, condition can be any expression, as long as its value is one of the built-in data types. When the value is the default value of the type, the expression value is false:

  • When the condition is of type int, if it is 0, the condition is false; otherwise, it is true
  • When the condition is of type float, if it is 0.0, the condition is false; otherwise, it is true
  • When the condition is of type string, if it is an empty string "", the condition is false; otherwise, it is true
  • When the condition is of type bool, the condition is the current value
  • When the condition is of type nil, the condition is false
  • When the condition is of type map, if its length is 0, the condition is false; otherwise, it is true
  • When the condition is of type list, if its length is 0, the condition is false; otherwise, it is true

Loop Statements

Platypus supports for statements and for in statements.

The following are two statements that can only be used within loop statement blocks:

  • continue statement, skips the remaining statements and continues to the next iteration
  • break statement, ends the loop

Using for statements may cause infinite loops, so they should be used with caution, or for in statements should be used instead whenever possible.

for init-expr; condition; loop-expr {

}
for varb_name in map_value/list_value/string_value  {

}

Usage Examples:

  • Using for to execute a loop 10 times:
for a = 0; a < 10; a = a + 1 {

}
  • Using for in to iterate over all elements of a list:
b = "2"
for a in ["1", "a" ,"2"] {
  b = b + a
  if b == "21a" {
    break
  }
}
# b == "21a"
  • Using for in to iterate over all keys of a map:
d = 0
map_a = {"a": 1, "b":2}
for x in map_a {
  d = d + map_a[x]
}
  • Using for in to iterate over all characters of a string:
s = ""
for c in "abcdef" {
  if s == "abc" {
    break
  } else {
    continue
  }
  s = s + "a"
}
# s == "abc"