Browse Source

Env: Add more core functions

master
Riyyi 1 year ago
parent
commit
93af6151fa
  1. 114
      src/functions.cpp

114
src/functions.cpp

@ -410,7 +410,6 @@ ADD_FUNCTION(
return makePtr<String>(file.data());
});
ADD_FUNCTION(
"eval",
{
@ -422,6 +421,119 @@ ADD_FUNCTION(
return eval(nodes.front(), nullptr);
});
// (atom 1)
ADD_FUNCTION(
"atom",
{
if (nodes.size() != 1) {
Error::the().add(format("wrong number of arguments: atom, {}", nodes.size()));
return nullptr;
}
return makePtr<Atom>(nodes.front());
});
// (atom? myatom 2 "foo")
ADD_FUNCTION(
"atom?",
{
bool result = true;
if (nodes.size() == 0) {
result = false;
}
for (auto node : nodes) {
if (!is<Atom>(node.get())) {
result = false;
break;
}
}
return makePtr<Value>((result) ? Value::True : Value::False);
});
// (deref myatom)
ADD_FUNCTION(
"deref",
{
if (nodes.size() != 1) {
Error::the().add(format("wrong number of arguments: deref, {}", nodes.size()));
return nullptr;
}
if (!is<Atom>(nodes.front().get())) {
Error::the().add(format("wrong argument type: atom, '{}'", nodes.front()));
return nullptr;
}
return std::static_pointer_cast<Atom>(nodes.front())->deref();
});
// (reset! myatom 2)
ADD_FUNCTION(
"reset!",
{
if (nodes.size() != 2) {
Error::the().add(format("wrong number of arguments: reset!, {}", nodes.size()));
return nullptr;
}
if (!is<Atom>(nodes.front().get())) {
Error::the().add(format("wrong argument type: atom, '{}'", nodes.front()));
return nullptr;
}
auto atom = std::static_pointer_cast<Atom>(*nodes.begin());
auto value = *std::next(nodes.begin());
atom->reset(value);
return value;
});
// (swap! myatom (fn* [x] (+ 1 x)))
ADD_FUNCTION(
"swap!",
{
if (nodes.size() < 2) {
Error::the().add(format("wrong number of arguments: reset!, {}", nodes.size()));
return nullptr;
}
auto first_argument = *nodes.begin();
auto second_argument = *std::next(nodes.begin());
if (!is<Atom>(first_argument.get())) {
Error::the().add(format("wrong argument type: atom, '{}'", first_argument));
return nullptr;
}
if (!is<Callable>(second_argument.get())) {
Error::the().add(format("wrong argument type: function, '{}'", second_argument));
return nullptr;
}
auto atom = std::static_pointer_cast<Atom>(first_argument);
// Remove atom and function from the argument list, add atom value
nodes.pop_front();
nodes.pop_front();
nodes.push_front(atom->deref());
ASTNodePtr value = nullptr;
if (is<Function>(second_argument.get())) {
auto function = std::static_pointer_cast<Function>(second_argument)->function();
value = function(nodes);
}
else {
auto lambda = std::static_pointer_cast<Lambda>(second_argument);
value = eval(lambda->body(), Environment::create(lambda, nodes));
}
return atom->reset(value);
});
// -----------------------------------------
void installFunctions(EnvironmentPtr env)

Loading…
Cancel
Save