cond implemented

special form, not as a macro
This commit is contained in:
VaclavT 2021-10-03 13:18:27 +02:00
parent ed0667475c
commit 6ada537e47
4 changed files with 45 additions and 8 deletions

View File

@ -1,5 +1,14 @@
(defun a (aa) (print aa))
(a 1 2)
(define a 20)
(cond
((> a 30) (print "a > 30"))
((> a 20) (print "a > 20"))
(1 (print "a je" a)))
(define a 25)
(cond
((> a 30) (print "a > 30"))
((> a 20) (print "a > 20"))
(1 (print "a je" a)))
;; (define csv_date (str-to-date "01/01/2021" "%m/%d/%Y"))
;; (date-to-str 3141583200 "%m/%d/%Y")

32
ml.cpp
View File

@ -165,7 +165,6 @@ std::vector<std::string> MlValue::get_used_atoms() {
}
}
// Is this a builtin function?
bool MlValue::is_builtin() const {
return type == BUILTIN;
}
@ -178,6 +177,10 @@ bool MlValue::is_string() const {
return type == STRING;
}
bool MlValue::is_list() const {
return type == LIST;
}
// Get the "truthy" boolean value of this value.
bool MlValue::as_bool() const {
return type != NIL && *this != MlValue(0l); // TODO remove 0 as false
@ -921,6 +924,28 @@ MlValue if_then_else(std::vector<MlValue> args, MlEnvironment &env) {
return MlValue(0l);
}
// cond (SPECIAL FORM), in lisp it's macro, but we don't have support for macros yet
MlValue cond(std::vector<MlValue> args, MlEnvironment &env) {
if (args.size() < 2)
throw MlError(MlValue("cond", cond), env, TOO_FEW_ARGS);
MlValue acc;
for (auto &arg : args) {
if (!arg.is_list())
throw MlError(MlValue("cond", cond), env, INVALID_ARGUMENT);
std::vector<MlValue> list = arg.as_list();
if (list[0].eval(env).as_bool()) {
for (size_t i = 1; i < list.size(); i++)
acc = list[i].eval(env);
return acc;
}
}
return MlValue::nil();
}
// Define a variable with a value (SPECIAL FORM)
MlValue define(std::vector<MlValue> args, MlEnvironment &env) {
if (args.size() != 2)
@ -1934,8 +1959,10 @@ bool MlEnvironment::has(const std::string &name) const {
// Get the value associated with this name in this scope
MlValue MlEnvironment::get(const std::string &name) const {
// Special forms
if (name == "if") return MlValue("if", builtin::if_then_else);
if (name == "define") return MlValue("define", builtin::define);
if (name == "set!") return MlValue("set!", builtin::setx);
if (name == "if") return MlValue("if", builtin::if_then_else);
if (name == "cond") return MlValue("if", builtin::cond);
if (name == "do") return MlValue("do", builtin::do_block);
if (name == "for") return MlValue("for", builtin::for_loop);
if (name == "while") return MlValue("while", builtin::while_loop);
@ -1945,7 +1972,6 @@ MlValue MlEnvironment::get(const std::string &name) const {
if (name == "lambda") return MlValue("lambda", builtin::lambda);
if (name == "and") return MlValue("and", builtin::do_and);
if (name == "or") return MlValue("or", builtin::do_or);
if (name == "set!") return MlValue("set!", builtin::setx);
// Comparison operations
if (name == "=") return MlValue("=", builtin::eq);

2
ml.h
View File

@ -145,6 +145,8 @@ public:
bool is_string() const;
bool is_list() const;
// Get the boolean value of this value.
bool as_bool() const;

View File

@ -136,7 +136,7 @@
</dict>
<dict>
<key>match</key>
<string>(?<=\()(?i:\*|\*\*|\*\*\*|\+|\+\+|\+\+\+|\-|/|//|///|/=|1\+|1\-|<|<=|=|>|>=|if|do|for|while|scope|quote|defun|and|or|set!|eval|type|parse|list|insert|index|remove|len|push|pop|head|tail|first|last|range|map|filter|reduce|exit|quit|print|input|random|include|read-file|read-file-lines|write-file|read-url|system-cmd|ls-dir|is-file?|is-dir?|parse-csv|parse-json|get-universal-time|date-to-str|str-to-date|date-add|debug|sprintf|display|string-replace|string-regex?|string-split|string-pad|string-rltrim|string-case|string-len|string-substr|string-find|benchmark|thread-create|thread-under-lock|thread-sleep|threads-join|try|throw|usql|first|second|third|fourth|fifth|sixth|seventh|eight|nth|print|get-universal-time|not|is-pos?|is-neg?|neg|dec|inc|string-ltrim|string-rtrim|string-trim|string-rpad|string-lpad|string-upcase|string-downcase|string-join|itok|ktoi|sleep|get-env|member|make-list-of|make-list|empty-list?|uniq|flatten|quick-sort-by|quick-sort|quick-sort-reverse|start-of-day|end-of-day|start-of-month|start-of-next-month|end-of-next-month|end-of-month|start-of-prev-month|end-of-prev-month|start-of-year|end-of-year|make-csv)(?=\s+)</string>
<string>(?<=\()(?i:\*|\*\*|\*\*\*|\+|\+\+|\+\+\+|\-|/|//|///|/=|1\+|1\-|<|<=|=|>|>=|if|cond|do|for|while|scope|quote|defun|and|or|set!|eval|type|parse|list|insert|index|remove|len|push|pop|head|tail|first|last|range|map|filter|reduce|exit|quit|print|input|random|include|read-file|read-file-lines|write-file|read-url|system-cmd|ls-dir|is-file?|is-dir?|parse-csv|parse-json|get-universal-time|date-to-str|str-to-date|date-add|debug|sprintf|display|string-replace|string-regex?|string-split|string-pad|string-rltrim|string-case|string-len|string-substr|string-find|benchmark|thread-create|thread-under-lock|thread-sleep|threads-join|try|throw|usql|first|second|third|fourth|fifth|sixth|seventh|eight|nth|print|get-universal-time|not|is-pos?|is-neg?|neg|dec|inc|string-ltrim|string-rtrim|string-trim|string-rpad|string-lpad|string-upcase|string-downcase|string-join|itok|ktoi|sleep|get-env|member|make-list-of|make-list|empty-list?|uniq|flatten|quick-sort-by|quick-sort|quick-sort-reverse|start-of-day|end-of-day|start-of-month|start-of-next-month|end-of-next-month|end-of-month|start-of-prev-month|end-of-prev-month|start-of-year|end-of-year|make-csv)(?=\s+)</string>
<key>name</key>
<string>keyword.control.lisp</string>
</dict>