Squirrel

From Bauman National Library
This page was last modified on 8 June 2016, at 14:58.
Squirrel
fraimed
Paradigm Multi-paradigm: scripting, imperative, functional, object-oriented
Designed by Alberto Demichelis
Typing discipline Dynamic
License MIT license
Website squirrel-lang.org
Influenced
MiniD

Squirrel is a high level imperative, object-oriented programming language, designed to be a light-weight scripting language that fits in the size, memory bandwidth, and real-time requirements of applications like video games. Squirrel is designed to be embedded in an application and not as general purpose language. It's main target is scripting video games mostly for PC and consoles.

History

The language is designed and maintained by Alberto Demichelis. It was made public in 2003 under the zlib/libpng license, and later, in November 2010, the license was changed to MIT license to enable the project to be hosted on Google Code. Demichelis was motivated by his work on Lua integration at game developer CryTek. One of the most common issues facing game developers who embed Lua is the unpredictability of the garbage collector, which can affect real-time performance. Lua’s incremental garbage collector can be controlled somewhat through the lua_gc() function, which accepts a step size argument that can be fine-tuned to manage the performance impact of collection. The optimal setting for this value is different for every project and can change as a project changes. To address the impact of Lua, which didn’t have an incremental collector at the time, Demichelis attempted to implement reference counting in Lua. Rather than relying on the collector to periodically scan memory, object ownership would be tracked by counting references to an object and releasing it when there were no more references. The work required to do this led Demichelis to start over with a new language that would address the other issues he encountered with Lua, such as its unconventional syntax (co-workers were constantly asking how to write a for-loop) and small set of features. While being inspired by Lua, it's syntax is closer to C/C++/C# than Lua. Currently the development of the language core is 'closed', meaning that only the author can touch it. Most recent squirrel specification is published under the version number of 3.0.

Language

Type system

Squirrel is a dynamically typed language, variables do not have a type, although they refer to a value that does have a type. Squirrel basic types are integer, float, string, null, table, array, function, generator, class, instance, bool, thread and userdata.

Primitive types

local a = 123    // decimal
local b = 0x0012 // hexadecimal
local c = 075    // octal
local d = 'w'    // char code
local a = 1.0    // float
local b = 0.234  // float
local a = true   // bool

Strings

Strings are an immutable sequence of characters, to modify a string it is necessary to create a new one. Squirrel's strings, behave like C or C++, are delimited by quotation marks(") and can contain escape sequences(\t,\a,\b,\n,\r,\v,\f,\\,\",\',\0,\xhhhh).

local a = "I'm a wonderful string\n"

Null

The null value is a primitive value that represents the null, empty, or non-existent reference. The type Null has exactly one value, called null.

local a = null

Table

Tables are associative containers, implemented as pairs of key/value (called a slot).

local t = {}
local test =
{
    a = 10
    b = function(a) { return a+1; }
}
test.c <- 1234  // add new slot 'c' to table with value 1234

Since Squirrel 3.0 is possible to declare a table using JSON syntax:

local x = {
  "id": 1,
  "name": "Foo",
  "price": 123,
  "tags": ["Bar","Eek"]
}

Array

Arrays are simple sequences of objects, their size is dynamic and their index starts always from 0.

local a = ["I'm","an","array"]
local b = [null]
b[0] = a[2];

Function

Functions are similar to those in other C-like languages and to most programming languages in general, however there are a few differences. Functions can be implemented in Squirrel or in a native language with calling conventions compatible with ANSI C.

local a = function(a,b,c) {return a+b-c;}
// or
function ciao(a,b,c)
{
    return a+b-c;
}
// or
this.ciao <- function(a,b,c)
{
    return a+b-c;
}
// or lambda
local myexp = @(a,b,c) a + b - c

Squirrel's functions can have variable number of parameters(varargs functions). A vararg function is declared by adding three dots (`...´) at the end of its parameter list. When the function is called all the extra parameters will be accessible through the array called vargv, that is passed as implicit parameter. vargv is a regular squirrel array and can be used accordingly.

function test(a,b,...)
{
	for(local i = 0; i< vargv.len(); i++)
	{
		::print("varparam "+i+" = "+vargv[i]+"\n");
	}
}

Generator

Generators are functions that can be suspended with the statement 'yield' and resumed later. When a generator function is called, it does not execute the function body, instead it returns a new suspended generator. The returned generator can be resumed through the resume statement while it is alive.

function geny(n)
{
    for(local i=0;i<n;i+=1)
        yield i;
    return null;
}

local gtor=geny(10);
local x;
while(x=resume gtor) print(x+”\n”);

Outputs:

