easycoder 250118.1__py2.py3-none-any.whl → 251103.4__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/ec_handler.py CHANGED
@@ -3,9 +3,11 @@ import json
3
3
  class Handler:
4
4
 
5
5
  def __init__(self, compiler):
6
+ self.compiler = compiler
6
7
  self.program = compiler.program
7
8
  self.getToken = compiler.getToken
8
9
  self.nextToken = compiler.nextToken
10
+ self.skip = compiler.skip
9
11
  self.peek = compiler.peek
10
12
  self.getValue = compiler.getValue
11
13
  self.nextValue = compiler.nextValue
@@ -21,20 +23,20 @@ class Handler:
21
23
  self.rewindTo = compiler.rewindTo
22
24
  self.warning = compiler.warning
23
25
  self.getPC = compiler.getPC
24
- self.addCommand = compiler.addCommand
26
+ self.add = compiler.addCommand
25
27
  self.getCommandAt = compiler.getCommandAt
26
28
  self.compileOne = compiler.compileOne
27
29
  self.compileFromHere = compiler.compileFromHere
28
30
  self.compileConstant = compiler.compileConstant
29
31
 
30
32
  self.code = self.program.code
31
- self.add = self.program.add
32
33
  self.evaluate = self.program.evaluate
33
34
  self.getVariable = self.program.getSymbolRecord
34
35
  self.getRuntimeValue = self.program.getRuntimeValue
35
36
  self.testCondition = self.program.condition.testCondition
36
37
  self.symbols = self.program.symbols
37
38
  self.stack = self.program.stack
39
+ self.getSymbolContent = self.program.getSymbolContent
38
40
  self.getSymbolValue = self.program.getSymbolValue
39
41
  self.putSymbolValue = self.program.putSymbolValue
40
42
  self.run = self.program.run
