A Scripting Language
SourceForge Logo

About
Kozmo Home

Projects using Kozmo
TankWar
Trident Rising
eMeme

Documentation
Kozmo Users Guide
Embedding Kozmo
API Reference

Downloads

  This is a very early draft of the Kozmo Users Guide and (IMHO) is not suitable for a beginner. Suggestions for updates and clarifications are more than welcome - please email me on my SourceForge Account.

Introduction

Kozmo is a stack based language, expressions are evaluated in a strict left-to-right order. If you have had any previous experience with FORTH you will find it very similar.

Every value in a Kozmo script is evaluated and the result placed on the stack. For atomic or built-in types this means the value you write is placed on the stack. For example, the simple expression 2 will result in the value 2 being the topmost value on the stack.

The main thing to remember is that stack items are removed in the reverse order that they were placed on the stack.

At times this can result in some bizarre looking code, but the simple left-to-right evaluation order is very easy to remember and contributes to the speed of execution.

Standard Data Types

The Kozmo interpreter supports five core data types in the current release. These types are described in detail below.

Integers

32 bit signed integers are an atomic data type in the Kozmo interpreter. Integers are expressed in scripts as a sequence of digits optionally prefixed by a sign (+ or -) character.

Strings

Strings are identified in scripts as character sequences beginning with the quote (") character and terminated by another quote character. Quote characters may included in the string by using the backslash (\) character as an escape. EG: "This is a \"string\ "" would result in the the string This is a "string".

Closures

Closures are Kozmos method of representing code written in Kozmo itself. Closures begin with the open curly bracket ({) and end with the close curly bracket (}). The Kozmo interpreter translates these sequences into an array of tokens and pushes the array on to the stack like any other value.

The difference between closures and other data types is that closures are evaluated as if the token sequence had been given as a script command. For example ...

'++ { 1 + } def

... defines a function which adds 1 to the value currently on the top of the stack.

Native Functions

Native functions are implemented by the hosting application and are registered using the Bind() method of the Session instance. Native functions cannot be created any other way.

Identifiers

Identifiers server multiple purposes in the Kozmo language. Identifiers can be bound to values and used as variables or used as a native data type themselves.

If an identifer is expressed by itself with no modifiers the interpreter finds the value the identifier is currently bound to and evaluates that value. If an identifier is bound to a string or an integer that value is pushed onto the stack, if the identifier is bound to a closure or a native function that code is executed.

If the identifier is not bound to anything the value NULL is pushed on to the stack. The golden rule is that all identifiers evaluate to something.

The @ modifier overrides this behaviour by forcing the contents of the identifier to be pushed on to the stack even if the contents are executable (closures or native functions).

The ' modifier causes the identifier itself to be pushed on to the stack regardless of what it is bound to.

Functions

Functions in Kozmo act on the values currently on the stack. There are two types of functions supported by the interpreter, native functions which are supplied by the runtime library or the hosting application and closures which are implemented by scripts.

This section details the functions supplied by the standard Kozmo runtime library and shows you how native functions can be provided by the hosting application or by yourself in scripts.

The Kozmo Runtime Library

The Kozmo interpreter provides a standard set of functions for every application that hosts it. These functions are available unless they are overridden by the application (not recommended) or by user scripts (which may happen to support operator overloading - in this case the overloaded function should support the same semantics as the original function).

Integer Functions

+ Adds two integer values

Description

  This function will add the top two values on the stack if they are both integers. The result is left on the top of the stack.


Example

  3 2 + !
5

- Subtracts two integer values

Description

  This function will subtract the topmost value on the stack from the next value on the stack - the result is left on the top of the stack. If both values are not integers the function will fail.


Example

  3 2 - !
1

* Multiply two integer values

Description

  This function will multiply the top two values on the stack if they are both integers and leave the result on the top of the stack.


Example

  3 2 * !
6

% Calculate the modulus of two values

Description

  Places the modulus of two integers on the top of the stack.


Example

  3 2 % !
1

/ Divides two integer values

Description

  Places the result of dividing two integers on the top of the stack.


Example

  3 2 / !
1

String Functions

& Concatenate two strings

Description

  This function concatenates the two values on the top of the stack and places the resulting value on the top of the stack. All data types can be coerced to strings so this function works with any data type.


Example

  "Hello" "World" &
HelloWorld

length Calculates the length of a string

Description

  This function places the length of the string on the top of the stack as an integer on the top of the stack. All data types can be coerced to strings so this function will return a result regardless of the type of the value on the top of the stack.


Example

  "Hello World" length !
11

substr Returns part of a string

Description

  Coerces the value on the top of the stack to a string and returns the specified part. Expects the stack to contain a string followed by two integers. String indices start at 0 (like the C language).


Example

  "Hello World" 0 4 substr !
Hell

Stack Manipulation Functions

. Removes the top value from the stack

Description

  This function silently removes the value currently on the top of the stack.


Example

  3 4 . !
3

dup Duplicates the value on the top of the stack

Description

  This function makes a copy of the value currently on the top of the stack and places the copy on the stack.


Example

  3 dup ! !
3
3


swap Swaps the order of the top two stack values

Description

  Takes the top two values on the stack and puts them back on in reverse order.


Example

  3 4 swap ! !
3
4


Binding Functions

def Associate an identifier with a value

Description

  This function associates an identifier with a value in the current context. Future references to the identifier in this context or any child contexts will return the value defined. If the value had already been defined the original definition will be overwritten in the context it was already defined.


Example

  In the same context

'three 3 def
three !
3
Definition in a child context

{ 'three 3 def three ! } eval
3
three !
NULL
Overriding an existing definition

'three 3 def
three !
3
{ 'three 4 def three ! } eval
4
three !
4


gdef Associate a value with an identifier in the global context

Description

  This function associates a value with an identifier in the global context. This means that the identifier is associated with that value for all contexts, not just the context it was defined in.


Example

  'three 3 gdef
three !
3

= Alternative form of def

Description

  This function behaves the same way as the def function except that the order of parameters is swapped. The primary reason for this function is to simplify user functions that take a large number of parameters. In this case parameters are already on the stack, the user can specify the appropriate local variable names and associate them with the variables.


Example

  'func1 { 'p4 = 'p3 = 'p2 = 'p1 = p1 p2 * p3 p4 * + } def
4 5 6 7 func1 !
62

Input/Output Functions

Kozmo has very limited support for input/output. The hosting application may provide up to two output streams - one for standard messages, the other for error messages but this is completely optional. If an appropriate output stream is not provided the Kozmo runtime will silently succeed on these functions without actually displaying any output.

An additional stream is provided for DEBUG builds of the library, this stream uses the libutil tracing functions to add entries to the trace file. If the stream is used in RELEASE (the default) builds of the library the output is silently consumed.
! Consume and display the top of the stack

Description

  This function converts the value on the top of the stack to a string and displays it on the standard output stream.


Example

  3 !
3
? Display the top of the stack without removing the value

Description

  Takes a copy of the value currently on top of the stack, converts it to a string and displays it on the standard output.


Example

  3 ? 2 + !
3
5
Functionally equivalent to ...
'? { dup ! } def

!Err Alternative form of !

Description

  Behaves the same way as ! but output is displayed on the error stream as opposed to the standard output stream.


Example

  3 !Err
3

?Err Alternative form of ?

Description

  Behaves the same way as ? but output is displayed on the error stream as opposed to the standard output stream.


Example

  3 ?Err 2 + !
3
5

Predicate Functions

Predicates are used to test values on the stack. In Kozmo predicates generally end with the character ?. Predicates will consume the values on the stack and replace them with either a TRUE or FALSE value.
eq? Determine if two values are equal

Description

  This function compares the two values on the top of the stack for equality. If the values are not of the same type the result will always be FALSE (or 0).


Example

  3 4 eq? !
FALSE
ne? Determine if two values are not equal

Description

  This function compares the two values on the top of the stack for equality. If the values are not of the same type the result will always be TRUE (or non-0).


Example

  3 4 ne? !
TRUE
lt? Determine one value is less than another

Description

  This function compares the two values on the top of the stack to see if one is less than the other. If the values are not of the same type the result will always be FALSE (or 0).


Example

  3 4 lt? !
TRUE
gt? Determine one value is greater than another

Description

  This function compares the two values on the top of the stack to see if one is less than the other. If the values are not of the same type the result will always be FALSE (or 0).


Example

  3 4 gt? !
FALSE
le? Determine one value is less than or equal to another

Description

  This function compares the two values on the top of the stack to see if one is less than or equal to the other. If the values are not of the same type the result will always be FALSE (or 0).


Example

  3 4 lt? !
TRUE
ge? Determine one value is greater than or equal to another

Description

  This function compares the two values on the top of the stack to see if one is greater than or equal to the other. If the values are not of the same type the result will always be FALSE (or 0).


Example

  3 4 ge? !
FALSE
true? Determine if the top value on the stack represent TRUE

Description

  In Kozmo (like C and C++) TRUE is represented by a non-zero value. This predicate determines if the value on the top of the stack can be considered TRUE. Non-atomic data types and strings are always considered TRUE, integers are considered TRUE only if they are non-zero. The special NULL value is always considered FALSE.


Example

  3 true? !
TRUE
false? Determine if the top value on the stack represent FALSE

Description

  In Kozmo (like C and C++) FALSE is represented by a zero or NULL value. This predicate determines if the value on the top of the stack can be considered TRUE. Non-atomic data types and strings are always considered TRUE, integers are considered TRUE only if they are non-zero. The special NULL value is always considered FALSE.


Example

  3 false? !
FALSE

Control Functions

Flow control is implemented in Kozmo in the same way as functions (most languages implement flow control as language specific statements). This simplifies the implementation and also allows you to implement your own flow control functions (something many other languages restrict you from doing).
if Evaluate if the condition is TRUE

Description

  Evaluates the specified value if the condition evaluates to TRUE. Although not mandatory, this function is most useful if the value is a closure or native function.


Example

  { "Yes" ! } True if
Yes
if-else Evaluate the first value if the condition is TRUE, otherwise evaluate the second value

Description

  Evaluates the first value if the condition evaluates to TRUE, otherwise the second value is evaluated. Although not mandatory, this function is most useful if the values to be evaluated are closures or native functions.


Example

  { "Yes" ! } { "No" ! } False if-else
No
while Evaluate while the condition is TRUE

Description

  Evaluates the specified value while the condition evaluates to TRUE. Although not mandatory, this function is most useful if the value and the condition are closures or native functions.


Example

  'cond 4 def { 'cond cond 1 - def } 'cond while cond !
0
loop Evaluate for a given number of iterations

Description

  Evaluates the value for the number of iterations specified.


Example

  'count 0 def { 'count count ? 1 + def } 3 loop
0
1
2

Miscellaneous Functions

Flow control is implemented in Kozmo in the same way as functions (most languages implement flow control as language specific statements). This simplifies the implementation and also allows you to implement your own flow control functions (something many other languages restrict you from doing).
eval Evaluate the value on the top of the stack

Description

  Evaluates the value on the top of the stack as if it were entered as part of a script. If the value is an atomic type (integer or string) it is simply pushed back on to the stack. If the value is an identifier, the value it is bound to is evaluated (closures and native functions are executed in this case). If the value is executable (a native function reference or a closure) it is executed.


Example

  { "Yes" ! } eval
Yes
noop Does nothing

Description

  This function was added mainly for benchmarking reasons. It is implemented as part of the runtime library (as a native function) and was used to test execution of native functions. For the life of me I can't possible imagine why you would want to use this function but you never know.


Example

  { noop } 10 loop
trace Consumes the top value on the stack and enters it in the trace file

Description

  This function is only useful in debug builds of the library. It uses the libutil tracing support to display the value (as a string) in the trace file. In release builds it simply consumes the top value of the stack and does nothing.


Example

  "Trace message" trace

User Defined Functions

TODO: This section should contain a tutorial on defining your own functions.

Copyright © 2001, Shane Gough. All Rights Reserved