Skip to content

Commit 716685d

Browse files
committedOct 29, 2022
Development of Python version
1 parent 2c60cae commit 716685d

24 files changed

+606
-736
lines changed
 

‎py/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ This class contans compiler and runtime modules for core keywords, values and co
3131
- a `compileCondition()` function to compile 'conditions'
3232
- a `c_xxx()` function to evaluate each runtime 'condition'
3333

34-
Each extension package has the same structure and deals with its own vocabulary and syntax.
34+
Each extension package has the same structure and deals with its own vocabulary and syntax. For example, `ec_graphics.py`, which is currently under development.
3535

3636
The individual compiler functions make heavy use of the Compiler class to retrieve tokens and process them. When they successfully complete the compilation of any given language structure they return an 'intermediate code' object with some standard fields such as the name of the package (the 'domain'), the script line number, and other fields that relate to the specific keyword, value or condition. This object goes into the array that becomes the program to be run.
3737

‎py/benchmark.ecs‎

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,49 +14,49 @@
1414

1515
!go to Skip
1616

17-
print `FOR loop counting to 10,000`
17+
print `FOR loop counting to 100,000`
1818
put now into Start
1919
put 0 into N
20-
while N is less than 10000 increment N
20+
while N is less than 100000 increment N
2121
put now into Finish
2222
take Start from Finish giving N
23-
print N cat ` milliseconds`
23+
print N cat ` seconds`
2424

2525
! debug step
2626

27-
print `Compare 10,000 long integers for equality`
27+
print `Compare 100,000 long integers for equality`
2828
put now into Start
2929
put 0 into N
30-
while N is less than 10000
30+
while N is less than 100000
3131
begin
3232
if N is 1234567890 begin end
3333
increment N
3434
end
3535
put now into Finish
3636
take Start from Finish giving N
37-
print N cat ` milliseconds`
37+
print N cat ` seconds`
3838

39-
print `Allocate and initialize a 10,000 element array`
39+
print `Allocate and initialize a 100,000 element array`
4040
put now into Start
41-
set the elements of Array to 10000
41+
set the elements of Array to 100000
4242
put 0 into N
43-
while N is less than 10000
43+
while N is less than 100000
4444
begin
4545
index Array to N
4646
put N into Array
4747
increment N
4848
end
4949
put now into Finish
5050
take Start from Finish giving N
51-
print N cat ` milliseconds`
51+
print N cat ` seconds`
5252

53-
print `Allocate and initialize a 50x50 dictionary`
53+
print `Allocate and initialize a 200x5200 dictionary`
5454
put now into Start
5555
put 0 into N
56-
while N is less than 50
56+
while N is less than 200
5757
begin
5858
put 0 into M
59-
while M is less than 50
59+
while M is less than 200
6060
begin
6161
put M into Dictionary as N cat ` ` cat M
6262
increment M
@@ -65,7 +65,7 @@
6565
end
6666
put now into Finish
6767
take Start from Finish giving N
68-
print N cat ` milliseconds`
68+
print N cat ` seconds`
6969

7070
put 20 into Y
7171
put 6 into X
@@ -112,7 +112,7 @@
112112
put 51 into N
113113
while N is less than 54
114114
begin
115-
if 52 is greater than N print `52 is greater than ` cat N else print `52 is not greater than cat N
115+
if 52 is greater than N print `52 is greater than ` cat N else print `52 is not greater than ` cat N
116116
if 52 is less than N print `52 is less than ` cat N else print `52 is not less than ` cat N
117117
if 52 is not greater than N print `52 is not greater than ` cat N else print `52 is greater than ` cat N
118118
if 52 is not less than N print `52 is not less than ` cat N else print `52 is less than ` cat N
@@ -128,16 +128,16 @@ Loop1:
128128
add 1 to N
129129
if N is less than 10 go to Loop1
130130

131-
open File `/home/pi/test.txt` for writing
131+
open File `test.txt` for writing
132132
write line `Hello, world!` to File
133133
close File
134-
open File `/home/pi/test.txt` for appending
134+
open File `test.txt` for appending
135135
write `I'm back!` to File
136136
close File
137137

138138
Skip:
139139
wait 2 seconds
140-
open File `/home/pi/test.txt` for reading
140+
open File `test.txt` for reading
141141
read line X from File
142142
print X
143143
read X from File

‎py/config‎

Lines changed: 0 additions & 14 deletions
This file was deleted.

‎py/dhcpcd.conf‎

Lines changed: 0 additions & 58 deletions
This file was deleted.

