1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-21 18:48:12 +03:00

Merge pull request #132 from sdt/native-swap

Native swap! implementation for cpp
This commit is contained in:
Joel Martin 2015-12-18 12:00:45 -06:00
commit 93cba02fb9
14 changed files with 101 additions and 71 deletions

View File

@ -33,7 +33,7 @@ static StaticList<malBuiltIn*> handlers;
static StaticList<malBuiltIn*>::Node HRECNAME(uniq) \
(handlers, new malBuiltIn(symbol, FUNCNAME(uniq))); \
malValuePtr FUNCNAME(uniq)(const String& name, \
malValueIter argsBegin, malValueIter argsEnd, malEnvPtr env)
malValueIter argsBegin, malValueIter argsEnd)
#define BUILTIN(symbol) BUILTIN_DEF(__LINE__, symbol)
@ -121,7 +121,7 @@ BUILTIN("apply")
args.push_back(lastArg->item(i));
}
return APPLY(op, args.begin(), args.end(), env->getRoot());
return APPLY(op, args.begin(), args.end());
}
BUILTIN("assoc")
@ -227,7 +227,7 @@ BUILTIN("empty?")
BUILTIN("eval")
{
CHECK_ARGS_IS(1);
return EVAL(*argsBegin, env->getRoot());
return EVAL(*argsBegin, NULL);
}
BUILTIN("first")
@ -357,6 +357,21 @@ BUILTIN("str")
return mal::string(printValues(argsBegin, argsEnd, "", false));
}
BUILTIN("swap!")
{
CHECK_ARGS_AT_LEAST(2);
ARG(malAtom, atom);
malValuePtr op = *argsBegin++; // this gets checked in APPLY
malValueVec args(1 + argsEnd - argsBegin);
args[0] = atom->deref();
std::copy(argsBegin, argsEnd, args.begin() + 1);
malValuePtr value = APPLY(op, args.begin(), args.end());
return atom->reset(value);
}
BUILTIN("symbol")
{
CHECK_ARGS_IS(1);

View File

@ -18,8 +18,7 @@ typedef RefCountedPtr<malEnv> malEnvPtr;
// step*.cpp
extern malValuePtr APPLY(malValuePtr op,
malValueIter argsBegin, malValueIter argsEnd,
malEnvPtr env);
malValueIter argsBegin, malValueIter argsEnd);
extern malValuePtr EVAL(malValuePtr ast, malEnvPtr env);
extern malValuePtr readline(const String& prompt);
extern String rep(const String& input, malEnvPtr env);

View File

@ -112,10 +112,9 @@ namespace mal {
};
malValuePtr malBuiltIn::apply(malValueIter argsBegin,
malValueIter argsEnd,
malEnvPtr env) const
malValueIter argsEnd) const
{
return m_handler(m_name, argsBegin, argsEnd, env);
return m_handler(m_name, argsBegin, argsEnd);
}
static String makeHashKey(malValuePtr key)
@ -302,8 +301,7 @@ malLambda::malLambda(const malLambda& that, bool isMacro)
}
malValuePtr malLambda::apply(malValueIter argsBegin,
malValueIter argsEnd,
malEnvPtr) const
malValueIter argsEnd) const
{
return EVAL(m_body, makeEnv(argsBegin, argsEnd));
}
@ -342,7 +340,7 @@ malValuePtr malList::eval(malEnvPtr env)
std::unique_ptr<malValueVec> items(evalItems(env));
auto it = items->begin();
malValuePtr op = *it;
return APPLY(op, ++it, items->end(), env);
return APPLY(op, ++it, items->end());
}
String malList::print(bool readably) const

View File

