Lisp Operating System, Abstraction Kernel Programming Language Description Copyright (C) 2004 - 2012 by Omar Jarjur Overview: The language implemented by the system is a purely functional dialect of Lisp. It uses static scope and an eager evaluation strategy. It also provides fixed precision integer arithmetic operations. The mainstream dialect that it most closely resembles is probably Scheme. A losak program is repeatedly evaluated with the result being used for I/O. Specifically, if a program evaluates to a function then the next input event (or null if no such events are available and the program was compiled without multitasking support) is passed to this function as a parameter and evaluation continues. Otherwise, if a program evaluates to a pair, the head of the pair is executed as an output event, and the tail of the pair is evaluated as the remainder of the computation. Kernel Parameters: Although subsequent stages of the process take a single parameter, the first value that a program evaluates to is a function that takes two parameters; one for the number of available cons cells, and the second for the parameter string. The parameter string is a list of integers, with each integer representing the ascii value of a character in the string. System Input: Each of the system input events have the following form. If it is (), then no new input is available yet. If it is a number, then it is a keycode received from the keyboard. Otherwise, it should be a pair of numbers, where the first number is an I/O port and the second number is the value in that port. System Output: Each output event generated by the program is interpreted as follows: If it is a number, then it is the next ascii value to be written to the screen. If it is a pair of numbers then the first number is an I/O port and the second number is a value to be written to that port. If it is a list of one number, then it is a request to poll that numbered I/O port. If it is a list of two numbers, then the first number is a memory location (less than 1 megabyte) and the second number is a (8-bit) value to be written to that memory location. Multitasking: Losak programs can be compiled in multitasking mode by passing the "-m" parameter to the compiler. This adds the ability to run multiple concurrent threads in the program. Child threads are forked by evaluating to a pair of the definition of the child thread, and the subsequent value of the parent thread. The child thread is defined using a list of the child thread's ID, the amount of memory allocated to it, and the child thread's initial value. A thread can send a message to another thread by evaluating to a pair of the message and the thread's subsequent value. If the message is a single element list, then that element is sent to the thread's parent. If the message is a two element list, then the first element identifies a child thread, and the second element is a value to be sent to that child thread. The root thread is considered to have the host system as its parent. Thus, system input events are sent to the top-level thread, and messages sent by that thread to its parent are treated as system output events. Language Constructs: A program consists of zero or more definitions followed by an expression. Any malformed expressions evaluate to (). Each primitive is a function except for define, quote, quasiquote, unquote, fn, if, cond, and let. Each parameter to a function is evaluated before that function is applied to it. Pattern matching is used both in let expressions and in function application. So, for example "((fn ((a . b) c) (cons a c)) '(1 . 2) 3)" evaluates to "(1 . 3)". Syntactic sugar is provided for defining quoted expressions and for quoted lists of integers. ' is equivalent to (quote ), ` is equivalent to (quasiquote ), , is equivalent to (unquote ), and "" is equivalent to (quote (<#X> <#Y> <#Z>)) where <#X> is the ascii value of the character . So "hello" will be parse as (quote (104 101 108 108 111)). (define ( . ) ) : Add a new function with the name , arg list of , and body of to the global definitions. This is only allowed at the top level; anywhere else it will simply evaluate to (). (define ) : Evaluate and add it to the global definitions with the name . This is only allowed at the top level; anywhere else it will simply evaluate to (). (quote ) or ' : Return without evaluating it. (quaisquote ) or ` : Return without evaluating it, except for subexpressions preceeded by a , or unquote. (unquote ) or , : Evaluate even if it is inside of a quasiquote. (fn ) : Return a static scoped function with the argument list and the value . (if ) : Evaluate . If it returned any value other than (), then evaluate and return its value. Otherwise, evaluate and return its value. (cond ( ) ( ) ...) : Repeatedly evaluate a until one of them returns a value other than (). At that point evaluate the corresponding and return its value. If every returns (), then return (). (let (( ) ( ) ... ) ): Evaluate each and bind its value to the corresponding . Then evaluate in the new environment and return its value. ( . ) : If is a function then evaluate and apply the function to it. Otherwise return (). (cons ) : Return the pair ( . ) (car ) : If is a pair return its first element. Otherwise return (). (cdr ) : If is a pair return its second element. Otherwise return (). (null? ) : If is null return a non-nil value. Otherwise return (). (pair? ) : If is a pair return a non-nil value. Otherwise return (). (symbol? ) : If is a symbol return a non-nil value. Otherwise return (). (number? ) : If is a number return a non-nil value. Otherwise return (). (function? ) : If is a function return a non-nil value. Otherwise return (). (= ) : Return a non-nil value if and are the same number or the same symbol. Otherwise return (). (< ) : Return a non-nil value if and are numbers and is less than , or if and are symbols and alphabetically precedes (In terms of ASCII characters). Otherwise return (). (> ) : Return a non-nil value if and are numbers and is greater than , or if and are symbols and alphabetically follows (In terms of ASCII characters). Otherwise return (). (+ ) : Return the sum of the two numbers and . (- ) : Return the negation of . (- ) : Return the difference of the two numbers and . (* ) : Return the product of the two numbers and . (/ ) : Return the integer quotient of divided by . (% ) : Return the integer remainder of divided by . (>> ) : Signed right shift of by places. (>>> ) : Unsigned right shift of by places. (<< ) : Left shift of by places. (& ) : Return the bitwise and of and . (| ) : Return the bitwise or of and . (^ ) : Return the bitwise xor of and . (~ ) : Return the bitwise negation of .