## Command line options
|option|Description|
|:-|-|
|-h|Prints help|
|-b|Skips loadin of std lib|
|-c code|Runs given code|
|-f source_file ..|Executes code in files|
|-i|Runs REPL|
|-p|Prints profile info at the end|
|-v|Prints version string|


## REPL commands
|Command|Description|
|:-|-|
|!q, !quit|Quit REPL|
|!e, !env|Display environment|
|!x, !export|Exports command from this session. Asks for filename to save|


## Syntax and Special Forms
|Special Form|Argument Evaluations|Purpose|
|:-|-|-|
|`(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.|
|`(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.|
|`(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.|
|`(defun name params body)`|`defun` evaluates none of its arguments.|This special form allows the user to conveniently define functions.|
|`(define name value)`|`define` evaluates the `value` argument, which is then assigned to `name` in the current scope.|This special form allows the user to bind atoms to values in a scope.|
|`(lambda params body)`|`lambda` evaluates none of its arguments.|This special form allows the user to define anonymous functions.|
|`(quote x)`|`quote` evaluates none of its arguments.|This is equivalent to the `'expr` syntactic sugar.|
|`(for x list ...)`|`for` evaluates only its list argument.|`for` iterates through the list storing each element in `x`, and then evaluating all of the rest of the values in the `for` body. It then returns the last value evaluated.|
|`(while cond ...)`|`while` evaluates only its cond argument.|`while` evaluates its condition expression every iteration before running. If it is true, it continues to evaluate every expression in the `while` body. It then returns the last value evaluated.|
|`(and ...)`|`and` evaluates logical and on its list argument.|`and` evaluates only until its true, it stops when becomes false.
|`(or ...)`|`or` evaluates logical or on its list argument.|`or` evaluates while its false, it stops when becomes true.|
|`(benchmark msg_string ...)`|`benchmark` 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 and prints msg_string and timing info.||

## Library
|Signature|Description|Return values|
|:-|-|-|
|`(= a b)`|Test whether two values are equal|`1` when equal otherwise `nil`|
|`(!= a b)`|Test whether two values are not equal|`1` when not equal otherwise `nil`|
|`(> a b)`|Test whether one value is greater to another |`1` when greater otherwise `nil`|
|`(< a b)`|Test whether one value is less to another |`1` when less otherwise `nil`|
|`(>= a b)`|Test whether one value is greater or equal to another |`1` when greater or equal otherwise `nil`|
|`(<= a b)`|Test whether one value is less or equal to another |`1` when less or equal otherwise `nil`|
|`(+ a b ..)`|Sum multiple values |sum of values|
|`(- a b)`|Substract two values |result of substraction|
|`(* a b ..)`|Multiply several values|result of multiplication|
|`(/ a b)`|Divide two values|result of division|
|`(% a b)`|Remainder of division|result of operation|
|`(list ..)`|Create a list of values||
|`(insert list index element)`|Insert an element into a list. Indexed from 0|new list with value inserted|
|`(index list index)`|Return element at index in list|Element at index|
|`(remove list index)`|Remove a value at an index from a list|List with element removed|
|`(len list)`|Get the length of a list|list length|
|`(push list element)`|Add an item to the end of a list|new list with element added|
|`(pop list)`|Returns last element of list|Last element|
|`(head list)`|Returns first element of a list|First element|
|`(tail list)`|Return all elements of list except first one|List without first element|
|`(first list)`|Returns first element of a list|First element|
|`(last list)`|Returns last element of list|Last element|
|`(range low high)`|Returns list with elements in range low .. high|`(range 1 5) => (1 2 3 4)`|
|`(member list item)`|Returns true (1) when list contains item||
|`(uniq list)`|Returns list with removed duplicates ||
|`(make-list len)`|Return list with len nil elements|`(make-list 3) => (nil nil nil)`|
|`(make-list-of len value)`|Return list with len value elements||
|`(map ..)`||`(map (lambda (x) (+ x 10)) '(1 2 3 4 5 6)) => (11 12 13 14 15 16)`|
|`(filter lambda list)`||`(filter (lambda (x) (> x 2)) '(1 2 3 4 5)) => (3 4 5)`|
|`(reduce lambda acumulator list)`||`>>> (reduce (lambda (x y) (+ (* x 10) y)) 0 '(1 2 3 4)) => 1234`|
|`(exit code)`|Exit the program with an integer code||
|`(quit code)`|Same as (exit ..)||
|`(print ..)`|Print several values and return the last one||
|`(input [prompt])`|Get user input with an optional prompt||
|`(random low high)`|Get a random number between two numbers inclusively||
|`(include file)`|Read a file and execute its code||
|`(read-file filename)`|Get the contents of a file||
|`(read-file-lines filename lambda)`|Reads file and for each line call lambda with passing the line as a parameter|`(read-file-lines "/tmp/f.txt" (lambda (ln) (print ln))`|
|`(write-file filename content-str)`|Write a string to a file||
|`(read-url url [headers])`|Reads URL|Returns list (status-code content)|
|`(system-cmd command_str)`|Execute system command||
|`(ls-dir dir)`|List a dir|List of directory entries|
|`(is-file? filename)`|Returns true if passed filename is a file||
|`(is-dir? filename)`|Returns true if passed filename is a directory||
|`(parse-csv string)`|Parse CSV string||
|`(parse-json json_string)`|Parse JSON string||
|`(save-csv ..)`|||
|`(get-universal-time)`|Get current time as secs from epoch||
|`(date-to-str date format)`|Converts date to formated string. Format is strftime format (https://www.tutorialspoint.com/c_standard_library/c_function_strftime.htm)|`>>> (date-to-str (get-universal-time) "%Y-%m-%d %H:%M:%S")
 => "2021-03-13 19:53:01"`|
|`(str-to-date string format)`|Converst string to time of secs since epoch. |`>>> (str-to-date "2021-03-13 19:53:01" "%Y-%m-%d %H:%M:%S") => 1615665181`|
|`(date-add date amount unit)`|Add number of units to date. A unit is one of 'year', 'month', 'day', 'hour', 'minute' or 'second'|`>>> (date-to-str (date-add (str-to-date "2021-03-13 19:53:01" "%Y-%m-%d %H:%M:%S") 10 "day") "%Y-%m-%d %H:%M:%S") => "2021-03-23 20:53:01"`|
|`start-of-day datetime`||`>>> (start-of-day (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S")) => 1620864000`|
|`end-of-day datetime`||`>>> (end-of-day (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S")) => 1620950399`|
|`start-of-month datetime`||`>>> (start-of-month (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S")) => 1619827200`|
|`start-of-next-month datetime`||`>>> (end-of-month (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S")) => 1622505599`|
|`end-of-next-month datetime`||`>>> (start-of-next-month (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S")) => 1622505600`|
|`end-of-month datetime`||`>>> (end-of-next-month (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S")) => 1625097599`|
|`start-of-prev-month datetime`||`>>> (start-of-prev-month (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S")) => 1617235200`|
|`end-of-prev-month datetime`||`>>> (end-of-prev-month (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S")) => 1619827199`|
|`start-of-year datetime`||`>>> (start-of-year (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S")) => 1609459200`|
|`end-of-year datetime`||`>>> (end-of-year (str-to-date "2021-05-13 10:32:12" "%Y-%m-%d %H:%M:%S")) => 1640995199`|
|`(debug ..)`|||
|`(display ..)`|||
|`(string-replace source substr replacement)`|Replace a substring with a replacement string in a source string|`>>> (string-replace "abcdefg" "de" "DE") => "abcDEfg"`|
|`(string-regex? where regex)`| Returns true if where contains regex|`>>> (string-regex? "aba123cdefg" "[0-9]+") => 1`|
|`(string-pad str len char rpad_lpad)`|||
|`(string-lpad str len char)`|Pad string from start with char to length len|`>>> (string-lpad "0" 10 "x")  => "xxxxxxxxx0"`|
|`(string-rpad str len char)`|Pad string from righ with char to length len|`>>> (string-rpad "0" 10 "x")  => "0xxxxxxxxx"`|
|`(string-split str separator)`|Splits string into list by regexp|`>>> (string-split "split me by space" "\s+") => ("split" "me" "by" "space")`|
`(string-rltrim str len RKRRKR)`| ||
`(string-ltrim str)`|Removes  " \n\r\t" from the begininfg of str||
`(string-rtrim str)`|Removes  " \n\r\t" from the end of str||
`(string-trim str)`|Removes  " \n\r\t" from the both strart and end of str||
`(string-case str RKRRKR)`|||
`(string-upcase str)`|Returns up cased string|`>>> (string-upcase "abcdefghchijklmn")  => "ABCDEFGHCHIJKLMN"`|
`(string-downcase str)`|Returns down cased string |`>>> (string-downcase "ABCDefghchijklmn") => "abcdefghchijklmn"`|
`(string-join lst sep)`|Returns string created as elements of concatenation of lst elements separated by sep|`>>> (string-join ("A" "B" "C" "D") ",") => "A,B,C,D"`|
`(string-len str)`|Returns string length|`>>> (string-len "abcdef") => 6`|
`(string-substr str pos len`|Returns substring from str starting at pos with len. If pos is negative returns substring from the end of string|`>>> (string-substr "ABCD" -2 2) => "CD"`|
`(string-find str lookup pos`|Returns position of lookup in str starting on position. First char index is 0. If not found returns nil|`>>> (string-find " long long int;" "long" 2) => 6`|
|`(int value)`|Cast an item to an int|`>>> (int 3.41) => 3`|
|`(float value)`|Cast item to a float|`>>> (int 3.41) => 3.14`|
|`(string value)`|Cast int or float item to a string|`>>> (string 3.14) => "3.14"`|
|`(eval <exp>)`|Eval returns the value of the second evaluation|`>>> (eval '(+ 1 2)) => 3`|
|`(type e)`|Returns data type of e|`>>> (type (+ 1 2)) => "int"`|
|`(parse ..)`||`>>> (eval (first (parse "(+ 1 2)"))) => 3`|
|`(make-list-of size value)`|Makes list with size elements of values|`>>> (make-list-of 5 0) => (0 0 0 0 0)`|
|`(make-list size)`|Makes list of nil values with size length|`>>> (make-list 5) => (nil nil nil nil nil)`|
|`(empty-list? lst)`|Return true is lst is list with zero elements|`>>> (empty-list? '()) => 1`|
|`(memeber lst item)`|Returns 1 when item is inluded in lst otherwise 0||
|`(uniq list)`|Filter out any duplicates from list|`>>> (uniq '(1 2 2 3 4 5 2 2)) => (1 2 3 4 5)`|
|`(flatten list)`||`>>> (flatten '(1 (2 2) 3)) => (1 2 2 3)`|
|`(quick-sort-by list cmp)`|||
|`(quick-sort list)`|return sorted list|`>>> (quick-sort '(2 4 6 1 7 3 3 9 5)) => (1 2 3 3 4 5 6 7 9)`|
|`(quick-sort-reverse list)`|return reverse sorted list|`>>> (quick-sort-reverse '(2 4 6 1 7 3 3 9 5)) => (9 7 6 5 4 3 3 2 1)`|
|`(not c)`|Logical NOT of c|`>>> (not 1) => nil`|
|`(neg n)`|Negates number|`>>> (neg -5) => 5`|
|`(is-pos? n)`|Returns true if n is positive number||
|`(is-neg? n)`|Returns true if n is negative number||
|`(dec n)`|Return n decremented by 1|`>>> (dec 5) => 4`|
|`(inc n)`|Return n incremented by 1|`>>> (inc 5) => 6`|
|`(sleep time)`|Pauses execution for time interval of seconds||
|`(get-env var)`|Return environment variable var|`>>> (get-env "HOME") => "/Users/vaclavt"`|
|`(second list)`|Returns second element of list|`>>> (second '(1 2 3 4 5 6 7)) => 2`|
|`(third list)`|Returns third element of list|`>>> (third '(1 2 3 4 5 6 7)) => 3`|
|`(fourth list)`|Returns fourth element of list|`>>> (fourth '(1 2 3 4 5 6 7)) => 4`|
|`(fifth list)`|Returns fifth element of list|`>>> (fifth '(1 2 3 4 5 6 7)) => 5`|
|`(nth i list)`|Return i-th elemenet of list. First element has index 1|`>>> (nth 7 '(1 2 3 4 5 6 7)) => 7`|
|`( make-csv list)`|creates csv string from list of lists|(print (make-csv '(("r1c1" "r1c2") ("r2c1" "r2c2"))))
|`(sprintf ..)`||`>>>  (sprintf "%s, %d, %.2f" (list "string" 1000 3.14)) => "string, 1000, 3.14"`|
|`(thread-create code..)`|Creates new thread, starts evalueating code and returns immediatelly thread id||
|`(thread-under-lock lockname code)`|Acquire lock with lockname and eval code. ilock currently is only allowd lockname||
|`(thread-sleep milisecons)`|Sleeps thread for given amount of miliseconds||
|`(threads-join)`|Wait for all running threads to finish||
|`(try block catch_block [finally_block])`|Evaluates block and if an exception is thrown, evaluates catch_block.Eventually in both cases evals finally_block. Return evaluated last expression from block if no exception or last expression from catch_block, if exception is thrown from block. Variable ml-exception in catch block is available with astring describing exception||
|`(throw-exception exp_desc)`|Throws an exception with exp_desc describing what happened ||
|`(xx ..)`|||
