From a87964f552520ba4f488a7f02455c94c45311038 Mon Sep 17 00:00:00 2001 From: VaclavT Date: Sun, 21 Feb 2021 14:03:14 +0100 Subject: [PATCH] regexp-search added, std lib loader changes, more REadme items --- .gitignore | 1 + Readme.md | 6 +++++- debug.lisp | 39 ++++++++++----------------------------- ml.cpp | 30 +++++++++++++++++++++++------- ml_string.cpp | 18 ++++++++++++++++++ ml_string.h | 4 +++- tests/test.lisp | 7 +++++-- tmp/divi-dates.lsp | 32 ++++++++++++++++++++++++++++++++ 8 files changed, 97 insertions(+), 40 deletions(-) create mode 100644 tmp/divi-dates.lsp diff --git a/.gitignore b/.gitignore index 1813863..ff9804d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ build .idea ml .DS_Store +CMakeFiles diff --git a/Readme.md b/Readme.md index e688eaf..2bf7a39 100644 --- a/Readme.md +++ b/Readme.md @@ -1,5 +1,6 @@ ### TODO +- make-list - print-table - download 1 year of data from api.nasdaq.com into test dir - support for including lisp libs at startup from dir @@ -14,7 +15,6 @@ - add instrumentation (time, nr of evals, debug info, debug environment etc) - in casting functions (as_string..) better exception description - add better print (syntax high-lighting) -- format (printf) - add comman line options -h -v - readline - execute system command should capture stderr @@ -32,6 +32,10 @@ - conversion functions like parse-integer - list function nth - in test.lisp some explaining prints +- format (printf) +- setq +- mapcar (funcall, apply) +- if then else, else part is optionw, allow then clause #### Performance - push_back - repeatedly without reserving size diff --git a/debug.lisp b/debug.lisp index fde17ef..11512df 100644 --- a/debug.lisp +++ b/debug.lisp @@ -2,36 +2,17 @@ ; (print (make-csv '(("r1c1" "r1c2") ("r2c1" "r2c2")))) -(defun divi-dates (date-str) - (do - (define curl_cmd (+ "curl -H \"Accept: application/json, text/plain, */*\" -H \"Origin: https://www.nasdaq.com/\" -H \"User-Agent: Mozilla/5.0 (Windows NT 10.0)\" https://api.nasdaq.com/api/calendar/dividends/?date=" date-str " 2>/dev/null")) - (define curl_out (system-cmd curl_cmd)) +(define path '("/usr/local/var/mlisp")) - (define json_list (parse-json (last curl_out))) - - (define data (first json_list)) - (define calendar (index data 1)) - (define calendar_data (index (index calendar 0) 1)) - (define header (index (index calendar_data 0) 1)) - (define rows (index (index calendar_data 1) 1)) - - (define csv_list '()) - (for e rows - ; (("announcement_Date" "01/07/2021") ("companyName" "Itau Unibanco Banco Holding SA") ("dividend_Ex_Date" "02/01/2021") ("dividend_Rate" 0.003) ("indicated_Annual_Dividend" 0.033) ("payment_Date" "03/11/2021") ("record_Date" "02/02/2021") ("symbol" "ITUB")) - (define symbol (second (first (filter (lambda (x) (= (first x) "symbol")) e)))) - (define divrate (second (first (filter (lambda (x) (= (first x) "dividend_Rate")) e)))) - (define adate (second (first (filter (lambda (x) (= (first x) "announcement_Date")) e)))) - (define name (second (first (filter (lambda (x) (= (first x) "companyName")) e)))) - (define edate (second (first (filter (lambda (x) (= (first x) "dividend_Ex_Date")) e)))) - (define pdate (second (first (filter (lambda (x) (= (first x) "payment_Date")) e)))) - (define rdate (second (first (filter (lambda (x) (= (first x) "record_Date")) e)))) - - (define csv_list (push csv_list (list symbol edate pdate divrate)))) - csv_list - )) - - -(print (make-csv (divi-dates "2021-02-01"))) +(for d path + (if (is-dir? d) + (for f (ls-dir d) + (if (regex-search? f "^.*\.l(i)?sp$") + (include (+ d "/" f)) + '()) + ) + ())) +(print (regex-search? "test.lsp" "^.*\.l(i)?sp$")) (print "Debug ends") diff --git a/ml.cpp b/ml.cpp index bbb6c33..87a24c3 100644 --- a/ml.cpp +++ b/ml.cpp @@ -889,6 +889,7 @@ namespace builtin { MlValue if_then_else(std::vector args, MlEnvironment &env) { if (args.size() != 3) throw MlError(MlValue("if", if_then_else), env, args.size() > 3 ? TOO_MANY_ARGS : TOO_FEW_ARGS); + if (args[0].eval(env).as_bool()) return args[1].eval(env); else return args[2].eval(env); @@ -1487,6 +1488,15 @@ namespace builtin { return MlValue::string(src); } + MlValue regex_search(std::vector args, MlEnvironment &env) { + eval_args(args, env); + + if (args.size() != 2) // if (args.size() < 2 || args.size() > 3) + throw MlError(MlValue("regex_search", regex_search), env, args.size() > 3 ? TOO_MANY_ARGS : TOO_FEW_ARGS); + + return MlValue(regexp_search(args[0].as_string(), args[1].as_string())); + } + MlValue display(std::vector args, MlEnvironment &env) { eval_args(args, env); @@ -1597,14 +1607,19 @@ void repl(MlEnvironment &env) { } } -// load lisp std library void load_std_lib(MlEnvironment &env) { - // TODO iterate through dir with files - std::string filename = "stdlib/stdlib.lisp"; + std::string loader = R"( (define ___lib_path '("/usr/local/var/mlisp")) + (for d ___lib_path + (if (is-dir? d) + (for f (ls-dir d) + (if (regex-search? f "^.*\.l(i)?sp$") + (include (+ d "/" f)) + '()) + ) + '())) + )"; - MlEnvironment e; - MlValue result = run(read_file_contents(filename), e); - env.combine(e); + run(loader, env); } // Does this environment, or its parent environment, have a variable? @@ -1700,8 +1715,9 @@ MlValue MlEnvironment::get(const std::string &name) const { // String operations if (name == "debug") return MlValue("debug", builtin::debug); - if (name == "replace") return MlValue("replace", builtin::replace); if (name == "display") return MlValue("display", builtin::display); + if (name == "replace") return MlValue("replace", builtin::replace); + if (name == "regex-search?") return MlValue("regex-search?", builtin::regex_search); // Casting operations if (name == "int") return MlValue("int", builtin::cast_to_int); diff --git a/ml_string.cpp b/ml_string.cpp index 118ef63..9bf542e 100644 --- a/ml_string.cpp +++ b/ml_string.cpp @@ -12,3 +12,21 @@ void replace_substring(std::string &src, const std::string &substr, const std::s } } + +// Returns true if where contains regex +bool regexp_search(const std::string &where, const std::string ®ex_str) { + // online tester https://www.regextester.com/97722 + std::regex regex(regex_str); + std::smatch match; + + if(std::regex_search(where, match, regex)) { + // std::cout << "matches for '" << where << "'\n"; + // std::cout << "Prefix: '" << match.prefix() << "'\n"; + // for (size_t i = 0; i < match.size(); ++i) + // std::cout << i << ": " << match[i] << '\n'; + // std::cout << "Suffix: '" << match.suffix() << "\'\n\n"; + + return true; + } + return false; +} diff --git a/ml_string.h b/ml_string.h index 20e5249..ce2ea70 100644 --- a/ml_string.h +++ b/ml_string.h @@ -4,9 +4,11 @@ #include "ml.h" #include +#include // Replace a substring with a replacement string in a source string void replace_substring(std::string &src, const std::string &substr, const std::string &replacement); - +// Returns true if where contains regex +bool regexp_search(const std::string &where, const std::string ®ex_str); diff --git a/tests/test.lisp b/tests/test.lisp index b7ac53f..481e0f7 100644 --- a/tests/test.lisp +++ b/tests/test.lisp @@ -14,11 +14,11 @@ (defun scitej (n) (if (<= n 1) 1 - (+ n (scitej - (- n 1))) + (+ n (scitej (- n 1))) )) (print (scitej 4000)) +; (print (scitej 5)) @@ -97,4 +97,7 @@ (print (str-to-date "01.01.1970" "%d.%m.%Y")) (print (date-add (str-to-date "01.01.1970" "%d.%m.%Y") 1 "day")) +(print (regex-search? "test.lsp" "^.*\.l(i)?sp$")) + + (print "Test ends") \ No newline at end of file diff --git a/tmp/divi-dates.lsp b/tmp/divi-dates.lsp new file mode 100644 index 0000000..2321e9e --- /dev/null +++ b/tmp/divi-dates.lsp @@ -0,0 +1,32 @@ + +(defun divi-dates (date-str) + (do + (define curl_cmd (+ "curl -H \"Accept: application/json, text/plain, */*\" -H \"Origin: https://www.nasdaq.com/\" -H \"User-Agent: Mozilla/5.0 (Windows NT 10.0)\" https://api.nasdaq.com/api/calendar/dividends/?date=" date-str " 2>/dev/null")) + (define curl_out (system-cmd curl_cmd)) + + (define json_list (parse-json (last curl_out))) + + (define data (first json_list)) + (define calendar (index data 1)) + (define calendar_data (index (index calendar 0) 1)) + (define header (index (index calendar_data 0) 1)) + (define rows (index (index calendar_data 1) 1)) + + ; (define csv_list '()) + (define csv_list '("symbol" "ex-date" "pay-date" "div-rate")) + (for e rows + ; (("announcement_Date" "01/07/2021") ("companyName" "Itau Unibanco Banco Holding SA") ("dividend_Ex_Date" "02/01/2021") ("dividend_Rate" 0.003) ("indicated_Annual_Dividend" 0.033) ("payment_Date" "03/11/2021") ("record_Date" "02/02/2021") ("symbol" "ITUB")) + (define symbol (second (first (filter (lambda (x) (= (first x) "symbol")) e)))) + (define divrate (second (first (filter (lambda (x) (= (first x) "dividend_Rate")) e)))) + (define adate (second (first (filter (lambda (x) (= (first x) "announcement_Date")) e)))) + (define name (second (first (filter (lambda (x) (= (first x) "companyName")) e)))) + (define exdate (second (first (filter (lambda (x) (= (first x) "dividend_Ex_Date")) e)))) + (define paydate (second (first (filter (lambda (x) (= (first x) "payment_Date")) e)))) + (define rdate (second (first (filter (lambda (x) (= (first x) "record_Date")) e)))) + + (define csv_list (push csv_list (list symbol exdate paydate divrate)))) + csv_list + )) + + +(print (make-csv (divi-dates "2021-02-01")))