@ -227,8 +227,7 @@ public:
malApplicable(malValuePtr meta) : malValue(meta) { }
virtual malValuePtr apply(malValueIter argsBegin,
malValueIter argsEnd,
malEnvPtr env) const = 0;
malValueIter argsEnd) const = 0;
};
class malHash : public malValue {
@ -263,8 +262,7 @@ class malBuiltIn : public malApplicable {
public:
typedef malValuePtr (ApplyFunc)(const String& name,
malValueIter argsBegin,
malValueIter argsEnd,
malEnvPtr env);
malValueIter argsEnd);
malBuiltIn(const String& name, ApplyFunc* handler)
: m_name(name), m_handler(handler) { }
@ -273,8 +271,7 @@ public:
: malApplicable(meta), m_name(that.m_name), m_handler(that.m_handler) { }
virtual malValuePtr apply(malValueIter argsBegin,
malValueIter argsEnd,
malEnvPtr env) const;
malValueIter argsEnd) const;
virtual String print(bool readably) const {
return STRF("#builtin-function(%s)", m_name.c_str());
@ -300,8 +297,7 @@ public:
malLambda(const malLambda& that, bool isMacro);
virtual malValuePtr apply(malValueIter argsBegin,
malValueIter argsEnd,
malEnvPtr env) const;
malValueIter argsEnd) const;
malValuePtr getBody() const { return m_body; }
malEnvPtr makeEnv(malValueIter argsBegin, malValueIter argsEnd) const;

View File

@ -60,7 +60,7 @@ malValuePtr EVAL(malValuePtr ast, malEnvPtr)
return ast;
}
malValuePtr APPLY(malValuePtr ast, malValueIter, malValueIter, malEnvPtr)
malValuePtr APPLY(malValuePtr ast, malValueIter, malValueIter)
{
return ast;
}

View File

