Gabriel Pariat
2 years ago
7 changed files with 5324 additions and 32 deletions
@ -1,13 +0,0 @@
@@ -1,13 +0,0 @@
|
||||
Running suite(s): Memory |
||||
Array |
||||
Table |
||||
Symbol |
||||
String |
||||
Cons |
||||
Environment |
||||
Evaluator |
||||
Lisp |
||||
Reader |
||||
Printer |
||||
100%: Checks: 85, Failures: 0, Errors: 0 |
||||
PASS check_ptlisp (exit status: 0) |
@ -1,4 +0,0 @@
@@ -1,4 +0,0 @@
|
||||
:test-result: PASS |
||||
:global-test-result: PASS |
||||
:recheck: no |
||||
:copy-in-global-log: no |
@ -1,14 +0,0 @@
@@ -1,14 +0,0 @@
|
||||
====================================== |
||||
ptlisp 0.1: tests/test-suite.log |
||||
====================================== |
||||
|
||||
# TOTAL: 1 |
||||
# PASS: 1 |
||||
# SKIP: 0 |
||||
# XFAIL: 0 |
||||
# FAIL: 0 |
||||
# XPASS: 0 |
||||
# ERROR: 0 |
||||
|
||||
.. contents:: :depth: 2 |
||||
|
@ -0,0 +1,375 @@
@@ -0,0 +1,375 @@
|
||||
* 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. |
Loading…
Reference in new issue