easycoder 241211.2__py2.py3-none-any.whl → 250116.1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of easycoder might be problematic. Click here for more details.
- easycoder/README.md +6 -0
- easycoder/__init__.py +1 -1
- easycoder/ec_classes.py +8 -2
- easycoder/ec_compiler.py +10 -6
- easycoder/ec_core.py +493 -208
- easycoder/ec_graphics.py +326 -0
- easycoder/ec_gutils.py +52 -0
- easycoder/ec_handler.py +1 -0
- easycoder/ec_program.py +156 -79
- easycoder/ec_value.py +21 -14
- easycoder-250116.1.dist-info/METADATA +102 -0
- easycoder-250116.1.dist-info/RECORD +17 -0
- {easycoder-241211.2.dist-info → easycoder-250116.1.dist-info}/WHEEL +1 -1
- easycoder-241211.2.dist-info/METADATA +0 -71
- easycoder-241211.2.dist-info/RECORD +0 -14
- {easycoder-241211.2.dist-info → easycoder-250116.1.dist-info}/LICENSE +0 -0
- {easycoder-241211.2.dist-info → easycoder-250116.1.dist-info}/entry_points.txt +0 -0
easycoder/ec_graphics.py
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
from .ec_classes import FatalError, RuntimeError, Object
|
|
2
|
+
from .ec_handler import Handler
|
|
3
|
+
from .ec_gutils import GUtils
|
|
4
|
+
import PySimpleGUI as psg
|
|
5
|
+
import json
|
|
6
|
+
|
|
7
|
+
class Graphics(Handler):
|
|
8
|
+
|
|
9
|
+
def __init__(self, compiler):
|
|
10
|
+
Handler.__init__(self, compiler)
|
|
11
|
+
self.utils = GUtils()
|
|
12
|
+
|
|
13
|
+
def getName(self):
|
|
14
|
+
return 'graphics'
|
|
15
|
+
|
|
16
|
+
#############################################################################
|
|
17
|
+
# Keyword handlers
|
|
18
|
+
|
|
19
|
+
def k_add(self, command):
|
|
20
|
+
elements = []
|
|
21
|
+
while True:
|
|
22
|
+
if self.nextIsSymbol():
|
|
23
|
+
symbolRecord = self.getSymbolRecord()
|
|
24
|
+
name = symbolRecord['name']
|
|
25
|
+
if 'iselement' in symbolRecord:
|
|
26
|
+
elements.append(name)
|
|
27
|
+
if self.peek() != 'and': break
|
|
28
|
+
else: FatalError(self.program.compiler, f'"{name}" is not a graphic element')
|
|
29
|
+
else: FatalError(self.program.compiler, f'Element expected; got "{self.getToken()}"')
|
|
30
|
+
self.nextToken()
|
|
31
|
+
command['elements'] = json.dumps(elements)
|
|
32
|
+
if self.nextIs('to'):
|
|
33
|
+
if self.nextIsSymbol():
|
|
34
|
+
symbolRecord = self.getSymbolRecord()
|
|
35
|
+
if symbolRecord['keyword'] == 'layout':
|
|
36
|
+
command['target'] = symbolRecord['name']
|
|
37
|
+
self.addCommand(command)
|
|
38
|
+
return True
|
|
39
|
+
return False
|
|
40
|
+
|
|
41
|
+
def r_add(self, command):
|
|
42
|
+
target = self.getVariable(command['target'])
|
|
43
|
+
elements = json.loads(command['elements'])
|
|
44
|
+
if not 'layout' in target:
|
|
45
|
+
target['layout'] = []
|
|
46
|
+
for element in elements:
|
|
47
|
+
v = self.getVariable(element)
|
|
48
|
+
target['layout'].append(v['layout'])
|
|
49
|
+
return self.nextPC()
|
|
50
|
+
|
|
51
|
+
def k_close(self, command):
|
|
52
|
+
if self.nextIsSymbol():
|
|
53
|
+
symbolRecord = self.getSymbolRecord()
|
|
54
|
+
if symbolRecord['keyword'] == 'window':
|
|
55
|
+
command['target'] = symbolRecord['name']
|
|
56
|
+
self.add(command)
|
|
57
|
+
return True
|
|
58
|
+
return False
|
|
59
|
+
|
|
60
|
+
def r_close(self, command):
|
|
61
|
+
target = self.getVariable(command['target'])
|
|
62
|
+
target['window'].close()
|
|
63
|
+
return self.nextPC()
|
|
64
|
+
|
|
65
|
+
# create {window} layout {layout}
|
|
66
|
+
# create {element} {args...}
|
|
67
|
+
def k_create(self, command):
|
|
68
|
+
if self.nextIsSymbol():
|
|
69
|
+
symbolRecord = self.getSymbolRecord()
|
|
70
|
+
type = symbolRecord['keyword']
|
|
71
|
+
command['type'] = type
|
|
72
|
+
command['name'] = symbolRecord['name']
|
|
73
|
+
if type == 'window':
|
|
74
|
+
command['title'] = self.nextValue()
|
|
75
|
+
if self.nextIs('layout'):
|
|
76
|
+
if self.nextIsSymbol():
|
|
77
|
+
symbolRecord = self.getSymbolRecord()
|
|
78
|
+
if symbolRecord['keyword'] == 'layout':
|
|
79
|
+
command['layout'] = symbolRecord['name']
|
|
80
|
+
self.addCommand(command)
|
|
81
|
+
return True
|
|
82
|
+
elif type[0:2] == 'g_':
|
|
83
|
+
command['args'] = self.compileConstant(self.utils.getArgs(self))
|
|
84
|
+
self.addCommand(command)
|
|
85
|
+
return True
|
|
86
|
+
return False
|
|
87
|
+
|
|
88
|
+
def r_create(self, command):
|
|
89
|
+
type = command['type']
|
|
90
|
+
record = self.getVariable(command['name'])
|
|
91
|
+
if type == 'window':
|
|
92
|
+
layout = self.getVariable(command['layout'])
|
|
93
|
+
title = self.getRuntimeValue(command['title'])
|
|
94
|
+
self.program.window = psg.Window(title, layout['layout'], finalize=True)
|
|
95
|
+
self.program.run(self.nextPC())
|
|
96
|
+
self.mainLoop()
|
|
97
|
+
self.program.kill()
|
|
98
|
+
return 0
|
|
99
|
+
elif 'iselement' in record:
|
|
100
|
+
layout = json.loads(self.getRuntimeValue(command['args']))
|
|
101
|
+
args = self.utils.getDefaultArgs(type)
|
|
102
|
+
content = json.loads(layout['content'])
|
|
103
|
+
for n in range(0, len(content)):
|
|
104
|
+
args = self.utils.decode(args, content[n])
|
|
105
|
+
element = self.utils.createElement(type, args)
|
|
106
|
+
record['layout'] = element
|
|
107
|
+
return self.nextPC()
|
|
108
|
+
else:
|
|
109
|
+
RuntimeError(self.program, 'Variable is not a window or an element')
|
|
110
|
+
|
|
111
|
+
def k_g_button(self, command):
|
|
112
|
+
command['iselement'] = True
|
|
113
|
+
return self.compileVariable(command)
|
|
114
|
+
|
|
115
|
+
def r_g_button(self, command):
|
|
116
|
+
return self.nextPC()
|
|
117
|
+
|
|
118
|
+
def k_g_input(self, command):
|
|
119
|
+
command['iselement'] = True
|
|
120
|
+
return self.compileVariable(command)
|
|
121
|
+
|
|
122
|
+
def r_g_input(self, command):
|
|
123
|
+
return self.nextPC()
|
|
124
|
+
|
|
125
|
+
def k_g_text(self, command):
|
|
126
|
+
command['iselement'] = True
|
|
127
|
+
return self.compileVariable(command)
|
|
128
|
+
|
|
129
|
+
def r_g_text(self, command):
|
|
130
|
+
return self.nextPC()
|
|
131
|
+
|
|
132
|
+
def k_init(self, command):
|
|
133
|
+
if self.nextIsSymbol():
|
|
134
|
+
record = self.getSymbolRecord()
|
|
135
|
+
if record['keyword'] == 'layout':
|
|
136
|
+
command['target'] = record['name']
|
|
137
|
+
if self.peek() == 'with':
|
|
138
|
+
self.nextToken()
|
|
139
|
+
if self.nextIsSymbol():
|
|
140
|
+
record = self.getSymbolRecord()
|
|
141
|
+
name = record['name']
|
|
142
|
+
if record['iselement']:
|
|
143
|
+
command['args'] = name
|
|
144
|
+
else: FatalError(self.program.compiler, f'\'{name}\' is not a graphic element')
|
|
145
|
+
else:
|
|
146
|
+
command['type'] = self.getToken()
|
|
147
|
+
command['args'] = self.utils.getArgs(self)
|
|
148
|
+
else: command['args'] = None
|
|
149
|
+
self.addCommand(command)
|
|
150
|
+
return True
|
|
151
|
+
return False
|
|
152
|
+
|
|
153
|
+
def r_init(self, command):
|
|
154
|
+
record = self.getVariable(command['target'])
|
|
155
|
+
record['layout'] = []
|
|
156
|
+
type = command['type']
|
|
157
|
+
args = command['args']
|
|
158
|
+
if args != None:
|
|
159
|
+
if args[0] == '{':
|
|
160
|
+
layout = json.loads(self.getRuntimeValue(json.loads(args)))
|
|
161
|
+
args = self.utils.getDefaultArgs(type)
|
|
162
|
+
for n in range(0, len(layout)):
|
|
163
|
+
args = self.utils.decode(args, layout[n])
|
|
164
|
+
record['layout'].append(self.utils.createElement(type, args))
|
|
165
|
+
else:
|
|
166
|
+
v = self.getVariable(args)
|
|
167
|
+
record['layout'].append(v['layout'])
|
|
168
|
+
return self.nextPC()
|
|
169
|
+
|
|
170
|
+
def k_layout(self, command):
|
|
171
|
+
command['iselement'] = True
|
|
172
|
+
return self.compileVariable(command)
|
|
173
|
+
|
|
174
|
+
def r_layout(self, command):
|
|
175
|
+
return self.nextPC()
|
|
176
|
+
|
|
177
|
+
def k_on(self, command):
|
|
178
|
+
token = self.nextToken()
|
|
179
|
+
command['type'] = token
|
|
180
|
+
if token == 'click':
|
|
181
|
+
command['event'] = token
|
|
182
|
+
if self.peek() == 'in':
|
|
183
|
+
self.nextToken()
|
|
184
|
+
if self.nextIs('screen'):
|
|
185
|
+
command['target'] = None
|
|
186
|
+
elif self.isSymbol():
|
|
187
|
+
target = self.getSymbolRecord()
|
|
188
|
+
command['target'] = target['name']
|
|
189
|
+
else:
|
|
190
|
+
FatalError(self.program.compiler, f'{self.getToken()} is not a screen element')
|
|
191
|
+
return False
|
|
192
|
+
command['goto'] = self.getPC() + 2
|
|
193
|
+
self.add(command)
|
|
194
|
+
self.nextToken()
|
|
195
|
+
pcNext = self.getPC()
|
|
196
|
+
cmd = {}
|
|
197
|
+
cmd['domain'] = 'core'
|
|
198
|
+
cmd['lino'] = command['lino']
|
|
199
|
+
cmd['keyword'] = 'gotoPC'
|
|
200
|
+
cmd['goto'] = 0
|
|
201
|
+
cmd['debug'] = False
|
|
202
|
+
self.addCommand(cmd)
|
|
203
|
+
self.compileOne()
|
|
204
|
+
cmd = {}
|
|
205
|
+
cmd['domain'] = 'core'
|
|
206
|
+
cmd['lino'] = command['lino']
|
|
207
|
+
cmd['keyword'] = 'stop'
|
|
208
|
+
cmd['debug'] = False
|
|
209
|
+
self.addCommand(cmd)
|
|
210
|
+
# Fixup the link
|
|
211
|
+
self.getCommandAt(pcNext)['goto'] = self.getPC()
|
|
212
|
+
return True
|
|
213
|
+
elif token == 'tick':
|
|
214
|
+
command['event'] = token
|
|
215
|
+
command['goto'] = self.getPC() + 2
|
|
216
|
+
self.add(command)
|
|
217
|
+
self.nextToken()
|
|
218
|
+
pcNext = self.getPC()
|
|
219
|
+
cmd = {}
|
|
220
|
+
cmd['domain'] = 'core'
|
|
221
|
+
cmd['lino'] = command['lino']
|
|
222
|
+
cmd['keyword'] = 'gotoPC'
|
|
223
|
+
cmd['goto'] = 0
|
|
224
|
+
cmd['debug'] = False
|
|
225
|
+
self.addCommand(cmd)
|
|
226
|
+
self.compileOne()
|
|
227
|
+
cmd = {}
|
|
228
|
+
cmd['domain'] = 'core'
|
|
229
|
+
cmd['lino'] = command['lino']
|
|
230
|
+
cmd['keyword'] = 'stop'
|
|
231
|
+
cmd['debug'] = False
|
|
232
|
+
self.addCommand(cmd)
|
|
233
|
+
# Fixup the link
|
|
234
|
+
self.getCommandAt(pcNext)['goto'] = self.getPC()
|
|
235
|
+
return True
|
|
236
|
+
return False
|
|
237
|
+
|
|
238
|
+
def r_on(self, command):
|
|
239
|
+
pc = command['goto']
|
|
240
|
+
if command['type'] == 'click':
|
|
241
|
+
event = command['event']
|
|
242
|
+
if event == 'click':
|
|
243
|
+
target = command['target']
|
|
244
|
+
if target == None:
|
|
245
|
+
value = 'screen'
|
|
246
|
+
else:
|
|
247
|
+
widget = self.getVariable(target)
|
|
248
|
+
value = widget['value'][widget['index']]
|
|
249
|
+
self.renderer.setOnClick(value['content'], lambda: self.run(pc))
|
|
250
|
+
return self.nextPC()
|
|
251
|
+
|
|
252
|
+
def k_popup(self, command):
|
|
253
|
+
command['message'] = self.nextValue()
|
|
254
|
+
self.addCommand(command)
|
|
255
|
+
return True
|
|
256
|
+
|
|
257
|
+
def r_popup(self, command):
|
|
258
|
+
psg.popup(self.getRuntimeValue(command['message']))
|
|
259
|
+
return self.nextPC()
|
|
260
|
+
|
|
261
|
+
def k_set(self, command):
|
|
262
|
+
return True
|
|
263
|
+
|
|
264
|
+
def r_set(self, command):
|
|
265
|
+
return self.nextPC()
|
|
266
|
+
|
|
267
|
+
def k_window(self, command):
|
|
268
|
+
return self.compileVariable(command)
|
|
269
|
+
|
|
270
|
+
def r_window(self, command):
|
|
271
|
+
return self.nextPC()
|
|
272
|
+
|
|
273
|
+
#############################################################################
|
|
274
|
+
# Compile a value in this domain
|
|
275
|
+
def compileValue(self):
|
|
276
|
+
value = {}
|
|
277
|
+
value['domain'] = 'graphics'
|
|
278
|
+
token = self.getToken()
|
|
279
|
+
if self.isSymbol():
|
|
280
|
+
return None
|
|
281
|
+
|
|
282
|
+
if self.tokenIs('the'):
|
|
283
|
+
self.nextToken()
|
|
284
|
+
token = self.getToken()
|
|
285
|
+
|
|
286
|
+
value['type'] = token
|
|
287
|
+
|
|
288
|
+
if token == 'test':
|
|
289
|
+
name = self.nextToken()
|
|
290
|
+
value = {}
|
|
291
|
+
value['type'] = 'text'
|
|
292
|
+
value['content'] = 'test'
|
|
293
|
+
return value
|
|
294
|
+
|
|
295
|
+
return None
|
|
296
|
+
|
|
297
|
+
#############################################################################
|
|
298
|
+
# Modify a value or leave it unchanged.
|
|
299
|
+
def modifyValue(self, value):
|
|
300
|
+
return value
|
|
301
|
+
|
|
302
|
+
#############################################################################
|
|
303
|
+
# Value handlers
|
|
304
|
+
|
|
305
|
+
def v_test(self, v):
|
|
306
|
+
return v
|
|
307
|
+
|
|
308
|
+
#############################################################################
|
|
309
|
+
# Compile a condition
|
|
310
|
+
def compileCondition(self):
|
|
311
|
+
condition = {}
|
|
312
|
+
return condition
|
|
313
|
+
|
|
314
|
+
#############################################################################
|
|
315
|
+
# Condition handlers
|
|
316
|
+
|
|
317
|
+
#############################################################################
|
|
318
|
+
# The main loop
|
|
319
|
+
def mainLoop(self):
|
|
320
|
+
while True:
|
|
321
|
+
event, values = self.program.window.Read(timeout=100)
|
|
322
|
+
if event == psg.WINDOW_CLOSED or event == "EXIT":
|
|
323
|
+
break
|
|
324
|
+
if event == '__TIMEOUT__': self.program.flushCB()
|
|
325
|
+
else:
|
|
326
|
+
print(event, values)
|
easycoder/ec_gutils.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import PySimpleGUI as psg
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
class GUtils:
|
|
5
|
+
|
|
6
|
+
# Parse a set of compile-time arguments
|
|
7
|
+
def getArgs(self, handler):
|
|
8
|
+
args = []
|
|
9
|
+
while True:
|
|
10
|
+
key = handler.nextToken()
|
|
11
|
+
value = json.dumps(handler.nextValue())
|
|
12
|
+
args.append(f'{key}={value}')
|
|
13
|
+
if handler.peek() == 'and':
|
|
14
|
+
handler.nextToken()
|
|
15
|
+
else: break
|
|
16
|
+
v = {}
|
|
17
|
+
v['type'] = 'text'
|
|
18
|
+
v['content'] = json.dumps(args)
|
|
19
|
+
return json.dumps(v)
|
|
20
|
+
|
|
21
|
+
# Get the default args for a graphic element
|
|
22
|
+
def getDefaultArgs(self, type):
|
|
23
|
+
args = {}
|
|
24
|
+
if type == 'g_text':
|
|
25
|
+
args['text'] = '(empty)'
|
|
26
|
+
args['expand_x'] = False
|
|
27
|
+
elif type == 'g_input':
|
|
28
|
+
args['key'] = None
|
|
29
|
+
args['size'] = (None, None)
|
|
30
|
+
elif type == 'g_button':
|
|
31
|
+
args['button_text'] = '(empty)'
|
|
32
|
+
return args
|
|
33
|
+
|
|
34
|
+
# Decode an argument at runtime
|
|
35
|
+
def decode(self, args, text):
|
|
36
|
+
p = text.find('=')
|
|
37
|
+
if p > 0:
|
|
38
|
+
key = text[0:p]
|
|
39
|
+
value = json.loads(text[p+1:])['content']
|
|
40
|
+
args[key] = value
|
|
41
|
+
return args
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
# Create an element
|
|
45
|
+
def createElement(self, type, args):
|
|
46
|
+
if type == 'g_text': return psg.Text(text=args['text'], expand_x=args['expand_x'])
|
|
47
|
+
elif type == 'g_input':
|
|
48
|
+
size = args['size'].split()
|
|
49
|
+
size = (size[0], size[1])
|
|
50
|
+
return psg.Input(key=args['key'], size=size)
|
|
51
|
+
elif type == 'g_button': return psg.Button(button_text=args['button_text'])
|
|
52
|
+
else: return None
|
easycoder/ec_handler.py
CHANGED
|
@@ -25,6 +25,7 @@ class Handler:
|
|
|
25
25
|
self.getCommandAt = compiler.getCommandAt
|
|
26
26
|
self.compileOne = compiler.compileOne
|
|
27
27
|
self.compileFromHere = compiler.compileFromHere
|
|
28
|
+
self.compileConstant = compiler.compileConstant
|
|
28
29
|
|
|
29
30
|
self.code = self.program.code
|
|
30
31
|
self.add = self.program.add
|