easycoder 241218.1__py2.py3-none-any.whl → 241231.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/ec_graphics.py CHANGED
@@ -1,6 +1,7 @@
1
- from .ec_classes import FatalError, RuntimeError
1
+ from .ec_classes import FatalError, RuntimeError, Object
2
2
  from .ec_handler import Handler
3
- from .ec_renderer import *
3
+ from .ec_screenspec import ScreenSpec
4
+ from .ec_renderer import Renderer
4
5
 
5
6
  class Graphics(Handler):
6
7
 
@@ -19,56 +20,183 @@ class Graphics(Handler):
19
20
  command['name'] = record['name']
20
21
  if self.nextIs('to'):
21
22
  value = self.nextValue()
23
+ record['id'] = value
22
24
  command['id'] = value
23
25
  self.add(command)
24
26
  return True
25
27
 
26
28
  def r_attach(self, command):
27
- target = self.getVariable(command['name'])
29
+ targetRecord = self.getVariable(command['name'])
30
+ keyword = targetRecord['keyword']
28
31
  id = self.getRuntimeValue(command['id'])
29
- element = getElement(id)
32
+ element = self.ui.getElement(id)
30
33
  if element == None:
31
34
  FatalError(self.program.compiler, f'There is no screen element with id \'{id}\'')
32
35
  return -1
33
- if element['type'] != target['keyword']:
34
- FatalError(self.program.compiler, f'Mismatched element type ({element['type']} and {target['keyword']})')
35
- self.putSymbolValue(target, {'type': 'text', 'content': id})
36
+ if element.getType() != keyword:
37
+ FatalError(self.program.compiler, f'Mismatched element type ({element['type']} and {keyword})')
38
+ self.putSymbolValue(targetRecord, {'type': 'text', 'content': id})
36
39
  return self.nextPC()
37
40
 
41
+ # close window
38
42
  def k_close(self, command):
39
- if self.nextIs('screen'):
43
+ if (self.nextIs('window')):
40
44
  self.add(command)
41
45
  return True
42
46
  return False
43
47
 
44
48
  def r_close(self, command):
45
- closeScreen()
46
- return self.nextPC()
49
+ self.renderer.stop()
50
+ return 0
47
51
 
52
+ # create window/ellipse/rectangle//text/image
48
53
  def k_create(self, command):
49
- if self.nextIs('screen'):
54
+ token = self.nextToken()
55
+ if (token == 'window'):
56
+ t = {}
57
+ t['type'] = 'text'
58
+ t['content'] = 'EasyCoder'
59
+ width = self.compileConstant(640)
60
+ height = self.compileConstant(480)
61
+ left = self.compileConstant(100)
62
+ top = self.compileConstant(100)
63
+ r = self.compileConstant(255)
64
+ g = self.compileConstant(255)
65
+ b = self.compileConstant(255)
50
66
  while True:
51
67
  token = self.peek()
52
- if token == 'at':
68
+ if token == 'title':
53
69
  self.nextToken()
54
- command['left'] = self.nextValue()
55
- command['top'] = self.nextValue()
70
+ t = self.nextValue()
71
+ elif token == 'at':
72
+ self.nextToken()
73
+ left = self.nextValue()
74
+ top = self.nextValue()
56
75
  elif token == 'size':
57
76
  self.nextToken()
58
- command['width'] = self.nextValue()
59
- command['height'] = self.nextValue()
77
+ width = self.nextValue()
78
+ height = self.nextValue()
60
79
  elif token == 'fill':
61
80
  self.nextToken()
62
- command['fill'] = self.nextValue()
81
+ if self.nextIs('color'):
82
+ r = self.nextValue()
83
+ g = self.nextValue()
84
+ b = self.nextValue()
63
85
  else:
64
86
  break
87
+ command['type'] = 'window'
88
+ command['title'] = t
89
+ command['pos'] = (left, top)
90
+ command['size'] = (width, height)
91
+ command['fill'] = (r, g, b)
65
92
  self.add(command)