‎py/easycoder.py‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,14 @@ class EasyCoder:
99
def __init__(self):
1010
self.version = 1
1111

12-
domainMap = {}
13-
domainMap['core'] = Core
14-
1512
if (len(sys.argv) > 1):
1613
scriptName = sys.argv[1]
1714

1815
f = open(scriptName, 'r')
1916
source = f.read()
2017
f.close()
2118

22-
Program(source, domainMap)
19+
Program(source, [Core])
2320

2421
if __name__ == '__main__':
2522
EasyCoder()

‎py/ec_autogui.py‎

Lines changed: 0 additions & 126 deletions
This file was deleted.

‎py/ec_classes.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ def __init__(self, compiler, message):
66
class RuntimeError:
77
def __init__(self, message):
88
print(f'Runtime Error: {message}')
9+
quit()
910

1011
class Script:
1112
def __init__(self, source):

‎py/ec_compiler.py‎

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from ec_classes import Token, FatalError
1+
from ec_classes import FatalError
22
from ec_value import Value
33
from ec_condition import Condition
44

@@ -56,7 +56,6 @@ def nextValue(self):
5656

5757
# Get a constant
5858
def getConstant(self, token):
59-
self.index += 1
6059
return self.value.compileConstant(token)
6160

6261
# Get a condition
@@ -108,21 +107,26 @@ def showWarnings(self):
108107
print(f'Line {self.getLino() + 1}: {warning}')
109108

110109
def getSymbolRecord(self):
111-
symbolRecord = self.code[self.symbols[self.getToken()]]
112-
symbolRecord['used'] = True
113-
return symbolRecord
110+
token = self.getToken()
111+
symbol = self.symbols[token]
112+
if symbol != None:
113+
symbolRecord = self.code[symbol]
114+
symbolRecord['used'] = True
115+
return symbolRecord
116+
return None
114117

115118
def compileLabel(self, command):
116-
return self.compileSymbol(command, self.getToken(), False)
119+
return self.compileSymbol(command, 'label', self.getToken(), False)
117120

118-
def compileVariable(self, command, valueHolder):
119-
return self.compileSymbol(command, self.nextToken(), valueHolder)
121+
def compileVariable(self, command, type, valueHolder):
122+
return self.compileSymbol(command, type, self.nextToken(), valueHolder)
120123

121-
def compileSymbol(self, command, name, valueHolder):
124+
def compileSymbol(self, command, type, name, valueHolder):
122125
if hasattr(self.symbols, name):
123126
FatalError(self, f'{self.code[self.pc].lino}: Duplicate symbol name "{name}"')
124127
return False
125128
self.symbols[name] = self.getPC()
129+
command['type'] = type
126130
command['isSymbol'] = True
127131
command['used'] = False
128132
command['valueHolder'] = valueHolder
@@ -150,8 +154,8 @@ def compileToken(self):
150154
command['keyword'] = token
151155
command['debug'] = True
152156
result = handler(command)
153-
return result
154-
else:
157+
if result:
158+
return result
155159
self.rewind()
156160
FatalError(self, f'No handler found for "{token}"')
157161
return False
@@ -161,7 +165,7 @@ def compileOne(self):
161165
keyword = self.getToken()
162166
if not keyword:
163167
return False
164-
#print(f'Compile keyword "{keyword}"')
168+
# print(f'Compile keyword "{keyword}"')
165169
if keyword.endswith(':'):
166170
command = {}
167171
command['domain'] = None
@@ -176,8 +180,6 @@ def compileFrom(self, index, stopOn):
176180
while True:
177181
token = self.tokens[self.index]
178182
keyword = token.token
179-
# line = self.script.lines[token.lino]
180-
# print(f'{keyword} - {line}')
181183
if keyword != 'else':
182184
if self.compileOne() == True:
183185
if self.index == len(self.tokens) - 1:

‎py/ec_condition.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ def compileCondition(self):
2121
return None
2222

2323
def testCondition(self, condition):
24-
handler = self.program.domainList[condition['domain']]
24+
handler = self.program.domainIndex[condition['domain']]
2525
handler = handler.conditionHandler(condition['type'])
26-
return handler(condition)
26+
return handler(condition)

‎py/ec_core.py‎

