Compare commits

...

5 Commits

  1. 74
      CMakeLists.txt
  2. 46
      src/ast.cpp
  3. 11
      src/ast.h
  4. 134
      src/eval-special-form.cpp
  5. 53
      src/eval.cpp
  6. 7
      src/eval.h
  7. 32
      src/functions.cpp
  8. 6
      src/reader.cpp
  9. 8
      src/step6_file.cpp
  10. 8
      src/step7_quote.cpp
  11. 8
      src/step8_macros.cpp
  12. 8
      src/step9_try.cpp
  13. 8
      src/stepA_mal.cpp

74
CMakeLists.txt

@ -95,49 +95,41 @@ add_custom_target(run
# ------------------------------------------ # ------------------------------------------
# Test targets # Test targets
add_custom_target(test0 function(make_test_target target_name step_name)
COMMAND ../vendor/mal/runtest.py --deferrable --optional ../tests/step0_repl.mal -- ./${PROJECT}) add_custom_target(${target_name}
add_dependencies(test0 ${PROJECT}) COMMAND ../vendor/mal/runtest.py --deferrable --optional ../tests/${step_name}.mal -- ./${step_name})
add_dependencies(${target_name} ${step_name})
add_custom_target(test1 endfunction()
COMMAND ../vendor/mal/runtest.py --deferrable --optional ../tests/step1_read_print.mal -- ./${PROJECT})
add_dependencies(test1 ${PROJECT})
add_custom_target(test2
COMMAND ../vendor/mal/runtest.py --deferrable --optional ../tests/step2_eval.mal -- ./${PROJECT})
add_dependencies(test2 ${PROJECT})
add_custom_target(test3
COMMAND ../vendor/mal/runtest.py --deferrable --optional ../tests/step3_env.mal -- ./${PROJECT})
add_dependencies(test3 ${PROJECT})
add_custom_target(test4
COMMAND ../vendor/mal/runtest.py --deferrable --optional ../tests/step4_if_fn_do.mal -- ./${PROJECT})
add_dependencies(test4 ${PROJECT})
add_custom_target(test5
COMMAND ../vendor/mal/runtest.py --deferrable --optional ../tests/step5_tco.mal -- ./${PROJECT})
add_dependencies(test5 ${PROJECT})
add_custom_target(test6
COMMAND ../vendor/mal/runtest.py --deferrable --optional ../tests/step6_file.mal -- ./${PROJECT})
add_dependencies(test6 ${PROJECT})
add_custom_target(test7
COMMAND ../vendor/mal/runtest.py --deferrable --optional ../tests/step7_quote.mal -- ./${PROJECT})
add_dependencies(test7 ${PROJECT})
add_custom_target(test8
COMMAND ../vendor/mal/runtest.py --deferrable --optional ../tests/step8_macros.mal -- ./${PROJECT})
add_dependencies(test8 ${PROJECT})
add_custom_target(test9 make_test_target("test0" "step0_repl")
COMMAND ../vendor/mal/runtest.py --deferrable --optional ../tests/step9_try.mal -- ./${PROJECT}) make_test_target("test1" "step1_read_print")
add_dependencies(test9 ${PROJECT}) make_test_target("test2" "step2_eval")
make_test_target("test3" "step3_env")
make_test_target("test4" "step4_if_fn_do")
make_test_target("test5" "step5_tco")
make_test_target("test6" "step6_file")
make_test_target("test7" "step7_quote")
make_test_target("test8" "step8_macros")
make_test_target("test9" "step9_try")
make_test_target("testA" "stepA_mal")
function(make_host_test_target target_name step_name)
add_custom_target(${target_name}
COMMAND ../vendor/mal/runtest.py --deferrable --optional ../tests/${step_name}.mal -- ./${PROJECT} ../mal/${step_name}.mal)
add_dependencies(${target_name} ${PROJECT})
endfunction()
add_custom_target(testA make_host_test_target("host_test0" "step0_repl")
COMMAND ../vendor/mal/runtest.py --deferrable --optional ../tests/stepA_mal.mal -- ./${PROJECT}) make_host_test_target("host_test1" "step1_read_print")
add_dependencies(testA ${PROJECT}) make_host_test_target("host_test2" "step2_eval")
make_host_test_target("host_test3" "step3_env")
make_host_test_target("host_test4" "step4_if_fn_do")
# make_host_test_target("host_test5" "step5_tco") # disabled
make_host_test_target("host_test6" "step6_file")
make_host_test_target("host_test7" "step7_quote")
make_host_test_target("host_test8" "step8_macros")
make_host_test_target("host_test9" "step9_try")
make_host_test_target("host_testA" "stepA_mal")
add_custom_target(perf add_custom_target(perf
COMMAND ./${PROJECT} ../tests/perf1.mal COMMAND ./${PROJECT} ../tests/perf1.mal

46
src/ast.cpp

@ -114,36 +114,16 @@ HashMap::HashMap(const HashMap& that, ValuePtr meta)
{ {
} }
void HashMap::add(const std::string& key, ValuePtr value) std::string HashMap::getKeyString(ValuePtr key)
{
if (value == nullptr) {
return;
}
m_elements.insert_or_assign(key, value);
}
void HashMap::add(ValuePtr key, ValuePtr value)
{
if (key == nullptr || value == nullptr) {
return;
}
m_elements.insert_or_assign(getKeyString(key), value);
}
void HashMap::remove(const std::string& key)
{
m_elements.erase(key);
}
void HashMap::remove(ValuePtr key)
{ {
if (key == nullptr) { if (!is<String>(key.get()) && !is<Keyword>(key.get())) {
return; Error::the().add(::format("wrong argument type: string or keyword, {}", key));
return {};
} }
m_elements.erase(getKeyString(key)); return is<String>(key.get())
? std::static_pointer_cast<String>(key)->data()
: std::static_pointer_cast<Keyword>(key)->keyword();
} }
bool HashMap::exists(const std::string& key) bool HashMap::exists(const std::string& key)
@ -170,18 +150,6 @@ ValuePtr HashMap::get(ValuePtr key)
return get(getKeyString(key)); return get(getKeyString(key));
} }
std::string HashMap::getKeyString(ValuePtr key)
{
if (!is<String>(key.get()) && !is<Keyword>(key.get())) {
Error::the().add(::format("wrong argument type: string or keyword, {}", key));
return {};
}
return is<String>(key.get())
? std::static_pointer_cast<String>(key)->data()
: std::static_pointer_cast<Keyword>(key)->keyword();
}
// ----------------------------------------- // -----------------------------------------
String::String(const std::string& data) String::String(const std::string& data)

11
src/ast.h

@ -174,20 +174,17 @@ private:
// ----------------------------------------- // -----------------------------------------
using Elements = std::map<std::string, ValuePtr>;
// {} // {}
class HashMap final : public Value { class HashMap final : public Value {
public: public:
using Elements = std::map<std::string, ValuePtr>;
HashMap() = default; HashMap() = default;
HashMap(const Elements& elements); HashMap(const Elements& elements);
HashMap(const HashMap& that, ValuePtr meta); HashMap(const HashMap& that, ValuePtr meta);
virtual ~HashMap() = default; virtual ~HashMap() = default;
void add(const std::string& key, ValuePtr value); static std::string getKeyString(ValuePtr key);
void add(ValuePtr key, ValuePtr value);
void remove(const std::string& key);
void remove(ValuePtr key);
bool exists(const std::string& key); bool exists(const std::string& key);
bool exists(ValuePtr key); bool exists(ValuePtr key);
@ -202,8 +199,6 @@ public:
private: private:
virtual bool isHashMap() const override { return true; } virtual bool isHashMap() const override { return true; }
std::string getKeyString(ValuePtr key);
Elements m_elements; Elements m_elements;
}; };

134
src/eval-special-form.cpp

@ -30,8 +30,8 @@ ValuePtr Eval::evalDef(const ValueVector& nodes, EnvironmentPtr env)
VALUE_CAST(symbol, Symbol, nodes.front()); VALUE_CAST(symbol, Symbol, nodes.front());
// Eval second argument // Eval second argument
m_ast_stack.push(*std::next(nodes.begin())); m_ast = *std::next(nodes.begin());
m_env_stack.push(env); m_env = env;
ValuePtr value = evalImpl(); ValuePtr value = evalImpl();
// Dont overwrite symbols after an error // Dont overwrite symbols after an error
@ -52,8 +52,8 @@ ValuePtr Eval::evalDefMacro(const ValueVector& nodes, EnvironmentPtr env)
VALUE_CAST(symbol, Symbol, nodes.front()); VALUE_CAST(symbol, Symbol, nodes.front());
// Eval second argument // Eval second argument
m_ast_stack.push(*std::next(nodes.begin())); m_ast = *std::next(nodes.begin());
m_env_stack.push(env); m_env = env;
ValuePtr value = evalImpl(); ValuePtr value = evalImpl();
VALUE_CAST(lambda, Lambda, value); VALUE_CAST(lambda, Lambda, value);
@ -111,6 +111,55 @@ ValuePtr Eval::evalQuote(const ValueVector& nodes)
return nodes.front(); return nodes.front();
} }
// (try* x (catch* y z))
ValuePtr Eval::evalTry(const ValueVector& nodes, EnvironmentPtr env)
{
CHECK_ARG_COUNT_AT_LEAST("try*", nodes.size(), 1);
// Try 'x'
m_ast = nodes.front();
m_env = env;
auto result = evalImpl();
if (!Error::the().hasAnyError()) {
return result;
}
if (nodes.size() == 1) {
return nullptr;
}
// Catch
// Get the error message
auto error = (Error::the().hasOtherError())
? makePtr<String>(Error::the().otherError())
: Error::the().exception();
Error::the().clearErrors();
VALUE_CAST(catch_list, List, nodes.back());
const auto& catch_nodes = catch_list->nodes();
CHECK_ARG_COUNT_IS("catch*", catch_nodes.size() - 1, 2);
VALUE_CAST(catch_symbol, Symbol, catch_nodes.front());
if (catch_symbol->symbol() != "catch*") {
Error::the().add("catch block must begin with catch*");
return nullptr;
}
VALUE_CAST(catch_binding, Symbol, (*std::next(catch_nodes.begin())));
// Create new Environment that binds 'y' to the value of the exception
auto catch_env = Environment::create(env);
catch_env->set(catch_binding->symbol(), error);
// Evaluate 'z' using the new Environment
m_ast = catch_nodes.back();
m_env = catch_env;
return evalImpl();
}
// -----------------------------------------
// (do 1 2 3) // (do 1 2 3)
void Eval::evalDo(const ValueVector& nodes, EnvironmentPtr env) void Eval::evalDo(const ValueVector& nodes, EnvironmentPtr env)
{ {
@ -118,14 +167,14 @@ void Eval::evalDo(const ValueVector& nodes, EnvironmentPtr env)
// Evaluate all nodes except the last // Evaluate all nodes except the last
for (auto it = nodes.begin(); it != std::prev(nodes.end(), 1); ++it) { for (auto it = nodes.begin(); it != std::prev(nodes.end(), 1); ++it) {
m_ast_stack.push(*it); m_ast = *it;
m_env_stack.push(env); m_env = env;
evalImpl(); evalImpl();
} }
// Eval last node // Eval last node
m_ast_stack.push(nodes.back()); m_ast = nodes.back();
m_env_stack.push(env); m_env = env;
return; // TCO return; // TCO
} }
@ -138,18 +187,18 @@ void Eval::evalIf(const ValueVector& nodes, EnvironmentPtr env)
auto second_argument = *std::next(nodes.begin()); auto second_argument = *std::next(nodes.begin());
auto third_argument = (nodes.size() == 3) ? *std::next(std::next(nodes.begin())) : makePtr<Constant>(Constant::Nil); auto third_argument = (nodes.size() == 3) ? *std::next(std::next(nodes.begin())) : makePtr<Constant>(Constant::Nil);
m_ast_stack.push(first_argument); m_ast = first_argument;
m_env_stack.push(env); m_env = env;
auto first_evaluated = evalImpl(); auto first_evaluated = evalImpl();
if (!is<Constant>(first_evaluated.get()) if (!is<Constant>(first_evaluated.get())
|| std::static_pointer_cast<Constant>(first_evaluated)->state() == Constant::True) { || std::static_pointer_cast<Constant>(first_evaluated)->state() == Constant::True) {
m_ast_stack.push(second_argument); m_ast = second_argument;
m_env_stack.push(env); m_env = env;
return; // TCO return; // TCO
} }
m_ast_stack.push(third_argument); m_ast = third_argument;
m_env_stack.push(env); m_env = env;
return; // TCO return; // TCO
} }
@ -173,16 +222,16 @@ void Eval::evalLet(const ValueVector& nodes, EnvironmentPtr env)
VALUE_CAST(elt, Symbol, (*it), void()); VALUE_CAST(elt, Symbol, (*it), void());
std::string key = elt->symbol(); std::string key = elt->symbol();
m_ast_stack.push(*std::next(it)); m_ast = *std::next(it);
m_env_stack.push(let_env); m_env = let_env;
ValuePtr value = evalImpl(); ValuePtr value = evalImpl();
let_env->set(key, value); let_env->set(key, value);
} }
// TODO: Remove limitation of 3 arguments // TODO: Remove limitation of 3 arguments
// Eval all arguments in this new env, return last sexp of the result // Eval all arguments in this new env, return last sexp of the result
m_ast_stack.push(*std::next(nodes.begin())); m_ast = *std::next(nodes.begin());
m_env_stack.push(let_env); m_env = let_env;
return; // TCO return; // TCO
} }
@ -277,53 +326,8 @@ void Eval::evalQuasiQuote(const ValueVector& nodes, EnvironmentPtr env)
auto result = evalQuasiQuoteImpl(nodes.front()); auto result = evalQuasiQuoteImpl(nodes.front());
m_ast_stack.push(result); m_ast = result;
m_env_stack.push(env); m_env = env;
return; // TCO
}
// (try* x (catch* y z))
void Eval::evalTry(const ValueVector& nodes, EnvironmentPtr env)
{
CHECK_ARG_COUNT_AT_LEAST("try*", nodes.size(), 1, void());
// Try 'x'
m_ast_stack.push(nodes.front());
m_env_stack.push(env);
auto result = evalImpl();
// Catch
if (nodes.size() == 2 && (Error::the().hasOtherError() || Error::the().hasException())) {
// Get the exception
auto error = (Error::the().hasOtherError())
? makePtr<String>(Error::the().otherError())
: Error::the().exception();
Error::the().clearErrors();
VALUE_CAST(catch_list, List, nodes.back(), void());
const auto& catch_nodes = catch_list->nodes();
CHECK_ARG_COUNT_IS("catch*", catch_nodes.size() - 1, 2, void());
VALUE_CAST(catch_symbol, Symbol, catch_nodes.front(), void());
if (catch_symbol->symbol() != "catch*") {
Error::the().add("catch block must begin with catch*");
return;
}
VALUE_CAST(catch_binding, Symbol, (*std::next(catch_nodes.begin())), void());
// Create new Environment that binds 'y' to the value of the exception
auto catch_env = Environment::create(env);
catch_env->set(catch_binding->symbol(), error);
// Evaluate 'z' using the new Environment
m_ast_stack.push(catch_nodes.back());
m_env_stack.push(catch_env);
return; // TCO
}
m_ast_stack.push(result);
m_env_stack.push(env);
return; // TCO return; // TCO
} }