66
93
  return True
94
+
95
+ elif self.isSymbol():
96
+ record = self.getSymbolRecord()
97
+ command['target'] = record['name']
98
+ type = record['keyword']
99
+ command['type'] = type
100
+ if type in ['ellipse', 'rectangle', 'image']:
101
+ self.getElementData(type, command)
102
+ for item in ['width', 'height', 'left', 'bottom', 'r', 'g', 'b']:
103
+ if command[item] == None:
104
+ FatalError(self.program.compiler, f'Missing property \'{item}\'')
105
+ return True
106
+ elif type == 'text':
107
+ self.getElementData(type, command)
108
+ for item in ['width', 'height', 'left', 'bottom', 'r', 'g', 'b', 'text']:
109
+ if command[item] == None:
110
+ FatalError(self.program.compiler, f'Missing property \'{item}\'')
111
+ self.add(command)
112
+ record['elementID'] = command['id']
67
113
  return False
114
+
115
+ def getElementData(self, type, command):
116
+ width = None
117
+ height = None
118
+ left = None
119
+ bottom = None
120
+ r = None
121
+ g = None
122
+ b = None
123
+ text = None
124
+ source = None
125
+ id = self.nextValue()
126
+ while True:
127
+ token = self.peek()
128
+ if token == 'size':
129
+ self.nextToken()
130
+ width = self.nextValue()
131
+ height = self.nextValue()
132
+ elif token == 'at':
133
+ self.nextToken()
134
+ left = self.nextValue()
135
+ bottom = self.nextValue()
136
+ elif token == 'fill':
137
+ self.nextToken()
138
+ r = self.nextValue()
139
+ g = self.nextValue()
140
+ b = self.nextValue()
141
+ elif token == 'text':
142
+ self.nextToken()
143
+ text = self.nextValue()
144
+ elif token == 'source':
145
+ self.nextToken()
146
+ source = self.nextValue()
147
+ else:
148
+ break
149
+ command['id'] = id
150
+ command['type'] = type
151
+ if width != None:
152
+ command['width'] = width
153
+ if height != None:
154
+ command['height'] = height
155
+ if left!= None:
156
+ command['left'] = left
157
+ if bottom != None:
158
+ command['bottom'] = bottom
159
+ if r != None:
160
+ command['r'] = r
161
+ if g != None:
162
+ command['g'] = g
163
+ if b != None:
164
+ command['b'] = b
165
+ if text != None:
166
+ command['text'] = text
167
+ if source != None:
168
+ command['source'] = source
68
169
 
69
170
  def r_create(self, command):
70
- createScreen(command)
171
+ try:
172
+ type = command['type']
173
+ if type == 'window':
174
+ self.windowSpec = Object()
175
+ self.windowSpec.title = command['title']['content']
176
+ self.windowSpec.flush = self.program.flush
177
+ self.windowSpec.finish = self.program.finish
178
+ self.windowSpec.pos = (self.getRuntimeValue(command['pos'][0]), self.getRuntimeValue(command['pos'][1]))
179
+ self.windowSpec.size = (self.getRuntimeValue(command['size'][0]), self.getRuntimeValue(command['size'][1]))
180
+ self.windowSpec.fill = (self.getRuntimeValue(command['fill'][0])/255, self.getRuntimeValue(command['fill'][1])/255, self.getRuntimeValue(command['fill'][2])/255)
181
+ else:
182
+ element = self.ui.createWidget(self.getWidgetSpec(command))
183
+ print(element)
184
+ except Exception as e:
185
+ RuntimeError(self.program, e)
71
186
  return self.nextPC()
