You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
1.8 KiB
93 lines
1.8 KiB
/* |
|
* Copyright (C) 2023 Riyyi |
|
* |
|
* SPDX-License-Identifier: MIT |
|
*/ |
|
|
|
#include <algorithm> // std::copy |
|
#include <memory> // std::static_pointer_cast |
|
|
|
#include "blaze/ast.h" |
|
#include "blaze/env/environment.h" |
|
#include "blaze/env/macro.h" |
|
#include "blaze/forward.h" |
|
#include "blaze/repl.h" |
|
#include "blaze/util.h" |
|
|
|
namespace blaze { |
|
|
|
void Environment::loadMutable() |
|
{ |
|
// (atom 1) |
|
ADD_FUNCTION( |
|
"atom", |
|
"", |
|
"", |
|
{ |
|
CHECK_ARG_COUNT_IS("atom", SIZE(), 1); |
|
|
|
return makePtr<Atom>(*begin); |
|
}); |
|
|
|
// (deref myatom) |
|
ADD_FUNCTION( |
|
"deref", |
|
"", |
|
"", |
|
{ |
|
CHECK_ARG_COUNT_IS("deref", SIZE(), 1); |
|
|
|
VALUE_CAST(atom, Atom, (*begin)); |
|
|
|
return atom->deref(); |
|
}); |
|
|
|
// (reset! myatom 2) |
|
ADD_FUNCTION( |
|
"reset!", |
|
"", |
|
"", |
|
{ |
|
CHECK_ARG_COUNT_IS("reset!", SIZE(), 2); |
|
|
|
VALUE_CAST(atom, Atom, (*begin)); |
|
auto value = *(begin + 1); |
|
|
|
atom->reset(value); |
|
|
|
return value; |
|
}); |
|
|
|
// (swap! myatom (fn* [x y] (+ 1 x y)) 2) -> (deref (def! myatom (atom ((fn* [x y] (+ 1 x y)) (deref myatom) 2)))) |
|
ADD_FUNCTION( |
|
"swap!", |
|
"", |
|
"", |
|
{ |
|
CHECK_ARG_COUNT_AT_LEAST("swap!", SIZE(), 2); |
|
|
|
VALUE_CAST(atom, Atom, (*begin)); |
|
|
|
VALUE_CAST(callable, Callable, (*(begin + 1))); |
|
|
|
// Remove atom and function from the argument list, add atom value |
|
begin += 2; |
|
auto arguments = ValueVector(SIZE() + 1); |
|
arguments[0] = atom->deref(); |
|
std::copy(begin, end, arguments.begin() + 1); |
|
|
|
ValuePtr value = nullptr; |
|
if (is<Function>(callable.get())) { |
|
auto function = std::static_pointer_cast<Function>(callable)->function(); |
|
value = function(arguments.begin(), arguments.end()); |
|
} |
|
else { |
|
auto lambda = std::static_pointer_cast<Lambda>(callable); |
|
value = Repl::eval(lambda->body(), Environment::create(lambda, std::move(arguments))); |
|
} |
|
|
|
return atom->reset(value); |
|
}); |
|
} |
|
|
|
} // namespace blaze
|
|
|