cond implemented
special form, not as a macro
This commit is contained in:
36
ml.cpp
36
ml.cpp
@@ -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
|
||||
@@ -376,13 +379,13 @@ MlValue MlValue::operator+(const MlValue &other) const {
|
||||
// before continuing with the addition.
|
||||
if (other.type == FLOAT)
|
||||
return MlValue(cast_to_float() + other.stack_data.f);
|
||||
// Otherwise, do integer addition.
|
||||
// Otherwise, do integer addition.
|
||||
else return MlValue(stack_data.i + other.stack_data.i);
|
||||
case STRING:
|
||||
// If the other value is also a string, do the concat
|
||||
if (other.type == STRING)
|
||||
return MlValue::string(str + other.str);
|
||||
// We throw an error if we try to concat anything of non-string type
|
||||
// We throw an error if we try to concat anything of non-string type
|
||||
else throw MlError(*this, MlEnvironment(), INVALID_BIN_OP);
|
||||
case LIST:
|
||||
// If the other value is also a list, do the concat
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user