Table of Contents
Aspic Programming Language, version 0.8
©2009,2025 by Mark Damon Hughes
cyberhole.online/aspic/
Text licensed as CC BY-NC-SA Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International license
Code licensed as BSD, see LICENSE.txt
Aspic is a Lisp-like scripting language.
Comments start with a ; and continue to the end of the line. They should be separated from other symbols by a space.
Valid data types are numbers, strings, lists, and words.
Numbers are 64-bit IEEE doubles.
Strings are double-quoted and escaped like C. Strings are immutable.
[A-Za-z_][A-Za-z0-9_]*
[ ;\t\r\n()\"] is a valid
word, but at least start with a letter unless you know what you're
doing.When a value is "eval num", numbers are returned, strings are parsed into number or 0 if invalid, lists cause an error.
(apply FNAME A...)
FNAME is evaluated, producing a string name of the function to call. A bare name is a variable, which is evaluated to determine the function. There is no direct lambda syntax, you need to define all functions with names.
Passes all arguments to that function, which evaluates them as usual.
(begin A...)
Evals each argument, and returns the value of the last one.
(break)
Interrupts a while loop. It is an error to use (break) outside of a while loop.
(cond (TEST THEN)...)
For each (TEST THEN) pair in order, eval TEST; if true, eval THEN and return result.
If the end is reached, returns 0.
To have an "else" clause, use 1 as the last TEST.
(define (NAME P...) BODY)
Defines a new function NAME, with parameters P..., which will eval BODY when called.
Unlike Scheme or Lisp, it does not introduce variable names.
(if A THEN ELSE)
Evals A; if true, eval THEN and return result; if false, eval ELSE and return result.
(while A LOOP)
Repeatedly eval bool A; if true, eval LOOP; if false, return last result of LOOP.
while can be interrupted with (break).
(global NAME X)
Sets global variable NAME to eval X.
(set NAME X)
Sets local variable NAME to eval X. This only affects the most recent function scope.
(display X...)
For each X, eval it, write concatenation to display.
(error X...)
For each X, eval it, then cause an error with concatenation as message.
(input FNAME)
Reads a line of input from Terminal, and calls function FNAME with it, when it is done.
TODO: suspends VM until complete.
(load FILENAME FNAME)
Evals FILENAME as string, loads that relative URL as a script, calls
function FNAME when it is done.
TODO: suspends VM until complete.
(isnumber A)
If eval(A) is a number, returns 1, else returns 0.
(isstring A)
If eval(A) is a string, returns 1, else returns 0.
(int N)
Evals VALUE and returns its equivalent as an integer.
If value is not a string or number, an error occurs.
(lower VALUE)
(title VALUE)
(upper VALUE)
Evals VALUE, which must be a string, and returns lower-case, title-case, or upper-case version. Results may depend on locale.
title-case changes every char, if preceded by a letter, becomes lower-case; otherwise it is upper-cased.
If value is not a string, an error occurs.
(chr VALUE)
Evals VALUE, which must be a number, and returns a single-character string of given Unicode code point.
If value is not a number, an error occurs.
(num VALUE)
Evals VALUE and returns its equivalent as a number.
If value is not a string or number, an error occurs.
(ord VALUE)
Evals VALUE, which must be a string, and returns a number of the first character's Unicode code point.
If value is not a string, an error occurs.
(str VALUE...)
Evals each VALUE, concatenates it, and returns the result as a single string.
(add X Y...) or (+ X Y...)
Eval num X and use as starting total.
For each Y, eval and add to total.
Returns total.
(sub X Y...) or (- X Y...)
Eval num X and use as starting total.
For each Y, eval num and subtract from total.
Returns total.
(mul X Y...) or *(\ X Y...)**
Eval num X and use as starting total.
For each Y, eval num and multiply by total.
Returns total.
(div X Y...) or (/ X Y...)
Eval num X and use as starting total.
For each Y, eval num and divide total by it. Divide by 0 is an error.
Returns total.
(mod X Y...) or (% X Y...)
Eval num X and use as starting total.
For each Y, eval num and modulo total by it. Modulo by 0 is an error.
Returns total.
(and X...)
Eval each X as bool, returns 0 if any are false, or last non-false value.
It does short-circuit, values after false are not evaluated.
(or X Y)
Eval each X as bool, returns first non-false value, or 0 if all are false.
It does short-circuit, values after true are not evaluated.
(not X)
Eval bool X; if true, return 0; if false, return 1.
(eq A B) or (== A B)
Evals A and B, and compares the results, which must be of the same type.
If eval(A) == eval(B), returns 1; else returns 0.
(ne A B) or (!= A B)
Evals A and B, and compares the results, which must be of the same type.
If eval(A) != eval(B), returns 1; else returns 0.
(lt A B) or (< A B)
Evals A and B, and compares the results, which must be of the same type.
If eval(A) < eval(B), returns 1; else returns 0.
(le A B) or (<= A B)
Evals A and B, and compares the results, which must be of the same type.
If eval(A) <= eval(B), returns 1; else returns 0.
(gt A B) or (> A B)
Evals A and B, and compares the results, which must be of the same type.
If eval(A) > eval(B), returns 1; else returns 0.
(ge A B) or (>= A B)
Evals A and B, and compares the results, which must be of the same type.
If eval(A) >= eval(B), returns 1; else returns 0.
(islist A)
If eval(A) is a list, returns 1, else returns 0.
(length VALUE)
Evals VALUE and returns its length:
If it is a string, the number of characters.
If it is a list, the number of items.
If it is a number, an error occurs.
(list VALUE...)
Evals each VALUE and returns a list containing the results.
(first A) or (car A)
Evals A;
If eval(A) is a list of 1+ items, returns the first item.
If eval(A) is a string of 1+ chars, returns the first char as a string.
Otherwise an error occurs.
(butfirst A) or (cdr A)
Evals A;
If eval(A) is a list of 1+ items, returns all but the first item as a list.
If eval(A) is a string of 1+ chars, returns all but the first char as a string.
Otherwise an error occurs.
(indexof NEEDLE HAYSTACK)
Evals NEEDLE and HAYSTACK:
If eval(HAYSTACK) is a list, returns the index at which eval(NEEDLE) is found, or -1 if not found.
If eval(HAYSTACK) is a string, returns the index at which eval(NEEDLE), which must be a string, is found, or -1 if not found.
Otherwise an error occurs.
(items A FROM TO)
Evals A, FROM, and TO;
If eval(A) is a list, returns a list containing items FROM through TO, inclusive.
If eval(A) is a string, returns a string containing chars FROM through TO, inclusive.
Otherwise an error occurs.
Strings and lists are 0-indexed. Negative indices count from the end. If FROM or TO are greater than length, an error occurs.
(last A)
Evals A;
If eval(A) is a list of 1+ items, returns the last item.
If eval(A) is a string of 1+ chars, returns the last char as a string.
Otherwise an error occurs.
(butlast A)
Evals A;
If eval(A) is a list of 1+ items, returns all but the last item as a list.
If eval(A) is a string of 1+ chars, returns all but the last char as a string.
Otherwise an error occurs.
(listref LS INDEX)
Evals LS and INDEX:
If eval(LS) is a list, and eval(INDEX) is a number and between 0 and
length of list-1, the INDEX-th item from it is returned.
Otherwise an error occurs.
Equivalent to (first (items LS INDEX INDEX))
(listset LS INDEX VALUE)
Evals LS, INDEX, and VALUE. As listref, but replaces the item with eval(VALUE), and returns it.
(makelist LEN FILL)
Creates a new list of given size eval(LEN), each cell filled with eval(FILL), which must be a string or number.
(merge VALUE...)
Creates a new list containing all values.
If eval(VALUE) is a list, all elements in that list are added to the new list;
otherwise the single item is added to the new list.
Returns the new list.
(merge 1 (list 2 3 4) 5) returns list (1 2 3 4 5)
(reverse A)
Evals A;
If eval(A) is a list, returns a list with items in reversed order.
If eval(A) is a string, returns a string with characters in reversed order.
Otherwise an error occurs.