Reserved Words And Their Meanings
The Squirrel language defines more than 30 keywords. These are reserved names and must not be used for variable identifiers. The list below is intended to be used as a quick look-up reference to these keywords. For a fuller description of their functionality and examples of their use, see the Squirrel Programming Guide.
Provides access to the methods and properties of a class’ parent class. Child classes are declared using the extends
keyword.
See extends and instanceof, below.
Causes the execution of a switch... case
, do... while
or while...
structure to come to an end.
See switch and foreach, below.
Indicates a block of code to be run if the variable tested in a switch... case
structure matches the value specified by the case
statement.
See switch and function, below.
Part of a try... catch
structure, it indicates the code to be run if an exception is raised by the code indicated by try
.
See try, below.
Indicates the start of a class definition.
class SensorClass() {
_i2c = null;
constructor(i2c) {
if (!(i2c in hardware)) throw "SensorClass() called with an I2C object not available on this imp";
if (i2c == null) throw "SensorClass() must be called with a non-null I2C object";
// Store the I2C object in the private property
_i2c = i2c;
}
}
See also extends and instanceof, below.
A function used to create a duplicate reference to the passed object. It does not perform a deep copy of the object: in the first example below, the two logged references will be different, but references to member objects will be the same. You can use code like that shown in the second example to perform a copy of member objects.
local anInstance = MyClass();
local anInstanceCopy = clone anInstance;
server.log(" anIstance address: " + anInstance);
server.log("anInstanceCopy address: " + anInstanceCopy);
function deepCopy(container) {
// Container must not have circular references
switch (typeof container) {
case "table":
local result = clone container;
foreach( k,v in container) result[k] = deepCopy(v);
return result;
case "array":
return container.map(deepCopy);
default: return container;
}
}
Indicates a class’ initialization function, called automatically when the class is instantiated.
See class, above.
Causes Squirrel to return to the point after the last break
statement it processed, or to proceed directly to the next iteration of a loop.
local config = getcurrentconfig();
server.log("Config Name: \"" + config.name + "\"");
foreach (key, value in config) {
// We've displayed the config's name (a string), so skip when we come to config.name
if (key == "name") continue;
// Iterate through the config's value (a table) key
foreach (subKey, subValue in value) {
server.log(subKey + ": " + (typeof subValue == "string" ? subValue : ("raw data of length " + subValue.len() + " bytes")));
}
}
Marks the following identifier as a constant. Only strings, integers and/or floats can be specified.
// ********** CONSTANTS **********
const DISCONNECT_TIMEOUT = 60;
const RECONNECT_TIMEOUT = 15;
const TICK_DURATION = 0.5;
const ALARM_DURATION = 2;
const ALARM_STATE_OFF = 0; // Alarm silent, ie. off
const ALARM_STATE_ON = 1; // Alarm triggered, ie. on
const ALARM_STATE_DONE = 2; // Alarm completed, can be deleted
const LED_ANGLE = 0;
Marks the default condition in a switch... case
structure. The code block that follows is executed if none of the structure’s case
conditions have been met.
See switch and function, below.
Removes the named key and value pair from a Squirrel table.
if ("done" in alarm) {
delete alarm.done;
}
Marks the start of a do... while
loop structure in which the condition for execution of the code within the structure is evaluated each time the loop completes, ie. the loop will always be executed at least once.
// Remove all complete alarms, ie. alarms marked 'done'
// As this modifies the source array, 'alarms', we can't
// enumerate it with foreach
local i = 0;
do {
local alarm = alarms[i];
if (alarm.done) {
// Alarm complete, so remove it from the list
alarms.remove(i);
} else {
i++;
}
while (i < alarms.len());
May be used as part an if
conditional structure to indicate code to be run if the if
statement’s condition is not met.
See if, below.
Marks the following identifiers as a series of sequential constants. Only strings, integers and/or floats can be included, and types can be mixed.
enum HT16K33_MATRIX_CLASS {
REGISTER_DISPLAY_ON = "\x81",
REGISTER_DISPLAY_OFF = "\x80",
REGISTER_SYSTEM_ON = "\x21",
REGISTER_SYSTEM_OFF = "\x20",
DISPLAY_ADDRESS = "\x00",
I2C_ADDRESS = 0x70,
UPDATE_INTERVAL = 0.05
}
server.log(HT16K33_MATRIX_CLASS.I2C_ADDRESS); // Displays '112'
Used as part of a class definition, it indicates that the class inherits the methods and properties of the named parent.
class Parent {
function answer() {
return 42;
}
}
class Child extends Parent {
// Child overrides Parent's 'answer()' with its own version
function answer() {
return "Forty-two";
}
function originalAnswer() {
return base.answer();
}
}
local a = Parent();
local b = Child();
// Call each instance's 'answer()'
server.log(a.answer()); // Displays '42'
server.log(b.answer()); // Displays 'Forty-two'
// Call the parent's original 'answer()' via 'base'
server.log(b.originalAnswer()); // Displays '42'
See also instanceof, below.
One of two possible Boolean outcomes of a conditional statement.
Defines a loop structure using an index variable. The statement includes the initial state of the index variable, the condition that must be met for the loop to end, and an expression to increase or decrease the value of the index variable each time the loop is executed.
// Iterate through the list of alarms to see if any should fire
if (alarms.len() > 0) {
for (local i = 0 ; i < alarms.len() ; i++) {
local alarm = alarms[i];
local now = date();
if (!alarm.on && alarm.hour == now.hour && alarm.mins == now.min) {
alarm.on = true;
display.triggerAlarm();
// We can only display one alarm at once, so we can stop
// iterating through the list of alarms
break;
}
}
}
Defines a loop structure by stepping through all the members of a collection data structure such as an array or table. Since Squirrel classes and class instances are stored in table structures, their members may also be stepped through in a foreach loop.
Iterating a table takes two variables before in
and these take the key and value in each iteration. Iterating an array typically takes one variables before in
(for the value of each element) but may take two: the first receives the index of the element in the array. This is shown in the second example below.
Note When enumerating a table with foreach
, do not add or remove keys within the foreach
loop.
// Table
foreach (key, value in myTable) {
server.log("Key \"" + key + "\" has the value " + value);
}
// Array
foreach (index, value in myArray) {
server.log(index + ". " + value);
}
if (alarms.len() > 0) {
foreach (alarm in alarms) {
local now = date();
if (!alarm.on && alarm.hour == now.hour && alarm.mins == now.min) {
alarm.on = true;
display.triggerAlarm();
// We can only display one alarm at once, so we can stop
// iterating through the list of alarms
break;
}
}
}
Marks the following block of code as a function.
function jsonencode(o, i = 0) {
local e = " ";
local p = "";
if (i > 0) {
for (local j = 0 ; j < i ; j++) p += " ";
}
// Branch on type of object being processed
switch (typeof o) {
// The following are a containers, so iterate through them
case "table":
local t = "";
foreach (k, v in o) {
if (t != "") t += "," + (!c ? "\n " + p : "");
t += e + jsonencode(k, i + k.len() + 7) + e + ":" + e + jsonencode(v, i + k.len() + 7);
}
return "{" + t + e + "}";
case "array":
local a = "";
foreach (v in o) {
if (a != "") a += "," + e;
a += jsonencode(v, i + a.len() + 2);
}
return "[" + e + a + e + "]";
// The following are not containers, so just return their value
case "string":
return "'" + o + "'";
case "integer":
case "float":
return o.tostring();
case "bool":
return o ? "true" : "false";
// Unsupported entities (functions, blobs, classes, instances) are
default:
return "'" + typeof(o) + "'";
}
}
Indicates a block of code which will be executed only if the accompanying expression evaluates to true
.
if (value > threshold) {
doHigher();
} else if (value < threshold) {
doLower();
} else {
doSame();
}
Checks for the presence of a name entity within the members of a collection data structure such as an array or table. Since Squirrel classes and class instances are stored in table structures, their members may also be tested using in
.
See delete and foreach, above.
Tests if an object is an instance of a particular class.
class Parent {
function answer() {
return 42;
}
}
class Child extends Parent {
function answer() {
return "Forty-two";
}
}
class Kid {
function answer() {
return 2001;
}
}
local a = Parent();
local b = Child();
server.log(b instanceof Kid); // Displays 'false'
server.log(b instanceof Child); // Displays 'true'
server.log(b instanceof Parent); // Displays 'true'
Marks the following variable’s scope as being local to the context or structure in which it is being defined.
See switch, below.
Squirrel’s name for a zero-value quantity.
// Cancel the 'Sync' display timer if it has yet to fire
if (syncTimer != null) imp.cancelwakeup(syncTimer);
syncTimer = null;
local aTable = { "keyOne": 42, "keyTwo": "forty-two", "keythree": null };
foreach (key, value in aTable) {
if (value != null) server.log("Key \"" + key + "\" has value " + value);
}
Triggers the execution of a generator function previously suspended with a yield
statement.
resume
, please see ‘Squirrel Generator Functions’Triggers the end of the execution of a function and returns the following value, if any.
See function, above.
Marks a scalar properties of a class as common to all instances of that class, ie. all instances share the variable. In Squirrel, all non-scalar members of a class are implicitly static, but can be made unique to the instance by assigning them in a constructor function.
class HT16K33Matrix {
// Mark 'VERSION' as common to all instances of HT16K33Matrix
static VERSION = "2.0.0";
Marks the start of a conditional structure in which the following variable is compared to a series of case values and code executed from the point at which the case value and variable value coincide. Execution continues from this point to the end of the structure unless a break statement is included.
// Rotate an 8-integer matrix through the specified angle in 90-degree increments:
// 0 = none, 1 = 90 clockwise, 2 = 180, 3 = 90 anti-clockwise
function _rotateMatrix(inputMatrix, angle = 0) {
if (angle == 0) return inputMatrix;
local a = 0;
local lineValue = 0;
local outputMatrix = blob(8);
// NOTE It's quicker to have three case-specific code blocks than a single, generic block
switch(angle) {
case 1:
for (local y = 0 ; y < 8 ; y++) {
lineValue = inputMatrix[y];
for (local x = 7 ; x > -1 ; --x) {
a = lineValue & (1 << x);
if (a != 0) outputMatrix[7 - x] = outputMatrix[7 - x] + (1 << y);
}
}
break;
case 2:
for (local y = 0 ; y < 8 ; y++) {
lineValue = inputMatrix[y];
for (local x = 7 ; x > -1 ; --x) {
a = lineValue & (1 << x);
if (a != 0) outputMatrix[7 - y] = outputMatrix[7 - y] + (1 << (7 - x));
}
}
break;
default:
for (local y = 0 ; y < 8 ; y++) {
lineValue = inputMatrix[y];
for (local x = 7 ; x > -1 ; --x) {
a = lineValue & (1 << x);
if (a != 0) outputMatrix[x] = outputMatrix[x] + (1 << (7 - y));
}
}
}
return outputMatrix;
}
An implicit parameter passed to all functions, it contains a reference to the function’s context object.
this
, please see ‘Squirrel Closures And Context Objects’.May be included within code that has been placed in the try
section of a try... catch
structure to force the generation of an exception which will then be dealt with by the code in the catch
section. It can also be used at any time to trigger a critical error, ie. one capable of halting Squirrel.
See class, above.
One of two possible Boolean outcomes of a conditional statement.
Part of a try... catch
structure, it indicates code to be run which might generate an exception. If this occurs, the exception is passed to the catch
section for processing.
// 'api' is an agent-side instance of the Rocky library, which is used to
// simply setting up APIs on the agent
// Handle POST requests to /settings : Apply a setting update
api.post("/settings", function(context) {
local data;
// Check we have valid JSON
try {
data = http.jsondecode(context.req.rawbody);
} catch (err) {
appError(err);
context.send(400, "Bad data posted");
return;
}
if ("enabled" in data) {
// Activate or deactivate the overnight dimmer
device.send("homeweather.set.offatnight", data.enabled);
context.send(202, "Nighttime dimmer activated");
return;
}
context.send(400, "Unknown command");
});
Indicates a variable’s data type; the type is returned as a lower-case string.
See function, above.
Defines the condition for the looped execution of a block of code. In a do... while
loop structure, the condition is evaluated each time the loop completes, ie. the loop will always be executed at least once. In a simple while...
structure, the condition is evaluated before the loop code is executed.
see do, above.
Indicates a function is a generator and marks the point at which execution of the function code will be suspended and its state preserved. Execution will not continue until the calling code includes a resume
statement.
yield
, please see ‘Squirrel Generator Functions’