summaryrefslogtreecommitdiff
path: root/starts/meaning-vm/level-0/baseref.hpp
blob: fbb7a289fc2946206757e402de11d3623e2805f4 (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
#pragma once

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

#include <map>
#include <vector>

namespace intellect {
namespace level0 {

template <typename ref>
class baseref
{
	struct array; struct links_t;
public:
	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(v)); }

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

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

	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; }

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); }
		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->(); }

	private:
		It it;
	};

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

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

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

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};
}

}
}