ChaiScript Reference

Files

ChaiScript, once parsed, is executed top to bottom in a single pass. Definitions and statements have the same precedence.

Recommendation: ChaiScript source files have a .chai extension.

Comments

Comments follow the same format as C++ comments.

/*
  This is a multi-line comment.
*/
//This is a single line comment.

Block Types

If Blocks

If Block ::= "if" "(" condition ")" block
Else If Block ::= "else if" "(" condition ")" block
Else Block ::= "else" block

While Blocks

While Block ::= "while" "(" condition ")" block

This loop can be broken using the break command.

For Blocks

For Block ::= "for" "(" [initial] ";" stop_condition ";" loop_expression ")" block

This loop can be broken using the break command.

Try Blocks

Try Block ::= "try" block 
  ("catch" ["(" variable ")"] [":" guards] block)+ 
  ["finally" block]

Function Definitions

Function Definition ::= [annotation + CR/LF] "def" identifier "(" [arg ("," arg)*] ")" [":" guard] block

annotation: meta-annotation on function, currently used as documentation. Optional.
identifier: name of function. Required.
args: comma-delimited list of parameter names. Optional.
guards: guarding statement that act as a prerequisite for the function. Optional.
{ }: scoped block as function body. Required.

Functions return values in one of two ways:

  1. By using an explicit return call, optionally passing the value to be returned.
  2. By implicitly returning the value of the last expression (if it is not a while or for loop).

In-Place Creation

Anonymous Functions

Lambda ::= "fun" "(" [variable] ("," variable)*  ")" block

Creates an anonymous function (sometimes called a lambda).

Vector

In-place Vector ::= "[" [expression ("," expression)*]  "]"

Ranged Vector

In-place Ranged Vector ::= "[" value ".." value "]"

Creates a vector over a range (eg. 1..10)

Map

In-place Map ::= "[" (string ":" expression)+ "]"

Object Model

Extending Registered C++ Classes

You may extend C++ classes that you have previously registered with the ChaiScript engine using the method definition syntax:

Method Definition ::= class_name "::" method_name "(" [arg ("," arg)*] ")" block

ChaiScript's Native Object Types

Constructors and Methods

Using the same method definition syntax you can create a constructor and add methods to a new type. For example:

def MyClass::MyClass() { }

This creates a constructor for the 'MyClass' type, which, if it doesn't already exist, will now be visible to your script. To instantiate a value of 'MyClass', call its constructor directly:

var myobject = MyClass()

Attributes

Attribute Definition ::= "attr" class_name "::" attribute_name

In addition to extending your new type with methods, you may also add attributes.

Extended example:

attr Rectangle::height
attr Rectangle::width
def Rectangle::Rectangle() { this.height = 10; this.width = 20 }
def Rectangle::area() { this.height * this.width }
 
var rect = Rectangle()
rect.height = 30
print(rect.area())

Standard Library (aka The Prelude)

ChaiScript, at its core, has some very functional programming-inspired habits. Few places show this off as clearly as the prelude, itself a name taken as a nod to the popular functional language Haskell. This prelude is available to all standard ChaiScript applications, and provides a simple foundation for using numbers, strings, and ranges (the general category of containers and their iteration).

Strings

to_string(x): Converts x into a string.

eval> to_string(3).is_type("string")
true

puts(x): Prints x to the terminal, without a trailing carriage return.

eval> puts("hi, "); puts("there")
hi, there

print(x): Prints x to the terminal, with a trailing carriage return.

eval> print("hello")
hello

find(str, substr): Finds the first instance of substr in str.

eval> find("abab", "ab")
0

rfind(str, substr): Finds the last instance of substr in str.

eval> rfind("abab", "ab")
2

find_first_of(str, list): Finds the first of characters in list in the str string.

eval> find_first_of("abab", "bec")
1

find_last_of(str, list): Finds the last of characters in list in the str string.

eval> find_last_of("abab", "bec")
3

find_first_not_of(str, list): Finds the first non-matching character to list in the str string.

eval> find_first_not_of("abcd", "fec")
0

find_last_not_of(str, list): Finds the last non-matching character to list in the str string.

eval> find_last_not_of("abcd", "fec")
3

ltrim(str): Removes whitespace from the front of the string.

eval> ltrim("  bob")
bob

rtrim(str): Removes whitespace from the back of the string.

eval> rtrim("bob  ") + "|"
bob|

trim(str): Removes whitespace from the front and back of the string.

eval> trim("  bob  ") + "|"
bob|

Numbers

max(a, b): Returns the maximum value of a or b.

eval> max(4, 10)
10

min(a, b): Returns the minimum value of a or b.

eval> min(4, 10)
4

even(x): Returns true if x is even, otherwise returns false.

eval> even(4)
true

odd(x): Returns true if x is odd, otherwise returns false.

eval> odd(4)
false

Containers

for_each(container, f): Applies the function f over each element in the container.

eval> for_each([1, 2, 3], print)
1
2
3

map(container, f): Applies f over each element in the container, joining all the results.

