@quenk/potoo 4.0.7 → 4.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/actor/address.js.map +1 -1
- package/lib/actor/api.d.ts +2 -2
- package/lib/actor/api.js.map +1 -1
- package/lib/actor/framework/index.js +2 -2
- package/lib/actor/framework/index.js.map +1 -1
- package/lib/actor/framework/process.d.ts +3 -2
- package/lib/actor/framework/process.js.map +1 -1
- package/lib/actor/framework/resident.d.ts +5 -3
- package/lib/actor/framework/resident.js +2 -0
- package/lib/actor/framework/resident.js.map +1 -1
- package/lib/actor/index.js.map +1 -1
- package/lib/actor/system/vm/allocator/index.js.map +1 -1
- package/lib/actor/system/vm/allocator/map.js +7 -4
- package/lib/actor/system/vm/allocator/map.js.map +1 -1
- package/lib/actor/system/vm/conf.js.map +1 -1
- package/lib/actor/system/vm/event/dispatcher.d.ts +31 -12
- package/lib/actor/system/vm/event/dispatcher.js +72 -20
- package/lib/actor/system/vm/event/dispatcher.js.map +1 -1
- package/lib/actor/system/vm/event/index.js.map +1 -1
- package/lib/actor/system/vm/frame.js.map +1 -1
- package/lib/actor/system/vm/group.js.map +1 -1
- package/lib/actor/system/vm/index.js +2 -2
- package/lib/actor/system/vm/index.js.map +1 -1
- package/lib/actor/system/vm/log/index.js.map +1 -1
- package/lib/actor/system/vm/log/writer.js.map +1 -1
- package/lib/actor/system/vm/object/foreign.js.map +1 -1
- package/lib/actor/system/vm/object/index.js.map +1 -1
- package/lib/actor/system/vm/object/list.js.map +1 -1
- package/lib/actor/system/vm/op/actor.js.map +1 -1
- package/lib/actor/system/vm/op/base.js.map +1 -1
- package/lib/actor/system/vm/op/index.js.map +1 -1
- package/lib/actor/system/vm/op/object.js.map +1 -1
- package/lib/actor/system/vm/registry.js.map +1 -1
- package/lib/actor/system/vm/runtime/error.js.map +1 -1
- package/lib/actor/system/vm/runtime.js.map +1 -1
- package/lib/actor/system/vm/scheduler.js.map +1 -1
- package/lib/actor/system/vm/script/index.js.map +1 -1
- package/lib/actor/system/vm/script/info.js.map +1 -1
- package/lib/actor/system/vm/strategy/error.js.map +1 -1
- package/lib/actor/system/vm/thread/factory.js.map +1 -1
- package/lib/actor/system/vm/thread/index.js.map +1 -1
- package/lib/actor/system/vm/thread/process.js.map +1 -1
- package/lib/actor/system/vm/thread/shared/index.js.map +1 -1
- package/lib/actor/system/vm/thread/shared/js.d.ts +2 -2
- package/lib/actor/system/vm/thread/shared/js.js +3 -3
- package/lib/actor/system/vm/thread/shared/js.js.map +1 -1
- package/lib/actor/system/vm/type.js.map +1 -1
- package/lib/actor/template.d.ts +20 -0
- package/lib/actor/template.js +17 -1
- package/lib/actor/template.js.map +1 -1
- package/package.json +11 -9
- package/lib/actor/address.ts +0 -90
- package/lib/actor/api.ts +0 -57
- package/lib/actor/framework/index.ts +0 -1
- package/lib/actor/framework/process.ts +0 -87
- package/lib/actor/framework/resident.ts +0 -90
- package/lib/actor/index.ts +0 -35
- package/lib/actor/system/vm/allocator/index.ts +0 -43
- package/lib/actor/system/vm/allocator/map.ts +0 -256
- package/lib/actor/system/vm/conf.ts +0 -33
- package/lib/actor/system/vm/event/dispatcher.ts +0 -85
- package/lib/actor/system/vm/event/index.ts +0 -143
- package/lib/actor/system/vm/frame.ts +0 -484
- package/lib/actor/system/vm/group.ts +0 -46
- package/lib/actor/system/vm/index.ts +0 -230
- package/lib/actor/system/vm/log/index.ts +0 -73
- package/lib/actor/system/vm/log/writer.ts +0 -96
- package/lib/actor/system/vm/object/foreign.ts +0 -10
- package/lib/actor/system/vm/object/index.ts +0 -4
- package/lib/actor/system/vm/object/list.ts +0 -8
- package/lib/actor/system/vm/op/actor.ts +0 -126
- package/lib/actor/system/vm/op/base.ts +0 -243
- package/lib/actor/system/vm/op/index.ts +0 -388
- package/lib/actor/system/vm/op/object.ts +0 -81
- package/lib/actor/system/vm/registry.ts +0 -223
- package/lib/actor/system/vm/runtime/error.ts +0 -248
- package/lib/actor/system/vm/runtime.ts +0 -31
- package/lib/actor/system/vm/scheduler.ts +0 -108
- package/lib/actor/system/vm/script/index.ts +0 -64
- package/lib/actor/system/vm/script/info.ts +0 -359
- package/lib/actor/system/vm/strategy/error.ts +0 -88
- package/lib/actor/system/vm/thread/factory.ts +0 -29
- package/lib/actor/system/vm/thread/index.ts +0 -29
- package/lib/actor/system/vm/thread/process.ts +0 -134
- package/lib/actor/system/vm/thread/shared/index.ts +0 -50
- package/lib/actor/system/vm/thread/shared/js.ts +0 -151
- package/lib/actor/system/vm/type.ts +0 -115
- package/lib/actor/template.ts +0 -170
- package/lib/tsconfig.json +0 -22
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import { Maybe } from '@quenk/noni/lib/data/maybe';
|
|
2
|
-
|
|
3
|
-
import { PTObject } from './object';
|
|
4
|
-
import {
|
|
5
|
-
PTString,
|
|
6
|
-
PTValue,
|
|
7
|
-
TYPE_LIST,
|
|
8
|
-
TYPE_MASK,
|
|
9
|
-
TYPE_OBJECT,
|
|
10
|
-
TYPE_STRING
|
|
11
|
-
} from './type';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* RegistryType indicates the type of the registry.
|
|
15
|
-
*/
|
|
16
|
-
export enum RegistryType {
|
|
17
|
-
string = TYPE_STRING,
|
|
18
|
-
object = TYPE_OBJECT
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* RefCount is a number indicating how many Frames are aware of an object.
|
|
23
|
-
*
|
|
24
|
-
* A zero value indicates the object is dead and can be removed from the
|
|
25
|
-
* registry.
|
|
26
|
-
*/
|
|
27
|
-
export type RefCount = number;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* RegistryAddress is the address of an object in the registry.
|
|
31
|
-
*/
|
|
32
|
-
export type RegistryAddress = number;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* RegistrySet is a container for all the registries used by the VM.
|
|
36
|
-
*/
|
|
37
|
-
export class RegistrySet {
|
|
38
|
-
constructor(
|
|
39
|
-
public strings = new Registry<PTString>(RegistryType.string),
|
|
40
|
-
public objects = new Registry<PTObject>(RegistryType.object)
|
|
41
|
-
) {}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* isRegistryAddress tests whether a number is a valid registry address.
|
|
45
|
-
*
|
|
46
|
-
* This does not test whether the address can be dereferenced.
|
|
47
|
-
*/
|
|
48
|
-
isRegistryAddress(addr: number): boolean {
|
|
49
|
-
let type = addr & TYPE_MASK;
|
|
50
|
-
return (
|
|
51
|
-
type === TYPE_STRING || type === TYPE_OBJECT || type === TYPE_LIST
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* addString to the registry.
|
|
57
|
-
*/
|
|
58
|
-
addString(value: PTString): RegistryAddress {
|
|
59
|
-
return this.strings.add(value);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* addObject to the registry.
|
|
64
|
-
*/
|
|
65
|
-
addObject(value: PTObject): RegistryAddress {
|
|
66
|
-
return this.objects.add(value);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* getString returns a string from the registry given its address.
|
|
71
|
-
*/
|
|
72
|
-
getString(addr: RegistryAddress): Maybe<PTString> {
|
|
73
|
-
return this.strings.get(addr);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* getObject returns an object from the registry given its address.
|
|
78
|
-
*/
|
|
79
|
-
getObject(addr: RegistryAddress): Maybe<PTObject> {
|
|
80
|
-
return this.objects.get(addr);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* increment the ref count for a registry address.
|
|
85
|
-
*/
|
|
86
|
-
increment(addr: RegistryAddress): void {
|
|
87
|
-
switch (addr & TYPE_MASK) {
|
|
88
|
-
case TYPE_STRING:
|
|
89
|
-
this.strings.increment(addr);
|
|
90
|
-
break;
|
|
91
|
-
case TYPE_OBJECT:
|
|
92
|
-
case TYPE_LIST:
|
|
93
|
-
this.objects.increment(addr);
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* decrement the ref count for a registry address.
|
|
100
|
-
*/
|
|
101
|
-
decrement(addr: RegistryAddress): void {
|
|
102
|
-
switch (addr & TYPE_MASK) {
|
|
103
|
-
case TYPE_STRING:
|
|
104
|
-
this.strings.decrement(addr);
|
|
105
|
-
break;
|
|
106
|
-
case TYPE_OBJECT:
|
|
107
|
-
case TYPE_LIST:
|
|
108
|
-
this.objects.decrement(addr);
|
|
109
|
-
break;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* deref an object from the registry.
|
|
115
|
-
*
|
|
116
|
-
* This attempts to retrieve an object from the relevant registry given its
|
|
117
|
-
* address.
|
|
118
|
-
*/
|
|
119
|
-
deref(addr: RegistryAddress): Maybe<PTValue> {
|
|
120
|
-
switch (addr & TYPE_MASK) {
|
|
121
|
-
case TYPE_STRING:
|
|
122
|
-
return this.strings.get(addr);
|
|
123
|
-
case TYPE_OBJECT:
|
|
124
|
-
case TYPE_LIST:
|
|
125
|
-
return this.objects.get(addr);
|
|
126
|
-
default:
|
|
127
|
-
return Maybe.nothing();
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* flush all the internal registries.
|
|
133
|
-
*/
|
|
134
|
-
flush(): void {
|
|
135
|
-
this.strings.flush();
|
|
136
|
-
this.objects.flush();
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Registry serves as a container for objects used by the VM.
|
|
142
|
-
*
|
|
143
|
-
* This interface allows for a naive reference counting system for objects
|
|
144
|
-
* created by the VM and foreign objects the VM is aware of. It does not yet
|
|
145
|
-
* take cyclical references into account.
|
|
146
|
-
*
|
|
147
|
-
* The tracking here is needed so that we know when an object can be removed
|
|
148
|
-
* from the container and allow the JS engine's own garbage collection to get
|
|
149
|
-
* rid of it.
|
|
150
|
-
*
|
|
151
|
-
* Each instance handles one specific type of data indicated by the "type"
|
|
152
|
-
* parameter. This value is used when generating the address of the object that
|
|
153
|
-
* can be used for its retrieval.
|
|
154
|
-
*/
|
|
155
|
-
export class Registry<T> {
|
|
156
|
-
constructor(
|
|
157
|
-
public type: RegistryType,
|
|
158
|
-
public values: Map<RegistryAddress, T> = new Map(),
|
|
159
|
-
public refCounts: Map<RegistryAddress, RefCount> = new Map(),
|
|
160
|
-
public deadValues: RegistryAddress[] = []
|
|
161
|
-
) {}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* add an object to the registry.
|
|
165
|
-
*
|
|
166
|
-
* Each time an object is added to the registry we initialize its counter
|
|
167
|
-
* to 0. The idea is for the VM opcodes to increment/decrement this value
|
|
168
|
-
* as needed.
|
|
169
|
-
*/
|
|
170
|
-
add(value: T): RegistryAddress {
|
|
171
|
-
let addr = (this.values.size + 1) | this.type;
|
|
172
|
-
this.values.set(addr, value);
|
|
173
|
-
this.refCounts.set(addr, 0);
|
|
174
|
-
return addr;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* get an object from the registry.
|
|
179
|
-
*/
|
|
180
|
-
get(addr: RegistryAddress): Maybe<T> {
|
|
181
|
-
return Maybe.fromNullable(this.values.get(addr));
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* increment the ref count for an object.
|
|
186
|
-
*
|
|
187
|
-
* This should be done anytime an object is used in a new Frame.
|
|
188
|
-
*/
|
|
189
|
-
increment(addr: RegistryAddress): void {
|
|
190
|
-
if (this.values.has(addr))
|
|
191
|
-
this.refCounts.set(addr, (this.refCounts.get(addr) || 0) + 1);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* decrement the ref count for an object.
|
|
196
|
-
*
|
|
197
|
-
* This should be done whenever a frame that "knows" about the object is
|
|
198
|
-
* popped off the stack. When the ref count reaches 0, the object is
|
|
199
|
-
* considered dead and will be marked for removal.
|
|
200
|
-
*/
|
|
201
|
-
decrement(addr: RegistryAddress): void {
|
|
202
|
-
if (!this.values.has(addr)) return;
|
|
203
|
-
let oldCount = this.refCounts.get(addr) || 0;
|
|
204
|
-
let newCount = oldCount <= 0 ? 0 : oldCount - 1;
|
|
205
|
-
this.refCounts.set(addr, newCount);
|
|
206
|
-
if (newCount === 0) this.deadValues.push(addr);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* flush all dead objects from the registry.
|
|
211
|
-
*
|
|
212
|
-
* When called, this method will remove all objects marked as dead from the
|
|
213
|
-
* registry. Determining the right time to call this method is left up to the
|
|
214
|
-
* VM.
|
|
215
|
-
*/
|
|
216
|
-
flush(): void {
|
|
217
|
-
this.deadValues.forEach(addr => {
|
|
218
|
-
this.values.delete(addr);
|
|
219
|
-
this.refCounts.delete(addr);
|
|
220
|
-
});
|
|
221
|
-
this.deadValues = [];
|
|
222
|
-
}
|
|
223
|
-
}
|
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
import { Err } from '@quenk/noni/lib/control/err';
|
|
2
|
-
|
|
3
|
-
import { Address, ADDRESS_RESTRICTED } from '../../../address';
|
|
4
|
-
import { TypeInfo } from '../script/info';
|
|
5
|
-
import { DATA_MAX_SAFE_UINT32 } from '../frame';
|
|
6
|
-
import { Thread } from '../thread';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* ErrorClass
|
|
10
|
-
*/
|
|
11
|
-
export class ErrorClass {
|
|
12
|
-
constructor(public message: string) {}
|
|
13
|
-
|
|
14
|
-
stack?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* InvalidIdError indicates an id used in a template is invalid.
|
|
19
|
-
*/
|
|
20
|
-
export class InvalidIdErr extends ErrorClass {
|
|
21
|
-
constructor(public id: string) {
|
|
22
|
-
super(
|
|
23
|
-
`The id "${id} must not contain` +
|
|
24
|
-
`${ADDRESS_RESTRICTED} or be an empty string!`
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* UnknownParentAddressErr indicates the parent address used for
|
|
31
|
-
* spawning an actor does not exist.
|
|
32
|
-
*/
|
|
33
|
-
export class UnknownParentAddressErr extends ErrorClass {
|
|
34
|
-
constructor(public address: Address) {
|
|
35
|
-
super(`The parent address "${address}" is not part of the system!`);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* DuplicateAddressErr indicates the address of a freshly spawned
|
|
41
|
-
* actor is already in use.
|
|
42
|
-
*/
|
|
43
|
-
export class DuplicateAddressErr extends ErrorClass {
|
|
44
|
-
constructor(public address: Address) {
|
|
45
|
-
super(`Duplicate address "${address}" detected!`);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* NullTemplatePointerErr occurs when a reference to a template
|
|
51
|
-
* does not exist in the templates table.
|
|
52
|
-
*/
|
|
53
|
-
export class NullTemplatePointerErr extends ErrorClass {
|
|
54
|
-
constructor(public index: number) {
|
|
55
|
-
super(`The index "${index}" does not exist in the Template table!`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export class NullFunctionPointerErr extends ErrorClass {
|
|
60
|
-
constructor(public index: number) {
|
|
61
|
-
super(`The index "${index}" does not exist in the function table!`);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* JumpOutOfBoundsErr
|
|
67
|
-
*/
|
|
68
|
-
export class JumpOutOfBoundsErr extends ErrorClass {
|
|
69
|
-
constructor(public location: number, public size: number) {
|
|
70
|
-
super(`Cannot jump to location "${location}"! Max location: ${size}!`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* NullPointerErr
|
|
76
|
-
*/
|
|
77
|
-
export class NullPointerErr extends ErrorClass {
|
|
78
|
-
constructor(public data: number) {
|
|
79
|
-
super(`Value: [${data.toString(16)}]`);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* UnexpectedDataType
|
|
85
|
-
*/
|
|
86
|
-
export class UnexpectedDataType extends ErrorClass {
|
|
87
|
-
constructor(public expected: number, public got: number) {
|
|
88
|
-
super(
|
|
89
|
-
`Expected: ${expected.toString(16)}, ` +
|
|
90
|
-
`Received: ${got.toString(16)}`
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* IllegalStopErr
|
|
97
|
-
*/
|
|
98
|
-
export class IllegalStopErr extends ErrorClass {
|
|
99
|
-
constructor(public parent: string, public child: string) {
|
|
100
|
-
super(`The actor at address "${parent}" can not kill "${child}"!`);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* NoReceiverErr
|
|
106
|
-
*/
|
|
107
|
-
export class NoReceiverErr extends ErrorClass {
|
|
108
|
-
constructor(public actor: string) {
|
|
109
|
-
super(`Actor ${actor} tried to read a message without a receiver!`);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* NoMailboxErr
|
|
115
|
-
*/
|
|
116
|
-
export class NoMailboxErr extends ErrorClass {
|
|
117
|
-
constructor(public actor: string) {
|
|
118
|
-
super(`Actor ${actor} has no mailbox!`);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* EmptyMailboxErr
|
|
124
|
-
*/
|
|
125
|
-
export class EmptyMailboxErr extends ErrorClass {
|
|
126
|
-
constructor() {
|
|
127
|
-
super('Mailbox empty.');
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* UnknownAddressErr
|
|
133
|
-
*/
|
|
134
|
-
export class UnknownAddressErr extends ErrorClass {
|
|
135
|
-
constructor(public actor: string) {
|
|
136
|
-
super(`The system has no actor for address "${actor}"!`);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* MissingSymbolErr
|
|
142
|
-
*/
|
|
143
|
-
export class MissingSymbolErr extends ErrorClass {
|
|
144
|
-
constructor(public index: number) {
|
|
145
|
-
super(`Cannot locate symbol at index 0x${index.toString(16)}`);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* IntegerOverflowErr
|
|
151
|
-
*/
|
|
152
|
-
export class IntegerOverflowErr extends ErrorClass {
|
|
153
|
-
constructor() {
|
|
154
|
-
super(`DATA_MAX_SAFE_UINT32=${DATA_MAX_SAFE_UINT32}`);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* StackEmptyErr
|
|
160
|
-
*/
|
|
161
|
-
export class StackEmptyErr extends ErrorClass {
|
|
162
|
-
constructor() {
|
|
163
|
-
super('Stack is empty.');
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* InvalidPropertyIndex
|
|
169
|
-
*/
|
|
170
|
-
export class InvalidPropertyIndex extends ErrorClass {
|
|
171
|
-
constructor(public cons: TypeInfo, public idx: number) {
|
|
172
|
-
super(`Constructor: ${cons.name}, index: ${idx}`);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* MissingInfoErr
|
|
178
|
-
*/
|
|
179
|
-
export class MissingInfoErr extends ErrorClass {
|
|
180
|
-
constructor(public idx: number) {
|
|
181
|
-
super(`No info object index: ${idx}!`);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* InvalidConstructorErr
|
|
187
|
-
*/
|
|
188
|
-
export class InvalidConstructorErr extends ErrorClass {
|
|
189
|
-
constructor(public name: string) {
|
|
190
|
-
super(`Named object "${name}" cannot be used as a constructor!`);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* InvalidFunctionErr
|
|
196
|
-
*/
|
|
197
|
-
export class InvalidFunctionErr extends ErrorClass {
|
|
198
|
-
constructor(public name: string) {
|
|
199
|
-
super(`Named object "${name}" cannot be used as a function!`);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* UnknownInstanceErr
|
|
205
|
-
*/
|
|
206
|
-
export class UnknownInstanceErr extends ErrorClass {
|
|
207
|
-
constructor(public instance: object) {
|
|
208
|
-
super(
|
|
209
|
-
'The instance provided with constructor "' +
|
|
210
|
-
(instance ? instance.constructor.name || instance : instance) +
|
|
211
|
-
'" is not in the system!'
|
|
212
|
-
);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* UnknownFuncErr
|
|
218
|
-
*/
|
|
219
|
-
export class UnknownFunErr extends ErrorClass {
|
|
220
|
-
constructor(public name: string) {
|
|
221
|
-
super(`The function '${name}' does not exist and cannot be executed!`);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* InvalidThreadErr
|
|
227
|
-
*/
|
|
228
|
-
export class InvalidThreadErr extends ErrorClass {
|
|
229
|
-
constructor(public thread: Thread) {
|
|
230
|
-
super('Thread is no longer part of the system or is invalid!');
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* ActorTerminatedErr
|
|
236
|
-
*
|
|
237
|
-
* Note: This signals that an actor has been removed involuntarily due to an
|
|
238
|
-
* unhandled error.
|
|
239
|
-
*/
|
|
240
|
-
export class ActorTerminatedErr extends Error {
|
|
241
|
-
constructor(
|
|
242
|
-
public actor: Address,
|
|
243
|
-
public origin: Address,
|
|
244
|
-
public originalError: Err
|
|
245
|
-
) {
|
|
246
|
-
super('ActorTerminated');
|
|
247
|
-
}
|
|
248
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { Api } from '../../api';
|
|
2
|
-
import { Actor } from '../..';
|
|
3
|
-
import { VM } from '.';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Runtime is the interface used by the outside world (JS) to execute code
|
|
7
|
-
* in the VM.
|
|
8
|
-
*/
|
|
9
|
-
export interface Runtime extends Actor, Api {
|
|
10
|
-
/**
|
|
11
|
-
* vm the Runtime belongs to.
|
|
12
|
-
*/
|
|
13
|
-
vm: VM;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* isValid indicates whether the Runtime is still valid.
|
|
17
|
-
*
|
|
18
|
-
* A Runtime is invalid if it has encountered an error or is no longer
|
|
19
|
-
* part of the system.
|
|
20
|
-
*/
|
|
21
|
-
isValid(): boolean;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* watch an asynchronous task, feeding any errors into the VM's
|
|
25
|
-
* error handling machinery.
|
|
26
|
-
*
|
|
27
|
-
* This method exists to allow async operations to trigger the error
|
|
28
|
-
* handling machinery built into the VM.
|
|
29
|
-
*/
|
|
30
|
-
watch<T>(task: () => Promise<T>): Promise<void>;
|
|
31
|
-
}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { SharedThread, ThreadState } from './thread/shared';
|
|
2
|
-
|
|
3
|
-
export const ERR_THREAD_DEQUEUED = 'ERR_THREAD_DEQUEUED';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* PendingTask tuple type.
|
|
7
|
-
*/
|
|
8
|
-
export type PendingTask = [SharedThread, (err?: Error) => void];
|
|
9
|
-
|
|
10
|
-
export class Task {
|
|
11
|
-
constructor(
|
|
12
|
-
public thread: SharedThread,
|
|
13
|
-
public abort: (err: Error) => void,
|
|
14
|
-
public exec: () => Promise<void>
|
|
15
|
-
) {}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Scheduler provides a mechanism for cooperative execution between Thread
|
|
20
|
-
* instances within the VM.
|
|
21
|
-
*
|
|
22
|
-
* Each Thread enqueues a Task to be executed each time it has work to do.
|
|
23
|
-
* The Scheduler.run() method will execute each of these tasks in a round-robin
|
|
24
|
-
* fashion until the queue is empty or no Threads are in the IDLE state.
|
|
25
|
-
*
|
|
26
|
-
* In prior versions, Threads executed code at will which made it possible
|
|
27
|
-
* for a single actor's state to be mutated while a previous tasks still executed
|
|
28
|
-
* (when an actor sends a message to itself for example).
|
|
29
|
-
*
|
|
30
|
-
* This led to errors and bugs that were hard to track down. By using scheduling
|
|
31
|
-
* execution we ensure threads do not preempt themselves.
|
|
32
|
-
*/
|
|
33
|
-
export class Scheduler {
|
|
34
|
-
constructor(public queue: Task[] = [], public isRunning = false) {}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* postTask a Task for future execution.
|
|
38
|
-
* @param task - The Task to post.
|
|
39
|
-
* @param preempt - If true, the task will be executed before any other
|
|
40
|
-
* tasks in the queue belonging to the Thread.
|
|
41
|
-
*/
|
|
42
|
-
postTask(task: Task, preempt = false) {
|
|
43
|
-
if (preempt) {
|
|
44
|
-
let idx = this.queue.findIndex(
|
|
45
|
-
({ thread }) => thread === task.thread
|
|
46
|
-
);
|
|
47
|
-
if (idx != -1) {
|
|
48
|
-
this.queue.splice(idx, 0, task);
|
|
49
|
-
} else {
|
|
50
|
-
this.queue.push(task);
|
|
51
|
-
}
|
|
52
|
-
} else {
|
|
53
|
-
this.queue.push(task);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
this.run();
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* removeTasks for a Thread.
|
|
61
|
-
*
|
|
62
|
-
* The Tasks will be terminated with an ERR_THREAD_DEQUEUED error.
|
|
63
|
-
*/
|
|
64
|
-
removeTasks(thread: SharedThread) {
|
|
65
|
-
this.queue = this.queue.filter(task => {
|
|
66
|
-
if (task.thread != thread) return true;
|
|
67
|
-
// TODO: dispatch event? callback into thread?
|
|
68
|
-
task.abort(new Error(ERR_THREAD_DEQUEUED));
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* run queued pending tasks for idle threads.
|
|
74
|
-
*
|
|
75
|
-
* This method only executes if the scheduler is not already running. It
|
|
76
|
-
* does not wait for tasks to be completed before moving on to the next
|
|
77
|
-
* however once a thread is not in the idle state no other tasks will
|
|
78
|
-
* be executed for it.
|
|
79
|
-
*/
|
|
80
|
-
run() {
|
|
81
|
-
if (this.isRunning) return;
|
|
82
|
-
|
|
83
|
-
this.isRunning = true;
|
|
84
|
-
|
|
85
|
-
let idx;
|
|
86
|
-
while (
|
|
87
|
-
(idx = this.queue.findIndex(
|
|
88
|
-
task => task.thread.state === ThreadState.IDLE
|
|
89
|
-
)) !== -1
|
|
90
|
-
) {
|
|
91
|
-
let task = this.queue.splice(idx, 1)[0];
|
|
92
|
-
|
|
93
|
-
task.thread.state = ThreadState.RUNNING;
|
|
94
|
-
|
|
95
|
-
// TODO: disatch event
|
|
96
|
-
task.exec()
|
|
97
|
-
.then(() => {
|
|
98
|
-
if (task.thread.state === ThreadState.RUNNING)
|
|
99
|
-
task.thread.state = ThreadState.IDLE;
|
|
100
|
-
})
|
|
101
|
-
.catch(err => {
|
|
102
|
-
task.abort(err);
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
this.isRunning = false;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { Either, left, right } from '@quenk/noni/lib/data/either';
|
|
2
|
-
import { Err } from '@quenk/noni/lib/control/error';
|
|
3
|
-
|
|
4
|
-
import { MissingInfoErr } from '../runtime/error';
|
|
5
|
-
import { PTNumber, PTString } from '../type';
|
|
6
|
-
import { Instruction } from '../op';
|
|
7
|
-
import { Info } from './info';
|
|
8
|
-
|
|
9
|
-
export const CONSTANTS_INDEX_NUMBER = 0;
|
|
10
|
-
export const CONSTANTS_INDEX_STRING = 1;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Constants is a tuple of immutable values available to a
|
|
14
|
-
* Script at runtime.
|
|
15
|
-
*/
|
|
16
|
-
export type Constants = [PTNumber[], PTString[]];
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Script contains the code and supporting information of an actor used by
|
|
20
|
-
* the VM for code execution.
|
|
21
|
-
*/
|
|
22
|
-
export interface Script {
|
|
23
|
-
/**
|
|
24
|
-
* name of the Script.
|
|
25
|
-
* This is an absolute path or an id for dynamically generated scripts.
|
|
26
|
-
*/
|
|
27
|
-
name: string;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* constants pool for the actor where certain references are resolved from.
|
|
31
|
-
*/
|
|
32
|
-
constants: Constants;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* info is a table of various named structures within the script source.
|
|
36
|
-
*/
|
|
37
|
-
info: Info[];
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* code is the actual instructions the VM will execute.
|
|
41
|
-
*/
|
|
42
|
-
code: Instruction[];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* PScript provides a constructor for creating Scripts.
|
|
47
|
-
*/
|
|
48
|
-
export class PScript implements Script {
|
|
49
|
-
constructor(
|
|
50
|
-
public name: string,
|
|
51
|
-
public constants: Constants = [[], []],
|
|
52
|
-
public info: Info[] = [],
|
|
53
|
-
public code: Instruction[] = []
|
|
54
|
-
) {}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* getInfo retrivies an Info object from the info section.
|
|
59
|
-
*/
|
|
60
|
-
export const getInfo = (s: Script, idx: number): Either<Err, Info> => {
|
|
61
|
-
if (s.info[idx] == null) return left(new MissingInfoErr(idx));
|
|
62
|
-
|
|
63
|
-
return right(s.info[idx]);
|
|
64
|
-
};
|