Don't pass an env to apply
[jackhill/mal.git] / cpp / Environment.cpp
CommitLineData
179e8eaf
ST
1#include "Environment.h"
2#include "Types.h"
3
4#include <algorithm>
5
dc9b184b
ST
6malEnv::malEnv(malEnvPtr outer)
7: m_outer(outer)
8{
9 TRACE_ENV("Creating malEnv %p, outer=%p\n", this, m_outer.ptr());
10}
11
ad0fc149
ST
12malEnv::malEnv(malEnvPtr outer, const StringVec& bindings,
13 malValueIter argsBegin, malValueIter argsEnd)
14: m_outer(outer)
15{
16 TRACE_ENV("Creating malEnv %p, outer=%p\n", this, m_outer.ptr());
17 int n = bindings.size();
18 auto it = argsBegin;
19 for (int i = 0; i < n; i++) {
20 if (bindings[i] == "&") {
0997015d 21 MAL_CHECK(i == n - 2, "There must be one parameter after the &");
ad0fc149
ST
22
23 set(bindings[n-1], mal::list(it, argsEnd));
24 return;
25 }
0997015d 26 MAL_CHECK(it != argsEnd, "Not enough parameters");
ad0fc149
ST
27 set(bindings[i], *it);
28 ++it;
29 }
0997015d 30 MAL_CHECK(it == argsEnd, "Too many parameters");
ad0fc149
ST
31}
32
dc9b184b
ST
33malEnv::~malEnv()
34{
35 TRACE_ENV("Destroying malEnv %p, outer=%p\n", this, m_outer.ptr());
36}
37
38malEnvPtr malEnv::find(const String& symbol)
39{
40 for (malEnvPtr env = this; env; env = env->m_outer) {
41 if (env->m_map.find(symbol) != env->m_map.end()) {
42 return env;
43 }
44 }
45 return NULL;
46}
47
179e8eaf
ST
48malValuePtr malEnv::get(const String& symbol)
49{
dc9b184b
ST
50 for (malEnvPtr env = this; env; env = env->m_outer) {
51 auto it = env->m_map.find(symbol);
52 if (it != env->m_map.end()) {
53 return it->second;
54 }
179e8eaf 55 }
0997015d 56 MAL_FAIL("'%s' not found", symbol.c_str());
179e8eaf
ST
57}
58
59malValuePtr malEnv::set(const String& symbol, malValuePtr value)
60{
61 m_map[symbol] = value;
62 return value;
63}
ad50bab2
ST
64
65malEnvPtr malEnv::getRoot()
66{
67 // Work our way down the the global environment.
68 for (malEnvPtr env = this; ; env = env->m_outer) {
69 if (!env->m_outer) {
70 return env;
71 }
72 }
73}