@ -59,14 +59,13 @@ String PRINT(malValuePtr ast)
return ast->print(true);
}
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd,
malEnvPtr env)
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd)
{
const malApplicable* handler = DYNAMIC_CAST(malApplicable, op);
MAL_CHECK(handler != NULL,
"\"%s\" is not applicable", op->print(true).c_str());
return handler->apply(argsBegin, argsEnd, env);
return handler->apply(argsBegin, argsEnd);
}
#define ARG(type, name) type* name = VALUE_CAST(type, *argsBegin++)
@ -79,7 +78,7 @@ malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd,
static malValuePtr builtIn_add(const String& name,
malValueIter argsBegin, malValueIter argsEnd, malEnvPtr env)
malValueIter argsBegin, malValueIter argsEnd)
{
CHECK_ARGS_IS(2);
ARG(malInteger, lhs);
@ -88,7 +87,7 @@ static malValuePtr builtIn_add(const String& name,
}
static malValuePtr builtIn_sub(const String& name,
malValueIter argsBegin, malValueIter argsEnd, malEnvPtr env)
malValueIter argsBegin, malValueIter argsEnd)
{
int argCount = CHECK_ARGS_BETWEEN(1, 2);
ARG(malInteger, lhs);
@ -100,7 +99,7 @@ static malValuePtr builtIn_sub(const String& name,
}
static malValuePtr builtIn_mul(const String& name,
malValueIter argsBegin, malValueIter argsEnd, malEnvPtr env)
malValueIter argsBegin, malValueIter argsEnd)
{
CHECK_ARGS_IS(2);
ARG(malInteger, lhs);
@ -109,7 +108,7 @@ static malValuePtr builtIn_mul(const String& name,
}
static malValuePtr builtIn_div(const String& name,
malValueIter argsBegin, malValueIter argsEnd, malEnvPtr env)
malValueIter argsBegin, malValueIter argsEnd)
{
CHECK_ARGS_IS(2);
ARG(malInteger, lhs);

View File

@ -12,11 +12,12 @@ String PRINT(malValuePtr ast);
static ReadLine s_readLine("~/.mal-history");
static malEnvPtr replEnv(new malEnv);
int main(int argc, char* argv[])
{
String prompt = "user> ";
String input;
malEnvPtr replEnv(new malEnv);
installCore(replEnv);
while (s_readLine.get(prompt, input)) {
String out;
@ -46,6 +47,9 @@ malValuePtr READ(const String& input)
malValuePtr EVAL(malValuePtr ast, malEnvPtr env)
{
if (!env) {
env = replEnv;
}
const malList* list = DYNAMIC_CAST(malList, ast);
if (!list || (list->count() == 0)) {
return ast->eval(env);
@ -81,7 +85,7 @@ malValuePtr EVAL(malValuePtr ast, malEnvPtr env)
// Now we're left with the case of a regular list to be evaluated.
std::unique_ptr<malValueVec> items(list->evalItems(env));
malValuePtr op = items->at(0);
return APPLY(op, items->begin()+1, items->end(), env);
return APPLY(op, items->begin()+1, items->end());
}
String PRINT(malValuePtr ast)
@ -89,14 +93,13 @@ String PRINT(malValuePtr ast)
return ast->print(true);
}
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd,
malEnvPtr env)
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd)
{
const malApplicable* handler = DYNAMIC_CAST(malApplicable, op);
MAL_CHECK(handler != NULL,
"\"%s\" is not applicable", op->print(true).c_str());
return handler->apply(argsBegin, argsEnd, env);
return handler->apply(argsBegin, argsEnd);
}
// Added to keep the linker happy at step A

View File

@ -13,11 +13,12 @@ static void installFunctions(malEnvPtr env);
static ReadLine s_readLine("~/.mal-history");
static malEnvPtr replEnv(new malEnv);
int main(int argc, char* argv[])
{
String prompt = "user> ";
String input;
malEnvPtr replEnv(new malEnv);
installCore(replEnv);
installFunctions(replEnv);
while (s_readLine.get(prompt, input)) {
@ -48,6 +49,9 @@ malValuePtr READ(const String& input)
malValuePtr EVAL(malValuePtr ast, malEnvPtr env)
{
if (!env) {
env = replEnv;
}
const malList* list = DYNAMIC_CAST(malList, ast);
if (!list || (list->count() == 0)) {
return ast->eval(env);
@ -122,7 +126,7 @@ malValuePtr EVAL(malValuePtr ast, malEnvPtr env)
lambda->makeEnv(items->begin()+1, items->end()));
}
else {
return APPLY(op, items->begin()+1, items->end(), env);
return APPLY(op, items->begin()+1, items->end());
}
}
@ -131,14 +135,13 @@ String PRINT(malValuePtr ast)
return ast->print(true);
}
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd,
malEnvPtr env)
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd)
{
const malApplicable* handler = DYNAMIC_CAST(malApplicable, op);
MAL_CHECK(handler != NULL,
"\"%s\" is not applicable", op->print(true).c_str());
return handler->apply(argsBegin, argsEnd, env);
return handler->apply(argsBegin, argsEnd);
}
static const char* malFunctionTable[] = {

View File

@ -13,11 +13,12 @@ static void installFunctions(malEnvPtr env);
static ReadLine s_readLine("~/.mal-history");
static malEnvPtr replEnv(new malEnv);
int main(int argc, char* argv[])
{
String prompt = "user> ";
String input;
malEnvPtr replEnv(new malEnv);
installCore(replEnv);
installFunctions(replEnv);
while (s_readLine.get(prompt, input)) {
@ -48,6 +49,9 @@ malValuePtr READ(const String& input)
malValuePtr EVAL(malValuePtr ast, malEnvPtr env)
{
if (!env) {
env = replEnv;
}
while (1) {
const malList* list = DYNAMIC_CAST(malList, ast);
if (!list || (list->count() == 0)) {
@ -128,7 +132,7 @@ malValuePtr EVAL(malValuePtr ast, malEnvPtr env)
continue; // TCO
}
else {
return APPLY(op, items->begin()+1, items->end(), env);
return APPLY(op, items->begin()+1, items->end());
}
}
}
@ -138,14 +142,13 @@ String PRINT(malValuePtr ast)
return ast->print(true);
}
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd,
malEnvPtr env)
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd)
{
const malApplicable* handler = DYNAMIC_CAST(malApplicable, op);
MAL_CHECK(handler != NULL,
"\"%s\" is not applicable", op->print(true).c_str());
return handler->apply(argsBegin, argsEnd, env);
return handler->apply(argsBegin, argsEnd);
}
static const char* malFunctionTable[] = {

View File

@ -16,11 +16,12 @@ static void safeRep(const String& input, malEnvPtr env);
static ReadLine s_readLine("~/.mal-history");
static malEnvPtr replEnv(new malEnv);
int main(int argc, char* argv[])
{
String prompt = "user> ";
String input;
malEnvPtr replEnv(new malEnv);
installCore(replEnv);
installFunctions(replEnv);
makeArgv(replEnv, argc - 2, argv + 2);
@ -71,6 +72,9 @@ malValuePtr READ(const String& input)
malValuePtr EVAL(malValuePtr ast, malEnvPtr env)
{
if (!env) {
env = replEnv;
}
while (1) {
const malList* list = DYNAMIC_CAST(malList, ast);
if (!list || (list->count() == 0)) {
@ -151,7 +155,7 @@ malValuePtr EVAL(malValuePtr ast, malEnvPtr env)
continue; // TCO
}
else {
return APPLY(op, items->begin()+1, items->end(), env);
return APPLY(op, items->begin()+1, items->end());
}
}
}
@ -161,14 +165,13 @@ String PRINT(malValuePtr ast)
return ast->print(true);
}
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd,
malEnvPtr env)
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd)
{
const malApplicable* handler = DYNAMIC_CAST(malApplicable, op);
MAL_CHECK(handler != NULL,
"\"%s\" is not applicable", op->print(true).c_str());
return handler->apply(argsBegin, argsEnd, env);
return handler->apply(argsBegin, argsEnd);
}
static const char* malFunctionTable[] = {

View File

@ -17,11 +17,12 @@ static malValuePtr quasiquote(malValuePtr obj);
static ReadLine s_readLine("~/.mal-history");
static malEnvPtr replEnv(new malEnv);
int main(int argc, char* argv[])
{
String prompt = "user> ";
String input;
malEnvPtr replEnv(new malEnv);
installCore(replEnv);
installFunctions(replEnv);
makeArgv(replEnv, argc - 2, argv + 2);
@ -72,6 +73,9 @@ malValuePtr READ(const String& input)
malValuePtr EVAL(malValuePtr ast, malEnvPtr env)
{
if (!env) {
env = replEnv;
}
while (1) {
const malList* list = DYNAMIC_CAST(malList, ast);
if (!list || (list->count() == 0)) {
@ -163,7 +167,7 @@ malValuePtr EVAL(malValuePtr ast, malEnvPtr env)
continue; // TCO
}
else {
return APPLY(op, items->begin()+1, items->end(), env);
return APPLY(op, items->begin()+1, items->end());
}
}
}
@ -173,14 +177,13 @@ String PRINT(malValuePtr ast)
return ast->print(true);
}
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd,
malEnvPtr env)
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd)
{
const malApplicable* handler = DYNAMIC_CAST(malApplicable, op);
MAL_CHECK(handler != NULL,
"\"%s\" is not applicable", op->print(true).c_str());
return handler->apply(argsBegin, argsEnd, env);
return handler->apply(argsBegin, argsEnd);
}
static bool isSymbol(malValuePtr obj, const String& text)

