Merge branch 'master' of http://gitea.stocksriddle.one/vaclavt/mlisp
This commit is contained in:
commit
0dfc657f23
|
|
@ -6,3 +6,4 @@ ml
|
|||
CMakeFiles
|
||||
Testing
|
||||
.cache
|
||||
Makefile
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@ utils/local_install.sh
|
|||
|
||||
|
||||
### KNOWNN BUGS
|
||||
- in (include "file.lsp") are not available stdlib.lsp finctions like (string-trim ..) etc
|
||||
- (read-url "https://api.nasdaq.com/api/calendar/dividends/") ; hangs in sslclient.cpp line 132
|
||||
|
||||
### TODO
|
||||
|
|
@ -96,8 +95,6 @@ utils/local_install.sh
|
|||
- string functions
|
||||
- compare - needed for sorting, cmp ignore case
|
||||
- regexp match, regexp tokens
|
||||
- date support
|
||||
- decode-universal-time (http://www.lispworks.com/documentation/HyperSpec/Body/f_dec_un.htm)
|
||||
- env functions
|
||||
- get-env, set-env; set-env cannot be implemented in stdlib.lsp, because popen is in fact subshell
|
||||
- macros and then loop, let etc
|
||||
|
|
@ -115,4 +112,4 @@ https://github.com/antirez/linenoise
|
|||
|
||||
|
||||
#### read stdout and stderr from popen
|
||||
https://stackoverflow.com/questions/478898how-do-i-execute-a-command-and-get-the-output-of-the-command-within-c-using-po
|
||||
https://stackoverflow.com/questions/478898how-do-i-execute-a-command-and-get-the-output-of-the-command-within-c-using-po
|
||||
127
debug.lsp
127
debug.lsp
|
|
@ -1,17 +1,118 @@
|
|||
(include "/usr/local/var/mlisp/terminal.lsp")
|
||||
|
||||
(doc::man "string-regex-list")
|
||||
(doc::man "string-split")
|
||||
(doc::man "string-trim")
|
||||
; TODO better env formating
|
||||
; TODO time parse function
|
||||
|
||||
;; (defn concat-lists (seq1 seq2)
|
||||
;; (do (def l seq1)
|
||||
;; (dotimes i (len seq2)
|
||||
;; (set! l (push l (index seq2 i))))
|
||||
;; ))
|
||||
|
||||
;; (print (concat-lists '(1 2 3) '(4 5 6)))
|
||||
;; (1 2 3 4 5 6)
|
||||
(defn cron::sleep-to-next-minute ()
|
||||
(* 1000 (- 60 (int (date-to-str (get-universal-time) "%S")))))
|
||||
|
||||
|
||||
(defn cron::eval-time-spec (val time_spec)
|
||||
(do
|
||||
;(print "DEBUG" "cron::eval-time-spec" val time_spec)
|
||||
(def r
|
||||
(cond
|
||||
((nil? time_spec)
|
||||
#t) ; no time_spec -> it's true
|
||||
((= time_spec "*")
|
||||
#t)
|
||||
((string-regex? time_spec "^[0-9]{1,4}$")
|
||||
(= val (int time_spec)))
|
||||
((string-regex? time_spec "^[0-9]{1,2}-[0-9]{1,2}$")
|
||||
(def interval (string-split time_spec "-"))
|
||||
(and (>= val (int (first interval))) (<= val (int (second interval)))))
|
||||
(#t
|
||||
nil) ; TODO exception
|
||||
)
|
||||
)
|
||||
(print "val:" val "time_spec:" time_spec "result" r)
|
||||
r
|
||||
))
|
||||
|
||||
|
||||
(defn cron::add-job (name time_spec job)
|
||||
; TODO if already there replace it
|
||||
(set! cron::entries (push cron::entries (list name time_spec job)))
|
||||
)
|
||||
|
||||
|
||||
(defn cron::time-to-run (now time_spec)
|
||||
(do
|
||||
; second, minute, hour, day, month, year, day-of-the-week
|
||||
(def time (decode-universal-time (get-universal-time)))
|
||||
|
||||
(def time_minute (second time))
|
||||
(def time_hour (third time))
|
||||
(def time_day (fourth time))
|
||||
(def time_month (fifth time))
|
||||
(def time_year (sixth time))
|
||||
(def time_weekday (seventh time))
|
||||
|
||||
(def bool (cron::eval-time-spec time_minute (find-val-in-list time_spec "minute")))
|
||||
(set! bool (and bool (cron::eval-time-spec time_hour (find-val-in-list time_spec "hour"))))
|
||||
(set! bool (and bool (cron::eval-time-spec time_weekday (find-val-in-list time_spec "weekday"))))
|
||||
(set! bool (and bool (cron::eval-time-spec time_day (find-val-in-list time_spec "day"))))
|
||||
(set! bool (and bool (cron::eval-time-spec time_month (find-val-in-list time_spec "month"))))
|
||||
(set! bool (and bool (cron::eval-time-spec time_year (find-val-in-list time_spec "year"))))
|
||||
(print "time-to-run test" bool)
|
||||
bool
|
||||
))
|
||||
|
||||
|
||||
(defn cron::start ()
|
||||
(do
|
||||
(def wait_time (cron::sleep-to-next-minute))
|
||||
(print "cron daemon started, waiting" wait_time "miliseconds for first run")
|
||||
; (thread-sleep wait_time)
|
||||
(while (not cron::stop)
|
||||
(def now (get-universal-time))
|
||||
(for e cron::entries
|
||||
(def job_name (first e))
|
||||
(def time_spec (second e))
|
||||
|
||||
; (print "DEBUG" "checking" job_name "time_spec" time_spec)
|
||||
(if (cron::time-to-run now time_spec)
|
||||
(do
|
||||
;(print "running job:" job_name "code:" (third e))
|
||||
(thread-create (eval (third e)))
|
||||
)
|
||||
; (print "not running" job_name)
|
||||
)
|
||||
)
|
||||
|
||||
(thread-sleep (cron::sleep-to-next-minute))
|
||||
)
|
||||
(threads-join)
|
||||
))
|
||||
|
||||
|
||||
(defn cron::stop ()
|
||||
(set! cron::stop #t))
|
||||
|
||||
|
||||
(def cron::entries '()) ; must be here
|
||||
(def cron::stop nil) ; must be here
|
||||
|
||||
|
||||
|
||||
|
||||
(cron::add-job "every_min_print"
|
||||
'(("minute" "*"))
|
||||
'(print "code: every_min_print"))
|
||||
|
||||
(cron::add-job "every_min_between_00_and_05"
|
||||
'(("minute" "00-05"))
|
||||
'(print "code: every_min_between_00_and_05"))
|
||||
|
||||
(cron::add-job "13:20_working_day"
|
||||
'(("weekday" "1-5")("hour" "13")("minute" "20"))
|
||||
'(print "code: 13:20_working_day"))
|
||||
|
||||
(cron::add-job "15:20_working_day"
|
||||
'(("weekday" "1-5")("hour" "15")("minute" "20"))
|
||||
'(print "code: 15:20_working_day"))
|
||||
|
||||
|
||||
(cron::start)
|
||||
|
||||
; pridat example
|
||||
; >>> (doc::man "push")
|
||||
; (push list element) - Add an item to the end of a list
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
|Special Form|Argument Evaluations|Purpose|Section|
|
||||
|:-|-|-|-|
|
||||
|`(if cond a b)`|`if` only evaluates its `cond` argument. If `cond` is truthy (non-zero), then `a` is evaluated. Otherwise, `b` is evaluated.|This special form is the main method of control flow.|Language|
|
||||
|`(cond (test1 action1) (test2 action2) ... (testn actionn))`|The first clause whose test evaluates to non-nil is selected; all other clauses are ignored, and the consequents of the selected clause are evaluated in order. If none of the test conditions are evaluated to be true, then the cond statement returns nil.|This special form is method of control flow.|Language|
|
||||
|`(cond (test1 action1 ..) (test2 action2 ..) ... (testn ..))`|The first clause whose test evaluates to non-nil is selected; all other clauses are ignored, and the consequents of the selected clause are evaluated in order. If none of the test conditions are evaluated to be true, then the cond statement returns nil.|This special form is method of control flow.|Language|
|
||||
|`(do a b c ...)`|`do` takes a list of s-expressions and evaluates them in the order they were given (in the current scope), and then returns the result of the last s-expression.|This special form allows lambda functions to have multi-step bodies.|Language|
|
||||
|`(scope a b c ...)`|`scope` takes a list of s-expressions and evaluates them in the order they were given _in a new scope_, and then returns the result of the last s-expression.|This special form allows the user to evaluate blocks of code in new scopes.|Language|
|
||||
|`(defn name params body)`|`defn` evaluates none of its arguments.|This special form allows the user to conveniently define functions.|Language|
|
||||
|
|
@ -73,6 +73,7 @@
|
|||
|`(make-list-of size value)`|Makes list with size elements of values|`>>> (make-list-of 5 0) => (0 0 0 0 0)`|List manipulation|
|
||||
|`(concat-lists seq1 seq2)`|Appends all elements from seq2 to seq1|`>>> (concat-lists '(1 2 3) '(4 5 6)) => (1 2 3 4 5 6)`|List manipulation|
|
||||
|`(take lst size)`|Makes sublist of a lst with size length|`>>> (take '(1 2 3 4 5 6) 3) => (1 2 3)`|List manipulation|
|
||||
|`(find-val-in-list lst name)`|Returns tail od sublist which first element is name|`>>> (find-val-in-list '(("a" ("av" "avv")) ("b" "bv") (31 32 33) (41 42 43)) "b") => "bv" >>> `|List manipulation|
|
||||
|`(map ..)`|Returns list that is the result of executing lambda on its elements|`(map (lambda (x) (+ x 10)) '(1 2 3 4 5 6)) => (11 12 13 14 15 16)`|List manipulation|
|
||||
|`(filter lambda list)`|Returns list with elements for which passed lambda returns true|`(filter (lambda (x) (> x 2)) '(1 2 3 4 5)) => (3 4 5)`|List manipulation|
|
||||
|`(reduce lambda acumulator list)`|Reduces list|`>>> (reduce (lambda (x y) (+ (* x 10) y)) 0 '(1 2 3 4)) => 1234`|List manipulation|
|
||||
|
|
@ -111,6 +112,7 @@
|
|||
|`end-of-prev-month datetime`|Returns epoch time of end of previous month|`>>> (end-of-prev-month (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S")) => 1619827199`|Date and time|
|
||||
|`start-of-year datetime`|Returns epoch time of start of year|`>>> (start-of-year (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S")) => 1609459200`|Date and time|
|
||||
|`end-of-year datetime`|Returns epoch time of end of year|`>>> (end-of-year (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S")) => 1640995199`|Date and time|
|
||||
|`decode-universal-time time`|Returns the decoded time represented by the given universal time. Returns list with (second, minute, hour, day, month, year, day-of-the-week)|`>>> (decode-universal-time 0) => (0 0 0 1 1 1970 4)`|Date and time|
|
||||
|`(debug ..)`|TODO add me|TODO add me|IO|
|
||||
|`(display ..)`|Displays passed parameters|`>>> (display '(1 2 3)) => "(1 2 3)"`|IO|
|
||||
|`(string-replace source substr replacement)`|Replace a substring with a replacement string in a source string|`>>> (string-replace "abcdefg" "de" "DE") => "abcDEfg"`|String manipulation|
|
||||
|
|
|
|||
6
ml.cpp
6
ml.cpp
|
|
@ -1393,16 +1393,12 @@ MlValue tcp_client(std::vector<MlValue> args, MlEnvironment &env) {
|
|||
|
||||
// Read a file and execute its code
|
||||
MlValue include(std::vector<MlValue> args, MlEnvironment &env) {
|
||||
// Import is technically not a special form, it's more of a macro.
|
||||
// We can evaluate our arguments.
|
||||
eval_args(args, env);
|
||||
|
||||
if (args.size() != 1)
|
||||
throw MlError(MlValue("include", include), env, args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
||||
|
||||
MlEnvironment e;
|
||||
MlValue result = run(read_file_contents(args[0].as_string()), e);
|
||||
env.combine(e);
|
||||
MlValue result = run(read_file_contents(args[0].as_string()), env);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@
|
|||
(defn end-of-prev-month (datetime) (date-add (end-of-month datetime) -1 "month"))
|
||||
(defn start-of-year (datetime) (str-to-date (+ (date-to-str datetime "%Y") "-01-01 00:00:00") "%Y-%m-%d %H:%M:%S"))
|
||||
(defn end-of-year (datetime) (str-to-date (+ (date-to-str datetime "%Y") "-12-31 23:59:59") "%Y-%m-%d %H:%M:%S"))
|
||||
|
||||
(defn decode-universal-time (time) (map (lambda (x) (int x)) (string-split (date-to-str time "%S %M %H %d %m %Y %w") "\s+")))
|
||||
|
||||
; from list of lists creates csv string
|
||||
; (print (make-csv '(("r1c1" "r1c2") ("r2c1" "r2c2"))))
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@
|
|||
(ut::define-test "result of (end-of-prev-month)" '(ut::assert-equal 1619827199 (end-of-prev-month (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S"))))
|
||||
(ut::define-test "result of (start-of-year)" '(ut::assert-equal 1609459200 (start-of-year (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S"))))
|
||||
(ut::define-test "result of (end-of-year)" '(ut::assert-equal 1640995199 (end-of-year (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S"))))
|
||||
(ut::define-test "result of (decode-universal-time 0)" '(ut::assert-equal '(0 0 0 1 1 1970 4) (decode-universal-time 0)))
|
||||
|
||||
(ut::define-test "result of (read-file-lines \"/tmp/f.txt\" counter)" '(ut::assert-equal 3 (read-file-lines "/tmp/f.txt" counter)))
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue