Primer

Greetings, SkookumScript newbies! Be you a grizzled game development veteran or new to the world of programming, this handy-dandy guide will get you started with SkookumScript and teach you all of the basics. Have fun!

Initial Installation

If you haven’t done so already, now is the time for you to install either the Stand-alone SkookumDemo (a fast-and-easy install that allows to you check out SkookumScript without installing a game engine) or the SkookumScript Unreal Engine 4 Plugin and SkookumDemo project (a longer and more involved setup that also includes setting up Unreal Engine 4 and using its world editor).

NOTE Both the SkookumScript UE4 Plugin and UE4 itself can be downloaded as pre-built binaries, or you can build them yourself, which enables you to pull them apart and put them back together according to your liking even with different game engines, as well as contribute fixes and improvements.

Start the Runtime and the SkookumIDE

Ensure that that the runtime (the stand-alone demo or the UE4 Editor) is up.

If you are using the stand-alone-demo, it will automatically launch and connect to the SkookumIDE.

If you are using the UE4 Editor, make sure you have a project loaded – we recommend the SkookumDemo project. To launch the SkookumIDE press the Sk button on the UE4 editor toolbar.

NOTE When using the UE4 Editor, many types of SkookumScript code can only be executed when your project is running – for example any commands that reference game objects or commands that take time to complete. So if it isn’t already running, start your UE4 project. For example, press the “Play” icon on the UE4 toolbar or press Alt+P in the UE4 Editor to “Play in the editor (PIE)”.

Play button on the UE4 Editor toolbar

TIP The SkookumScript UE4 Plugin remembers the SkookumIDE state from the last time you launched the UE4 Editor. If the SkookumIDE was up when you shut the UE4 Editor down, the next time you run the UE4 Editor, it will automatically launch and connect to the SkookumIDE. If the UE4 Editor loses its connection with the SkookumIDE for any any reason, just press the Sk button on the UE4 toolbar to launch the SkookumIDE and connect. This will also reconnect to the SkookumIDE if it is already running though not connected to the runtime. If the SkookumIDE is already running and already connected to the UE4 Editor then pressing the Sk button will bring the SkookumIDE to the foreground.

UE4 SkookumIDE disconnected UE4 SkookumIDE connected

The UE4 Editor SkookumIDE connection toolbar button indicating disconnected with a red no symbol at the bottom right and just the regular SkookumScript Sk icon if connected respectively.

SkookumIDE disconnected SkookumIDE connected

The SkookumIDE runtime connection toolbar button indicating disconnected with a red no symbol at the bottom right and just the regular SkookumScript Sk icon if connected respectively.

NOTE The SkookumIDE is an independent application and it can be used to edit scripts without being connected to the runtime so it stays up even after the runtime (stand-alone-demo or UE4 Editor) is closed. If it is still up when you reload the stand-alone-demo or the UE4 Editor, it will just reconnect. If you don’t need it after you shutdown the runtime, you can just close it.

SkookumIDE Workbench basics

In a long-standing programming language manual tradition, we begin with the minimal amount of code needed to print something:

"Hello, world!"

The SkookumIDE Workbenches allow you to run code snippets on any connected and running project. Type (or copy and paste) "Hello World!" into the Workbench (REPL), then open the “Build” menu option and select “Execute Selection on Runtime”. In the Log widget you should see the following printed out:

"Hello, world!"

Simple, eh? No includes, mucking about with files, making classes, nor other typical language red-tape or bookkeeping is needed.

Stringing you along

