Conventions¶
If you are familiar with almost any programming language, you should find GreyScript easy to pick up. However, GreyScript does perform some things a little differently. Let's cover some of the ABCs of GreyScript.
Syntax¶
Improper Syntax vs Proper Syntax
See the example below of incorrect vs correct syntax.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Can you spot what's wrong with the incorrect example?
- Line 1: functions should be declared as a variable
- Lines 1, 4, 6, 9 & 10: code blocks in GreyScript do not use curly braces
{ }
- Lines 2 & 6: Brackets/Parentheses should generally not be wrapped around conditional statements
- Lines 3, 7, 8 & 12: semicolons should be avoided. One line of code per line.
- Line 7: strings require
"double quotes"
- Line 8: the numerical increment operator (
++
) is not supported
One statement per line¶
In GreyScript, each code statement typically belongs on a single line. There are no semicolons (;
) or curly braces ({ }
).
Multiple statements on one line
The exception to this rule is where you want to have more compact code, by joining multiple statements on one line. While this is discouraged, it is nevertheless supported.
x = 0; while x < 10; x=x+1; print(x); end while //prints numbers 1-10
Single quotes ('like this') are not supported¶
Instead use "double quotes".
See strings
Code Blocks¶
You may be accustomed to seeing curly braces around blocks of code. In GreyScript, code blocks always begin with a keyword (if
, for
, while
, or function
) and end with a matching end statement (end if
, end for
, end while
, or end function
).
Indentation is not required for code blocks, although it does make your code blocks more readable.
Indentation Example
Both blocks A and B are valid, and perform exactly the same function, but block B uses indentation.
Block A
lastIndexOf = function(list, val)
if list.indexOf(val) == null then
return null
end if
i = 0
li = 0
for e in list
if e == val then
li = i
end if
i=i+1
end for
return li
end function
Block B
lastIndexOf = function(list, val)
if list.indexOf(val) == null then
return null
end if
i = 0
li = 0
for e in list
if e == val then
li = i
end if
i=i+1
end for
return li
end function
Whitespace¶
Between strings, numbers, and operators, spacing is optional. Additional spacing looks cleaner, but is not required.
Example
1 2 3 4 5 |
|
In the above example, lines 1 & 2 are the same as lines 4 & 5.
Case Sensitivity¶
Variable names are case sensitive.
Comments¶
Comments are a means of placing notes within your code, to remind you (or help others who are reading your code better understand) what the code is doing.
As with many other languages, comments begin with two slashes.
Example
print("Hello world!") //this line prints the message 'Hello world!'
// Another comment here
print("The above line is not processed as code")
Brackets¶
GreyScript has some unconventional behaviours when it comes to brackets (also known as parentheses).
In GreyScript, brackets are typically only used in the following three instances:
-
grouping mathematical operations
num = (1+2) * 5 // not the same as 1 + 2 * 5
-
passing arguments in function calls
print("Hello")
See passing arguments.
-
declaring a function
myFunction = function() return true end function
Brackets do not belong elsewhere (such as in if statements or while loops).
Example
You may want to write this:
if(params[0] == "y") then
while(i > 10) then
// perform miracles
i=i-1
end while
end if
Instead, write this:
if params[0] == "y" then
while i > 10 then
// perform miracles
i=i-1
end while
end if
Passing arguments¶
While in many languages, a function is called with brackets e.g. myFunction()
, in GreyScript we only use brackets when calling a function if we are passing arguments to that function.
Example
If we wish to print an empty new line, we can call the print
function without any arguments. The correct way to do this is by running simply print
, instead of print()
.
print("Something")
print
print("Something else")
Variable Scope¶
In many languages, as with GreyScript, we need to be aware of any limitations to scope.
Variables in GreyScript are always local in scope. Accordingly, each variable is scoped to the function executing at the time.
Usage Example
1 2 3 4 5 6 7 8 9 10 11 12 |
|
5
5
4
5
globals.var¶
If we need the reference to a global variable in order to modify that variable from within a function, we can use globals.
Usage Example
foo = function()
globals.bar = 0
end function
bar = 1
print(bar)
foo // call foo(), setting bar to 0
print(bar)
1
0
locals.var¶
If we need the reference to a local variable for the current function, we can use locals.
This function is largely of minimal use, because variable scope is always local, but it can help us to be clear in our code when we are seeking local scope only.
Usage Example
count = 0
state = "New York"
go = function()
globals.count = globals.count + 1
locals.state = "Mississippi"
print(globals.count + " " + state)
end function
go
go
go
print(state)
1 Mississippi
2 Mississippi
3 Mississippi
New York
Objects and Classes¶
Like many other programming languages, GreyScript utilises Object Oriented Programming (or OOP) with prototype-based inheritance. This also means that there are no differences between a class and an object.
In simple terms, this means that we have objects with their own functions, called by objectname.functionname
e.g. Computer
.lan_ip
.
Creating a Class¶
Fruit = {}
Fruit.colour = ""
Here we have established a new base class (which is essentially just a map), while providing a colour property. We have told GreyScript that our Fruit class should always have a colour property with an empty default.
Now let's create a subclass with new Fruit
, assigning this to Apple. We should also override the colour property of Fruit (apples are often green, after all).
Apple = new Fruit
Apple.colour = "green"
Now we can instantiate our Apple subclass:
a = new Apple
print(a.colour) // prints "green"
While these are essentially just maps, because they have been created with new
, these maps contain a property named __isa
, which points to the parent map. You should not need to worry about this property, other than to know two things:
- When you create a map using the
new
operator, the__isa
member is set for you. - When you look up an identifier in a map, GreyScript will walk the
__isa
chain looking for a map containing that identifier. The value returned is the first value found.
Let's add to the above, by creating a function under Fruit, which will work on any subclass.
Fruit.capitalise = function()
return slice(self.colour, 0, 1).upper + slice(self.colour, 1)
end function
print(t.capitalise) // prints "Green"
Note that the Fruit.capitalise
function is able to utilise the special self
variable, which refers to the object on which it was invoked (in this case t). Through self
, class functions can access, as well as modify, object data.
Booleans¶
In GreyScript boolean values are represented as numbers: either 1
(true) or 0
(false).
The keywords true
and false
can be used as return types in functions (e.g. return true
) but these are exactly equal to the numbers 1
and 0
respectively.
if and while¶
When using if
and while
or in any other context that evaluates the truth of a variable, anything equalling 0 will always evaluate as false, while almost anything else will evaluate as true (with the exception on empty values below).
Usage Example
fun = function()
return true // actually returns `1`
end function
if fun then
print("fun")
end if
fun
Empty Values¶
As is common in many languages, any non-empty variable (string, map, or list) will evaluate as true. Furthermore, any variable that equals null
will evaluate as false.
mylist = [] // false
mylist = ["blah"] // true
str = "" // false
str = " " // true
pam = {} // false
pam = {"a":"b"} // true
x = null // false
Control Flow¶
In GreyScript usage of if statements and loops (for and while) are straightforward, providing you remember the guidance concerning brackets, booleans, and code blocks.
if statements¶
As explained on the subject of code blocks, if statements should begin if
, and end with end if
.
if condition then
//do things
end if
A basic if statement
total = 100
if total == 100 then
print("The total is 100")
end if
The total is 100
if and else
total = 50
if total == 100 then
print("The total is 100")
else
print("The total is not 100")
end if
The total is not 100
if and else-if
total = 25
if total == 100 then
print("The total is 100")
else if total >= 10 and total < 20 then
print("The total is between 10 and 20")
else if total >= 20 and total < 30 then
print("The total is between 20 and 30")
else
print("The total is something else (" + total + ")")
end if
The total is between 20 and 30
shortcut¶
'Shortcut' if
statements are if
statements written on a single line. Both if
and if/else
are supported, although else if
is not.
Limitations:
- A single statement for the then block
- A single statement for the else block (if used)
Example
hello = 1
if hello then print("Hello!")
greeting = 0
if greeting then print("Hello!") else print("Goodbye")
for loops¶
A for loop
can loop through a list, with each iteration handling a value from the list.
for e in list
//do things with 'e'
end for
Usage Example
for i in range(10, 1)
print(i + "...")
end for
print("Liftoff!")
10...
9...
8...
7...
6...
5...
4...
3...
2...
1...
Liftoff!
strings¶
You can also use a for loop over a string, where the string is essentially split into a list of its characters.
Usage Example
fruit = "apple"
for c in fruit
print(c)
end for
a
p
p
l
e
maps¶
It is also possible to loop over a map, though in this case the iteration will equal a mini-map consisting of key
and value
. See the example below.
Usage Example
mymap = {"fruit": "apple", "colour": "orange", "vegetable": "cucumber"}
for item in mymap
print("The key '" + item.key + "' has the value: " + item.value)
end for
The key 'fruit' has the value: apple
The key 'colour' has the value: orange
The key 'vegetable' has the value: cucumber
while loops¶
If you are not familiar with while loops, they essentially loop over a block of code while a condition remains true. The block repeats infinitely, until the condition evaluates as false.
Usage Example
i = 1
while i <= 5
print(i)
i = i + 1 //without this line, i would not increase and the loop would keep running infinitely
end while
1
2
3
4
5
This example declares i
as 0
. The while loop checks whether i
is less than or equal to 5, and if so then prints i
and increases i
by 1. The while loop runs again and again, until i
has increased to 6 (which is not <= 5
) and therefore the loop ends before its sixth iteration because the condition is no longer true.
break and continue¶
As with other languages employing loops, break
and continue
operate in their usual way, in while
and for
loops
break¶
Run from inside the loop, this halts the loop
Usage Example
i = 0
while i < 5
i=i+1
print(i)
if i == 3 then
break
end if
end while
1
2
3
This stops at the number 3 because when i
equals 3, break
quits the loop after print(3)
.
continue¶
Run from inside the loop, this skips the specific iteration and the loop continues
Usage Example
i = 0
while i < 5
i=i+1
if i == 3 then
continue
end if
print(i)
end while
1
2
4
5
This does not print the number 3 because when i
equals 3, continue
skips the iteration before print is called.
Behaviour¶
While GreyScript unlocks many exciting opportunities, not everything is possible. It is important to beware of some of the limitations in GreyScript.
Script Execution¶
When working with GreyScript it is important to understand that any code is executed on the multiplayer server (or in single player, the local server), and once completed, the output is then returned to the client terminal.
It is now possible to prompt the user for information from within the terminal, (instead of requiring all parameters. In this case, script execution will continue once the user input is provided.
Filesize Limits¶
There is a limit of 80,000 characters for a compiled binary.
Terminal Output¶
There is a limit of 2,000 characters on the text any script can print to the terminal. If the script attempts to exceed this, the output will be cut down to its last 2,000 characters.