You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
376 lines
14 KiB
376 lines
14 KiB
2 years ago
|
* 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
|
||
|
*** 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.
|