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