Lines changed: 80 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import json, math, hashlib, threading, os, requests, time
1+
import json, math, hashlib, threading, os, requests, time, numbers
22
from datetime import datetime, timezone
33
from random import randrange
44
from ec_classes import FatalError, RuntimeError
@@ -124,7 +124,7 @@ def r_clear(self, command):
124124
val['type'] = 'boolean'
125125
val['content'] = False
126126
self.putSymbolValue(target, val)
127-
self.add(command)
127+
# self.add(command)
128128
return self.nextPC()
129129

130130
def k_close(self, command):
@@ -173,7 +173,7 @@ def r_decrement(self, command):
173173
return self.incdec(command, '-')
174174

175175
def k_dictionary(self, command):
176-
return self.compileVariable(command, False)
176+
return self.compileVariable(command, 'dictionary', False)
177177

178178
def r_dictionary(self, command):
179179
return self.nextPC()
@@ -245,10 +245,10 @@ def k_exit(self, command):
245245
return True
246246

247247
def r_exit(self, command):
248-
return 0
248+
return -1
249249

250250
def k_file(self, command):
251-
return self.compileVariable(command, False)
251+
return self.compileVariable(command, 'file', False)
252252

253253
def r_file(self, command):
254254
return self.nextPC()
@@ -561,6 +561,7 @@ def r_print(self, command):
561561
if value != None:
562562
print(f'-> {value}')
563563
return self.nextPC()
564+
return False
564565

565566
def k_put(self, command):
566567
command['value'] = self.nextValue()
@@ -621,17 +622,20 @@ def k_read(self, command):
621622
else:
622623
command['line'] = False
623624
if self.nextIsSymbol():
624-
symbolRecord = self.getSymbolRecord()
625-
if symbolRecord['valueHolder']:
626-
if self.peek() == 'from':
627-
self.nextToken()
628-
if self.nextIsSymbol():
629-
fileRecord = self.getSymbolRecord()
630-
if fileRecord['keyword'] == 'file':
631-
command['target'] = symbolRecord['name']
632-
command['file'] = fileRecord['name']
633-
self.add(command)
634-
return True
625+
symbolRecord = self.getSymbolRecord()
626+
if symbolRecord['valueHolder']:
627+
if self.peek() == 'from':
628+
self.nextToken()
629+
if self.nextIsSymbol():
630+
fileRecord = self.getSymbolRecord()
631+
if fileRecord['keyword'] == 'file':
632+
command['target'] = symbolRecord['name']
633+
command['file'] = fileRecord['name']
634+
self.add(command)
635+
return True
636+
FatalError(self.program.compiler, f'Symbol "{symbolRecord["name"]}" is not a value holder')
637+
return False
638+
FatalError(self.program.compiler, f'Symbol "{self.getToken()}" has not been declared')
635639
return False
636640

637641
def r_read(self, command):
@@ -781,13 +785,58 @@ def r_set(self, command):
781785
self.putSymbolValue(target, val)
782786
return self.nextPC()
783787

788+
def k_split(self, command):
789+
if self.nextIsSymbol():
790+
symbolRecord = self.getSymbolRecord()
791+
if symbolRecord['valueHolder']:
792+
command['target'] = symbolRecord['name']
793+
command['on'] = '\n'
794+
if self.peek() == 'on':
795+
self.nextToken()
796+
command['on'] = self.getValue()
797+
self.add(command)
798+
return True
799+
return False
800+
801+
def r_split(self, command):
802+
target = self.getVariable(command['target'])
803+
value = self.getSymbolValue(target)
804+
content = value['content'].split(command['on'])
805+
elements = len(content)
806+
target['elements'] = elements
807+
target['value'] = [None] * elements
808+
809+
for index, item in enumerate(content):
810+
element = {}
811+
element['type'] = 'text'
812+
element['numeric'] = 'false'
813+
element['content'] = item
814+
target['value'][index] = element
815+
816+
return self.nextPC()
817+
784818
def k_stop(self, command):
785819
self.add(command)
786820
return True
787821

788822
def r_stop(self, command):
789823
return 0
790824

825+
def k_system(self, command):
826+
value = self.nextValue()
827+
if value != None:
828+
command['value'] = value
829+
self.add(command)
830+
return True
831+
FatalError(self.program.compiler, 'I can\'t give this command')
832+
return False
833+
834+
def r_system(self, command):
835+
value = self.getRuntimeValue(command['value'])
836+
if value != None:
837+
os.system(value)
838+
return self.nextPC()
839+
791840
def k_take(self, command):
792841
# Get the (first) value
793842
command['value1'] = self.nextValue()
@@ -862,17 +911,19 @@ def r_toggle(self, command):
862911
val['type'] = 'boolean'
863912
val['content'] = not value['content']
864913
self.putSymbolValue(target, val)
865-
self.add(command)
866914
return self.nextPC()
867915