eval> map([1, 2, 3], odd)
[true, false, true]

foldl(container, f, initial): Starts with the initial value and applies the function f to it and the first element of the container. The result is then applied to the second element, and so on until the elements are exhausted.

eval> foldl([1, 2, 3, 4], `+`, 0)
10

sum(container): Returns the sum total of the values in the container.

eval> sum([1, 2, 3, 4])
10

product(container): Returns the product of the value in the container.

eval> product([1, 2, 3, 4])
24

take(container, num): Takes num elements from the container, returning them.

eval> take([1, 2, 3, 4], 2)
[1, 2]

take_while(container, f): Takes elements from the container that match function f, stopping at the first non-match, returning them as a new Vector.

eval> take_while([1, 2, 3], odd)
[1]

drop(container, num): Drops num elements from the container, returning the remainder.

eval> drop([1, 2, 3, 4], 2)
[3, 4]

drop_while(container, f): Drops elements from the container that match f, stopping at the first non-match, returning the remainder.

eval> drop_while([1, 2, 3], odd)         
[2, 3]

reduce(container, f): Similar to foldl, this takes the first two elements as its starting values for f. This assumes container has at least 2 elements.

eval> reduce([1, 2, 3, 4], `+`)
10

filter(container, f): Takes elements from container that match function f, return them.

eval> filter([1, 2, 3, 4], odd)
[1, 3]

join(container, delim): Joins the elements of the container into a string, delimiting each with the delim string.

eval> join([1, 2, 3], "*") 
1*2*3

reverse(container): Returns the contents of the container in reversed order.

eval> reverse([1, 2, 3, 4, 5, 6, 7])
[7, 6, 5, 4, 3, 2, 1]

generate_range(x, y): Generates a new Vector filled with values starting at x and ending with y.

eval> generate_range(1, 10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

concat(x, y): Returns a new Vector with x and y concatenated.

eval> concat([1, 2, 3], [4, 5, 6])
[1, 2, 3, 4, 5, 6]

collate(x, y): Returns a new Vector with x and y as its values.

eval> collate(1, 2)
[1, 2]

zip_with(f, x, y): Applies f to elements of x and y, returning a new Vector with the result of each application.

eval> zip_with(`+`, [1, 2, 3], [4, 5, 6])
[5, 7, 9]

zip(x, y): Collates elements of x and y, returning a new Vector with the result.

eval> zip([1, 2, 3], [4, 5, 6])
[[1, 4], [2, 5], [3, 6]]

Statement Types

Statements are formed by combining one or more of the following:

Numbers

ChaiScript supports both ints and doubles.

Example int:

10

Example doubles:

3.14, NaN, Infinity

Booleans

Example booleans:

true, false

Variables

Any variable identifier that follows the C naming convention.

Example variable:

bob

Strings

Quoted string values.

Example string:

"test me"

Strings accept the following escaped sequences:

Sequence Description
\b Backspace
\f Form feed
\n Newline
\r Carriage return
\t Tab
\' Single quote
\" Double quote
\\ Single backslash

Strings also allow in-string evaluation, which allows you to evaluate simple expressions inside of the string. For example:

var five = 5
"3 + 5 = ${3 + five}"

Characters

Single-Quoted char values.

Example char:

'b'

Chars also accept the following escaped sequences:

Sequence Description
\b Backspace
\f Form feed
\n Newline
\r Carriage return
\t Tab
\' Single quote
\" Double quote
\\ Single backslash

Operator Literals

A special form of the operator that allows you to reference it as an identifier.

Example operator literal:

`+`

Note: These may be used as first-class functions.

Expressions

Example expression:

3 + 4 * 5

Mathematical expression following the order of precedence mentioned in "Operators".

Variable Declarations

Variable Declaration ::= "var" identifier

A variable name preceded by the keyword var, which declares the variable as an anonymous type. Once a variable has been given a type by assigning it to a value, the variable must maintain this type while it's in scope.

Equations

Equation ::= lvalue "=" rvalue

Takes a copy of what is on the right hand side and assigns it to the identifier named on the left hand side. For complex types this calls the "clone" method for that type.

Function Calls

Function Call ::= fun_name "(" [arg ("," arg)*] ")"

Calls the function pointed to by the lhs value.

Method Calls

Method Call ::= obj_name "." fun_name "(" [arg ("," arg)*] ")"

In ChaiScript the above notation is identical to:

fun_name "(" obj_name ("," arg)* ")"

Array Calls

Array Call ::= obj_name "[" key "]"

An array value lookup. In maps, 'key' is a string value, in vectors it is a numeric index.

Throwing Exceptions

Throw ::= "throw" "(" value ")"

Supported Types

Native Types

The following are natively supported types in ChaiScript:

Type Example
int 10
double 1.2
bool true
string "hello"
char 'b'
Vector [1, 2] and [1..10]
Map ["key":100]

Supported Types

All C++ types are support (value, reference, and pointer types included). Additionally, values of boost::shared_ptr are also supported.