summaryrefslogtreecommitdiff
path: root/starts/meaning-vm/level-0/baseref.hpp
blob: b6e98e84fb359afd574534711857d22ed47e743d (plain)
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#pragma once

#include "common.hpp"
#include "errors.hpp"
#include "memorystore.hpp"

#include <map>
#include <vector>

namespace intellect {
namespace level0 {

template <typename ref>
class baseref
{
public:
	struct array; struct links_t;
	baseref(concept *p)
	: p(p)
	{
		if (p == 0) {
			throw null_reference();
		}
	}

	baseref & operator=(concept *p)
	{
		self.p = p;
		return self;
	}

	void link(ref const & type, ref const & target) { p->link(type.p, target.p); }
	void unlink(ref const & type, ref const & target) { p->unlink(type.p, target.p); }
	void unlink(ref const & type) { p->unlink(type.p); }

	bool linked(ref const & type) const { return p->linked(type.p); }
	bool linked(ref const & type, ref const & target) const { return p->linked(type.p, target.p); }

	ref get(ref const & type) const { return p->get(type.p); }
	void set(ref const & type, ref const & target) { p->set(type.p, target.p); }

	array getAll(ref const & type) const;
	links_t links() const;

	template <typename... Ref>
	ref link(Ref... refspack)
	{
		std::initializer_list<ref> refs{refspack...};
		for (auto it = refs.begin(); it != refs.end();) {
			ref type = *it++;
			ref target = *it++;
			link(type, target);
		}
		return ptr();
	}

	template <typename T>
	T& vget(ref const & type) const { return p->vget<T>(type.p); }
	template <typename T>
	void vset(ref const & type, T const & v) { p->set(type.p, level0::alloc(self, v)); }

	template <typename T>
	T& val() { return p->val<T>(); }
	template <typename T>
	void val(T const & v) { p->val<T>(v); }
	bool hasval() { return p->hasval(); }
	template <typename T>
	bool hasvalof() { return p->hasvalof<T>(); }

	operator concept*() const { return p; }
	concept*& ptr() { return p; }
	concept* const & ptr() const { return p; }

	operator level0::ref const &() const { return *reinterpret_cast<level0::ref*>(this); }
	operator level1::ref const &() const { return *reinterpret_cast<level1::ref*>(this); }
	operator level2::ref const &() const { return *reinterpret_cast<level2::ref*>(this); }
	operator level3::ref const &() const { return *reinterpret_cast<level3::ref*>(this); }
	operator level4::ref const &() const { return *reinterpret_cast<level4::ref*>(this); }
	operator level5::ref const &() const { return *reinterpret_cast<level5::ref*>(this); }
	operator level6::ref const &() const { return *reinterpret_cast<level6::ref*>(this); }
	operator level7::ref const &() const { return *reinterpret_cast<level7::ref*>(this); }
	operator level8::ref const &() const { return *reinterpret_cast<level8::ref*>(this); }
	operator level9::ref const &() const { return *reinterpret_cast<level9::ref*>(this); }

	operator level0::ref &() { return *reinterpret_cast<level0::ref*>(this); }
	operator level1::ref &() { return *reinterpret_cast<level1::ref*>(this); }
	operator level2::ref &() { return *reinterpret_cast<level2::ref*>(this); }
	operator level3::ref &() { return *reinterpret_cast<level3::ref*>(this); }
	operator level4::ref &() { return *reinterpret_cast<level4::ref*>(this); }
	operator level5::ref &() { return *reinterpret_cast<level5::ref*>(this); }
	operator level6::ref &() { return *reinterpret_cast<level6::ref*>(this); }
	operator level7::ref &() { return *reinterpret_cast<level7::ref*>(this); }
	operator level8::ref &() { return *reinterpret_cast<level8::ref*>(this); }
	operator level9::ref &() { return *reinterpret_cast<level9::ref*>(this); }

	bool operator==(ref const & other) const { return self.p == other.p; }
	bool operator!=(ref const & other) const { return self.p != other.p; }
	bool operator<(ref const & other) const { return self.p < other.p; }

	bool crucial() { return self.p->crucial(); }
	bool crucial(ref type, ref target) { return self.p->crucial(type.p, target.p); }

	void setcrucial() { self.p->setcrucial(); }
	void setcrucial(ref type, ref target) { self.p->setcrucial(type.p, target.p); }

protected:
	concept * p;

private:
	template <typename val, typename It>
	struct mutated_it
	{
		mutated_it(It const & it) : it(it) { }

		using mutit = mutated_it<val, It>;

		mutit & operator++() { ++ self.it; return self; }
		mutit operator++(int i) { return self.it.operator++(i); }
		mutit & operator--() { -- self.it; return self; }
		mutit operator--(int i) { return self.it.operator--(i); }
		bool operator==(mutit const & other) const { return self.it == other.it; }
		bool operator!=(mutit const & other) const { return self.it != other.it; }

		val & operator*() { return *(val*)&self.it.operator*(); }
		val * operator->() { return (val*)self.it.operator->(); }

		It & underlying() { return it; }

	private:
		It it;
	};

public:
	struct array
	{
		using iterator = mutated_it<ref,typename concept::array::iterator>;
		iterator begin() { return array.begin(); }
		iterator end() { return array.end(); }
	
		typename concept::array array;
	};

	struct links_t
	{
		using iterator = mutated_it<std::pair<ref,ref>,typename decltype(concept::links)::iterator>;
		iterator begin() { return links.begin(); }
		iterator end() { return links.end(); }

		decltype(concept::links) & links;
	};

	void unlink(typename links_t::iterator & it) { p->unlink(it.underlying()); }
	bool crucial(typename links_t::iterator it) { return self.p->crucial(it.underlying()); }
	void setcrucial(typename links_t::iterator it) { self.p->setcrucial(it.underlying()); }
};

template <typename ref>
typename baseref<ref>::array baseref<ref>::getAll(ref const & type) const
{
	return {p->getAll(type.p)};
}
template <typename ref>
typename baseref<ref>::links_t baseref<ref>::links() const
{
	return {p->links};
}

}
}