The Isis Primer

This introduction to Isis assumes you have a basic understanding of computer programming and a working knowledge of the Unix operating system. If you are completely new to programming or Unix, you may wish begin elsewhere. Contact Stefan for some suggestions on how best to proceed.


Running Isis

In general, you can always start an Isis interpreter by simply typing isis at your shell prompt. You will see something like this:
$ isis *** Isis 6 ->
The -> is Isis's prompt, letting you know that it is ready for you to type expressions directly into the interpreter. Alternatively, you can write an Isis program using your favorite text editor and run Isis on the contents of a file by passing the name of the file as an argument, like this:
$ isis test1.isis ...
Any of the examples shown below can be written in a file or typed directly into the Isis interpreter with exactly the same effect.

Check the getting started section for more information on how to install Isis and how to work with Isis interpreters under Unix-based operating systems.


Expressions and Values

The Isis interpreter reads expressions from your keyboard or from a file, and evaluates each one to produce a value. If you type the expression directly on your keyboard, its value will be printed on your screen for you to see. You can enter several expressions on a single line if you like, and they will be evaluated in order.

The simplest kind of expression you could possibly enter is a constant. For a very simple example, type the number 42 in the interpreter and press return:

-> 42 42 ->
In this case, you typed the expression 42, which evaluated to the value 42. All constants evaluate to themselves.


Types

Every value in Isis has a type. There are 7 types possible in Isis: integer, real number, character, boolean, address, procedure, and list. The first six of these are called basic types because they cannot be subdivided further. Lists are merely ordered collections of values of any type. Each of these types is explained below:


Comments

