From 4c18b557a2e66995c752758e54afca5fff3debac Mon Sep 17 00:00:00 2001 From: Julian Thatcher Date: Tue, 20 Feb 2018 00:55:41 +1100 Subject: [PATCH] Version 0.86: Improved lists Also updates the stress_threads example based on performance issues. --- PocoLithp/PocoLithp.hpp | 2 +- PocoLithp/stdlib/ELlists.cpp | 42 ++++++++++++++++++++++++++++-------- README.md | 10 ++++++--- samples/stress_threads.lisp | 6 ++---- 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/PocoLithp/PocoLithp.hpp b/PocoLithp/PocoLithp.hpp index 5b742e2..61c8fa6 100644 --- a/PocoLithp/PocoLithp.hpp +++ b/PocoLithp/PocoLithp.hpp @@ -3,7 +3,7 @@ #include "stdafx.h" #include // Ugly hack -#define ELISP_VERSION "0.85" +#define ELISP_VERSION "0.86" // Undefine to use recursive emulator #define ELISP_STACKLESS diff --git a/PocoLithp/stdlib/ELlists.cpp b/PocoLithp/stdlib/ELlists.cpp index d5fed0d..ee58a89 100644 --- a/PocoLithp/stdlib/ELlists.cpp +++ b/PocoLithp/stdlib/ELlists.cpp @@ -9,30 +9,30 @@ using namespace PocoLithp::Stackless; LithpCell proc_empty(const LithpCells &c) { - if(c.size() == 0) return LithpCell(Var, 0); + if(c.empty()) return LithpCell(Var, 0); return c[0].empty() ? sym_true : sym_false; } LithpCell proc_length(const LithpCells &c) { - if(c.size() == 0) return LithpCell(Var, 0); + if(c.empty()) return LithpCell(Var, 0); return LithpCell(Var, c[0].size()); } LithpCell proc_nullp(const LithpCells &c) { - if(c.size() == 0) return sym_true; + if(c.empty()) return sym_true; return c[0].is_nullp() ? sym_true : sym_false; } LithpCell proc_head(const LithpCells &c) { - if(c.size() == 0) return sym_nil; - if(c[0].size() == 0) return sym_nil; + if(c.empty()) return sym_nil; + if(c[0].empty()) return sym_nil; return c[0][0]; } LithpCell proc_tail(const LithpCells &c) { - if (c.size() == 0) + if(c.empty()) return LithpCell(List, LithpCells()); LithpCells result = c[0].list(); - if(result.size() == 0) + if(result.empty()) return LithpCell(List, LithpCells()); result.erase(result.begin()); return LithpCell(List, result); @@ -40,7 +40,7 @@ LithpCell proc_tail(const LithpCells &c) LithpCell proc_append(const LithpCells &c) { - if (c.size() == 0) + if(c.empty()) return LithpCell(List, LithpCells()); else if(c.size() == 1) return LithpCell(List, c[0].list()); @@ -53,7 +53,7 @@ LithpCell proc_append(const LithpCells &c) LithpCell proc_cons(const LithpCells &c) { - if (c.size() == 0) + if(c.empty()) return LithpCell(List, LithpCells()); else if(c.size() == 1) return LithpCell(List, c[0].list()); @@ -70,6 +70,29 @@ LithpCell proc_list(const LithpCells &c) return LithpCell(List, c); } +/** Lists module native inbuilt functions (NIF) */ +namespace nif_lists { + /** + * Drop given Value from List. + * + * @param List list() + * @param Value any() + * @return list() + */ + LithpCell drop(const LithpCells &c) { + LithpCells result; + if(c.empty() || c.size() < 2) + return LithpCell(List, LithpCells()); + const LithpCells &list_from = c[0].list(); + const LithpCell &list_drop = c[1]; + for (LithpCells::const_iterator it = list_from.cbegin(); it != list_from.cend(); ++it) { + if(*it != list_drop) + result.push_back(*it); + } + return LithpCell(List, result); + } +} + void Elispidae::Stdlib::init_lists() { add_environment_runtime([](LithpEnvironment &env) { env["append"] = LithpCell(&proc_append); env["head"] = LithpCell(&proc_head); @@ -77,5 +100,6 @@ void Elispidae::Stdlib::init_lists() { env["length"] = LithpCell(&proc_length); env["list"] = LithpCell(&proc_list); env["null?"] = LithpCell(&proc_nullp); env["empty?"] = LithpCell(&proc_empty); + env["lists:drop"] = LithpCell(nif_lists::drop); }); } diff --git a/README.md b/README.md index a866b56..d7153a9 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,10 @@ Why? An attempt at a much more lightweight implementation of a C++ Lithp (other attempt [Stackful](https://github.com/andrakis/Stackful) being rather more complicated than desired.) +It aims to be reasonably fast even on slower processors - one of its intended targets is OpenRISC 1000, specifically the [JavaSript OpenRISC 1000 emulator](https://jor1k.com). Other interpreted languages are available on OpenRISC, but the performance of these languages tends to be very slow. + +It also aims to borrow several ideas from different programming languages, rather than trying to port them to OpenRISC. + What? ----- @@ -111,15 +115,15 @@ How? Status ------ -**Version: 0.85** +**Version: 0.86** **Language compatibility level:** Lisp-ish, with macros. Mainly Lisp-like syntax, mixed with Lithp (Variables are introduced, `#` is synonym for `lambda`). - Microthreading, message passing, and scheduling is working. + Microthreading, message passing, and scheduling is working. - Tail-call optimization is presently not working. + Tail-call optimization has once again been dropped. Frame optimizations are the future development target. Building ======== diff --git a/samples/stress_threads.lisp b/samples/stress_threads.lisp index 8333708..6d72147 100644 --- a/samples/stress_threads.lisp +++ b/samples/stress_threads.lisp @@ -7,7 +7,7 @@ ;; because it is a much slower platform. (define ThreadCount (if (== or1k (arch)) - 15 + 10 50 ) ) @@ -24,8 +24,6 @@ (# (Ele Acc) (if (Predicate Ele) (+ Acc (list Ele)) Acc))) )) - (define lists:drop (# (List Value) - (lists:filter List (# (Ele) (!= Ele Value))))) ;; Helper function to spawn many threads with given Code and Argument. ;; Returns list of thread references. @@ -58,7 +56,7 @@ (begin (define Thread (head ThreadsStarted)) (print "Requesting factorial " N "from" Thread) - (send (list N (self)) Thread) + (send (list (+ N 5) (self)) Thread) (message-loop (tail ThreadsStarted) (+ (list Thread) ThreadsRunning) (+ N 1)) ) ;; else, sent messages to all threads, get responses.