#include "Debug.h"
+#include "Environment.h"
#include "Types.h"
#include <algorithm>
#include <typeinfo>
namespace mal {
+ malValuePtr builtin(const String& name, malBuiltIn::ApplyFunc handler) {
+ return malValuePtr(new malBuiltIn(name, handler));
+ };
+
malValuePtr falseValue() {
static malValuePtr c(new malConstant("false"));
return malValuePtr(c);
};
- malValuePtr hash(malValueVec* items) {
- return malValuePtr(new malHash(items));
- };
+ malValuePtr hash(malValueIter argsBegin, malValueIter argsEnd) {
+ return malValuePtr(new malHash(argsBegin, argsEnd));
+ }
malValuePtr integer(int value) {
return malValuePtr(new malInteger(value));
- }
+ };
malValuePtr integer(const String& token) {
return integer(std::stoi(token));
};
};
+malValuePtr malBuiltIn::apply(malValueIter argsBegin,
+ malValueIter argsEnd,
+ malEnv& env) const
+{
+ return m_handler(m_name, argsBegin, argsEnd, env);
+}
+
static String makeHashKey(malValuePtr key)
{
- if (malString* skey = dynamic_cast<malString*>(key.ptr())) {
+ if (const malString* skey = DYNAMIC_CAST(malString, key)) {
return skey->print(true);
}
- else if (malKeyword* kkey = dynamic_cast<malKeyword*>(key.ptr())) {
+ else if (const malKeyword* kkey = DYNAMIC_CAST(malKeyword, key)) {
return kkey->print(true);
}
ASSERT(false, "%s is not a string or keyword", key->print(true).c_str());
}
-static malHash::Map createMap(malValueVec* items)
+static malHash::Map addToMap(malHash::Map& map,
+ malValueIter argsBegin, malValueIter argsEnd)
{
- int itemCount = items->size();
- ASSERT(itemCount % 2 == 0, "hash-map requires an even-sized list");
-
- malHash::Map map;
- for (int i = 0; i < itemCount; i += 2) {
- map[makeHashKey(items->at(i))] = items->at(i+1);
+ // This is intended to be called with pre-evaluated arguments.
+ for (auto it = argsBegin; it != argsEnd; ++it) {
+ String key = makeHashKey(*it++);
+ map[key] = *it;
}
+
return map;
}
-malHash::malHash(malValueVec* items)
-: m_map(createMap(items))
+static malHash::Map createMap(malValueIter argsBegin, malValueIter argsEnd)
+{
+ ASSERT(std::distance(argsBegin, argsEnd) % 2 == 0,
+ "hash-map requires an even-sized list");
+
+ malHash::Map map;
+ return addToMap(map, argsBegin, argsEnd);
+}
+
+malHash::malHash(malValueIter argsBegin, malValueIter argsEnd)
+: m_map(createMap(argsBegin, argsEnd))
{
}
return s + "}";
}
+malValuePtr malList::eval(malEnv& env)
+{
+ if (count() == 0) {
+ return malValuePtr(this);
+ }
+
+ std::unique_ptr<malValueVec> items(evalItems(env));
+ auto it = items->begin();
+ malValuePtr op = *it;
+ return APPLY(op, ++it, items->end(), env);
+}
+
String malList::print(bool readably) const
{
return '(' + malSequence::print(readably) + ')';
}
+malValuePtr malValue::eval(malEnv& env)
+{
+ // Default case of eval is just to return the object itself.
+ return malValuePtr(this);
+}
+
malSequence::malSequence(malValueVec* items)
: m_items(items)
{
delete m_items;
}
+malValueVec* malSequence::evalItems(malEnv& env) const
+{
+ malValueVec* items = new malValueVec;;
+ items->reserve(count());
+ for (auto it = m_items->begin(), end = m_items->end(); it != end; ++it) {
+ items->push_back(EVAL(*it, env));
+ }
+ return items;
+}
+
String malSequence::print(bool readably) const
{
String str;
return readably ? escapedValue() : value();
}
+malValuePtr malSymbol::eval(malEnv& env)
+{
+ return env.get(value());
+}
+
+malValuePtr malVector::eval(malEnv& env)
+{
+ return mal::vector(evalItems(env));
+}
+
String malVector::print(bool readably) const
{
return '[' + malSequence::print(readably) + ']';