Like most other programming languages, you can embed comments in your Isis programs that will be ignored by the interpreter. In Isis, any text entered following the character # on a single line will be treated as a comment. Placing comments in strategic places will greatly enhance the readability of your programs.
-> 43 # This is a comment that will be ignored by the interpreter 43 -> 'x' ##### hi mom 'x'
You can create multi-line comments by following the # with a curly-bracket {. Everything up to the next closing curly-bracket } will be considered a comment.
-> [ 1 2 3 #{ This is a multi-line comment } 4 5 6 ] [ 1 2 3 4 5 6 ]


Multi-line expressions

If the expression you are typing is too large to fit on one line, you can press return in the middle of the expression as many times as you like. Isis will only evaluate the expression when all brackets and parentheses have been closed.
-> [1 2 3 4 5 6 7 8 9 10 11 12 13 # here is a frivolous comment 14 15 16 17 18] [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ] ->


Strings

A "string" is computer jargon for a sequence of characters that represents a quotation or other piece of text. In Isis, strings are handled simply as lists that contain only character values. However, it is tiresome to type out each character constant in a list in order to create a string. Thankfully, Isis provides a short-cut---all you have to do is enclose the sequence of characters in double quotes. Typing out the list of character literals will produce exactly the same result. In addition, when printing a list, the interpreter checks if all the elements of the list are characters, and if so, a string enclosed in double quotes is printed instead (just as you might have entered it).
-> "hello!" "hello!" -> [ 'h' 'e' 'l' 'l' 'o' '!' ] "hello!"


Null

Isis provides the ability to express an "empty" (or "null") value by entering Null. Null values represent the absence or nonexistence of a value. Null is commonly returned from procedures when a return value does not make sense or if there is an error. Null evaluates to itself, and it is printed simply as Null.
-> Null Null


Errors

The interpreter will print error messages whenever it can't understand what you have typed in. By convention, errors will always appear on lines by themselves preceded by an asterisk *.
-> 'qq' * Error line 1: Bad character constant. 'q' -> ] * Error line 2: Too many close parens/brackets. Null -> Falsse * Variable 'Falsse' has not been defined. Null ->
Isis provides a number of debugging utilities that are described in the debugging section of the documentation that you might like to read later.


Other Isis expressions

The following sections describe other core language expressions available in Isis. In each definition, any italicized word may be replaced by any expression described in this document, including the constant expressions described above. Any elements surrounded in curly brackets { } are optional. Elipses (...) indicate that an arbitrary number of elements following the established pattern is allowed. Finally, varname represents a variable name, which must be a sequence of characters that does not begin with a number, a period, or the characters + or -.


Variables

Variable binding

( set varname exp )

Variable reference

varname

Variable query

( bound? varname )
Variables are named storage locations for values of any type. Use the set expression to bind a variable to the value of a particular expression. If the variable was already bound, its value will be reset to the new value. To retrieve the value of a variable, simply enter the variable name. Use bound? to check if a variable is defined in the current environment. bound? will return either True or False.
-> (set x 42) 42 -> (set y "abc") "abc" -> x 42 -> y "abc" -> (set x [ 1 2 3 ]) [ 1 2 3 ] -> x [ 1 2 3 ] -> (bound? x) True -> (bound? q) False


Lists

List formation

[ exp exp ... ]

List reference

( list index )
A list is simply an ordered collection of values of any type. To create a list, simply enclose an arbitrary number of expressions in sqaure brackets [ ]. The expressions are evaluated and their values become the elements of the list.

The list reference expression retrieves a particular item in a list. list must evaluate to a list value and index must evaluate to an integer. The first item in a list is numbered 0 (zero). Null will be returned and an error will be printed if the index is out of range.

-> (set alist [10 11 12 13 14 15]) [ 10 11 12 13 14 15 ] -> (alist 3) 13 -> (alist 10) * Index 10 out of range. Null -> (set blist [ ["stefan" "E15-348"] ["vmb" "E15-324"] ["willy" "E15-339"]]) [ [ "stefan" "E15-348" ] [ "vmb" "E15-324" ] [ "willy" "E15-339" ] ] -> ((blist 2) 1) "E15-339"


Memory manipulation

Memory retrieval

( address memtype )
( address [ memtype len ] )
( address [ memtype len offset ] )

Memory storage

( address memtype val )
( address [ memtype len ] val )
( address [ memtype len offset ] val )
These expressions allow you to access and manipulate data directly in memory. Single elements or arrays of data may be stored and retrieved from any given address, with an optional offset. These operators are explained on the memory manipulation documentation page, along with other useful memory utilities, including routines for allocating and deallocating memory for your own use.


Conditional evaluation

Conditionals enable you to branch the execution of your program in different ways depending on the value of a certain expression. Isis has 4 such constructs, each described below. Typically, Isis will evaluate a condition expression, and depending on whether its value logically true or logically false, the interpreter will proceed in a different way, leaving certain expressions unevaluated. Isis considers a value to be logically true if it is a non-zero number, character, or address, or if the value is a procedure or a non-empty list, or if it is the boolean True. Any other value, including Null, is considered logically false.

if statement

( if exp then { else } )
If exp evaluates to a logically true value, the result of evaluating the then expression is returned. Otherwise, the result of the else expression, if it exists, is returned. If the else expression is omitted, Null is returned. Only one of either the then or else expressions is evaluated.
(print "Please enter username: ") (set username (read-string)) (if (= username "Stefan") (print "Welcome Sir." newline) (print "Access denied." newline))

cond statement

( cond ( exp val ) ( exp val ) ... )
The exp expressions are evaluated in order until one of them results in a logically true value, and then the result of the corresponding val expression is returned. Only the val expression corresponding to the first logically true condition is evaluated. A condition of True could be used at the end to specify a default action. If none of the conditions results in a logically true value, Null is returned.
(print "Please enter your age: " newline) (set age (eval (read-string))) (set bev (cond ((< age 2) "warm milk") ((< age 12) "fruit punch") ((< age 21) "a milkshake") ((> age 50) "a glass of lemonade") (True "a shot of tequilla"))) (print "Your beverage will be " bev ". Please be seated." newline)

while statement

( while exp body )
The body expression is evaluated repeatedly as long as exp results in a logically true value. The value of the entire while expression is the value of the body the last time it is evaluated, or Null if it is never evaluated because the condition was initially false.
(set x 10) (while (> x 0) (begin (print x) (sleep 1) (set x (- x 1)))) (print "Blastoff!" newline)

switch statement

( switch exp ( case val ) ( case val ) ... { ( else val ) } )
exp is evaluated, and its value is compared in sequence to the results of the case expressions until a match is found, and the result of the corresponding val expression is returned. If desired, use the keyword else at the end to specify a default action. If no match is found and no else is present, Null is returned.
(print "Please enter your preference: ") (set selection (read-string)) (set dinner (switch selection ("carnivore" "barbequed ribs") ("vegetarian" "a spinach omelette") ("vegan" "cucumber salad") (else "freshly cut twigs"))) (print "Your dinner will be " dinner ". Please be seated." newline)

Logic

Isis provides the logical operators and, or, nand, and nor:
( and exp exp ... )
( or exp exp ... )
( nand exp exp ... )
( nor exp exp ... )
The and statement returns True only if all its expressions evaluate to logically true values. The or statement returns True if just one or more of its expressions evaluate to logically true values. Otherwise, these expressions return False. nand and nor are analogous to and and or except they will return the opposite value ("not" and and "not" or).

As stated above, Isis considers a value to be logically true if it is a non-zero number, character, or address, or if the value is a procedure or a non-empty list, or if it is the boolean True. Any other value, including Null, is considered logically false.

In these constructs, Isis only evaluates the necessary expressions from left to right to determine the result. For example, if the first expression in an and statement evaluates to a false value, any remaining expressions are not evaluated, because their values would have no effect on the final result.

(print "Please enter your hair color: ") (set hair (read-string)) (print "Please enter your sex: ") (set sex (read-string)) (print "Please enter your shoe size: ") (set shoe (eval (read-string))) (cond ((and (= hair "brown") (= sex "male") (= shoe 10)) (print "Hi Wilbert." newline)) ((and (= sex "female") (= hair "blonde")) (print "Please to meet you, maam." newline)) ((or (= hair "green") (> shoe 20) (and (!= sex "female") (!= sex "male"))) (print "Welcome to Earth." newline)) (True (print "Your information has been recorded. Goodbye." newline)))


Sequential evaluation

begin statement

( begin exp exp ... )
The begin statement allows you to encapsulate several operations in a single expression. Each expression is evaluated in order, and the value of the final expression is returned.
(print "Please enter your current heart rate: ") (set rate (eval (read-string))) (set period (* 60.0 (/ 1.0 rate))) (print "I will now count your heartbeats: " newline) (set x 1) (while True (begin (print x) (sleep period) (set x (+ x 1))))

Local environments

local statement

( local ( varname varname ... ) exp )
The local expression sets up a local environment consisting of the specified variables. A local environment is a collection of variables that are accessible only within the body of the local statement. These variables are automatically given an initial value of Null.

The given expression is then evaluated in the context of this new environment and its value returned. Since the local variable names may duplicate those in the parent environment, variable references in the body expression are resolved by first looking in the local environment and then, if not found there, in the parent environment.

(set x 3) (set y 7) (set z 32) (local (y z) (begin (set y 100) (set z 200) (print "Inside the local statement: " (+ x y z) newline))) (print "Outside the local statement: " (+ x y z) newline)

Procedures

Procedure definition

( proc ( varname varname ... ) exp )
( proc varname exp )

Procedure application

( proc exp exp )
Procedures express an action that should be taken on a set of values that has not yet been determined (the arguments). Procedures may be defined in two ways. In the first way, specific variable names are given (enclosed in parentheses) for each argument that will be passed to the procedure when it is applied. A procedure of this kind must always be called with exactly that number of arguments. In the second way, a single variable name is given that will become bound to a list of the arguments passed to the procedure. This allows the procedure to accept an arbitrary number of arguments.

When a procedure is defined, it includes a reference to the environment within which it was defined. Then, when the procedure is applied, a new local environment is created on top of this environment in which the procedure's argument variable names are bound to the corresponding values that are passed to it. The given expression will be evaluated in the context of this new environment. Therefore, variable references in the body are resolved first in the local environment (the argument variables) and then in the parent environment (the environment in which the procedure was defined, not the environment in which it is applied).

The result of a procedure definition is a procedure value. You can invoke the procedure by using this value in a procedure application expression. In a procedure application, the proc expression must evaluate to a procedure value. This procedure is applied to the values of the remaining expressions. Procedure application is the same regardless of whether the procedure was written directly in Isis or if it links to an external C function.

-> (set add3 (proc (fred) (+ fred 3))) Proc -> (add3 10) 13 -> (add3 20 30) * Incorrect number of arguments in call (2 for 1). 23 -> (set dup (proc arglist (append arglist arglist))) Proc -> (dup 1 2 3 4) [ 1 2 3 4 1 2 3 4 ] -> (set factorial (proc (x) (if (= 0 x) 1 (* x (factorial (- x 1)))))) Proc -> (factorial 10) 3628800