868916
def k_variable(self, command):
869-
return self.compileVariable(command, True)
917+
return self.compileVariable(command, 'variable', True)
870918

871919
def r_variable(self, command):
872920
return self.nextPC()
873921

874922
def k_wait(self, command):
875-
command['value'] = self.nextValue()
923+
value = self.nextValue()
924+
if value is None:
925+
return False
926+
command['value'] = value
876927
multipliers = {}
877928
multipliers['milli'] = 1
878929
multipliers['millis'] = 1
@@ -881,7 +932,7 @@ def k_wait(self, command):
881932
multipliers['second'] = 1000
882933
multipliers['seconds'] = 1000
883934
multipliers['minute'] = 60000
884-
multipliers['minutes7'] = 60000
935+
multipliers['minutes'] = 60000
885936
command['multiplier'] = multipliers['second']
886937
token = self.peek()
887938
if token in multipliers:
@@ -1379,15 +1430,13 @@ def v_property(self, v):
13791430
target = self.getVariable(v['target'])
13801431
target = self.getSymbolValue(target)
13811432
content = target['content']
1382-
if content == '':
1383-
content = ''
1384-
content['name'] = '(anon)'
1433+
val = content.get(name)
13851434
value = {}
1386-
value['type'] = 'text'
1387-
if content.get(name):
1388-
value['content'] = content[name]
1435+
value['content'] = val
1436+
if isinstance(v, numbers.Number):
1437+
value['type'] = 'int'
13891438
else:
1390-
value['content'] = ''
1439+
value['type'] = 'text'
13911440
return value
13921441

13931442
def v_random(self, v):
@@ -1572,7 +1621,10 @@ def c_includes(self, condition):
15721621

15731622
def c_empty(self, condition):
15741623
value = self.getRuntimeValue(condition['value1'])
1575-
comparison = len(value) == 0
1624+
if value == None:
1625+
comparison = True
1626+
else:
1627+
comparison = len(value) == 0
15761628
return not comparison if condition['negate'] else comparison
15771629

15781630
def c_exists(self, condition):