View File

@ -19,11 +19,12 @@ static void installMacros(malEnvPtr env);
static ReadLine s_readLine("~/.mal-history");
static malEnvPtr replEnv(new malEnv);
int main(int argc, char* argv[])
{
String prompt = "user> ";
String input;
malEnvPtr replEnv(new malEnv);
installCore(replEnv);
installFunctions(replEnv);
installMacros(replEnv);
@ -75,6 +76,9 @@ malValuePtr READ(const String& input)
malValuePtr EVAL(malValuePtr ast, malEnvPtr env)
{
if (!env) {
env = replEnv;
}
while (1) {
const malList* list = DYNAMIC_CAST(malList, ast);
if (!list || (list->count() == 0)) {
@ -186,7 +190,7 @@ malValuePtr EVAL(malValuePtr ast, malEnvPtr env)
continue; // TCO
}
else {
return APPLY(op, items->begin()+1, items->end(), env);
return APPLY(op, items->begin()+1, items->end());
}
}
}
@ -196,14 +200,13 @@ String PRINT(malValuePtr ast)
return ast->print(true);
}
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd,
malEnvPtr env)
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd)
{
const malApplicable* handler = DYNAMIC_CAST(malApplicable, op);
MAL_CHECK(handler != NULL,
"\"%s\" is not applicable", op->print(true).c_str());
return handler->apply(argsBegin, argsEnd, env);
return handler->apply(argsBegin, argsEnd);
}
static bool isSymbol(malValuePtr obj, const String& text)
@ -271,7 +274,7 @@ static malValuePtr macroExpand(malValuePtr obj, malEnvPtr env)
{
while (const malLambda* macro = isMacroApplication(obj, env)) {
const malSequence* seq = STATIC_CAST(malSequence, obj);
obj = macro->apply(seq->begin() + 1, seq->end(), env);
obj = macro->apply(seq->begin() + 1, seq->end());
}
return obj;
}

View File

