-
Notifications
You must be signed in to change notification settings - Fork 1
/
Scope.h
96 lines (83 loc) · 2.47 KB
/
Scope.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#pragma once
#include "Forward.h"
#include "HashTable.h"
#include "ImmutableString.h"
template <typename _Tysc>
struct Scopelet
{
HashTable< ImmutableString, _Tysc> table;
_Tysc* at(const ImmutableString& key) { return &(table.at(key));}
};
template <typename _Ty>
class Scope {
/*
This class can serve two functionalities, whose implementations are merged into one powerful class.
1. This can be (but isn't) used by the Parser to keep track of the Object or Function tree system, to be later collapsed into Program::definedFunctions and Program::definedObjTypes, if it wants
2. This can be (and is) used by the Interpreter to keep track of scoped variables (so, Values), allowing for their access and dismissal as it enters and exits various Scopes.
*/
std::deque<Scopelet<_Ty>> stack;
std::string top_scope_name; // Usually the name of the function which owns this scope.
public:
Scope(const std::string& sc)
:top_scope_name(sc)
{
stack.push_front(Scopelet<_Ty>());
}
_Ty* get(const ImmutableString& name)
{
//std::cout << "The front of the stack is now " << stack.front()->scopename << "!\n";
for (auto it = stack.begin(); it != stack.end(); it++)
{
_Ty* maybe = (*it).table.lazy_at(name);
if (maybe)
return maybe;
}
return nullptr; // Give up.
}
_Ty* get_front(const ImmutableString& name)
{
return stack.front().table.lazy_at(name);
}
_Ty* get_back(const ImmutableString& name)
{
return stack.back().table.lazy_at(name);
}
ImmutableString get_back_name() const
{
return top_scope_name;
}
void set(const ImmutableString& name, const _Ty& t)
{
(stack.front().table[name]) = t;
}
bool Override(const ImmutableString& name, _Ty& t)
{
for (auto it = stack.begin(); it != stack.end(); it++)
{
Scopelet<_Ty>& sc = *it;
//std::cout << "Looking at scope " << sc.scopename << "...\n";
if (sc.table.contains(name))
{
sc.table[name] = t;
return true;
}
}
return false;
}
void push() // Add a new stack layer
{
//std::cout << "Creating new scope layer called " << name << "...\n";
stack.push_front(Scopelet<_Ty>());
//std::cout << "The front of the stack is now " << stack.front()->scopename << "!\n";
}
void pop() // Delete the newest stack layer
{
//std::cout << "Stack layer " << stack.front()->scopename << " popped!\n";
if (stack.empty()) // Attempting to delete the base stack
{
std::cout << "WEIRD_ERROR: Attempted to delete backmost stack of a Scope!";
return; // fails.
}
stack.pop_front();
}
};