‎py/ec_graphics.py‎

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
from ec_classes import FatalError, RuntimeError
2+
from ec_handler import Handler
3+
from graphson import createScreen, renderSpec, renderScreen, getElement, closeScreen, setOnClick
4+
5+
class Graphics(Handler):
6+
7+
def __init__(self, compiler):
8+
Handler.__init__(self, compiler)
9+
10+
def getName(self):
11+
return 'graphics'
12+
13+
#############################################################################
14+
# Keyword handlers
15+
16+
def k_attach(self, command):
17+
if self.nextIsSymbol():
18+
record = self.getSymbolRecord()
19+
command['name'] = record['name']
20+
if self.nextIs('to'):
21+
value = self.nextValue()
22+
command['id'] = value
23+
self.add(command)
24+
return True
25+
26+
def r_attach(self, command):
27+
target = self.getVariable(command['name'])
28+
id = self.getRuntimeValue(command['id'])
29+
element = getElement(id)
30+
if element == None:
31+
FatalError(self.program.compiler, f'There is no screen element with id \'{self.getToken()}\'')
32+
self.putSymbolValue(target, {'type': 'text', 'content': id})
33+
return self.nextPC()
34+
35+
def k_close(self, command):
36+
if self.nextToken() == 'screen':
37+
self.add(command)
38+
return True
39+
40+
def r_close(self, command):
41+
closeScreen(self.screen)
42+
self.screen = None
43+
return self.nextPC()
44+
45+
def k_create(self, command):
46+
if self.nextToken() == 'screen':
47+
self.add(command)
48+
return True
49+
return False
50+
51+
def r_create(self, command):
52+
self.screen = createScreen()
53+
return self.nextPC()
54+
55+
def k_label(self, command):
56+
return self.compileVariable(command, 'label', False)
57+
58+
def r_label(self, command):
59+
return self.nextPC()
60+
61+
def k_on(self, command):
62+
token = self.nextToken()
63+
if token == 'click':
64+
command['event'] = token
65+
if self.peek() == 'in':
66+
self.nextToken()
67+
if self.nextIs('screen'):
68+
command['target'] = None
69+
elif self.isSymbol():
70+
target = self.getSymbolRecord()
71+
command['target'] = target['name']
72+
else:
73+
FatalError(self.program.compiler, f'{self.getToken()} is not a screen element')
74+
return False
75+
command['goto'] = self.getPC() + 2
76+
self.add(command)
77+
self.nextToken()
78+
pcNext = self.getPC()
79+
cmd = {}
80+
cmd['domain'] = 'core'
81+
cmd['lino'] = command['lino']
82+
cmd['keyword'] = 'gotoPC'
83+
cmd['goto'] = 0
84+
cmd['debug'] = False
85+
self.addCommand(cmd)
86+
self.compileOne()
87+
# Fixup the link
88+
self.getCommandAt(pcNext)['goto'] = self.getPC()
89+
return True
90+
return False
91+
92+
def r_on(self, command):
93+
event = command['event']
94+
if event == 'click':
95+
target = command['target']
96+
if target == None:
97+
value = 'screen'
98+
else:
99+
widget = self.getVariable(target)
100+
value = widget['value'][widget['index']]
101+
pc = command['goto']
102+
setOnClick(value['content'], lambda: self.run(pc))
103+
return self.nextPC()
104+
105+
def k_rectangle(self, command):
106+
return self.compileVariable(command, 'rectangle', False)
107+
108+
def r_rectangle(self, command):
109+
return self.nextPC()
110+
111+
def k_render(self, command):
112+
if self.nextIs('screen'):
113+
command['name'] = None
114+
self.add(command)
115+
return True
116+
elif self.isSymbol():
117+
record = self.getSymbolRecord()
118+
name = record['name']
119+
type = record['type']
120+
command['type'] = type
121+
if type == 'variable':
122+
command['name'] = name
123+
if self.peek() == 'in':
124+
if self.nextIsSymbol():
125+
record = self.getSymbolRecord()
126+
type = record['type']
127+
name = record['name']
128+
if type in ['rectangle', 'ellipse']:
129+
command['parent'] = record['name']
130+
self.add(command)
131+
return True
132+
else:
133+
self.warning(f'{name} cannot be a parent of another element')
134+
return False
135+
command['parent'] = 'screen'
136+
self.add(command)
137+
return True
138+
FatalError(self.program.compiler, f'This variable type cannot be rendered')
139+
return False
140+
FatalError(self.program.compiler, 'Nothing specified to render')
141+
return False
142+
143+
def r_render(self, command):
144+
if command['name'] == None:
145+
renderScreen(self.screen)
146+
else:
147+
variable = self.getVariable(command['name'])
148+
spec = self.getRuntimeValue(variable)
149+
offset = {'dx': 0, 'dy': 0}
150+
result = renderSpec(self.screen, spec, offset)
151+
if result != None:
152+
RuntimeError(f'Rendering error: {result}')
153+
return self.nextPC()
154+
155+
#############################################################################
156+
# Compile a value in this domain
157+
def compileValue(self):
158+
value = {}
159+
value['domain'] = 'graphics'
160+
if self.tokenIs('the'):
161+
self.nextToken()
162+
token = self.getToken()
163+
if token == 'xxxxx':
164+
return value
165+
166+
return None
167+
168+
#############################################################################
169+
# Modify a value or leave it unchanged.
170+
def modifyValue(self, value):
171+
return value
172+
173+
#############################################################################
174+
# Value handlers
175+
176+
def v_xxxxx(self, v):
177+
value = {}
178+
return value
179+
180+
#############################################################################
181+
# Compile a condition
182+
def compileCondition(self):
183+
condition = {}
184+
return condition
185+
186+
#############################################################################
187+
# Condition handlers

‎py/ec_handler.py‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,18 @@ def keywordHandler(self, name):
4949

5050
# Get a run handler
5151
def runHandler(self, name):
52-
return getattr(self, f'r_{name}')
52+
if hasattr(self, f'r_{name}'):
53+
return getattr(self, f'r_{name}')
54+
return None
5355

5456
# Get a value handler
5557
def valueHandler(self, name):
56-
return getattr(self, f'v_{name}')
58+
if hasattr(self, f'v_{name}'):
59+
return getattr(self, f'v_{name}')
60+
return None
5761

5862
# Get a condition handler
5963
def conditionHandler(self, name):
60-
return getattr(self, f'c_{name}')
64+
if hasattr(self, f'c_{name}'):
65+
return getattr(self, f'c_{name}')
66+
return None

‎py/ec_program.py‎

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66

77
class Program:
88

9-
def __init__(self, source, domainMap):
9+
def __init__(self, source, domains):
1010