@@ -0,0 +1,439 @@
1
+ from .ec_handler import Handler
2
+ from .ec_border import Border
3
+ from PySide6.QtWidgets import (
4
+ QDialog,
5
+ QVBoxLayout,
6
+ QHBoxLayout,
7
+ QPushButton,
8
+ QLineEdit,
9
+ QPlainTextEdit,
10
+ QWidget,
11
+ QStackedWidget,
12
+ QSpacerItem,
13
+ QSizePolicy,
14
+ QGraphicsDropShadowEffect
15
+ )
16
+ from PySide6.QtGui import QFont, QIcon, QPixmap, QPainter
17
+ from PySide6.QtCore import Qt, QTimer, Signal, QRect
18
+
19
+ class Keyboard(Handler):
20
+ iconClicked = Signal()
21
+
22
+ def __init__(self, program, keyboardType, receiverLayout, receivers, caller = None, parent=None):
23
+ super().__init__(program.compiler)
24
+
25
+ self.program = program
26
+ self.receivers = receivers
27
+
28
+ dialog = QDialog(caller)
29
+ self.dialog = dialog
30
+
31
+ # dialog.setWindowTitle('')
32
+ dialog.setWindowFlags(Qt.FramelessWindowHint)
33
+ dialog.setModal(True)
34
+ dialog.setFixedWidth(500)
35
+ dialog.setStyleSheet('background-color: white;border:1px solid black;')
36
+
37
+ # Add drop shadow
38
+ shadow = QGraphicsDropShadowEffect(dialog)
39
+ shadow.setBlurRadius(40)
40
+ shadow.setOffset(0, 4)
41
+ shadow.setColor(Qt.black)
42
+ dialog.setGraphicsEffect(shadow)
43
+
44
+ # Add the keyboard
45
+ layout = QVBoxLayout(dialog)
46
+
47
+ border = Border()
48
+ border.tickClicked.connect(self.dialog.accept)
49
+ border.closeClicked.connect(self.reject)
50
+ layout.addWidget(border)
51
+ layout.addLayout(receiverLayout)
52
+ self.vk = VirtualKeyboard(keyboardType, 42, receivers[0], dialog.accept)
53
+ layout.addWidget(self.vk)
54
+
55
+ restore = []
56
+ index = 0
57
+ for receiver in receivers:
58
+ receiver.field.setContainer(self)
59
+ receiver.index = index
60
+ restore.append(receiver.getContent())
61
+ index += 1
62
+ self.restore = restore
63
+
64
+ # Position at bottom of parent window
65
+ dialog.show() # Ensure geometry is calculated
66
+ if parent:
67
+ parent_pos = parent.mapToGlobal(parent.rect().bottomLeft())
68
+ x = parent_pos.x() + (parent.width - dialog.width()) / 2
69
+ y = parent_pos.y() - dialog.height() - 40
70
+ dialog.move(x, y)
71
+
72
+ dialog.exec()
73
+
74
+ def setClickSource(self, field):
75
+ receivers = self.receivers
76
+ for receiver in receivers:
77
+ if receiver.field == field:
78
+ self.vk.setReceiver(receiver)
79
+ return
80
+
81
+ def reject(self):
82
+ receivers = self.receivers
83
+ index = 0
84
+ for receiver in receivers:
85
+ receiver.setContent(self.restore[index])
86
+ index += 1
87
+ self.dialog.reject()
88
+
89
+ class TextReceiver():
90
+ def __init__(self, field):
91
+ self.field = field
92
+
93
+ def addCharacter(self, char):
94
+ char = char.replace('&&', '&')
95
+ if len(char) == 1:
96
+ self.setContent(self.getContent() + char)
97
+ else:
98
+ raise ValueError("Only single characters are allowed.")
99
+
100
+ def backspace(self):
101
+ current_text = self.getContent()
102
+ if current_text:
103
+ self.setContent(current_text[:-1])
104
+
105
+ def setContent(self, text):
106
+ if isinstance(self.field, QLineEdit):
107
+ self.field.setText(text)
108
+ elif isinstance(self.field, QPlainTextEdit):
109
+ self.field.setPlainText(text)
110
+
111
+ def getContent(self):
112
+ if isinstance(self.field, QLineEdit):
113
+ return self.field.text()
114
+ elif isinstance(self.field, QPlainTextEdit):
115
+ return self.field.toPlainText()
116
+
117
+ class KeyboardButton(QPushButton):
118
+ def __init__(self, width, height, onClick, text=None, icon=None):
119
+ if text != None: text = text.replace('&','&&')
120
+ super().__init__(text)
121
+ self.setFixedSize(width, height)
122
+ self.setFont(QFont("Arial", height // 2)) # Font size is half the button height
123
+ self.setStyleSheet(f"""
124
+ QPushButton {{
125
+ background-color: white;
126
+ border: none;
127
+ border-radius: {int(height * 0.2)}px; /* Rounded corners */
128
+ }}
129
+ QPushButton:pressed {{
130
+ background-color: #ddd; /* Slightly darker background when pressed */
131
+ }}
132
+ """)
133
+
134
+ if icon:
135
+ self.setIcon(QIcon(icon))
136
+ self.setIconSize(self.size())
137
+
138
+ self.clicked.connect(lambda: self.animate_button(onClick, text))
139
+
140
+ def animate_button(self, onClick, text):
141
+ # Move the button 2 pixels down and right
142
+ self.move(self.x() + 2, self.y() + 2)
143
+ QTimer.singleShot(200, lambda: self.move(self.x() - 2, self.y() - 2)) # Move back after 200ms
144
+ onClick(text)
145
+
146
+ class KeyboardRow(QHBoxLayout):
147
+ def __init__(self, items):
148
+ super().__init__()
149
+ for item in items:
150
+ if isinstance(item, QWidget):
151
+ self.addWidget(item)
152
+ elif isinstance(item, QSpacerItem):
153
+ self.addSpacerItem(item)
154
+
155
+ class KeyboardView(QVBoxLayout):
156
+ def __init__(self, rows):
157
+ super().__init__()
158
+ for row in rows:
159
+ self.addLayout(row)
160
+
161
+ ###############################################################################
162
+ # VirtualKeyboard Class
163
+ class VirtualKeyboard(QStackedWidget):
164
+ def __init__(self, keyboardType, buttonHeight, receiver, onFinished):
165
+ super().__init__()
166
+ self.keyboardType = keyboardType
167
+ self.buttonHeight = buttonHeight
168
+ self.receiver = receiver
169
+ self.onFinished = onFinished
170
+ self.setStyleSheet('background-color: #ccc;border:none;')
171
+
172
+ # Create the 4 keyboard layouts
173
+ self.addKeyboardLayout0()
174
+ self.addKeyboardLayout1()
175
+ self.addKeyboardLayout2()
176
+ self.addKeyboardLayout3()
177
+
178
+ ###########################################################################
179
+ # Add the first keyboard layout (lowercase letters)
180
+ def addKeyboardLayout0(self):
181
+ rowList = []
182
+
183
+ # Row 1: Numbers
184
+ # row1 = KeyboardRow([KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, char) for char in '1234567890'])
185
+ # rowList.append(row1)
186
+
187
+ # Row 2: qwertyuiop
188
+ row2 = KeyboardRow([
189
+ QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum),
190
+ *[KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, char) for char in 'qwertyuiop'],
191
+ QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum)
192
+ ])
193
+ rowList.append(row2)
194
+
195
+ # Row 3: asdfghjkl with horizontal stretches
196
+ row3 = KeyboardRow([
197
+ QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum),
198
+ *[KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, char) for char in 'asdfghjkl'],
199
+ QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum)
200
+ ])
201
+ rowList.append(row3)
202
+
203
+ # Row 4: Shift, ZXC..., Backspace
204
+ row4 = KeyboardRow([
205
+ QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum),
206
+ KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickShift, None, 'img/up.png'),
207
+ QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
208
+ *[KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, char) for char in 'zxcvbnm'],
209
+ QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
210
+ KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickBack, None, 'img/back.png'),
211
+ QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum)
212
+ ])
213
+ rowList.append(row4)
214
+
215
+ # Row 5: Numbers, Space, Enter
216
+ row5 = KeyboardRow([
217
+ QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum),
218
+ KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickNumbers, None, 'img/numbers.png'),
219
+ QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
220
+ KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, ","),
221
+ KeyboardButton(self.buttonHeight * 5, self.buttonHeight, self.onClickSpace, None, 'keyboard/space.png'),
222
+ KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, "."),
223
+ QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
224
+ KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickEnter, None, 'img/enter.png'),
225
+ QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum)
226
+ ])
227
+ rowList.append(row5)
228
+
229
+ # Add the rows to the KeyboardView
230
+ keyboardView = KeyboardView(rowList)
231
+ container = QWidget()
232
+ container.setLayout(keyboardView)
233
+ self.addWidget(container)
234
+
235
+ ###########################################################################
236
+ # Add the second keyboard layout (uppercase letters)
237
+ def addKeyboardLayout1(self):
238
+ rowList = []
239
+
240
+ # Row 1: Numbers
241
+ # row1 = KeyboardRow([KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, char) for char in '1234567890'])
242
+ # rowList.append(row1)
243
+
244
+ # Row 2: Uppercase QWERTY
245
+ row2 = KeyboardRow([
246
+ QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum),
247
+ *[KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, char) for char in 'QWERTYUIOP'],
248
+ QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum)
249
+ ])
250
+ rowList.append(row2)
251
+
252
+ # Row 3: Uppercase ASDFGHJKL with horizontal stretches
253
+ row3 = KeyboardRow([
254
+ QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum),
255
+ *[KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, char) for char in 'ASDFGHJKL'],
256
+ QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum)
257
+ ])
258
+ rowList.append(row3)
259
+
260
+ # Row 4: Shift, Uppercase ZXC..., Backspace
261
+ row4 = KeyboardRow([
262
+ QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum),
263
+ KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickShift, None, 'img/up.png'),
264
+ QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
265
+ *[KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, char) for char in 'ZXCVBNM'],
266
+ QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
267
+ KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickBack, None, 'img/back.png'),
268
+ QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum)
269
+ ])
270
+ rowList.append(row4)
271
+
272
+ # Row 5: Numbers, Space, Enter
273
+ row5 = KeyboardRow([
274
+ QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum),
275
+ KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickNumbers, None, 'img/numbers.png'),
276
+ QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
277
+ KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, ","),
278
+ KeyboardButton(self.buttonHeight * 5, self.buttonHeight, self.onClickSpace, None, 'img/space.png'),
279
+ KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, "."),
280
+ QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
281
+ KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickEnter, None, 'img/enter.png'),
282
+ QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum)
283
+ ])
284
+ rowList.append(row5)
285
+
286
+ # Add the rows to the KeyboardView
287
+ keyboardView = KeyboardView(rowList)
288
+ container = QWidget()
289
+ container.setLayout(keyboardView)
290
+ self.addWidget(container)
291
+
292
+ ###########################################################################
293
+ # Add the third keyboard layout (numbers and symbols)
294
+ def addKeyboardLayout2(self):
295
+ rowList = []
296
+
297
+ # Row 1: Numbers
298
+ row1 = KeyboardRow([
299
+ QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum),
300
+ *[KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, char) for char in '1234567890'],
301
+ QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum)
302
+ ])
303
+ rowList.append(row1)
304
+
305
+ # Row 2: Symbols
306
+ row2 = KeyboardRow([
307
+ QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum),
308
+ *[KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, char) for char in '@#£&_-()=%'],
309
+ QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum)
310
+ ])
311
+ rowList.append(row2)
312
+
313
+ # Row 3: Symbols with horizontal stretches
314
+ row3 = KeyboardRow([
315
+ QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum),
316
+ KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickSymbols, None, 'img/symbols.png'),
317
+ QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
318
+ *[KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, char) for char in '"*\'/:!?+'],
319
+ QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
320
+ KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickBack, None, 'img/back.png'),
321
+ QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum)
322
+ ])
323
+ rowList.append(row3)
324
+
325
+ # Row 4: Numbers, Space, Enter
326
+ row4 = KeyboardRow([
327
+ QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum),
328
+ KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickLetters, None, 'img/letters.png'),
329
+ QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
330
+ KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, ","),
331
+ KeyboardButton(self.buttonHeight * 5.2, self.buttonHeight, self.onClickSpace, None, 'keyboard/space.png'),
332
+ KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, "."),
333
+ QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
334
+ KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickEnter, None, 'img/enter.png'),
335
+ QSpacerItem(10, 40, QSizePolicy.Expanding, QSizePolicy.Minimum)
336
+ ])
337
+ rowList.append(row4)
338
+
339
+ # Add the rows to the KeyboardView
340
+ keyboardView = KeyboardView(rowList)
341
+ container = QWidget()
342
+ container.setLayout(keyboardView)
343
+ self.addWidget(container)
344
+
345
+ ###########################################################################
346
+ # Add the fourth keyboard layout (additional symbols)
347
+ def addKeyboardLayout3(self):
348
+ rowList = []
349
+
350
+ # Row 1: Extended symbols
351
+ row1 = KeyboardRow([
352
+ QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum),
353
+ *[KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, char) for char in '$€¥¢©®µ~¿¡'],
354
+ QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum)
355
+ ])
356
+ rowList.append(row1)
357
+
358
+ # Row 2: Additional symbols
359
+ row2 = KeyboardRow([
360
+ QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum),
361
+ *[KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, char) for char in '¼½¾[]{}<>^'],
362
+ QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum)
363
+ ])
364
+ rowList.append(row2)
365
+
366
+ # Row 3: Symbols with horizontal stretches
367
+ row3 = KeyboardRow([
368
+ QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum),
369
+ KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickNumbers, None, 'img/numbers.png'),
370
+ QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
371
+ *[KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, char) for char in '`;÷\\∣|¬±'],
372
+ QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
373
+ KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickBack, None, 'img/back.png'),
374
+ QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum)
375
+ ])
376
+ rowList.append(row3)
377
+
378
+ # Row 4: Numbers, Space, Enter
379
+ row4 = KeyboardRow([
380
+ QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum),
381
+ KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickLetters, None, 'img/letters.png'),
382
+ QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
383
+ KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, ","),
384
+ KeyboardButton(self.buttonHeight * 3, self.buttonHeight, self.onClickSpace, None, 'img/space.png'),
385
+ QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
386
+ *[KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, char) for char in '✕§¶°'],
387
+ KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickEnter, None, 'img/enter.png'),
388
+ QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum)
389
+ ])
390
+ rowList.append(row4)
391
+
392
+ # Add the rows to the KeyboardView
393
+ keyboardView = KeyboardView(rowList)
394
+ container = QWidget()
395
+ container.setLayout(keyboardView)
396
+ self.addWidget(container)
397
+
398
+ def setReceiver(self, receiver):
399
+ self.receiver = receiver
400
+
401
+ def getReceiver(self):
402
+ return self.receiver
403
+
404
+ # Callback functions
405
+ def onClickChar(self,keycode):
406
+ # print(f"Key pressed: {keycode}")
407
+ self.receiver.addCharacter(keycode)
408
+
409
+ def onClickShift(self,keycode):
410
+ # print("Shift pressed")
411
+ if self.currentIndex() == 0:
412
+ self.setCurrentIndex(1)
413
+ elif self.currentIndex() == 1:
414
+ self.setCurrentIndex(0)
415
+
416
+ def onClickLetters(self,keycode):
417
+ # print("Letters pressed")
418
+ self.setCurrentIndex(0)
419
+
420
+ def onClickNumbers(self,keycode):
421
+ # print("Numbers pressed")
422
+ self.setCurrentIndex(2)
423
+
424
+ def onClickSymbols(self,keycode):
425
+ # print("Symbols pressed")
426
+ self.setCurrentIndex(3)
427
+
428
+ def onClickBack(self,keycode):
429
+ # print("Backspace pressed")
430
+ self.receiver.backspace()
431
+
432
+ def onClickSpace(self,keycode):
433
+ # print("Space pressed")
434
+ self.receiver.addCharacter(' ')
435
+
436
+ def onClickEnter(self,keycode):
437
+ # print("Enter pressed")
438
+ if self.receiver.field.multiline: self.receiver.addCharacter('\n')
439
+ else: self.onFinished()
easycoder/ec_program.py CHANGED
@@ -22,11 +22,8 @@ class Program:
22
22
  if len(argv) == 0:
