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
//
// EmojicodeAPI.h
// Emojicode
//
// Created by Theo Weidmann on 12.01.15.
// Copyright (c) 2015 Theo Weidmann. All rights reserved.
//
#ifndef EmojicodeAPI_h
#define EmojicodeAPI_h
#include "../EmojicodeShared.h"
#include <cstddef>
namespace Emojicode {
typedef unsigned char Byte;
typedef int_fast64_t EmojicodeInteger;
struct Class;
struct List;
struct Object;
class Thread;
extern Class *CL_STRING;
extern Class *CL_LIST;
extern Class *CL_DATA;
extern Class *CL_DICTIONARY;
extern Class *CL_CLOSURE;
extern Class *CL_ARRAY;
/// A one-Emojicode-word large value without type information.
union Value {
/// Returns an undefined Value
Value() {}
Value(bool raw) : raw(raw) {}
Value(EmojicodeInteger raw) : raw(raw) {}
Value(EmojicodeChar raw) : character(raw) {}
Value(Object *object) : object(object) {}
Value(Value *value) : value(value) {}
Value(double doubl) : doubl(doubl) {}
EmojicodeInteger raw;
EmojicodeChar character;
double doubl;
Object *object;
Class *klass;
Value *value;
void makeNothingness() { raw = T_NOTHINGNESS; }
void optionalSet(Value value) { raw = T_OPTIONAL_VALUE; this[1] = value; }
void storeError(EmojicodeInteger error) { raw = T_ERROR; this[1] = error; }
void setValueForError(Value value) { raw = T_OPTIONAL_VALUE; this[1] = value; }
};
struct Object {
union {
/// The class of the object
Class *klass;
/// Used by the Garbage Collector, do not change!
Object *newLocation;
};
/** The size of this object: the size of the Object struct and the value area. */
size_t size;
template <typename T>
inline T* val() {
#ifdef DEBUG
if (size == 0 && klass == nullptr) throw;
#endif
return reinterpret_cast<T*>(this + 1);
}
inline Value* variableDestination(EmojicodeInstruction index) {
#ifdef DEBUG
if (size == 0 && klass == nullptr) throw;
#endif
return reinterpret_cast<Value *>(reinterpret_cast<Byte *>(this) + sizeof(Object) + sizeof(Value) * index);
}
};
/// Used to store a value when the type of the value is not known at compile time.
struct Box {
Box(EmojicodeInteger type, Value value1) : type(type), value1(value1) {}
Box() {}
/// The type of the value stored in this box.
Value type;
Value value1;
Value value2;
Value value3;
/// Returns true if this Box contains Nothingness
bool isNothingness() const { return type.raw == T_NOTHINGNESS; }
/// Aborts the program if this Box contains Nothingness
void unwrapOptional() const;
/// Makes this Box contain Nothingness
void makeNothingness() { type.raw = T_NOTHINGNESS; }
void copySingleValue(EmojicodeInteger type, Value value) { this->type = type; value1 = value; }
void copy(Value *value) { *this = *reinterpret_cast<Box *>(value); }
void copyTo(Value *value) const { *reinterpret_cast<Box *>(value) = *this; }
};
#define STORAGE_BOX_VALUE_SIZE 4
// MARK: Callables
/** You can use this function to call a callable object. It’s internally Garbage-Collector safe. */
extern void executeCallableExtern(Object *callable, Value *args, size_t argsSize, Thread *thread, Value *destination);
// MARK: Primitive Objects
/**
* Allocates a new object for the given class.
* The @c value field will point to a value area as large as specified for the given class.
* @param klass The class of the object.
* @warning GC-invoking
*/
extern Object* newObject(Class *klass);
/**
* Multiplies @c items by @c itemSize and terminates the program with an error if an integer
* overflow occured.
*/
extern size_t sizeCalculationWithOverflowProtection(size_t items, size_t itemSize);
/**
* Allocates an array with a value area of the given size.
* @param size The size of the value area.
* @warning GC-invoking
*/
extern Object* newArray(size_t size);
/**
* Tries to resize the given array object to the given size and returns a pointer to the resized array.
* @param array An array object created by @c newArray.
* @param size The new size.
* @returns A pointer to the resized array.
* @warning GC-invoking
*/
extern Object* resizeArray(Object *array, size_t size, Thread *thread);
// MARK: Garbage Collection
/**
* Marks the object @c O pointed to by the pointer @c P to which @c of points.
* @warning This function will modify @c P to point to an exact copy of @c O after the function call.
*/
extern void mark(Object **of);
/**
* If the calling thread needs to be paused for the GC to run, this function will first
* unlock @c mutex if it is not a @c nullptr pointer, then block until the GC cycle is completed
* and finally try to acquire @c mutex. Otherwise no action is performed.
*
* You normally do not need to call this method from method or intializer implementations.
*/
extern void pauseForGC();
/**
* This function allows the GC to run even while the calling thread is not paused and working.
* You must ensure that @c disallowGCAndPauseIfNeeded is called at an appropriate time, but it must be
* called before the calling thread finishes.
*
* @warning Between the call to this function and @c disallowGCAndPauseIfNeeded you must not perform
* any allocations or other kind of GC-invoking operations.
*/
extern void allowGC();
/**
* See @c allowGC
*/
extern void disallowGCAndPauseIfNeeded();
typedef void (*FunctionFunctionPointer)(Thread *thread);
typedef void (*Marker)(Object *self);
#undef major
#undef minor
/// The version of a package. Must follow semantic versioning 2.0 http://semver.org
struct PackageVersion {
PackageVersion(uint16_t major, uint16_t minor) noexcept : major(major), minor(minor) {}
/** The major version */
uint16_t major;
/** The minor version */
uint16_t minor;
};
}
#define LinkingTable Emojicode::FunctionFunctionPointer linkingTable[] =
#endif /* EmojicodeAPI_h */