14 KiB
- Types:
- Symbols:
- Functions:
- number?
- integer?
- double?
- rational?
- NaN?
- undefined?
- char?
- string?
- cons?
- fn?
- macro?
- array?
- hash-table?
- stream?
- double
- ceil
- floor
- round
- +
- -
- *
- /
- **
- &
- |
- ^
- ~
- &&
- ||
- !
- if
- =
- <
- >
- <=
- >=
- !=
- list
- cons
- car
- cdr
- peek-char
- read-char
- set-reader-macro
- read
- eval
- quote
- def
- set
- macro
- fn
- string
- array
- hash-table
- push
- pop
- insert
- get
- write
- do
- length
- let
- quasiquote
- unquote
- unquote-splicing
- Reader macros:
- Requirements:
Types:
integer
double
rational
character
string
cons
fn
macro
array
hash-table
stream
Symbols:
nil
t
NaN
undefined
Functions:
number?
Is the argument a number?
Takes anything and return T if it's type is an integer, double or rational.
integer?
Is the argument an integer?
Takes anything and return T if it's type is an integer.
double?
Is the argument a double floating-point number?
Takes anything and return T if it's type is a double.
rational?
Is the argument a rational number?
Takes anything and return T if it's type is a rational.
NaN?
Is the argument not a number?
Takes anything and return T if it's type is a double and the value is NaN.
undefined?
Is the argument undefined?
Takes anything and return T if it's pointer is the same as undefined.
char?
Is the argument a character?
Takes anything and return T if it's type is a character.
string?
Is the argument a string?
Takes anything and return T if it's type is a string.
cons?
Is the argument a cons pair?
Takes anything and return T if it's type is a cons.
fn?
Is the argument a function?
Takes anything and return T if it's type is a function.
macro?
Is the argument a macro?
Takes anything and return T if it's type is a macro.
array?
Is the argument an array?
Takes anything and return T if it's type is an array.
hash-table?
Is the argument an hash-table?
Takes anything and return T if it's type is an hash-table.
stream?
Is the argument a stream?
Takes anything and return T if it's type is a stream.
double
Convert a number to double floating-point?
Takes a number and convert it into a double floating-point number.
ceil
Round a number upward?
Takes a number and round it upward.
floor
Round a number downward?
Takes a number and round it downward.
round
Round a number
Takes a number and round it to mathematically closest and if it's in between two integers i.e 0.5, round to closest even (divisible by two) integer
+
Add n numbers
Takes integers, rationals and doubles. If a number is double return a double. Else if a number is rational and the result's denominator is not 1 then return a rational. Else return an integer.
0 number => 0
1 number => n
> 1 numbers => n0 + n1 + n2 …
-
Substract n numbers
Takes integers, rationals and doubles. If a number is double return a double. Else if a number is rational and the result's denominator is not 1 then return a rational. Else return an integer.
0 number => Error
1 number => 0 - n
> 1 numbers => n0 - n1 - n2 …
*
Multiply n numbers
Takes integers, rationals and doubles. If a number is double return a double. Else if a number is rational and the result's denominator is not 1 then return a rational. Else return an integer.
0 number => 1
1 number => n
> 1 numbers => n0 * n1 * n2 …
/
Divide n numbers
Takes integers, rationals and doubles. If a number is double return a double. Else if a number is rational and the result's denominator is not 1 then return a rational. Else return an integer.
0 number => Error
1 number => 1 / n
> 1 numbers => n0 / n1 / n2 …
**
Power 2 numbers
Takes integers, rationals and doubles. If a number is double return a double. Else if a number is rational and the result's denominator is not 1 then return a rational. Else return an integer.
< 2 number => Error
2 numbers => n0 ** n1
> 2 numbers => Error
&
Bitwise AND numbers
Takes integers and return an integer.
0 number => -1
1 number => n
> 1 numbers => n0 & n1 & n2 …
|
Bitwise OR numbers
Takes integers and return an integer.
0 number => 0
1 number => n
> 1 numbers => n0 | n1 | n2 …
^
Bitwise XOR numbers
Takes integers and return an integer.
0 number => 0
1 number => n
> 1 numbers => n0 ^ n1 ^ n2 …
~
Bitwise NOT numbers
Takes an integer and return an integer.
0 number => ERROR
1 number => ~n
> 1 numbers => ERROR
&&
Branching AND expresions.
Takes anything, evaluate left to right and return the first item that eval to NIL or the result of the last eval.
0 item => T
> 0 items => first item to eval to nil or the last item.
||
Branching OR expresions.
Takes anything, evaluate left to right and return the first item that eval to not NIL or the result of the last eval.
0 item => T
> 0 items => first item to eval to not nil or the last item eval.
!
Return T if NIL else NIL.
Takes anything.
if
Branching tree.
Evaluate the condition and then evaluate the true or false branch based on the result. I.e: if the condition evaluate to nil, evaluate the false branch.
=
Compare 2 arguments for equality.
Takes 2 argument and compare them for equality. If the types are different, return false, unless they're different number types. Compare numbers by value: Integer value to integer value if both integer. If integer and rational than always return false. If one is a double, the other argument is to be converted to double and then compared. Rationals are to be compared numerator to numerator and denominator to denominator.
<
Is n0 less than n1?
Compare the first number with the second and return true if it's less than.
>
Is n0 greater than n1?
Compare the first number with the second and return true if it's greater than.
<=
Is n0 less than or equal to n1?
Compare the first number with the second and return true if it's less than or equal.
>=
Is n0 greater than or equal to n1?
Compare the first number with the second and return true if it's greater than or equal.
!=
Compare 2 arguments for inequality.
Takes 2 argument and compare them for inequality. Compare
list
Return a list from the arguments
Return nil if no arguments.
cons
Return a cons pair from 2 arguments
Return an error if more than 2 arguments.
car
Return first element of a pair/list
Return an error if not a cons.
cdr
Return second element of a pair / rest of the list
Return an error if not a cons.
peek-char
Return first char in the specified stream.
Takes nothing, NIL, T or a stream, anything else return an error. If nothing, NIL or T use the standard-input stream as the stream. Return the first character without increasing the reading pointer in the stream.
read-char
Return first char in the specified stream.
Takes nothing, NIL, T or a stream, anything else return an error. If nothing, NIL or T use the standard-input stream as the stream. Return the first character while increasing the reading pointer in the stream.
set-reader-macro
Bind a function on a character that will be triggered during reading.
Takes a character and a function. The later takes in a character and a stream and return a value.
read
Return an expression read in the specified stream.
Takes nothing, NIL, T or a stream, anything else return an error. If nothing, NIL or T use the standard-input stream as the stream. Return the first character while increasing the reading pointer in the stream.
eval
Return the result of the evaluation of an expression.
Takes 1 argument of anything and evaluate it and return the result.
quote
Return the argument received as is.
Therefore preventing any evaluation of it.
def
Bound a value to a symbol in the global environment.
Takes a symbol and anything else. More than 2 arguments result in an error.
set
Set the value of the symbol bound in the environment.
It goes from the local environmnet outward trying to find a binding on the symbol and if it doesn't then it bind it in the global env.
macro
Create a macro function from a list of arguments and the rest is the body.
fn
Create a function from a list of arguments and the rest is the body.
string
Create a string from different value.
If it's a string return it. If it's a symbol, create string from it's text value. If it's a character, create string from it. If it's a number, create the string representation of it. If it's a list or array, concactenate it's content string representation. i.e (string '(\h \e \l \l \o)) => "hello" Return an error on anything else. I.e hash-table, function…
array
Create an array from the arguments.
Takes anything or nothing and create an array with the arguments in it. (array 1 2 3 4) => [1 2 3 4]
hash-table
Create an hash-table from the arguments.
Takes anything or nothing and create an hash-table with the arguments splitted in pairs. The first element of a pair is the key and the second is the value. Return an error if odd number of arguments.
push
Push an element at the end of a collection.
If the collection is a string, convert the element to string and append it. If the collection is a list, append the element to the end of it. If the collection is an array, append the element to the end of it. Else return an error.
pop
Pop an element from the end of a collection.
If the collection is a string, reduce it's length by 1 and return the last character. Handle UTF-8 character so that if the last byte of the string is part of an UTF-8 character, reduce the length until you get the header, and return the UTF-8 character. If the collection is a list, set the cdr of second to last pair to nil and return the last element. If the collection is an array, reduce the length by 1 and return the last element. Else return an error.
insert
Insert an element at a position in a collection.
Let you insert into list, string, array and hash-table. Takes a number position for a list, string, array or anything as key for an hash-table. Takes anything as value to be inserted.
get
Get an element at a position in a collection.
Let you retrieve an element into list, string, array and hash-table. Takes a number position for a list, string, array or anything as key for an hash-table. Return undefined if nothing is found.
write
Write to a stream in a format that could be read back.
Write in a way that the reader could make sense of the result. Useful for writing to a file to be read from later on, or just debugging.
Print to a stream in a human friendly way.
Useful for user messages.
do
Block of expresions to be evaluated.
The last evaluation is to be returned.
length
Return the length of string, list or array.
If anything but a string, list or array return an error. Accepts only 1 argument.
let
Create a local environment
Takes a list of key value list and a body. Creates a new environment table and insert for the key, the evaluated value. Reuse this new environment table for the next key, value pair. Making it that the key, value of the previous pair can be used to eval the current one. Then eval the body, one expression after the other using the new local environment and return the result of the last expression.
quasiquote
Acts like quote but with a twist.
Don't eval the expression but navigate it and eval only the expression with 'unquote' or 'unquote-splicing' as their car.
unquote
Evaluate the expression in place
unquote-splicing
Evaluate the expression and inline the list result.
Inline in a list by changing the cdr of the previous pair to result and the cdr of the last cons in result to be the cdr of the previous cons before the change. i.e (quasiquote 1 2 3 (unquote-splicing (list 4 5)) 6) => (cons 1 (cons 2 (cons 3 (cons 4 (cons 5 (cons 6 nil))))))
Reader macros:
\(
Create a list by reading elements after elements until a \) is encountered.
\)
Return a error because there shouldn't be a closing bracket without a begining.
\'
Quote the following read. I.e 'hello => (quote hello)
\[
Create an array by reading elements after elements until a \] is encountered.
\]
Return a error because there shouldn't be a closing bracket without a begining.
\{
Create an hash-table by reading elements after elements until a \} is encountered.
\}
Return a error because there shouldn't be a closing bracket without a begining.
\`
Quasiquote the following read. I.e `hello => (quasiquote hello). But also create the \, reader-macro and remove it after the following read.
\,
Is created and removed by \`. Unquote or unquote-splicing the following read. I.e ,hello => (unquote hello) ,@'(1 2) => (unquote-splicing '(1 2))
Requirements:
Garbage collection
The idea of the garbage collector is to iterate through the blocks in memory and marking them as free. Then navigate the global environment to mark everything in it as used (not free). And finally reiterate through the blocks again to then actually free them. It's probably a naive implementation, but it's better than nothing. It will run when something is to be allocated and according to a certain interval. Maintain a counter that decrease by an amount relative to the percent of memory used. If the counter goes below zero, run the garbage collector and reset the counter.
Tail call optimisation
This optimisation will be done in the evaluator. The goal is to detect when a function is calling it self in tail position. And to achieve this, on function evaluation on the last item of the body navigate through those constructs if existant: LET, IF, AND, OR and DO. And when we navigate through those construct we're looking for the tail call of them. I.e LET, AND, OR and DO is the last expression, IF is the true or false path. And when after that navigation we end up on call to the function currently being evaluated then we can optimise. The optimisation will consist in updating the environment with the new argument values to be passed to the function and instead of calling eval on it, just execute a jump to the start of the current function evaluation. In the eye of the user nothing will happen, but it will prevent that the stack based host pulls out a stack overflow. There might be a boost in performance, but it's probably minimal.