easycoder 251104.2__py2.py3-none-any.whl → 260110.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 +5 -3
- easycoder/debugger/__init__.py +5 -0
- easycoder/debugger/ec_dbg_value_display copy.py +195 -0
- easycoder/debugger/ec_dbg_value_display.py +24 -0
- easycoder/debugger/ec_dbg_watch_list copy.py +219 -0
- easycoder/debugger/ec_dbg_watchlist.py +293 -0
- easycoder/debugger/ec_debug.py +1025 -0
- easycoder/ec_border.py +15 -11
- easycoder/ec_classes.py +487 -11
- easycoder/ec_compiler.py +81 -44
- easycoder/ec_condition.py +1 -1
- easycoder/ec_core.py +1044 -1090
- easycoder/ec_gclasses.py +236 -0
- easycoder/ec_graphics.py +1683 -0
- easycoder/ec_handler.py +18 -13
- easycoder/ec_keyboard.py +50 -50
- easycoder/ec_program.py +299 -156
- easycoder/ec_psutil.py +48 -0
- easycoder/ec_timestamp.py +2 -1
- easycoder/ec_value.py +65 -47
- easycoder/icons/exit.png +0 -0
- easycoder/icons/run.png +0 -0
- easycoder/icons/step.png +0 -0
- easycoder/icons/stop.png +0 -0
- easycoder/pre/README.md +3 -0
- easycoder/pre/__init__.py +17 -0
- easycoder/pre/debugger/__init__.py +5 -0
- easycoder/pre/debugger/ec_dbg_value_display copy.py +195 -0
- easycoder/pre/debugger/ec_dbg_value_display.py +24 -0
- easycoder/pre/debugger/ec_dbg_watch_list copy.py +219 -0
- easycoder/pre/debugger/ec_dbg_watchlist.py +293 -0
- easycoder/pre/debugger/ec_debug.py +1014 -0
- easycoder/pre/ec_border.py +67 -0
- easycoder/pre/ec_classes.py +470 -0
- easycoder/pre/ec_compiler.py +291 -0
- easycoder/pre/ec_condition.py +27 -0
- easycoder/pre/ec_core.py +2772 -0
- easycoder/pre/ec_gclasses.py +230 -0
- easycoder/{ec_pyside.py → pre/ec_graphics.py} +631 -496
- easycoder/pre/ec_handler.py +79 -0
- easycoder/pre/ec_keyboard.py +439 -0
- easycoder/pre/ec_program.py +557 -0
- easycoder/pre/ec_psutil.py +48 -0
- easycoder/pre/ec_timestamp.py +11 -0
- easycoder/pre/ec_value.py +124 -0
- easycoder/pre/icons/close.png +0 -0
- easycoder/pre/icons/exit.png +0 -0
- easycoder/pre/icons/run.png +0 -0
- easycoder/pre/icons/step.png +0 -0
- easycoder/pre/icons/stop.png +0 -0
- easycoder/pre/icons/tick.png +0 -0
- {easycoder-251104.2.dist-info → easycoder-260110.1.dist-info}/METADATA +11 -1
- easycoder-260110.1.dist-info/RECORD +58 -0
- easycoder/ec_debug.py +0 -464
- easycoder-251104.2.dist-info/RECORD +0 -20
- /easycoder/{close.png → icons/close.png} +0 -0
- /easycoder/{tick.png → icons/tick.png} +0 -0
- {easycoder-251104.2.dist-info → easycoder-260110.1.dist-info}/WHEEL +0 -0
- {easycoder-251104.2.dist-info → easycoder-260110.1.dist-info}/entry_points.txt +0 -0
- {easycoder-251104.2.dist-info → easycoder-260110.1.dist-info}/licenses/LICENSE +0 -0
easycoder/ec_core.py
CHANGED
|
@@ -1,16 +1,31 @@
|
|
|
1
1
|
import json, math, hashlib, threading, os, subprocess, time
|
|
2
|
-
import
|
|
2
|
+
import base64, binascii, random, requests, paramiko, uuid
|
|
3
3
|
from copy import deepcopy
|
|
4
|
-
from psutil import Process
|
|
5
4
|
from datetime import datetime
|
|
6
|
-
from .ec_classes import
|
|
5
|
+
from .ec_classes import (
|
|
6
|
+
FatalError,
|
|
7
|
+
RuntimeWarning,
|
|
8
|
+
RuntimeError,
|
|
9
|
+
RuntimeAssertionError,
|
|
10
|
+
NoValueError,
|
|
11
|
+
NoValueRuntimeError,
|
|
12
|
+
ECObject,
|
|
13
|
+
ECVariable,
|
|
14
|
+
ECDictionary,
|
|
15
|
+
ECList,
|
|
16
|
+
ECFile,
|
|
17
|
+
ECStack,
|
|
18
|
+
ECSSH,
|
|
19
|
+
ECValue,
|
|
20
|
+
ECModule
|
|
21
|
+
)
|
|
22
|
+
|
|
7
23
|
from .ec_handler import Handler
|
|
8
|
-
from .ec_timestamp import getTimestamp
|
|
9
24
|
|
|
10
25
|
class Core(Handler):
|
|
11
26
|
|
|
12
27
|
def __init__(self, compiler):
|
|
13
|
-
|
|
28
|
+
super().__init__(compiler)
|
|
14
29
|
self.encoding = 'utf-8'
|
|
15
30
|
|
|
16
31
|
def getName(self):
|
|
@@ -43,91 +58,80 @@ class Core(Handler):
|
|
|
43
58
|
# Keyword handlers
|
|
44
59
|
|
|
45
60
|
# Arithmetic add
|
|
46
|
-
# add {value} to {variable}
|
|
61
|
+
# add {value} to {variable}
|
|
62
|
+
# add {value1} to {value2} giving {variable}
|
|
47
63
|
def k_add(self, command):
|
|
48
64
|
# Get the (first) value
|
|
49
65
|
command['value1'] = self.nextValue()
|
|
50
|
-
if
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
if command['value1'] == None: return False
|
|
67
|
+
self.skip('to')
|
|
68
|
+
if self.nextIsSymbol():
|
|
69
|
+
record = self.getSymbolRecord()
|
|
70
|
+
if not isinstance(self.getObject(record), ECVariable): return False
|
|
71
|
+
# If 'giving' comes next, this variable is the second value
|
|
72
|
+
if self.peek() == 'giving':
|
|
73
|
+
v2 = ECValue(type='symbol', content=record['name'])
|
|
74
|
+
command['value2'] = v2
|
|
75
|
+
self.nextToken()
|
|
76
|
+
# Now get the target variable
|
|
77
|
+
if self.nextIsSymbol():
|
|
78
|
+
record = self.getSymbolRecord()
|
|
79
|
+
self.checkObjectType(record, ECVariable)
|
|
80
|
+
command['target'] = record['name']
|
|
81
|
+
self.add(command)
|
|
82
|
+
return True
|
|
67
83
|
else:
|
|
68
|
-
# Here
|
|
69
|
-
command['
|
|
70
|
-
if self.
|
|
71
|
-
command['target'] = self.nextToken()
|
|
84
|
+
# Here the variable is the target
|
|
85
|
+
command['target'] = record['name']
|
|
86
|
+
if self.getObject(record).isMutable():
|
|
72
87
|
self.add(command)
|
|
73
88
|
return True
|
|
74
|
-
|
|
89
|
+
else:
|
|
90
|
+
# Here we have 2 values so 'giving' must come next
|
|
91
|
+
command['value2'] = self.getValue()
|
|
92
|
+
if self.nextToken() == 'giving':
|
|
93
|
+
if self.nextIsSymbol():
|
|
94
|
+
record = self.getSymbolRecord()
|
|
95
|
+
self.checkObjectType(record, ECVariable)
|
|
96
|
+
command['target'] = record['name']
|
|
97
|
+
self.add(command)
|
|
98
|
+
return True
|
|
99
|
+
# raise FatalError(self.compiler, 'Cannot add values: target variable expected')
|
|
75
100
|
return False
|
|
76
101
|
|
|
77
102
|
def r_add(self, command):
|
|
78
|
-
value1 = command['value1']
|
|
79
|
-
|
|
80
|
-
value2 = command['value2']
|
|
81
|
-
except:
|
|
82
|
-
value2 = None
|
|
103
|
+
value1 = self.textify(command['value1'])
|
|
104
|
+
value2 = self.textify(command['value2']) if 'value2' in command else None
|
|
83
105
|
target = self.getVariable(command['target'])
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
targetValue =
|
|
89
|
-
targetValue['content'] = 0
|
|
90
|
-
targetValue['type'] = 'int'
|
|
91
|
-
if value2:
|
|
92
|
-
v1 = int(self.getRuntimeValue(value1))
|
|
93
|
-
v2 = int(self.getRuntimeValue(value2))
|
|
94
|
-
targetValue['content'] = v1 + v2
|
|
106
|
+
# Check that the target variable is mutable. If not, it's not an arithmetic add
|
|
107
|
+
# If value2 exists, we are adding two values and storing the result in target
|
|
108
|
+
if value2 != None:
|
|
109
|
+
# add X to Y giving Z
|
|
110
|
+
targetValue = ECValue(type=int, content=int(value1) + int(value2))
|
|
95
111
|
else:
|
|
96
|
-
#
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
v = int(v)
|
|
100
|
-
v1 = int(self.getRuntimeValue(value1))
|
|
101
|
-
if v1 == None:
|
|
102
|
-
v1 = 0
|
|
103
|
-
targetValue['content'] = v + v1
|
|
112
|
+
# add X to Y
|
|
113
|
+
targetValue = self.getSymbolValue(target)
|
|
114
|
+
targetValue.setContent(int(targetValue.getContent()) + int(value1))
|
|
104
115
|
self.putSymbolValue(target, targetValue)
|
|
105
116
|
return self.nextPC()
|
|
106
117
|
|
|
107
|
-
# Append a value to an
|
|
108
|
-
# append {value} to {
|
|
118
|
+
# Append a value to an list
|
|
119
|
+
# append {value} to {list}
|
|
109
120
|
def k_append(self, command):
|
|
110
121
|
command['value'] = self.nextValue()
|
|
111
122
|
if self.nextIs('to'):
|
|
112
123
|
if self.nextIsSymbol():
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
self.warning(f'Core.append: Variable {symbolRecord["name"]} does not hold a value')
|
|
124
|
+
record = self.getSymbolRecord()
|
|
125
|
+
self.program.checkObjectType(self.getObject(record), ECList)
|
|
126
|
+
command['target'] = record['name']
|
|
127
|
+
self.add(command)
|
|
128
|
+
return True
|
|
119
129
|
return False
|
|
120
130
|
|
|
121
131
|
def r_append(self, command):
|
|
122
|
-
value = self.
|
|
123
|
-
target = self.getVariable(command['target'])
|
|
124
|
-
|
|
125
|
-
content = val['content']
|
|
126
|
-
if content == '':
|
|
127
|
-
content = []
|
|
128
|
-
content.append(value)
|
|
129
|
-
val['content'] = content
|
|
130
|
-
self.putSymbolValue(target, val)
|
|
132
|
+
value = self.textify(command['value'])
|
|
133
|
+
target = self.getObject(self.getVariable(command['target']))
|
|
134
|
+
target.append(value)
|
|
131
135
|
return self.nextPC()
|
|
132
136
|
|
|
133
137
|
#assert {condition} [with {message}]
|
|
@@ -145,7 +149,7 @@ class Core(Handler):
|
|
|
145
149
|
test = self.program.condition.testCondition(command['test'])
|
|
146
150
|
if test:
|
|
147
151
|
return self.nextPC()
|
|
148
|
-
|
|
152
|
+
RuntimeAssertionError(self.program, self.textify(command['with']))
|
|
149
153
|
|
|
150
154
|
# Begin a block
|
|
151
155
|
def k_begin(self, command):
|
|
@@ -162,23 +166,32 @@ class Core(Handler):
|
|
|
162
166
|
|
|
163
167
|
# clear {variable}
|
|
164
168
|
def k_clear(self, command):
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
command['
|
|
168
|
-
|
|
169
|
+
token = self.nextToken()
|
|
170
|
+
if token == 'breakpoint':
|
|
171
|
+
command['breakpoint'] = True
|
|
172
|
+
self.add(command)
|
|
173
|
+
return True
|
|
174
|
+
elif self.isSymbol():
|
|
175
|
+
record = self.getSymbolRecord()
|
|
176
|
+
command['target'] = record['name']
|
|
177
|
+
object = self.getObject(record)
|
|
178
|
+
if isinstance(object, ECSSH):
|
|
179
|
+
self.add(command)
|
|
180
|
+
return True
|
|
181
|
+
if isinstance(object, ECVariable):
|
|
169
182
|
self.add(command)
|
|
170
183
|
return True
|
|
171
184
|
return False
|
|
172
185
|
|
|
173
186
|
def r_clear(self, command):
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
target['ssh'] = None
|
|
187
|
+
if 'breakpoint' in command:
|
|
188
|
+
self.program.breakpoint = False
|
|
177
189
|
else:
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
190
|
+
target = self.getVariable(command['target'])
|
|
191
|
+
if target['keyword'] == 'ssh':
|
|
192
|
+
target['ssh'] = None
|
|
193
|
+
else:
|
|
194
|
+
self.putSymbolValue(target, ECValue(type=bool, content=False))
|
|
182
195
|
return self.nextPC()
|
|
183
196
|
|
|
184
197
|
# Close a file
|
|
@@ -186,10 +199,10 @@ class Core(Handler):
|
|
|
186
199
|
def k_close(self, command):
|
|
187
200
|
if self.nextIsSymbol():
|
|
188
201
|
fileRecord = self.getSymbolRecord()
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
202
|
+
self.checkObjectType
|
|
203
|
+
command['file'] = fileRecord['name']
|
|
204
|
+
self.add(command)
|
|
205
|
+
return True
|
|
193
206
|
return False
|
|
194
207
|
|
|
195
208
|
def r_close(self, command):
|
|
@@ -197,7 +210,35 @@ class Core(Handler):
|
|
|
197
210
|
fileRecord['file'].close()
|
|
198
211
|
return self.nextPC()
|
|
199
212
|
|
|
200
|
-
#
|
|
213
|
+
# copy {variable} to {variable}
|
|
214
|
+
# copy {dictionary} to {dictionary}
|
|
215
|
+
# copy {list} to {list}
|
|
216
|
+
def k_copy(self, command):
|
|
217
|
+
if self.nextIsSymbol():
|
|
218
|
+
record = self.getSymbolRecord()
|
|
219
|
+
sourceObject = self.getObject(record)
|
|
220
|
+
if self.isObjectType(sourceObject, (ECVariable, ECDictionary, ECList)):
|
|
221
|
+
command['source'] = record['name']
|
|
222
|
+
self.skip('to')
|
|
223
|
+
if self.nextIsSymbol():
|
|
224
|
+
record = self.getSymbolRecord()
|
|
225
|
+
targetObject = self.getObject(record)
|
|
226
|
+
# Check that the types match
|
|
227
|
+
if type(sourceObject) != type(targetObject):
|
|
228
|
+
raise FatalError(self.compiler, 'Cannot copy - type mismatch')
|
|
229
|
+
command['target'] = record['name']
|
|
230
|
+
self.add(command)
|
|
231
|
+
return True
|
|
232
|
+
return False
|
|
233
|
+
|
|
234
|
+
def r_copy(self, command):
|
|
235
|
+
sourceRecord = self.getVariable(command['source'])
|
|
236
|
+
targetRecord = self.getVariable(command['target'])
|
|
237
|
+
# Copy the value (type already checked at compile time)
|
|
238
|
+
self.putSymbolValue(targetRecord, self.textify(sourceRecord))
|
|
239
|
+
return self.nextPC()
|
|
240
|
+
|
|
241
|
+
# Create directory
|
|
201
242
|
# create directory {name}
|
|
202
243
|
def k_create(self, command):
|
|
203
244
|
if self.nextIs('directory'):
|
|
@@ -209,7 +250,7 @@ class Core(Handler):
|
|
|
209
250
|
|
|
210
251
|
def r_create(self, command):
|
|
211
252
|
if command['item'] == 'directory':
|
|
212
|
-
path = self.
|
|
253
|
+
path = self.textify(command['path'])
|
|
213
254
|
if not os.path.exists(path):
|
|
214
255
|
os.makedirs(path)
|
|
215
256
|
return self.nextPC()
|
|
@@ -221,7 +262,7 @@ class Core(Handler):
|
|
|
221
262
|
self.compiler.debugCompile = True
|
|
222
263
|
self.nextToken()
|
|
223
264
|
return True
|
|
224
|
-
elif token in ['step', 'stop', 'program', 'custom']:
|
|
265
|
+
elif token in ['step', 'stop', 'skip', 'breakpoint', 'program', 'custom']:
|
|
225
266
|
command['mode'] = token
|
|
226
267
|
self.nextToken()
|
|
227
268
|
elif token == 'stack':
|
|
@@ -247,18 +288,22 @@ class Core(Handler):
|
|
|
247
288
|
self.program.debugStep = True
|
|
248
289
|
elif command['mode'] == 'stop':
|
|
249
290
|
self.program.debugStep = False
|
|
291
|
+
elif command['mode'] == 'skip':
|
|
292
|
+
self.program.debugSkip = True
|
|
293
|
+
elif command['mode'] == 'breakpoint':
|
|
294
|
+
self.program.breakpoint = True
|
|
250
295
|
elif command['mode'] == 'program':
|
|
251
296
|
for item in self.code:
|
|
252
297
|
print(json.dumps(item, indent = 2))
|
|
253
298
|
elif command['mode'] == 'stack':
|
|
254
299
|
stackRecord = self.getVariable(command['stack'])
|
|
255
300
|
value = self.getSymbolValue(stackRecord)
|
|
256
|
-
print(f'{self.
|
|
301
|
+
print(f'{self.textify(command["as"])}:',json.dumps(self.getSymbolValue(stackRecord), indent = 2))
|
|
257
302
|
elif command['mode'] == 'custom':
|
|
258
303
|
# Custom debugging code goes in here
|
|
259
304
|
record = self.getVariable('Script')
|
|
260
305
|
print('(Debug) Script:',record)
|
|
261
|
-
value = self.
|
|
306
|
+
value = self.textify(record)
|
|
262
307
|
print('(Debug) Value:',value)
|
|
263
308
|
pass
|
|
264
309
|
return self.nextPC()
|
|
@@ -267,12 +312,11 @@ class Core(Handler):
|
|
|
267
312
|
# decrement {variable}
|
|
268
313
|
def k_decrement(self, command):
|
|
269
314
|
if self.nextIsSymbol():
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
self.warning(f'Core.decrement: Variable {symbolRecord["name"]} does not hold a value')
|
|
315
|
+
record = self.getSymbolRecord()
|
|
316
|
+
self.checkObjectType(self.getObject(record), ECVariable)
|
|
317
|
+
command['target'] = record['name']
|
|
318
|
+
self.add(command)
|
|
319
|
+
return True
|
|
276
320
|
return False
|
|
277
321
|
|
|
278
322
|
def r_decrement(self, command):
|
|
@@ -280,8 +324,7 @@ class Core(Handler):
|
|
|
280
324
|
|
|
281
325
|
# Delete a file or a property
|
|
282
326
|
# delete file {filename}
|
|
283
|
-
# delete property {
|
|
284
|
-
# delete element {name} of {variable}
|
|
327
|
+
# delete entry/item/property/element {name/number} of {variable}
|
|
285
328
|
def k_delete(self, command):
|
|
286
329
|
token = self.nextToken( )
|
|
287
330
|
command['type'] = token
|
|
@@ -289,94 +332,119 @@ class Core(Handler):
|
|
|
289
332
|
command['filename'] = self.nextValue()
|
|
290
333
|
self.add(command)
|
|
291
334
|
return True
|
|
292
|
-
elif token in
|
|
335
|
+
elif token in ('entry', 'item', 'property', 'element'):
|
|
293
336
|
command['key'] = self.nextValue()
|
|
294
337
|
self.skip('of')
|
|
295
338
|
if self.nextIsSymbol():
|
|
296
339
|
record = self.getSymbolRecord()
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
self.
|
|
300
|
-
|
|
301
|
-
|
|
340
|
+
command['variable'] = record['name']
|
|
341
|
+
if token == 'entry':
|
|
342
|
+
self.checkObjectType(self.getObject(record), ECDictionary)
|
|
343
|
+
elif token == 'item':
|
|
344
|
+
self.checkObjectType(self.getObject(record), ECList)
|
|
345
|
+
self.add(command)
|
|
346
|
+
return True
|
|
302
347
|
self.warning(f'Core.delete: variable expected; got {self.getToken()}')
|
|
303
348
|
else:
|
|
304
|
-
self.warning(f'Core.delete: "file", "property" or "element" expected; got {token}')
|
|
349
|
+
self.warning(f'Core.delete: "file", "entry", "item", "property" or "element" expected; got {token}')
|
|
305
350
|
return False
|
|
306
351
|
|
|
307
352
|
def r_delete(self, command):
|
|
308
353
|
type = command['type']
|
|
309
354
|
if type == 'file':
|
|
310
|
-
filename = self.
|
|
355
|
+
filename = self.textify(command['filename'])
|
|
311
356
|
if filename != None:
|
|
312
357
|
if os.path.isfile(filename): os.remove(filename)
|
|
358
|
+
elif type == 'entry':
|
|
359
|
+
key = self.textify(command['key'])
|
|
360
|
+
record = self.getVariable(command['variable'])
|
|
361
|
+
self.getObject(record).deleteEntry(key)
|
|
362
|
+
elif type == 'item':
|
|
363
|
+
key = self.textify(command['key'])
|
|
364
|
+
record = self.getVariable(command['variable'])
|
|
365
|
+
self.getObject(record).deleteItem(key)
|
|
313
366
|
elif type == 'property':
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
367
|
+
raise NotImplementedError('Core.delete property not implemented yet')
|
|
368
|
+
key = self.textify(command['key'])
|
|
369
|
+
record = self.getVariable(command['var'])
|
|
370
|
+
value = self.getSymbolValue(record)
|
|
371
|
+
content = value.getContent()
|
|
318
372
|
content.pop(key, None)
|
|
319
|
-
value
|
|
320
|
-
self.putSymbolValue(
|
|
373
|
+
value.setContent(content)
|
|
374
|
+
self.putSymbolValue(record, value)
|
|
321
375
|
elif type == 'element':
|
|
322
|
-
key = self.
|
|
323
|
-
|
|
324
|
-
value = self.getSymbolValue(
|
|
325
|
-
content = value
|
|
326
|
-
if key
|
|
376
|
+
key = self.textify(command['key'])
|
|
377
|
+
record = self.getVariable(command['variable'])
|
|
378
|
+
value = self.getSymbolValue(record)
|
|
379
|
+
content = value.getContent()
|
|
380
|
+
if isinstance(key, int):
|
|
381
|
+
if key >= 0 and key < len(content): del(content[key])
|
|
382
|
+
elif isinstance(key, str):
|
|
383
|
+
if key in content: content.remove(key)
|
|
327
384
|
else: RuntimeError(self.program, f'Index {key} out of range')
|
|
328
|
-
value
|
|
329
|
-
self.putSymbolValue(
|
|
385
|
+
value.setContent(content)
|
|
386
|
+
self.putSymbolValue(record, value)
|
|
387
|
+
return self.nextPC()
|
|
388
|
+
|
|
389
|
+
# Declare a dictionary variable
|
|
390
|
+
def k_dictionary(self, command):
|
|
391
|
+
self.compiler.addValueType()
|
|
392
|
+
return self.compileVariable(command, 'ECDictionary')
|
|
393
|
+
|
|
394
|
+
def r_dictionary(self, command):
|
|
330
395
|
return self.nextPC()
|
|
331
396
|
|
|
332
|
-
|
|
333
|
-
# divide
|
|
397
|
+
|
|
398
|
+
# Arithmetic divide
|
|
399
|
+
# divide {variable} by {value}
|
|
400
|
+
# divide {value1} by {value2} giving {variable}
|
|
334
401
|
def k_divide(self, command):
|
|
335
|
-
# Get the (first)
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
402
|
+
# Get the (first) item. If it's a symbol, it may be the target variable
|
|
403
|
+
if self.nextIsSymbol():
|
|
404
|
+
record = self.getSymbolRecord()
|
|
405
|
+
self.checkObjectType(record, ECVariable)
|
|
406
|
+
# Hold onto the variable and its value
|
|
407
|
+
variable1 = record['name']
|
|
408
|
+
value1 = self.getValue()
|
|
409
|
+
else:
|
|
410
|
+
# Here we have a value
|
|
411
|
+
value1 = self.getValue()
|
|
412
|
+
variable1 = None
|
|
413
|
+
self.skip('by')
|
|
414
|
+
command['value2'] = self.nextValue()
|
|
415
|
+
# if 'giving' comes next, the target is the next value
|
|
416
|
+
if self.peek() == 'giving':
|
|
417
|
+
self.nextToken()
|
|
418
|
+
if self.nextIsSymbol():
|
|
419
|
+
record = self.getSymbolRecord()
|
|
420
|
+
self.checkObjectType(record, ECVariable)
|
|
421
|
+
command['target'] = record['name']
|
|
422
|
+
command['value1'] = value1
|
|
423
|
+
self.add(command)
|
|
424
|
+
return True
|
|
425
|
+
else:
|
|
426
|
+
# Here the first variable is the target
|
|
427
|
+
if variable1 != None:
|
|
428
|
+
command['target'] = variable1
|
|
429
|
+
self.add(command)
|
|
430
|
+
return True
|
|
353
431
|
return False
|
|
354
432
|
|
|
355
433
|
def r_divide(self, command):
|
|
356
|
-
value1 = command['value1']
|
|
357
|
-
|
|
358
|
-
value2 = command['value2']
|
|
359
|
-
except:
|
|
360
|
-
value2 = None
|
|
434
|
+
value1 = self.textify(command['value1']) if 'value1' in command else None
|
|
435
|
+
value2 = self.textify(command['value2'])
|
|
361
436
|
target = self.getVariable(command['target'])
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
value['type'] = 'int'
|
|
369
|
-
if value2:
|
|
370
|
-
v1 = int(self.getRuntimeValue(value1))
|
|
371
|
-
v2 = int(self.getRuntimeValue(value2))
|
|
372
|
-
value['content'] = int(v1/v2)
|
|
437
|
+
# Check that the target variable can hold a value
|
|
438
|
+
self.checkObjectType(target, ECVariable)
|
|
439
|
+
# If value1 exists, we are adding two values and storing the result in target
|
|
440
|
+
if value1 != None:
|
|
441
|
+
# divide X by Y giving Z
|
|
442
|
+
targetValue = ECValue(type=int, content=int(value1) // int(value2))
|
|
373
443
|
else:
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
value['content'] = int(v/v1)
|
|
379
|
-
self.putSymbolValue(target, value)
|
|
444
|
+
# divide X by Y
|
|
445
|
+
targetValue = self.getSymbolValue(target)
|
|
446
|
+
targetValue.setContent(int(targetValue.getContent()) // int(value2))
|
|
447
|
+
self.putSymbolValue(target, targetValue)
|
|
380
448
|
return self.nextPC()
|
|
381
449
|
|
|
382
450
|
# download [binary] {url} to {path}
|
|
@@ -393,8 +461,8 @@ class Core(Handler):
|
|
|
393
461
|
|
|
394
462
|
def r_download(self, command):
|
|
395
463
|
binary = command['binary']
|
|
396
|
-
url = self.
|
|
397
|
-
path = self.
|
|
464
|
+
url = self.textify(command['url'])
|
|
465
|
+
path = self.textify(command['path'])
|
|
398
466
|
mode = 'wb' if binary else 'w'
|
|
399
467
|
response = requests.get(url, stream=True)
|
|
400
468
|
with open(path, mode) as f:
|
|
@@ -402,14 +470,6 @@ class Core(Handler):
|
|
|
402
470
|
if chunk: f.write(chunk)
|
|
403
471
|
return self.nextPC()
|
|
404
472
|
|
|
405
|
-
# Dummy command for testing
|
|
406
|
-
def k_dummy(self, command):
|
|
407
|
-
self.add(command)
|
|
408
|
-
return True
|
|
409
|
-
|
|
410
|
-
def r_dummy(self, command):
|
|
411
|
-
return self.nextPC()
|
|
412
|
-
|
|
413
473
|
# Match a begin
|
|
414
474
|
def k_end(self, command):
|
|
415
475
|
self.add(command)
|
|
@@ -430,15 +490,16 @@ class Core(Handler):
|
|
|
430
490
|
|
|
431
491
|
# Declare a file variable
|
|
432
492
|
def k_file(self, command):
|
|
433
|
-
|
|
493
|
+
self.compiler.addValueType()
|
|
494
|
+
return self.compileVariable(command, 'ECFile')
|
|
434
495
|
|
|
435
496
|
def r_file(self, command):
|
|
436
497
|
return self.nextPC()
|
|
437
498
|
|
|
438
499
|
# Fork to a label
|
|
500
|
+
# fork [to] {label}
|
|
439
501
|
def k_fork(self, command):
|
|
440
|
-
|
|
441
|
-
self.nextToken()
|
|
502
|
+
self.skip('to') # Optional 'to' (core-reserved keyword, plugin-safe)
|
|
442
503
|
command['fork'] = self.nextToken()
|
|
443
504
|
self.add(command)
|
|
444
505
|
return True
|
|
@@ -454,14 +515,14 @@ class Core(Handler):
|
|
|
454
515
|
self.run(label)
|
|
455
516
|
return next
|
|
456
517
|
|
|
457
|
-
# get {variable) from {url} [or {command}]
|
|
518
|
+
# get {variable) from url {url} [or {command}]
|
|
458
519
|
def k_get(self, command):
|
|
459
520
|
if self.nextIsSymbol():
|
|
460
|
-
|
|
461
|
-
if
|
|
521
|
+
record = self.getSymbolRecord()
|
|
522
|
+
if isinstance(self.getObject(record), ECObject):
|
|
462
523
|
command['target'] = self.getToken()
|
|
463
524
|
else:
|
|
464
|
-
NoValueError(self.compiler,
|
|
525
|
+
NoValueError(self.compiler, record)
|
|
465
526
|
if self.nextIs('from'):
|
|
466
527
|
if self.nextIs('url'):
|
|
467
528
|
url = self.nextValue()
|
|
@@ -473,9 +534,7 @@ class Core(Handler):
|
|
|
473
534
|
self.nextToken()
|
|
474
535
|
command['timeout'] = self.nextValue()
|
|
475
536
|
else:
|
|
476
|
-
timeout =
|
|
477
|
-
timeout['type'] = 'int'
|
|
478
|
-
timeout['content'] = 5
|
|
537
|
+
timeout = ECValue(type = int, content = 5)
|
|
479
538
|
command['timeout'] = timeout
|
|
480
539
|
self.processOr(command, get)
|
|
481
540
|
return True
|
|
@@ -483,14 +542,12 @@ class Core(Handler):
|
|
|
483
542
|
|
|
484
543
|
def r_get(self, command):
|
|
485
544
|
global errorCode, errorReason
|
|
486
|
-
retval =
|
|
487
|
-
|
|
488
|
-
retval['numeric'] = False
|
|
489
|
-
url = self.getRuntimeValue(command['url'])
|
|
545
|
+
retval = ECValue(type=str)
|
|
546
|
+
url = self.textify(command['url'])
|
|
490
547
|
target = self.getVariable(command['target'])
|
|
491
|
-
response =
|
|
548
|
+
response = {}
|
|
492
549
|
try:
|
|
493
|
-
timeout = self.
|
|
550
|
+
timeout = self.textify(command['timeout'])
|
|
494
551
|
response = requests.get(url, auth = ('user', 'pass'), timeout=timeout)
|
|
495
552
|
if response.status_code >= 400:
|
|
496
553
|
errorCode = response.status_code
|
|
@@ -505,15 +562,15 @@ class Core(Handler):
|
|
|
505
562
|
return command['or']
|
|
506
563
|
else:
|
|
507
564
|
RuntimeError(self.program, f'Error: {errorReason}')
|
|
508
|
-
retval
|
|
565
|
+
retval.setContent(response.text) # type: ignore
|
|
509
566
|
self.program.putSymbolValue(target, retval)
|
|
510
567
|
return self.nextPC()
|
|
511
568
|
|
|
512
569
|
# Go to a label
|
|
570
|
+
# go [to] {label}
|
|
513
571
|
def k_go(self, command):
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
return self.k_goto(command)
|
|
572
|
+
self.skip('to') # Optional 'to' (core-reserved keyword, plugin-safe)
|
|
573
|
+
return self.k_goto(command)
|
|
517
574
|
|
|
518
575
|
def k_goto(self, command):
|
|
519
576
|
command['keyword'] = 'goto'
|
|
@@ -535,9 +592,9 @@ class Core(Handler):
|
|
|
535
592
|
return command['goto']
|
|
536
593
|
|
|
537
594
|
# Call a subroutine
|
|
595
|
+
# gosub [to] {label}
|
|
538
596
|
def k_gosub(self, command):
|
|
539
|
-
|
|
540
|
-
self.nextToken()
|
|
597
|
+
self.skip('to') # Optional 'to' (core-reserved keyword, plugin-safe)
|
|
541
598
|
command['gosub'] = self.nextToken()
|
|
542
599
|
self.add(command)
|
|
543
600
|
return True
|
|
@@ -599,55 +656,51 @@ class Core(Handler):
|
|
|
599
656
|
|
|
600
657
|
# Import one or more variables
|
|
601
658
|
def k_import(self, command):
|
|
659
|
+
self.add(command)
|
|
602
660
|
imports = []
|
|
603
661
|
while True:
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
variable['keyword'] = keyword
|
|
613
|
-
variable['import'] = None
|
|
614
|
-
variable['used'] = False
|
|
615
|
-
variable['hasValue'] = True if keyword == 'variable' else False
|
|
616
|
-
self.add(variable)
|
|
662
|
+
vartype = self.nextToken()
|
|
663
|
+
for domain in self.program.getDomains():
|
|
664
|
+
handler = domain.keywordHandler(vartype)
|
|
665
|
+
if handler != None:
|
|
666
|
+
variable = {}
|
|
667
|
+
if not handler(variable):
|
|
668
|
+
raise RuntimeError(self.program, f'Failed to handle variable type "{vartype}"')
|
|
669
|
+
imports.append(variable)
|
|
617
670
|
if self.peek() != 'and':
|
|
618
671
|
break
|
|
619
672
|
self.nextToken()
|
|
620
|
-
command['imports'] =
|
|
621
|
-
self.add(command)
|
|
673
|
+
command['imports'] = imports
|
|
622
674
|
return True
|
|
623
675
|
|
|
624
676
|
def r_import(self, command):
|
|
625
677
|
exports = self.program.exports
|
|
626
|
-
imports =
|
|
678
|
+
imports = command['imports']
|
|
627
679
|
if len(imports) < len(exports):
|
|
628
680
|
RuntimeError(self.program, 'Too few imports')
|
|
629
681
|
elif len(imports) > len(exports):
|
|
630
682
|
RuntimeError(self.program, 'Too many imports')
|
|
631
683
|
for n in range(0, len(imports)):
|
|
632
684
|
exportRecord = exports[n]
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
685
|
+
importRecord = imports[n]
|
|
686
|
+
if importRecord['classname'] != exportRecord['classname']:
|
|
687
|
+
raise RuntimeError(self.program, f'Import {n} does not match export (wrong type)')
|
|
688
|
+
name = importRecord['name']
|
|
689
|
+
importRecord.clear()
|
|
690
|
+
importRecord['name'] = name
|
|
691
|
+
importRecord['domain'] = exportRecord['domain']
|
|
692
|
+
importRecord['keyword'] = exportRecord['keyword']
|
|
693
|
+
importRecord['import'] = exportRecord
|
|
640
694
|
return self.nextPC()
|
|
641
695
|
|
|
642
696
|
# Increment a variable
|
|
643
697
|
def k_increment(self, command):
|
|
644
698
|
if self.nextIsSymbol():
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
self.warning(f'Core.increment: Variable {symbolRecord["name"]} does not hold a value')
|
|
699
|
+
record = self.getSymbolRecord()
|
|
700
|
+
self.checkObjectType(self.getObject(record), ECVariable)
|
|
701
|
+
command['target'] = record['name']
|
|
702
|
+
self.add(command)
|
|
703
|
+
return True
|
|
651
704
|
return False
|
|
652
705
|
|
|
653
706
|
def r_increment(self, command):
|
|
@@ -667,43 +720,18 @@ class Core(Handler):
|
|
|
667
720
|
return False
|
|
668
721
|
|
|
669
722
|
def r_index(self, command):
|
|
670
|
-
|
|
671
|
-
|
|
723
|
+
value = self.textify(command['value'])
|
|
724
|
+
record = self.getVariable(command['target'])
|
|
725
|
+
self.getObject(record).setIndex(value)
|
|
672
726
|
return self.nextPC()
|
|
673
727
|
|
|
674
|
-
#
|
|
675
|
-
def k_init(self, command):
|
|
676
|
-
# get the variable
|
|
677
|
-
if self.nextIsSymbol():
|
|
678
|
-
symbolRecord = self.getSymbolRecord()
|
|
679
|
-
keyword = symbolRecord['keyword']
|
|
680
|
-
if keyword in ['stack','array', 'object']:
|
|
681
|
-
command['keyword'] = keyword
|
|
682
|
-
command['target'] = symbolRecord['name']
|
|
683
|
-
return True
|
|
684
|
-
return False
|
|
685
|
-
|
|
686
|
-
def r_init(self, command):
|
|
687
|
-
symbolRecord = self.getVariable(command['target'])
|
|
688
|
-
keyword = command['keyword']
|
|
689
|
-
if keyword in ['stack', 'array']:
|
|
690
|
-
self.putSymbolValue(symbolRecord, json.loads('[]'))
|
|
691
|
-
elif keyword == 'object':
|
|
692
|
-
self.putSymbolValue(symbolRecord, json.loads('{}'))
|
|
693
|
-
else:
|
|
694
|
-
RuntimeError(self.program, f"Inappropriate variable type '{keyword}'")
|
|
695
|
-
return self.nextPC()
|
|
696
|
-
|
|
697
|
-
# Inout a value from the terminal
|
|
728
|
+
# Input a value from the terminal
|
|
698
729
|
# input {variable} [with {prompt}]
|
|
699
730
|
def k_input(self, command):
|
|
700
731
|
# get the variable
|
|
701
732
|
if self.nextIsSymbol():
|
|
702
733
|
command['target'] = self.getToken()
|
|
703
|
-
value =
|
|
704
|
-
value['type'] = 'text'
|
|
705
|
-
value['numeric'] = 'false'
|
|
706
|
-
value['content'] = ': '
|
|
734
|
+
value = ECValue(type=str, content=': ')
|
|
707
735
|
command['prompt'] = value
|
|
708
736
|
if self.peek() == 'with':
|
|
709
737
|
self.nextToken()
|
|
@@ -713,13 +741,18 @@ class Core(Handler):
|
|
|
713
741
|
return False
|
|
714
742
|
|
|
715
743
|
def r_input(self, command):
|
|
716
|
-
|
|
717
|
-
prompt = command['prompt']
|
|
718
|
-
value =
|
|
719
|
-
value
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
744
|
+
record = self.getVariable(command['target'])
|
|
745
|
+
prompt = command['prompt'].getValue()
|
|
746
|
+
value = ECValue(type=str, content=prompt+input(prompt))
|
|
747
|
+
self.putSymbolValue(record, value)
|
|
748
|
+
return self.nextPC()
|
|
749
|
+
|
|
750
|
+
# Declare a list variable
|
|
751
|
+
def k_list(self, command):
|
|
752
|
+
self.compiler.addValueType()
|
|
753
|
+
return self.compileVariable(command, 'ECList')
|
|
754
|
+
|
|
755
|
+
def r_list(self, command):
|
|
723
756
|
return self.nextPC()
|
|
724
757
|
|
|
725
758
|
# 1 Load a plugin. This is done at compile time.
|
|
@@ -733,9 +766,9 @@ class Core(Handler):
|
|
|
733
766
|
self.program.importPlugin(f'{source}:{clazz}')
|
|
734
767
|
return True
|
|
735
768
|
elif self.isSymbol():
|
|
736
|
-
|
|
737
|
-
if
|
|
738
|
-
command['target'] =
|
|
769
|
+
record = self.getSymbolRecord()
|
|
770
|
+
if isinstance(self.getObject(record), (ECVariable, ECDictionary, ECList)):
|
|
771
|
+
command['target'] = record['name']
|
|
739
772
|
if self.nextIs('from'):
|
|
740
773
|
if self.nextIsSymbol():
|
|
741
774
|
record = self.getSymbolRecord()
|
|
@@ -759,7 +792,7 @@ class Core(Handler):
|
|
|
759
792
|
target = self.getVariable(command['target'])
|
|
760
793
|
if 'ssh' in command:
|
|
761
794
|
ssh = self.getVariable(command['ssh'])
|
|
762
|
-
path = self.
|
|
795
|
+
path = self.textify(command['path'])
|
|
763
796
|
sftp = ssh['sftp']
|
|
764
797
|
try:
|
|
765
798
|
with sftp.open(path, 'r') as remote_file: content = remote_file.read().decode()
|
|
@@ -771,13 +804,9 @@ class Core(Handler):
|
|
|
771
804
|
else:
|
|
772
805
|
RuntimeError(self.program, f'Error: {errorReason}')
|
|
773
806
|
else:
|
|
774
|
-
filename = self.
|
|
807
|
+
filename = self.textify(command['file'])
|
|
775
808
|
try:
|
|
776
809
|
with open(filename) as f: content = f.read()
|
|
777
|
-
try:
|
|
778
|
-
if filename.endswith('.json'): content = json.loads(content)
|
|
779
|
-
except:
|
|
780
|
-
errorReason = 'Bad or null JSON string'
|
|
781
810
|
except:
|
|
782
811
|
errorReason = f'Unable to read from {filename}'
|
|
783
812
|
|
|
@@ -787,17 +816,20 @@ class Core(Handler):
|
|
|
787
816
|
return command['or']
|
|
788
817
|
else:
|
|
789
818
|
RuntimeError(self.program, f'Error: {errorReason}')
|
|
790
|
-
|
|
791
|
-
value
|
|
792
|
-
|
|
793
|
-
|
|
819
|
+
|
|
820
|
+
value = ECValue(type=str, content=content)
|
|
821
|
+
try:
|
|
822
|
+
self.putSymbolValue(target, value)
|
|
823
|
+
except Exception as e:
|
|
824
|
+
print(f'Exception "{e}": Running the "or" clause')
|
|
825
|
+
return command['or']
|
|
794
826
|
return self.nextPC()
|
|
795
827
|
|
|
796
828
|
# Lock a variable
|
|
797
829
|
def k_lock(self, command):
|
|
798
830
|
if self.nextIsSymbol():
|
|
799
|
-
|
|
800
|
-
command['target'] =
|
|
831
|
+
record = self.getSymbolRecord()
|
|
832
|
+
command['target'] = record['name']
|
|
801
833
|
self.add(command)
|
|
802
834
|
return True
|
|
803
835
|
return False
|
|
@@ -815,88 +847,91 @@ class Core(Handler):
|
|
|
815
847
|
|
|
816
848
|
# Declare a module variable
|
|
817
849
|
def k_module(self, command):
|
|
818
|
-
|
|
850
|
+
self.compiler.addValueType()
|
|
851
|
+
return self.compileVariable(command, 'ECModule')
|
|
819
852
|
|
|
820
853
|
def r_module(self, command):
|
|
821
854
|
return self.nextPC()
|
|
822
855
|
|
|
823
856
|
# Arithmetic multiply
|
|
824
|
-
# multiply {variable} by {value}
|
|
857
|
+
# multiply {variable} by {value}
|
|
858
|
+
# multiply {value1} by {value2} giving {variable}
|
|
825
859
|
def k_multiply(self, command):
|
|
826
|
-
# Get the (first)
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
860
|
+
# Get the (first) item. If it's a symbol, it may be the target variable
|
|
861
|
+
if self.nextIsSymbol():
|
|
862
|
+
record = self.getSymbolRecord()
|
|
863
|
+
self.checkObjectType(record, ECVariable)
|
|
864
|
+
# Hold onto the variable and its value
|
|
865
|
+
variable1 = record['name']
|
|
866
|
+
value1 = self.getValue()
|
|
867
|
+
else:
|
|
868
|
+
# Here we have a value
|
|
869
|
+
value1 = self.getValue()
|
|
870
|
+
variable1 = None
|
|
871
|
+
self.skip('by')
|
|
872
|
+
command['value2'] = self.nextValue()
|
|
873
|
+
# if 'giving' comes next, the target is the next value
|
|
874
|
+
if self.peek() == 'giving':
|
|
875
|
+
self.nextToken()
|
|
876
|
+
if self.nextIsSymbol():
|
|
877
|
+
record = self.getSymbolRecord()
|
|
878
|
+
self.checkObjectType(record, ECVariable)
|
|
879
|
+
command['target'] = record['name']
|
|
880
|
+
command['value1'] = value1
|
|
881
|
+
self.add(command)
|
|
882
|
+
return True
|
|
883
|
+
else:
|
|
884
|
+
# Here the first variable is the target
|
|
885
|
+
if variable1 != None:
|
|
886
|
+
command['target'] = variable1
|
|
887
|
+
self.add(command)
|
|
888
|
+
return True
|
|
844
889
|
return False
|
|
845
890
|
|
|
846
891
|
def r_multiply(self, command):
|
|
847
|
-
value1 = command['value1']
|
|
848
|
-
|
|
849
|
-
value2 = command['value2']
|
|
850
|
-
except:
|
|
851
|
-
value2 = None
|
|
892
|
+
value1 = self.textify(command['value1']) if 'value1' in command else None
|
|
893
|
+
value2 = self.textify(command['value2'])
|
|
852
894
|
target = self.getVariable(command['target'])
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
value['type'] = 'int'
|
|
860
|
-
if value2:
|
|
861
|
-
v1 = int(self.getRuntimeValue(value1))
|
|
862
|
-
v2 = int(self.getRuntimeValue(value2))
|
|
863
|
-
value['content'] = v1*v2
|
|
895
|
+
# Check that the target variable can hold a value
|
|
896
|
+
self.checkObjectType(target, ECVariable)
|
|
897
|
+
# If value1 exists, we are adding two values and storing the result in target
|
|
898
|
+
if value1 != None:
|
|
899
|
+
# multiply X by Y giving Z
|
|
900
|
+
targetValue = ECValue(type=int, content=int(value1) * int(value2))
|
|
864
901
|
else:
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
v1 = int(self.getRuntimeValue(value1))
|
|
870
|
-
value['content'] = v*v1
|
|
871
|
-
self.putSymbolValue(target, value)
|
|
902
|
+
# multiply X by Y
|
|
903
|
+
targetValue = self.getSymbolValue(target)
|
|
904
|
+
targetValue.setContent(int(targetValue.getContent()) * int(value2))
|
|
905
|
+
self.putSymbolValue(target, targetValue)
|
|
872
906
|
return self.nextPC()
|
|
873
907
|
|
|
874
908
|
# Negate a variable
|
|
875
909
|
def k_negate(self, command):
|
|
876
910
|
if self.nextIsSymbol():
|
|
877
|
-
|
|
878
|
-
if
|
|
911
|
+
record = self.getSymbolRecord()
|
|
912
|
+
if record['hasValue']:
|
|
879
913
|
command['target'] = self.getToken()
|
|
880
914
|
self.add(command)
|
|
881
915
|
return True
|
|
882
|
-
self.warning(f'Core.negate: Variable {
|
|
916
|
+
self.warning(f'Core.negate: Variable {record["name"]} does not hold a value')
|
|
883
917
|
return False
|
|
884
918
|
|
|
885
919
|
def r_negate(self, command):
|
|
886
|
-
|
|
887
|
-
if not
|
|
888
|
-
NoValueRuntimeError(self.program,
|
|
920
|
+
record = self.getVariable(command['target'])
|
|
921
|
+
if not record['hasValue']:
|
|
922
|
+
NoValueRuntimeError(self.program, record)
|
|
889
923
|
return None
|
|
890
|
-
value = self.getSymbolValue(
|
|
924
|
+
value = self.getSymbolValue(record)
|
|
891
925
|
if value == None:
|
|
892
|
-
RuntimeError(self.program, f'{
|
|
893
|
-
value
|
|
894
|
-
self.putSymbolValue(
|
|
926
|
+
RuntimeError(self.program, f'{record["name"]} has not been initialised')
|
|
927
|
+
value.setContent(value.getContent() * -1)
|
|
928
|
+
self.putSymbolValue(record, value)
|
|
895
929
|
return self.nextPC()
|
|
896
930
|
|
|
897
931
|
# on message {action}
|
|
898
932
|
def k_on(self, command):
|
|
899
|
-
|
|
933
|
+
token = self.peek()
|
|
934
|
+
if token == 'message':
|
|
900
935
|
self.nextToken()
|
|
901
936
|
command['goto'] = 0
|
|
902
937
|
self.add(command)
|
|
@@ -928,10 +963,10 @@ class Core(Handler):
|
|
|
928
963
|
# open {file} for reading/writing/appending
|
|
929
964
|
def k_open(self, command):
|
|
930
965
|
if self.nextIsSymbol():
|
|
931
|
-
|
|
932
|
-
command['target'] =
|
|
966
|
+
record = self.getSymbolRecord()
|
|
967
|
+
command['target'] = record['name']
|
|
933
968
|
command['path'] = self.nextValue()
|
|
934
|
-
if
|
|
969
|
+
if record['keyword'] == 'file':
|
|
935
970
|
if self.peek() == 'for':
|
|
936
971
|
self.nextToken()
|
|
937
972
|
token = self.nextToken()
|
|
@@ -956,39 +991,43 @@ class Core(Handler):
|
|
|
956
991
|
return False
|
|
957
992
|
|
|
958
993
|
def r_open(self, command):
|
|
959
|
-
|
|
960
|
-
path = self.
|
|
994
|
+
record = self.getVariable(command['target'])
|
|
995
|
+
path = self.textify(command['path'])
|
|
961
996
|
if command['mode'] == 'r' and os.path.exists(path) or command['mode'] != 'r':
|
|
962
|
-
|
|
997
|
+
record['file'] = open(path, command['mode'])
|
|
963
998
|
return self.nextPC()
|
|
964
999
|
RuntimeError(self.program, f"File {path} does not exist")
|
|
965
1000
|
|
|
1001
|
+
# Dummy command to hit a debugger breakpoint
|
|
1002
|
+
def k_pass(self, command):
|
|
1003
|
+
self.add(command)
|
|
1004
|
+
return True
|
|
1005
|
+
|
|
1006
|
+
def r_pass(self, command):
|
|
1007
|
+
return self.nextPC()
|
|
1008
|
+
|
|
966
1009
|
# Pop a value from a stack
|
|
967
1010
|
# pop {variable} from {stack}
|
|
968
1011
|
def k_pop(self, command):
|
|
969
1012
|
if (self.nextIsSymbol()):
|
|
970
|
-
|
|
971
|
-
|
|
1013
|
+
record = self.getSymbolRecord()
|
|
1014
|
+
self.checkObjectType(record, ECObject)
|
|
1015
|
+
command['target'] = record['name']
|
|
972
1016
|
if self.peek() == 'from':
|
|
973
1017
|
self.nextToken()
|
|
974
1018
|
if self.nextIsSymbol():
|
|
975
|
-
|
|
1019
|
+
record = self.getSymbolRecord()
|
|
1020
|
+
self.checkObjectType(record, ECStack)
|
|
1021
|
+
command['from'] = record['name']
|
|
976
1022
|
self.add(command)
|
|
977
1023
|
return True
|
|
978
1024
|
return False
|
|
979
1025
|
|
|
980
1026
|
def r_pop(self, command):
|
|
981
|
-
|
|
982
|
-
if not symbolRecord['hasValue']:
|
|
983
|
-
NoValueRuntimeError(self.program, symbolRecord)
|
|
1027
|
+
record = self.getVariable(command['target'])
|
|
984
1028
|
stackRecord = self.getVariable(command['from'])
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
self.putSymbolValue(stackRecord, stack)
|
|
988
|
-
value = {}
|
|
989
|
-
value['type'] = 'int' if type(v) == int else 'text'
|
|
990
|
-
value['content'] = v
|
|
991
|
-
self.putSymbolValue(symbolRecord, value)
|
|
1029
|
+
value = stackRecord['object'].pop()
|
|
1030
|
+
self.putSymbolValue(record, value)
|
|
992
1031
|
return self.nextPC()
|
|
993
1032
|
|
|
994
1033
|
# Perform an HTTP POST
|
|
@@ -1013,14 +1052,12 @@ class Core(Handler):
|
|
|
1013
1052
|
|
|
1014
1053
|
def r_post(self, command):
|
|
1015
1054
|
global errorCode, errorReason
|
|
1016
|
-
retval =
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
value = self.getRuntimeValue(command['value'])
|
|
1020
|
-
url = self.getRuntimeValue(command['url'])
|
|
1055
|
+
retval = ECValue(type=str, content = '')
|
|
1056
|
+
value = self.textify(command['value'])
|
|
1057
|
+
url = self.textify(command['url'])
|
|
1021
1058
|
try:
|
|
1022
1059
|
response = requests.post(url, value, timeout=5)
|
|
1023
|
-
retval
|
|
1060
|
+
retval.setContent(response.text) # type: ignore
|
|
1024
1061
|
if response.status_code >= 400:
|
|
1025
1062
|
errorCode = response.status_code
|
|
1026
1063
|
errorReason = response.reason
|
|
@@ -1052,7 +1089,7 @@ class Core(Handler):
|
|
|
1052
1089
|
return False
|
|
1053
1090
|
|
|
1054
1091
|
def r_print(self, command):
|
|
1055
|
-
value = self.
|
|
1092
|
+
value = self.textify(command['value'])
|
|
1056
1093
|
program = command['program']
|
|
1057
1094
|
code = program.code[program.pc]
|
|
1058
1095
|
lino = str(code['lino'] + 1)
|
|
@@ -1073,38 +1110,32 @@ class Core(Handler):
|
|
|
1073
1110
|
if peekValue in ['onto', 'to']:
|
|
1074
1111
|
self.nextToken()
|
|
1075
1112
|
if self.nextIsSymbol():
|
|
1076
|
-
|
|
1077
|
-
command['to'] =
|
|
1113
|
+
record = self.getSymbolRecord()
|
|
1114
|
+
command['to'] = record['name']
|
|
1078
1115
|
self.add(command)
|
|
1079
1116
|
return True
|
|
1080
1117
|
return False
|
|
1081
1118
|
|
|
1082
1119
|
def r_push(self, command):
|
|
1083
|
-
value = deepcopy(self.
|
|
1120
|
+
value = deepcopy(self.evaluate(command['value']))
|
|
1084
1121
|
stackRecord = self.getVariable(command['to'])
|
|
1085
|
-
|
|
1086
|
-
RuntimeError(self.program, f'{stackRecord["name"]} is not a stack')
|
|
1087
|
-
return -1
|
|
1088
|
-
stack = stackRecord['value'][stackRecord['index']]
|
|
1089
|
-
if stack == None:
|
|
1090
|
-
stack = [value]
|
|
1091
|
-
else:
|
|
1092
|
-
stack.append(value)
|
|
1093
|
-
self.putSymbolValue(stackRecord, stack)
|
|
1122
|
+
stackRecord['object'].push(value)
|
|
1094
1123
|
return self.nextPC()
|
|
1095
1124
|
|
|
1096
|
-
# put {value} into {variable}
|
|
1125
|
+
# put {value} into {variable/dictionary/list}
|
|
1097
1126
|
def k_put(self, command):
|
|
1098
1127
|
value = self.nextValue()
|
|
1099
1128
|
if value != None:
|
|
1100
1129
|
command['value'] = value
|
|
1130
|
+
valueType = value.getType()
|
|
1101
1131
|
if self.nextIs('into'):
|
|
1102
1132
|
if self.nextIsSymbol():
|
|
1103
|
-
|
|
1104
|
-
command['target'] =
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1133
|
+
record = self.getSymbolRecord()
|
|
1134
|
+
command['target'] = record['name']
|
|
1135
|
+
object = self.getObject(record)
|
|
1136
|
+
self.checkObjectType(object, (ECVariable, ECDictionary, ECList))
|
|
1137
|
+
if (isinstance(object, ECVariable) and not valueType in ('dict', 'list', 'json') or
|
|
1138
|
+
isinstance(object, (ECDictionary, ECList))):
|
|
1108
1139
|
command['or'] = None
|
|
1109
1140
|
self.processOr(command, self.getCodeSize())
|
|
1110
1141
|
return True
|
|
@@ -1114,16 +1145,8 @@ class Core(Handler):
|
|
|
1114
1145
|
|
|
1115
1146
|
def r_put(self, command):
|
|
1116
1147
|
value = self.evaluate(command['value'])
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
return command['or']
|
|
1120
|
-
else:
|
|
1121
|
-
RuntimeError(self.program, f'Error: could not compute value')
|
|
1122
|
-
symbolRecord = self.getVariable(command['target'])
|
|
1123
|
-
if not symbolRecord['hasValue']:
|
|
1124
|
-
NoValueRuntimeError(self.program, symbolRecord)
|
|
1125
|
-
return -1
|
|
1126
|
-
self.putSymbolValue(symbolRecord, value)
|
|
1148
|
+
record = self.getVariable(command['target'])
|
|
1149
|
+
self.putSymbolValue(record, value)
|
|
1127
1150
|
return self.nextPC()
|
|
1128
1151
|
|
|
1129
1152
|
# Read from a file
|
|
@@ -1135,41 +1158,38 @@ class Core(Handler):
|
|
|
1135
1158
|
else:
|
|
1136
1159
|
command['line'] = False
|
|
1137
1160
|
if self.nextIsSymbol():
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
FatalError(self.compiler, f'Symbol "{symbolRecord["name"]}" is not a value holder')
|
|
1161
|
+
record = self.getSymbolRecord()
|
|
1162
|
+
self.checkObjectType(self.getObject(record), ECVariable)
|
|
1163
|
+
if self.peek() == 'from':
|
|
1164
|
+
self.nextToken()
|
|
1165
|
+
if self.nextIsSymbol():
|
|
1166
|
+
fileRecord = self.getSymbolRecord()
|
|
1167
|
+
self.checkObjectType(fileRecord['object'], ECFile)
|
|
1168
|
+
command['target'] = record['name']
|
|
1169
|
+
command['file'] = fileRecord['name']
|
|
1170
|
+
self.add(command)
|
|
1171
|
+
return True
|
|
1150
1172
|
return False
|
|
1151
1173
|
FatalError(self.compiler, f'Symbol "{self.getToken()}" has not been declared')
|
|
1152
1174
|
return False
|
|
1153
1175
|
|
|
1154
1176
|
def r_read(self, command):
|
|
1155
|
-
|
|
1177
|
+
record = self.getVariable(command['target'])
|
|
1156
1178
|
fileRecord = self.getVariable(command['file'])
|
|
1157
1179
|
line = command['line']
|
|
1158
1180
|
file = fileRecord['file']
|
|
1159
1181
|
if file.mode == 'r':
|
|
1160
|
-
value = {}
|
|
1161
1182
|
content = file.readline().split('\n')[0] if line else file.read()
|
|
1162
|
-
value
|
|
1163
|
-
value
|
|
1164
|
-
value['content'] = content
|
|
1165
|
-
self.putSymbolValue(symbolRecord, value)
|
|
1183
|
+
value = ECValue(type=str, content=content)
|
|
1184
|
+
self.putSymbolValue(record, value)
|
|
1166
1185
|
return self.nextPC()
|
|
1167
1186
|
|
|
1168
1187
|
# Release the parent script
|
|
1169
1188
|
def k_release(self, command):
|
|
1170
1189
|
if self.nextIs('parent'):
|
|
1171
1190
|
self.add(command)
|
|
1172
|
-
|
|
1191
|
+
return True
|
|
1192
|
+
return False
|
|
1173
1193
|
|
|
1174
1194
|
def r_release(self, command):
|
|
1175
1195
|
self.program.releaseParent()
|
|
@@ -1194,23 +1214,35 @@ class Core(Handler):
|
|
|
1194
1214
|
|
|
1195
1215
|
def r_replace(self, command):
|
|
1196
1216
|
templateRecord = self.getVariable(command['target'])
|
|
1197
|
-
content = self.getSymbolValue(templateRecord)
|
|
1198
|
-
original = self.
|
|
1199
|
-
replacement = self.
|
|
1217
|
+
content = self.getSymbolValue(templateRecord).getContent()
|
|
1218
|
+
original = self.textify(command['original'])
|
|
1219
|
+
replacement = self.textify(command['replacement'])
|
|
1200
1220
|
content = content.replace(original, str(replacement))
|
|
1201
|
-
value =
|
|
1202
|
-
value['type'] = 'text'
|
|
1203
|
-
value['numeric'] = False
|
|
1204
|
-
value['content'] = content
|
|
1221
|
+
value = ECValue(type=str, content=content)
|
|
1205
1222
|
self.putSymbolValue(templateRecord, value)
|
|
1206
1223
|
return self.nextPC()
|
|
1207
1224
|
|
|
1225
|
+
# Reset a variable
|
|
1226
|
+
def k_reset(self, command):
|
|
1227
|
+
if self.nextIsSymbol():
|
|
1228
|
+
record = self.getSymbolRecord()
|
|
1229
|
+
command['target'] = record['name']
|
|
1230
|
+
self.add(command)
|
|
1231
|
+
return True
|
|
1232
|
+
return False
|
|
1233
|
+
|
|
1234
|
+
def r_reset(self, command):
|
|
1235
|
+
record = self.getVariable(command['target'])
|
|
1236
|
+
self.getObject(record).reset()
|
|
1237
|
+
return self.nextPC()
|
|
1238
|
+
|
|
1208
1239
|
# Return from subroutine
|
|
1209
1240
|
def k_return(self, command):
|
|
1210
1241
|
self.add(command)
|
|
1211
1242
|
return True
|
|
1212
1243
|
|
|
1213
1244
|
def r_return(self, command):
|
|
1245
|
+
self.program.debugSkip = False
|
|
1214
1246
|
return self.stack.pop()
|
|
1215
1247
|
|
|
1216
1248
|
# Compile and run a script
|
|
@@ -1246,15 +1278,15 @@ class Core(Handler):
|
|
|
1246
1278
|
|
|
1247
1279
|
def r_run(self, command):
|
|
1248
1280
|
module = self.getVariable(command['module'])
|
|
1249
|
-
path = self.
|
|
1281
|
+
path = self.textify(command['path'])
|
|
1250
1282
|
exports = json.loads(command['exports'])
|
|
1251
1283
|
for n in range(0, len(exports)):
|
|
1252
1284
|
exports[n] = self.getVariable(exports[n])
|
|
1253
1285
|
module['path'] = path
|
|
1254
|
-
parent =
|
|
1255
|
-
parent.program = self.program
|
|
1256
|
-
parent.pc = self.nextPC()
|
|
1257
|
-
parent.waiting = True
|
|
1286
|
+
parent = ECValue()
|
|
1287
|
+
parent.program = self.program # type: ignore
|
|
1288
|
+
parent.pc = self.nextPC() # type: ignore
|
|
1289
|
+
parent.waiting = True # type: ignore
|
|
1258
1290
|
p = self.program.__class__
|
|
1259
1291
|
p(path).start(parent, module, exports)
|
|
1260
1292
|
return 0
|
|
@@ -1268,7 +1300,6 @@ class Core(Handler):
|
|
|
1268
1300
|
if record['keyword'] == 'ssh':
|
|
1269
1301
|
command['ssh'] = record['name']
|
|
1270
1302
|
command['path'] = self.nextValue()
|
|
1271
|
-
self.add(command)
|
|
1272
1303
|
else:
|
|
1273
1304
|
command['file'] = self.getValue()
|
|
1274
1305
|
else:
|
|
@@ -1280,10 +1311,10 @@ class Core(Handler):
|
|
|
1280
1311
|
|
|
1281
1312
|
def r_save(self, command):
|
|
1282
1313
|
errorReason = None
|
|
1283
|
-
content = self.
|
|
1314
|
+
content = self.textify(command['content'])
|
|
1284
1315
|
if 'ssh' in command:
|
|
1285
1316
|
ssh = self.getVariable(command['ssh'])
|
|
1286
|
-
path = self.
|
|
1317
|
+
path = self.textify(command['path'])
|
|
1287
1318
|
sftp = ssh['sftp']
|
|
1288
1319
|
if path.endswith('.json'): content = json.dumps(content)
|
|
1289
1320
|
try:
|
|
@@ -1296,12 +1327,17 @@ class Core(Handler):
|
|
|
1296
1327
|
else:
|
|
1297
1328
|
RuntimeError(self.program, f'Error: {errorReason}')
|
|
1298
1329
|
else:
|
|
1299
|
-
filename = self.
|
|
1300
|
-
if filename.endswith('.json'): content = json.dumps(content)
|
|
1330
|
+
filename = self.textify(command['file'])
|
|
1301
1331
|
try:
|
|
1332
|
+
if content == None:
|
|
1333
|
+
content = ''
|
|
1334
|
+
elif isinstance(content, dict) or isinstance(content, list):
|
|
1335
|
+
content = json.dumps(content)
|
|
1336
|
+
elif not isinstance(content, str):
|
|
1337
|
+
content = self.textify(content)
|
|
1302
1338
|
with open(filename, 'w') as f: f.write(content)
|
|
1303
|
-
except:
|
|
1304
|
-
errorReason = f'Unable to write to {filename}'
|
|
1339
|
+
except Exception as e:
|
|
1340
|
+
errorReason = f'Unable to write to {filename}: {str(e)}'
|
|
1305
1341
|
|
|
1306
1342
|
if errorReason:
|
|
1307
1343
|
if command['or'] != None:
|
|
@@ -1322,32 +1358,30 @@ class Core(Handler):
|
|
|
1322
1358
|
if self.nextIs('to'):
|
|
1323
1359
|
if self.nextIsSymbol():
|
|
1324
1360
|
record = self.getSymbolRecord()
|
|
1325
|
-
if record
|
|
1361
|
+
if self.isObjectType(record, ECModule):
|
|
1326
1362
|
command['module'] = record['name']
|
|
1327
1363
|
self.add(command)
|
|
1328
1364
|
return True
|
|
1329
1365
|
return False
|
|
1330
1366
|
|
|
1331
1367
|
def r_send(self, command):
|
|
1332
|
-
message = self.
|
|
1368
|
+
message = self.textify(command['message'])
|
|
1333
1369
|
module = self.getVariable(command['module'])
|
|
1334
1370
|
module['child'].handleMessage(message)
|
|
1335
1371
|
return self.nextPC()
|
|
1336
1372
|
|
|
1337
1373
|
# Set a value
|
|
1338
1374
|
# set {variable}
|
|
1375
|
+
# set {variable} to {value}
|
|
1339
1376
|
# set {ssh} host {host} user {user} password {password}
|
|
1340
|
-
# set the elements of {variable} to {value}
|
|
1341
|
-
# set
|
|
1377
|
+
# set the items/elements in/of {variable} to {value}
|
|
1378
|
+
# set item/entry/property of {variable} to {value}
|
|
1379
|
+
# set breakpoint
|
|
1342
1380
|
def k_set(self, command):
|
|
1343
1381
|
if self.nextIsSymbol():
|
|
1344
1382
|
record = self.getSymbolRecord()
|
|
1345
1383
|
command['target'] = record['name']
|
|
1346
|
-
if record['
|
|
1347
|
-
command['type'] = 'set'
|
|
1348
|
-
self.add(command)
|
|
1349
|
-
return True
|
|
1350
|
-
elif record['keyword'] == 'ssh':
|
|
1384
|
+
if record['keyword'] == 'ssh':
|
|
1351
1385
|
host = None
|
|
1352
1386
|
user = None
|
|
1353
1387
|
password = None
|
|
@@ -1369,7 +1403,18 @@ class Core(Handler):
|
|
|
1369
1403
|
command['type'] = 'ssh'
|
|
1370
1404
|
self.add(command)
|
|
1371
1405
|
return True
|
|
1372
|
-
|
|
1406
|
+
elif isinstance(self.getObject(record), ECVariable):
|
|
1407
|
+
self.skip('to')
|
|
1408
|
+
mark = self.compiler.getIndex()
|
|
1409
|
+
value = self.nextValue()
|
|
1410
|
+
if value != None:
|
|
1411
|
+
command['type'] = 'setValue'
|
|
1412
|
+
command['value'] = value
|
|
1413
|
+
else:
|
|
1414
|
+
self.rewindTo(mark)
|
|
1415
|
+
command['type'] = 'set'
|
|
1416
|
+
self.add(command)
|
|
1417
|
+
return True
|
|
1373
1418
|
return False
|
|
1374
1419
|
|
|
1375
1420
|
token = self.getToken()
|
|
@@ -1379,7 +1424,7 @@ class Core(Handler):
|
|
|
1379
1424
|
|
|
1380
1425
|
if token == 'elements':
|
|
1381
1426
|
self.nextToken()
|
|
1382
|
-
if self.peek()
|
|
1427
|
+
if self.peek() in ('in', 'of'):
|
|
1383
1428
|
self.nextToken()
|
|
1384
1429
|
if self.nextIsSymbol():
|
|
1385
1430
|
command['name'] = self.getToken()
|
|
@@ -1395,11 +1440,14 @@ class Core(Handler):
|
|
|
1395
1440
|
self.add(command)
|
|
1396
1441
|
return True
|
|
1397
1442
|
|
|
1398
|
-
elif token
|
|
1399
|
-
command['
|
|
1443
|
+
elif token in ('entry', 'property'):
|
|
1444
|
+
command['key'] = self.nextValue()
|
|
1400
1445
|
if self.nextIs('of'):
|
|
1401
1446
|
if self.nextIsSymbol():
|
|
1402
|
-
|
|
1447
|
+
record = self.getSymbolRecord()
|
|
1448
|
+
if token == 'entry':
|
|
1449
|
+
self.checkObjectType(self.getObject(record), ECDictionary)
|
|
1450
|
+
command['target'] = record['name']
|
|
1403
1451
|
if self.nextIs('to'):
|
|
1404
1452
|
value = self.nextValue()
|
|
1405
1453
|
if value == None:
|
|
@@ -1408,7 +1456,7 @@ class Core(Handler):
|
|
|
1408
1456
|
self.add(command)
|
|
1409
1457
|
return True
|
|
1410
1458
|
|
|
1411
|
-
elif token == '
|
|
1459
|
+
elif token == 'item':
|
|
1412
1460
|
command['index'] = self.nextValue()
|
|
1413
1461
|
if self.nextIs('of'):
|
|
1414
1462
|
if self.nextIsSymbol():
|
|
@@ -1422,6 +1470,11 @@ class Core(Handler):
|
|
|
1422
1470
|
command['path'] = self.nextValue()
|
|
1423
1471
|
self.add(command)
|
|
1424
1472
|
return True
|
|
1473
|
+
|
|
1474
|
+
elif token == 'breakpoint':
|
|
1475
|
+
command['breakpoint'] = True
|
|
1476
|
+
self.add(command)
|
|
1477
|
+
return True
|
|
1425
1478
|
|
|
1426
1479
|
return False
|
|
1427
1480
|
|
|
@@ -1429,81 +1482,70 @@ class Core(Handler):
|
|
|
1429
1482
|
cmdType = command['type']
|
|
1430
1483
|
if cmdType == 'set':
|
|
1431
1484
|
target = self.getVariable(command['target'])
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1485
|
+
self.putSymbolValue(target, ECValue(type=bool, content=True))
|
|
1486
|
+
return self.nextPC()
|
|
1487
|
+
|
|
1488
|
+
elif cmdType == 'setValue':
|
|
1489
|
+
value = self.evaluate(command['value'])
|
|
1490
|
+
target = self.getVariable(command['target'])
|
|
1491
|
+
self.putSymbolValue(target, value)
|
|
1436
1492
|
return self.nextPC()
|
|
1437
1493
|
|
|
1438
1494
|
elif cmdType == 'elements':
|
|
1439
|
-
|
|
1440
|
-
elements = self.
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
currentValue = [None]
|
|
1445
|
-
newValue = [None] * elements
|
|
1446
|
-
if elements > currentElements:
|
|
1447
|
-
for index, value in enumerate(currentValue):
|
|
1448
|
-
newValue[index] = value
|
|
1449
|
-
elif elements < currentElements:
|
|
1450
|
-
for index, value in enumerate(currentValue):
|
|
1451
|
-
if index < elements:
|
|
1452
|
-
newValue[index] = value
|
|
1453
|
-
symbolRecord['elements'] = elements
|
|
1454
|
-
symbolRecord['value'] = newValue
|
|
1455
|
-
symbolRecord['index'] = 0
|
|
1495
|
+
record = self.getVariable(command['name'])
|
|
1496
|
+
elements = self.textify(command['elements'])
|
|
1497
|
+
object = self.getObject(record)
|
|
1498
|
+
self.checkObjectType(object, ECObject)
|
|
1499
|
+
object.setElements(elements)
|
|
1456
1500
|
return self.nextPC()
|
|
1457
1501
|
|
|
1458
|
-
elif cmdType == '
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
content = []
|
|
1466
|
-
# else:
|
|
1467
|
-
# content = json.loads(content)
|
|
1468
|
-
content[index] = value
|
|
1469
|
-
val['content'] = content
|
|
1470
|
-
self.putSymbolValue(target, val)
|
|
1502
|
+
elif cmdType == 'item':
|
|
1503
|
+
index = self.textify(command['index'])
|
|
1504
|
+
value = self.textify(command['value'])
|
|
1505
|
+
record = self.getVariable(command['target'])
|
|
1506
|
+
self.checkObjectType(self.getObject(record), ECList)
|
|
1507
|
+
variable = self.getObject(record)
|
|
1508
|
+
variable.setItem(index, value)
|
|
1471
1509
|
return self.nextPC()
|
|
1472
1510
|
|
|
1473
1511
|
elif cmdType == 'encoding':
|
|
1474
|
-
self.encoding = self.
|
|
1512
|
+
self.encoding = self.textify(command['encoding'])
|
|
1475
1513
|
return self.nextPC()
|
|
1476
1514
|
|
|
1477
1515
|
elif cmdType == 'path':
|
|
1478
|
-
path = self.
|
|
1516
|
+
path = self.textify(command['path'])
|
|
1479
1517
|
os.chdir(path)
|
|
1480
1518
|
return self.nextPC()
|
|
1481
1519
|
|
|
1520
|
+
elif cmdType == 'entry':
|
|
1521
|
+
key = self.textify(command['key'])
|
|
1522
|
+
value = self.textify(command['value'])
|
|
1523
|
+
record = self.getVariable(command['target'])
|
|
1524
|
+
self.checkObjectType(self.getObject(record), ECDictionary)
|
|
1525
|
+
variable = self.getObject(record)
|
|
1526
|
+
variable.setEntry(key, value)
|
|
1527
|
+
return self.nextPC()
|
|
1528
|
+
|
|
1482
1529
|
elif cmdType == 'property':
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
RuntimeError(self.program, f'{
|
|
1492
|
-
if content
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
content[name] = value
|
|
1496
|
-
except:
|
|
1497
|
-
RuntimeError(self.program, f'{target} is not an object')
|
|
1498
|
-
val['content'] = content
|
|
1499
|
-
self.putSymbolValue(targetVariable, val)
|
|
1530
|
+
key = self.textify(command['key'])
|
|
1531
|
+
value = self.evaluate(command['value'])
|
|
1532
|
+
record = self.getVariable(command['target'])
|
|
1533
|
+
variable = self.getObject(record)
|
|
1534
|
+
variable.setProperty(key, value)
|
|
1535
|
+
content = variable.getContent()
|
|
1536
|
+
if content == None: content = {}
|
|
1537
|
+
elif not isinstance(content, dict):
|
|
1538
|
+
raise RuntimeError(self.program, f'{record["name"]} is not a dictionary')
|
|
1539
|
+
if isinstance(value, dict): content[key] = value
|
|
1540
|
+
else: content[key] = self.textify(value)
|
|
1541
|
+
variable.setContent(ECValue(type='dict', content=content))
|
|
1500
1542
|
return self.nextPC()
|
|
1501
1543
|
|
|
1502
1544
|
elif cmdType == 'ssh':
|
|
1503
1545
|
target = self.getVariable(command['target'])
|
|
1504
|
-
host = self.
|
|
1505
|
-
user = self.
|
|
1506
|
-
password = self.
|
|
1546
|
+
host = self.textify(command['host'])
|
|
1547
|
+
user = self.textify(command['user'])
|
|
1548
|
+
password = self.textify(command['password'])
|
|
1507
1549
|
ssh = paramiko.SSHClient()
|
|
1508
1550
|
target['ssh'] = ssh
|
|
1509
1551
|
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
@@ -1513,50 +1555,51 @@ class Core(Handler):
|
|
|
1513
1555
|
except:
|
|
1514
1556
|
target['error'] = f'Unable to connect to {host} (timeout)'
|
|
1515
1557
|
return self.nextPC()
|
|
1558
|
+
|
|
1559
|
+
elif cmdType == 'breakpoint':
|
|
1560
|
+
self.program.breakpoint = True
|
|
1561
|
+
return self.nextPC()
|
|
1516
1562
|
|
|
1517
|
-
# Shuffle a list
|
|
1563
|
+
# Shuffle a JSON list
|
|
1518
1564
|
def k_shuffle(self, command):
|
|
1519
1565
|
if self.nextIsSymbol():
|
|
1520
|
-
|
|
1521
|
-
if
|
|
1566
|
+
record = self.getSymbolRecord()
|
|
1567
|
+
if record['hasValue']:
|
|
1522
1568
|
command['target'] = self.getToken()
|
|
1523
1569
|
self.add(command)
|
|
1524
1570
|
return True
|
|
1525
|
-
self.warning(f'Core.negate: Variable {
|
|
1571
|
+
self.warning(f'Core.negate: Variable {record["name"]} does not hold a value')
|
|
1526
1572
|
return False
|
|
1527
1573
|
|
|
1528
1574
|
def r_shuffle(self, command):
|
|
1529
|
-
|
|
1530
|
-
if not
|
|
1531
|
-
NoValueRuntimeError(self.program,
|
|
1575
|
+
record = self.getVariable(command['target'])
|
|
1576
|
+
if not record['hasValue']:
|
|
1577
|
+
NoValueRuntimeError(self.program, record)
|
|
1532
1578
|
return None
|
|
1533
|
-
value = self.getSymbolValue(
|
|
1579
|
+
value = self.getSymbolValue(record)
|
|
1534
1580
|
if value == None:
|
|
1535
|
-
RuntimeError(self.program, f'{
|
|
1536
|
-
content = value
|
|
1581
|
+
RuntimeError(self.program, f'{record["name"]} has not been initialised')
|
|
1582
|
+
content = value.getContent()
|
|
1537
1583
|
if isinstance(content, list):
|
|
1538
1584
|
random.shuffle(content)
|
|
1539
|
-
value
|
|
1540
|
-
self.putSymbolValue(
|
|
1585
|
+
value.setContent(content)
|
|
1586
|
+
self.putSymbolValue(record, value)
|
|
1541
1587
|
return self.nextPC()
|
|
1542
|
-
RuntimeError(self.program, f'{
|
|
1588
|
+
RuntimeError(self.program, f'{record["name"]} is not a list')
|
|
1543
1589
|
|
|
1544
1590
|
# Split a string into a variable with several elements
|
|
1545
1591
|
# split {variable} on {value}
|
|
1546
1592
|
def k_split(self, command):
|
|
1547
1593
|
if self.nextIsSymbol():
|
|
1548
|
-
|
|
1549
|
-
if
|
|
1550
|
-
command['target'] =
|
|
1551
|
-
value =
|
|
1552
|
-
value['type'] = 'text'
|
|
1553
|
-
value['numeric'] = 'false'
|
|
1554
|
-
value['content'] = '\n'
|
|
1594
|
+
record = self.getSymbolRecord()
|
|
1595
|
+
if isinstance(record['object'], ECObject):
|
|
1596
|
+
command['target'] = record['name']
|
|
1597
|
+
value = ECValue(type=str, content='\n')
|
|
1555
1598
|
command['on'] = value
|
|
1556
1599
|
if self.peek() == 'on':
|
|
1557
1600
|
self.nextToken()
|
|
1558
1601
|
if self.peek() == 'tab':
|
|
1559
|
-
value
|
|
1602
|
+
value.setContent('\t')
|
|
1560
1603
|
self.nextToken()
|
|
1561
1604
|
else:
|
|
1562
1605
|
command['on'] = self.nextValue()
|
|
@@ -1568,30 +1611,31 @@ class Core(Handler):
|
|
|
1568
1611
|
def r_split(self, command):
|
|
1569
1612
|
target = self.getVariable(command['target'])
|
|
1570
1613
|
value = self.getSymbolValue(target)
|
|
1571
|
-
content = value
|
|
1614
|
+
content = value.getContent().split(self.textify(command['on']))
|
|
1572
1615
|
elements = len(content)
|
|
1573
|
-
target['
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
element['content'] = item
|
|
1582
|
-
target['value'][index] = element
|
|
1616
|
+
object = target['object']
|
|
1617
|
+
object.setElements(elements)
|
|
1618
|
+
|
|
1619
|
+
for n in range(0, elements):
|
|
1620
|
+
val = ECValue(type=str, content=content[n])
|
|
1621
|
+
object.setIndex(n)
|
|
1622
|
+
object.setValue(val)
|
|
1623
|
+
object.setIndex(0)
|
|
1583
1624
|
|
|
1584
1625
|
return self.nextPC()
|
|
1585
1626
|
|
|
1627
|
+
# Declare an SSH connection variable
|
|
1586
1628
|
def k_ssh(self, command):
|
|
1587
|
-
|
|
1629
|
+
self.compiler.addValueType()
|
|
1630
|
+
return self.compileVariable(command, 'ECSSH')
|
|
1588
1631
|
|
|
1589
1632
|
def r_ssh(self, command):
|
|
1590
1633
|
return self.nextPC()
|
|
1591
1634
|
|
|
1592
1635
|
# Declare a stack variable
|
|
1593
1636
|
def k_stack(self, command):
|
|
1594
|
-
|
|
1637
|
+
self.compiler.addValueType()
|
|
1638
|
+
return self.compileVariable(command, 'ECStack')
|
|
1595
1639
|
|
|
1596
1640
|
def r_stack(self, command):
|
|
1597
1641
|
return self.nextPC()
|
|
@@ -1622,7 +1666,7 @@ class Core(Handler):
|
|
|
1622
1666
|
return False
|
|
1623
1667
|
|
|
1624
1668
|
def r_system(self, command):
|
|
1625
|
-
value = self.
|
|
1669
|
+
value = self.textify(command['value'])
|
|
1626
1670
|
if value != None:
|
|
1627
1671
|
if command['background']:
|
|
1628
1672
|
subprocess.Popen(["sh",value,"&"])
|
|
@@ -1631,82 +1675,77 @@ class Core(Handler):
|
|
|
1631
1675
|
return self.nextPC()
|
|
1632
1676
|
|
|
1633
1677
|
# Arithmetic subtraction
|
|
1634
|
-
# take {value} from {variable}
|
|
1678
|
+
# take {value} from {variable}
|
|
1679
|
+
# take {value1} from {value2} giving {variable}
|
|
1635
1680
|
def k_take(self, command):
|
|
1636
1681
|
# Get the (first) value
|
|
1637
1682
|
command['value1'] = self.nextValue()
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1683
|
+
self.skip('from')
|
|
1684
|
+
if self.nextIsSymbol():
|
|
1685
|
+
record = self.getSymbolRecord()
|
|
1686
|
+
self.checkObjectType(record, ECObject)
|
|
1687
|
+
# If 'giving' comes next, this variable is the second value
|
|
1688
|
+
if self.peek() == 'giving':
|
|
1689
|
+
v2 = ECValue(type='symbol')
|
|
1690
|
+
v2.setContent(record['name'])
|
|
1691
|
+
command['value2'] = v2
|
|
1692
|
+
self.nextToken()
|
|
1693
|
+
# Now get the target variable
|
|
1694
|
+
if self.nextIsSymbol():
|
|
1695
|
+
record = self.getSymbolRecord()
|
|
1696
|
+
self.checkObjectType(record, ECVariable)
|
|
1697
|
+
command['target'] = record['name']
|
|
1698
|
+
self.add(command)
|
|
1699
|
+
return True
|
|
1655
1700
|
else:
|
|
1656
|
-
# Here
|
|
1657
|
-
command['
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
self.
|
|
1701
|
+
# Here the variable is the target
|
|
1702
|
+
command['target'] = record['name']
|
|
1703
|
+
self.add(command)
|
|
1704
|
+
return True
|
|
1705
|
+
else:
|
|
1706
|
+
# Here we have 2 values so 'giving' must come next
|
|
1707
|
+
command['value2'] = self.getValue()
|
|
1708
|
+
if self.nextToken() == 'giving':
|
|
1709
|
+
if self.nextIsSymbol():
|
|
1710
|
+
record = self.getSymbolRecord()
|
|
1711
|
+
self.checkObjectType(record, ECVariable)
|
|
1712
|
+
command['target'] = record['name']
|
|
1713
|
+
self.add(command)
|
|
1714
|
+
return True
|
|
1715
|
+
raise FatalError(self.compiler, 'Cannot subtract values: target variable expected')
|
|
1667
1716
|
return False
|
|
1668
1717
|
|
|
1669
1718
|
def r_take(self, command):
|
|
1670
|
-
value1 = command['value1']
|
|
1671
|
-
|
|
1672
|
-
value2 = command['value2']
|
|
1673
|
-
except:
|
|
1674
|
-
value2 = None
|
|
1719
|
+
value1 = self.textify(command['value1'])
|
|
1720
|
+
value2 = self.textify(command['value2']) if 'value2' in command else None
|
|
1675
1721
|
target = self.getVariable(command['target'])
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
value['type'] = 'int'
|
|
1683
|
-
if value2:
|
|
1684
|
-
v1 = int(self.getRuntimeValue(value1))
|
|
1685
|
-
v2 = int(self.getRuntimeValue(value2))
|
|
1686
|
-
value['content'] = v2-v1
|
|
1722
|
+
# Check that the target variable can hold a value
|
|
1723
|
+
self.checkObjectType(target, ECVariable)
|
|
1724
|
+
# If value2 exists, we are adding two values and storing the result in target
|
|
1725
|
+
if value2 != None:
|
|
1726
|
+
# take X from Y giving Z
|
|
1727
|
+
targetValue = ECValue(type=int, content=int(value2) - int(value1))
|
|
1687
1728
|
else:
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
self.putSymbolValue(target,
|
|
1729
|
+
# take X from Y
|
|
1730
|
+
targetValue = self.getSymbolValue(target)
|
|
1731
|
+
targetValue.setContent(int(targetValue.getContent()) - int(value1))
|
|
1732
|
+
self.putSymbolValue(target, targetValue)
|
|
1692
1733
|
return self.nextPC()
|
|
1693
1734
|
|
|
1694
1735
|
# Toggle a boolean value
|
|
1695
1736
|
def k_toggle(self, command):
|
|
1696
1737
|
if self.nextIsSymbol():
|
|
1697
1738
|
target = self.getSymbolRecord()
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1739
|
+
self.checkObjectType(target, ECVariable)
|
|
1740
|
+
command['target'] = target['name']
|
|
1741
|
+
self.add(command)
|
|
1742
|
+
return True
|
|
1702
1743
|
return False
|
|
1703
1744
|
|
|
1704
1745
|
def r_toggle(self, command):
|
|
1705
1746
|
target = self.getVariable(command['target'])
|
|
1706
1747
|
value = self.getSymbolValue(target)
|
|
1707
|
-
val =
|
|
1708
|
-
val['type'] = 'boolean'
|
|
1709
|
-
val['content'] = not value['content']
|
|
1748
|
+
val = ECValue(type=bool, content=not value.getContent())
|
|
1710
1749
|
self.putSymbolValue(target, val)
|
|
1711
1750
|
self.add(command)
|
|
1712
1751
|
return self.nextPC()
|
|
@@ -1724,9 +1763,9 @@ class Core(Handler):
|
|
|
1724
1763
|
def r_trim(self, command):
|
|
1725
1764
|
record = self.getVariable(command['name'])
|
|
1726
1765
|
value = record['value'][record['index']]
|
|
1727
|
-
if value
|
|
1728
|
-
content = value
|
|
1729
|
-
value
|
|
1766
|
+
if value.getType() == str:
|
|
1767
|
+
content = value.getContent()
|
|
1768
|
+
value.setContent(content.strip())
|
|
1730
1769
|
return self.nextPC()
|
|
1731
1770
|
|
|
1732
1771
|
# Truncate a file
|
|
@@ -1747,8 +1786,8 @@ class Core(Handler):
|
|
|
1747
1786
|
# Unlock a variable
|
|
1748
1787
|
def k_unlock(self, command):
|
|
1749
1788
|
if self.nextIsSymbol():
|
|
1750
|
-
|
|
1751
|
-
command['target'] =
|
|
1789
|
+
record = self.getSymbolRecord()
|
|
1790
|
+
command['target'] = record['name']
|
|
1752
1791
|
self.add(command)
|
|
1753
1792
|
return True
|
|
1754
1793
|
return False
|
|
@@ -1758,7 +1797,10 @@ class Core(Handler):
|
|
|
1758
1797
|
target['locked'] = False
|
|
1759
1798
|
return self.nextPC()
|
|
1760
1799
|
|
|
1761
|
-
#
|
|
1800
|
+
# use plugin {class} from {source}
|
|
1801
|
+
# use graphics
|
|
1802
|
+
# use mqtt
|
|
1803
|
+
# use psutil
|
|
1762
1804
|
def k_use(self, command):
|
|
1763
1805
|
if self.peek() == 'plugin':
|
|
1764
1806
|
# Import a plugin
|
|
@@ -1771,21 +1813,22 @@ class Core(Handler):
|
|
|
1771
1813
|
return False
|
|
1772
1814
|
else:
|
|
1773
1815
|
token = self.nextToken()
|
|
1774
|
-
if token
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
self.program.usingGraphics = True
|
|
1781
|
-
if token == 'debugger': self.program.debugging = True
|
|
1782
|
-
return True
|
|
1816
|
+
if token == 'graphics':
|
|
1817
|
+
return self.program.useGraphics()
|
|
1818
|
+
elif token == 'mqtt':
|
|
1819
|
+
return self.program.useMQTT()
|
|
1820
|
+
elif token == 'psutil':
|
|
1821
|
+
return self.program.usePSUtil()
|
|
1783
1822
|
return False
|
|
1823
|
+
|
|
1824
|
+
# Unused
|
|
1825
|
+
def r_use(self, command):
|
|
1826
|
+
return self.nextPC()
|
|
1784
1827
|
|
|
1785
1828
|
# Declare a general-purpose variable
|
|
1786
1829
|
def k_variable(self, command):
|
|
1787
1830
|
self.compiler.addValueType()
|
|
1788
|
-
return self.compileVariable(command)
|
|
1831
|
+
return self.compileVariable(command, 'ECVariable')
|
|
1789
1832
|
|
|
1790
1833
|
def r_variable(self, command):
|
|
1791
1834
|
return self.nextPC()
|
|
@@ -1811,7 +1854,7 @@ class Core(Handler):
|
|
|
1811
1854
|
return True
|
|
1812
1855
|
|
|
1813
1856
|
def r_wait(self, command):
|
|
1814
|
-
value = self.
|
|
1857
|
+
value = self.textify(command['value']) * command['multiplier']
|
|
1815
1858
|
next = self.nextPC()
|
|
1816
1859
|
threading.Timer(value/1000.0, lambda: (self.run(next))).start()
|
|
1817
1860
|
return 0
|
|
@@ -1877,7 +1920,7 @@ class Core(Handler):
|
|
|
1877
1920
|
return False
|
|
1878
1921
|
|
|
1879
1922
|
def r_write(self, command):
|
|
1880
|
-
value = self.
|
|
1923
|
+
value = self.textify(command['value'])
|
|
1881
1924
|
fileRecord = self.getVariable(command['file'])
|
|
1882
1925
|
file = fileRecord['file']
|
|
1883
1926
|
if file.mode in ['w', 'w+', 'a', 'a+']:
|
|
@@ -1890,158 +1933,147 @@ class Core(Handler):
|
|
|
1890
1933
|
# Support functions
|
|
1891
1934
|
|
|
1892
1935
|
def incdec(self, command, mode):
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
if
|
|
1898
|
-
RuntimeError(self.program, f'{
|
|
1899
|
-
if mode == '+':
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
value['content'] -= 1
|
|
1903
|
-
self.putSymbolValue(symbolRecord, value)
|
|
1936
|
+
record = self.getVariable(command['target'])
|
|
1937
|
+
self.checkObjectType(record['object'], ECVariable)
|
|
1938
|
+
value = self.getSymbolValue(record)
|
|
1939
|
+
content = value.getContent()
|
|
1940
|
+
if not isinstance(content, int):
|
|
1941
|
+
RuntimeError(self.program, f'Variable {record["name"]} does not hold an integer')
|
|
1942
|
+
if mode == '+': value.setContent(content + 1)
|
|
1943
|
+
else: value.setContent(content - 1)
|
|
1944
|
+
self.putSymbolValue(record, value)
|
|
1904
1945
|
return self.nextPC()
|
|
1905
1946
|
|
|
1906
1947
|
#############################################################################
|
|
1907
1948
|
# Compile a value in this domain
|
|
1908
1949
|
def compileValue(self):
|
|
1909
|
-
value =
|
|
1910
|
-
value['domain'] = self.getName()
|
|
1950
|
+
value = ECValue()
|
|
1911
1951
|
token = self.getToken()
|
|
1912
1952
|
if self.isSymbol():
|
|
1913
|
-
value
|
|
1914
|
-
|
|
1915
|
-
keyword = symbolRecord['keyword']
|
|
1916
|
-
|
|
1917
|
-
if keyword == 'module':
|
|
1918
|
-
value['type'] = 'module'
|
|
1919
|
-
return value
|
|
1920
|
-
|
|
1921
|
-
if keyword in ['ssh', 'variable']:
|
|
1922
|
-
value['type'] = 'symbol'
|
|
1923
|
-
return value
|
|
1924
|
-
|
|
1925
|
-
return None
|
|
1953
|
+
value.setValue(type='symbol', content=token)
|
|
1954
|
+
return value
|
|
1926
1955
|
|
|
1927
|
-
value
|
|
1956
|
+
value.setType(token)
|
|
1928
1957
|
|
|
1929
1958
|
if token == 'arg':
|
|
1930
1959
|
self.nextToken()
|
|
1931
|
-
value
|
|
1960
|
+
value.index = self.getValue()
|
|
1932
1961
|
return value
|
|
1933
1962
|
|
|
1934
1963
|
if token in ['cos', 'sin', 'tan']:
|
|
1935
|
-
value
|
|
1964
|
+
value.angle = self.nextValue()
|
|
1936
1965
|
if self.nextToken() == 'radius':
|
|
1937
|
-
value
|
|
1966
|
+
value.radius = self.nextValue()
|
|
1938
1967
|
return value
|
|
1939
1968
|
return None
|
|
1940
1969
|
|
|
1941
1970
|
if token in ['now', 'today', 'newline', 'tab', 'empty']:
|
|
1942
1971
|
return value
|
|
1943
1972
|
|
|
1944
|
-
if token in ['stringify', 'prettify', 'json', 'lowercase', 'uppercase', 'hash', 'random',
|
|
1945
|
-
value
|
|
1973
|
+
if token in ['stringify', 'prettify', 'json', 'lowercase', 'uppercase', 'hash', 'random', float, 'integer', 'encode', 'decode']:
|
|
1974
|
+
value.setContent(self.nextValue())
|
|
1946
1975
|
return value
|
|
1947
1976
|
|
|
1948
1977
|
if (token in ['datime', 'datetime']):
|
|
1949
|
-
value
|
|
1950
|
-
value
|
|
1978
|
+
value.setType('datime')
|
|
1979
|
+
value.timestamp = self.nextValue()
|
|
1951
1980
|
if self.peek() == 'format':
|
|
1952
1981
|
self.nextToken()
|
|
1953
|
-
value
|
|
1982
|
+
value.format = self.nextValue()
|
|
1954
1983
|
else:
|
|
1955
|
-
value
|
|
1984
|
+
value.format = None
|
|
1956
1985
|
return value
|
|
1957
1986
|
|
|
1958
|
-
if token == '
|
|
1959
|
-
value
|
|
1987
|
+
if token == 'item':
|
|
1988
|
+
value.index = self.nextValue()
|
|
1960
1989
|
if self.nextToken() == 'of':
|
|
1961
1990
|
if self.nextIsSymbol():
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
self.warning(f'Core.compileValue: Token {symbolRecord["name"]} does not hold a value')
|
|
1991
|
+
record = self.getSymbolRecord()
|
|
1992
|
+
self.checkObjectType(record['object'], ECList)
|
|
1993
|
+
value.target = ECValue(type='symbol', content=record['name'])
|
|
1994
|
+
return value
|
|
1967
1995
|
return None
|
|
1968
1996
|
|
|
1969
|
-
if token == '
|
|
1970
|
-
value
|
|
1971
|
-
if self.nextToken()
|
|
1997
|
+
if token == 'entry':
|
|
1998
|
+
value.key = self.nextValue() # type: ignore
|
|
1999
|
+
if self.nextToken() in ('in', 'of'):
|
|
1972
2000
|
if self.nextIsSymbol():
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
2001
|
+
record = self.getSymbolRecord()
|
|
2002
|
+
object = record['object']
|
|
2003
|
+
self.checkObjectType(object, ECDictionary)
|
|
2004
|
+
value.target = object.name
|
|
2005
|
+
return value
|
|
1978
2006
|
return None
|
|
1979
2007
|
|
|
1980
2008
|
if token == 'arg':
|
|
1981
|
-
value
|
|
2009
|
+
value.setContent(self.nextValue())
|
|
1982
2010
|
if self.getToken() == 'of':
|
|
1983
2011
|
if self.nextIsSymbol():
|
|
1984
|
-
|
|
1985
|
-
if
|
|
1986
|
-
value
|
|
2012
|
+
record = self.getSymbolRecord()
|
|
2013
|
+
if record['keyword'] == 'variable':
|
|
2014
|
+
value.target = record['name'] # type: ignore
|
|
1987
2015
|
return value
|
|
1988
2016
|
return None
|
|
1989
2017
|
|
|
1990
2018
|
if token == 'trim':
|
|
1991
2019
|
self.nextToken()
|
|
1992
|
-
value
|
|
2020
|
+
value.setContent(self.getValue())
|
|
1993
2021
|
return value
|
|
1994
2022
|
|
|
1995
2023
|
if self.getToken() == 'the':
|
|
1996
2024
|
self.nextToken()
|
|
1997
2025
|
|
|
1998
2026
|
token = self.getToken()
|
|
1999
|
-
value
|
|
2027
|
+
value.setType(token)
|
|
2000
2028
|
|
|
2001
|
-
if token
|
|
2002
|
-
|
|
2029
|
+
if token in ['args', 'message', 'uuid', 'weekday']:
|
|
2030
|
+
return value
|
|
2003
2031
|
|
|
2004
|
-
if token
|
|
2005
|
-
if self.
|
|
2032
|
+
if token in ('items', 'elements'):
|
|
2033
|
+
if self.nextToken() in ('in', 'of'):
|
|
2006
2034
|
if self.nextIsSymbol():
|
|
2007
|
-
value
|
|
2035
|
+
value.name = self.getToken() # type: ignore
|
|
2008
2036
|
return value
|
|
2009
2037
|
return None
|
|
2010
2038
|
|
|
2011
2039
|
if token == 'keys':
|
|
2012
2040
|
if self.nextIs('of'):
|
|
2013
|
-
|
|
2014
|
-
|
|
2041
|
+
if self.nextIsSymbol():
|
|
2042
|
+
value.name = self.getToken() # type: ignore
|
|
2043
|
+
return value
|
|
2015
2044
|
return None
|
|
2016
2045
|
|
|
2017
2046
|
if token == 'count':
|
|
2018
2047
|
if self.nextIs('of'):
|
|
2019
2048
|
if self.nextIsSymbol():
|
|
2020
|
-
|
|
2021
|
-
|
|
2049
|
+
record = self.getSymbolRecord()
|
|
2050
|
+
object = record['object']
|
|
2051
|
+
if isinstance(object, ECList):
|
|
2052
|
+
value.setContent(record['name'])
|
|
2022
2053
|
return value
|
|
2023
2054
|
return None
|
|
2024
2055
|
|
|
2025
2056
|
if token == 'index':
|
|
2026
2057
|
if self.nextIs('of'):
|
|
2027
2058
|
if self.nextIsSymbol():
|
|
2028
|
-
value
|
|
2059
|
+
value.variable = self.getSymbolRecord()['name'] # type: ignore
|
|
2029
2060
|
if self.peek() == 'in':
|
|
2030
|
-
value
|
|
2031
|
-
value
|
|
2061
|
+
value.value = None # type: ignore
|
|
2062
|
+
value.setType('indexOf')
|
|
2063
|
+
self.nextToken()
|
|
2032
2064
|
if self.nextIsSymbol():
|
|
2033
|
-
value
|
|
2065
|
+
value.target = self.getSymbolRecord()['name'] # type: ignore
|
|
2034
2066
|
return value
|
|
2035
2067
|
else:
|
|
2036
|
-
value
|
|
2068
|
+
value.name = self.getToken() # type: ignore
|
|
2037
2069
|
return value
|
|
2038
2070
|
else:
|
|
2039
|
-
value
|
|
2071
|
+
value.value = self.getValue() # type: ignore
|
|
2040
2072
|
if self.nextIs('in'):
|
|
2041
|
-
value
|
|
2042
|
-
value
|
|
2073
|
+
value.variable = None # type: ignore
|
|
2074
|
+
value.setType('indexOf')
|
|
2043
2075
|
if self.nextIsSymbol():
|
|
2044
|
-
value
|
|
2076
|
+
value.target = self.getSymbolRecord()['name'] # type: ignore
|
|
2045
2077
|
return value
|
|
2046
2078
|
return None
|
|
2047
2079
|
|
|
@@ -2049,111 +2081,101 @@ class Core(Handler):
|
|
|
2049
2081
|
if self.nextIs('of'):
|
|
2050
2082
|
v = self.nextValue()
|
|
2051
2083
|
if v !=None:
|
|
2052
|
-
value
|
|
2053
|
-
value['content'] = v
|
|
2084
|
+
value.setValue(type='valueOf', content=v)
|
|
2054
2085
|
return value
|
|
2055
2086
|
return None
|
|
2056
2087
|
|
|
2057
2088
|
if token == 'length':
|
|
2058
|
-
value
|
|
2089
|
+
value.setType('lengthOf')
|
|
2059
2090
|
if self.nextIs('of'):
|
|
2060
|
-
value
|
|
2091
|
+
value.setContent(self.nextValue())
|
|
2061
2092
|
return value
|
|
2062
2093
|
return None
|
|
2063
2094
|
|
|
2064
2095
|
if token in ['left', 'right']:
|
|
2065
|
-
value
|
|
2096
|
+
value.count = self.nextValue() # type: ignore
|
|
2066
2097
|
if self.nextToken() == 'of':
|
|
2067
|
-
value
|
|
2098
|
+
value.setContent(self.nextValue())
|
|
2068
2099
|
return value
|
|
2069
2100
|
return None
|
|
2070
2101
|
|
|
2102
|
+
# from {n} of {value}
|
|
2103
|
+
# from {n} to {m} of {value}
|
|
2071
2104
|
if token == 'from':
|
|
2072
|
-
value
|
|
2105
|
+
value.start = self.nextValue() # type: ignore
|
|
2073
2106
|
if self.peek() == 'to':
|
|
2074
2107
|
self.nextToken()
|
|
2075
|
-
value
|
|
2108
|
+
value.to = self.nextValue() # type: ignore
|
|
2076
2109
|
else:
|
|
2077
|
-
value
|
|
2110
|
+
value.to = None # type: ignore
|
|
2078
2111
|
if self.nextToken() == 'of':
|
|
2079
|
-
value
|
|
2112
|
+
value.setContent(self.nextValue())
|
|
2080
2113
|
return value
|
|
2081
2114
|
|
|
2115
|
+
# position of [the] [last] {needle} in {haystack}
|
|
2082
2116
|
if token == 'position':
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
value['haystack'] = self.nextValue()
|
|
2092
|
-
return value
|
|
2093
|
-
|
|
2094
|
-
if token == 'message':
|
|
2117
|
+
self.skip('of')
|
|
2118
|
+
self.skip('the')
|
|
2119
|
+
if self.peek() == 'last':
|
|
2120
|
+
value.last = True # type: ignore
|
|
2121
|
+
self.nextToken()
|
|
2122
|
+
value.needle = self.nextValue() # type: ignore
|
|
2123
|
+
self.skip('in')
|
|
2124
|
+
value.haystack = self.nextValue() # type: ignore
|
|
2095
2125
|
return value
|
|
2096
2126
|
|
|
2097
2127
|
if token == 'timestamp':
|
|
2098
|
-
value
|
|
2128
|
+
value.format = None # type: ignore
|
|
2099
2129
|
if self.peek() == 'of':
|
|
2100
2130
|
self.nextToken()
|
|
2101
|
-
value
|
|
2131
|
+
value.timestamp = self.nextValue() # type: ignore
|
|
2102
2132
|
if self.peek() == 'format':
|
|
2103
2133
|
self.nextToken()
|
|
2104
|
-
value
|
|
2134
|
+
value.format = self.nextValue() # type: ignore
|
|
2105
2135
|
return value
|
|
2106
2136
|
|
|
2107
2137
|
if token == 'files':
|
|
2108
2138
|
token = self.nextToken()
|
|
2109
2139
|
if token in ['in', 'of']:
|
|
2110
|
-
value
|
|
2140
|
+
value.target = self.nextValue() # type: ignore
|
|
2111
2141
|
return value
|
|
2112
2142
|
return None
|
|
2113
2143
|
|
|
2114
|
-
if token == 'weekday':
|
|
2115
|
-
value['type'] = 'weekday'
|
|
2116
|
-
return value
|
|
2117
|
-
|
|
2118
|
-
if token == 'mem' or token == 'memory':
|
|
2119
|
-
value['type'] = 'memory'
|
|
2120
|
-
return value
|
|
2121
|
-
|
|
2122
2144
|
if token == 'error':
|
|
2123
2145
|
token = self.peek()
|
|
2124
2146
|
if token == 'code':
|
|
2125
2147
|
self.nextToken()
|
|
2126
|
-
value
|
|
2148
|
+
value.item = 'errorCode' # type: ignore
|
|
2127
2149
|
return value
|
|
2128
2150
|
elif token == 'reason':
|
|
2129
2151
|
self.nextToken()
|
|
2130
|
-
value
|
|
2152
|
+
value.item = 'errorReason' # type: ignore
|
|
2131
2153
|
return value
|
|
2132
2154
|
elif token in ['in', 'of']:
|
|
2133
2155
|
self.nextToken()
|
|
2134
2156
|
if self.nextIsSymbol():
|
|
2135
2157
|
record = self.getSymbolRecord()
|
|
2136
|
-
if record['
|
|
2137
|
-
value
|
|
2138
|
-
value
|
|
2158
|
+
if isinstance(record['object'], ECSSH):
|
|
2159
|
+
value.item = 'sshError' # type: ignore
|
|
2160
|
+
value.name = record['name'] # type: ignore
|
|
2139
2161
|
return value
|
|
2140
2162
|
return None
|
|
2141
2163
|
|
|
2142
2164
|
if token == 'type':
|
|
2143
2165
|
if self.nextIs('of'):
|
|
2144
|
-
value
|
|
2166
|
+
value.value = self.nextValue() # type: ignore
|
|
2145
2167
|
return value
|
|
2146
2168
|
return None
|
|
2147
2169
|
|
|
2148
2170
|
if token == 'modification':
|
|
2149
2171
|
if self.nextIs('time'):
|
|
2150
2172
|
if self.nextIs('of'):
|
|
2151
|
-
value
|
|
2173
|
+
value.fileName = self.nextValue() # type: ignore
|
|
2152
2174
|
return value
|
|
2153
2175
|
return None
|
|
2154
2176
|
|
|
2155
2177
|
if token == 'system':
|
|
2156
|
-
value
|
|
2178
|
+
value.setContent(self.nextValue())
|
|
2157
2179
|
return value
|
|
2158
2180
|
|
|
2159
2181
|
if token == 'ticker':
|
|
@@ -2166,12 +2188,9 @@ class Core(Handler):
|
|
|
2166
2188
|
def modifyValue(self, value):
|
|
2167
2189
|
if self.peek() == 'modulo':
|
|
2168
2190
|
self.nextToken()
|
|
2169
|
-
mv =
|
|
2170
|
-
mv
|
|
2171
|
-
mv
|
|
2172
|
-
mv['content'] = value
|
|
2173
|
-
mv['modval'] = self.nextValue()
|
|
2174
|
-
value = mv
|
|
2191
|
+
mv = ECValue(type='modulo', content=value)
|
|
2192
|
+
mv.modval = self.nextValue() # type: ignore
|
|
2193
|
+
return mv
|
|
2175
2194
|
|
|
2176
2195
|
return value
|
|
2177
2196
|
|
|
@@ -2179,472 +2198,368 @@ class Core(Handler):
|
|
|
2179
2198
|
# Value handlers
|
|
2180
2199
|
|
|
2181
2200
|
def v_args(self, v):
|
|
2182
|
-
|
|
2183
|
-
value['type'] = 'text'
|
|
2184
|
-
value['content'] = json.dumps(self.program.argv)
|
|
2185
|
-
return value
|
|
2201
|
+
return ECValue(type=str, content=json.dumps(self.program.argv))
|
|
2186
2202
|
|
|
2187
2203
|
def v_arg(self, v):
|
|
2188
|
-
|
|
2189
|
-
value['type'] = 'text'
|
|
2190
|
-
index = self.getRuntimeValue(v['index'])
|
|
2204
|
+
index = self.textify(v['index'])
|
|
2191
2205
|
if index >= len(self.program.argv):
|
|
2192
2206
|
RuntimeError(self.program, 'Index exceeds # of args')
|
|
2193
|
-
|
|
2194
|
-
return value
|
|
2207
|
+
return ECValue(type=str, content=self.program.argv[index])
|
|
2195
2208
|
|
|
2209
|
+
def v_bool(self, v):
|
|
2210
|
+
value = ECValue(type=bool, content=v.getContent())
|
|
2211
|
+
|
|
2196
2212
|
def v_boolean(self, v):
|
|
2197
|
-
|
|
2198
|
-
value['type'] = 'boolean'
|
|
2199
|
-
value['content'] = v['content']
|
|
2200
|
-
return value
|
|
2213
|
+
return self.v_bool(v)
|
|
2201
2214
|
|
|
2202
2215
|
def v_cos(self, v):
|
|
2203
|
-
angle = self.
|
|
2204
|
-
radius = self.
|
|
2205
|
-
|
|
2206
|
-
value['type'] = 'int'
|
|
2207
|
-
value['content'] = round(math.cos(angle * 0.01745329) * radius)
|
|
2208
|
-
return value
|
|
2216
|
+
angle = self.textify(v['angle'])
|
|
2217
|
+
radius = self.textify(v['radius'])
|
|
2218
|
+
return ECValue(type=int, content=round(math.cos(angle * 0.01745329) * radius))
|
|
2209
2219
|
|
|
2210
2220
|
def v_count(self, v):
|
|
2211
|
-
variable = self.getVariable(v
|
|
2212
|
-
|
|
2213
|
-
value = {}
|
|
2214
|
-
value['type'] = 'int'
|
|
2215
|
-
value['content'] = len(content)
|
|
2216
|
-
return value
|
|
2221
|
+
variable = self.getObject(self.getVariable(v.getContent()))
|
|
2222
|
+
return ECValue(type=int, content=variable.getItemCount())
|
|
2217
2223
|
|
|
2218
2224
|
def v_datime(self, v):
|
|
2219
|
-
ts = self.
|
|
2220
|
-
fmt = v
|
|
2225
|
+
ts = self.textify(v.timestamp)
|
|
2226
|
+
fmt = v.format
|
|
2221
2227
|
if fmt == None:
|
|
2222
2228
|
fmt = '%b %d %Y %H:%M:%S'
|
|
2223
2229
|
else:
|
|
2224
|
-
fmt = self.
|
|
2225
|
-
|
|
2226
|
-
value['type'] = 'text'
|
|
2227
|
-
value['content'] = datetime.fromtimestamp(ts/1000).strftime(fmt)
|
|
2228
|
-
return value
|
|
2230
|
+
fmt = self.textify(fmt)
|
|
2231
|
+
return ECValue(type=str, content=datetime.fromtimestamp(ts/1000).strftime(fmt))
|
|
2229
2232
|
|
|
2230
2233
|
def v_decode(self, v):
|
|
2231
|
-
content = self.
|
|
2232
|
-
value =
|
|
2233
|
-
value['type'] = 'text'
|
|
2234
|
+
content = self.textify(v.getContent())
|
|
2235
|
+
value = ECValue(type=str)
|
|
2234
2236
|
if self.encoding == 'utf-8':
|
|
2235
|
-
value
|
|
2237
|
+
value.setContent(content.decode('utf-8'))
|
|
2236
2238
|
elif self.encoding == 'base64':
|
|
2237
2239
|
base64_bytes = content.encode('ascii')
|
|
2238
2240
|
message_bytes = base64.b64decode(base64_bytes)
|
|
2239
|
-
value
|
|
2241
|
+
value.setContent(message_bytes.decode('ascii'))
|
|
2240
2242
|
elif self.encoding == 'hex':
|
|
2241
2243
|
hex_bytes = content.encode('utf-8')
|
|
2242
2244
|
message_bytes = binascii.unhexlify(hex_bytes)
|
|
2243
|
-
value
|
|
2245
|
+
value.setContent(message_bytes.decode('utf-8'))
|
|
2244
2246
|
else:
|
|
2245
2247
|
value = v
|
|
2246
2248
|
return value
|
|
2247
2249
|
|
|
2248
|
-
def v_element(self, v):
|
|
2249
|
-
index = self.getRuntimeValue(v['index'])
|
|
2250
|
-
target = self.getVariable(v['target'])
|
|
2251
|
-
val = self.getSymbolValue(target)
|
|
2252
|
-
content = val['content']
|
|
2253
|
-
value = {}
|
|
2254
|
-
value['type'] = 'int' if isinstance(content, int) else 'text'
|
|
2255
|
-
if type(content) == list:
|
|
2256
|
-
try:
|
|
2257
|
-
value['content'] = content[index]
|
|
2258
|
-
return value
|
|
2259
|
-
except:
|
|
2260
|
-
RuntimeError(self.program, 'Index out of range')
|
|
2261
|
-
# lino = self.program.code[self.program.pc]['lino']
|
|
2262
|
-
RuntimeError(self.program, 'Item is not a list')
|
|
2263
|
-
|
|
2264
2250
|
def v_elements(self, v):
|
|
2265
|
-
var = self.getVariable(v
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
return value
|
|
2251
|
+
var = self.getVariable(v.name)
|
|
2252
|
+
object = var['object']
|
|
2253
|
+
self.checkObjectType(object, ECVariable)
|
|
2254
|
+
return ECValue(type=int, content=object.getElements())
|
|
2270
2255
|
|
|
2271
2256
|
def v_empty(self, v):
|
|
2272
|
-
|
|
2273
|
-
value['type'] = 'text'
|
|
2274
|
-
value['content'] = ''
|
|
2275
|
-
return value
|
|
2257
|
+
return ECValue(type=str, content='' )
|
|
2276
2258
|
|
|
2277
2259
|
def v_encode(self, v):
|
|
2278
|
-
content = self.
|
|
2279
|
-
value =
|
|
2280
|
-
value['type'] = 'text'
|
|
2260
|
+
content = self.textify(v.getContent())
|
|
2261
|
+
value = ECValue(type=str)
|
|
2281
2262
|
if self.encoding == 'utf-8':
|
|
2282
|
-
value
|
|
2263
|
+
value.setContent(content.encode('utf-8'))
|
|
2283
2264
|
elif self.encoding == 'base64':
|
|
2284
2265
|
data_bytes = content.encode('ascii')
|
|
2285
2266
|
base64_bytes = base64.b64encode(data_bytes)
|
|
2286
|
-
value
|
|
2267
|
+
value.setContent(base64_bytes.decode('ascii'))
|
|
2287
2268
|
elif self.encoding == 'hex':
|
|
2288
2269
|
data_bytes = content.encode('utf-8')
|
|
2289
2270
|
hex_bytes = binascii.hexlify(data_bytes)
|
|
2290
|
-
value
|
|
2271
|
+
value.setContent(hex_bytes.decode('utf-8'))
|
|
2291
2272
|
else:
|
|
2292
2273
|
value = v
|
|
2293
2274
|
return value
|
|
2294
2275
|
|
|
2276
|
+
def v_entry(self, v):
|
|
2277
|
+
record = self.getVariable(v.target)
|
|
2278
|
+
dictionary = self.getObject(record)
|
|
2279
|
+
return dictionary.getEntry(self.textify(v.key))
|
|
2280
|
+
|
|
2295
2281
|
def v_error(self, v):
|
|
2296
2282
|
global errorCode, errorReason
|
|
2297
|
-
value =
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
value
|
|
2301
|
-
elif
|
|
2302
|
-
value
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
value['type'] = 'text'
|
|
2307
|
-
value['content'] = record['error'] if 'error' in record else ''
|
|
2283
|
+
value = ECValue()
|
|
2284
|
+
item = v.item
|
|
2285
|
+
if item == 'errorCode':
|
|
2286
|
+
value.setValue(type=int, content=errorCode)
|
|
2287
|
+
elif item == 'errorReason':
|
|
2288
|
+
value.setValue(type=str, content=errorReason)
|
|
2289
|
+
elif item == 'sshError':
|
|
2290
|
+
record = self.getVariable(v.name)
|
|
2291
|
+
value.setValue(type=str, content=record['error'] if 'error' in record else '')
|
|
2308
2292
|
return value
|
|
2309
2293
|
|
|
2310
2294
|
def v_files(self, v):
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
value['type'] = 'text'
|
|
2314
|
-
value['content'] = os.listdir(v)
|
|
2315
|
-
return value
|
|
2295
|
+
path = self.textify(v.target)
|
|
2296
|
+
return ECValue(type=str, content=json.dumps(os.listdir(path)))
|
|
2316
2297
|
|
|
2317
2298
|
def v_float(self, v):
|
|
2318
|
-
val = self.
|
|
2319
|
-
value =
|
|
2320
|
-
value['type'] = 'float'
|
|
2299
|
+
val = self.textify(v.getContent())
|
|
2300
|
+
value = ECValue(type=float)
|
|
2321
2301
|
try:
|
|
2322
|
-
value
|
|
2302
|
+
value.setContent(float(val))
|
|
2323
2303
|
except:
|
|
2324
2304
|
RuntimeWarning(self.program, f'Value cannot be parsed as floating-point')
|
|
2325
|
-
value
|
|
2305
|
+
value.setContent(0.0)
|
|
2326
2306
|
return value
|
|
2327
2307
|
|
|
2328
2308
|
def v_from(self, v):
|
|
2329
|
-
content = self.
|
|
2330
|
-
start = self.
|
|
2331
|
-
to = v
|
|
2332
|
-
if not
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
if to == None:
|
|
2337
|
-
value['content'] = content[start:]
|
|
2338
|
-
else:
|
|
2339
|
-
value['content'] = content[start:to]
|
|
2340
|
-
return value
|
|
2309
|
+
content = self.textify(v.getContent())
|
|
2310
|
+
start = self.textify(v.start)
|
|
2311
|
+
to = self.textify(v.to)
|
|
2312
|
+
if start is not None and type(start) != int:
|
|
2313
|
+
RuntimeError(self.program, 'Invalid "from" value')
|
|
2314
|
+
if to is not None and type(to) != int:
|
|
2315
|
+
RuntimeError(self.program, 'Invalid "to" value')
|
|
2316
|
+
return ECValue(type=str, content=content[start:] if to == None else content[start:to])
|
|
2341
2317
|
|
|
2342
2318
|
def v_hash(self, v):
|
|
2343
|
-
hashval = self.
|
|
2344
|
-
|
|
2345
|
-
value['type'] = 'text'
|
|
2346
|
-
value['content'] = hashlib.sha256(hashval.encode('utf-8')).hexdigest()
|
|
2347
|
-
return value
|
|
2319
|
+
hashval = self.textify(v.getContent())
|
|
2320
|
+
return ECValue(type=str, content=hashlib.sha256(hashval.encode('utf-8')).hexdigest())
|
|
2348
2321
|
|
|
2349
2322
|
def v_index(self, v):
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
return value
|
|
2323
|
+
record = self.getVariable(v.name)
|
|
2324
|
+
object = self.getObject(record)
|
|
2325
|
+
return ECValue(type=int, content=object.getIndex())
|
|
2354
2326
|
|
|
2355
2327
|
def v_indexOf(self, v):
|
|
2356
|
-
value = v
|
|
2328
|
+
value = v.value
|
|
2357
2329
|
if value == None:
|
|
2358
|
-
|
|
2330
|
+
var = self.getObject(self.getVariable(v.variable))
|
|
2331
|
+
value = var.getContent()
|
|
2359
2332
|
else:
|
|
2360
|
-
value = self.
|
|
2361
|
-
target = self.getVariable(v
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2333
|
+
value = self.textify(value)
|
|
2334
|
+
target = self.getObject(self.getVariable(v.target))
|
|
2335
|
+
if hasattr(target, 'getIndexOf'):
|
|
2336
|
+
index = target.getIndexOf(value)
|
|
2337
|
+
else:
|
|
2338
|
+
data = target.getContent()
|
|
2339
|
+
try: index = data.index(value)
|
|
2340
|
+
except: index = -1
|
|
2341
|
+
return ECValue(type=int, content=index)
|
|
2342
|
+
|
|
2343
|
+
def v_int(self, v):
|
|
2344
|
+
content = self.textify(v.getContent())
|
|
2345
|
+
if content in ('', None):
|
|
2346
|
+
return ECValue(type=int, content=0)
|
|
2347
|
+
return ECValue(type=int, content=int(content))
|
|
2372
2348
|
|
|
2373
2349
|
def v_integer(self, v):
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2350
|
+
return self.v_int(v)
|
|
2351
|
+
|
|
2352
|
+
def v_item(self, v):
|
|
2353
|
+
index = self.textify(v.index)
|
|
2354
|
+
targetName = v.target
|
|
2355
|
+
target = self.getVariable(targetName.getContent())
|
|
2356
|
+
variable = self.getObject(target)
|
|
2357
|
+
self.checkObjectType(variable, ECList)
|
|
2358
|
+
if index >= variable.getItemCount():
|
|
2359
|
+
RuntimeError(self.program, f'Index out of range in {targetName}')
|
|
2360
|
+
targetValue = variable.getItem(index)
|
|
2361
|
+
return targetValue
|
|
2362
|
+
|
|
2363
|
+
def v_items(self, v):
|
|
2364
|
+
record = self.getVariable(v.name)
|
|
2365
|
+
object = self.getObject(record)
|
|
2366
|
+
self.checkObjectType(object, ECList)
|
|
2367
|
+
return object.getItemCount()
|
|
2379
2368
|
|
|
2380
2369
|
def v_json(self, v):
|
|
2381
|
-
item = self.
|
|
2382
|
-
value =
|
|
2383
|
-
value['type'] = 'object'
|
|
2370
|
+
item = self.textify(v.getContent())
|
|
2371
|
+
value = ECValue()
|
|
2384
2372
|
try:
|
|
2385
|
-
|
|
2373
|
+
v = json.loads(item)
|
|
2374
|
+
if type(v) == list: value.setType('list')
|
|
2375
|
+
elif type(v) == dict: value.setType('dict')
|
|
2376
|
+
else: value.setType(str)
|
|
2377
|
+
value.setContent(v)
|
|
2386
2378
|
except:
|
|
2387
2379
|
value = None
|
|
2388
2380
|
return value
|
|
2389
2381
|
|
|
2390
2382
|
def v_keys(self, v):
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
value['content'] = list(self.getRuntimeValue(v['name']).keys())
|
|
2394
|
-
return value
|
|
2383
|
+
dictionary = self.getObject(self.getVariable(v.name))
|
|
2384
|
+
return ECValue(type='list', content=list(dictionary.keys())) # type: ignore
|
|
2395
2385
|
|
|
2396
2386
|
def v_left(self, v):
|
|
2397
|
-
content = self.
|
|
2398
|
-
count = self.
|
|
2399
|
-
|
|
2400
|
-
value['type'] = 'text'
|
|
2401
|
-
value['content'] = content[0:count]
|
|
2402
|
-
return value
|
|
2387
|
+
content = self.textify(v.getContent())
|
|
2388
|
+
count = self.textify(v.count)
|
|
2389
|
+
return ECValue(type=str, content=content[0:count])
|
|
2403
2390
|
|
|
2404
2391
|
def v_lengthOf(self, v):
|
|
2405
|
-
content = self.
|
|
2392
|
+
content = self.textify(v.getContent())
|
|
2406
2393
|
if type(content) == str:
|
|
2407
|
-
|
|
2408
|
-
value['type'] = 'int'
|
|
2409
|
-
value['content'] = len(content)
|
|
2410
|
-
return value
|
|
2394
|
+
return ECValue(type=int, content=len(content))
|
|
2411
2395
|
RuntimeError(self.program, 'Value is not a string')
|
|
2412
2396
|
|
|
2413
2397
|
def v_lowercase(self, v):
|
|
2414
|
-
content = self.
|
|
2415
|
-
|
|
2416
|
-
value['type'] = 'text'
|
|
2417
|
-
value['content'] = content.lower()
|
|
2418
|
-
return value
|
|
2419
|
-
|
|
2420
|
-
def v_memory(self, v):
|
|
2421
|
-
process: Process = Process(os.getpid())
|
|
2422
|
-
megabytes: float = process.memory_info().rss / (1024 * 1024)
|
|
2423
|
-
value = {}
|
|
2424
|
-
value['type'] = 'float'
|
|
2425
|
-
value['content'] = megabytes
|
|
2426
|
-
return value
|
|
2398
|
+
content = self.textify(v.getValue())
|
|
2399
|
+
return ECValue(type=str, content=content.lower())
|
|
2427
2400
|
|
|
2428
2401
|
def v_message(self, v):
|
|
2429
|
-
|
|
2430
|
-
value['type'] = 'text'
|
|
2431
|
-
value['content'] = self.program.message
|
|
2432
|
-
return value
|
|
2402
|
+
return ECValue(type=str, content=self.program.message)
|
|
2433
2403
|
|
|
2434
2404
|
def v_modification(self, v):
|
|
2435
|
-
fileName = self.
|
|
2405
|
+
fileName = self.textify(v['fileName'])
|
|
2436
2406
|
ts = int(os.stat(fileName).st_mtime)
|
|
2437
|
-
|
|
2438
|
-
value['type'] = 'int'
|
|
2439
|
-
value['content'] = ts
|
|
2440
|
-
return value
|
|
2407
|
+
return ECValue(type=int, content=ts)
|
|
2441
2408
|
|
|
2442
2409
|
def v_modulo(self, v):
|
|
2443
|
-
val = self.
|
|
2444
|
-
modval = self.
|
|
2445
|
-
|
|
2446
|
-
value['type'] = 'int'
|
|
2447
|
-
value['content'] = val % modval
|
|
2448
|
-
return value
|
|
2410
|
+
val = self.textify(v.getContent())
|
|
2411
|
+
modval = self.textify(v.modval)
|
|
2412
|
+
return ECValue(type=int, content=val % modval)
|
|
2449
2413
|
|
|
2450
2414
|
def v_newline(self, v):
|
|
2451
|
-
|
|
2452
|
-
value['type'] = 'text'
|
|
2453
|
-
value['content'] = '\n'
|
|
2454
|
-
return value
|
|
2415
|
+
return ECValue(type=str, content='\n')
|
|
2455
2416
|
|
|
2456
2417
|
def v_now(self, v):
|
|
2457
|
-
|
|
2458
|
-
value['type'] = 'int'
|
|
2459
|
-
value['content'] = int(time.time())
|
|
2460
|
-
return value
|
|
2418
|
+
return ECValue(type=int, content=int(time.time()))
|
|
2461
2419
|
|
|
2462
2420
|
def v_position(self, v):
|
|
2463
|
-
needle = self.
|
|
2464
|
-
haystack = self.
|
|
2465
|
-
last = v
|
|
2466
|
-
|
|
2467
|
-
value['type'] = 'int'
|
|
2468
|
-
value['content'] = haystack.rfind(needle) if last else haystack.find(needle)
|
|
2469
|
-
return value
|
|
2421
|
+
needle = self.textify(v.needle)
|
|
2422
|
+
haystack = self.textify(v.haystack)
|
|
2423
|
+
last = v.last
|
|
2424
|
+
return ECValue(type=int, content=haystack.rfind(needle) if last else haystack.find(needle))
|
|
2470
2425
|
|
|
2471
2426
|
def v_prettify(self, v):
|
|
2472
|
-
item = self.
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
value['content'] = json.dumps(item, indent=4)
|
|
2476
|
-
return value
|
|
2427
|
+
item = self.textify(v.getContent())
|
|
2428
|
+
if isinstance(item, str): item = json.loads(item)
|
|
2429
|
+
return ECValue(type=str, content=json.dumps(item, indent=4))
|
|
2477
2430
|
|
|
2478
2431
|
def v_property(self, v):
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
targetValue = self.getRuntimeValue(v['value'])
|
|
2486
|
-
try:
|
|
2487
|
-
val = targetValue[propertyValue]
|
|
2488
|
-
except:
|
|
2489
|
-
RuntimeError(self.program, f'This value does not have the property \'{propertyValue}\'')
|
|
2490
|
-
return None
|
|
2491
|
-
value = {}
|
|
2492
|
-
value['content'] = val
|
|
2493
|
-
if isinstance(v, numbers.Number):
|
|
2494
|
-
value['type'] = 'int'
|
|
2495
|
-
else:
|
|
2496
|
-
value['type'] = 'text'
|
|
2497
|
-
return value
|
|
2432
|
+
propertyName = v.name
|
|
2433
|
+
propertyValue = self.textify(propertyName)
|
|
2434
|
+
targetName = v.target
|
|
2435
|
+
target = self.getVariable(targetName.getContent())
|
|
2436
|
+
variable = self.getObject(target)
|
|
2437
|
+
return variable.getProperty(propertyValue)
|
|
2498
2438
|
|
|
2499
2439
|
def v_random(self, v):
|
|
2500
|
-
limit = self.
|
|
2501
|
-
|
|
2502
|
-
value['type'] = 'int'
|
|
2503
|
-
value['content'] = random.randrange(0, limit)
|
|
2504
|
-
return value
|
|
2440
|
+
limit = self.textify(v.getValue())
|
|
2441
|
+
return ECValue(type=int, content=random.randrange(0, limit))
|
|
2505
2442
|
|
|
2506
2443
|
def v_right(self, v):
|
|
2507
|
-
content = self.
|
|
2508
|
-
count = self.
|
|
2509
|
-
|
|
2510
|
-
value['type'] = 'text'
|
|
2511
|
-
value['content'] = content[-count:]
|
|
2512
|
-
return value
|
|
2444
|
+
content = self.textify(v.getContent())
|
|
2445
|
+
count = self.textify(v.count)
|
|
2446
|
+
return ECValue(type=str, content=content[-count:])
|
|
2513
2447
|
|
|
2514
2448
|
def v_sin(self, v):
|
|
2515
|
-
angle = self.
|
|
2516
|
-
radius = self.
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2449
|
+
angle = self.textify(v.angle)
|
|
2450
|
+
radius = self.textify(v.radius)
|
|
2451
|
+
return ECValue(type=int, content=round(math.sin(angle * 0.01745329) * radius))
|
|
2452
|
+
|
|
2453
|
+
def v_str(self, v):
|
|
2454
|
+
content = self.textify(v.getContent())
|
|
2455
|
+
return ECValue(type=str, content=str(content))
|
|
2521
2456
|
|
|
2522
2457
|
def v_stringify(self, v):
|
|
2523
|
-
item = self.
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
value['content'] = json.dumps(item)
|
|
2527
|
-
return value
|
|
2458
|
+
item = self.textify(v.getContent())
|
|
2459
|
+
item = json.loads(item)
|
|
2460
|
+
return ECValue(type=str, content=json.dumps(item))
|
|
2528
2461
|
|
|
2529
2462
|
# This is used by the expression evaluator to get the value of a symbol
|
|
2530
|
-
def v_symbol(self,
|
|
2531
|
-
name =
|
|
2532
|
-
|
|
2533
|
-
keyword =
|
|
2534
|
-
if keyword == '
|
|
2535
|
-
return
|
|
2463
|
+
def v_symbol(self, v):
|
|
2464
|
+
name = v.name
|
|
2465
|
+
record = self.program.getSymbolRecord(name)
|
|
2466
|
+
keyword = record['keyword']
|
|
2467
|
+
if keyword == 'object':
|
|
2468
|
+
return record['object'].getValue()
|
|
2469
|
+
elif keyword == 'variable':
|
|
2470
|
+
return self.getSymbolValue(record)
|
|
2536
2471
|
elif keyword == 'ssh':
|
|
2537
|
-
|
|
2538
|
-
v['type'] = 'boolean'
|
|
2539
|
-
v['content'] = True if 'ssh' in symbolRecord and symbolRecord['ssh'] != None else False
|
|
2540
|
-
return v
|
|
2472
|
+
return ECValue(type=bool, content=True if 'ssh' in record and record['ssh'] != None else False)
|
|
2541
2473
|
else:
|
|
2542
2474
|
return None
|
|
2543
2475
|
|
|
2544
2476
|
def v_system(self, v):
|
|
2545
|
-
command = self.
|
|
2477
|
+
command = self.textify(v.getContent())
|
|
2546
2478
|
result = os.popen(command).read()
|
|
2547
|
-
|
|
2548
|
-
value['type'] = 'text'
|
|
2549
|
-
value['content'] = result
|
|
2550
|
-
return value
|
|
2479
|
+
return ECValue(type=str, content=result)
|
|
2551
2480
|
|
|
2552
2481
|
def v_tab(self, v):
|
|
2553
|
-
|
|
2554
|
-
value['type'] = 'text'
|
|
2555
|
-
value['content'] = '\t'
|
|
2556
|
-
return value
|
|
2482
|
+
return ECValue(type=str, content='\t')
|
|
2557
2483
|
|
|
2558
2484
|
def v_tan(self, v):
|
|
2559
|
-
angle = self.
|
|
2560
|
-
radius = self.
|
|
2561
|
-
|
|
2562
|
-
value['type'] = 'int'
|
|
2563
|
-
value['content'] = round(math.tan(angle * 0.01745329) * radius)
|
|
2564
|
-
return value
|
|
2485
|
+
angle = self.textify(v['angle'])
|
|
2486
|
+
radius = self.textify(v['radius'])
|
|
2487
|
+
return ECValue(type=int, content=round(math.tan(angle * 0.01745329) * radius))
|
|
2565
2488
|
|
|
2566
2489
|
def v_ticker(self, v):
|
|
2567
|
-
|
|
2568
|
-
value['type'] = 'int'
|
|
2569
|
-
value['content'] = self.program.ticker
|
|
2570
|
-
return value
|
|
2490
|
+
return ECValue(type=int, content=self.program.ticker)
|
|
2571
2491
|
|
|
2572
2492
|
def v_timestamp(self, v):
|
|
2573
|
-
value =
|
|
2574
|
-
|
|
2575
|
-
fmt = v['format']
|
|
2493
|
+
value = ECValue(type=int)
|
|
2494
|
+
fmt = v.format
|
|
2576
2495
|
if fmt == None:
|
|
2577
|
-
value
|
|
2496
|
+
value.setContent(int(time.time()))
|
|
2578
2497
|
else:
|
|
2579
|
-
fmt = self.
|
|
2580
|
-
dt = self.
|
|
2498
|
+
fmt = self.textify(fmt)
|
|
2499
|
+
dt = self.textify(v.timestamp)
|
|
2581
2500
|
spec = datetime.strptime(dt, fmt)
|
|
2582
2501
|
t = datetime.now().replace(hour=spec.hour, minute=spec.minute, second=spec.second, microsecond=0)
|
|
2583
|
-
value
|
|
2502
|
+
value.setContent(int(t.timestamp()))
|
|
2584
2503
|
return value
|
|
2585
2504
|
|
|
2586
2505
|
def v_today(self, v):
|
|
2587
|
-
|
|
2588
|
-
value['type'] = 'int'
|
|
2589
|
-
value['content'] = int(datetime.combine(datetime.now().date(),datetime.min.time()).timestamp())*1000
|
|
2590
|
-
return value
|
|
2506
|
+
return ECValue(type=int, content=int(datetime.combine(datetime.now().date(),datetime.min.time()).timestamp()) * 1000)
|
|
2591
2507
|
|
|
2592
2508
|
def v_trim(self, v):
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
value['content'] = v.strip()
|
|
2597
|
-
return value
|
|
2509
|
+
content = v.getContent()
|
|
2510
|
+
content = self.textify(content)
|
|
2511
|
+
return ECValue(type=str, content=content.strip())
|
|
2598
2512
|
|
|
2599
2513
|
def v_type(self, v):
|
|
2600
|
-
value =
|
|
2601
|
-
|
|
2602
|
-
val = self.getRuntimeValue(v['value'])
|
|
2514
|
+
value = ECValue(type=str)
|
|
2515
|
+
val = self.textify(v['value'])
|
|
2603
2516
|
if val is None:
|
|
2604
|
-
value
|
|
2517
|
+
value.setContent('none')
|
|
2605
2518
|
elif type(val) is str:
|
|
2606
|
-
value
|
|
2519
|
+
value.setContent(str)
|
|
2607
2520
|
elif type(val) is int:
|
|
2608
|
-
value
|
|
2521
|
+
value.setContent('numeric')
|
|
2609
2522
|
elif type(val) is bool:
|
|
2610
|
-
value
|
|
2523
|
+
value.setContent(bool)
|
|
2611
2524
|
elif type(val) is list:
|
|
2612
|
-
value
|
|
2525
|
+
value.setContent('list')
|
|
2613
2526
|
elif type(val) is dict:
|
|
2614
|
-
value
|
|
2527
|
+
value.setContent('dict')
|
|
2615
2528
|
return value
|
|
2616
2529
|
|
|
2617
2530
|
def v_uppercase(self, v):
|
|
2618
|
-
content = self.
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
return
|
|
2531
|
+
content = self.textify(v.getContent())
|
|
2532
|
+
return ECValue(type=str, content=content.upper())
|
|
2533
|
+
|
|
2534
|
+
def v_uuid(self, v):
|
|
2535
|
+
return ECValue(type=str, content=str(uuid.uuid4())[:8])
|
|
2623
2536
|
|
|
2624
2537
|
def v_valueOf(self, v):
|
|
2625
|
-
v = self.
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2538
|
+
v = self.textify(v.getContent())
|
|
2539
|
+
return ECValue(type=int, content=int(v) if v != '' else 0)
|
|
2540
|
+
|
|
2541
|
+
def v_variable(self, v):
|
|
2542
|
+
name = v.getContent()
|
|
2543
|
+
record = self.program.getSymbolRecord(name)
|
|
2544
|
+
variable = record['object']
|
|
2545
|
+
self.checkObjectType(variable, ECVariable)
|
|
2546
|
+
value = variable.getValue()
|
|
2629
2547
|
return value
|
|
2630
2548
|
|
|
2631
2549
|
def v_weekday(self, v):
|
|
2632
|
-
|
|
2633
|
-
value['type'] = 'int'
|
|
2634
|
-
value['content'] = datetime.today().weekday()
|
|
2635
|
-
return value
|
|
2550
|
+
return ECValue(type=int, content=datetime.today().weekday())
|
|
2636
2551
|
|
|
2637
2552
|
#############################################################################
|
|
2638
2553
|
# Compile a condition
|
|
2639
2554
|
def compileCondition(self):
|
|
2640
|
-
condition =
|
|
2641
|
-
condition.negate = False
|
|
2555
|
+
condition = ECValue()
|
|
2556
|
+
condition.negate = False # type: ignore
|
|
2642
2557
|
|
|
2643
2558
|
token = self.getToken()
|
|
2644
2559
|
|
|
2645
2560
|
if token == 'not':
|
|
2646
|
-
condition.type = 'not'
|
|
2647
|
-
condition.value = self.nextValue()
|
|
2561
|
+
condition.type = 'not' # type: ignore
|
|
2562
|
+
condition.value = self.nextValue() # type: ignore
|
|
2648
2563
|
return condition
|
|
2649
2564
|
|
|
2650
2565
|
elif token == 'error':
|
|
@@ -2653,21 +2568,21 @@ class Core(Handler):
|
|
|
2653
2568
|
if self.nextIsSymbol():
|
|
2654
2569
|
record = self.getSymbolRecord()
|
|
2655
2570
|
if record['keyword'] == 'ssh':
|
|
2656
|
-
condition.type = 'sshError'
|
|
2657
|
-
condition.target = record['name']
|
|
2571
|
+
condition.type = 'sshError' # type: ignore
|
|
2572
|
+
condition.target = record['name'] # type: ignore
|
|
2658
2573
|
return condition
|
|
2659
2574
|
return None
|
|
2660
2575
|
|
|
2661
2576
|
elif token == 'file':
|
|
2662
2577
|
path = self.nextValue()
|
|
2663
|
-
condition.path = path
|
|
2664
|
-
condition.type = 'exists'
|
|
2578
|
+
condition.path = path # type: ignore
|
|
2579
|
+
condition.type = 'exists' # type: ignore
|
|
2665
2580
|
self.skip('on')
|
|
2666
2581
|
if self.nextIsSymbol():
|
|
2667
2582
|
record = self.getSymbolRecord()
|
|
2668
2583
|
if record['keyword'] == 'ssh':
|
|
2669
|
-
condition.type = 'sshExists'
|
|
2670
|
-
condition.target = record['name']
|
|
2584
|
+
condition.type = 'sshExists' # type: ignore
|
|
2585
|
+
condition.target = record['name'] # type: ignore
|
|
2671
2586
|
token = self.nextToken()
|
|
2672
2587
|
else: token = self.getToken()
|
|
2673
2588
|
if token == 'exists':
|
|
@@ -2675,24 +2590,33 @@ class Core(Handler):
|
|
|
2675
2590
|
elif token == 'does':
|
|
2676
2591
|
if self.nextIs('not'):
|
|
2677
2592
|
if self.nextIs('exist'):
|
|
2678
|
-
condition.negate = not condition.negate
|
|
2593
|
+
condition.negate = not condition.negate # type: ignore
|
|
2679
2594
|
return condition
|
|
2680
2595
|
return None
|
|
2596
|
+
|
|
2597
|
+
elif token == 'debugging':
|
|
2598
|
+
condition.type = 'debugging' # type: ignore
|
|
2599
|
+
return condition
|
|
2681
2600
|
|
|
2682
2601
|
value = self.getValue()
|
|
2683
2602
|
if value == None:
|
|
2684
2603
|
return None
|
|
2685
2604
|
|
|
2686
|
-
condition.value1 = value
|
|
2605
|
+
condition.value1 = value # type: ignore
|
|
2687
2606
|
token = self.peek()
|
|
2688
|
-
condition.type = token
|
|
2607
|
+
condition.type = token # type: ignore
|
|
2689
2608
|
|
|
2690
2609
|
if token == 'has':
|
|
2691
2610
|
self.nextToken()
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2611
|
+
token = self.nextToken()
|
|
2612
|
+
if token in ('entry', 'property'):
|
|
2613
|
+
value = self.nextValue()
|
|
2614
|
+
if token == 'entry':
|
|
2615
|
+
condition.type = 'hasEntry' # type: ignore
|
|
2616
|
+
condition.entry = value # type: ignore
|
|
2617
|
+
elif token == 'property:':
|
|
2618
|
+
condition.type = 'hasProperty' # type: ignore
|
|
2619
|
+
condition.property = value # type: ignore
|
|
2696
2620
|
return condition
|
|
2697
2621
|
return None
|
|
2698
2622
|
|
|
@@ -2701,50 +2625,55 @@ class Core(Handler):
|
|
|
2701
2625
|
if self.nextIs('not'):
|
|
2702
2626
|
token = self.nextToken()
|
|
2703
2627
|
if token == 'have':
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2628
|
+
token = self.nextToken()
|
|
2629
|
+
if token in ('entry', 'property:'):
|
|
2630
|
+
value = self.nextValue()
|
|
2631
|
+
if token == 'entry':
|
|
2632
|
+
condition.type = 'hasEntry' # type: ignore
|
|
2633
|
+
condition.entry = value # type: ignore
|
|
2634
|
+
elif token == 'property':
|
|
2635
|
+
condition.type = 'hasProperty' # type: ignore
|
|
2636
|
+
condition.property = value # type: ignore
|
|
2637
|
+
condition.negate = not condition.negate # type: ignore
|
|
2709
2638
|
return condition
|
|
2710
2639
|
elif token == 'include':
|
|
2711
2640
|
value = self.nextValue()
|
|
2712
|
-
condition.type = 'includes'
|
|
2713
|
-
condition.value2 = value
|
|
2714
|
-
condition.negate = not condition.negate
|
|
2641
|
+
condition.type = 'includes' # type: ignore
|
|
2642
|
+
condition.value2 = value # type: ignore
|
|
2643
|
+
condition.negate = not condition.negate # type: ignore
|
|
2715
2644
|
return condition
|
|
2716
2645
|
return None
|
|
2717
2646
|
|
|
2718
2647
|
if token in ['starts', 'ends']:
|
|
2719
2648
|
self.nextToken()
|
|
2720
2649
|
if self.nextToken() == 'with':
|
|
2721
|
-
condition.value2 = self.nextValue()
|
|
2650
|
+
condition.value2 = self.nextValue() # type: ignore
|
|
2722
2651
|
return condition
|
|
2723
2652
|
|
|
2724
2653
|
if token == 'includes':
|
|
2725
|
-
condition.value2 = self.nextValue()
|
|
2654
|
+
condition.value2 = self.nextValue() # type: ignore
|
|
2726
2655
|
return condition
|
|
2727
2656
|
|
|
2728
2657
|
if token == 'is':
|
|
2729
2658
|
token = self.nextToken()
|
|
2730
2659
|
if self.peek() == 'not':
|
|
2731
2660
|
self.nextToken()
|
|
2732
|
-
condition.negate = True
|
|
2661
|
+
condition.negate = True # type: ignore
|
|
2733
2662
|
token = self.nextToken()
|
|
2734
|
-
condition.type = token
|
|
2735
|
-
if token in ['numeric', 'string', 'boolean', 'none', 'list', 'object', 'even', 'odd', 'empty']:
|
|
2663
|
+
condition.type = token # type: ignore
|
|
2664
|
+
if token in ['numeric', 'string', 'bool', 'boolean', 'none', 'list', 'object', 'even', 'odd', 'empty']:
|
|
2736
2665
|
return condition
|
|
2737
2666
|
if token in ['greater', 'less']:
|
|
2738
2667
|
if self.nextToken() == 'than':
|
|
2739
|
-
condition.value2 = self.nextValue()
|
|
2668
|
+
condition.value2 = self.nextValue() # type: ignore
|
|
2740
2669
|
return condition
|
|
2741
|
-
condition.type = 'is'
|
|
2742
|
-
condition.value2 = self.getValue()
|
|
2670
|
+
condition.type = 'is' # type: ignore
|
|
2671
|
+
condition.value2 = self.getValue() # type: ignore
|
|
2743
2672
|
return condition
|
|
2744
2673
|
|
|
2745
|
-
if condition.value1:
|
|
2674
|
+
if condition.value1: # type: ignore
|
|
2746
2675
|
# It's a boolean if
|
|
2747
|
-
condition.type =
|
|
2676
|
+
condition.type = bool # type: ignore
|
|
2748
2677
|
return condition
|
|
2749
2678
|
|
|
2750
2679
|
self.warning(f'Core.compileCondition: I can\'t get a conditional:')
|
|
@@ -2760,8 +2689,8 @@ class Core(Handler):
|
|
|
2760
2689
|
#############################################################################
|
|
2761
2690
|
# Condition handlers
|
|
2762
2691
|
|
|
2763
|
-
def
|
|
2764
|
-
value = self.
|
|
2692
|
+
def c_bool(self, condition):
|
|
2693
|
+
value = self.textify(condition.value1)
|
|
2765
2694
|
if type(value) == bool:
|
|
2766
2695
|
return not value if condition.negate else value
|
|
2767
2696
|
elif type(value) == int:
|
|
@@ -2774,77 +2703,102 @@ class Core(Handler):
|
|
|
2774
2703
|
else:
|
|
2775
2704
|
return True if condition.negate else False
|
|
2776
2705
|
return False
|
|
2706
|
+
|
|
2707
|
+
def c_boolean(self, condition):
|
|
2708
|
+
return self.c_bool(condition)
|
|
2709
|
+
|
|
2710
|
+
def c_debugging(self, condition):
|
|
2711
|
+
return self.program.debugging
|
|
2777
2712
|
|
|
2778
2713
|
def c_empty(self, condition):
|
|
2779
|
-
|
|
2714
|
+
if condition.value1.getType() == 'symbol':
|
|
2715
|
+
record = self.getVariable(condition.value1.content)
|
|
2716
|
+
variable = self.getObject(record)
|
|
2717
|
+
if isinstance(variable, (ECList, ECDictionary)):
|
|
2718
|
+
comparison = variable.isEmpty()
|
|
2719
|
+
return not comparison if condition.negate else comparison
|
|
2720
|
+
value = self.textify(condition.value1)
|
|
2780
2721
|
if value == None:
|
|
2781
2722
|
comparison = True
|
|
2782
|
-
|
|
2723
|
+
elif isinstance(value, str):
|
|
2783
2724
|
comparison = len(value) == 0
|
|
2725
|
+
else:
|
|
2726
|
+
domainName = condition.value1.domain
|
|
2727
|
+
domain = self.program.domainIndex[domainName] # type: ignore
|
|
2728
|
+
handler = domain.valueHandler('empty') # type: ignore
|
|
2729
|
+
if handler: comparison = self.textify(handler(condition.value1))
|
|
2784
2730
|
return not comparison if condition.negate else comparison
|
|
2785
2731
|
|
|
2786
2732
|
def c_ends(self, condition):
|
|
2787
|
-
value1 = self.
|
|
2788
|
-
value2 = self.
|
|
2733
|
+
value1 = self.textify(condition.value1)
|
|
2734
|
+
value2 = self.textify(condition.value2)
|
|
2789
2735
|
return value1.endswith(value2)
|
|
2790
2736
|
|
|
2791
2737
|
def c_even(self, condition):
|
|
2792
|
-
return self.
|
|
2738
|
+
return self.textify(condition.value1) % 2 == 0
|
|
2793
2739
|
|
|
2794
2740
|
def c_exists(self, condition):
|
|
2795
|
-
path = self.
|
|
2741
|
+
path = self.textify(condition.path)
|
|
2796
2742
|
comparison = os.path.exists(path)
|
|
2797
2743
|
return not comparison if condition.negate else comparison
|
|
2798
2744
|
|
|
2799
2745
|
def c_greater(self, condition):
|
|
2800
2746
|
comparison = self.program.compare(condition.value1, condition.value2)
|
|
2747
|
+
if comparison == None:
|
|
2748
|
+
raise RuntimeError(self.program, f'Cannot compare {self.textify(condition.value1)} and {self.textify(condition.value2)}')
|
|
2801
2749
|
return comparison <= 0 if condition.negate else comparison > 0
|
|
2802
2750
|
|
|
2751
|
+
def c_hasEntry(self, condition):
|
|
2752
|
+
dictionary = self.getObject(self.getVariable(condition.value1.content))
|
|
2753
|
+
entry = self.textify(condition.entry)
|
|
2754
|
+
hasEntry = dictionary.hasEntry(entry) # type: ignore
|
|
2755
|
+
return not hasEntry if condition.negate else hasEntry
|
|
2756
|
+
|
|
2803
2757
|
def c_hasProperty(self, condition):
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
hasProp = True
|
|
2809
|
-
except:
|
|
2810
|
-
hasProp = False
|
|
2758
|
+
record = self.getVariable(condition.value1)
|
|
2759
|
+
variable = self.getObject(record)
|
|
2760
|
+
prop = self.textify(condition.property)
|
|
2761
|
+
hasProp = variable.hasProperty(prop)
|
|
2811
2762
|
return not hasProp if condition.negate else hasProp
|
|
2812
2763
|
|
|
2813
2764
|
def c_includes(self, condition):
|
|
2814
|
-
value1 = self.
|
|
2815
|
-
value2 = self.
|
|
2765
|
+
value1 = self.textify(condition.value1)
|
|
2766
|
+
value2 = self.textify(condition.value2)
|
|
2816
2767
|
includes = value2 in value1
|
|
2817
2768
|
return not includes if condition.negate else includes
|
|
2818
2769
|
|
|
2819
2770
|
def c_is(self, condition):
|
|
2820
2771
|
comparison = self.program.compare(condition.value1, condition.value2)
|
|
2772
|
+
if comparison == None: comparison = 1
|
|
2821
2773
|
return comparison != 0 if condition.negate else comparison == 0
|
|
2822
2774
|
|
|
2823
2775
|
def c_less(self, condition):
|
|
2824
2776
|
comparison = self.program.compare(condition.value1, condition.value2)
|
|
2777
|
+
if comparison == None:
|
|
2778
|
+
raise RuntimeError(self.program, f'Cannot compare {self.textify(condition.value1)} and {self.textify(condition.value2)}')
|
|
2825
2779
|
return comparison >= 0 if condition.negate else comparison < 0
|
|
2826
2780
|
|
|
2827
2781
|
def c_list(self, condition):
|
|
2828
|
-
comparison = type(self.
|
|
2782
|
+
comparison = type(self.textify(condition.value1)) is list
|
|
2829
2783
|
return not comparison if condition.negate else comparison
|
|
2830
2784
|
|
|
2831
2785
|
def c_numeric(self, condition):
|
|
2832
|
-
comparison = type(self.
|
|
2786
|
+
comparison = type(self.textify(condition.value1)) is int
|
|
2833
2787
|
return not comparison if condition.negate else comparison
|
|
2834
2788
|
|
|
2835
2789
|
def c_none(self, condition):
|
|
2836
|
-
comparison = self.
|
|
2790
|
+
comparison = self.textify(condition.value1) is None
|
|
2837
2791
|
return not comparison if condition.negate else comparison
|
|
2838
2792
|
|
|
2839
2793
|
def c_not(self, condition):
|
|
2840
|
-
return not self.
|
|
2794
|
+
return not self.textify(condition.value)
|
|
2841
2795
|
|
|
2842
2796
|
def c_object(self, condition):
|
|
2843
|
-
comparison = type(self.
|
|
2797
|
+
comparison = type(self.textify(condition.value1)) is dict
|
|
2844
2798
|
return not comparison if condition.negate else comparison
|
|
2845
2799
|
|
|
2846
2800
|
def c_odd(self, condition):
|
|
2847
|
-
return self.
|
|
2801
|
+
return self.textify(condition.value1) % 2 == 1
|
|
2848
2802
|
|
|
2849
2803
|
def c_sshError(self, condition):
|
|
2850
2804
|
target = self.getVariable(condition.target)
|
|
@@ -2854,7 +2808,7 @@ class Core(Handler):
|
|
|
2854
2808
|
return not test if condition.negate else test
|
|
2855
2809
|
|
|
2856
2810
|
def c_sshExists(self, condition):
|
|
2857
|
-
path = self.
|
|
2811
|
+
path = self.textify(condition.path)
|
|
2858
2812
|
ssh = self.getVariable(condition.target)
|
|
2859
2813
|
sftp = ssh['sftp']
|
|
2860
2814
|
try:
|
|
@@ -2865,10 +2819,10 @@ class Core(Handler):
|
|
|
2865
2819
|
return not comparison if condition.negate else comparison
|
|
2866
2820
|
|
|
2867
2821
|
def c_starts(self, condition):
|
|
2868
|
-
value1 = self.
|
|
2869
|
-
value2 = self.
|
|
2822
|
+
value1 = self.textify(condition.value1)
|
|
2823
|
+
value2 = self.textify(condition.value2)
|
|
2870
2824
|
return value1.startswith(value2)
|
|
2871
2825
|
|
|
2872
2826
|
def c_string(self, condition):
|
|
2873
|
-
comparison = type(self.
|
|
2827
|
+
comparison = type(self.textify(condition.value1)) is str
|
|
2874
2828
|
return not comparison if condition.negate else comparison
|