easycoder 250403.1__py2.py3-none-any.whl → 250404.1__py2.py3-none-any.whl
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.
Potentially problematic release.
This version of easycoder might be problematic. Click here for more details.
- easycoder/__init__.py +1 -1
- easycoder/ec_core.py +11 -5
- {easycoder-250403.1.dist-info → easycoder-250404.1.dist-info}/METADATA +15 -10
- {easycoder-250403.1.dist-info → easycoder-250404.1.dist-info}/RECORD +7 -9
- easycoder/__init__.sync-conflict-20250331-210244-M3XB3VD.py +0 -12
- easycoder/ec_core.sync-conflict-20250331-210238-M3XB3VD.py +0 -2564
- {easycoder-250403.1.dist-info → easycoder-250404.1.dist-info}/WHEEL +0 -0
- {easycoder-250403.1.dist-info → easycoder-250404.1.dist-info}/entry_points.txt +0 -0
- {easycoder-250403.1.dist-info → easycoder-250404.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,2564 +0,0 @@
|
|
|
1
|
-
import json, math, hashlib, threading, os, subprocess, sys, requests, time, numbers, base64, binascii
|
|
2
|
-
from psutil import Process
|
|
3
|
-
from datetime import datetime, timezone
|
|
4
|
-
from random import randrange
|
|
5
|
-
from .ec_classes import FatalError, RuntimeWarning, RuntimeError, AssertionError, Condition, Object
|
|
6
|
-
from .ec_handler import Handler
|
|
7
|
-
from .ec_timestamp import getTimestamp
|
|
8
|
-
|
|
9
|
-
class Core(Handler):
|
|
10
|
-
|
|
11
|
-
def __init__(self, compiler):
|
|
12
|
-
Handler.__init__(self, compiler)
|
|
13
|
-
self.encoding = 'utf-8'
|
|
14
|
-
|
|
15
|
-
def getName(self):
|
|
16
|
-
return 'core'
|
|
17
|
-
|
|
18
|
-
#############################################################################
|
|
19
|
-
# Keyword handlers
|
|
20
|
-
|
|
21
|
-
# Arithmetic add
|
|
22
|
-
# add {value} to {variable}[ giving {variable}]}
|
|
23
|
-
def k_add(self, command):
|
|
24
|
-
# Get the (first) value
|
|
25
|
-
command['value1'] = self.nextValue()
|
|
26
|
-
if self.nextToken() == 'to':
|
|
27
|
-
if self.nextIsSymbol():
|
|
28
|
-
symbolRecord = self.getSymbolRecord()
|
|
29
|
-
if symbolRecord['valueHolder']:
|
|
30
|
-
if self.peek() == 'giving':
|
|
31
|
-
# This variable must be treated as a second value
|
|
32
|
-
command['value2'] = self.getValue()
|
|
33
|
-
self.nextToken()
|
|
34
|
-
command['target'] = self.nextToken()
|
|
35
|
-
self.add(command)
|
|
36
|
-
return True
|
|
37
|
-
else:
|
|
38
|
-
# Here the variable is the target
|
|
39
|
-
command['target'] = self.getToken()
|
|
40
|
-
self.add(command)
|
|
41
|
-
return True
|
|
42
|
-
self.warning(f'Core.add: Expected value holder')
|
|
43
|
-
else:
|
|
44
|
-
# Here we have 2 values so 'giving' must come next
|
|
45
|
-
command['value2'] = self.getValue()
|
|
46
|
-
if self.nextToken() == 'giving':
|
|
47
|
-
command['target'] = self.nextToken()
|
|
48
|
-
self.add(command)
|
|
49
|
-
return True
|
|
50
|
-
self.warning(f'Core.add: Expected "giving"')
|
|
51
|
-
return False
|
|
52
|
-
|
|
53
|
-
def r_add(self, command):
|
|
54
|
-
value1 = command['value1']
|
|
55
|
-
try:
|
|
56
|
-
value2 = command['value2']
|
|
57
|
-
except:
|
|
58
|
-
value2 = None
|
|
59
|
-
target = self.getVariable(command['target'])
|
|
60
|
-
if not target['valueHolder']:
|
|
61
|
-
self.variableDoesNotHoldAValueError(target['name'])
|
|
62
|
-
targetValue = self.getSymbolValue(target)
|
|
63
|
-
if targetValue == None:
|
|
64
|
-
targetValue = {}
|
|
65
|
-
targetValue['content'] = 0
|
|
66
|
-
targetValue['type'] = 'int'
|
|
67
|
-
if value2:
|
|
68
|
-
v1 = int(self.getRuntimeValue(value1))
|
|
69
|
-
v2 = int(self.getRuntimeValue(value2))
|
|
70
|
-
targetValue['content'] = v1 + v2
|
|
71
|
-
else:
|
|
72
|
-
# if targetValue['type'] != 'int' and targetValue['content'] != None:
|
|
73
|
-
# self.nonNumericValueError()
|
|
74
|
-
v = self.getRuntimeValue(targetValue)
|
|
75
|
-
v = int(v)
|
|
76
|
-
v1 = int(self.getRuntimeValue(value1))
|
|
77
|
-
if v1 == None:
|
|
78
|
-
v1 = 0
|
|
79
|
-
targetValue['content'] = v + v1
|
|
80
|
-
self.putSymbolValue(target, targetValue)
|
|
81
|
-
return self.nextPC()
|
|
82
|
-
|
|
83
|
-
# Append a value to an array
|
|
84
|
-
# append {value} to {array}
|
|
85
|
-
def k_append(self, command):
|
|
86
|
-
command['value'] = self.nextValue()
|
|
87
|
-
if self.nextIs('to'):
|
|
88
|
-
if self.nextIsSymbol():
|
|
89
|
-
symbolRecord = self.getSymbolRecord()
|
|
90
|
-
if symbolRecord['valueHolder']:
|
|
91
|
-
command['target'] = symbolRecord['name']
|
|
92
|
-
self.add(command)
|
|
93
|
-
return True
|
|
94
|
-
self.warning(f'Core.append: Variable "{symbolRecord["name"]}" does not hold a value')
|
|
95
|
-
return False
|
|
96
|
-
|
|
97
|
-
def r_append(self, command):
|
|
98
|
-
value = self.getRuntimeValue(command['value'])
|
|
99
|
-
target = self.getVariable(command['target'])
|
|
100
|
-
val = self.getSymbolValue(target)
|
|
101
|
-
content = val['content']
|
|
102
|
-
if content == '':
|
|
103
|
-
content = []
|
|
104
|
-
content.append(value)
|
|
105
|
-
val['content'] = content
|
|
106
|
-
self.putSymbolValue(target, val)
|
|
107
|
-
return self.nextPC()
|
|
108
|
-
|
|
109
|
-
# Define an array
|
|
110
|
-
def k_array(self, command):
|
|
111
|
-
return self.compileVariable(command)
|
|
112
|
-
|
|
113
|
-
def r_array(self, command):
|
|
114
|
-
return self.nextPC()
|
|
115
|
-
|
|
116
|
-
# Assertion
|
|
117
|
-
#assert {condition} [with {message}]
|
|
118
|
-
def k_assert(self, command):
|
|
119
|
-
command['test'] = self.nextCondition()
|
|
120
|
-
if self.peek() == 'with':
|
|
121
|
-
self.nextToken()
|
|
122
|
-
command['with'] = self.nextValue()
|
|
123
|
-
else:
|
|
124
|
-
command['with'] = None
|
|
125
|
-
self.addCommand(command)
|
|
126
|
-
return True
|
|
127
|
-
|
|
128
|
-
def r_assert(self, command):
|
|
129
|
-
test = self.program.condition.testCondition(command['test'])
|
|
130
|
-
if test:
|
|
131
|
-
return self.nextPC()
|
|
132
|
-
AssertionError(self.program, self.getRuntimeValue(command['with']))
|
|
133
|
-
|
|
134
|
-
# Begin a block
|
|
135
|
-
def k_begin(self, command):
|
|
136
|
-
if self.nextToken() == 'end':
|
|
137
|
-
cmd = {}
|
|
138
|
-
cmd['domain'] = 'core'
|
|
139
|
-
cmd['keyword'] = 'end'
|
|
140
|
-
cmd['debug'] = True
|
|
141
|
-
cmd['lino'] = command['lino']
|
|
142
|
-
self.addCommand(cmd)
|
|
143
|
-
return self.nextPC()
|
|
144
|
-
else:
|
|
145
|
-
return self.compileFromHere(['end'])
|
|
146
|
-
|
|
147
|
-
# Clear (set False)
|
|
148
|
-
# clear {variable}
|
|
149
|
-
def k_clear(self, command):
|
|
150
|
-
if self.nextIsSymbol():
|
|
151
|
-
target = self.getSymbolRecord()
|
|
152
|
-
if target['valueHolder']:
|
|
153
|
-
command['target'] = target['name']
|
|
154
|
-
self.add(command)
|
|
155
|
-
return True
|
|
156
|
-
return False
|
|
157
|
-
|
|
158
|
-
def r_clear(self, command):
|
|
159
|
-
target = self.getVariable(command['target'])
|
|
160
|
-
val = {}
|
|
161
|
-
val['type'] = 'boolean'
|
|
162
|
-
val['content'] = False
|
|
163
|
-
self.putSymbolValue(target, val)
|
|
164
|
-
# self.add(command)
|
|
165
|
-
return self.nextPC()
|
|
166
|
-
|
|
167
|
-
# Close a file
|
|
168
|
-
# close {file}
|
|
169
|
-
def k_close(self, command):
|
|
170
|
-
if self.nextIsSymbol():
|
|
171
|
-
fileRecord = self.getSymbolRecord()
|
|
172
|
-
if fileRecord['keyword'] == 'file':
|
|
173
|
-
command['file'] = fileRecord['name']
|
|
174
|
-
self.add(command)
|
|
175
|
-
return True
|
|
176
|
-
return False
|
|
177
|
-
|
|
178
|
-
def r_close(self, command):
|
|
179
|
-
fileRecord = self.getVariable(command['file'])
|
|
180
|
-
fileRecord['file'].close()
|
|
181
|
-
return self.nextPC()
|
|
182
|
-
|
|
183
|
-
#Create directory
|
|
184
|
-
# create directory {name}
|
|
185
|
-
def k_create(self, command):
|
|
186
|
-
if self.nextIs('directory'):
|
|
187
|
-
command['item'] = 'directory'
|
|
188
|
-
command['path'] = self.nextValue()
|
|
189
|
-
self.add(command)
|
|
190
|
-
return True
|
|
191
|
-
return False
|
|
192
|
-
|
|
193
|
-
def r_create(self, command):
|
|
194
|
-
if command['item'] == 'directory':
|
|
195
|
-
path = self.getRuntimeValue(command['path'])
|
|
196
|
-
if not os.path.exists(path):
|
|
197
|
-
os.makedirs(path)
|
|
198
|
-
return self.nextPC()
|
|
199
|
-
|
|
200
|
-
# Debug the script
|
|
201
|
-
def k_debug(self, command):
|
|
202
|
-
token = self.peek()
|
|
203
|
-
if token in ['step', 'stop', 'program', 'custom']:
|
|
204
|
-
command['mode'] = token
|
|
205
|
-
self.nextToken()
|
|
206
|
-
elif token == 'stack':
|
|
207
|
-
command['mode'] = self.nextToken()
|
|
208
|
-
if (self.nextIsSymbol()):
|
|
209
|
-
command['stack'] = self.getToken()
|
|
210
|
-
if self.peek() == 'as':
|
|
211
|
-
self.nextToken()
|
|
212
|
-
command['as'] = self.nextValue()
|
|
213
|
-
else:
|
|
214
|
-
command['as'] = 'Stack'
|
|
215
|
-
else:
|
|
216
|
-
return False
|
|
217
|
-
else:
|
|
218
|
-
command['mode'] = None
|
|
219
|
-
self.add(command)
|
|
220
|
-
return True
|
|
221
|
-
|
|
222
|
-
def r_debug(self, command):
|
|
223
|
-
if command['mode'] == 'step':
|
|
224
|
-
self.program.debugStep = True
|
|
225
|
-
elif command['mode'] == 'stop':
|
|
226
|
-
self.program.debugStep = False
|
|
227
|
-
elif command['mode'] == 'program':
|
|
228
|
-
for item in self.code:
|
|
229
|
-
print(json.dumps(item, indent = 2))
|
|
230
|
-
elif command['mode'] == 'stack':
|
|
231
|
-
stackRecord = self.getVariable(command['stack'])
|
|
232
|
-
value = self.getSymbolValue(stackRecord)
|
|
233
|
-
print(f'{self.getRuntimeValue(command["as"])}:',json.dumps(self.getSymbolValue(stackRecord), indent = 2))
|
|
234
|
-
elif command['mode'] == 'custom':
|
|
235
|
-
# Custom debugging code goes in here
|
|
236
|
-
record = self.getVariable('Script')
|
|
237
|
-
print('(Debug) Script:',record)
|
|
238
|
-
value = self.getRuntimeValue(record)
|
|
239
|
-
print('(Debug) Value:',value)
|
|
240
|
-
pass
|
|
241
|
-
return self.nextPC()
|
|
242
|
-
|
|
243
|
-
# Decrement a variable
|
|
244
|
-
# decrement {variable}
|
|
245
|
-
def k_decrement(self, command):
|
|
246
|
-
if self.nextIsSymbol():
|
|
247
|
-
symbolRecord = self.getSymbolRecord()
|
|
248
|
-
if symbolRecord['valueHolder']:
|
|
249
|
-
command['target'] = self.getToken()
|
|
250
|
-
self.add(command)
|
|
251
|
-
return True
|
|
252
|
-
self.warning(f'Core.decrement: Variable "{symbolRecord["name"]}" does not hold a value')
|
|
253
|
-
return False
|
|
254
|
-
|
|
255
|
-
def r_decrement(self, command):
|
|
256
|
-
return self.incdec(command, '-')
|
|
257
|
-
|
|
258
|
-
# Delete a file or a property
|
|
259
|
-
# delete {filename}
|
|
260
|
-
# delete property {value} of {variable}
|
|
261
|
-
def k_delete(self, command):
|
|
262
|
-
token = self.nextToken( )
|
|
263
|
-
if token == 'file':
|
|
264
|
-
command['type'] = 'file'
|
|
265
|
-
command['filename'] = self.nextValue()
|
|
266
|
-
self.add(command)
|
|
267
|
-
return True
|
|
268
|
-
elif token == 'property':
|
|
269
|
-
command['key'] = self.nextValue();
|
|
270
|
-
if self.nextIs('of'):
|
|
271
|
-
command['type'] = 'property'
|
|
272
|
-
command['var'] = self.nextToken()
|
|
273
|
-
self.add(command)
|
|
274
|
-
return True
|
|
275
|
-
else:
|
|
276
|
-
self.warning(f'Core.delete: "of" expected; got {self.getToken()}')
|
|
277
|
-
else:
|
|
278
|
-
self.warning(f'Core.delete: "file" or "property" expected; got {token}')
|
|
279
|
-
return False
|
|
280
|
-
|
|
281
|
-
def r_delete(self, command):
|
|
282
|
-
type = command['type']
|
|
283
|
-
if type == 'file':
|
|
284
|
-
filename = self.getRuntimeValue(command['filename'])
|
|
285
|
-
if os.path.isfile(filename):
|
|
286
|
-
print('Deleting',filename)
|
|
287
|
-
os.remove(filename)
|
|
288
|
-
elif type == 'property':
|
|
289
|
-
key = self.getRuntimeValue(command['key'])
|
|
290
|
-
symbolRecord = self.getVariable(command['var'])
|
|
291
|
-
value = self.getSymbolValue(symbolRecord)
|
|
292
|
-
content = value['content']
|
|
293
|
-
content.pop(key, None)
|
|
294
|
-
value['content'] = content
|
|
295
|
-
self.putSymbolValue(symbolRecord, value)
|
|
296
|
-
return self.nextPC()
|
|
297
|
-
|
|
298
|
-
# Arithmetic division
|
|
299
|
-
# divide {variable} by {value}[ giving {variable}]}
|
|
300
|
-
def k_divide(self, command):
|
|
301
|
-
# Get the (first) value
|
|
302
|
-
command['value1'] = self.nextValue()
|
|
303
|
-
if self.nextToken() == 'by':
|
|
304
|
-
command['value2'] = self.nextValue()
|
|
305
|
-
if self.peek() == 'giving':
|
|
306
|
-
self.nextToken()
|
|
307
|
-
if (self.nextIsSymbol()):
|
|
308
|
-
command['target'] = self.getToken()
|
|
309
|
-
self.add(command)
|
|
310
|
-
return True
|
|
311
|
-
FatalError(self.compiler, 'Symbol expected')
|
|
312
|
-
else:
|
|
313
|
-
# First value must be a variable
|
|
314
|
-
if command['value1']['type'] == 'symbol':
|
|
315
|
-
command['target'] = command['value1']['name']
|
|
316
|
-
self.add(command)
|
|
317
|
-
return True
|
|
318
|
-
FatalError(self.compiler, 'First value must be a variable')
|
|
319
|
-
return False
|
|
320
|
-
|
|
321
|
-
def r_divide(self, command):
|
|
322
|
-
value1 = command['value1']
|
|
323
|
-
try:
|
|
324
|
-
value2 = command['value2']
|
|
325
|
-
except:
|
|
326
|
-
value2 = None
|
|
327
|
-
target = self.getVariable(command['target'])
|
|
328
|
-
if not target['valueHolder']:
|
|
329
|
-
self.variableDoesNotHoldAValueError(target['name'])
|
|
330
|
-
return None
|
|
331
|
-
value = self.getSymbolValue(target)
|
|
332
|
-
if value == None:
|
|
333
|
-
value = {}
|
|
334
|
-
value['type'] = 'int'
|
|
335
|
-
if value2:
|
|
336
|
-
v1 = int(self.getRuntimeValue(value1))
|
|
337
|
-
v2 = int(self.getRuntimeValue(value2))
|
|
338
|
-
value['content'] = int(v1/v2)
|
|
339
|
-
else:
|
|
340
|
-
if value['type'] != 'int' and value['content'] != None:
|
|
341
|
-
self.nonNumericValueError(self.compiler, command['lino'])
|
|
342
|
-
v = int(self.getRuntimeValue(value))
|
|
343
|
-
v1 = int(self.getRuntimeValue(value1))
|
|
344
|
-
value['content'] = int(v/v1)
|
|
345
|
-
self.putSymbolValue(target, value)
|
|
346
|
-
return self.nextPC()
|
|
347
|
-
|
|
348
|
-
# Dummy command for testing
|
|
349
|
-
def k_dummy(self, command):
|
|
350
|
-
self.add(command)
|
|
351
|
-
return True
|
|
352
|
-
|
|
353
|
-
def r_dummy(self, command):
|
|
354
|
-
return self.nextPC()
|
|
355
|
-
|
|
356
|
-
# Match a begin
|
|
357
|
-
def k_end(self, command):
|
|
358
|
-
self.add(command)
|
|
359
|
-
return True
|
|
360
|
-
|
|
361
|
-
def r_end(self, command):
|
|
362
|
-
return self.nextPC()
|
|
363
|
-
|
|
364
|
-
# Exit the script
|
|
365
|
-
def k_exit(self, command):
|
|
366
|
-
self.add(command)
|
|
367
|
-
return True
|
|
368
|
-
|
|
369
|
-
def r_exit(self, command):
|
|
370
|
-
return -1
|
|
371
|
-
|
|
372
|
-
# Declare a file variable
|
|
373
|
-
def k_file(self, command):
|
|
374
|
-
return self.compileVariable(command, False)
|
|
375
|
-
|
|
376
|
-
def r_file(self, command):
|
|
377
|
-
return self.nextPC()
|
|
378
|
-
|
|
379
|
-
# Fork to a label
|
|
380
|
-
def k_fork(self, command):
|
|
381
|
-
if self.peek() == 'to':
|
|
382
|
-
self.nextToken()
|
|
383
|
-
command['fork'] = self.nextToken()
|
|
384
|
-
self.add(command)
|
|
385
|
-
return True
|
|
386
|
-
|
|
387
|
-
def r_fork(self, command):
|
|
388
|
-
next = self.nextPC()
|
|
389
|
-
label = command['fork']
|
|
390
|
-
try:
|
|
391
|
-
label = self.symbols[label + ':']
|
|
392
|
-
except:
|
|
393
|
-
RuntimeError(self.program, f'There is no label "{label + ":"}"')
|
|
394
|
-
return None
|
|
395
|
-
self.run(label)
|
|
396
|
-
return next
|
|
397
|
-
|
|
398
|
-
# Issue a REST GET request
|
|
399
|
-
# get {variable) from {url} [or {command}]
|
|
400
|
-
def k_get(self, command):
|
|
401
|
-
if self.nextIsSymbol():
|
|
402
|
-
symbolRecord = self.getSymbolRecord()
|
|
403
|
-
if symbolRecord['valueHolder']:
|
|
404
|
-
command['target'] = self.getToken()
|
|
405
|
-
else:
|
|
406
|
-
FatalError(self.compiler, f'Variable "{symbolRecord["name"]}" does not hold a value')
|
|
407
|
-
if self.nextIs('from'):
|
|
408
|
-
command['url'] = self.nextValue()
|
|
409
|
-
command['or'] = None
|
|
410
|
-
get = self.getPC()
|
|
411
|
-
if self.peek() == 'timeout':
|
|
412
|
-
self.nextToken()
|
|
413
|
-
command['timeout'] = self.nextValue()
|
|
414
|
-
else:
|
|
415
|
-
timeout = {}
|
|
416
|
-
timeout['type'] = 'int'
|
|
417
|
-
timeout['content'] = 5
|
|
418
|
-
command['timeout'] = timeout
|
|
419
|
-
self.addCommand(command)
|
|
420
|
-
if self.peek() == 'or':
|
|
421
|
-
self.nextToken()
|
|
422
|
-
self.nextToken()
|
|
423
|
-
# Add a 'goto' to skip the 'or'
|
|
424
|
-
cmd = {}
|
|
425
|
-
cmd['lino'] = command['lino']
|
|
426
|
-
cmd['domain'] = 'core'
|
|
427
|
-
cmd['keyword'] = 'gotoPC'
|
|
428
|
-
cmd['goto'] = 0
|
|
429
|
-
cmd['debug'] = False
|
|
430
|
-
skip = self.getPC()
|
|
431
|
-
self.addCommand(cmd)
|
|
432
|
-
# Process the 'or'
|
|
433
|
-
self.getCommandAt(get)['or'] = self.getPC()
|
|
434
|
-
self.compileOne()
|
|
435
|
-
# Fixup the skip
|
|
436
|
-
self.getCommandAt(skip)['goto'] = self.getPC()
|
|
437
|
-
return True
|
|
438
|
-
|
|
439
|
-
def r_get(self, command):
|
|
440
|
-
global errorCode, errorReason
|
|
441
|
-
retval = {}
|
|
442
|
-
retval['type'] = 'text'
|
|
443
|
-
retval['numeric'] = False
|
|
444
|
-
url = self.getRuntimeValue(command['url'])
|
|
445
|
-
target = self.getVariable(command['target'])
|
|
446
|
-
response = json.loads('{}')
|
|
447
|
-
try:
|
|
448
|
-
timeout = self.getRuntimeValue(command['timeout'])
|
|
449
|
-
response = requests.get(url, auth = ('user', 'pass'), timeout=timeout)
|
|
450
|
-
if response.status_code >= 400:
|
|
451
|
-
errorCode = response.status_code
|
|
452
|
-
errorReason = response.reason
|
|
453
|
-
if command['or'] != None:
|
|
454
|
-
return command['or']
|
|
455
|
-
else:
|
|
456
|
-
RuntimeError(self.program, f'Error code {errorCode}: {errorReason}')
|
|
457
|
-
except Exception as e:
|
|
458
|
-
errorReason = str(e)
|
|
459
|
-
if command['or'] != None:
|
|
460
|
-
return command['or']
|
|
461
|
-
else:
|
|
462
|
-
RuntimeError(self.program, f'Error: {errorReason}')
|
|
463
|
-
retval['content'] = response.text
|
|
464
|
-
self.program.putSymbolValue(target, retval)
|
|
465
|
-
return self.nextPC()
|
|
466
|
-
|
|
467
|
-
# Go to a label
|
|
468
|
-
def k_go(self, command):
|
|
469
|
-
if self.peek() == 'to':
|
|
470
|
-
self.nextToken()
|
|
471
|
-
return self.k_goto(command)
|
|
472
|
-
|
|
473
|
-
def k_goto(self, command):
|
|
474
|
-
command['keyword'] = 'goto'
|
|
475
|
-
command['goto'] = self.nextToken()
|
|
476
|
-
self.add(command)
|
|
477
|
-
return True
|
|
478
|
-
|
|
479
|
-
def r_goto(self, command):
|
|
480
|
-
label = f'{command["goto"]}:'
|
|
481
|
-
try:
|
|
482
|
-
if self.symbols[label]:
|
|
483
|
-
return self.symbols[label]
|
|
484
|
-
except:
|
|
485
|
-
pass
|
|
486
|
-
RuntimeError(self.program, f'There is no label "{label}"')
|
|
487
|
-
return None
|
|
488
|
-
|
|
489
|
-
def r_gotoPC(self, command):
|
|
490
|
-
return command['goto']
|
|
491
|
-
|
|
492
|
-
# Call a subroutine
|
|
493
|
-
def k_gosub(self, command):
|
|
494
|
-
if self.peek() == 'to':
|
|
495
|
-
self.nextToken()
|
|
496
|
-
command['gosub'] = self.nextToken()
|
|
497
|
-
self.add(command)
|
|
498
|
-
return True
|
|
499
|
-
|
|
500
|
-
def r_gosub(self, command):
|
|
501
|
-
label = command['gosub'] + ':'
|
|
502
|
-
address = self.symbols[label]
|
|
503
|
-
if address != None:
|
|
504
|
-
self.stack.append(self.nextPC())
|
|
505
|
-
return address
|
|
506
|
-
RuntimeError(self.program, f'There is no label "{label + ":"}"')
|
|
507
|
-
return None
|
|
508
|
-
|
|
509
|
-
# if <condition> <action> [else <action>]
|
|
510
|
-
def k_if(self, command):
|
|
511
|
-
command['condition'] = self.nextCondition()
|
|
512
|
-
self.addCommand(command)
|
|
513
|
-
self.nextToken()
|
|
514
|
-
pcElse = self.getPC()
|
|
515
|
-
cmd = {}
|
|
516
|
-
cmd['lino'] = command['lino']
|
|
517
|
-
cmd['domain'] = 'core'
|
|
518
|
-
cmd['keyword'] = 'gotoPC'
|
|
519
|
-
cmd['goto'] = 0
|
|
520
|
-
cmd['debug'] = False
|
|
521
|
-
self.addCommand(cmd)
|
|
522
|
-
# Get the 'then' code
|
|
523
|
-
self.compileOne()
|
|
524
|
-
if self.peek() == 'else':
|
|
525
|
-
self.nextToken()
|
|
526
|
-
# Add a 'goto' to skip the 'else'
|
|
527
|
-
pcNext = self.getPC()
|
|
528
|
-
cmd = {}
|
|
529
|
-
cmd['lino'] = command['lino']
|
|
530
|
-
cmd['domain'] = 'core'
|
|
531
|
-
cmd['keyword'] = 'gotoPC'
|
|
532
|
-
cmd['goto'] = 0
|
|
533
|
-
cmd['debug'] = False
|
|
534
|
-
self.addCommand(cmd)
|
|
535
|
-
# Fixup the link to the 'else' branch
|
|
536
|
-
self.getCommandAt(pcElse)['goto'] = self.getPC()
|
|
537
|
-
# Process the 'else' branch
|
|
538
|
-
self.nextToken()
|
|
539
|
-
self.compileOne()
|
|
540
|
-
# Fixup the pcNext 'goto'
|
|
541
|
-
self.getCommandAt(pcNext)['goto'] = self.getPC()
|
|
542
|
-
else:
|
|
543
|
-
# We're already at the next command
|
|
544
|
-
self.getCommandAt(pcElse)['goto'] = self.getPC()
|
|
545
|
-
return True
|
|
546
|
-
|
|
547
|
-
def r_if(self, command):
|
|
548
|
-
test = self.program.condition.testCondition(command['condition'])
|
|
549
|
-
if test:
|
|
550
|
-
self.program.pc += 2
|
|
551
|
-
else:
|
|
552
|
-
self.program.pc += 1
|
|
553
|
-
return self.program.pc
|
|
554
|
-
|
|
555
|
-
def k_import(self, command):
|
|
556
|
-
if self.peek() == 'plugin':
|
|
557
|
-
# Import a plugin
|
|
558
|
-
self.nextToken()
|
|
559
|
-
clazz = self.nextToken()
|
|
560
|
-
if self.nextIs('from'):
|
|
561
|
-
source = self.nextToken()
|
|
562
|
-
self.program.importPlugin(f'{source}:{clazz}')
|
|
563
|
-
return True
|
|
564
|
-
return False
|
|
565
|
-
else:
|
|
566
|
-
# Import one or more variables
|
|
567
|
-
imports = []
|
|
568
|
-
while True:
|
|
569
|
-
keyword = self.nextToken()
|
|
570
|
-
name = self.nextToken()
|
|
571
|
-
item = [keyword, name]
|
|
572
|
-
imports.append(item)
|
|
573
|
-
self.symbols[name] = self.getPC()
|
|
574
|
-
variable = {}
|
|
575
|
-
variable['domain'] = None
|
|
576
|
-
variable['name'] = name
|
|
577
|
-
variable['keyword'] = keyword
|
|
578
|
-
variable['import'] = None
|
|
579
|
-
self.addCommand(variable)
|
|
580
|
-
if self.peek() != 'and':
|
|
581
|
-
break
|
|
582
|
-
self.nextToken()
|
|
583
|
-
command['imports'] = json.dumps(imports)
|
|
584
|
-
self.add(command)
|
|
585
|
-
return True
|
|
586
|
-
|
|
587
|
-
def r_import(self, command):
|
|
588
|
-
exports = self.program.exports
|
|
589
|
-
imports = json.loads(command['imports'])
|
|
590
|
-
if len(imports) < len(exports):
|
|
591
|
-
RuntimeError(self.program, 'Too few imports')
|
|
592
|
-
elif len(imports) > len(exports):
|
|
593
|
-
RuntimeError(self.program, 'Too many imports')
|
|
594
|
-
for n in range(0, len(imports)):
|
|
595
|
-
exportRecord = exports[n]
|
|
596
|
-
exportKeyword = exportRecord['keyword']
|
|
597
|
-
name = imports[n][1]
|
|
598
|
-
symbolRecord = self.program.getSymbolRecord(name)
|
|
599
|
-
symbolKeyword = symbolRecord['keyword']
|
|
600
|
-
if symbolKeyword != exportKeyword:
|
|
601
|
-
RuntimeError(self.program, f'Import {n} ({symbolKeyword}) does not match export {n} ({exportKeyword})')
|
|
602
|
-
symbolRecord['import'] = exportRecord
|
|
603
|
-
return self.nextPC()
|
|
604
|
-
|
|
605
|
-
# Increment a variable
|
|
606
|
-
def k_increment(self, command):
|
|
607
|
-
if self.nextIsSymbol():
|
|
608
|
-
symbolRecord = self.getSymbolRecord()
|
|
609
|
-
if symbolRecord['valueHolder']:
|
|
610
|
-
command['target'] = self.getToken()
|
|
611
|
-
self.add(command)
|
|
612
|
-
return True
|
|
613
|
-
self.warning(f'Core.increment: Variable "{symbolRecord["name"]}" does not hold a value')
|
|
614
|
-
return False
|
|
615
|
-
|
|
616
|
-
def r_increment(self, command):
|
|
617
|
-
return self.incdec(command, '+')
|
|
618
|
-
|
|
619
|
-
# Index to a specified element in a variable
|
|
620
|
-
# index {variable} to {value}
|
|
621
|
-
def k_index(self, command):
|
|
622
|
-
# get the variable
|
|
623
|
-
if self.nextIsSymbol():
|
|
624
|
-
command['target'] = self.getToken()
|
|
625
|
-
if self.nextToken() == 'to':
|
|
626
|
-
# get the value
|
|
627
|
-
command['value'] = self.nextValue()
|
|
628
|
-
self.add(command)
|
|
629
|
-
return True
|
|
630
|
-
return False
|
|
631
|
-
|
|
632
|
-
def r_index(self, command):
|
|
633
|
-
symbolRecord = self.getVariable(command['target'])
|
|
634
|
-
symbolRecord['index'] = self.getRuntimeValue(command['value'])
|
|
635
|
-
return self.nextPC()
|
|
636
|
-
|
|
637
|
-
# Initialise a stack, array or object
|
|
638
|
-
def k_init(self, command):
|
|
639
|
-
# get the variable
|
|
640
|
-
if self.nextIsSymbol():
|
|
641
|
-
symbolRecord = self.getSymbolRecord()
|
|
642
|
-
keyword = symbolRecord['keyword']
|
|
643
|
-
if keyword in ['stack','array', 'object']:
|
|
644
|
-
command['keyword'] = keyword
|
|
645
|
-
command['target'] = symbolRecord['name']
|
|
646
|
-
return True
|
|
647
|
-
return False
|
|
648
|
-
|
|
649
|
-
def r_init(self, command):
|
|
650
|
-
symbolRecord = self.getVariable(command['target'])
|
|
651
|
-
keyword = command['keyword']
|
|
652
|
-
if keyword in ['stack', 'array']:
|
|
653
|
-
self.putSymbolValue(symbolRecord, json.loads('[]'))
|
|
654
|
-
elif keyword == 'object':
|
|
655
|
-
self.putSymbolValue(symbolRecord, json.loads('{}'))
|
|
656
|
-
else:
|
|
657
|
-
RuntimeError(self.program, f"Inappropriate variable type '{keyword}'")
|
|
658
|
-
return self.nextPC()
|
|
659
|
-
|
|
660
|
-
# Inout a value from the terminal
|
|
661
|
-
# input {variable} [with {prompt}]
|
|
662
|
-
def k_input(self, command):
|
|
663
|
-
# get the variable
|
|
664
|
-
if self.nextIsSymbol():
|
|
665
|
-
command['target'] = self.getToken()
|
|
666
|
-
value = {}
|
|
667
|
-
value['type'] = 'text'
|
|
668
|
-
value['numeric'] = 'false'
|
|
669
|
-
value['content'] = ': '
|
|
670
|
-
command['prompt'] = value
|
|
671
|
-
if self.peek() == 'with':
|
|
672
|
-
self.nextToken()
|
|
673
|
-
command['prompt'] = self.nextValue()
|
|
674
|
-
self.add(command)
|
|
675
|
-
return True
|
|
676
|
-
return False
|
|
677
|
-
|
|
678
|
-
def r_input(self, command):
|
|
679
|
-
symbolRecord = self.getVariable(command['target'])
|
|
680
|
-
prompt = command['prompt']['content']
|
|
681
|
-
value = {}
|
|
682
|
-
value['type'] = 'text'
|
|
683
|
-
value['numeric'] = False
|
|
684
|
-
value['content'] = prompt+input(prompt)
|
|
685
|
-
self.putSymbolValue(symbolRecord, value)
|
|
686
|
-
return self.nextPC()
|
|
687
|
-
|
|
688
|
-
# 1 Load a plugin. This is done at compile time.
|
|
689
|
-
# 2 Load text from a file
|
|
690
|
-
def k_load(self, command):
|
|
691
|
-
self.nextToken()
|
|
692
|
-
if self.tokenIs('plugin'):
|
|
693
|
-
clazz = self.nextToken()
|
|
694
|
-
if self.nextIs('from'):
|
|
695
|
-
source = self.nextToken()
|
|
696
|
-
self.program.importPlugin(f'{source}:{clazz}')
|
|
697
|
-
return True
|
|
698
|
-
elif self.isSymbol():
|
|
699
|
-
symbolRecord = self.getSymbolRecord()
|
|
700
|
-
if symbolRecord['valueHolder']:
|
|
701
|
-
command['target'] = symbolRecord['name']
|
|
702
|
-
if self.nextIs('from'):
|
|
703
|
-
command['file'] = self.nextValue()
|
|
704
|
-
self.add(command)
|
|
705
|
-
return True
|
|
706
|
-
else:
|
|
707
|
-
FatalError(self.compiler, f'I don\'t understand \'{self.getToken()}\'')
|
|
708
|
-
return False
|
|
709
|
-
|
|
710
|
-
def r_load(self, command):
|
|
711
|
-
target = self.getVariable(command['target'])
|
|
712
|
-
filename = self.getRuntimeValue(command['file'])
|
|
713
|
-
try:
|
|
714
|
-
with open(filename) as f: content = f.read()
|
|
715
|
-
except:
|
|
716
|
-
RuntimeError(self.program, f'File \'{filename}\' not found')
|
|
717
|
-
try:
|
|
718
|
-
if filename.endswith('.json'): content = json.loads(content)
|
|
719
|
-
except:
|
|
720
|
-
RuntimeError(self.program, 'Bad or null JSON string')
|
|
721
|
-
value = {}
|
|
722
|
-
value['type'] = 'text'
|
|
723
|
-
value['content'] = content
|
|
724
|
-
self.putSymbolValue(target, value)
|
|
725
|
-
return self.nextPC()
|
|
726
|
-
|
|
727
|
-
# Lock a variable
|
|
728
|
-
def k_lock(self, command):
|
|
729
|
-
if self.nextIsSymbol():
|
|
730
|
-
symbolRecord = self.getSymbolRecord()
|
|
731
|
-
command['target'] = symbolRecord['name']
|
|
732
|
-
self.add(command)
|
|
733
|
-
return True
|
|
734
|
-
return False
|
|
735
|
-
|
|
736
|
-
def r_lock(self, command):
|
|
737
|
-
target = self.getVariable(command['target'])
|
|
738
|
-
target['locked'] = True
|
|
739
|
-
return self.nextPC()
|
|
740
|
-
|
|
741
|
-
# Log a message
|
|
742
|
-
def k_log(self, command):
|
|
743
|
-
command['log'] = True
|
|
744
|
-
command['keyword'] = 'print'
|
|
745
|
-
return self.k_print(command)
|
|
746
|
-
|
|
747
|
-
# Declare a module variable
|
|
748
|
-
def k_module(self, command):
|
|
749
|
-
return self.compileVariable(command)
|
|
750
|
-
|
|
751
|
-
def r_module(self, command):
|
|
752
|
-
return self.nextPC()
|
|
753
|
-
|
|
754
|
-
# Arithmetic multiply
|
|
755
|
-
# multiply {variable} by {value}[ giving {variable}]}
|
|
756
|
-
def k_multiply(self, command):
|
|
757
|
-
# Get the (first) value
|
|
758
|
-
command['value1'] = self.nextValue()
|
|
759
|
-
if self.nextToken() == 'by':
|
|
760
|
-
command['value2'] = self.nextValue()
|
|
761
|
-
if self.peek() == 'giving':
|
|
762
|
-
self.nextToken()
|
|
763
|
-
if (self.nextIsSymbol()):
|
|
764
|
-
command['target'] = self.getToken()
|
|
765
|
-
self.add(command)
|
|
766
|
-
return True
|
|
767
|
-
FatalError(self.compiler, 'Symbol expected')
|
|
768
|
-
else:
|
|
769
|
-
# First value must be a variable
|
|
770
|
-
if command['value1']['type'] == 'symbol':
|
|
771
|
-
command['target'] = command['value1']['name']
|
|
772
|
-
self.add(command)
|
|
773
|
-
return True
|
|
774
|
-
FatalError(self.compiler, 'First value must be a variable')
|
|
775
|
-
return False
|
|
776
|
-
|
|
777
|
-
def r_multiply(self, command):
|
|
778
|
-
value1 = command['value1']
|
|
779
|
-
try:
|
|
780
|
-
value2 = command['value2']
|
|
781
|
-
except:
|
|
782
|
-
value2 = None
|
|
783
|
-
target = self.getVariable(command['target'])
|
|
784
|
-
if not target['valueHolder']:
|
|
785
|
-
self.variableDoesNotHoldAValueError(target['name'])
|
|
786
|
-
return None
|
|
787
|
-
value = self.getSymbolValue(target)
|
|
788
|
-
if value == None:
|
|
789
|
-
value = {}
|
|
790
|
-
value['type'] = 'int'
|
|
791
|
-
if value2:
|
|
792
|
-
v1 = int(self.getRuntimeValue(value1))
|
|
793
|
-
v2 = int(self.getRuntimeValue(value2))
|
|
794
|
-
value['content'] = v1*v2
|
|
795
|
-
else:
|
|
796
|
-
if value['type'] != 'int' and value['content'] != None:
|
|
797
|
-
self.nonNumericValueError()
|
|
798
|
-
return None
|
|
799
|
-
v = int(self.getRuntimeValue(value))
|
|
800
|
-
v1 = int(self.getRuntimeValue(value1))
|
|
801
|
-
value['content'] = v*v1
|
|
802
|
-
self.putSymbolValue(target, value)
|
|
803
|
-
return self.nextPC()
|
|
804
|
-
|
|
805
|
-
# Negate a variable
|
|
806
|
-
def k_negate(self, command):
|
|
807
|
-
if self.nextIsSymbol():
|
|
808
|
-
symbolRecord = self.getSymbolRecord()
|
|
809
|
-
if symbolRecord['valueHolder']:
|
|
810
|
-
command['target'] = self.getToken()
|
|
811
|
-
self.add(command)
|
|
812
|
-
return True
|
|
813
|
-
self.warning(f'Core.negate: Variable "{symbolRecord["name"]}" does not hold a value')
|
|
814
|
-
return False
|
|
815
|
-
|
|
816
|
-
def r_negate(self, command):
|
|
817
|
-
symbolRecord = self.getVariable(command['target'])
|
|
818
|
-
if not symbolRecord['valueHolder']:
|
|
819
|
-
RuntimeError(self.program, f'{symbolRecord["name"]} does not hold a value')
|
|
820
|
-
return None
|
|
821
|
-
value = self.getSymbolValue(symbolRecord)
|
|
822
|
-
if value == None:
|
|
823
|
-
RuntimeError(self.program, f'{symbolRecord["name"]} has not been initialised')
|
|
824
|
-
value['content'] *= -1
|
|
825
|
-
self.putSymbolValue(symbolRecord, value)
|
|
826
|
-
return self.nextPC()
|
|
827
|
-
|
|
828
|
-
# Define an object variable
|
|
829
|
-
def k_object(self, command):
|
|
830
|
-
return self.compileVariable(command)
|
|
831
|
-
|
|
832
|
-
def r_object(self, command):
|
|
833
|
-
return self.nextPC()
|
|
834
|
-
|
|
835
|
-
# on message {action}
|
|
836
|
-
def k_on(self, command):
|
|
837
|
-
if self.nextIs('message'):
|
|
838
|
-
self.nextToken()
|
|
839
|
-
command['goto'] = 0
|
|
840
|
-
self.add(command)
|
|
841
|
-
cmd = {}
|
|
842
|
-
cmd['domain'] = 'core'
|
|
843
|
-
cmd['lino'] = command['lino']
|
|
844
|
-
cmd['keyword'] = 'gotoPC'
|
|
845
|
-
cmd['goto'] = 0
|
|
846
|
-
cmd['debug'] = False
|
|
847
|
-
self.addCommand(cmd)
|
|
848
|
-
# Add the action and a 'stop'
|
|
849
|
-
self.compileOne()
|
|
850
|
-
cmd = {}
|
|
851
|
-
cmd['domain'] = 'core'
|
|
852
|
-
cmd['lino'] = command['lino']
|
|
853
|
-
cmd['keyword'] = 'stop'
|
|
854
|
-
cmd['debug'] = False
|
|
855
|
-
self.addCommand(cmd)
|
|
856
|
-
# Fixup the link
|
|
857
|
-
command['goto'] = self.getPC()
|
|
858
|
-
return True
|
|
859
|
-
return False
|
|
860
|
-
|
|
861
|
-
def r_on(self, command):
|
|
862
|
-
self.program.onMessage(self.nextPC()+1)
|
|
863
|
-
return command['goto']
|
|
864
|
-
|
|
865
|
-
# Open a file
|
|
866
|
-
# open {file} for reading/writing/appending
|
|
867
|
-
def k_open(self, command):
|
|
868
|
-
if self.nextIsSymbol():
|
|
869
|
-
symbolRecord = self.getSymbolRecord()
|
|
870
|
-
command['target'] = symbolRecord['name']
|
|
871
|
-
command['path'] = self.nextValue()
|
|
872
|
-
if symbolRecord['keyword'] == 'file':
|
|
873
|
-
if self.peek() == 'for':
|
|
874
|
-
self.nextToken()
|
|
875
|
-
token = self.nextToken()
|
|
876
|
-
if token == 'appending':
|
|
877
|
-
mode = 'a'
|
|
878
|
-
elif token == 'reading':
|
|
879
|
-
mode = 'r'
|
|
880
|
-
elif token == 'writing':
|
|
881
|
-
mode = 'w'
|
|
882
|
-
else:
|
|
883
|
-
FatalError(self.compiler, 'Unknown file open mode {self.getToken()}')
|
|
884
|
-
return False
|
|
885
|
-
command['mode'] = mode
|
|
886
|
-
else:
|
|
887
|
-
command['mode'] = 'r'
|
|
888
|
-
self.add(command)
|
|
889
|
-
return True
|
|
890
|
-
else:
|
|
891
|
-
FatalError(self.compiler, f'Variable "{self.getToken()}" is not a file')
|
|
892
|
-
else:
|
|
893
|
-
self.warning(f'Core.open: Variable "{self.getToken()}" not declared')
|
|
894
|
-
return False
|
|
895
|
-
|
|
896
|
-
def r_open(self, command):
|
|
897
|
-
symbolRecord = self.getVariable(command['target'])
|
|
898
|
-
path = self.getRuntimeValue(command['path'])
|
|
899
|
-
if command['mode'] == 'r' and os.path.exists(path) or command['mode'] != 'r':
|
|
900
|
-
symbolRecord['file'] = open(path, command['mode'])
|
|
901
|
-
return self.nextPC()
|
|
902
|
-
RuntimeError(self.program, f"File {path} does not exist")
|
|
903
|
-
|
|
904
|
-
# Pop a value from a stack
|
|
905
|
-
# pop {variable} from {stack}
|
|
906
|
-
def k_pop(self, command):
|
|
907
|
-
if (self.nextIsSymbol()):
|
|
908
|
-
symbolRecord = self.getSymbolRecord()
|
|
909
|
-
command['target'] = symbolRecord['name']
|
|
910
|
-
if self.peek() == 'from':
|
|
911
|
-
self.nextToken()
|
|
912
|
-
if self.nextIsSymbol():
|
|
913
|
-
command['from'] = self.getToken()
|
|
914
|
-
self.add(command)
|
|
915
|
-
return True
|
|
916
|
-
return False;
|
|
917
|
-
|
|
918
|
-
def r_pop(self, command):
|
|
919
|
-
symbolRecord = self.getVariable(command['target'])
|
|
920
|
-
if not symbolRecord['valueHolder']:
|
|
921
|
-
RuntimeError(self.program, f'{symbolRecord["name"]} does not hold a value')
|
|
922
|
-
stackRecord = self.getVariable(command['from'])
|
|
923
|
-
stack = self.getSymbolValue(stackRecord)
|
|
924
|
-
v = stack.pop();
|
|
925
|
-
self.putSymbolValue(stackRecord, stack)
|
|
926
|
-
value = {}
|
|
927
|
-
value['type'] = 'int' if type(v) == int else 'text'
|
|
928
|
-
value['content'] = v
|
|
929
|
-
self.putSymbolValue(symbolRecord, value)
|
|
930
|
-
return self.nextPC()
|
|
931
|
-
|
|
932
|
-
# Perform an HTTP POST
|
|
933
|
-
# post {value} to {url} [giving {variable}] [or {command}]
|
|
934
|
-
def k_post(self, command):
|
|
935
|
-
if self.nextIs('to'):
|
|
936
|
-
command['value'] = self.getConstant('')
|
|
937
|
-
command['url'] = self.getValue()
|
|
938
|
-
else:
|
|
939
|
-
command['value'] = self.getValue()
|
|
940
|
-
if self.nextIs('to'):
|
|
941
|
-
command['url'] = self.nextValue()
|
|
942
|
-
if self.peek() == 'giving':
|
|
943
|
-
self.nextToken()
|
|
944
|
-
command['result'] = self.nextToken()
|
|
945
|
-
else:
|
|
946
|
-
command['result'] = None
|
|
947
|
-
command['or'] = None
|
|
948
|
-
post = self.getPC()
|
|
949
|
-
self.addCommand(command)
|
|
950
|
-
if self.peek() == 'or':
|
|
951
|
-
self.nextToken()
|
|
952
|
-
self.nextToken()
|
|
953
|
-
# Add a 'goto' to skip the 'or'
|
|
954
|
-
cmd = {}
|
|
955
|
-
cmd['lino'] = command['lino']
|
|
956
|
-
cmd['domain'] = 'core'
|
|
957
|
-
cmd['keyword'] = 'gotoPC'
|
|
958
|
-
cmd['goto'] = 0
|
|
959
|
-
cmd['debug'] = False
|
|
960
|
-
skip = self.getPC()
|
|
961
|
-
self.addCommand(cmd)
|
|
962
|
-
# Process the 'or'
|
|
963
|
-
self.getCommandAt(post)['or'] = self.getPC()
|
|
964
|
-
self.compileOne()
|
|
965
|
-
# Fixup the skip
|
|
966
|
-
self.getCommandAt(skip)['goto'] = self.getPC()
|
|
967
|
-
return True
|
|
968
|
-
|
|
969
|
-
def r_post(self, command):
|
|
970
|
-
global errorCode, errorReason
|
|
971
|
-
retval = {}
|
|
972
|
-
retval['type'] = 'text'
|
|
973
|
-
retval['numeric'] = False
|
|
974
|
-
value = self.getRuntimeValue(command['value'])
|
|
975
|
-
url = self.getRuntimeValue(command['url'])
|
|
976
|
-
try:
|
|
977
|
-
response = requests.post(url, value, timeout=5)
|
|
978
|
-
retval['content'] = response.text
|
|
979
|
-
if response.status_code >= 400:
|
|
980
|
-
errorCode = response.status_code
|
|
981
|
-
errorReason = response.reason
|
|
982
|
-
if command['or'] != None:
|
|
983
|
-
print(f'Error {errorCode} {errorReason}: Running the "or" clause')
|
|
984
|
-
return command['or']
|
|
985
|
-
else:
|
|
986
|
-
RuntimeError(self.program, f'Error code {errorCode}: {errorReason}')
|
|
987
|
-
except Exception as e:
|
|
988
|
-
errorReason = str(e)
|
|
989
|
-
if command['or'] != None:
|
|
990
|
-
print(f'Exception "{errorReason}": Running the "or" clause')
|
|
991
|
-
return command['or']
|
|
992
|
-
else:
|
|
993
|
-
RuntimeError(self.program, f'Error: {errorReason}')
|
|
994
|
-
if command['result'] != None:
|
|
995
|
-
result = self.getVariable(command['result'])
|
|
996
|
-
self.program.putSymbolValue(result, retval)
|
|
997
|
-
return self.nextPC()
|
|
998
|
-
|
|
999
|
-
# Print a value
|
|
1000
|
-
def k_print(self, command):
|
|
1001
|
-
value = self.nextValue()
|
|
1002
|
-
if value != None:
|
|
1003
|
-
command['value'] = value
|
|
1004
|
-
self.add(command)
|
|
1005
|
-
return True
|
|
1006
|
-
FatalError(self.compiler, 'I can\'t print this value')
|
|
1007
|
-
return False
|
|
1008
|
-
|
|
1009
|
-
def r_print(self, command):
|
|
1010
|
-
value = self.getRuntimeValue(command['value'])
|
|
1011
|
-
program = command['program']
|
|
1012
|
-
code = program.code[program.pc]
|
|
1013
|
-
lino = str(code['lino'] + 1)
|
|
1014
|
-
while len(lino) < 5: lino = f' {lino}'
|
|
1015
|
-
if value == None: value = '<empty>'
|
|
1016
|
-
if 'log' in command:
|
|
1017
|
-
print(f'{datetime.now().time()}:{lino}-> {value}')
|
|
1018
|
-
else:
|
|
1019
|
-
print(value)
|
|
1020
|
-
return self.nextPC()
|
|
1021
|
-
|
|
1022
|
-
# Push a value onto a stack
|
|
1023
|
-
# push {value} to/onto {stack}
|
|
1024
|
-
def k_push(self, command):
|
|
1025
|
-
value = self.nextValue()
|
|
1026
|
-
command['value'] = value
|
|
1027
|
-
peekValue = self.peek()
|
|
1028
|
-
if peekValue in ['onto', 'to']:
|
|
1029
|
-
self.nextToken()
|
|
1030
|
-
if self.nextIsSymbol():
|
|
1031
|
-
symbolRecord = self.getSymbolRecord()
|
|
1032
|
-
command['to'] = symbolRecord['name']
|
|
1033
|
-
self.add(command)
|
|
1034
|
-
return True
|
|
1035
|
-
return False
|
|
1036
|
-
|
|
1037
|
-
def r_push(self, command):
|
|
1038
|
-
value = self.getRuntimeValue(command['value'])
|
|
1039
|
-
stackRecord = self.getVariable(command['to'])
|
|
1040
|
-
if stackRecord['keyword'] != 'stack':
|
|
1041
|
-
RuntimeError(self.program, f'{stackRecord["name"]} is not a stack')
|
|
1042
|
-
return -1
|
|
1043
|
-
stack = stackRecord['value'][stackRecord['index']]
|
|
1044
|
-
if stack == None:
|
|
1045
|
-
stack = [value]
|
|
1046
|
-
else:
|
|
1047
|
-
stack.append(value)
|
|
1048
|
-
self.putSymbolValue(stackRecord, stack)
|
|
1049
|
-
return self.nextPC()
|
|
1050
|
-
|
|
1051
|
-
# Put a value into a variable
|
|
1052
|
-
# put {value} into {variable}
|
|
1053
|
-
def k_put(self, command):
|
|
1054
|
-
command['value'] = self.nextValue()
|
|
1055
|
-
if self.nextIs('into'):
|
|
1056
|
-
if self.nextIsSymbol():
|
|
1057
|
-
symbolRecord = self.getSymbolRecord()
|
|
1058
|
-
command['target'] = symbolRecord['name']
|
|
1059
|
-
if 'valueholder' in symbolRecord and symbolRecord['valueHolder'] == False:
|
|
1060
|
-
FatalError(self.compiler, f'Symbol {symbolRecord["name"]} is not a value holder')
|
|
1061
|
-
else:
|
|
1062
|
-
self.add(command)
|
|
1063
|
-
return True
|
|
1064
|
-
else:
|
|
1065
|
-
FatalError(self.compiler, f'Symbol {self.getToken()} is not a variable')
|
|
1066
|
-
return False
|
|
1067
|
-
|
|
1068
|
-
def r_put(self, command):
|
|
1069
|
-
value = self.evaluate(command['value'])
|
|
1070
|
-
if value == None:
|
|
1071
|
-
return -1
|
|
1072
|
-
symbolRecord = self.getVariable(command['target'])
|
|
1073
|
-
if not symbolRecord['valueHolder']:
|
|
1074
|
-
RuntimeError(self.program, f'{symbolRecord["name"]} does not hold a value')
|
|
1075
|
-
return -1
|
|
1076
|
-
self.putSymbolValue(symbolRecord, value)
|
|
1077
|
-
return self.nextPC()
|
|
1078
|
-
|
|
1079
|
-
# Read from a file
|
|
1080
|
-
# read {variable} from {file}
|
|
1081
|
-
def k_read(self, command):
|
|
1082
|
-
if self.peek() == 'line':
|
|
1083
|
-
self.nextToken()
|
|
1084
|
-
command['line'] = True
|
|
1085
|
-
else:
|
|
1086
|
-
command['line'] = False
|
|
1087
|
-
if self.nextIsSymbol():
|
|
1088
|
-
symbolRecord = self.getSymbolRecord()
|
|
1089
|
-
if symbolRecord['valueHolder']:
|
|
1090
|
-
if self.peek() == 'from':
|
|
1091
|
-
self.nextToken()
|
|
1092
|
-
if self.nextIsSymbol():
|
|
1093
|
-
fileRecord = self.getSymbolRecord()
|
|
1094
|
-
if fileRecord['keyword'] == 'file':
|
|
1095
|
-
command['target'] = symbolRecord['name']
|
|
1096
|
-
command['file'] = fileRecord['name']
|
|
1097
|
-
self.add(command)
|
|
1098
|
-
return True
|
|
1099
|
-
FatalError(self.compiler, f'Symbol "{symbolRecord["name"]}" is not a value holder')
|
|
1100
|
-
return False
|
|
1101
|
-
FatalError(self.compiler, f'Symbol "{self.getToken()}" has not been declared')
|
|
1102
|
-
return False
|
|
1103
|
-
|
|
1104
|
-
def r_read(self, command):
|
|
1105
|
-
symbolRecord = self.getVariable(command['target'])
|
|
1106
|
-
fileRecord = self.getVariable(command['file'])
|
|
1107
|
-
line = command['line']
|
|
1108
|
-
file = fileRecord['file']
|
|
1109
|
-
if file.mode == 'r':
|
|
1110
|
-
value = {}
|
|
1111
|
-
content = file.readline().split('\n')[0] if line else file.read()
|
|
1112
|
-
value['type'] = 'text'
|
|
1113
|
-
value['numeric'] = False
|
|
1114
|
-
value['content'] = content
|
|
1115
|
-
self.putSymbolValue(symbolRecord, value)
|
|
1116
|
-
return self.nextPC()
|
|
1117
|
-
|
|
1118
|
-
# Replace a substring
|
|
1119
|
-
#replace {value} with {value} in {variable}
|
|
1120
|
-
def k_replace(self, command):
|
|
1121
|
-
original = self.nextValue()
|
|
1122
|
-
if self.peek() == 'with':
|
|
1123
|
-
self.nextToken()
|
|
1124
|
-
replacement = self.nextValue()
|
|
1125
|
-
if self.nextIs('in'):
|
|
1126
|
-
if self.nextIsSymbol():
|
|
1127
|
-
templateRecord = self.getSymbolRecord()
|
|
1128
|
-
command['original'] = original
|
|
1129
|
-
command['replacement'] = replacement
|
|
1130
|
-
command['target'] = templateRecord['name']
|
|
1131
|
-
self.add(command)
|
|
1132
|
-
return True
|
|
1133
|
-
return False
|
|
1134
|
-
|
|
1135
|
-
def r_replace(self, command):
|
|
1136
|
-
templateRecord = self.getVariable(command['target'])
|
|
1137
|
-
content = self.getSymbolValue(templateRecord)['content']
|
|
1138
|
-
original = self.getRuntimeValue(command['original'])
|
|
1139
|
-
replacement = self.getRuntimeValue(command['replacement'])
|
|
1140
|
-
content = content.replace(original, str(replacement))
|
|
1141
|
-
value = {}
|
|
1142
|
-
value['type'] = 'text'
|
|
1143
|
-
value['numeric'] = False
|
|
1144
|
-
value['content'] = content
|
|
1145
|
-
self.putSymbolValue(templateRecord, value)
|
|
1146
|
-
return self.nextPC()
|
|
1147
|
-
|
|
1148
|
-
# Release the parent script
|
|
1149
|
-
def k_release(self, command):
|
|
1150
|
-
if self.nextIs('parent'):
|
|
1151
|
-
self.add(command)
|
|
1152
|
-
return True
|
|
1153
|
-
|
|
1154
|
-
def r_release(self, command):
|
|
1155
|
-
self.program.releaseParent()
|
|
1156
|
-
return self.nextPC()
|
|
1157
|
-
|
|
1158
|
-
# Return from subroutine
|
|
1159
|
-
def k_return(self, command):
|
|
1160
|
-
self.add(command)
|
|
1161
|
-
return True
|
|
1162
|
-
|
|
1163
|
-
def r_return(self, command):
|
|
1164
|
-
return self.stack.pop()
|
|
1165
|
-
|
|
1166
|
-
# Compile and run a script
|
|
1167
|
-
# run {path} [as {module}] [with {variable} [and {variable}...]]
|
|
1168
|
-
def k_run(self, command):
|
|
1169
|
-
try:
|
|
1170
|
-
command['path'] = self.nextValue()
|
|
1171
|
-
except Exception as e:
|
|
1172
|
-
self.warning(f'Core.run: Path expected')
|
|
1173
|
-
return False
|
|
1174
|
-
if self.nextIs('as'):
|
|
1175
|
-
if self.nextIsSymbol():
|
|
1176
|
-
record = self.getSymbolRecord()
|
|
1177
|
-
if record['keyword'] == 'module':
|
|
1178
|
-
name = record['name']
|
|
1179
|
-
command['module'] = name
|
|
1180
|
-
else: RuntimeError(self.program, f'Symbol \'name\' is not a module')
|
|
1181
|
-
else: RuntimeError(self.program, 'Module name expected after \'as\'')
|
|
1182
|
-
else: RuntimeError(self.program, '\'as {module name}\' expected')
|
|
1183
|
-
exports = []
|
|
1184
|
-
if self.peek() == 'with':
|
|
1185
|
-
self.nextToken()
|
|
1186
|
-
while True:
|
|
1187
|
-
name = self.nextToken()
|
|
1188
|
-
record = self.getSymbolRecord()
|
|
1189
|
-
exports.append(name)
|
|
1190
|
-
if self.peek() != 'and':
|
|
1191
|
-
break
|
|
1192
|
-
self.nextToken()
|
|
1193
|
-
command['exports'] = json.dumps(exports)
|
|
1194
|
-
self.add(command)
|
|
1195
|
-
return True
|
|
1196
|
-
|
|
1197
|
-
def r_run(self, command):
|
|
1198
|
-
module = self.getVariable(command['module'])
|
|
1199
|
-
path = self.getRuntimeValue(command['path'])
|
|
1200
|
-
exports = json.loads(command['exports'])
|
|
1201
|
-
for n in range(0, len(exports)):
|
|
1202
|
-
exports[n] = self.getVariable(exports[n])
|
|
1203
|
-
module['path'] = path
|
|
1204
|
-
parent = Object()
|
|
1205
|
-
parent.program = self.program
|
|
1206
|
-
parent.pc = self.nextPC()
|
|
1207
|
-
parent.waiting = True
|
|
1208
|
-
p = self.program.__class__
|
|
1209
|
-
p(path).start(parent, module, exports)
|
|
1210
|
-
return 0
|
|
1211
|
-
|
|
1212
|
-
# Provide a name for the script
|
|
1213
|
-
def k_script(self, command):
|
|
1214
|
-
self.program.name = self.nextToken()
|
|
1215
|
-
return True
|
|
1216
|
-
|
|
1217
|
-
# Save a value to a file
|
|
1218
|
-
def k_save(self, command):
|
|
1219
|
-
command['content'] = self.nextValue()
|
|
1220
|
-
if self.nextIs('to'):
|
|
1221
|
-
command['file'] = self.nextValue()
|
|
1222
|
-
self.add(command)
|
|
1223
|
-
return True
|
|
1224
|
-
return False
|
|
1225
|
-
|
|
1226
|
-
def r_save(self, command):
|
|
1227
|
-
content = self.getRuntimeValue(command['content'])
|
|
1228
|
-
filename = self.getRuntimeValue(command['file'])
|
|
1229
|
-
if filename.endswith('.json'): content = json.dumps(content)
|
|
1230
|
-
with open(filename, 'w') as f: f.write(content)
|
|
1231
|
-
return self.nextPC()
|
|
1232
|
-
|
|
1233
|
-
# Send a message to a module
|
|
1234
|
-
def k_send(self, command):
|
|
1235
|
-
command['message'] = self.nextValue()
|
|
1236
|
-
if self.nextIs('to'):
|
|
1237
|
-
if self.nextIsSymbol():
|
|
1238
|
-
record = self.getSymbolRecord()
|
|
1239
|
-
if record['keyword'] == 'module':
|
|
1240
|
-
command['module'] = record['name']
|
|
1241
|
-
self.add(command)
|
|
1242
|
-
return True
|
|
1243
|
-
return False
|
|
1244
|
-
|
|
1245
|
-
def r_send(self, command):
|
|
1246
|
-
message = self.getRuntimeValue(command['message'])
|
|
1247
|
-
module = self.getVariable(command['module'])
|
|
1248
|
-
module['child'].handleMessage(message)
|
|
1249
|
-
return self.nextPC()
|
|
1250
|
-
|
|
1251
|
-
# Set a value
|
|
1252
|
-
# set {variable}
|
|
1253
|
-
# set the elements of {variable} to {value}
|
|
1254
|
-
# set element/property of {variable} to {value}
|
|
1255
|
-
def k_set(self, command):
|
|
1256
|
-
if self.nextIsSymbol():
|
|
1257
|
-
target = self.getSymbolRecord()
|
|
1258
|
-
if target['valueHolder']:
|
|
1259
|
-
command['type'] = 'set'
|
|
1260
|
-
command['target'] = target['name']
|
|
1261
|
-
self.add(command)
|
|
1262
|
-
return True
|
|
1263
|
-
return False
|
|
1264
|
-
|
|
1265
|
-
token = self.getToken()
|
|
1266
|
-
if token == 'the':
|
|
1267
|
-
token = self.nextToken()
|
|
1268
|
-
command['type'] = token
|
|
1269
|
-
|
|
1270
|
-
if token == 'elements':
|
|
1271
|
-
self.nextToken()
|
|
1272
|
-
if self.peek() == 'of':
|
|
1273
|
-
self.nextToken()
|
|
1274
|
-
if self.nextIsSymbol():
|
|
1275
|
-
command['name'] = self.getToken()
|
|
1276
|
-
if self.peek() == 'to':
|
|
1277
|
-
self.nextToken()
|
|
1278
|
-
command['elements'] = self.nextValue()
|
|
1279
|
-
self.add(command)
|
|
1280
|
-
return True
|
|
1281
|
-
|
|
1282
|
-
elif token == 'encoding':
|
|
1283
|
-
if self.nextIs('to'):
|
|
1284
|
-
command['encoding'] = self.nextValue()
|
|
1285
|
-
self.add(command)
|
|
1286
|
-
return True
|
|
1287
|
-
|
|
1288
|
-
elif token == 'property':
|
|
1289
|
-
command['name'] = self.nextValue()
|
|
1290
|
-
if self.nextIs('of'):
|
|
1291
|
-
if self.nextIsSymbol():
|
|
1292
|
-
command['target'] = self.getSymbolRecord()['name']
|
|
1293
|
-
if self.nextIs('to'):
|
|
1294
|
-
command['value'] = self.nextValue()
|
|
1295
|
-
self.add(command)
|
|
1296
|
-
return True
|
|
1297
|
-
|
|
1298
|
-
elif token == 'element':
|
|
1299
|
-
command['index'] = self.nextValue()
|
|
1300
|
-
if self.nextIs('of'):
|
|
1301
|
-
if self.nextIsSymbol():
|
|
1302
|
-
command['target'] = self.getSymbolRecord()['name']
|
|
1303
|
-
if self.nextIs('to'):
|
|
1304
|
-
command['value'] = self.nextValue()
|
|
1305
|
-
self.add(command)
|
|
1306
|
-
return True
|
|
1307
|
-
return False
|
|
1308
|
-
|
|
1309
|
-
def r_set(self, command):
|
|
1310
|
-
cmdType = command['type']
|
|
1311
|
-
if cmdType == 'set':
|
|
1312
|
-
target = self.getVariable(command['target'])
|
|
1313
|
-
val = {}
|
|
1314
|
-
val['type'] = 'boolean'
|
|
1315
|
-
val['content'] = True
|
|
1316
|
-
self.putSymbolValue(target, val)
|
|
1317
|
-
return self.nextPC()
|
|
1318
|
-
|
|
1319
|
-
elif cmdType == 'elements':
|
|
1320
|
-
symbolRecord = self.getVariable(command['name'])
|
|
1321
|
-
elements = self.getRuntimeValue(command['elements'])
|
|
1322
|
-
currentElements = symbolRecord['elements']
|
|
1323
|
-
currentValue = symbolRecord['value']
|
|
1324
|
-
if currentValue == None:
|
|
1325
|
-
currentValue = [None]
|
|
1326
|
-
newValue = [None] * elements
|
|
1327
|
-
if elements > currentElements:
|
|
1328
|
-
for index, value in enumerate(currentValue):
|
|
1329
|
-
newValue[index] = value
|
|
1330
|
-
elif elements < currentElements:
|
|
1331
|
-
for index, value in enumerate(currentValue):
|
|
1332
|
-
if index < elements:
|
|
1333
|
-
newValue[index] = value
|
|
1334
|
-
symbolRecord['elements'] = elements
|
|
1335
|
-
symbolRecord['value'] = newValue
|
|
1336
|
-
return self.nextPC()
|
|
1337
|
-
|
|
1338
|
-
elif cmdType == 'element':
|
|
1339
|
-
value = self.getRuntimeValue(command['value'])
|
|
1340
|
-
index = self.getRuntimeValue(command['index'])
|
|
1341
|
-
target = self.getVariable(command['target'])
|
|
1342
|
-
val = self.getSymbolValue(target)
|
|
1343
|
-
content = val['content']
|
|
1344
|
-
if content == '':
|
|
1345
|
-
content = []
|
|
1346
|
-
# else:
|
|
1347
|
-
# content = json.loads(content)
|
|
1348
|
-
content[index] = value
|
|
1349
|
-
val['content'] = content
|
|
1350
|
-
self.putSymbolValue(target, val)
|
|
1351
|
-
return self.nextPC()
|
|
1352
|
-
|
|
1353
|
-
elif cmdType == 'encoding':
|
|
1354
|
-
self.encoding = self.getRuntimeValue(command['encoding'])
|
|
1355
|
-
return self.nextPC()
|
|
1356
|
-
|
|
1357
|
-
elif cmdType == 'property':
|
|
1358
|
-
value = self.getRuntimeValue(command['value'])
|
|
1359
|
-
name = self.getRuntimeValue(command['name'])
|
|
1360
|
-
target = command['target']
|
|
1361
|
-
targetVariable = self.getVariable(target)
|
|
1362
|
-
val = self.getSymbolValue(targetVariable)
|
|
1363
|
-
try:
|
|
1364
|
-
content = val['content']
|
|
1365
|
-
except:
|
|
1366
|
-
RuntimeError(self.program, f'{target} is not an object')
|
|
1367
|
-
if content == '':
|
|
1368
|
-
content = {}
|
|
1369
|
-
try:
|
|
1370
|
-
content[name] = value
|
|
1371
|
-
except:
|
|
1372
|
-
RuntimeError(self.program, f'{target} is not an object')
|
|
1373
|
-
val['content'] = content
|
|
1374
|
-
self.putSymbolValue(targetVariable, val)
|
|
1375
|
-
return self.nextPC()
|
|
1376
|
-
|
|
1377
|
-
# Split a string into a variable with several elements
|
|
1378
|
-
# split {variable} on {value}
|
|
1379
|
-
def k_split(self, command):
|
|
1380
|
-
if self.nextIsSymbol():
|
|
1381
|
-
symbolRecord = self.getSymbolRecord()
|
|
1382
|
-
if symbolRecord['valueHolder']:
|
|
1383
|
-
command['target'] = symbolRecord['name']
|
|
1384
|
-
value = {}
|
|
1385
|
-
value['type'] = 'text'
|
|
1386
|
-
value['numeric'] = 'false'
|
|
1387
|
-
value['content'] = '\n'
|
|
1388
|
-
command['on'] = value
|
|
1389
|
-
if self.peek() == 'on':
|
|
1390
|
-
self.nextToken()
|
|
1391
|
-
if self.peek() == 'tab':
|
|
1392
|
-
value['content'] = '\t'
|
|
1393
|
-
self.nextToken()
|
|
1394
|
-
else:
|
|
1395
|
-
command['on'] = self.nextValue()
|
|
1396
|
-
self.add(command)
|
|
1397
|
-
return True
|
|
1398
|
-
return False
|
|
1399
|
-
|
|
1400
|
-
def r_split(self, command):
|
|
1401
|
-
target = self.getVariable(command['target'])
|
|
1402
|
-
value = self.getSymbolValue(target)
|
|
1403
|
-
content = value['content'].split(self.getRuntimeValue(command['on']))
|
|
1404
|
-
elements = len(content)
|
|
1405
|
-
target['elements'] = elements
|
|
1406
|
-
target['value'] = [None] * elements
|
|
1407
|
-
|
|
1408
|
-
for index, item in enumerate(content):
|
|
1409
|
-
element = {}
|
|
1410
|
-
element['type'] = 'text'
|
|
1411
|
-
element['numeric'] = 'false'
|
|
1412
|
-
element['content'] = item
|
|
1413
|
-
target['value'][index] = element
|
|
1414
|
-
|
|
1415
|
-
return self.nextPC()
|
|
1416
|
-
|
|
1417
|
-
# Declare a stack variable
|
|
1418
|
-
def k_stack(self, command):
|
|
1419
|
-
return self.compileVariable(command)
|
|
1420
|
-
|
|
1421
|
-
def r_stack(self, command):
|
|
1422
|
-
return self.nextPC()
|
|
1423
|
-
|
|
1424
|
-
# Stop the current execution thread
|
|
1425
|
-
def k_stop(self, command):
|
|
1426
|
-
self.add(command)
|
|
1427
|
-
return True
|
|
1428
|
-
|
|
1429
|
-
def r_stop(self, command):
|
|
1430
|
-
return 0
|
|
1431
|
-
|
|
1432
|
-
# Issue a system call
|
|
1433
|
-
# system {command}
|
|
1434
|
-
def k_system(self, command):
|
|
1435
|
-
background = False
|
|
1436
|
-
token = self.nextToken()
|
|
1437
|
-
if token == 'background':
|
|
1438
|
-
self.nextToken()
|
|
1439
|
-
background = True
|
|
1440
|
-
value = self.getValue()
|
|
1441
|
-
if value != None:
|
|
1442
|
-
command['value'] = value
|
|
1443
|
-
command['background'] = background
|
|
1444
|
-
self.add(command)
|
|
1445
|
-
return True
|
|
1446
|
-
FatalError(self.compiler, 'I can\'t give this command')
|
|
1447
|
-
return False
|
|
1448
|
-
|
|
1449
|
-
def r_system(self, command):
|
|
1450
|
-
value = self.getRuntimeValue(command['value'])
|
|
1451
|
-
if value != None:
|
|
1452
|
-
if command['background']:
|
|
1453
|
-
subprocess.Popen(["sh",value,"&"])
|
|
1454
|
-
else:
|
|
1455
|
-
os.system(value)
|
|
1456
|
-
return self.nextPC()
|
|
1457
|
-
|
|
1458
|
-
# Arithmetic subtraction
|
|
1459
|
-
# take {value} from {variable}[ giving {variable}]}
|
|
1460
|
-
def k_take(self, command):
|
|
1461
|
-
# Get the (first) value
|
|
1462
|
-
command['value1'] = self.nextValue()
|
|
1463
|
-
if self.nextToken() == 'from':
|
|
1464
|
-
if self.nextIsSymbol():
|
|
1465
|
-
symbolRecord = self.getSymbolRecord()
|
|
1466
|
-
if symbolRecord['valueHolder']:
|
|
1467
|
-
if self.peek() == 'giving':
|
|
1468
|
-
# This variable must be treated as a second value
|
|
1469
|
-
command['value2'] = self.getValue()
|
|
1470
|
-
self.nextToken()
|
|
1471
|
-
command['target'] = self.nextToken()
|
|
1472
|
-
self.add(command)
|
|
1473
|
-
return True
|
|
1474
|
-
else:
|
|
1475
|
-
# Here the variable is the target
|
|
1476
|
-
command['target'] = self.getToken()
|
|
1477
|
-
self.add(command)
|
|
1478
|
-
return True
|
|
1479
|
-
self.warning(f'Core.take: Expected value holder')
|
|
1480
|
-
else:
|
|
1481
|
-
# Here we have 2 values so 'giving' must come next
|
|
1482
|
-
command['value2'] = self.getValue()
|
|
1483
|
-
if self.nextToken() == 'giving':
|
|
1484
|
-
if (self.nextIsSymbol()):
|
|
1485
|
-
command['target'] = self.getToken()
|
|
1486
|
-
self.add(command)
|
|
1487
|
-
return True
|
|
1488
|
-
else:
|
|
1489
|
-
FatalError(self.compiler, f'\'{self.getToken()}\' is not a symbol')
|
|
1490
|
-
else:
|
|
1491
|
-
self.warning(f'Core.take: Expected "giving"')
|
|
1492
|
-
return False
|
|
1493
|
-
|
|
1494
|
-
def r_take(self, command):
|
|
1495
|
-
value1 = command['value1']
|
|
1496
|
-
try:
|
|
1497
|
-
value2 = command['value2']
|
|
1498
|
-
except:
|
|
1499
|
-
value2 = None
|
|
1500
|
-
target = self.getVariable(command['target'])
|
|
1501
|
-
if not target['valueHolder']:
|
|
1502
|
-
self.variableDoesNotHoldAValueError(target['name'])
|
|
1503
|
-
return None
|
|
1504
|
-
value = self.getSymbolValue(target)
|
|
1505
|
-
if value == None:
|
|
1506
|
-
value = {}
|
|
1507
|
-
value['type'] = 'int'
|
|
1508
|
-
if value2:
|
|
1509
|
-
v1 = int(self.getRuntimeValue(value1))
|
|
1510
|
-
v2 = int(self.getRuntimeValue(value2))
|
|
1511
|
-
value['content'] = v2-v1
|
|
1512
|
-
else:
|
|
1513
|
-
v = int(self.getRuntimeValue(value))
|
|
1514
|
-
v1 = int(self.getRuntimeValue(value1))
|
|
1515
|
-
value['content'] = v-v1
|
|
1516
|
-
self.putSymbolValue(target, value)
|
|
1517
|
-
return self.nextPC()
|
|
1518
|
-
|
|
1519
|
-
# Toggle a boolean value
|
|
1520
|
-
def k_toggle(self, command):
|
|
1521
|
-
if self.nextIsSymbol():
|
|
1522
|
-
target = self.getSymbolRecord()
|
|
1523
|
-
if target['valueHolder']:
|
|
1524
|
-
command['target'] = target['name']
|
|
1525
|
-
self.add(command)
|
|
1526
|
-
return True
|
|
1527
|
-
return False
|
|
1528
|
-
|
|
1529
|
-
def r_toggle(self, command):
|
|
1530
|
-
target = self.getVariable(command['target'])
|
|
1531
|
-
value = self.getSymbolValue(target)
|
|
1532
|
-
val = {}
|
|
1533
|
-
val['type'] = 'boolean'
|
|
1534
|
-
val['content'] = not value['content']
|
|
1535
|
-
self.putSymbolValue(target, val)
|
|
1536
|
-
self.add(command)
|
|
1537
|
-
return self.nextPC()
|
|
1538
|
-
|
|
1539
|
-
# Truncate a file
|
|
1540
|
-
def k_truncate(self, command):
|
|
1541
|
-
if self.nextIsSymbol():
|
|
1542
|
-
fileRecord = self.getSymbolRecord()
|
|
1543
|
-
if fileRecord['keyword'] == 'file':
|
|
1544
|
-
command['file'] = fileRecord['name']
|
|
1545
|
-
self.add(command)
|
|
1546
|
-
return True
|
|
1547
|
-
return False
|
|
1548
|
-
|
|
1549
|
-
def r_truncate(self, command):
|
|
1550
|
-
fileRecord = self.getVariable(command['file'])
|
|
1551
|
-
fileRecord['file'].truncate()
|
|
1552
|
-
return self.nextPC()
|
|
1553
|
-
|
|
1554
|
-
# Unlock a variable
|
|
1555
|
-
def k_unlock(self, command):
|
|
1556
|
-
if self.nextIsSymbol():
|
|
1557
|
-
symbolRecord = self.getSymbolRecord()
|
|
1558
|
-
command['target'] = symbolRecord['name']
|
|
1559
|
-
self.add(command)
|
|
1560
|
-
return True
|
|
1561
|
-
return False
|
|
1562
|
-
|
|
1563
|
-
def r_unlock(self, command):
|
|
1564
|
-
target = self.getVariable(command['target'])
|
|
1565
|
-
target['locked'] = False
|
|
1566
|
-
return self.nextPC()
|
|
1567
|
-
|
|
1568
|
-
# Declare a general-purpose variable
|
|
1569
|
-
def k_variable(self, command):
|
|
1570
|
-
return self.compileVariable(command, True)
|
|
1571
|
-
|
|
1572
|
-
def r_variable(self, command):
|
|
1573
|
-
return self.nextPC()
|
|
1574
|
-
|
|
1575
|
-
# Pause for a specified time
|
|
1576
|
-
def k_wait(self, command):
|
|
1577
|
-
command['value'] = self.nextValue()
|
|
1578
|
-
multipliers = {}
|
|
1579
|
-
multipliers['milli'] = 1
|
|
1580
|
-
multipliers['millis'] = 1
|
|
1581
|
-
multipliers['tick'] = 10
|
|
1582
|
-
multipliers['ticks'] = 10
|
|
1583
|
-
multipliers['second'] = 1000
|
|
1584
|
-
multipliers['seconds'] = 1000
|
|
1585
|
-
multipliers['minute'] = 60000
|
|
1586
|
-
multipliers['minutes'] = 60000
|
|
1587
|
-
command['multiplier'] = multipliers['second']
|
|
1588
|
-
token = self.peek()
|
|
1589
|
-
if token in multipliers:
|
|
1590
|
-
self.nextToken()
|
|
1591
|
-
command['multiplier'] = multipliers[token]
|
|
1592
|
-
self.add(command)
|
|
1593
|
-
return True
|
|
1594
|
-
|
|
1595
|
-
def r_wait(self, command):
|
|
1596
|
-
value = self.getRuntimeValue(command['value']) * command['multiplier']
|
|
1597
|
-
next = self.nextPC()
|
|
1598
|
-
threading.Timer(value/1000.0, lambda: (self.run(next))).start()
|
|
1599
|
-
return 0
|
|
1600
|
-
|
|
1601
|
-
# while <condition> <action>
|
|
1602
|
-
def k_while(self, command):
|
|
1603
|
-
code = self.nextCondition()
|
|
1604
|
-
if code == None:
|
|
1605
|
-
return None
|
|
1606
|
-
# token = self.getToken()
|
|
1607
|
-
command['condition'] = code
|
|
1608
|
-
test = self.getPC()
|
|
1609
|
-
self.addCommand(command)
|
|
1610
|
-
# Set up a goto for when the test fails
|
|
1611
|
-
fail = self.getPC()
|
|
1612
|
-
cmd = {}
|
|
1613
|
-
cmd['lino'] = command['lino']
|
|
1614
|
-
cmd['domain'] = 'core'
|
|
1615
|
-
cmd['keyword'] = 'gotoPC'
|
|
1616
|
-
cmd['goto'] = 0
|
|
1617
|
-
cmd['debug'] = False
|
|
1618
|
-
self.addCommand(cmd)
|
|
1619
|
-
# Do the body of the while
|
|
1620
|
-
self.nextToken()
|
|
1621
|
-
if self.compileOne() == False:
|
|
1622
|
-
return False
|
|
1623
|
-
# Repeat the test
|
|
1624
|
-
cmd = {}
|
|
1625
|
-
cmd['lino'] = command['lino']
|
|
1626
|
-
cmd['domain'] = 'core'
|
|
1627
|
-
cmd['keyword'] = 'gotoPC'
|
|
1628
|
-
cmd['goto'] = test
|
|
1629
|
-
cmd['debug'] = False
|
|
1630
|
-
self.addCommand(cmd)
|
|
1631
|
-
# Fixup the 'goto' on completion
|
|
1632
|
-
self.getCommandAt(fail)['goto'] = self.getPC()
|
|
1633
|
-
return True
|
|
1634
|
-
|
|
1635
|
-
def r_while(self, command):
|
|
1636
|
-
test = self.program.condition.testCondition(command['condition'])
|
|
1637
|
-
if test:
|
|
1638
|
-
self.program.pc += 2
|
|
1639
|
-
else:
|
|
1640
|
-
self.program.pc += 1
|
|
1641
|
-
return self.program.pc
|
|
1642
|
-
|
|
1643
|
-
# Write to a file
|
|
1644
|
-
def k_write(self, command):
|
|
1645
|
-
if self.peek() == 'line':
|
|
1646
|
-
self.nextToken()
|
|
1647
|
-
command['line'] = True
|
|
1648
|
-
else:
|
|
1649
|
-
command['line'] = False
|
|
1650
|
-
command['value'] = self.nextValue()
|
|
1651
|
-
if self.peek() == 'to':
|
|
1652
|
-
self.nextToken()
|
|
1653
|
-
if self.nextIsSymbol():
|
|
1654
|
-
fileRecord = self.getSymbolRecord()
|
|
1655
|
-
if fileRecord['keyword'] == 'file':
|
|
1656
|
-
command['file'] = fileRecord['name']
|
|
1657
|
-
self.add(command)
|
|
1658
|
-
return True
|
|
1659
|
-
return False
|
|
1660
|
-
|
|
1661
|
-
def r_write(self, command):
|
|
1662
|
-
value = self.getRuntimeValue(command['value'])
|
|
1663
|
-
fileRecord = self.getVariable(command['file'])
|
|
1664
|
-
file = fileRecord['file']
|
|
1665
|
-
if file.mode in ['w', 'w+', 'a', 'a+']:
|
|
1666
|
-
file.write(f'{value}')
|
|
1667
|
-
if command['line']:
|
|
1668
|
-
file.write('\n')
|
|
1669
|
-
return self.nextPC()
|
|
1670
|
-
|
|
1671
|
-
#############################################################################
|
|
1672
|
-
# Support functions
|
|
1673
|
-
|
|
1674
|
-
def incdec(self, command, mode):
|
|
1675
|
-
symbolRecord = self.getVariable(command['target'])
|
|
1676
|
-
if not symbolRecord['valueHolder']:
|
|
1677
|
-
RuntimeError(self.program, f'{symbolRecord["name"]} does not hold a value')
|
|
1678
|
-
return None
|
|
1679
|
-
value = self.getSymbolValue(symbolRecord)
|
|
1680
|
-
if value == None:
|
|
1681
|
-
RuntimeError(self.program, f'{symbolRecord["name"]} has not been initialised')
|
|
1682
|
-
if mode == '+':
|
|
1683
|
-
value['content'] += 1
|
|
1684
|
-
else:
|
|
1685
|
-
value['content'] -= 1
|
|
1686
|
-
self.putSymbolValue(symbolRecord, value)
|
|
1687
|
-
return self.nextPC()
|
|
1688
|
-
|
|
1689
|
-
#############################################################################
|
|
1690
|
-
# Compile a value in this domain
|
|
1691
|
-
def compileValue(self):
|
|
1692
|
-
value = {}
|
|
1693
|
-
value['domain'] = self.getName()
|
|
1694
|
-
token = self.getToken()
|
|
1695
|
-
if self.isSymbol():
|
|
1696
|
-
value['name'] = token
|
|
1697
|
-
symbolRecord = self.getSymbolRecord()
|
|
1698
|
-
keyword = symbolRecord['keyword']
|
|
1699
|
-
|
|
1700
|
-
if keyword == 'module':
|
|
1701
|
-
value['type'] = 'module'
|
|
1702
|
-
return value
|
|
1703
|
-
|
|
1704
|
-
if keyword == 'variable':
|
|
1705
|
-
value['type'] = 'symbol'
|
|
1706
|
-
return value
|
|
1707
|
-
return None
|
|
1708
|
-
|
|
1709
|
-
value['type'] = token
|
|
1710
|
-
|
|
1711
|
-
if token == 'arg':
|
|
1712
|
-
self.nextToken()
|
|
1713
|
-
value['index'] = self.getValue()
|
|
1714
|
-
return value
|
|
1715
|
-
|
|
1716
|
-
if token in ['cos', 'sin', 'tan']:
|
|
1717
|
-
value['angle'] = self.nextValue()
|
|
1718
|
-
if self.nextToken() == 'radius':
|
|
1719
|
-
value['radius'] = self.nextValue()
|
|
1720
|
-
return value
|
|
1721
|
-
return None
|
|
1722
|
-
|
|
1723
|
-
if token in ['now', 'today', 'newline', 'tab', 'empty']:
|
|
1724
|
-
return value
|
|
1725
|
-
|
|
1726
|
-
if token in ['stringify', 'json', 'lowercase', 'uppercase', 'hash', 'random', 'float', 'integer', 'encode', 'decode']:
|
|
1727
|
-
value['content'] = self.nextValue()
|
|
1728
|
-
return value
|
|
1729
|
-
|
|
1730
|
-
if (token in ['datime', 'datetime']):
|
|
1731
|
-
value['type'] = 'datime'
|
|
1732
|
-
value['timestamp'] = self.nextValue()
|
|
1733
|
-
if self.peek() == 'format':
|
|
1734
|
-
self.nextToken()
|
|
1735
|
-
value['format'] = self.nextValue()
|
|
1736
|
-
else:
|
|
1737
|
-
value['format'] = None
|
|
1738
|
-
return value
|
|
1739
|
-
|
|
1740
|
-
if token == 'element':
|
|
1741
|
-
value['index'] = self.nextValue()
|
|
1742
|
-
if self.nextToken() == 'of':
|
|
1743
|
-
if self.nextIsSymbol():
|
|
1744
|
-
symbolRecord = self.getSymbolRecord()
|
|
1745
|
-
if symbolRecord['valueHolder']:
|
|
1746
|
-
value['target'] = symbolRecord['name']
|
|
1747
|
-
return value
|
|
1748
|
-
self.warning(f'Core.compileValue: Token \'{self.getToken()}\' does not hold a value')
|
|
1749
|
-
return None
|
|
1750
|
-
|
|
1751
|
-
if token == 'property':
|
|
1752
|
-
value['name'] = self.nextValue()
|
|
1753
|
-
if self.nextToken() == 'of':
|
|
1754
|
-
if self.nextIsSymbol():
|
|
1755
|
-
symbolRecord = self.getSymbolRecord()
|
|
1756
|
-
if symbolRecord['valueHolder']:
|
|
1757
|
-
value['target'] = symbolRecord['name']
|
|
1758
|
-
return value
|
|
1759
|
-
FatalError(self.compiler, 'Variable does not hold a value')
|
|
1760
|
-
return None
|
|
1761
|
-
|
|
1762
|
-
if token == 'arg':
|
|
1763
|
-
value['content'] = self.nextValue()
|
|
1764
|
-
if self.getToken() == 'of':
|
|
1765
|
-
if self.nextIsSymbol():
|
|
1766
|
-
symbolRecord = self.getSymbolRecord()
|
|
1767
|
-
if symbolRecord['keyword'] == 'variable':
|
|
1768
|
-
value['target'] = symbolRecord['name']
|
|
1769
|
-
return value
|
|
1770
|
-
return None
|
|
1771
|
-
|
|
1772
|
-
if token == 'trim':
|
|
1773
|
-
self.nextToken()
|
|
1774
|
-
value['content'] = self.getValue()
|
|
1775
|
-
return value
|
|
1776
|
-
|
|
1777
|
-
if self.getToken() == 'the':
|
|
1778
|
-
self.nextToken()
|
|
1779
|
-
|
|
1780
|
-
token = self.getToken()
|
|
1781
|
-
value['type'] = token
|
|
1782
|
-
|
|
1783
|
-
if token == 'args':
|
|
1784
|
-
return value
|
|
1785
|
-
|
|
1786
|
-
if token == 'elements':
|
|
1787
|
-
if self.nextIs('of'):
|
|
1788
|
-
if self.nextIsSymbol():
|
|
1789
|
-
value['name'] = self.getToken()
|
|
1790
|
-
return value
|
|
1791
|
-
return None
|
|
1792
|
-
|
|
1793
|
-
if token == 'keys':
|
|
1794
|
-
if self.nextIs('of'):
|
|
1795
|
-
value['name'] = self.nextValue()
|
|
1796
|
-
return value
|
|
1797
|
-
return None
|
|
1798
|
-
|
|
1799
|
-
if token == 'count':
|
|
1800
|
-
if self.nextIs('of'):
|
|
1801
|
-
if self.nextIsSymbol():
|
|
1802
|
-
value['name'] = self.getToken()
|
|
1803
|
-
return value
|
|
1804
|
-
return None
|
|
1805
|
-
|
|
1806
|
-
if token == 'index':
|
|
1807
|
-
if self.nextIs('of'):
|
|
1808
|
-
if self.nextIsSymbol():
|
|
1809
|
-
value['variable'] = self.getSymbolRecord()['name']
|
|
1810
|
-
if self.peek() == 'in':
|
|
1811
|
-
value['value'] = None
|
|
1812
|
-
value['type'] = 'indexOf'
|
|
1813
|
-
if self.nextIsSymbol():
|
|
1814
|
-
value['target'] = self.getSymbolRecord()['name']
|
|
1815
|
-
return value
|
|
1816
|
-
else:
|
|
1817
|
-
value['name'] = self.getToken()
|
|
1818
|
-
return value
|
|
1819
|
-
else:
|
|
1820
|
-
value['value'] = self.getValue()
|
|
1821
|
-
if self.nextIs('in'):
|
|
1822
|
-
value['variable'] = None
|
|
1823
|
-
value['type'] = 'indexOf'
|
|
1824
|
-
if self.nextIsSymbol():
|
|
1825
|
-
value['target'] = self.getSymbolRecord()['name']
|
|
1826
|
-
return value
|
|
1827
|
-
return None
|
|
1828
|
-
|
|
1829
|
-
if token == 'value':
|
|
1830
|
-
if self.nextIs('of'):
|
|
1831
|
-
v = self.nextValue()
|
|
1832
|
-
if v !=None:
|
|
1833
|
-
value['type'] = 'valueOf'
|
|
1834
|
-
value['content'] = v
|
|
1835
|
-
return value
|
|
1836
|
-
return None
|
|
1837
|
-
|
|
1838
|
-
if token == 'length':
|
|
1839
|
-
value['type'] = 'lengthOf'
|
|
1840
|
-
if self.nextIs('of'):
|
|
1841
|
-
value['content'] = self.nextValue()
|
|
1842
|
-
return value
|
|
1843
|
-
return None
|
|
1844
|
-
|
|
1845
|
-
if token in ['left', 'right']:
|
|
1846
|
-
value['count'] = self.nextValue()
|
|
1847
|
-
if self.nextToken() == 'of':
|
|
1848
|
-
value['content'] = self.nextValue()
|
|
1849
|
-
return value
|
|
1850
|
-
return None
|
|
1851
|
-
|
|
1852
|
-
if token == 'from':
|
|
1853
|
-
value['start'] = self.nextValue()
|
|
1854
|
-
if self.peek() == 'to':
|
|
1855
|
-
self.nextToken()
|
|
1856
|
-
value['to'] = self.nextValue()
|
|
1857
|
-
else:
|
|
1858
|
-
value['to'] = None
|
|
1859
|
-
if self.nextToken() == 'of':
|
|
1860
|
-
value['content'] = self.nextValue()
|
|
1861
|
-
return value
|
|
1862
|
-
|
|
1863
|
-
if token == 'position':
|
|
1864
|
-
if self.nextIs('of'):
|
|
1865
|
-
value['last'] = False
|
|
1866
|
-
if self.nextIs('the'):
|
|
1867
|
-
if self.nextIs('last'):
|
|
1868
|
-
self.nextToken()
|
|
1869
|
-
value['last'] = True
|
|
1870
|
-
value['needle'] = self.getValue()
|
|
1871
|
-
if self.nextToken() == 'in':
|
|
1872
|
-
value['haystack'] = self.nextValue()
|
|
1873
|
-
return value
|
|
1874
|
-
|
|
1875
|
-
if token == 'message':
|
|
1876
|
-
return value
|
|
1877
|
-
|
|
1878
|
-
if token == 'timestamp':
|
|
1879
|
-
value['format'] = None
|
|
1880
|
-
if self.peek() == 'of':
|
|
1881
|
-
self.nextToken()
|
|
1882
|
-
value['datime'] = self.nextValue()
|
|
1883
|
-
if self.peek() == 'format':
|
|
1884
|
-
self.nextToken()
|
|
1885
|
-
value['format'] = self.nextValue()
|
|
1886
|
-
return value
|
|
1887
|
-
|
|
1888
|
-
if token == 'files':
|
|
1889
|
-
token = self.nextToken()
|
|
1890
|
-
if token in ['in', 'of']:
|
|
1891
|
-
value['target'] = self.nextValue()
|
|
1892
|
-
return value
|
|
1893
|
-
return None
|
|
1894
|
-
|
|
1895
|
-
if token == 'weekday':
|
|
1896
|
-
value['type'] = 'weekday'
|
|
1897
|
-
return value
|
|
1898
|
-
|
|
1899
|
-
if token == 'mem' or token == 'memory':
|
|
1900
|
-
value['type'] = 'memory'
|
|
1901
|
-
return value
|
|
1902
|
-
|
|
1903
|
-
if token == 'error':
|
|
1904
|
-
if self.peek() == 'code':
|
|
1905
|
-
self.nextToken()
|
|
1906
|
-
value['item'] = 'errorCode'
|
|
1907
|
-
return value
|
|
1908
|
-
if self.peek() == 'reason':
|
|
1909
|
-
self.nextToken()
|
|
1910
|
-
value['item'] = 'errorReason'
|
|
1911
|
-
return value
|
|
1912
|
-
|
|
1913
|
-
if token == 'type':
|
|
1914
|
-
if self.nextIs('of'):
|
|
1915
|
-
value['value'] = self.nextValue()
|
|
1916
|
-
return value
|
|
1917
|
-
return None
|
|
1918
|
-
|
|
1919
|
-
if token == 'modification':
|
|
1920
|
-
if self.nextIs('time'):
|
|
1921
|
-
if self.nextIs('of'):
|
|
1922
|
-
value['fileName'] = self.nextValue()
|
|
1923
|
-
return value
|
|
1924
|
-
return None
|
|
1925
|
-
|
|
1926
|
-
if token == 'system':
|
|
1927
|
-
value['command'] = self.nextValue()
|
|
1928
|
-
return value
|
|
1929
|
-
|
|
1930
|
-
return None
|
|
1931
|
-
|
|
1932
|
-
#############################################################################
|
|
1933
|
-
# Modify a value or leave it unchanged.
|
|
1934
|
-
def modifyValue(self, value):
|
|
1935
|
-
if self.peek() == 'modulo':
|
|
1936
|
-
self.nextToken()
|
|
1937
|
-
mv = {}
|
|
1938
|
-
mv['domain'] = 'core'
|
|
1939
|
-
mv['type'] = 'modulo'
|
|
1940
|
-
mv['content'] = value
|
|
1941
|
-
mv['modval'] = self.nextValue()
|
|
1942
|
-
value = mv
|
|
1943
|
-
|
|
1944
|
-
return value
|
|
1945
|
-
|
|
1946
|
-
#############################################################################
|
|
1947
|
-
# Value handlers
|
|
1948
|
-
|
|
1949
|
-
def v_args(self, v):
|
|
1950
|
-
value = {}
|
|
1951
|
-
value['type'] = 'text'
|
|
1952
|
-
value['content'] = json.dumps(self.program.argv)
|
|
1953
|
-
return value
|
|
1954
|
-
|
|
1955
|
-
def v_arg(self, v):
|
|
1956
|
-
value = {}
|
|
1957
|
-
value['type'] = 'text'
|
|
1958
|
-
index = self.getRuntimeValue(v['index'])
|
|
1959
|
-
if index >= len(self.program.argv):
|
|
1960
|
-
RuntimeError(self.program, 'Index exceeds # of args')
|
|
1961
|
-
value['content'] = self.program.argv[index]
|
|
1962
|
-
return value
|
|
1963
|
-
|
|
1964
|
-
def v_boolean(self, v):
|
|
1965
|
-
value = {}
|
|
1966
|
-
value['type'] = 'boolean'
|
|
1967
|
-
value['content'] = v['content']
|
|
1968
|
-
return value
|
|
1969
|
-
|
|
1970
|
-
def v_cos(self, v):
|
|
1971
|
-
angle = self.getRuntimeValue(v['angle'])
|
|
1972
|
-
radius = self.getRuntimeValue(v['radius'])
|
|
1973
|
-
value = {}
|
|
1974
|
-
value['type'] = 'int'
|
|
1975
|
-
value['content'] = round(math.cos(angle * 0.01745329) * radius)
|
|
1976
|
-
return value
|
|
1977
|
-
|
|
1978
|
-
def v_count(self, v):
|
|
1979
|
-
variable = self.getVariable(v['name'])
|
|
1980
|
-
content = variable['value'][variable['index']]['content']
|
|
1981
|
-
value = {}
|
|
1982
|
-
value['type'] = 'int'
|
|
1983
|
-
value['content'] = len(content)
|
|
1984
|
-
return value
|
|
1985
|
-
|
|
1986
|
-
def v_datime(self, v):
|
|
1987
|
-
ts = self.getRuntimeValue(v['timestamp'])
|
|
1988
|
-
fmt = v['format']
|
|
1989
|
-
if fmt == None:
|
|
1990
|
-
fmt = '%b %d %Y %H:%M:%S'
|
|
1991
|
-
else:
|
|
1992
|
-
fmt = self.getRuntimeValue(fmt)
|
|
1993
|
-
value = {}
|
|
1994
|
-
value['type'] = 'text'
|
|
1995
|
-
value['content'] = datetime.fromtimestamp(ts/1000).strftime(fmt)
|
|
1996
|
-
return value
|
|
1997
|
-
|
|
1998
|
-
def v_decode(self, v):
|
|
1999
|
-
content = self.getRuntimeValue(v['content'])
|
|
2000
|
-
value = {}
|
|
2001
|
-
value['type'] = 'text'
|
|
2002
|
-
if self.encoding == 'utf-8':
|
|
2003
|
-
value['content'] = content.decode('utf-8')
|
|
2004
|
-
elif self.encoding == 'base64':
|
|
2005
|
-
base64_bytes = content.encode('ascii')
|
|
2006
|
-
message_bytes = base64.b64decode(base64_bytes)
|
|
2007
|
-
value['content'] = message_bytes.decode('ascii')
|
|
2008
|
-
elif self.encoding == 'hex':
|
|
2009
|
-
hex_bytes = content.encode('utf-8')
|
|
2010
|
-
message_bytes = binascii.unhexlify(hex_bytes)
|
|
2011
|
-
value['content'] = message_bytes.decode('utf-8')
|
|
2012
|
-
else:
|
|
2013
|
-
value = v
|
|
2014
|
-
return value
|
|
2015
|
-
|
|
2016
|
-
def v_element(self, v):
|
|
2017
|
-
index = self.getRuntimeValue(v['index'])
|
|
2018
|
-
target = self.getVariable(v['target'])
|
|
2019
|
-
val = self.getSymbolValue(target)
|
|
2020
|
-
content = val['content']
|
|
2021
|
-
value = {}
|
|
2022
|
-
value['type'] = 'int' if isinstance(content, int) else 'text'
|
|
2023
|
-
if type(content) == list:
|
|
2024
|
-
try:
|
|
2025
|
-
value['content'] = content[index]
|
|
2026
|
-
return value
|
|
2027
|
-
except:
|
|
2028
|
-
RuntimeError(self.program, 'Index out of range')
|
|
2029
|
-
# lino = self.program.code[self.program.pc]['lino']
|
|
2030
|
-
RuntimeError(self.program, 'Item is not a list')
|
|
2031
|
-
|
|
2032
|
-
def v_elements(self, v):
|
|
2033
|
-
var = self.getVariable(v['name'])
|
|
2034
|
-
value = {}
|
|
2035
|
-
value['type'] = 'int'
|
|
2036
|
-
value['content'] = var['elements']
|
|
2037
|
-
return value
|
|
2038
|
-
|
|
2039
|
-
def v_empty(self, v):
|
|
2040
|
-
value = {}
|
|
2041
|
-
value['type'] = 'text'
|
|
2042
|
-
value['content'] = ''
|
|
2043
|
-
return value
|
|
2044
|
-
|
|
2045
|
-
def v_encode(self, v):
|
|
2046
|
-
content = self.getRuntimeValue(v['content'])
|
|
2047
|
-
value = {}
|
|
2048
|
-
value['type'] = 'text'
|
|
2049
|
-
if self.encoding == 'utf-8':
|
|
2050
|
-
value['content'] = content.encode('utf-8')
|
|
2051
|
-
elif self.encoding == 'base64':
|
|
2052
|
-
data_bytes = content.encode('ascii')
|
|
2053
|
-
base64_bytes = base64.b64encode(data_bytes)
|
|
2054
|
-
value['content'] = base64_bytes.decode('ascii')
|
|
2055
|
-
elif self.encoding == 'hex':
|
|
2056
|
-
data_bytes = content.encode('utf-8')
|
|
2057
|
-
hex_bytes = binascii.hexlify(data_bytes)
|
|
2058
|
-
value['content'] = hex_bytes.decode('utf-8')
|
|
2059
|
-
else:
|
|
2060
|
-
value = v
|
|
2061
|
-
return value
|
|
2062
|
-
|
|
2063
|
-
def v_error(self, v):
|
|
2064
|
-
global errorCode, errorReason
|
|
2065
|
-
value = {}
|
|
2066
|
-
if v['item'] == 'errorCode':
|
|
2067
|
-
value['type'] = 'int'
|
|
2068
|
-
value['content'] = errorCode
|
|
2069
|
-
elif v['item'] == 'errorReason':
|
|
2070
|
-
value['type'] = 'text'
|
|
2071
|
-
value['content'] = errorReason
|
|
2072
|
-
return value
|
|
2073
|
-
|
|
2074
|
-
def v_files(self, v):
|
|
2075
|
-
v = self.getRuntimeValue(v['target'])
|
|
2076
|
-
value = {}
|
|
2077
|
-
value['type'] = 'text'
|
|
2078
|
-
value['content'] = os.listdir(v)
|
|
2079
|
-
return value
|
|
2080
|
-
|
|
2081
|
-
def v_float(self, v):
|
|
2082
|
-
val = self.getRuntimeValue(v['content'])
|
|
2083
|
-
value = {}
|
|
2084
|
-
value['type'] = 'float'
|
|
2085
|
-
try:
|
|
2086
|
-
value['content'] = float(val)
|
|
2087
|
-
except:
|
|
2088
|
-
RuntimeWarning(self.program, f'Value cannot be parsed as floating-point')
|
|
2089
|
-
value['content'] = 0.0
|
|
2090
|
-
return value
|
|
2091
|
-
|
|
2092
|
-
def v_from(self, v):
|
|
2093
|
-
content = self.getRuntimeValue(v['content'])
|
|
2094
|
-
start = self.getRuntimeValue(v['start'])
|
|
2095
|
-
to = v['to']
|
|
2096
|
-
if not to == None:
|
|
2097
|
-
to = self.getRuntimeValue(to)
|
|
2098
|
-
value = {}
|
|
2099
|
-
value['type'] = 'text'
|
|
2100
|
-
if to == None:
|
|
2101
|
-
value['content'] = content[start:]
|
|
2102
|
-
else:
|
|
2103
|
-
value['content'] = content[start:to]
|
|
2104
|
-
return value
|
|
2105
|
-
|
|
2106
|
-
def v_hash(self, v):
|
|
2107
|
-
hashval = self.getRuntimeValue(v['content'])
|
|
2108
|
-
value = {}
|
|
2109
|
-
value['type'] = 'text'
|
|
2110
|
-
value['content'] = hashlib.sha256(hashval.encode('utf-8')).hexdigest()
|
|
2111
|
-
return value
|
|
2112
|
-
|
|
2113
|
-
def v_index(self, v):
|
|
2114
|
-
value = {}
|
|
2115
|
-
value['type'] = 'int'
|
|
2116
|
-
value['content'] = self.getVariable(v['name'])['index']
|
|
2117
|
-
return value
|
|
2118
|
-
|
|
2119
|
-
def v_indexOf(self, v):
|
|
2120
|
-
value = v['value']
|
|
2121
|
-
if value == None:
|
|
2122
|
-
value = self.getSymbolValue(v['variable'])['content']
|
|
2123
|
-
else:
|
|
2124
|
-
value = self.getRuntimeValue(value)
|
|
2125
|
-
target = self.getVariable(v['target'])
|
|
2126
|
-
data = self.getSymbolValue(target)['content']
|
|
2127
|
-
index = -1
|
|
2128
|
-
for n in range(0, len(data)):
|
|
2129
|
-
if data[n] == value:
|
|
2130
|
-
index = n
|
|
2131
|
-
break
|
|
2132
|
-
retval = {}
|
|
2133
|
-
retval['type'] = 'int'
|
|
2134
|
-
retval['content'] = index
|
|
2135
|
-
return retval
|
|
2136
|
-
|
|
2137
|
-
def v_integer(self, v):
|
|
2138
|
-
val = self.getRuntimeValue(v['content'])
|
|
2139
|
-
value = {}
|
|
2140
|
-
value['type'] = 'int'
|
|
2141
|
-
value['content'] = int(val)
|
|
2142
|
-
return value
|
|
2143
|
-
|
|
2144
|
-
def v_json(self, v):
|
|
2145
|
-
item = self.getRuntimeValue(v['content'])
|
|
2146
|
-
value = {}
|
|
2147
|
-
value['type'] = 'object'
|
|
2148
|
-
try:
|
|
2149
|
-
value['content'] = json.loads(item)
|
|
2150
|
-
except:
|
|
2151
|
-
RuntimeError(self.program, 'Cannot encode value')
|
|
2152
|
-
return value
|
|
2153
|
-
|
|
2154
|
-
def v_keys(self, v):
|
|
2155
|
-
value = {}
|
|
2156
|
-
value['type'] = 'int'
|
|
2157
|
-
value['content'] = list(self.getRuntimeValue(v['name']).keys())
|
|
2158
|
-
return value
|
|
2159
|
-
|
|
2160
|
-
def v_left(self, v):
|
|
2161
|
-
content = self.getRuntimeValue(v['content'])
|
|
2162
|
-
count = self.getRuntimeValue(v['count'])
|
|
2163
|
-
value = {}
|
|
2164
|
-
value['type'] = 'text'
|
|
2165
|
-
value['content'] = content[0:count]
|
|
2166
|
-
return value
|
|
2167
|
-
|
|
2168
|
-
def v_lengthOf(self, v):
|
|
2169
|
-
content = self.getRuntimeValue(v['content'])
|
|
2170
|
-
if type(content) == str:
|
|
2171
|
-
value = {}
|
|
2172
|
-
value['type'] = 'int'
|
|
2173
|
-
value['content'] = len(content)
|
|
2174
|
-
return value
|
|
2175
|
-
RuntimeError(self.program, 'Value is not a string')
|
|
2176
|
-
|
|
2177
|
-
def v_lowercase(self, v):
|
|
2178
|
-
content = self.getRuntimeValue(v['content'])
|
|
2179
|
-
value = {}
|
|
2180
|
-
value['type'] = 'text'
|
|
2181
|
-
value['content'] = content.lower()
|
|
2182
|
-
return value
|
|
2183
|
-
|
|
2184
|
-
def v_memory(self, v):
|
|
2185
|
-
process: Process = Process(os.getpid())
|
|
2186
|
-
megabytes: float = process.memory_info().rss / (1024 * 1024)
|
|
2187
|
-
value = {}
|
|
2188
|
-
value['type'] = 'float'
|
|
2189
|
-
value['content'] = megabytes
|
|
2190
|
-
return value
|
|
2191
|
-
|
|
2192
|
-
def v_message(self, v):
|
|
2193
|
-
value = {}
|
|
2194
|
-
value['type'] = 'text'
|
|
2195
|
-
value['content'] = self.program.message
|
|
2196
|
-
return value
|
|
2197
|
-
|
|
2198
|
-
def v_modification(self, v):
|
|
2199
|
-
fileName = self.getRuntimeValue(v['fileName'])
|
|
2200
|
-
ts = int(os.stat(fileName).st_mtime)
|
|
2201
|
-
value = {}
|
|
2202
|
-
value['type'] = 'int'
|
|
2203
|
-
value['content'] = ts
|
|
2204
|
-
return value
|
|
2205
|
-
|
|
2206
|
-
def v_modulo(self, v):
|
|
2207
|
-
val = self.getRuntimeValue(v['content'])
|
|
2208
|
-
modval = self.getRuntimeValue(v['modval'])
|
|
2209
|
-
value = {}
|
|
2210
|
-
value['type'] = 'int'
|
|
2211
|
-
value['content'] = val % modval
|
|
2212
|
-
return value
|
|
2213
|
-
|
|
2214
|
-
def v_newline(self, v):
|
|
2215
|
-
value = {}
|
|
2216
|
-
value['type'] = 'text'
|
|
2217
|
-
value['content'] = '\n'
|
|
2218
|
-
return value
|
|
2219
|
-
|
|
2220
|
-
def v_now(self, v):
|
|
2221
|
-
value = {}
|
|
2222
|
-
value['type'] = 'int'
|
|
2223
|
-
value['content'] = getTimestamp(time.time())
|
|
2224
|
-
return value
|
|
2225
|
-
|
|
2226
|
-
def v_position(self, v):
|
|
2227
|
-
needle = self.getRuntimeValue(v['needle'])
|
|
2228
|
-
haystack = self.getRuntimeValue(v['haystack'])
|
|
2229
|
-
last = v['last']
|
|
2230
|
-
value = {}
|
|
2231
|
-
value['type'] = 'int'
|
|
2232
|
-
value['content'] = haystack.rfind(needle) if last else haystack.find(needle)
|
|
2233
|
-
return value
|
|
2234
|
-
|
|
2235
|
-
def v_property(self, v):
|
|
2236
|
-
propertyValue = self.getRuntimeValue(v['name'])
|
|
2237
|
-
if 'target' in v:
|
|
2238
|
-
targetName = v['target']
|
|
2239
|
-
target = self.getVariable(targetName)
|
|
2240
|
-
targetValue = self.getRuntimeValue(target)
|
|
2241
|
-
else:
|
|
2242
|
-
targetValue = self.getRuntimeValue(v['value'])
|
|
2243
|
-
try:
|
|
2244
|
-
val = targetValue[propertyValue]
|
|
2245
|
-
except:
|
|
2246
|
-
RuntimeError(self.program, f'This value does not have the property \'{propertyValue}\'')
|
|
2247
|
-
return None
|
|
2248
|
-
value = {}
|
|
2249
|
-
value['content'] = val
|
|
2250
|
-
if isinstance(v, numbers.Number):
|
|
2251
|
-
value['type'] = 'int'
|
|
2252
|
-
else:
|
|
2253
|
-
value['type'] = 'text'
|
|
2254
|
-
return value
|
|
2255
|
-
|
|
2256
|
-
def v_random(self, v):
|
|
2257
|
-
limit = self.getRuntimeValue(v['content'])
|
|
2258
|
-
value = {}
|
|
2259
|
-
value['type'] = 'int'
|
|
2260
|
-
value['content'] = randrange(0, limit)
|
|
2261
|
-
return value
|
|
2262
|
-
|
|
2263
|
-
def v_right(self, v):
|
|
2264
|
-
content = self.getRuntimeValue(v['content'])
|
|
2265
|
-
count = self.getRuntimeValue(v['count'])
|
|
2266
|
-
value = {}
|
|
2267
|
-
value['type'] = 'text'
|
|
2268
|
-
value['content'] = content[-count:]
|
|
2269
|
-
return value
|
|
2270
|
-
|
|
2271
|
-
def v_sin(self, v):
|
|
2272
|
-
angle = self.getRuntimeValue(v['angle'])
|
|
2273
|
-
radius = self.getRuntimeValue(v['radius'])
|
|
2274
|
-
value = {}
|
|
2275
|
-
value['type'] = 'int'
|
|
2276
|
-
value['content'] = round(math.sin(angle * 0.01745329) * radius)
|
|
2277
|
-
return value
|
|
2278
|
-
|
|
2279
|
-
def v_stringify(self, v):
|
|
2280
|
-
item = self.getRuntimeValue(v['content'])
|
|
2281
|
-
value = {}
|
|
2282
|
-
value['type'] = 'text'
|
|
2283
|
-
value['content'] = json.dumps(item)
|
|
2284
|
-
return value
|
|
2285
|
-
|
|
2286
|
-
# This is used by the expression evaluator to get the value of a symbol
|
|
2287
|
-
def v_symbol(self, symbolRecord):
|
|
2288
|
-
if symbolRecord['keyword'] == 'variable':
|
|
2289
|
-
return self.getSymbolValue(symbolRecord)
|
|
2290
|
-
else:
|
|
2291
|
-
return None
|
|
2292
|
-
|
|
2293
|
-
def v_system(self, v):
|
|
2294
|
-
command = self.getRuntimeValue(v['command'])
|
|
2295
|
-
result = os.popen(command).read()
|
|
2296
|
-
value = {}
|
|
2297
|
-
value['type'] = 'text'
|
|
2298
|
-
value['content'] = result
|
|
2299
|
-
return value
|
|
2300
|
-
|
|
2301
|
-
def v_tab(self, v):
|
|
2302
|
-
value = {}
|
|
2303
|
-
value['type'] = 'text'
|
|
2304
|
-
value['content'] = '\t'
|
|
2305
|
-
return value
|
|
2306
|
-
|
|
2307
|
-
def v_tan(self, v):
|
|
2308
|
-
angle = self.getRuntimeValue(v['angle'])
|
|
2309
|
-
radius = self.getRuntimeValue(v['radius'])
|
|
2310
|
-
value = {}
|
|
2311
|
-
value['type'] = 'int'
|
|
2312
|
-
value['content'] = round(math.tan(angle * 0.01745329) * radius)
|
|
2313
|
-
return value
|
|
2314
|
-
|
|
2315
|
-
def v_timestamp(self, v):
|
|
2316
|
-
value = {}
|
|
2317
|
-
value['type'] = 'int'
|
|
2318
|
-
fmt = v['format']
|
|
2319
|
-
if fmt == None:
|
|
2320
|
-
value['content'] = int(time.time())
|
|
2321
|
-
else:
|
|
2322
|
-
fmt = self.getRuntimeValue(fmt)
|
|
2323
|
-
dt = self.getRuntimeValue(v['datime'])
|
|
2324
|
-
spec = datetime.strptime(dt, fmt)
|
|
2325
|
-
t = datetime.now().replace(hour=spec.hour, minute=spec.minute, second=spec.second, microsecond=0)
|
|
2326
|
-
value['content'] = int(t.timestamp())
|
|
2327
|
-
return value
|
|
2328
|
-
|
|
2329
|
-
def v_today(self, v):
|
|
2330
|
-
value = {}
|
|
2331
|
-
value['type'] = 'int'
|
|
2332
|
-
value['content'] = int(datetime.combine(datetime.now().date(),datetime.min.time()).timestamp())*1000
|
|
2333
|
-
return value
|
|
2334
|
-
|
|
2335
|
-
def v_trim(self, v):
|
|
2336
|
-
v = self.getRuntimeValue(v['content'])
|
|
2337
|
-
value = {}
|
|
2338
|
-
value['type'] = 'text'
|
|
2339
|
-
value['content'] = v.strip()
|
|
2340
|
-
return value
|
|
2341
|
-
|
|
2342
|
-
def v_type(self, v):
|
|
2343
|
-
value = {}
|
|
2344
|
-
value['type'] = 'text'
|
|
2345
|
-
val = self.getRuntimeValue(v['value'])
|
|
2346
|
-
if val is None:
|
|
2347
|
-
value['content'] = 'none'
|
|
2348
|
-
elif type(val) is str:
|
|
2349
|
-
value['content'] = 'text'
|
|
2350
|
-
elif type(val) is int:
|
|
2351
|
-
value['content'] = 'numeric'
|
|
2352
|
-
elif type(val) is bool:
|
|
2353
|
-
value['content'] = 'boolean'
|
|
2354
|
-
elif type(val) is list:
|
|
2355
|
-
value['content'] = 'list'
|
|
2356
|
-
elif type(val) is dict:
|
|
2357
|
-
value['content'] = 'object'
|
|
2358
|
-
return value
|
|
2359
|
-
|
|
2360
|
-
def v_uppercase(self, v):
|
|
2361
|
-
content = self.getRuntimeValue(v['content'])
|
|
2362
|
-
value = {}
|
|
2363
|
-
value['type'] = 'text'
|
|
2364
|
-
value['content'] = content.upper()
|
|
2365
|
-
return value
|
|
2366
|
-
|
|
2367
|
-
def v_valueOf(self, v):
|
|
2368
|
-
v = self.getRuntimeValue(v['content'])
|
|
2369
|
-
value = {}
|
|
2370
|
-
value['type'] = 'int'
|
|
2371
|
-
value['content'] = int(v)
|
|
2372
|
-
return value
|
|
2373
|
-
|
|
2374
|
-
def v_weekday(self, v):
|
|
2375
|
-
value = {}
|
|
2376
|
-
value['type'] = 'int'
|
|
2377
|
-
value['content'] = datetime.today().weekday()
|
|
2378
|
-
return value
|
|
2379
|
-
|
|
2380
|
-
#############################################################################
|
|
2381
|
-
# Compile a condition
|
|
2382
|
-
def compileCondition(self):
|
|
2383
|
-
condition = Condition()
|
|
2384
|
-
|
|
2385
|
-
if self.getToken() == 'not':
|
|
2386
|
-
condition.type = 'not'
|
|
2387
|
-
condition.value = self.nextValue()
|
|
2388
|
-
return condition
|
|
2389
|
-
|
|
2390
|
-
if self.getToken() == 'file':
|
|
2391
|
-
path = self.nextValue()
|
|
2392
|
-
if self.peek() == 'exists':
|
|
2393
|
-
condition.type = 'exists'
|
|
2394
|
-
condition.path = path
|
|
2395
|
-
self.nextToken()
|
|
2396
|
-
return condition
|
|
2397
|
-
return None
|
|
2398
|
-
|
|
2399
|
-
value = self.getValue()
|
|
2400
|
-
if value == None:
|
|
2401
|
-
return None
|
|
2402
|
-
|
|
2403
|
-
condition.value1 = value
|
|
2404
|
-
token = self.peek()
|
|
2405
|
-
condition.type = token
|
|
2406
|
-
|
|
2407
|
-
if token == 'has':
|
|
2408
|
-
self.nextToken()
|
|
2409
|
-
if self.nextToken() == 'property':
|
|
2410
|
-
prop = self.nextValue()
|
|
2411
|
-
condition.type = 'hasProperty'
|
|
2412
|
-
condition.property = prop
|
|
2413
|
-
return condition
|
|
2414
|
-
return None
|
|
2415
|
-
|
|
2416
|
-
if token == 'does':
|
|
2417
|
-
self.nextToken()
|
|
2418
|
-
if self.nextIs('not'):
|
|
2419
|
-
if self.nextIs('have'):
|
|
2420
|
-
if self.nextToken() == 'property':
|
|
2421
|
-
prop = self.nextValue()
|
|
2422
|
-
condition.type = 'hasProperty'
|
|
2423
|
-
condition.property = prop
|
|
2424
|
-
condition.negate = not condition.negate
|
|
2425
|
-
return condition
|
|
2426
|
-
return None
|
|
2427
|
-
|
|
2428
|
-
if token in ['starts', 'ends']:
|
|
2429
|
-
self.nextToken()
|
|
2430
|
-
if self.nextToken() == 'with':
|
|
2431
|
-
condition.value2 = self.nextValue()
|
|
2432
|
-
return condition
|
|
2433
|
-
|
|
2434
|
-
if token == 'includes':
|
|
2435
|
-
condition.value2 = self.nextValue()
|
|
2436
|
-
return condition
|
|
2437
|
-
|
|
2438
|
-
if token == 'is':
|
|
2439
|
-
token = self.nextToken()
|
|
2440
|
-
if self.peek() == 'not':
|
|
2441
|
-
self.nextToken()
|
|
2442
|
-
condition.negate = True
|
|
2443
|
-
token = self.nextToken()
|
|
2444
|
-
condition.type = token
|
|
2445
|
-
if token in ['numeric', 'string', 'boolean', 'none', 'list', 'object', 'even', 'odd', 'empty']:
|
|
2446
|
-
return condition
|
|
2447
|
-
if token in ['greater', 'less']:
|
|
2448
|
-
if self.nextToken() == 'than':
|
|
2449
|
-
condition.value2 = self.nextValue()
|
|
2450
|
-
return condition
|
|
2451
|
-
condition.type = 'is'
|
|
2452
|
-
condition.value2 = self.getValue()
|
|
2453
|
-
return condition
|
|
2454
|
-
|
|
2455
|
-
if condition.value1:
|
|
2456
|
-
# It's a boolean if
|
|
2457
|
-
condition.type = 'boolean'
|
|
2458
|
-
return condition
|
|
2459
|
-
|
|
2460
|
-
self.warning(f'Core.compileCondition: I can\'t get a conditional:')
|
|
2461
|
-
return None
|
|
2462
|
-
|
|
2463
|
-
def isNegate(self):
|
|
2464
|
-
token = self.getToken()
|
|
2465
|
-
if token == 'not':
|
|
2466
|
-
self.nextToken()
|
|
2467
|
-
return True
|
|
2468
|
-
return False
|
|
2469
|
-
|
|
2470
|
-
#############################################################################
|
|
2471
|
-
# Condition handlers
|
|
2472
|
-
|
|
2473
|
-
def c_boolean(self, condition):
|
|
2474
|
-
value = self.getRuntimeValue(condition.value1)
|
|
2475
|
-
if type(value) == bool:
|
|
2476
|
-
return not value if condition.negate else value
|
|
2477
|
-
elif type(value) == int:
|
|
2478
|
-
return True if condition.negate else False
|
|
2479
|
-
elif type(value) == str:
|
|
2480
|
-
if value.lower() == 'true':
|
|
2481
|
-
return False if condition.negate else True
|
|
2482
|
-
elif value.lower() == 'false':
|
|
2483
|
-
return True if condition.negate else False
|
|
2484
|
-
else:
|
|
2485
|
-
return True if condition.negate else False
|
|
2486
|
-
return False
|
|
2487
|
-
|
|
2488
|
-
def c_empty(self, condition):
|
|
2489
|
-
value = self.getRuntimeValue(condition.value1)
|
|
2490
|
-
if value == None:
|
|
2491
|
-
comparison = True
|
|
2492
|
-
else:
|
|
2493
|
-
comparison = len(value) == 0
|
|
2494
|
-
return not comparison if condition.negate else comparison
|
|
2495
|
-
|
|
2496
|
-
def c_ends(self, condition):
|
|
2497
|
-
value1 = self.getRuntimeValue(condition.value1)
|
|
2498
|
-
value2 = self.getRuntimeValue(condition.value2)
|
|
2499
|
-
return value1.endswith(value2)
|
|
2500
|
-
|
|
2501
|
-
def c_even(self, condition):
|
|
2502
|
-
return self.getRuntimeValue(condition.value1) % 2 == 0
|
|
2503
|
-
|
|
2504
|
-
def c_exists(self, condition):
|
|
2505
|
-
path = self.getRuntimeValue(condition.path)
|
|
2506
|
-
return os.path.exists(path)
|
|
2507
|
-
|
|
2508
|
-
def c_greater(self, condition):
|
|
2509
|
-
comparison = self.program.compare(condition.value1, condition.value2)
|
|
2510
|
-
return comparison <= 0 if condition.negate else comparison > 0
|
|
2511
|
-
|
|
2512
|
-
def c_hasProperty(self, condition):
|
|
2513
|
-
value = self.getRuntimeValue(condition.value1)
|
|
2514
|
-
prop = self.getRuntimeValue(condition.property)
|
|
2515
|
-
try:
|
|
2516
|
-
value[prop]
|
|
2517
|
-
hasProp = True
|
|
2518
|
-
except:
|
|
2519
|
-
hasProp = False
|
|
2520
|
-
return not hasProp if condition.negate else hasProp
|
|
2521
|
-
|
|
2522
|
-
def c_includes(self, condition):
|
|
2523
|
-
value1 = self.getRuntimeValue(condition.value1)
|
|
2524
|
-
value2 = self.getRuntimeValue(condition.value2)
|
|
2525
|
-
return value2 in value1
|
|
2526
|
-
|
|
2527
|
-
def c_is(self, condition):
|
|
2528
|
-
comparison = self.program.compare(condition.value1, condition.value2)
|
|
2529
|
-
return comparison != 0 if condition.negate else comparison == 0
|
|
2530
|
-
|
|
2531
|
-
def c_less(self, condition):
|
|
2532
|
-
comparison = self.program.compare(condition.value1, condition.value2)
|
|
2533
|
-
return comparison >= 0 if condition.negate else comparison < 0
|
|
2534
|
-
|
|
2535
|
-
def c_list(self, condition):
|
|
2536
|
-
comparison = type(self.getRuntimeValue(condition.value1)) is list
|
|
2537
|
-
return not comparison if condition.negate else comparison
|
|
2538
|
-
|
|
2539
|
-
def c_numeric(self, condition):
|
|
2540
|
-
comparison = type(self.getRuntimeValue(condition.value1)) is int
|
|
2541
|
-
return not comparison if condition.negate else comparison
|
|
2542
|
-
|
|
2543
|
-
def c_none(self, condition):
|
|
2544
|
-
comparison = self.getRuntimeValue(condition.value1) is None
|
|
2545
|
-
return not comparison if condition.negate else comparison
|
|
2546
|
-
|
|
2547
|
-
def c_not(self, condition):
|
|
2548
|
-
return not self.getRuntimeValue(condition.value)
|
|
2549
|
-
|
|
2550
|
-
def c_object(self, condition):
|
|
2551
|
-
comparison = type(self.getRuntimeValue(condition.value1)) is dict
|
|
2552
|
-
return not comparison if condition.negate else comparison
|
|
2553
|
-
|
|
2554
|
-
def c_odd(self, condition):
|
|
2555
|
-
return self.getRuntimeValue(condition.value1) % 2 == 1
|
|
2556
|
-
|
|
2557
|
-
def c_starts(self, condition):
|
|
2558
|
-
value1 = self.getRuntimeValue(condition.value1)
|
|
2559
|
-
value2 = self.getRuntimeValue(condition.value2)
|
|
2560
|
-
return value1.startswith(value2)
|
|
2561
|
-
|
|
2562
|
-
def c_string(self, condition):
|
|
2563
|
-
comparison = type(self.getRuntimeValue(condition.value1)) is str
|
|
2564
|
-
return not comparison if condition.negate else comparison
|