23
23
  print('No script supplied')
24
24
  exit()
25
- self.classes=[Core]
25
+ if argv in ['-v', '--version']: return
26
26
  scriptName = argv
27
- if scriptName.endswith('.ecg'):
28
- from .ec_graphics import Graphics
29
- self.classes.append(Graphics)
30
27
 
31
28
  f = open(scriptName, 'r')
32
29
  source = f.read()
@@ -37,19 +34,26 @@ class Program:
37
34
  self.domainIndex = {}
38
35
  self.name = '<anon>'
39
36
  self.code = []
37
+ self.pc = 0
40
38
  self.symbols = {}
41
39
  self.onError = 0
42
- self.pc = 0
43
40
  self.debugStep = False
44
41
  self.stack = []
45
42
  self.script = Script(source)
46
43
  self.compiler = Compiler(self)
47
44
  self.value = self.compiler.value
48
45
  self.condition = self.compiler.condition
49
- self.processClasses()
46
+ self.graphics = None
47
+ self.useClass(Core)
50
48
  self.externalControl = False
49
+ self.ticker = 0
51
50
  self.running = True
52
51
 
52
+ # This is called at 10msec intervals by the GUI code
53
+ def flushCB(self):
54
+ self.ticker += 1
55
+ flush()
56
+
53
57
  def start(self, parent=None, module = None, exports=[]):