0
1
2
3
4
5
6
7
8
9

Class

Classes are associative containers implemented as pairs of key/value. Classes are created through a 'class expression' or a 'class statement'. class members can be inherited from another class object at creation time. After creation members can be added until a instance of the class is created.

class Foo {
	//constructor
	constructor(a)
	{
		testy = ["stuff",1,2,3,a];
	}
	//member function
	function PrintTesty()
	{
		foreach(i,val in testy)
		{
			::print("idx = "+i+" = "+val+" \n");
		}
	}
	//property
	testy = null;	
}

Class instance

Class instances are created by calling a class object. Instances, as tables, are implemented as pair of key/value. Instances members cannot be dyncamically added or removed however the value of the members can be changed.

//creates a new instance of Foo
local inst = Foo();

Userdata

Userdata objects are blobs of memory(or pointers) defined by the host application but stored into Squirrel variables.

Thread

Threads are objects that represents a cooperative thread of execution, also known as coroutines. At first look a Squirrel thread can be confused with a generator, in fact their behaviour is quite similar. However while a generator runs in the caller stack and can suspend only the local routine stack a thread has its own execution stack, global table and error handler; This allows a thread to suspend nested calls and have it's own error policies.

Paradigm

Squirrel is multi-paradigm language: it's designed for embedded scripting in imperative object-oriented or functional manner. A squirrel program is a simple sequence of statements. Semantics of squirrel is comparable to the C-Family languages (C/C++, Java, C# etc...): assignment, function calls, program flow control structures etc.. plus some custom statement like yield, table and array constructors.

Deployment

Squirrel is embedded JIT-compiled cross-platform language, bytecode is running on virtual machine. Because of his nature of extension language, Squirrel’s compiler and virtual machine are implemented as C library. The library exposes a set of functions to compile scripts, call functions, manipulate data and extend the virtual machine. All declarations needed for embedding the language in an application are in the header file ‘squirrel.h’.

Squirrel uses reference counting (RC) as primary system for memory management, however, the virtual machine (VM) has an auxiliary mark and sweep garbage collector that can be invoked on demand. Squirrel can be compiled on 64 bits architectures by defining '_SQ64' in the C++ preprocessor.

int main(int argc, char* argv[])
{
    HSQUIRRELVM v;
    v = sq_open(1024); //creates a VM with initial stack size 1024    //do some stuff with squirrel here    sq_close(v);
}

Squirrel exchanges values with the virtual machine through a stack. This mechanism has been inherited from the language Lua. For instance to call a Squirrel function from C it is necessary to push the function and the arguments in the stack and then invoke the function; also when Squirrel calls a C function the parameters will be in the stack as well.

When an exception is not handled by Squirrel code with a try/catch statement, a runtime error is raised and the execution of the current program is interrupted. It is possible to set a call back function to intercept the runtime error from the host program.

Threading

Squirrel supports cooperative threads (also known as coroutines). A cooperative thread is a subroutine that can suspended in mid-execution and provide a value to the caller without returning program flow, then its execution can be resumed later from the same point where it was suspended. At first look a Squirrel thread can be confused with a generator, in fact their behaviour is quite similar. However while a generator runs in the caller stack and can suspend only the local routine stack a thread has its own execution stack, global table and error handler; This allows a thread to suspend nested calls and have it's own error policies.

No kernel-threads access is provided by the runtime.

function coroutine_test(a,b)
{
	::print(a+" "+b+"\n");
	local ret = ::suspend("suspend 1");
	::print("the coroutine says "+ret+"\n");
	ret = ::suspend("suspend 2");
	::print("the coroutine says "+ret+"\n");
	ret = ::suspend("suspend 3");
	::print("the coroutine says "+ret+"\n");
	return "I'm done"
}

local coro = ::newthread(coroutine_test);

local susparam = coro.call("test","coroutine"); //starts the coroutine

local i = 1;
do
{
	::print("suspend passed ("+susparam+")\n")
	susparam = coro.wakeup("ciao "+i);
	++i;
}while(coro.getstatus() == "suspended")

::print("return passed ("+susparam+")\n")

Will output:

test coroutine
suspend passed (suspend 1)
the coroutine says ciao 1
suspend passed (suspend 2)
the coroutine says ciao 2
suspend passed (suspend 3)
the coroutine says ciao 3
return passed (I'm done).

Applications

Games using Squirrel:

  • Left 4 Dead 2
  • Portal 2
  • Alien Swarm
  • OpenTTD
  • Counter Strike: Global Offensive
  • War Thunder
  • Shadow Warrior

It is also used in CodeBlocks IDE as scripting engine.

External links