File: Value.h

package info (click to toggle)
storm-lang 0.7.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,004 kB
  • sloc: ansic: 261,462; cpp: 140,405; 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 (184 lines) | stat: -rw-r--r-- 6,454 bytes parent folder | download | duplicates (2)
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
#pragma once
#include "Core/EnginePtr.h"
#include "Code/Operand.h"
#include "Code/TypeDesc.h"
#include "NamedFlags.h"

namespace storm {
	STORM_PKG(core.lang);

	/**
	 * Represents a variable that contains a value of a particular type.
	 *
	 * As such, a value is a pointer to a type alongside whether the variable contains the variable
	 * directly, or if it is a reference to the variable. This is mostly relevant for function
	 * parameters, but is often useful for local variables as well.
	 */
	class Value {
		STORM_VALUE;
	public:
		// Create 'void'.
		STORM_CTOR Value();

		// Create from a specific type. Never a reference.
		STORM_CAST_CTOR Value(MAYBE(Type *) type);

		// Create from a type and if it is to be a reference.
		STORM_CTOR Value(Type *type, Bool ref);

		// Deep copy.
		void deepCopy(CloneEnv *env);

		// The type stored. If `null`, the value refers to `void` and the value in `ref` is meaningless.
		MAYBE(Type*) type;

		// Is this value representing a reference to `type`?
		Bool ref;

		// Any/empty. Empty means 'void'.
		Bool STORM_FN any() { return type != null; }
		Bool STORM_FN empty() { return type == null; }

		// Return a copy that is a reference.
		Value STORM_FN asRef() const;
		Value STORM_FN asRef(Bool ref) const;

		// Same type?
		Bool STORM_FN operator ==(Value o) const;
		Bool STORM_FN operator !=(Value o) const;

		// Output.
		void STORM_FN toS(StrBuf *to) const;

		// Check if a value of this type may refer to a value of type `x`. As the name implies, this
		// check is performed with references in mind. As such, this is used to determine if formal
		// parameters of a function matches actual parameters, or when figuring out if a (copy)
		// assignment should be allowed.
		//
		// Note: `void` is considered to be able to refer to all other types.
		//
		// Note: This definition is separate from storage. Since the size of derived value types
		// differ, it is not possible to store a derived type in a variable sized after the
		// super type (without slicing), even if the super type may refer to the derived type.
		//
		// Note: This function was previously named 'canStore', but was split due to to the possible
		// confusion with storage size.
		Bool STORM_FN mayReferTo(MAYBE(Type *) x) const;
		Bool STORM_FN mayReferTo(Value x) const;

		// See if it is possible to store a value of `x` inside a value of this type without any
		// conversions. Works like 'mayReferTo', except that value types use strict equality, and
		// `void` is not considered to be able to store any other types.
		Bool STORM_FN mayStore(MAYBE(Type *) x) const;
		Bool STORM_FN mayStore(Value x) const;

		// Does this value match another value according to NamedFlags? Works like 'mayReferTo',
		// but flags effect the outcome. Note that this relation is not reflexive. If no special
		// flags are set, then it is equivalent to 'mayReferTo'.
		Bool STORM_FN matches(Value v, NamedFlags flags) const;

		/**
		 * Code generation information.
		 */

		// Should this type be returned in a register? Note: we count `void` as being returned in a register.
		Bool STORM_FN returnInReg() const;

		// Does this value refer to a value-type? Either `isValue` or `isObject` returns true for non-void types.
		Bool STORM_FN isValue() const;

		// Does this value refer to a heap-allocated type (i.e. a class or an actor)? Either
		// `isValue` or `isObject` returns true for non-void types.
		Bool STORM_FN isObject() const;

		// Is this a class type?
		Bool STORM_FN isClass() const;

		// Is this an actor type?
		Bool STORM_FN isActor() const;

		// Is this a primitive type? e.g. int, float, etc. These do not need explicit construction
		// and can be stored in registers. Note: Object-types and references are not primitives in
		// this regard, as pointers generally need initialization. `void` is not considered a
		// primitive.
		Bool STORM_FN isPrimitive() const;

		// Can this type be manipulated by the CPU directly. This includes the primitive types, but
		// also reference types and object types. ASM types never have destructors. Does not
		// consider references to be AsmTypes, as they are expected to be handled at a different level.
		Bool STORM_FN isAsmType() const;

		// Is this some kind of pointer that may need garbage collection?
		Bool STORM_FN isPtr() const;

		// Return the size of this type. Respects by-reference semantics and the `ref` member. As
		// such, always return a pointer size for classes and actors.
		Size STORM_FN size() const;

		// Get type info for this type.
		BasicTypeInfo typeInfo() const;

		// Get a type description of this type.
		code::TypeDesc *desc(Engine &e) const ON(Compiler);

		/**
		 * Access to common member functions.
		 */

		// Get an Operand pointing to the copy constructor for this type. Only returns something
		// useful for value types, as other types can and shall be copied using an inline
		// mov-instruction.
		code::Operand STORM_FN copyCtor() const ON(Compiler);

		// Get an Operand pointing to the destructor for this type. May return Operand(), meaning no
		// destructor is needed.
		code::Operand STORM_FN destructor() const ON(Compiler);
	};

	// Get a description of this type.
	code::TypeDesc *STORM_FN desc(EnginePtr e, Value v) ON(Compiler);


	/**
	 * Compute the common denominator of two values so that
	 * it is possible to cast both 'a' and 'b' to the resulting
	 * type. In case 'a' and 'b' are unrelated, Value() - void
	 * is returned.
	 */
	Value STORM_FN common(Value a, Value b) ON(Compiler);

	// Create a this pointer for a type.
	Value STORM_FN thisPtr(Type *t) ON(Compiler);

	// Output.
	wostream &operator <<(wostream &to, const Value &v);

	// Generate a list of values.
#ifdef VISUAL_STUDIO
	// Uses a visual studio specific extension...
	Array<Value> *valList(Engine &e, Nat count, ...);
#elif defined(USE_VA_TEMPLATE)
	template <class... Val>
	void valListAdd(Array<Value> *to, const Value &first, const Val&... rest) {
		to->push(first);
		valListAdd(to, rest...);
	}

	inline void valListAdd(Array<Value> *to) {
		UNUSED(to);
	}

	template <class... Val>
	Array<Value> *valList(Engine &e, Nat count, const Val&... rest) {
		assert(sizeof...(rest) == count, L"'count' does not match the number of parameters passed to 'valList'.");
		Array<Value> *v = new (e) Array<Value>();
		v->reserve(count);

		valListAdd(v, rest...);

		return v;
	}
#else
#error "Can not implement 'valList'"
#endif
}