54
58
  self.parent = parent
55
59
  self.exports = exports
@@ -57,7 +61,7 @@ class Program:
57
61
  module['child'] = self
58
62
  startCompile = time.time()
59
63
  self.tokenise(self.script)
60
- if self.compiler.compileFrom(0, []):
64
+ if self.compiler.compileFromStart():
61
65
  finishCompile = time.time()
62
66
  s = len(self.script.lines)
63
67
  t = len(self.script.tokens)
@@ -78,7 +82,7 @@ class Program:
78
82
  while True:
79
83
  if self.running == True:
80
84
  flush()
81
- time.sleep(0.1)
85
+ time.sleep(0.01)
82
86
  else:
83
87
  break
84
88
 
@@ -97,25 +101,18 @@ class Program:
97
101
  module = module.replace('/','.').replace('.py','')
98
102
  module = importlib.import_module(module)
99
103
  plugin = getattr(module, args[1])
100
- self.classes.append(plugin)
101
- self.processClasses()
104
+ self.useClass(plugin)
102
105
 
103
- # Process the class list to get the domains
104
- def processClasses(self):
105
- self.domains=[]
106
- for clazz in self.classes:
107
- handler = clazz(self.compiler)
108
- self.domains.append(handler)
109
- self.domainIndex[handler.getName()] = handler
106
+ # Use a specified class
107
+ def useClass(self, clazz):
108
+ handler = clazz(self.compiler)
109
+ self.domains.append(handler)
110
+ self.domainIndex[handler.getName()] = handler
110
111
 