11-
self.domainMap = domainMap
12-
self.domainList = {}
1311
self.domains = []
12+
self.domainIndex = {}
1413
self.name = '<anon>'
1514
self.code = []
1615
self.symbols = {}
@@ -22,13 +21,10 @@ def __init__(self, source, domainMap):
2221
self.compiler = Compiler(self)
2322
self.value = self.compiler.value
2423
self.condition = self.compiler.condition
25-
for name in domainMap:
26-
if name[0] != '_':
27-
domain = domainMap[name](self.compiler)
28-
self.domains.append(domain)
29-
self.domainList = {}
30-
for domain in self.domains:
31-
self.domainList[domain.getName()] = domain
24+
for domain in domains:
25+
handler = domain(self.compiler)
26+
self.domains.append(handler)
27+
self.domainIndex[handler.getName()] = handler
3228
self.queue = deque()
3329

3430
startCompile = time.time()
@@ -78,17 +74,24 @@ def doValue(self, value):
7874
content += val
7975
result['type'] = 'text'
8076
result['content'] = content
81-
elif valType == 'symbol':
82-
name = value['name']
83-
symbolRecord = self.getSymbolRecord(name)
84-
if symbolRecord['value'] == [None]:
77+
# elif valType == 'symbol':
78+
# name = value['name']
79+
# symbolRecord = self.getSymbolRecord(name)
80+
# if symbolRecord['value'] == [None]:
81+
# RuntimeError(f'Variable "{name}" has no value')
82+
# return None
83+
# handler = self.domainIndex[symbolRecord['domain']].valueHandler('symbol')
84+
# result = handler(symbolRecord)
85+
elif value['isSymbol']:
86+
if value['value'] == [None]:
87+
name = value['name']
8588
RuntimeError(f'Variable "{name}" has no value')
8689
return None
87-
handler = self.domainList[symbolRecord['domain']].valueHandler('symbol')
88-
result = handler(symbolRecord)
90+
handler = self.domainIndex[value['domain']].valueHandler('symbol')
91+
result = handler(value)
8992
else:
9093
# Call the given domain to handle a value
91-
domain = self.domainList[value['domain']]
94+
domain = self.domainIndex[value['domain']]
9295
handler = domain.valueHandler(value['type'])
9396
if handler:
9497
result = handler(value)
@@ -203,7 +206,7 @@ def run(self, pc):
203206
lino = command['lino'] + 1
204207
line = self.script.lines[command['lino']].strip()
205208
print(f'{self.name}: Line {lino}: PC: {self.pc} {domainName}:{keyword}: {line}')
206-
domain = self.domainList[domainName]
209+
domain = self.domainIndex[domainName]
207210
handler = domain.runHandler(keyword)
208211
if handler:
209212
self.pc = handler(self.code[self.pc])

‎py/ec_timestamp.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import pytz, time
1+
import pytz
22
from datetime import datetime
33

44
def getTimestamp(t):

‎py/ec_value.py‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def compileValue(self):
5858
token = self.getToken()
5959
item = self.getItem()
6060
if item == None:
61-
FatalError(self.compiler, f'Cannot get the value of "{token}"')
61+
self.warning(f'Cannot get the value of "{token}"')
6262
return None
6363

6464
value = {}
@@ -75,16 +75,18 @@ def compileValue(self):
7575
else:
7676
value = item
7777

78-
# See if any domain has something to add to the value
78+
# See if any domain has something to add to the value
7979
for domain in self.domains:
8080
value = domain.modifyValue(value)
8181

8282
return value
8383

8484
def compileConstant(self, token):
8585
value = {}
86-
if token.isnumeric():
86+
if isinstance(token, str):
8787
val = eval(token)
88+
else:
89+
val = token
8890
if isinstance(val, int):
8991
value['type'] = 'int'
9092
value['content'] = val

‎py/getaddr-eth0.ecs‎

Lines changed: 0 additions & 65 deletions
This file was deleted.

‎py/getaddr-wlan0.ecs‎

Lines changed: 0 additions & 64 deletions
This file was deleted.

‎py/getaddr.ecs‎

Lines changed: 0 additions & 63 deletions
This file was deleted.

‎py/getip.ecs‎

Lines changed: 0 additions & 36 deletions
This file was deleted.

