summaryrefslogtreecommitdiff
path: root/starts/meaning-vm/level-0/baseref.hpp
blob: 205b42244362c05bd143ac71bb836294b42c8553 (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
#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();
		}
	}

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

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

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

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

}
}