187
+
188
+ def getWidgetSpec(self, command):
189
+ spec = Object()
190
+ spec.id = self.getRuntimeValue(command['id'])
191
+ spec.type = command['type']
192
+ spec.w = self.getRuntimeValue(command['width'])
193
+ spec.h = self.getRuntimeValue(command['height'])
194
+ spec.x = self.getRuntimeValue(command['left'])
195
+ spec.y = self.getRuntimeValue(command['bottom'])
196
+ spec.r = self.getRuntimeValue(command['r'])/255
197
+ spec.g = self.getRuntimeValue(command['g'])/255
198
+ spec.b = self.getRuntimeValue(command['b'])/255
199
+ return spec
72
200
 
73
201
  def k_ellipse(self, command):
74
202
  return self.compileVariable(command)
@@ -76,75 +204,57 @@ class Graphics(Handler):
76
204
  def r_ellipse(self, command):
77
205
  return self.nextPC()
78
206
 
207
+ def r_getui(self, command):
208
+ self.ui = self.renderer.getUI()
209
+ return self.nextPC()
210
+
79
211
  def k_image(self, command):
80
212
  return self.compileVariable(command)
81
213
 
82
214
  def r_image(self, command):
83
215
  return self.nextPC()
84
216
 
217
+ # move an element
85
218
  def k_move(self, command):
86
219
  if self.nextIsSymbol():
87
220
  record = self.getSymbolRecord()
88
- if record['keyword'] in ['rectangle', 'ellipse', 'text', 'image']:
89
- command['name'] = record['name']
90
- if self.nextToken() in ['by', 'to']:
91
- command['type'] = self.getToken()
221
+ type = record['keyword']
222
+ if type in ['ellipse', 'rectangle']:
223
+ command['target'] = record['id']
224
+ token = self.nextToken()
225
+ if token == 'to':
92
226
  command['x'] = self.nextValue()
93
227
  command['y'] = self.nextValue()
94
228
  self.add(command)
95
229
  return True
230
+ elif token == 'by':
231
+ command['keyword'] = 'moveBy'
232
+ command['dx'] = self.nextValue()
233
+ command['dy'] = self.nextValue()
234
+ self.add(command)
235
+ return True
96
236
  return False
97
237
 
98
238
  def r_move(self, command):
99
- target = self.getVariable(command['name'])
100
- id = self.getSymbolValue(target)['content']
101
- type = command['type']
102
- x = self.getRuntimeValue(command['x'])
103
- y = self.getRuntimeValue(command['y'])
104
- if type == 'by':
105
- moveElement(id, x, y)
106
- elif type == 'to':
107
- moveElementTo(id, x, y)
239
+ pos = (self.getRuntimeValue(command['x']), self.getRuntimeValue(command['y']))
240
+ self.ui.moveElementTo(self.getRuntimeValue(command['target']), pos)
241
+ return self.nextPC()
242
+
243
+ def r_moveBy(self, command):
244
+ dist = (self.getRuntimeValue(command['dx']), self.getRuntimeValue(command['dy']))
245
+ self.ui.moveElementBy(self.getRuntimeValue(command['target']), dist)
108
246
  return self.nextPC()
109
247
 
110
248
  def k_on(self, command):
111
249
  token = self.nextToken()
112
- command['type'] = token
113
- if token == 'click':
114
- command['event'] = token
115
- if self.peek() == 'in':
116
- self.nextToken()
117
- if self.nextIs('screen'):
118
- command['target'] = None
119
- elif self.isSymbol():
250
+ if token in ['click', 'tap']:
251
+ command['type'] = 'tap'
252
+ if self.nextIsSymbol():
120
253
  target = self.getSymbolRecord()
121
- command['target'] = target['name']
122
254
  else:
123
255
  FatalError(self.program.compiler, f'{self.getToken()} is not a screen element')
124
256
  return False
