Language Description
This section serves as a comprehensive guide to the UniotLisp language itself. It is intended for users who want to learn how to write programs in UniotLisp, understand its syntax, semantics, and utilize its features effectively.
Language features
UniotLisp is a traditional Lisp interpreter. It reads one expression at a time from the standard input, evaluates it, and then prints out the return value of the expression. Here is an example of a valid input.
The above expression prints "3".
UniotLisp comes with a set of built-in primitives that provide essential functionalities. These primitives are the fundamental operations that can be used within Lisp code.
Literals
UniotLisp supports integer literals, ()
, #t
, symbols, and list literals.
Integer Literals: Positive or negative integers.
()
: Represents both the false value (Nil
) and the empty list.#t
: Represents the true value (True
). It's a preferred way to representtrue
, while any non-()
value is considered true.Symbols: Objects with unique names used to represent identifiers. Since UniotLisp does not have a string type, symbols are sometimes used as substitutes for strings.
List Literals: Constructed using cons cells. They can be regular lists (ending with
()
) or dotted lists (ending with any non-()
value).
List Operators
UniotLisp provides fundamental list manipulation operators: cons
, car
, cdr
, and setcar
.
cons
: Constructs a cons cell from two arguments, setting the first argument as thecar
and the second as thecdr
.car
: Retrieves the first element (car
) of a cons cell.cdr
: Retrieves the second element (cdr
) of a cons cell.setcar
: Mutates thecar
of an existing cons cell. It takes two arguments: the cons cell to mutate and the new value for thecar
.
Numeric Operators
UniotLisp includes basic arithmetic and comparison operators: +
, -
, *
, /
, %
, <
, <=
, >
, >=
, =
, and abs
.
+
: Returns the sum of its arguments.-
: Negates its argument if only one argument is provided; otherwise, subtracts each subsequent argument from the first.*
: Returns the product of its arguments./
: Divides the first argument by the subsequent arguments. Raises an error on division by zero.%
: Computes the modulo of the first argument by the second. Raises an error on division by zero.<
: Checks if the first argument is less than the second. Returns#t
if true, otherwise()
.<=
: Checks if the first argument is less than or equal to the second. Returns#t
if true, otherwise()
.>
: Checks if the first argument is greater than the second. Returns#t
if true, otherwise()
.>=
: Checks if the first argument is greater than or equal to the second. Returns#t
if true, otherwise()
.=
: Checks if two integers or boolean values are equal. Returns#t
if both arguments are the same integer or both represent the same boolean value, otherwise returns()
.abs
: Computes the absolute value of an integer.
Logical Operations
UniotLisp provides logical operations for boolean expressions: and
, or
, and not
.
and
: Returns#t
if all arguments are true; otherwise, returns()
.or
: Returns#t
if any argument is true; otherwise, returns()
.not
: Returns#t
if the argument is()
, otherwise returns()
.
Conditionals
UniotLisp provides the if
special form for conditional execution and eq
for testing equivalence between objects.
(if condition then-expr else-expr)
:Behavior: Evaluates
condition
. If the result is a true value (#t
or any non-()
value), it evaluates and returnsthen-expr
. Otherwise, it evaluates and returnselse-expr
.Examples:
eq
:Behavior: Performs a pointer comparison. Returns
#t
if both arguments reference the exact same object, otherwise returns()
.Examples:
Loops
UniotLisp supports looping through the while
special form.
Syntax:
Behavior: Continues to evaluate
expr ...
as long ascondition
evaluates to a true value (#t
or any non-()
value). The loop terminates whencondition
evaluates to()
.Example:
Output:
Note: Unlike Scheme, UniotLisp does not support tail recursion for loops. Tail calls consume stack space, leading to memory exhaustion errors if used for looping.
Quoting and Evaluation
UniotLisp provides mechanisms to control the evaluation of expressions and manipulate code as data. This section covers the quote
special form, the shorthand single quote ('
), the eval
primitive, and the list
primitive.
quote
: Thequote
special form is used to prevent the evaluation of an expression. Instead of evaluating its argument,quote
returns the expression itself as data.Syntax:
Behavior:
Returns the
expression
without evaluating it.Useful for representing literal data structures or symbols.
Examples:
'
(Single Quote): The single quote ('
) is a shorthand notation for thequote
special form, providing a more concise way to prevent evaluation of an expression.Syntax:
Behavior:
Equivalent to
(quote expression)
.Enhances readability and reduces verbosity in code.
Examples:
eval
: Theeval
primitive evaluates a given expression within the current environment. It takes a quoted expression and returns the result of its evaluation.Syntax:
Behavior:
Evaluates the
expression
as if it were entered directly.Useful for dynamic code execution and metaprogramming.
Examples:
Notes:
The argument to
eval
must be a quoted expression; otherwise, it will be evaluated before being passed toeval
.Use
eval
with caution, as it can execute arbitrary code, which may lead to security vulnerabilities if not managed properly.
list
: Thelist
primitive constructs a new list from its evaluated arguments. It takes any number of arguments, evaluates each one, and returns a list containing those values.Syntax:
Behavior:
Evaluates each
expr
and assembles them into a new list.Useful for creating dynamic lists based on runtime values.
Examples:
Notes:
Unlike
quote
, the arguments tolist
are evaluated before being included in the new list.Combining
list
withquote
allows for flexible construction of complex data structures.
Output Operators
UniotLisp provides the print
primitive for outputting objects to the standard output.
print
:Purpose: Prints the string representation of a given object.
Usage:
Behavior: Outputs the evaluated object to the standard output. Does not return the printed object; instead, it returns
()
.
Definitions
UniotLisp supports defining variables and functions using define
, setq
, lambda
, and defun
.
Defining Variables:
Syntax:
Behavior: Evaluates
expression
and binds the result tovariable-name
in the current environment.Example:
Assigning Values to Variables
Syntax:
Behavior: Updates the binding of the variable with the evaluated expression. Raises an error if the variable is not defined.
Example:
Defining Functions:
There are two primary ways to define functions in UniotLisp: using
lambda
anddefun
.Using
lambda
:Syntax:
Behavior: Creates an anonymous function that can be assigned to a variable or used directly.
Example:
Using
defun
:Syntax:
Behavior: Defines a named function, equivalent to using
define
withlambda
.Example:
Note:
You can write a function that takes a variable number of arguments. If the parameter list is a dotted list, the remaining arguments are bound to the last parameter as a list.
Variable Scope and Lexical Binding:
Variables in UniotLisp are lexically scoped and have indefinite extent. This means that references to "outer" variables remain valid even after the function that created the variables returns.
Example:
Macros
Macros in UniotLisp provide powerful metaprogramming capabilities by allowing code transformations before evaluation.
Defining Macros (
defmacro
):Syntax:
Behavior: Defines a macro that takes expressions as input and returns a new expression to be evaluated.
Example: Define an
unless
macro that acts as the opposite ofif
.
Macro Expansion:
Purpose: Transforms macro calls into their expanded forms before evaluation.
Example Usage:
macroexpand
:Purpose: A special form to view the expanded form of a macro without evaluating it.
Syntax:
Example:
gensym
:Purpose: Generates a unique symbol that is guaranteed not to be
eq
to any other symbol except itself. Useful for creating unique identifiers within macros.Usage:
Comments
Comments in UniotLisp follow the traditional Lisp syntax, using the semicolon (;
) to start a single-line comment.
Syntax:
Behavior: The interpreter ignores any text following a semicolon until the end of the line.
Example:
For further assistance or to contribute to the project, please refer to the project's repository or contact the maintainers.
Last updated