@ -19,11 +19,12 @@ static void installMacros(malEnvPtr env);
static ReadLine s_readLine("~/.mal-history");
static malEnvPtr replEnv(new malEnv);
int main(int argc, char* argv[])
{
String prompt = "user> ";
String input;
malEnvPtr replEnv(new malEnv);
installCore(replEnv);
installFunctions(replEnv);
installMacros(replEnv);
@ -75,6 +76,9 @@ malValuePtr READ(const String& input)
malValuePtr EVAL(malValuePtr ast, malEnvPtr env)
{
if (!env) {
env = replEnv;
}
while (1) {
const malList* list = DYNAMIC_CAST(malList, ast);
if (!list || (list->count() == 0)) {
@ -227,7 +231,7 @@ malValuePtr EVAL(malValuePtr ast, malEnvPtr env)
continue; // TCO
}
else {
return APPLY(op, items->begin()+1, items->end(), env);
return APPLY(op, items->begin()+1, items->end());
}
}
}
@ -237,14 +241,13 @@ String PRINT(malValuePtr ast)
return ast->print(true);
}
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd,
malEnvPtr env)
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd)
{
const malApplicable* handler = DYNAMIC_CAST(malApplicable, op);
MAL_CHECK(handler != NULL,
"\"%s\" is not applicable", op->print(true).c_str());
return handler->apply(argsBegin, argsEnd, env);
return handler->apply(argsBegin, argsEnd);
}
static bool isSymbol(malValuePtr obj, const String& text)
@ -312,7 +315,7 @@ static malValuePtr macroExpand(malValuePtr obj, malEnvPtr env)
{
while (const malLambda* macro = isMacroApplication(obj, env)) {
const malSequence* seq = STATIC_CAST(malSequence, obj);
obj = macro->apply(seq->begin() + 1, seq->end(), env);
obj = macro->apply(seq->begin() + 1, seq->end());
}
return obj;
}

View File

@ -19,11 +19,12 @@ static void installMacros(malEnvPtr env);
static ReadLine s_readLine("~/.mal-history");
static malEnvPtr replEnv(new malEnv);
int main(int argc, char* argv[])
{
String prompt = "user> ";
String input;
malEnvPtr replEnv(new malEnv);
installCore(replEnv);
installFunctions(replEnv);
installMacros(replEnv);
@ -75,6 +76,9 @@ malValuePtr READ(const String& input)
malValuePtr EVAL(malValuePtr ast, malEnvPtr env)
{
if (!env) {
env = replEnv;
}
while (1) {
const malList* list = DYNAMIC_CAST(malList, ast);
if (!list || (list->count() == 0)) {
@ -227,7 +231,7 @@ malValuePtr EVAL(malValuePtr ast, malEnvPtr env)
continue; // TCO
}
else {
return APPLY(op, items->begin()+1, items->end(), env);
return APPLY(op, items->begin()+1, items->end());
}
}
}
@ -237,14 +241,13 @@ String PRINT(malValuePtr ast)
return ast->print(true);
}
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd,
malEnvPtr env)
malValuePtr APPLY(malValuePtr op, malValueIter argsBegin, malValueIter argsEnd)
{
const malApplicable* handler = DYNAMIC_CAST(malApplicable, op);
MAL_CHECK(handler != NULL,
"\"%s\" is not applicable", op->print(true).c_str());
return handler->apply(argsBegin, argsEnd, env);
return handler->apply(argsBegin, argsEnd);
}
static bool isSymbol(malValuePtr obj, const String& text)
@ -312,7 +315,7 @@ static malValuePtr macroExpand(malValuePtr obj, malEnvPtr env)
{
while (const malLambda* macro = isMacroApplication(obj, env)) {
const malSequence* seq = STATIC_CAST(malSequence, obj);
obj = macro->apply(seq->begin() + 1, seq->end(), env);
obj = macro->apply(seq->begin() + 1, seq->end());
}
return obj;
}
@ -348,7 +351,6 @@ static const char* malFunctionTable[] = {
(eval (read-string (str \"(do \" (slurp filename) \")\")))))",
"(def! map (fn* (f xs) (if (empty? xs) xs \
(cons (f (first xs)) (map f (rest xs))))))",
"(def! swap! (fn* (atom f & args) (reset! atom (apply f @atom args))))",
"(def! *host-language* \"c++\")",
};