Squirrel

From Valve Developer Community
Jump to: navigation, search

Squirrel Language Squirrel is a programming language similar to Lua, but uses a C like syntax. In Source Squirrel is used as one of the scripting languages in the VScript scripting system. The official Squirrel documentation can be found here

Squirrel heavily uses an associative array data structure called a table. Both the keys and values of a table can contain almost any kind of variable. The scripting environment consists of nested tables, and when a script is executed its variables and functions are added as table slots.

Variables

Squirrel has two kinds of variables: table slots and local variables. Since the execution scope is always a table, any variables declared outside functions will always be table slots.

  • Table slots have to be declared using the <- operator.
  • Variables local to functions can be declared using the local keyword. These should be used for temporary values or as helpers.
  • Global variables are slots in the root table, and can be declared using the :: scoping operator.

Here are examples illustrating the declaration and use of variables.

// Variable declaration.
a <- 5
b <- "A text string"

// Modifying the variable.
b = "New string"
function MultiplyWithTwo(inValue)
{
	// Local variable declaration.
	local factor = 2
	
	return inValue * factor
}
// Global variable declaration. Sets x to 10.
::x <- MultiplyWithTwo(a)

Data Types

Squirrel is a dynamically typed language. Any variable can be assigned a value of any type.

Note.png Note:  The VScript API functions are bindings to the Source C++ code, so while it may seem possible to pass values of any type to them, they only accept specific types.

The built-in function typeof returns the type of an input value as a string in lower case, e.g. typeof(5) == "integer".

Type Description
Integer The integers -2147483648 to 2147483647.
Float -3.4028235e38 to 3.4028235e38, which equal -3.4028235 × 1038 to 3.4028235 × 1038.
String An immutable string. They behave like C strings, and support escape sequences (\t,\a,\b,\n,\r,\v,\f,\\,\",\',\0,\xhhhh).
Null
Bool Boolean data type that can be true or false.
Table Associative array.
Array Mutable C style array.
Function Second order functions are supported, so functions can assigned as values to variables.
Class Object oriented class. Implementation similar to tables.
Class Instance Object instances of classes. Script handles generated by the game also identify as instances.
Generator To do: Possibly unavailable in VScript
Userdata Opaque data used by the game.
Thread To do: Possibly unavailable in VScript
Weak reference


Data Structures

Squirrel has built-in support for two different data structures, arrays and tables.

Arrays

Arrays are sequences of objects that are numerically indexed starting from 0. Syntactically they function similarly to C arrays, but unlike C arrays, they are mutable and values can be inserted and removed using a set of built in functions.

Arrays are defined using square brackets.

// Array definition.
myArray <- 
[
	7,
	"more text",
	null,
	1
]
// Prints "7"
printl(myArray[0])

myArray.remove(0)

// Prints "more text"
printl(myArray[0])

Tables

Tables are associative arrays, meaning that they contain a collection of key-value pairs, called slots. A table can be indexed into using the key, returning the associated value. The keys and values can be of any data type (except null for the key), including other tables, allowing the creation of more complex data structures.

Tables are defined using curly brackets. Inside a table definition slots can be defined using the key = value pattern. Outside of the definition, new slots can be added to existing tables using the table.key <- value pattern.

Using the . operator to index a key only works when the key is a string or numerical literal. Array style indexing table[keyVariable] can be used to index any kind of key.

// Table defintion.
myTable <-
{
	a = 3,
	b = 7,
	x = "example text",
	
	nestedTable =
	{
		z = "another string"
	}
}
// Adding non-string keys
a <- "0"
myTable[a] <- 11
myTable[["u", "v", "w"]] <- null

// Prints "3"
printl(myTable.a)

// Prints "11"
printl(myTable[a])
// Prints all the key-value pairs in the table.
foreach(key, value in myTable)
{
	printl(key + ": " + value)
}

// Prints the value of the key in the nested table.
printl(myTable.nestedTable.z)

Functions

Functions in Squirrel work similarly to their C counterparts. Second order functions are supported, so functions can be directly manipulated like other values, including it being possible to store them in variables and table slots. Default parameter values and variable numbers of parameters are also supported.

For more details, see the Squirrel API about functions.

Declaration and Definition

It is an idea to choose function names so that they begin with a capital letter.

// declares and (re)defines "Greet"
function Greet()
{
  printl("Hello!")
}

Greet() // prints "Hello!"
// declares and (re)defines "Greet"
Greet <- function()
{
  printl("Hello!")
}

Greet() // prints "Hello!"
// (re)defines "Greet"; exception if "Greet" not declared!
Greet = function()
{
  printl("Hello!")
}

Greet() // prints "Hello!"

Parameters

When a function is called, it can be made so that it can or must receive input values that determine the function's side effects and/or its return value.

  • Multiple parameters must be comma delimited: function Test( a , b , c , d=4, e=5) {...}
  • All parameters with no default value must be the first.
  • To avoid exceptions, it is often a good idea to check if a parameter is not null. The statements if (object != null) {...} and if (object) {...} are equivalent.
  • As parameters are not restricted to a type, the typeof function can be used to handle different types differently.
// normal parameter
function Greet(name)
{
  printl("Hello, " + name + "!")
}

Greet()       // exception
Greet("Gabe") // prints "Hello, Gabe!"
// parameter with default value
function Greet(name="Gordon")
{
  printl("Hello, " + name + "!")
}

Greet()       // prints "Hello, Gordon!"
Greet("Gabe") // prints "Hello, Gabe!"

Return Value

A function is ended with the optional return statement, where it is also possible to return a value. It can be imagined that this value will be inserted to where the function was called.

  • If a function ends without a return statement, it returns the value null.
function IsEven(n)
{
  if (n % 2 == 0)
    return true
  else
    return false
}

if (IsEven(42)) // (42 % 2 == 0) == true
{
  printl("42 is even!")
}

Classes

The following is just an example of some basic class syntax. For details, see Squirrel API about classes.

class Weapon
{
	static prefix = "weapon_" // static variables are read-only!
	
	// For instance-individual variables it's best to declare them with anything and overwritte them on construction.
	name    = null
	primMax = null
	secMax  = null
	
	count = [0] // Containers and instances are not copied per instance, just the reference. count[0] is the same for all of instances.
	
	constructor(name0, prim, sec)
	{
		name    = prefix + name0
		primMax = prim
		secMax  = sec
		count[0]++
	}
	
	function GetAll()
	{
		local list = []
		local wep = null
		while ( wep = Entities.FindByClassname(wep, name) )
		{
			list.append(wep)
		}
		return list
	}
	
	// ... more useful functions ...
}

awp  <- Weapon("awp", 10, 30)
ak47 <- Weapon("ak47", 30, 90)
// can access class variables and class functions with awp.[...]

To do:  Get a better example.

Scripting

Please see VScript Fundamentals for more information.

With the Source VScript system, scripts are stored in the game\scripts\vscripts\ directory. Squirrel scripts use the .nut file extension, and the .nuc extension for ICE encrypted files.

Common to all Squirrel using games, scripts can be associated to a game entity as an entity script that is executed then the entity spawns, and has access to the script handle of its entity through the self variable. Specific games can also have other methosds of executing scripts.

Script files can also be executed from the Developer Console using the script_execute command. Lines of code can even be executed in-line with the script command.

See Also

External links