53
src/eval.cpp

@ -23,6 +23,7 @@ namespace blaze {
Eval::Eval(ValuePtr ast, EnvironmentPtr env) Eval::Eval(ValuePtr ast, EnvironmentPtr env)
: m_ast(ast) : m_ast(ast)
, m_env(env) , m_env(env)
, m_outer_env(env)
{ {
} }
@ -30,11 +31,6 @@ Eval::Eval(ValuePtr ast, EnvironmentPtr env)
void Eval::eval() void Eval::eval()
{ {
m_ast_stack = std::stack<ValuePtr>();
m_env_stack = std::stack<EnvironmentPtr>();
m_ast_stack.push(m_ast);
m_env_stack.push(m_env);
m_ast = evalImpl(); m_ast = evalImpl();
} }
@ -48,20 +44,13 @@ ValuePtr Eval::evalImpl()
return nullptr; return nullptr;
} }
if (m_ast_stack.size() == 0) { ast = m_ast;
return nullptr; env = m_env;
}
if (m_env_stack.size() == 0) { if (env == nullptr) {
m_env_stack.push(m_env); env = m_outer_env;
} }
ast = m_ast_stack.top();
env = m_env_stack.top();
m_ast_stack.pop();
m_env_stack.pop();
if (!is<List>(ast.get())) { if (!is<List>(ast.get())) {
return evalAst(ast, env); return evalAst(ast, env);
} }
@ -100,6 +89,9 @@ ValuePtr Eval::evalImpl()
if (symbol == "quote") { if (symbol == "quote") {
return evalQuote(nodes); return evalQuote(nodes);
} }
if (symbol == "try*") {
return evalTry(nodes, env);
}
// Tail call optimized functions // Tail call optimized functions
if (symbol == "do") { if (symbol == "do") {
evalDo(nodes, env); evalDo(nodes, env);
@ -117,10 +109,6 @@ ValuePtr Eval::evalImpl()
evalQuasiQuote(nodes, env); evalQuasiQuote(nodes, env);
continue; // TCO continue; // TCO
} }
if (symbol == "try*") {
evalTry(nodes, env);
continue; // TCO
}
} }
auto evaluated_list = std::static_pointer_cast<List>(evalAst(ast, env)); auto evaluated_list = std::static_pointer_cast<List>(evalAst(ast, env));
@ -133,8 +121,8 @@ ValuePtr Eval::evalImpl()
if (is<Lambda>(evaluated_list->front().get())) { if (is<Lambda>(evaluated_list->front().get())) {
auto lambda = std::static_pointer_cast<Lambda>(evaluated_list->front()); auto lambda = std::static_pointer_cast<Lambda>(evaluated_list->front());
m_ast_stack.push(lambda->body()); m_ast = lambda->body();
m_env_stack.push(Environment::create(lambda, evaluated_list->rest())); m_env = Environment::create(lambda, evaluated_list->rest());
continue; // TCO continue; // TCO
} }
@ -165,8 +153,8 @@ ValuePtr Eval::evalAst(ValuePtr ast, EnvironmentPtr env)
auto evaluated_nodes = ValueVector(count); auto evaluated_nodes = ValueVector(count);
for (size_t i = 0; i < count; ++i) { for (size_t i = 0; i < count; ++i) {
m_ast_stack.push(nodes[i]); m_ast = nodes[i];
m_env_stack.push(env); m_env = env;
ValuePtr eval_node = evalImpl(); ValuePtr eval_node = evalImpl();
if (eval_node == nullptr) { if (eval_node == nullptr) {
return nullptr; return nullptr;
@ -181,19 +169,19 @@ ValuePtr Eval::evalAst(ValuePtr ast, EnvironmentPtr env)
return makePtr<Vector>(evaluated_nodes); return makePtr<Vector>(evaluated_nodes);
} }
else if (is<HashMap>(ast_raw_ptr)) { else if (is<HashMap>(ast_raw_ptr)) {
auto result = makePtr<HashMap>();
const auto& elements = std::static_pointer_cast<HashMap>(ast)->elements(); const auto& elements = std::static_pointer_cast<HashMap>(ast)->elements();
Elements evaluated_elements;
for (const auto& element : elements) { for (const auto& element : elements) {
m_ast_stack.push(element.second); m_ast = element.second;
m_env_stack.push(env); m_env = env;
ValuePtr element_node = evalImpl(); ValuePtr element_node = evalImpl();
if (element_node == nullptr) { if (element_node == nullptr) {
return nullptr; return nullptr;
} }
result->add(element.first, element_node); evaluated_elements.insert_or_assign(element.first, element_node);
} }
return result; return makePtr<HashMap>(evaluated_elements);
} }
return ast; return ast;
@ -231,18 +219,19 @@ ValuePtr Eval::macroExpand(ValuePtr ast, EnvironmentPtr env)
{ {
while (isMacroCall(ast, env)) { while (isMacroCall(ast, env)) {
auto list = std::static_pointer_cast<List>(ast); auto list = std::static_pointer_cast<List>(ast);
auto value = env->get(std::static_pointer_cast<Symbol>(list->front())->symbol()); auto value = env->get(std::static_pointer_cast<Symbol>(list->front())->symbol());
auto lambda = std::static_pointer_cast<Lambda>(value); auto lambda = std::static_pointer_cast<Lambda>(value);
m_ast_stack.push(lambda->body()); m_ast = lambda->body();
m_env_stack.push(Environment::create(lambda, list->rest())); m_env = Environment::create(lambda, list->rest());
ast = evalImpl(); ast = evalImpl();
} }
return ast; return ast;
} }
//----------------------------------------- // -----------------------------------------
ValuePtr Eval::apply(std::shared_ptr<List> evaluated_list) ValuePtr Eval::apply(std::shared_ptr<List> evaluated_list)
{ {

7
src/eval.h

@ -38,19 +38,18 @@ private:
ValuePtr evalMacroExpand(const ValueVector& nodes, EnvironmentPtr env); ValuePtr evalMacroExpand(const ValueVector& nodes, EnvironmentPtr env);
ValuePtr evalQuasiQuoteExpand(const ValueVector& nodes); ValuePtr evalQuasiQuoteExpand(const ValueVector& nodes);
ValuePtr evalQuote(const ValueVector& nodes); ValuePtr evalQuote(const ValueVector& nodes);
ValuePtr evalTry(const ValueVector& nodes, EnvironmentPtr env);
void evalDo(const ValueVector& nodes, EnvironmentPtr env); void evalDo(const ValueVector& nodes, EnvironmentPtr env);
void evalIf(const ValueVector& nodes, EnvironmentPtr env); void evalIf(const ValueVector& nodes, EnvironmentPtr env);
void evalLet(const ValueVector& nodes, EnvironmentPtr env); void evalLet(const ValueVector& nodes, EnvironmentPtr env);
void evalQuasiQuote(const ValueVector& nodes, EnvironmentPtr env); void evalQuasiQuote(const ValueVector& nodes, EnvironmentPtr env);
void evalTry(const ValueVector& nodes, EnvironmentPtr env);
ValuePtr apply(std::shared_ptr<List> evaluated_list); ValuePtr apply(std::shared_ptr<List> evaluated_list);
ValuePtr m_ast; ValuePtr m_ast;
EnvironmentPtr m_env; EnvironmentPtr m_env;
EnvironmentPtr m_outer_env;
std::stack<ValuePtr> m_ast_stack;
std::stack<EnvironmentPtr> m_env_stack;
}; };
} // namespace blaze } // namespace blaze

32
src/functions.cpp

@ -518,7 +518,7 @@ ADD_FUNCTION(
return makePtr<List>(collection->rest()); return makePtr<List>(collection->rest());
}); });
// (apply + 1 2 (list 3 4)) -> (+ 1 2 3 4) // (apply + 1 2 (list 3 4)) -> (+ 1 2 3 4) -> 10
ADD_FUNCTION( ADD_FUNCTION(
"apply", "apply",
{ {
@ -712,16 +712,16 @@ ADD_FUNCTION(
{ {
CHECK_ARG_COUNT_EVEN("hash-map", SIZE()); CHECK_ARG_COUNT_EVEN("hash-map", SIZE());
auto result = makePtr<HashMap>(); Elements elements;
for (auto it = begin; it != end; std::advance(it, 2)) { for (auto it = begin; it != end; std::advance(it, 2)) {
result->add(*it, *(std::next(it))); const ValuePtr& value = *(std::next(it)); // temporary instance to get around const
elements.insert_or_assign(HashMap::getKeyString(*it), value);
} }
return result; return makePtr<HashMap>(elements);
}); });
// (assoc {:a 1 :b 2} :a 3 :c 1) // (assoc {:a 1 :b 2} :a 3 :c 1) -> {:a 3 :b 2 :c 1}
ADD_FUNCTION( ADD_FUNCTION(
"assoc", "assoc",
{ {
@ -732,15 +732,16 @@ ADD_FUNCTION(
CHECK_ARG_COUNT_EVEN("assoc", SIZE()); CHECK_ARG_COUNT_EVEN("assoc", SIZE());
auto result = makePtr<HashMap>(hash_map->elements()); Elements elements(hash_map->elements());
for (auto it = begin; it != end; std::advance(it, 2)) { for (auto it = begin; it != end; std::advance(it, 2)) {
result->add(*it, *(std::next(it))); const ValuePtr& value = *(std::next(it)); // temporary instance to get around const
elements.insert_or_assign(HashMap::getKeyString(*it), value);
} }
return result; return makePtr<HashMap>(elements);
}); });
// (dissoc {:a 1 :b 2 :c 3} :a :c :d) -> {:b 2}
ADD_FUNCTION( ADD_FUNCTION(
"dissoc", "dissoc",
{ {
@ -749,13 +750,12 @@ ADD_FUNCTION(
VALUE_CAST(hash_map, HashMap, (*begin)); VALUE_CAST(hash_map, HashMap, (*begin));
begin++; begin++;
auto result = makePtr<HashMap>(hash_map->elements()); Elements elements(hash_map->elements());
for (auto it = begin; it != end; ++it) { for (auto it = begin; it != end; ++it) {
result->remove(*it); elements.erase(HashMap::getKeyString(*it));
} }
return result; return makePtr<HashMap>(elements);
}); });
// (get {:kw "value"} :kw) -> "value" // (get {:kw "value"} :kw) -> "value"
@ -984,8 +984,8 @@ ADD_FUNCTION(
void installFunctions(EnvironmentPtr env) void installFunctions(EnvironmentPtr env)
{ {
for (const auto& [name, lambda] : s_functions) { for (const auto& [name, function] : s_functions) {
env->set(name, makePtr<Function>(name, lambda)); env->set(name, makePtr<Function>(name, function));
} }
} }

6
src/reader.cpp

@ -174,7 +174,7 @@ ValuePtr Reader::readHashMap()
{ {
ignore(); // { ignore(); // {
auto hash_map = makePtr<HashMap>(); Elements elements;
while (!isEOF() && peek().type != Token::Type::BraceClose) { while (!isEOF() && peek().type != Token::Type::BraceClose) {
auto key = readImpl(); auto key = readImpl();
@ -193,7 +193,7 @@ ValuePtr Reader::readHashMap()
} }
auto value = readImpl(); auto value = readImpl();
hash_map->add(key, value); elements.insert_or_assign(HashMap::getKeyString(key), value);
} }
if (!consumeSpecific(Token { .type = Token::Type::BraceClose })) { // } if (!consumeSpecific(Token { .type = Token::Type::BraceClose })) { // }
@ -201,7 +201,7 @@ ValuePtr Reader::readHashMap()
return nullptr; return nullptr;
} }
return hash_map; return makePtr<HashMap>(elements);
} }
ValuePtr Reader::readQuote() ValuePtr Reader::readQuote()

8
src/step6_file.cpp

@ -94,11 +94,9 @@ static auto installLambdas(EnvironmentPtr env) -> void
static auto makeArgv(EnvironmentPtr env, std::vector<std::string> arguments) -> void static auto makeArgv(EnvironmentPtr env, std::vector<std::string> arguments) -> void
{ {
size_t count = arguments.size(); size_t count = arguments.size();
auto nodes = ValueVector(count - 1); auto nodes = ValueVector();
if (count > 1) { for (size_t i = 1; i < count; ++i) {
for (size_t i = 1; i < count; ++i) { nodes.push_back(makePtr<String>(arguments[i]));
nodes.at(i) = makePtr<String>(arguments[i]);
}
} }
env->set("*ARGV*", makePtr<List>(nodes)); env->set("*ARGV*", makePtr<List>(nodes));
} }

8
src/step7_quote.cpp

@ -94,11 +94,9 @@ static auto installLambdas(EnvironmentPtr env) -> void
static auto makeArgv(EnvironmentPtr env, std::vector<std::string> arguments) -> void static auto makeArgv(EnvironmentPtr env, std::vector<std::string> arguments) -> void
{ {
size_t count = arguments.size(); size_t count = arguments.size();
auto nodes = ValueVector(count - 1); auto nodes = ValueVector();
if (count > 1) { for (size_t i = 1; i < count; ++i) {
for (size_t i = 1; i < count; ++i) { nodes.push_back(makePtr<String>(arguments[i]));
nodes.at(i) = makePtr<String>(arguments[i]);
}
} }
env->set("*ARGV*", makePtr<List>(nodes)); env->set("*ARGV*", makePtr<List>(nodes));
} }

8
src/step8_macros.cpp

@ -101,11 +101,9 @@ static auto installLambdas(EnvironmentPtr env) -> void
static auto makeArgv(EnvironmentPtr env, std::vector<std::string> arguments) -> void static auto makeArgv(EnvironmentPtr env, std::vector<std::string> arguments) -> void
{ {
size_t count = arguments.size(); size_t count = arguments.size();
auto nodes = ValueVector(count - 1); auto nodes = ValueVector();
if (count > 1) { for (size_t i = 1; i < count; ++i) {
for (size_t i = 1; i < count; ++i) { nodes.push_back(makePtr<String>(arguments[i]));
nodes.at(i) = makePtr<String>(arguments[i]);
}
} }
env->set("*ARGV*", makePtr<List>(nodes)); env->set("*ARGV*", makePtr<List>(nodes));
} }

8
src/step9_try.cpp

@ -101,11 +101,9 @@ static auto installLambdas(EnvironmentPtr env) -> void
static auto makeArgv(EnvironmentPtr env, std::vector<std::string> arguments) -> void static auto makeArgv(EnvironmentPtr env, std::vector<std::string> arguments) -> void
{ {
size_t count = arguments.size(); size_t count = arguments.size();
auto nodes = ValueVector(count - 1); auto nodes = ValueVector();
if (count > 1) { for (size_t i = 1; i < count; ++i) {
for (size_t i = 1; i < count; ++i) { nodes.push_back(makePtr<String>(arguments[i]));
nodes.at(i) = makePtr<String>(arguments[i]);
}
} }
env->set("*ARGV*", makePtr<List>(nodes)); env->set("*ARGV*", makePtr<List>(nodes));
} }

8
src/stepA_mal.cpp

@ -113,11 +113,9 @@ static auto installLambdas(EnvironmentPtr env) -> void
static auto makeArgv(EnvironmentPtr env, std::vector<std::string> arguments) -> void static auto makeArgv(EnvironmentPtr env, std::vector<std::string> arguments) -> void
{ {
size_t count = arguments.size(); size_t count = arguments.size();
auto nodes = ValueVector(count - 1); auto nodes = ValueVector();
if (count > 1) { for (size_t i = 1; i < count; ++i) {
for (size_t i = 1; i < count; ++i) { nodes.push_back(makePtr<String>(arguments[i]));
nodes.at(i) = makePtr<String>(arguments[i]);
}
} }
env->set("*ARGV*", makePtr<List>(nodes)); env->set("*ARGV*", makePtr<List>(nodes));
} }

Loading…
Cancel
Save