‎py/graphson.py‎

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
import tkinter as tk
2+
import json
3+
4+
elements = {}
5+
zlist = []
6+
7+
def createScreen():
8+
global dx, dy, running
9+
running = True
10+
screen = tk.Tk()
11+
# screen.attributes('-fullscreen', True)
12+
13+
screen.overrideredirect(True)
14+
w = 600
15+
h = 800
16+
# x = int((screen.winfo_screenwidth() / 2) - (w / 2))
17+
dx = int(screen.winfo_screenwidth() - w)
18+
dy = int((screen.winfo_screenheight() / 2) - (h / 2))
19+
geometry = str(w) + 'x' + str(h) + '+' + str(dx) + '+' + str(dy)
20+
screen.geometry(geometry)
21+
22+
screen.bind('<Button-1>', onClick)
23+
return screen
24+
25+
def setOnClick(id, cb):
26+
global elements
27+
if id in elements:
28+
elements[id]['cb'] = cb
29+
else:
30+
RuntimeError(f'Element \'{id}\' does not exist')
31+
return
32+
33+
def onClick(event):
34+
global dx, dy, zlist
35+
x = event.x_root
36+
y = event.y_root
37+
# print('Clicked at : '+ str(x) +","+ str(y))
38+
for i in range(1, len(zlist) + 1):
39+
element = zlist[-i]
40+
id = list(element)[0]
41+
values = element[id]
42+
x1 = dx + values['left']
43+
x2 = x1 + values['width']
44+
y1 = dy + values['top']
45+
y2 = y1 + values['height']
46+
if x >= x1 and x < x2 and y >= y1 and y < y2:
47+
if id in elements:
48+
pc = elements[id]['cb']()
49+
else:
50+
RuntimeError(f'Element \'{id}\' does not exist')
51+
return pc
52+
return
53+
54+
def closeScreen(screen):
55+
global running
56+
running = False
57+
58+
def renderScreen(screen):
59+
screen.after(1000, lambda: afterCB(screen))
60+
screen.mainloop()
61+
return
62+
63+
def afterCB(screen):
64+
global running
65+
if not running:
66+
screen.destroy()
67+
else:
68+
screen.after(1000, lambda: afterCB(screen))
69+
70+
# Render a graphic specification expressed as JSON text
71+
def renderSpec(screen, text, offset):
72+
global canvas, elements, zlist
73+
74+
def renderCanvas(values):
75+
global canvas
76+
left = values['left'] if 'left' in values else 0
77+
top = values['top'] if 'top' in values else 0
78+
width = values['width'] if 'width' in values else 600
79+
height = values['height'] if 'height' in values else 800
80+
fill = values['fill'] if 'fill' in values else 'white'
81+
canvas = tk.Canvas(master=screen, width=width, height=height, bg=fill)
82+
canvas.place(x=left, y=top)
83+
if '#' in values:
84+
children = values['#']
85+
if type(children) == list:
86+
for item in children:
87+
if item in values:
88+
child = values[item]
89+
result = renderWidget(child, {'dx': left, 'dy': top})
90+
if result != None:
91+
return result
92+
else:
93+
return f'Element \'{item}\' does not exist'
94+
else:
95+
child = values[children]
96+
return renderWidget(child, offset)
97+
98+
def renderRect(values, offset):
99+
global canvas
100+
left = values['left'] if 'left' in values else 10
101+
top = values['top'] if 'top' in values else 10
102+
left = offset['dx'] + left
103+
top = offset['dy'] + top
104+
width = values['width'] if 'width' in values else 100
105+
height = values['height'] if 'height' in values else 100
106+
right = left + width
107+
bottom = top + height
108+
fill = values['fill'] if 'fill' in values else None
109+
outline = values['outline'] if 'outline' in values else None
110+
rectId = canvas.create_rectangle(left, top, right, bottom, fill=fill, outline=outline)
111+
if 'id' in values:
112+
id = values['id']
113+
spec = {
114+
"id": rectId,
115+
"left": left,
116+
"top": top,
117+
"width": width,
118+
"height": height
119+
}
120+
elements[id] = spec
121+
zlist.append({id: spec})
122+
if '#' in values:
123+
children = values['#']
124+
if type(children) == list:
125+
for item in children:
126+
if item in values:
127+
child = values[item]
128+
result = renderWidget(child, {'dx': left, 'dy': top})
129+
if result != None:
130+
return result
131+
else:
132+
return f'Unable to render \'{item}\''
133+
else:
134+
child = values[children]
135+
result = renderWidget(child, offset)
136+
if result != None:
137+
return result
138+
return None
139+
140+
def renderLabel(values, offset):
141+
global canvas
142+
left = values['left'] if 'left' in values else 10
143+
top = values['top'] if 'top' in values else 10
144+
left = offset['dx'] + left
145+
top = offset['dy'] + top
146+
width = values['width'] if 'width' in values else 100
147+
height = values['height'] if 'height' in values else 100
148+
right = left + width
149+
bottom = top + height
150+
fill = values['fill'] if 'fill' in values else None
151+
outline = values['outline'] if 'outline' in values else None
152+
color = values['color'] if 'color' in values else None
153+
text = values['text'] if 'text' in values else ''
154+
rectId = canvas.create_rectangle(left, top, right, bottom, fill=fill, outline=outline)
155+
if 'id' in values:
156+
id = values['id']
157+
spec = {
158+
"id": rectId,
159+
"left": left,
160+
"top": top,
161+
"width": width,
162+
"height": height
163+
}
164+
elements[id] = spec
165+
zlist.append({id: spec})
166+
canvas.create_text(left + width/2, top + height/2 + 5, fill=color, font="Times 22 bold", text=text, anchor='center')
167+
return None
168+
169+
# Create a canvas or render a widget
170+
def renderWidget(widget, offset):
171+
widgetType = widget['type']
172+
if widgetType == 'canvas':
173+
return renderCanvas(widget)
174+
elif widgetType == 'rect':
175+
return renderRect(widget, offset)
176+
elif widgetType == 'label':
177+
return renderLabel(widget, offset)
178+
179+
# Render a block - an array of widgets
180+
def renderBlock(block, offset):
181+
for name in block.keys():
182+
result = renderWidget(block[name], offset)
183+
if result != None:
184+
return result
185+
186+
# Render a complete specification
187+
def renderSpec(spec, offset):
188+
if type(spec) == dict:
189+
return renderBlock(item, offset)
190+
elif type(spec) == list:
191+
for item in spec:
192+
result = renderBlock(item, offset)
193+
if result != None:
194+
return result
195+
196+
# Render a specification supplied as JSON text
197+
return renderSpec(json.loads(text), offset)
198+
199+
def getElement(name):
200+
global elements
201+
if name in elements:
202+
return elements[name]
203+
else:
204+
RuntimeError(f'Element \'{name}\' does not exist')