125
- command['goto'] = self.getPC() + 2
126
- self.add(command)
127
- self.nextToken()
128
- pcNext = self.getPC()
129
- cmd = {}
130
- cmd['domain'] = 'core'
131
- cmd['lino'] = command['lino']
132
- cmd['keyword'] = 'gotoPC'
133
- cmd['goto'] = 0
134
- cmd['debug'] = False
135
- self.addCommand(cmd)
136
- self.compileOne()
137
- cmd = {}
138
- cmd['domain'] = 'core'
139
- cmd['lino'] = command['lino']
140
- cmd['keyword'] = 'stop'
141
- cmd['debug'] = False
142
- self.addCommand(cmd)
143
- # Fixup the link
144
- self.getCommandAt(pcNext)['goto'] = self.getPC()
145
- return True
146
- elif token == 'tick':
147
- command['event'] = token
257
+ command['target'] = target['name']
148
258
  command['goto'] = self.getPC() + 2
149
259
  self.add(command)
150
260
  self.nextToken()
@@ -170,18 +280,14 @@ class Graphics(Handler):
170
280
 
171
281
  def r_on(self, command):
172
282
  pc = command['goto']
173
- if command['type'] == 'click':
174
- event = command['event']
175
- if event == 'click':
176
- target = command['target']
177
- if target == None:
178
- value = 'screen'
179
- else:
180
- widget = self.getVariable(target)
181
- value = widget['value'][widget['index']]
182
- setOnClick(value['content'], lambda: self.run(pc))
183
- elif command['type'] == 'tick':
184
- setOnTick(lambda: self.run(pc))
283
+ if command['type'] == 'tap':
284
+ record = self.getVariable(command['target'])
285
+ keyword = record['keyword']
286
+ if keyword in ['ellipse', 'rectangle', 'text', 'image']:
287
+ id = record['value'][record['index']]['content']
288
+ self.ui.setOnClick(id, lambda: self.run(pc))
289
+ else:
290
+ RuntimeError(self.program, f'{record['name']} is not a clickable object')
185
291
  return self.nextPC()
186
292
 
187
293
  def k_rectangle(self, command):
@@ -190,181 +296,128 @@ class Graphics(Handler):
190
296
  def r_rectangle(self, command):
191
297
  return self.nextPC()
192
298
 
299
+ def k_text(self, command):
300
+ return self.compileVariable(command)
301
+
302
+ def r_text(self, command):
303
+ return self.nextPC()
304
+
305
+ # render {spec}
193
306
  def k_render(self, command):
194
- command['value'] = self.nextValue()
195
- command['parent'] = 'screen'
196
- if self.peek() == 'in':
197
- self.nextToken()
198
- if self.nextIsSymbol():
199
- record = self.getSymbolRecord()
200
- type = record['type']
201
- name = record['name']
202
- if type in ['rectangle', 'ellipse']:
203
- command['parent'] = record['name']
204
- self.add(command)
205
- return True
206
- else:
207
- self.warning(f'Graphics.render: {name} cannot be a parent of another element')
208
- return False
307
+ command['spec'] = self.nextValue()
209
308
  self.add(command)
210
309
  return True
211
- FatalError(self.program.compiler, 'Nothing specified to render')
212
- return False
213
310
 
214
311
  def r_render(self, command):
215
- parent = command['parent']
216
- value = self.getRuntimeValue(command['value'])
217
- render(value, parent)
312
+ self.ui = self.renderer.getUI()
313
+ try:
314
+ ScreenSpec().render(self.getRuntimeValue(command['spec']), self.ui)
315
+ except Exception as e:
316
+ RuntimeError(self.program, e)
218
317
  return self.nextPC()
219
318
 
