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