‎py/json/test.json‎

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
[
2+
{
3+
"Background": {
4+
"type": "canvas",
5+
"left": 0,
6+
"top": 0,
7+
"width": 600,
8+
"height": 800,
9+
"fill": "#ffc",
10+
"#": ["Rect 1", "Rect 2", "Exit"],
11+
12+
"Rect 1": {
13+
"type": "rect",
14+
"left": 100,
15+
"top": 100,
16+
"width": 200,
17+
"height": 100,
18+
"fill": "red",
19+
"outline": "black"
20+
},
21+
22+
"Rect 2": {
23+
"type": "rect",
24+
"left": 500,
25+
"top": 500,
26+
"width": 100,
27+
"height": 200,
28+
"fill": "green",
29+
"outline": "black",
30+
"#":["Rect 2A"],
31+
32+
"Rect 2A": {
33+
"type": "rect",
34+
"left": 10,
35+
"top": 100,
36+
"width": 50,
37+
"height": 50,
38+
"fill": "blue",
39+
"outline": "white"
40+
}
41+
},
42+
43+
"Exit": {
44+
"type": "label",
45+
"id": "exit",
46+
"left": 530,
47+
"top": 760,
48+
"width": 60,
49+
"height": 30,
50+
"fill": "black",
51+
"outline": "red",
52+
"color": "yellow",
53+
"text": "Exit"
54+
}
55+
}
56+
}
57+
]

‎py/rbr.ecs‎

Lines changed: 0 additions & 157 deletions
This file was deleted.

‎py/rbr.py‎

Lines changed: 0 additions & 55 deletions
This file was deleted.

‎py/test.py‎

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
#! /bin/python
22

3-
import sys
43
from ec_program import Program
54
from ec_core import Core
5+
from ec_graphics import Graphics
66

77
class EasyCoder:
88

99
def __init__(self):
1010
self.version = 1
1111

12-
domainMap = {}
13-
domainMap['core'] = Core
14-
15-
f = open('py/getip.ecs', 'r')
12+
f = open('/home/graham/Dropbox/Code/VisualStudio/EasyCoder/easycoder.github.io/py/test.ecs', 'r')
1613
source = f.read()
1714
f.close()
1815

19-
Program(source, domainMap)
16+
Program(source, [Core, Graphics])
2017

2118
if __name__ == '__main__':
2219
EasyCoder()

0 commit comments

Comments
 (0)
Please sign in to comment.