111
112
  # Get the domain list
112
113
  def getDomains(self):
113
114
  return self.domains
114
115
 
115
- # Add a command to the code list
116
- def add(self, command):
117
- self.code.append(command)
118
-
119
116
  def getSymbolRecord(self, name):
120
117
  try:
121
118
  target = self.code[self.symbols[name]]
@@ -127,7 +124,7 @@ class Program:
127
124
 
128
125
  def doValue(self, value):
129
126
  if value == None:
130
- FatalError(self.compiler, f'Undefined value (variable not initialized?)')
127
+ RuntimeError(self, f'Undefined value (variable not initialized?)')
131
128
 
132
129
  result = {}
133
130
  valType = value['type']
@@ -149,17 +146,19 @@ class Program:
149
146
  elif valType == 'symbol':
150
147
  name = value['name']
151
148
  symbolRecord = self.getSymbolRecord(name)
152
- if symbolRecord['value'] == [None]:
153
- RuntimeWarning(self.program, f'Variable "{name}" has no value')
154
- return None
149
+ # if symbolRecord['hasValue']:
155
150
  handler = self.domainIndex[symbolRecord['domain']].valueHandler('symbol')
156
151
  result = handler(symbolRecord)
152
+ # else:
153
+ # # Call the given domain to handle a value
154
+ # # domain = self.domainIndex[value['domain']]
155
+ # handler = domain.valueHandler(value['type'])
156
+ # if handler: result = handler(value)
157
157
  else:
158
158
  # Call the given domain to handle a value
159
159
  domain = self.domainIndex[value['domain']]
160
160
  handler = domain.valueHandler(value['type'])
161
- if handler:
162
- result = handler(value)
161
+ if handler: result = handler(value)
163
162
 
164
163
  return result
165
164
 
@@ -197,10 +196,17 @@ class Program:
197
196
  return ''
198
197
  return None
199
198
 
199
+ def getSymbolContent(self, symbolRecord):
200
+ if len(symbolRecord['value']) == 0:
201
+ return None
202
+ try: return symbolRecord['value'][symbolRecord['index']]
203
+ except: RuntimeError(self, f'Cannot get content of symbol "{symbolRecord["name"]}"')
204
+
200
205
  def getSymbolValue(self, symbolRecord):
201
206
  if len(symbolRecord['value']) == 0:
202
207
  return None
203
- value = symbolRecord['value'][symbolRecord['index']]
208
+ try: value = symbolRecord['value'][symbolRecord['index']]
209
+ except: RuntimeError(self, f'Cannot get value of symbol "{symbolRecord["name"]}"')
204
210
  copy = deepcopy(value)
205
211
  return copy
206
212
 
@@ -285,9 +291,6 @@ class Program:
285
291
  self.parent.waiting = False
286
292
  self.parent.program.run(self.parent.pc)
287
293
 
288
- def flushCB(self):
289
- flush()
290
-
291
294
  # Flush the queue
292
295
  def flush(self, pc):
293
296
  global queue
@@ -314,13 +317,12 @@ class Program:
314
317
  queue = deque()
315
318
  if self.parent != None:
316
319
  self.releaseParent()
317
- else:
318
- self.running = False
319
- break
320
+ self.running = False
321
+ break
320
322
  elif self.pc == None or self.pc == 0 or self.pc >= len(self.code):
321
323
  break
322
324
 
323
- # Run the script
325
+ # Run the script at a given PC value
324
326
  def run(self, pc):
325
327
  global queue
326
328
  item = Object()
@@ -330,6 +332,7 @@ class Program:
330
332
 
331
333
  def kill(self):
332
334
  self.running = False
335
+ if self.parent != None: self.parent.program.kill()
333
336
 
334
337
  def setExternalControl(self):
335
338
  self.externalControl = True
@@ -350,8 +353,10 @@ class Program:
350
353
  return 0
351
354
  v1 = val1['content']
352
355
  v2 = val2['content']
353
- if v1 == None and v2 != None or v1 != None and v2 == None:
354
- return 0
356
+ # if v1 == None and v2 != None or v1 != None and v2 == None:
357
+ # return 0
358
+ if v1 == None and v2 != None: return -1
359
+ elif v2 == None and v1 != None: return 1
355
360
  if v1 != None and val1['type'] == 'int':
356
361
  if not val2['type'] == 'int':
357
362
  if type(v2) is str:
@@ -393,7 +398,7 @@ def Main():
393
398
  if (len(sys.argv) > 1):
394
399
  Program(sys.argv[1]).start()
395
400
  else:
396
- print('Syntax: easycoder <scriptname> [plugins]')
401
+ Program('-v')
397
402
 
398
403
  if __name__ == '__main__':
399
404
  Main()