We will get into more details later, though zero or more characters surrounded by double quotes (") is known as a string literal.

SkookumScript prints out the result of any script that is executed (or evaluated, run, called, invoked – whatever term you prefer).

What is a REPL?

Many languages call the ability to interactively execute code a read-eval-print loop or REPL and it is traditionally accomplished with a simple interactive command line prompt. These REPLs read in a command, evaluate it, print out the result and then loop all over again with any new command. Since this is the 21st Century, SkookumScript’s Workbench widgets use a spacious text edit box that can accommodate multiple lines of commands. It also saves all your commands for later use, which can be very handy. While this is more sophisticated than a traditional REPL, we still call it a REPL since it serves essentially the same purpose and people looking for a “REPL” will find it when searching information about the SkookumIDE.

NOTE You may have noticed that there are two workbench widget tabs - the REPL and the Tutorial. The REPL workbench is writeable, saves your changes and reloads with each launch of the SkookumIDE. The Tutorial Workbench is read-only since the example code snippets that it contains are frequently changed by the mad computer scientists on the SkookumScript team and any of your own custom code snippets would be lost with each update. You can still execute the example code snippets or copy them over to the REPL workbench if you want to edit them.

You can enter math into a Workbench. The SkookumIDE is a great calculator.

6 * 7

42

This is actually really useful. We mad computer scientists use it all the time.

Since a result is often something you want to reuse, there are some hotkeys to help you copy it around:

  • Alt+Insert pastes the most recent result string into a Workbench at the caret position
  • Alt+Ctrl+Insert copies the result into the system clipboard

Printing to the Log

If you would like to print something other than a result to the Log, you can put it in a println() command, which prints out one or more objects and adds a line break (hence the ln for “line” at the end). Printing is an essential and versatile tool for any programmer’s toolbox.

println("Hello, world!")

F4 is a keyboard shortcut for executing code. You can place the edit caret anywhere on a line and press F4 rather than go through the context menu.

You will see:

Hello, world!

nil

While the result of the simple 6 * 7 above was the number 42, the result of a println() command is nil. nil is an object that essentially represents nothing or the absence of a value.

Nihilistic notation

nil, or something like it, is common in many languages (Smalltalk, Lisp, Objective-C, Ruby). It goes by several different names, such as NULL (C), nullptr (C++), and null (JavaScript).

TIP Those with a sharp eye may have noted that the println() command prints out one or more objects.

println("The answer: " 42 "and running on object:" this)

The answer: 42 and running on object: 'SkookumDemo'

nil

You can cram in as many arguments to println() as you like and they are all converted to strings and joined together. All SkookumScript objects know how to convert themselves to a string to get a textual representation of themselves.

The println() command above is called with 3 arguments: a string, a number and another string. SkookumScript arguments do not need to be separated with commas , – the parser automatically figures out where one argument ends and another begins. You can use commas if you think it makes things easier to read, though they aren’t necessary.

When you execute several commands at once, they will be called one after the other (in sequence).

println("Hello, world!")
println("I'll be your megalomaniacal overlord for today.")

SkookumScript also does not need an end of line or end of expression / statement delimiter such as a semi-colon ; like most C/C++ languages. Some amount of whitespace between each expression is all that is needed.

Select both lines with the mouse or keyboard, and then press F4.

Hello, world!
I'll be your megalomaniacal overlord for today.

nil

Using these mechanisms, you can execute any selection of text that parses correctly—including a portion of a single line, or multiple lines – or the whole unselected line that the caret is on.

The SkookumIDE\Scripts\workbench.sk file is saved with your latest changes every time you execute a line of code in a Workbench, press Ctrl+S, or shut down the SkookumIDE. All these handy code snippets are then ready to reuse the next time you run the SkookumIDE.

Language warnings and errors

Errors are something you must embrace if you wish to become an awesome coder. No matter how awesome you get, you will always have errors—though your errors will become progressively more interesting.

The SkookumIDE will helpfully alert you whenever it detects what may be an error and helps visualize it with, different colorizations, red underlines, mouse hover info and more.

Since errors will be a frequent companion and patient teacher at this point in your journey, we recommend that you take a detour to the Parser error checking page and then return filled with knowledge of error notification goodness.

Comments

Comments are ignored by the SkookumScript parser which considers them to be no more than whitespace. While the computer ignores them, comments are essential for us humans to make notes in code to other users or as an aid to memory to your future self. You can also use comments to have the parser skip over code that you don’t want to be present in the runtime though you want to keep it around for reference.

Comments in SkookumScript are similar to C++. Single-line comments begin at any point on a line with two forward slashes // and it continues until the end of the line.

// This is an example of a single line comment.
// It continues from its start until the end of the line ->
do_this

// It can be on its own line
do_that  // or at the end of other code

Multi-line comments start with a forward slash and then an asterisk /* and they run until their end which is an asterisk and a slash */ – the reverse of the start. Unlike C++ multi-line comments, SkookumScript comments can be nested inside of other multiline comments. This enables comment out large swaths of code quickly even if the code already has multi-line comments.

/* This is an example of a multi-line comment.
   It can be a single line, multiple lines or used
   in the middle of code just like other whitespace. */

if /*like this*/ test
  [
  do_this
  do_that
  ]

/* [ML1] Multi-line comments
do_this 

  /* [ML2] can nest other comment blocks
  do_that
  do_stuff // Including single line comments
  */  // end of [ML2]

do_other
*/  // end of [ML1]
do_end

Your future self can be quite forgetful about all the time and sweat your current self has put in to author code. No matter how deeply immersed you are in an area now you can be sure that the mists of time will clear much of it away.

// You may look at this code and think that rewriting it
// to do X is a good idea - don't do it! X and Z limit
// the solution to the way it is written here.
// Modify at your peril!

Thanks, past me! I forgot and was about to rewrite this code.

Future you

I know, this is the second time we thought to rewrite this code. The first time there was no comment so we forgot the peril and wasted a bunch of time.

Past you

See the comments reference for details on the comment syntax.

Expressions

An expression is a combination of one or more specific commands, queries, values or names that is computed sometimes with side-effects to produce a result value. Expressions are the smallest elements that describe an action in SkookumScript.

Performing the action and doing whatever computation is necessary is called code evaluation or often code execution. In SkookumScript, everything is an expression and all expressions return a result when evaluated.

There are five kinds of expressions:

  • Literals create simple, handy building-block values such as numbers, strings of text, Booleans (true and false), and lists, as well as more sophisticated objects known as closures (which represent a hunk of code as an object).
  • Identifiers reference objects in the language and include variables, data members, and classes. Another form of identifier unique to SkookumScript is an ​object id​, which references named objects often specified from outside the language (such as items placed in a game editor).
  • Flow-control specifies expression groupings, alternate code paths, iterations for code to execute, timings and concurrency.
  • Primitives create and set variables, manage type-checking, and convert objects from one class type to another.
  • Invocations are the mechanisms for calling commands and actions called routines (methods and coroutines), which include special operator symbols for math, comparison and logic.

TIP Multiple expressions can be grouped together using a code block.

Literals

A literal is a way of writing a specific value for a new object you want to create.

SkookumScript has several different types of literals:

  • Integer (42, -123, 123_456_789, 2r10101, 8r52, 0x1b)
  • Real (0.0, 3.14159, -.33, 7.5e-8)
  • Boolean (true, false)
  • String ("Hello, world!", "first" + " second", "Line 1\nLine2")
  • Symbol ('idle', 'playing bongo', 'eating sandwich')
  • List ({1 2 3}, {1 "two" 3.0}, String{})
  • Closure (()[do_stuff], 10.do[do_stuff])

Integer

You can’t get far in a programming language without numbers.

Integers are whole numbers without a fractional part and they can be positive, zero or negative.

42
0
-123

See the full Integer syntax here.

Also check out the Integer class in the SkookumIDE by selecting it using the Classes widget and look at its members in the Members widget.

Specifying a radix (or base)

These integers are all in decimal which is radix (or base) 10.

In programming, it is often handy to be able to use a different radix than than the default radix 10. To specify a particular radix, prefix the radix you want to use followed by an r and then digits or letters that are valid for that radix that represent the number you want.

// These all are the same as:
42       // Decimal

2r10101  // Binary
8r52     // Octal
10r42    // Decimal - redundant though valid
16r2a    // Hexidecimal
21r2     // radix 21 - sure why not?
36r16    // Haxatrigesimal - largest allowed radix

Digit grouping separator

When you have big numbers, it can be handy to mark groups of thousands so you don’t get lost in digits. SkookumScript allows you to do this with optional underscores _ between digits. (The underscore is a common digit separator used by several languages. Space, , or ' cannot be used to mark groupings since they are used for other language syntax elements.)

123_456_789

Real

Real literals are used to create numbers that include a fractional part (real numbers) and they are represented by objects of the class type Real. (Real objects use the traditional floating-point mechanism shared with similar types often known as float or double in other languages such C++.)

42.0
0.0
-123.0
3.14159

// If the leading part is zero you can omit it
.5
-.33

See the full Real syntax here.

Also check out the Real class in the SkookumIDE by selecting it using the Classes widget and look at its members in the Members widget.

E-notation

Real values can also be written using E-notation as a shorthand for Scientific notation (m * 10n).

E-notation: real value e power of ten

4.2e1    //         42
1e6      //  1 000 000
-1e6     // -1 000 000
7.5e-8   //  0.000 000 075
-7.5e-8  // -0.000 000 075

Common details on numbers

Integer and real numbers have some common considerations that affect both of their literal values.

Negative number vs. subtract operator

Since SkookumScript does not need any sort of delimiter between expressions, it is possible that a single expression with one number subtracting a second number could be confused with two separate number expressions with the second number being negative. The SkookumScript syntax follows the rule-of-thumb that most humans would use visually.

In order to be recognized as single subtract - operator expression and not an expression followed by a second expression starting with a minus sign, the minus symbol - must either have whitespace following it or no whitespace on either side.

So for example:

1-2    // one subtract two - 1 expression
1- 2   // one subtract two - 1 expression
1 -2   // *one and negative two - 2 expressions
1 - 2  // one subtract two - 1 expression

Expected number types

If the parser expects an integer value to be passed as an argument, then it will not accept a real value as an argument or vice-versa.

40 + 2.0

This gives the error:

The argument supplied to operator parameter num was expected to be an object of the type Integer and was given the type Real which is not compatible.

SkookumScript does not coerce (automatically convert) from one type to another. (Though you can explicitly convert from an Integer type to a Real type using the conversion operator 2.0>>Real or calling the conversion method 2.0.Integer – though we will go into details of conversion later.)

However, if the parser knows that a Real type is expected and if the real value that you want to supply happens to have no fractional part (such as -1.0, 0.0, 1.0, 123.0) then you can omit the .0. So even though it looks like an integer literal, it is actually a real literal (such as -1, 0, 1, 123). This is not coercion, the parser just automatically adds the .0 on for you and treats it as a Real type.

The 2 below is a real literal since the + operator on 40.0, which is a Real type, also expects the operand (the value passed to the operator) to be a Real type.

40.0 + 2

The parser sees the 2 and realizes that what you really mean is 2.0.

It is nice to be lazy when you can. The SkookumScript parser gets what you want and has your back.

Boolean (true and false)

Numbers are great, though what would a programming language be without logic?

SkookumScript has a Boolean literal with two possible values: true and false. They are both of the single class type Boolean.

Boolean values can be used to store logical states and they are especially useful when working with conditional expressions such as if, when and unless that allow changing the control flow of code. More details about conditional expressions can be found here.

Also check out the Boolean class in the SkookumIDE by selecting it using the Classes widget and examine its members in the Members widget. In particular, note the logical operators and, or, xor, nand, nor, nxor and not that are frequently used with Boolean values and their associated methods.

Converting to and from Boolean values

Unlike some other languages, in SkookumScript only false is accepted as a negative truth value – no other type or value such as 0, nil, empty string or empty list is implicitly accepted or coerced as a false value. Similarly, true is the only accepted positive value – no other values are implicitly accepted as a true value.

Though you can explicitly convert from an Boolean type to an Integer type using the conversion operator true>>Integer or calling the conversion method true.Integer – and the reverse 0>>Boolean or 0.Boolean. You can also call obj.not_nil? to convert something that could be nil to false when nil or to true otherwise.

String

Zero or more characters surrounded by double quotes " is known as a string literal and it creates a String object. The string itself is the characters between the double quotes.

"Hello, world!"

// The empty string
""

Strings can span more than one line, in which case they will store the newline character for the end of each line.

// Multi line string
"line 1
line 2
line 3"

One or more string literals with a concatenation operator + between them will be parsed as a single string. The concatenation operator is necessary since the parser will otherwise consider the adjacent strings to be separate string literals that create separate string objects.

// same as "just one string"
"just " + "one " + "string"

// same as "also one string"
"also "
+ "one "
+ "string"

// Three string objects
"three" "separate" "strings"

String internals

Strings are internally stored as reference counted null-terminated (0) arrays of ANSI characters (to ensure compliance with native C++). Copying from one string to another is quite efficient since they only copy a pointer to a shared string reference structure and increment a reference count.

The internal representation will likely be stored in a Unicode compliant mechanism in the future.

See the full string syntax here.

Also check out the String class in the SkookumIDE by selecting it using the Classes widget and look at its members in the Members widget.

SkookumScript strings are mutable—you can change them after they have been created, including reducing or increasing their number of characters.

The String class is restrained since there are usually more efficient mechanisms to use in games such as enumerations or Symbols. However, the internal C++ AString class that the SkookumScript String is based on has much more functionality that can be exposed as needed.

Escaped special characters

The backslash \ is used to escape (or substitute) special characters in a string (or symbol) literal. The most commonly used special character is probably the newline \n—expect to see it everywhere.

Characters other than the specials of a, b, f, n, r, t and v just pass right through unchanged such as quotes \' \" and the backslash itself \\.

Escape Character substitution Hex
\a bell/alert 07
\b backspace 08
\f formfeed 0c
\n newline 0a
\r carriage return 0d
\t tab 09
\v vertical tab 0b
\integer-literal ANSI character from integer
\? resolves to itself such as \' and \"

When an ANSI character code is specified using \ and an integer literal, it can specify a radix so the number can be in the form easiest for the situation: decimal, hexadecimal, etc.

These all specify the asterisk * character:

"*"          // simple character
"\42"        // binary
"\8r52"      // octal
"\16r2a"     // hexadecimal
"\2r101010"  // binary
"\*"         // pass through

Here is an example that includes double quotes and newlines:

"\"The secret is to bang the rocks together, guys.\"\n"
+ "  - Douglas Adams\n"
+ "  The Hitchhiker's Guide to the Galaxy"
// "The secret is to bang the rocks together, guys."
//   - Douglas Adams
//   The Hitchhiker's Guide to the Galaxy

Symbol

Symbols are like a hybrid between strings and enumerations (or integers). They can be just about any sequence of characters like a string though they are as simple and as efficient as enumerations internally.

They look similar to a string though they use single quotes and they are limited to no more than 255 characters.

// identifier names in the language
'some_routine_name'

// used like enumerations
'small'
'medium'
'large'
'fries with that'

// names for behavior states
'idle'
'hunting for smoothie ingredients'
'making smoothie'
'drinking smoothie'
'brain freeze!'

Symbols are what SkookumScript uses to store all of its internal representations for the names of aspects language.

See the full symbol syntax here.

The UE4 equivalent for Symbol is often the C++ FName class which is called the Name class in SkookumScript.

Also check out the Symbol class in the SkookumIDE by selecting it using the Classes widget and look at its members in the Members widget.

List

Lists group together objects so they can be treated as a single List object. List objects (also sometimes called collections or arrays in other languages depending on their implementation) store zero or more objects referred to as items in an ordered, indexable (they can be retrieved by their position number) group that can dynamically change in length. The same item can simultaneously be in several positions in the same list.

A list literal makes a List object using a series of expressions surrounded by curly brackets { } (also known as braces) marking the beginning and the ending of the list. Items are separated by whitespace. You can alternatively separate items with a comma , though they are optional (just as they are with routine arguments) and should only be used if they aid readability.

Here are some simple list literals:

// empty list that expects Object items
{}

// List of 3 integers
{1 2 3}

// Same as above - commas optional
{1, 2, 3}

// List of 3 strings
{"hey" "hi" "hello"}

Each item expression is executed in order, the resulting object has its reference count incremented and then the object is added to the list as an item.

Lists can have more than one item class type.

// List with item type <Integer|String|Real>
{1 "two" 3.0}

Simple lists infer the item class type by examining the items in the list literal.

If you want to have an empty list that will use a particular item class type, the type must be specified using a mechanism such as an item typed list.

// empty list that expects Integer items
Integer{}

// empty list that expects String items
String{}

// Can still specify initial items
Integer{123 42}

// Simpler since Integer is inferred
{123 42}

The syntax of list literals can be simple or tricky depending on the class type of the list, the class type(s) of the items in the list and whether any initial items are present. See the full list reference here for all the details.

Also see some examples of using lists here, check out the List class in the SkookumIDE by selecting it using the Classes widget and look at its powerful and useful members in the Members widget.

Closure: the basics

Closures are a sophisticated and powerful concept that include much more than we’ve gone over in the Primer to this point, so for now we’ll only go over their basics. They are a literal so they are included here for completeness, though we’ll detail them later after their building block concepts have been introduced.

A closure literal (also known as a block in some languages) is essentially a series of expressions grouped together like a routine without a name though also with references to any variables that were created outside of that series of expressions. This allows you to treat code as an object so you can pass code to and return from routines and delay its evaluation until needed. This allows callbacks, custom control flow, and all manner of amazing and zany concepts.

Some examples of closures:

// Closure that triples an Integer
(Integer x)[3 * x]

// Tail closure called by Integer.do
// The closure is the [ ] bit
10.do
  [
  println("hey")
  println("hi")
  println("hello")
  ]

This is just a taste—don’t worry about understanding closures yet.

See the full closure reference here.

Next up

Check out the rest of the documentation and move on to some tutorials.