easycoder 251215.2__py2.py3-none-any.whl → 260111.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.
Files changed (48) hide show
  1. easycoder/__init__.py +4 -3
  2. easycoder/debugger/ec_dbg_value_display copy.py +1 -1
  3. easycoder/debugger/ec_dbg_value_display.py +12 -11
  4. easycoder/debugger/ec_dbg_watchlist.py +146 -12
  5. easycoder/debugger/ec_debug.py +85 -8
  6. easycoder/ec_classes.py +228 -25
  7. easycoder/ec_compiler.py +29 -8
  8. easycoder/ec_core.py +364 -242
  9. easycoder/ec_gclasses.py +20 -9
  10. easycoder/ec_graphics.py +42 -26
  11. easycoder/ec_handler.py +4 -3
  12. easycoder/ec_mqtt.py +248 -0
  13. easycoder/ec_program.py +63 -28
  14. easycoder/ec_psutil.py +1 -1
  15. easycoder/ec_value.py +57 -36
  16. easycoder/pre/README.md +3 -0
  17. easycoder/pre/__init__.py +17 -0
  18. easycoder/pre/debugger/__init__.py +5 -0
  19. easycoder/pre/debugger/ec_dbg_value_display copy.py +195 -0
  20. easycoder/pre/debugger/ec_dbg_value_display.py +24 -0
  21. easycoder/pre/debugger/ec_dbg_watch_list copy.py +219 -0
  22. easycoder/pre/debugger/ec_dbg_watchlist.py +293 -0
  23. easycoder/pre/debugger/ec_debug.py +1014 -0
  24. easycoder/pre/ec_border.py +67 -0
  25. easycoder/pre/ec_classes.py +470 -0
  26. easycoder/pre/ec_compiler.py +291 -0
  27. easycoder/pre/ec_condition.py +27 -0
  28. easycoder/pre/ec_core.py +2772 -0
  29. easycoder/pre/ec_gclasses.py +230 -0
  30. easycoder/pre/ec_graphics.py +1682 -0
  31. easycoder/pre/ec_handler.py +79 -0
  32. easycoder/pre/ec_keyboard.py +439 -0
  33. easycoder/pre/ec_program.py +557 -0
  34. easycoder/pre/ec_psutil.py +48 -0
  35. easycoder/pre/ec_timestamp.py +11 -0
  36. easycoder/pre/ec_value.py +124 -0
  37. easycoder/pre/icons/close.png +0 -0
  38. easycoder/pre/icons/exit.png +0 -0
  39. easycoder/pre/icons/run.png +0 -0
  40. easycoder/pre/icons/step.png +0 -0
  41. easycoder/pre/icons/stop.png +0 -0
  42. easycoder/pre/icons/tick.png +0 -0
  43. {easycoder-251215.2.dist-info → easycoder-260111.1.dist-info}/METADATA +1 -1
  44. easycoder-260111.1.dist-info/RECORD +59 -0
  45. easycoder-251215.2.dist-info/RECORD +0 -31
  46. {easycoder-251215.2.dist-info → easycoder-260111.1.dist-info}/WHEEL +0 -0
  47. {easycoder-251215.2.dist-info → easycoder-260111.1.dist-info}/entry_points.txt +0 -0
  48. {easycoder-251215.2.dist-info → easycoder-260111.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,291 @@
1
+ import sys
2
+ from .ec_classes import FatalError
3
+ from .ec_value import Value
4
+ from .ec_condition import Condition
5
+
6
+ class Compiler:
7
+
8
+ def __init__(self, program):
9
+ self.program = program
10
+ self.value = Value(self)
11
+ self.condition = Condition(self)
12
+ self.marker = 0
13
+ self.script = self.program.script
14
+ self.tokens = self.script.tokens
15
+ self.symbols = self.program.symbols
16
+ self.code = self.program.code
17
+ self.program.compiler = self
18
+ self.compileConstant = self.value.compileConstant
19
+ self.debugCompile = False
20
+ self.valueTypes = {}
21
+
22
+ # Get the current code size. Used during compilation
23
+ def getCodeSize(self):
24
+ return len(self.program.code)
25
+
26
+ # Get the current index (the program counter)
27
+ def getIndex(self):
28
+ return self.index
29
+
30
+ # Move the index along
31
+ def next(self):
32
+ self.index += 1
33
+
34
+ # Get the current token
35
+ def getToken(self):
36
+ if self.index >= len(self.tokens):
37
+ FatalError(self, 'Premature end of script')
38
+ return self.tokens[self.index].token
39
+
40
+ # Get the next token
41
+ def nextToken(self):
42
+ self.index += 1
43
+ return self.getToken()
44
+
45
+ # Peek ahead to see the next token without advancing the index
46
+ def peek(self):
47
+ try:
48
+ return self.tokens[self.index + 1].token
49
+ except:
50
+ return None
51
+
52
+ # Get a constant
53
+ def getConstant(self, token):
54
+ self.index += 1
55
+ return self.compileConstant(token)
56
+
57
+ # Get a value
58
+ def getValue(self):
59
+ self.program.ensureNotRunning()
60
+ return self.value.compileValue()
61
+
62
+ # Get the next value
63
+ def nextValue(self):
64
+ self.program.ensureNotRunning()
65
+ self.index += 1
66
+ return self.value.compileValue()
67
+
68
+ # Get a condition
69
+ def getCondition(self):
70
+ return self.condition.compileCondition()
71
+
72
+ # Get the next condition
73
+ def nextCondition(self):
74
+ self.index += 1
75
+ return self.condition.compileCondition()
76
+
77
+ # Test if the current token has a specified value
78
+ def tokenIs(self, value):
79
+ return self.getToken() == value
80
+
81
+ # Test if the next token has the specified value
82
+ def nextIs(self, value):
83
+ return self.nextToken() == value
84
+
85
+ # Get the command at a given pc in the code list
86
+ def getCommandAt(self, pc):
87
+ return self.program.code[pc]
88
+
89
+ # Add a command to the code list
90
+ def addCommand(self, command, debug=True):
91
+ command['debug'] = debug
92
+ command['bp'] = False
93
+ self.code.append(command)
94
+
95
+ # Test if the current token is a symbol
96
+ def isSymbol(self):
97
+ token = self.getToken()
98
+ try:
99
+ self.symbols[token]
100
+ except:
101
+ return False
102
+ return True
103
+
104
+ # Test if the next token is a symbol
105
+ def nextIsSymbol(self):
106
+ self.next()
107
+ return self.isSymbol()
108
+
109
+ # Skip the next token if it matches the value given
110
+ def skip(self, token):
111
+ next = self.peek()
112
+ if type(token) == list:
113
+ for item in token:
114
+ if next == item:
115
+ self.nextToken()
116
+ return
117
+ elif next == token:
118
+ self.nextToken()
119
+
120
+ # Skip common articles (optional syntactic noise for readability/disambiguation)
121
+ # Consumes leading articles ('the', 'a', 'an') at the next position
122
+ def skipArticles(self):
123
+ # Consume leading articles at next position(s) — like skip() but for multiple
124
+ while True:
125
+ next_tok = self.peek()
126
+ if next_tok in ['the', 'a', 'an']:
127
+ self.nextToken()
128
+ else:
129
+ break
130
+
131
+ # Rewind to a given position in the code list
132
+ def rewindTo(self, index):
133
+ self.index = index
134
+
135
+ # Get source line number containing the current token
136
+ def getLino(self):
137
+ if self.index >= len(self.tokens):
138
+ return 0
139
+ return self.tokens[self.index].lino
140
+
141
+ # Issue a warning
142
+ def warning(self, message):
143
+ self.warnings.append(f'Warning at line {self.getLino() + 1} of {self.program.name}: {message}')
144
+
145
+ # Print all warnings
146
+ def showWarnings(self):
147
+ for warning in self.warnings:
148
+ print(warning)
149
+
150
+ # Get the symbol record for the current token (assumes it is a symbol name)
151
+ def getSymbolRecord(self, name=None):
152
+ self.program.ensureNotRunning()
153
+ if name == None: name = self.getToken()
154
+ if not name in self.symbols:
155
+ FatalError(self, f'Undefined symbol name "{name}"')
156
+ return None
157
+ symbol = self.symbols[name]
158
+ if symbol == None: return None
159
+ record = self.code[symbol]
160
+ record['used'] = True
161
+ return record
162
+
163
+ # Add a value type
164
+ def addValueType(self):
165
+ name = self.peek()
166
+ record = None
167
+ try:
168
+ record = self.symbols[name]
169
+ except:
170
+ pass
171
+ if record != None:
172
+ raise FatalError(self, f'Duplicate symbol name "{name}"')
173
+ self.valueTypes[name] = True
174
+
175
+ # Test if a given value is in the value types list
176
+ def hasValue(self, type):
177
+ return type in self.valueTypes
178
+
179
+ # Instantiate an object of the given class name
180
+ def instantiate(self, classname):
181
+ # Search through all loaded modules for the class
182
+ items = sys.modules.items()
183
+ for module_name, module in items:
184
+ if module is None:
185
+ continue
186
+ try:
187
+ if hasattr(module, classname):
188
+ cls = getattr(module, classname)
189
+ # Verify it's actually a class
190
+ if isinstance(cls, type):
191
+ # Attempt to instantiate
192
+ try:
193
+ return cls()
194
+ except TypeError as ex:
195
+ raise FatalError(self, f"Object instantiation error: {ex}")
196
+ except Exception:
197
+ continue
198
+ return None
199
+
200
+ # Compile a variable
201
+ def compileVariable(self, command, classname):
202
+ return self.compileSymbol(command, self.nextToken(), classname)
203
+
204
+ # Compile a symbol
205
+ def compileSymbol(self, command, name, classname):
206
+ # try:
207
+ # self.symbols[name]
208
+ # raise FatalError(self, f'Duplicate symbol name "{name}"')
209
+ # except: pass
210
+ command['name'] = name
211
+ command['classname'] = classname
212
+ command['program'] = self.program
213
+ command['used'] = False
214
+ self.symbols[name] = self.getCodeSize()
215
+ if classname != ':':
216
+ object = self.instantiate(classname)
217
+ command['object'] = object
218
+ if object != None:
219
+ command['type'] = 'symbol'
220
+ object.setName(name) # type: ignore
221
+ self.addCommand(command, False)
222
+ return True
223
+
224
+ # Compile a program label (a symbol ending with ':')
225
+ def compileLabel(self, command):
226
+ return self.compileSymbol(command, self.getToken(), ':')
227
+
228
+ # Compile the current token
229
+ def compileToken(self):
230
+ self.warnings = []
231
+ token = self.getToken()
232
+ # print(f'Compile {token}')
233
+ if not token:
234
+ return False
235
+ if len(self.code) == 0:
236
+ if self.program.parent == None and self.program.graphics:
237
+ cmd = {'domain': 'graphics', 'keyword': 'init'}
238
+ self.code.append(cmd)
239
+ mark = self.getIndex()
240
+ for domain in self.program.getDomains():
241
+ handler = domain.keywordHandler(token)
242
+ if handler:
243
+ command = {}
244
+ command['domain'] = domain.getName()
245
+ command['lino'] = self.tokens[self.index].lino
246
+ command['keyword'] = token
247
+ result = handler(command)
248
+ if result:
249
+ return result
250
+ else:
251
+ self.rewindTo(mark)
252
+ else:
253
+ self.rewindTo(mark)
254
+ FatalError(self, f'Unable to compile this "{token}" command')
255
+
256
+ # Compile a single command
257
+ def compileOne(self):
258
+ keyword = self.getToken()
259
+ if not keyword:
260
+ return False
261
+ # print(f'Compile keyword "{keyword}"')
262
+ if keyword.endswith(':'):
263
+ command = {}
264
+ command['domain'] = None
265
+ command['lino'] = self.tokens[self.index].lino
266
+ return self.compileLabel(command)
267
+ else:
268
+ return self.compileToken()
269
+
270
+ # Compile the script
271
+ def compileFrom(self, index, stopOn):
272
+ self.index = index
273
+ while True:
274
+ token = self.tokens[self.index]
275
+ if self.debugCompile: print(f'{token.lino + 1}: {self.script.lines[token.lino]}')
276
+ if self.compileOne() == True:
277
+ if self.index == len(self.tokens) - 1:
278
+ return True
279
+ token = self.nextToken()
280
+ if token in stopOn:
281
+ return True
282
+ else:
283
+ return False
284
+
285
+ # Compile fom the current location, stopping on any of a list of tokens
286
+ def compileFromHere(self, stopOn):
287
+ return self.compileFrom(self.getIndex(), stopOn)
288
+
289
+ # Compile from the start of the script
290
+ def compileFromStart(self):
291
+ return self.compileFrom(0, [])
@@ -0,0 +1,27 @@
1
+ class Condition:
2
+
3
+ def __init__(self, compiler):
4
+ self.compiler = compiler
5
+ self.getToken = compiler.getToken
6
+ self.nextToken = compiler.nextToken
7
+ self.peek = compiler.peek
8
+ self.getIndex = compiler.getIndex
9
+ self.tokenIs = compiler.tokenIs
10
+ self.rewindTo = compiler.rewindTo
11
+ self.program = compiler.program
12
+ self.negate = False
13
+
14
+ def compileCondition(self):
15
+ mark = self.getIndex()
16
+ for domain in self.compiler.program.getDomains():
17
+ condition = domain.compileCondition()
18
+ if condition != None:
19
+ condition.domain = domain.getName()
20
+ return condition
21
+ self.rewindTo(mark)
22
+ return None
23
+
24
+ def testCondition(self, condition):
25
+ handler = self.program.domainIndex[condition.domain]
26
+ handler = handler.conditionHandler(condition.type)
27
+ return handler(condition)