initial support for nil, make-list

unfinished, but usable.. still 0 is false in libs and code
This commit is contained in:
VaclavT 2021-03-01 18:26:58 +01:00
parent 46b29fc229
commit 8586a66285
6 changed files with 55 additions and 13 deletions

View File

@ -4,7 +4,7 @@
### TODO ### TODO
- test whether AIG,,,10 csv row is parsed - test whether AIG,,,10 csv row is parsed
- support for (), nil, t - support for (), nil, t, in lsp code replace 0 by nil in logicals
- print-table - print-table
- download 10 years of data from api.nasdaq.com into test dir - download 10 years of data from api.nasdaq.com into test dir
- documentation - documentation

View File

@ -24,4 +24,9 @@
(print (string-lpad "lpad" 10 "x")) (print (string-lpad "lpad" 10 "x"))
(print nil)
(print ())
(print (make-list 5))
(print "Debug ends") (print "Debug ends")

37
ml.cpp
View File

@ -30,7 +30,6 @@
#define INVALID_ORDER "cannot order expression" #define INVALID_ORDER "cannot order expression"
#define BAD_CAST "cannot cast" #define BAD_CAST "cannot cast"
#define ATOM_NOT_DEFINED "atom not defined" #define ATOM_NOT_DEFINED "atom not defined"
#define EVAL_EMPTY_LIST "evaluated empty list"
#define INTERNAL_ERROR "internal virtual machine error" #define INTERNAL_ERROR "internal virtual machine error"
#define INDEX_OUT_OF_RANGE "index out of range" #define INDEX_OUT_OF_RANGE "index out of range"
#define MALFORMED_PROGRAM "malformed program" #define MALFORMED_PROGRAM "malformed program"
@ -40,6 +39,7 @@
#define INT_TYPE "int" #define INT_TYPE "int"
#define FLOAT_TYPE "float" #define FLOAT_TYPE "float"
#define UNIT_TYPE "unit" #define UNIT_TYPE "unit"
#define NIL_TYPE "nil"
#define FUNCTION_TYPE "function" #define FUNCTION_TYPE "function"
#define ATOM_TYPE "atom" #define ATOM_TYPE "atom"
#define QUOTE_TYPE "quote" #define QUOTE_TYPE "quote"
@ -93,6 +93,12 @@ MlValue MlValue::string(const std::string &s) {
return result; return result;
} }
MlValue MlValue::nil() {
MlValue result;
result.type = NIL;
return result;
}
// Construct a lambda function // Construct a lambda function
MlValue::MlValue(const std::vector<MlValue> &params, MlValue ret, MlEnvironment const &env) : type(LAMBDA) { MlValue::MlValue(const std::vector<MlValue> &params, MlValue ret, MlEnvironment const &env) : type(LAMBDA) {
// We store the params and the result in the list member // We store the params and the result in the list member
@ -162,7 +168,7 @@ bool MlValue::is_number() const {
// Get the "truthy" boolean value of this value. // Get the "truthy" boolean value of this value.
bool MlValue::as_bool() const { bool MlValue::as_bool() const {
return *this != MlValue(0); return type != NIL && *this != MlValue(0); // TODO remove 0 as false
} }
// Get this item's integer value // Get this item's integer value
@ -281,6 +287,8 @@ bool MlValue::operator==(MlValue other) const {
// The values for quotes are stored in the // The values for quotes are stored in the
// first slot of the list member. // first slot of the list member.
return list[0] == other.list[0]; return list[0] == other.list[0];
case NIL:
return other.type == NIL;
default: default:
return true; return true;
} }
@ -516,6 +524,8 @@ std::string MlValue::get_type_name() {
return FUNCTION_TYPE; return FUNCTION_TYPE;
case UNIT: case UNIT:
return UNIT_TYPE; return UNIT_TYPE;
case NIL:
return NIL_TYPE;
default: default:
// We don't know the name of this type. // We don't know the name of this type.
// This isn't the users fault, this is just unhandled. // This isn't the users fault, this is just unhandled.
@ -553,6 +563,8 @@ std::string MlValue::display() const {
return "<" + str + " at " + to_string(long(stack_data.b)) + ">"; return "<" + str + " at " + to_string(long(stack_data.b)) + ">";
case UNIT: case UNIT:
return "@"; return "@";
case NIL:
return "nil";
default: default:
// We don't know how to display whatever type this is. // We don't know how to display whatever type this is.
// This isn't the users fault, this is just unhandled. // This isn't the users fault, this is just unhandled.
@ -594,6 +606,8 @@ std::string MlValue::debug() const {
return "<" + str + " at " + to_string(long(stack_data.b)) + ">"; return "<" + str + " at " + to_string(long(stack_data.b)) + ">";
case UNIT: case UNIT:
return "@"; return "@";
case NIL:
return "nil";
default: default:
// We don't know how to debug whatever type this is. // We don't know how to debug whatever type this is.
// This isn't the users fault, this is just unhandled. // This isn't the users fault, this is just unhandled.
@ -621,8 +635,7 @@ MlError::~MlError() {
} }
std::string MlError::description() { std::string MlError::description() {
return "error: the expression `" + cause->debug() + "` failed in scope " + to_string(env) + " with message \"" + return "error: the expression `" + cause->debug() + "` failed in scope " + to_string(env) + " with message \"" + msg + "\"";
msg + "\"";
} }
void MlEnvironment::combine(MlEnvironment const &other) { void MlEnvironment::combine(MlEnvironment const &other) {
@ -657,9 +670,7 @@ MlValue MlValue::apply(std::vector<MlValue> args, MlEnvironment &env) {
// Get the list of parameter atoms // Get the list of parameter atoms
params = list[0].list; params = list[0].list;
if (params.size() != args.size()) if (params.size() != args.size())
throw MlError(MlValue(args), env, args.size() > params.size() ? throw MlError(MlValue(args), env, args.size() > params.size() ? TOO_MANY_ARGS : TOO_FEW_ARGS);
TOO_MANY_ARGS : TOO_FEW_ARGS
);
// Get the captured scope from the lambda // Get the captured scope from the lambda
e = lambda_scope; e = lambda_scope;
@ -701,7 +712,7 @@ MlValue MlValue::eval(MlEnvironment &env) {
return env.get(str); return env.get(str);
case LIST: case LIST:
if (list.size() < 1) if (list.size() < 1)
throw MlError(*this, env, EVAL_EMPTY_LIST); return MlValue::nil();
args = std::vector<MlValue>(list.begin() + 1, list.end()); args = std::vector<MlValue>(list.begin() + 1, list.end());
@ -747,6 +758,7 @@ MlValue parse(std::string &s, int &ptr) {
if (s == "") { if (s == "") {
return MlValue(); return MlValue();
} else if (s[ptr] == '\'') { } else if (s[ptr] == '\'') {
// If this is a quote // If this is a quote
ptr++; ptr++;
@ -807,6 +819,7 @@ MlValue parse(std::string &s, int &ptr) {
} }
return MlValue::string(x); return MlValue::string(x);
} else if (s[ptr] == '@') { } else if (s[ptr] == '@') {
ptr++; ptr++;
skip_whitespace(s, ptr); skip_whitespace(s, ptr);
@ -822,7 +835,11 @@ MlValue parse(std::string &s, int &ptr) {
std::string x = s.substr(ptr, n); std::string x = s.substr(ptr, n);
ptr += n; ptr += n;
skip_whitespace(s, ptr); skip_whitespace(s, ptr);
return MlValue::atom(x); if (x == "nil")
return MlValue::nil();
else
return MlValue::atom(x);
} else { } else {
throw std::runtime_error(MALFORMED_PROGRAM); throw std::runtime_error(MALFORMED_PROGRAM);
} }
@ -1765,7 +1782,7 @@ int main(int argc, const char **argv) {
try { try {
load_std_lib(env); load_std_lib(env);
// for xcode profiling // for xcode profiling
// run(read_file_contents("/Users/vaclavt/Development/mlisp/tests/test.lsp"), env); run(read_file_contents("/Users/vaclavt/Development/mlisp/tests/test.lsp"), env);
if (argc == 1 || (argc == 2 && std::string(argv[1]) == "-i")) if (argc == 1 || (argc == 2 && std::string(argv[1]) == "-i"))
repl(env); repl(env);

6
ml.h
View File

@ -98,6 +98,9 @@ public:
// Construct a string // Construct a string
static MlValue string(const std::string &s); static MlValue string(const std::string &s);
// Construct a nil
static MlValue nil();
// Construct a lambda function // Construct a lambda function
MlValue(const std::vector<MlValue> &params, MlValue ret, MlEnvironment const &env); MlValue(const std::vector<MlValue> &params, MlValue ret, MlEnvironment const &env);
@ -197,7 +200,8 @@ private:
STRING, STRING,
LAMBDA, LAMBDA,
BUILTIN, BUILTIN,
UNIT UNIT,
NIL
} type; } type;
union { union {

View File

@ -69,6 +69,19 @@
0) 0)
)) ))
(defun make-list-of (size val)
(do
(define lst '())
(define i 0)
(while (< i size)
(define lst (push lst val))
(define i (inc i)))
lst
))
(defun make-list (size)
(make-list-of size nil))
; quicksort ; quicksort
(defun quick-sort-by (l cmp) (defun quick-sort-by (l cmp)

View File

@ -14,6 +14,9 @@
(print "(member '(1 2 3) 3:" (member '(1 2 3) 3)) (print "(member '(1 2 3) 3:" (member '(1 2 3) 3))
(print "(member '(1 2 3) 30:" (member '(1 2 3) 30)) (print "(member '(1 2 3) 30:" (member '(1 2 3) 30))
(print "(make-list 3) :" (make-list 3))
(print "(make-list-of 3) :" (make-list-of 3 999))
(defun fact (n) (defun fact (n)
(if (<= n 1) (if (<= n 1)
@ -45,7 +48,7 @@
(print "sorted: " (quick-sort '(1 2 3 4 5 6 7 8 9 10))) (print "sorted: " (quick-sort '(1 2 3 4 5 6 7 8 9 10)))
(print "sorted by: " (quick-sort-by '(10 9 8 7 6 5 4 3 2 1) (lambda (a b) (> a b)) )) (print "sorted by: " (quick-sort-by '(10 9 8 7 6 5 4 3 2 1) (lambda (a b) (> a b)) ))
(print "sorted by: " (quick-sort-by '(1 2 3 4 5 6 7 8 9 10) (lambda (a b) (> a b)) )) (print "sorted by: " (quick-sort-by '(1 2 3 4 5 6 7 8 9 10) (lambda (a b) (> a b)) ))
(print "sorted by: " (quick-sort-by '(1 2 3 4 5 6 7 8 9 10) (lambda (a b) (< a b)) )) (print "sorted by desc: " (quick-sort-by '(1 2 3 4 5 6 7 8 9 10) (lambda (a b) (< a b)) ))