File: Handle.h

package info (click to toggle)
storm-lang 0.7.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,028 kB
  • sloc: ansic: 261,471; cpp: 140,432; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (217 lines) | stat: -rw-r--r-- 6,020 bytes parent folder | download | duplicates (3)
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#pragma once
#include "Utils/Templates.h"
#include "Object.h"

namespace storm {
	STORM_PKG(core.lang); // TODO: Other package? If so, update Compiler/RefHandle as well.

	/**
	 * A type handle, ie. information about a type without actually knowing exactly which type it
	 * is. Used to make it easier to implement templates usable in Storm from C++.
	 *
	 * Note: we can always move objects with a memcpy (as this is what the gc does all the time). We
	 * may, however, need to make copies using the copy constructor.
	 *
	 * Note: all function pointers are exported to the GC, as they may point to generated code (which is gc:d).
	 */
	class Handle : public Object {
		STORM_CLASS;
	public:
		STORM_CTOR Handle();

		// Size of the type.
		size_t size;

		// GcType for arrays of the type.
		const GcType *gcArrayType;

		// Is this type hashed based off its pointer somehow?
		bool locationHash;

		// Copy constructor. Acts as an assignment (ie. never deeply copies heap-allocated types).
		typedef void (*CopyFn)(void *dest, const void *src);
		UNKNOWN(PTR_GC) CopyFn copyFn;

		// Safe copy. Falls back on memcpy.
		inline void safeCopy(void *dest, const void *src) const {
			if (copyFn)
				(*copyFn)(dest, src);
			else
				memcpy(dest, src, size);
		}

		// Destructor. May be null.
		typedef void (*DestroyFn)(void *obj);
		UNKNOWN(PTR_GC) DestroyFn destroyFn;

		// Helper for safe destroying. Zeroes out any used memory so that we do not retain any
		// unneeded objects.
		inline void safeDestroy(void *obj) const {
			if (destroyFn)
				(*destroyFn)(obj);
			memset(obj, 0, size);
		}

		// Deep copy an instance of this type. May be null.
		typedef void (*DeepCopyFn)(void *obj, CloneEnv *env);
		UNKNOWN(PTR_GC) DeepCopyFn deepCopyFn;

		// ToS implementation (always present).
		typedef void (*ToSFn)(const void *obj, StrBuf *to);
		UNKNOWN(PTR_GC) ToSFn toSFn;

		// Hash function.
		typedef Nat (*HashFn)(const void *obj);
		UNKNOWN(PTR_GC) HashFn hashFn;

		// Equality function.
		typedef Bool (*EqualFn)(const void *a, const void *b);
		UNKNOWN(PTR_GC) EqualFn equalFn;

		// Less-than function.
		typedef Bool (*LessFn)(const void *a, const void *b);
		UNKNOWN(PTR_GC) LessFn lessFn;

		// Helper for equality comparison. Works if one of 'equalFn' and 'lessFn' is implemented.
		inline Bool hasEqual() const {
			return equalFn || lessFn;
		}
		inline Bool equal(const void *a, const void *b) const {
			if (equalFn) {
				// Use '==' if possible.
				return (*equalFn)(a, b);
			} else {
				// Otherwise, we can use '!(a < b) && !(b < a)' instead.
				return !(*lessFn)(a, b) && !(*lessFn)(a, b);
			}
		}

		// Acquire information about serializing this type. May be null.
		typedef SerializedType *(*SerializedTypeFn)();
		UNKNOWN(PTR_GC) SerializedTypeFn serializedTypeFn;
	};

	/**
	 * Get limited type info for a type (may be pointer or reference).
	 */
	template <class T>
	struct StormInfo {
		// Type id in Storm for this module.
		static Nat id() {
			return BaseType<T>::Type::stormTypeId;
		}

		// Get a handle for T.
		static const Handle &handle(Engine &e) {
			return BaseType<T>::Type::stormHandle(e);
		}

		// Get the type for T.
		static Type *type(Engine &e) {
			return BaseType<T>::Type::stormType(e);
		}
	};

	template <>
	struct StormInfo<void> {
		static Nat id() {
			return -1;
		}

		static const Handle &handle(Engine &e) {
			return runtime::voidHandle(e);
		}

		static Type *type(Engine &e) {
			return null;
		}
	};

	// Specializations for built-in types. Generates StormInfo for them too, see Storm.h.
	STORM_PKG(core);

	/**
	 * Boolean value. Contains either 'true' or 'false'.
	 */
	STORM_PRIMITIVE(Bool, createBool);

	/**
	 * Unsigned 8-bit number.
	 *
	 * Can store values from 0 to 255. Operations yielding values that are out of range are
	 * truncated, effectively performing computations modulo 256.
	 */
	STORM_PRIMITIVE(Byte, createByte);

	/**
	 * Signed 32-bit number (using two's complement).
	 *
	 * Can store values from -2 147 843 648 to 2 147 843 647. Languages may assume that overflow
	 * does not occur (as C++ does). Currently, no language in Storm does this.
	 */
	STORM_PRIMITIVE(Int, createInt);

	/**
	 * Unsigned 32-bit number.
	 *
	 * Can store values from 0 to 4 294 967 295. Used as the standard type to describe quantities
	 * that are known to be positive, such as sizes of arrays etc. It is safe to assume that
	 * operations on this type are performed modulo 2^32.
	 */
	STORM_PRIMITIVE(Nat, createNat);

	/**
	 * Signed 64-bit number (using two's complement).
	 *
	 * Can store values from -9 223 372 036 854 775 808 to 9 223 372 036 854 775 807. Languages may
	 * assume that overflow does not occur (as C++ does). Currently, no language in Storm does this.
	 *
	 * Prefer to use Int over Long if possible, as the former is more efficient on most systems (32
	 * bit platforms requires additional instructions to manipulate 64 bit numbers, and 32-bit
	 * instructions are shorter on x86-64).
	 */
	STORM_PRIMITIVE(Long, createLong);

	/**
	 * Unsigned 64-bit number.
	 *
	 * Can store values from 0 to 18 446 744 073 709 551 615. It is safe to assume that operations
	 * on this type are performed modulo 2^64.
	 *
	 * Prefer to use Nat over Word if possible, as the former is more efficient on most systems (32
	 * bit platforms requires additional instructions to manipulate 64 bit numbers, and 32-bit
	 * instructions are shorter on x86-64).
	 */
	STORM_PRIMITIVE(Word, createWord);

	/**
	 * 32-bit floating point number.
	 */
	STORM_PRIMITIVE(Float, createFloat);

	/**
	 * 64-bit floating point number.
	 */
	STORM_PRIMITIVE(Double, createDouble);


	/**
	 * Helper for figuring out how to create objects.
	 */
	template <class T>
	struct CreateFn {
		// Create a value.
		static void fn(void *to, Engine &e) {
			new (Place(to)) T();
		}
	};

	template <class T>
	struct CreateFn<T *> {
		// Create an object or an actor.
		static void fn(void *to, Engine &e) {
			T **o = (T **)to;
			*o = new (e) T();
		}
	};
}