220
- def k_set(self, command):
221
- if self.peek() == 'the':
222
- self.nextToken()
223
- token = self.peek()
224
- if token == 'text':
225
- self.nextToken()
226
- command['variant'] = 'setText'
227
- if self.peek() == 'of':
228
- self.nextToken()
229
- if self.nextIsSymbol():
230
- record = self.getSymbolRecord()
231
- command['name'] = record['name']
232
- if record['keyword'] != 'text':
233
- RuntimeError(command['program'], f'Symbol type is not \'text\'')
234
- if self.peek() == 'to':
235
- self.nextToken()
236
- command['value'] = self.nextValue()
237
- self.add(command)
238
- return True
239
- return False
240
- elif token == 'background':
241
- self.nextToken()
242
- command['variant'] = 'setBackground'
243
- if self.peek() == 'color':
244
- self.nextToken()
245
- if self.peek() == 'of':
246
- self.nextToken()
247
- if self.nextIsSymbol():
248
- record = self.getSymbolRecord()
249
- command['name'] = record['name']
250
- if not record['keyword'] in ['rectangle', 'ellipse']:
251
- RuntimeError(command['program'], f'Symbol type is not \'rectangle\' or \'ellipse\'')
252
- if self.peek() == 'to':
253
- self.nextToken()
254
- command['value'] = self.nextValue()
255
- self.add(command)
256
- return True
257
- return False
258
- return False
259
-
260
- def r_set(self, command):
261
- variant = command['variant']
262
- if variant == 'setText':
263
- variable = self.getVariable(command['name'])
264
- element = self.getSymbolValue(variable)
265
- value = self.getRuntimeValue(command['value'])
266
- setText(element['content'], value)
267
- elif variant == 'setBackground':
268
- variable = self.getVariable(command['name'])
269
- element = self.getSymbolValue(variable)
270
- value = self.getRuntimeValue(command['value'])
271
- setBackground(element['content'], value)
272
- return self.nextPC()
273
-
274
- def k_show(self, command):
275
- if self.nextIs('screen'):
276
- command['name'] = None
319
+ # run graphics
320
+ def k_run(self, command):
321
+ if self.nextIs('graphics'):
277
322
  self.add(command)
323
+ cmd = {}
324
+ cmd['domain'] = 'graphics'
325
+ cmd['lino'] = command['lino'] + 1
326
+ cmd['keyword'] = 'getui'
327
+ cmd['debug'] = False
328
+ self.addCommand(cmd)
278
329
  return True
279
330
  return False
280
331
 
281
- def r_show(self, command):
282
- showScreen()
283
- return self.nextPC()
332
+ def r_run(self, command):
333
+ self.renderer = Renderer()
334
+ self.renderer.init(self.windowSpec)
335
+ self.program.setExternalControl()
336
+ self.program.run(self.nextPC())
337
+ self.renderer.run()
284
338
 
285
- def k_spec(self, command):
286
- return self.compileVariable(command, True)
339
+ # Set something
340
+ def k_set(self, command):
341
+ if self.nextIs('attribute'):
342
+ command['attribute'] = self.nextValue()
343
+ if self.nextIs('of'):
344
+ if self.nextIsSymbol():
345
+ record = self.getSymbolRecord()
346
+ if record['keyword'] in ['ellipse', 'rectangle', 'text', 'image']:
347
+ command['target'] = record['name']
348
+ if self.nextIs('to'):
349
+ command['value'] = self.nextValue()
350
+ self.addCommand(command)
351
+ return True
352
+ else:
353
+ FatalError(self.program.compiler, f'Invalid type: {record['keyword']}')
354
+ else:
355
+ FatalError(self.program.compiler, f'\'{self.getToken()}\' is not a variable')
356
+ return False
287
357
 
288
- def r_spec(self, command):
358
+ def r_set(self, command):
359
+ attribute = self.getRuntimeValue(command['attribute'])
360
+ target = self.getVariable(command['target'])
361
+ id = target['value'][target['index']]['content']
362
+ value = self.getRuntimeValue(command['value'])
363
+ self.ui.setAttribute(id, attribute, value)
289
364
  return self.nextPC()
290
365
 
291
- def k_text(self, command):
292
- return self.compileVariable(command)
366
+ #############################################################################
367
+ # Modify a value or leave it unchanged.
368
+ def modifyValue(self, value):
369
+ return value
293
370
 
294
- def r_text(self, command):
295
- return self.nextPC()
296
-
297
371
  #############################################################################
298
372
  # Compile a value in this domain
299
373
  def compileValue(self):
300
374
  value = {}
301
- value['domain'] = 'graphics'
302
- token = self.getToken()
303
- if self.isSymbol():
304
- value['name'] = token
305
- symbolRecord = self.getSymbolRecord()
306
- keyword = symbolRecord['keyword']
307
- if keyword == 'module':
308
- value['type'] = 'module'
309
- return value
310
-
311
- if symbolRecord['valueHolder'] == True or keyword == 'dictionary':
312
- value['type'] = 'symbol'
313
- return value
314
- return None
315
-
375
+ value['domain'] = self.getName()
316
376
  if self.tokenIs('the'):
317
377
  self.nextToken()
318
- token = self.getToken()
319
-
320
- value['type'] = token
321
-
322
- if token == 'color':
323
- name = self.nextToken()
324
- value = {}
325
- value['type'] = 'string'
326
- value['content'] = name
327
- return value
328
-
329
- elif token == 'attribute':
330
- value['attribute'] = self.nextValue()
331
- if (self.nextIs('of')):
332
- if (self.nextIsSymbol()):
333
- value['name'] = self.getToken()
334
- return value
378
+ kwd = self.getToken()
379
+ value['type'] = kwd
380
+ if kwd == 'attribute':
381
+ attribute = self.nextValue()
382
+ if self.nextIs('of'):
383
+ if self.nextIsSymbol():
384
+ record = self.getSymbolRecord()
385
+ if record['keyword'] in ['ellipse', 'rectangle']:
386
+ value['attribute'] = attribute
387
+ value['target'] = record['name']
388
+ return value
389
+ elif kwd == 'window':
390
+ attribute = self.nextToken()
391
+ if attribute in ['left', 'top', 'width', 'height']:
392
+ value['attribute'] = attribute
393
+ return value
335
394
  return None
336
395
 
337
- #############################################################################
338
- # Modify a value or leave it unchanged.
339
- def modifyValue(self, value):
340
- return value
341
-
342
396
  #############################################################################
343
397
  # Value handlers
344
398
 
345
- def v_symbol(self, symbolRecord):
346
- result = {}
347
- if symbolRecord['valueHolder']:
348
- symbolValue = self.getSymbolValue(symbolRecord)
349
- if symbolValue == None:
350
- return None
351
- result['type'] = symbolValue['type']
352
- content = symbolValue['content']
353
- if content == None:
354
- return ''
355
- result['content'] = content
356
- return result
357
- else:
358
- return ''
359
-
360
399
  def v_attribute(self, v):
361
- target = self.getVariable(v['name'])
362
- attribute = self.getRuntimeValue(v['attribute'])
363
- name = target['value'][target['index']]['content']
364
- value = {}
365
- value['type'] = 'int'
366
- value['content'] = getAttribute(name, attribute)
367
- return value
400
+ try:
401
+ attribute = self.getRuntimeValue(v['attribute'])
402
+ target = self.getVariable(v['target'])
403
+ val = self.getSymbolValue(target)
404
+ v = self.ui.getAttribute(val['content'], attribute)
405
+ value = {}
406
+ value['type'] = 'int'
407
+ value['content'] = int(round(v))
408
+ return value
409
+ except Exception as e:
410
+ RuntimeError(self.program, e)
411
+
412
+ def v_window(self, v):
413
+ try:
414
+ attribute = v['attribute']
415
+ value = {}
416
+ value['type'] = 'int'
417
+ value['content'] = int(round(self.ui.getWindowAttribute(attribute)))
418
+ return value
419
+ except Exception as e:
420
+ RuntimeError(self.program, e)
368
421
 
369
422
  #############################################################################
370
423
  # Compile a condition
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