easycoder 241218.1__tar.gz → 241231.1__tar.gz
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-241218.1 → easycoder-241231.1}/PKG-INFO +11 -3
- {easycoder-241218.1 → easycoder-241231.1}/README.md +10 -2
- easycoder-241231.1/easycoder/README.md +6 -0
- {easycoder-241218.1 → easycoder-241231.1}/easycoder/__init__.py +2 -2
- easycoder-241231.1/easycoder/ec.py +10 -0
- {easycoder-241218.1 → easycoder-241231.1}/easycoder/ec_classes.py +3 -0
- {easycoder-241218.1 → easycoder-241231.1}/easycoder/ec_compiler.py +7 -6
- {easycoder-241218.1 → easycoder-241231.1}/easycoder/ec_core.py +29 -4
- easycoder-241231.1/easycoder/ec_graphics.py +429 -0
- {easycoder-241218.1 → easycoder-241231.1}/easycoder/ec_handler.py +1 -0
- {easycoder-241218.1 → easycoder-241231.1}/easycoder/ec_program.py +72 -58
- easycoder-241231.1/easycoder/ec_renderer.py +245 -0
- easycoder-241231.1/easycoder/ec_screenspec.py +77 -0
- {easycoder-241218.1 → easycoder-241231.1}/easycoder/ec_value.py +10 -10
- easycoder-241231.1/json/graphics-demo.json +74 -0
- easycoder-241231.1/scripts/README.md +16 -0
- easycoder-241231.1/scripts/graphics-demo.ecg +102 -0
- easycoder-241231.1/scripts/wave.ecg +118 -0
- easycoder-241218.1/easycoder/ec_graphics.py +0 -376
- easycoder-241218.1/easycoder/ec_renderer.py +0 -335
- easycoder-241218.1/json/graphics-demo.json +0 -60
- easycoder-241218.1/scripts/graphics-demo.ecs +0 -71
- {easycoder-241218.1 → easycoder-241231.1}/LICENSE +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/README.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/add.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/append.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/assert.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/begin.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/clear.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/close.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/create.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/debug.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/decrement.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/delete.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/divide.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/exit.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/file.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/fork.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/get.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/go.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/gosub.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/if.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/import.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/increment.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/index.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/init.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/input.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/multiply.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/open.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/pop.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/post.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/print.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/push.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/put.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/read.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/replace.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/return.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/script.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/set.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/split.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/stack.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/stop.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/system.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/take.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/toggle.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/truncate.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/variable.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/wait.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/while.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/doc/core/write.md +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/easycoder/ec_condition.py +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/easycoder/ec_timestamp.py +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/images/Semoigo Dawn.jpg +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/plugins/ec_p100.py +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/plugins/example.py +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/pyproject.toml +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/scripts/benchmark.ecs +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/scripts/fizzbuzz.ecs +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/scripts/hello.ecs +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/scripts/points.ecs +0 -0
- {easycoder-241218.1 → easycoder-241231.1}/scripts/tests.ecs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: easycoder
|
|
3
|
-
Version:
|
|
3
|
+
Version: 241231.1
|
|
4
4
|
Summary: Rapid scripting in English
|
|
5
5
|
Keywords: compiler,scripting,prototyping,programming,coding,python,low code,hypertalk,computer language,learn to code
|
|
6
6
|
Author-email: Graham Trott <gtanyware@gmail.com>
|
|
@@ -60,9 +60,17 @@ Here in the repository is a folder called `scripts` containing some sample scrip
|
|
|
60
60
|
`fizzbuzz.ecs` is a simple programming challenge often given at job interviews
|
|
61
61
|
|
|
62
62
|
## Graphical programmming
|
|
63
|
-
**_EasyCoder_**
|
|
63
|
+
**_EasyCoder_** includes a graphical programming environment that is in the early stages of development. A couple of demo scripts are included in the `scripts` directory. To run them, first install the Python `kivy` graphics library if it's not already present on your system. This is done with `pip install kivy`. Then run a script using `easycoder {scriptname}.ecg`.
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
Graphical scripts look much like any other script but their file names must use the extension `.ecg` to signal to **_EasyCoder_** that it needs to load the graphics module. This allows the **_EasyCoder_** application to be used wherever Python is installed, in either a command-line or a graphical environment (but graphics will of course not be available in the former).
|
|
66
|
+
|
|
67
|
+
A couple of demo scripts are included in the `scripts` directory:
|
|
68
|
+
|
|
69
|
+
`graphics-demo.ecg` shows some of the elements that can be created, and demonstrates a variety of the graphical features of the language such as detecting when elements are clicked.
|
|
70
|
+
|
|
71
|
+
`wave.ecg` is a "Mexican Wave" simulation.
|
|
72
|
+
|
|
73
|
+
**_EasyCoder_** graphics are handled by a library module, `ec_renderer` that can be used outside of the **_EasyCoder_** environment, in other Python programs.
|
|
66
74
|
|
|
67
75
|
## EasyCoder programming reference
|
|
68
76
|
|
|
@@ -49,9 +49,17 @@ Here in the repository is a folder called `scripts` containing some sample scrip
|
|
|
49
49
|
`fizzbuzz.ecs` is a simple programming challenge often given at job interviews
|
|
50
50
|
|
|
51
51
|
## Graphical programmming
|
|
52
|
-
**_EasyCoder_**
|
|
52
|
+
**_EasyCoder_** includes a graphical programming environment that is in the early stages of development. A couple of demo scripts are included in the `scripts` directory. To run them, first install the Python `kivy` graphics library if it's not already present on your system. This is done with `pip install kivy`. Then run a script using `easycoder {scriptname}.ecg`.
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
Graphical scripts look much like any other script but their file names must use the extension `.ecg` to signal to **_EasyCoder_** that it needs to load the graphics module. This allows the **_EasyCoder_** application to be used wherever Python is installed, in either a command-line or a graphical environment (but graphics will of course not be available in the former).
|
|
55
|
+
|
|
56
|
+
A couple of demo scripts are included in the `scripts` directory:
|
|
57
|
+
|
|
58
|
+
`graphics-demo.ecg` shows some of the elements that can be created, and demonstrates a variety of the graphical features of the language such as detecting when elements are clicked.
|
|
59
|
+
|
|
60
|
+
`wave.ecg` is a "Mexican Wave" simulation.
|
|
61
|
+
|
|
62
|
+
**_EasyCoder_** graphics are handled by a library module, `ec_renderer` that can be used outside of the **_EasyCoder_** environment, in other Python programs.
|
|
55
63
|
|
|
56
64
|
## EasyCoder programming reference
|
|
57
65
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# EasyCode source code
|
|
2
|
+
These are the Python files that comprise **_EasyCoder_**.
|
|
3
|
+
|
|
4
|
+
**_EasyCoder_** has a small number of third-party dependencies. A minor one is `pytz`, which handles timezones. The biggest one by far is `kivy`, a comprehensive Python graphics library.
|
|
5
|
+
|
|
6
|
+
If an **_EasyCoder_** script filename ends with `.ecs` it's a command-line script. If it ends with `.ecg` it's a script for a graphical application and will cause `kivy` to be imported. Obviously this will only work on a GUI-based system, whereas command-line scripts will run anywhere there is Python.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'''EasyCoder for Python'''
|
|
2
2
|
|
|
3
|
+
from .ec import Main
|
|
3
4
|
from .ec_classes import *
|
|
4
5
|
from .ec_compiler import *
|
|
5
6
|
from .ec_condition import *
|
|
@@ -8,6 +9,5 @@ from .ec_handler import *
|
|
|
8
9
|
from .ec_program import *
|
|
9
10
|
from .ec_timestamp import *
|
|
10
11
|
from .ec_value import *
|
|
11
|
-
from .ec_graphics import *
|
|
12
12
|
|
|
13
|
-
__version__ = "
|
|
13
|
+
__version__ = "241231.1"
|
|
@@ -16,6 +16,7 @@ class Compiler:
|
|
|
16
16
|
self.warnings = []
|
|
17
17
|
self.program.compiler = self
|
|
18
18
|
self.addCommand = self.program.add
|
|
19
|
+
self.compileConstant = self.value.compileConstant
|
|
19
20
|
|
|
20
21
|
def getPC(self):
|
|
21
22
|
return len(self.program.code)
|
|
@@ -44,6 +45,11 @@ class Compiler:
|
|
|
44
45
|
except:
|
|
45
46
|
return None
|
|
46
47
|
|
|
48
|
+
# Get a constant
|
|
49
|
+
def getConstant(self, token):
|
|
50
|
+
self.index += 1
|
|
51
|
+
return self.compileConstant(token)
|
|
52
|
+
|
|
47
53
|
# Get a value
|
|
48
54
|
def getValue(self):
|
|
49
55
|
return self.value.compileValue()
|
|
@@ -53,11 +59,6 @@ class Compiler:
|
|
|
53
59
|
self.index += 1
|
|
54
60
|
return self.value.compileValue()
|
|
55
61
|
|
|
56
|
-
# Get a constant
|
|
57
|
-
def getConstant(self, token):
|
|
58
|
-
self.index += 1
|
|
59
|
-
return self.value.compileConstant(token)
|
|
60
|
-
|
|
61
62
|
# Get a condition
|
|
62
63
|
def getCondition(self):
|
|
63
64
|
return self.condition.compileCondition()
|
|
@@ -101,7 +102,7 @@ class Compiler:
|
|
|
101
102
|
|
|
102
103
|
def showWarnings(self):
|
|
103
104
|
for warning in self.warnings:
|
|
104
|
-
print(f'Warning
|
|
105
|
+
print(f'Warning at line {self.getLino() + 1} from {warning}')
|
|
105
106
|
|
|
106
107
|
def getSymbolRecord(self):
|
|
107
108
|
token = self.getToken()
|
|
@@ -696,6 +696,29 @@ class Core(Handler):
|
|
|
696
696
|
self.putSymbolValue(target, value)
|
|
697
697
|
return self.nextPC()
|
|
698
698
|
|
|
699
|
+
# Negate a variable
|
|
700
|
+
def k_negate(self, command):
|
|
701
|
+
if self.nextIsSymbol():
|
|
702
|
+
symbolRecord = self.getSymbolRecord()
|
|
703
|
+
if symbolRecord['valueHolder']:
|
|
704
|
+
command['target'] = self.getToken()
|
|
705
|
+
self.add(command)
|
|
706
|
+
return True
|
|
707
|
+
self.warning(f'Core.negate: Variable "{symbolRecord["name"]}" does not hold a value')
|
|
708
|
+
return False
|
|
709
|
+
|
|
710
|
+
def r_negate(self, command):
|
|
711
|
+
symbolRecord = self.getVariable(command['target'])
|
|
712
|
+
if not symbolRecord['valueHolder']:
|
|
713
|
+
RuntimeError(self.program, f'{symbolRecord["name"]} does not hold a value')
|
|
714
|
+
return None
|
|
715
|
+
value = self.getSymbolValue(symbolRecord)
|
|
716
|
+
if value == None:
|
|
717
|
+
RuntimeError(self.program, f'{symbolRecord["name"]} has not been initialised')
|
|
718
|
+
value['content'] *= -1
|
|
719
|
+
self.putSymbolValue(symbolRecord, value)
|
|
720
|
+
return self.nextPC()
|
|
721
|
+
|
|
699
722
|
# Define an object variable
|
|
700
723
|
def k_object(self, command):
|
|
701
724
|
return self.compileVariable(command)
|
|
@@ -724,8 +747,10 @@ class Core(Handler):
|
|
|
724
747
|
FatalError(self.program.compiler, 'Unknown file open mode {self.getToken()}')
|
|
725
748
|
return False
|
|
726
749
|
command['mode'] = mode
|
|
727
|
-
|
|
728
|
-
|
|
750
|
+
else:
|
|
751
|
+
command['mode'] = 'r'
|
|
752
|
+
self.add(command)
|
|
753
|
+
return True
|
|
729
754
|
else:
|
|
730
755
|
FatalError(self.compiler, f'Variable "{self.getToken()}" is not a file')
|
|
731
756
|
else:
|
|
@@ -974,7 +999,7 @@ class Core(Handler):
|
|
|
974
999
|
content = self.getSymbolValue(templateRecord)['content']
|
|
975
1000
|
original = self.getRuntimeValue(command['original'])
|
|
976
1001
|
replacement = self.getRuntimeValue(command['replacement'])
|
|
977
|
-
content = content.replace(original, replacement)
|
|
1002
|
+
content = content.replace(original, str(replacement))
|
|
978
1003
|
value = {}
|
|
979
1004
|
value['type'] = 'text'
|
|
980
1005
|
value['numeric'] = False
|
|
@@ -1415,7 +1440,7 @@ class Core(Handler):
|
|
|
1415
1440
|
# Compile a value in this domain
|
|
1416
1441
|
def compileValue(self):
|
|
1417
1442
|
value = {}
|
|
1418
|
-
value['domain'] =
|
|
1443
|
+
value['domain'] = self.getName()
|
|
1419
1444
|
token = self.getToken()
|
|
1420
1445
|
if self.isSymbol():
|
|
1421
1446
|
value['name'] = token
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
from .ec_classes import FatalError, RuntimeError, Object
|
|
2
|
+
from .ec_handler import Handler
|
|
3
|
+
from .ec_screenspec import ScreenSpec
|
|
4
|
+
from .ec_renderer import Renderer
|
|
5
|
+
|
|
6
|
+
class Graphics(Handler):
|
|
7
|
+
|
|
8
|
+
def __init__(self, compiler):
|
|
9
|
+
Handler.__init__(self, compiler)
|
|
10
|
+
|
|
11
|
+
def getName(self):
|
|
12
|
+
return 'graphics'
|
|
13
|
+
|
|
14
|
+
#############################################################################
|
|
15
|
+
# Keyword handlers
|
|
16
|
+
|
|
17
|
+
def k_attach(self, command):
|
|
18
|
+
if self.nextIsSymbol():
|
|
19
|
+
record = self.getSymbolRecord()
|
|
20
|
+
command['name'] = record['name']
|
|
21
|
+
if self.nextIs('to'):
|
|
22
|
+
value = self.nextValue()
|
|
23
|
+
record['id'] = value
|
|
24
|
+
command['id'] = value
|
|
25
|
+
self.add(command)
|
|
26
|
+
return True
|
|
27
|
+
|
|
28
|
+
def r_attach(self, command):
|
|
29
|
+
targetRecord = self.getVariable(command['name'])
|
|
30
|
+
keyword = targetRecord['keyword']
|
|
31
|
+
id = self.getRuntimeValue(command['id'])
|
|
32
|
+
element = self.ui.getElement(id)
|
|
33
|
+
if element == None:
|
|
34
|
+
FatalError(self.program.compiler, f'There is no screen element with id \'{id}\'')
|
|
35
|
+
return -1
|
|
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})
|
|
39
|
+
return self.nextPC()
|
|
40
|
+
|
|
41
|
+
# close window
|
|
42
|
+
def k_close(self, command):
|
|
43
|
+
if (self.nextIs('window')):
|
|
44
|
+
self.add(command)
|
|
45
|
+
return True
|
|
46
|
+
return False
|
|
47
|
+
|
|
48
|
+
def r_close(self, command):
|
|
49
|
+
self.renderer.stop()
|
|
50
|
+
return 0
|
|
51
|
+
|
|
52
|
+
# create window/ellipse/rectangle//text/image
|
|
53
|
+
def k_create(self, command):
|
|
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)
|
|
66
|
+
while True:
|
|
67
|
+
token = self.peek()
|
|
68
|
+
if token == 'title':
|
|
69
|
+
self.nextToken()
|
|
70
|
+
t = self.nextValue()
|
|
71
|
+
elif token == 'at':
|
|
72
|
+
self.nextToken()
|
|
73
|
+
left = self.nextValue()
|
|
74
|
+
top = self.nextValue()
|
|
75
|
+
elif token == 'size':
|
|
76
|
+
self.nextToken()
|
|
77
|
+
width = self.nextValue()
|
|
78
|
+
height = self.nextValue()
|
|
79
|
+
elif token == 'fill':
|
|
80
|
+
self.nextToken()
|
|
81
|
+
if self.nextIs('color'):
|
|
82
|
+
r = self.nextValue()
|
|
83
|
+
g = self.nextValue()
|
|
84
|
+
b = self.nextValue()
|
|
85
|
+
else:
|
|
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)
|
|
92
|
+
self.add(command)
|
|
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']
|
|
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
|
|
169
|
+
|
|
170
|
+
def r_create(self, 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)
|
|
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
|
|
200
|
+
|
|
201
|
+
def k_ellipse(self, command):
|
|
202
|
+
return self.compileVariable(command)
|
|
203
|
+
|
|
204
|
+
def r_ellipse(self, command):
|
|
205
|
+
return self.nextPC()
|
|
206
|
+
|
|
207
|
+
def r_getui(self, command):
|
|
208
|
+
self.ui = self.renderer.getUI()
|
|
209
|
+
return self.nextPC()
|
|
210
|
+
|
|
211
|
+
def k_image(self, command):
|
|
212
|
+
return self.compileVariable(command)
|
|
213
|
+
|
|
214
|
+
def r_image(self, command):
|
|
215
|
+
return self.nextPC()
|
|
216
|
+
|
|
217
|
+
# move an element
|
|
218
|
+
def k_move(self, command):
|
|
219
|
+
if self.nextIsSymbol():
|
|
220
|
+
record = self.getSymbolRecord()
|
|
221
|
+
type = record['keyword']
|
|
222
|
+
if type in ['ellipse', 'rectangle']:
|
|
223
|
+
command['target'] = record['id']
|
|
224
|
+
token = self.nextToken()
|
|
225
|
+
if token == 'to':
|
|
226
|
+
command['x'] = self.nextValue()
|
|
227
|
+
command['y'] = self.nextValue()
|
|
228
|
+
self.add(command)
|
|
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
|
|
236
|
+
return False
|
|
237
|
+
|
|
238
|
+
def r_move(self, command):
|
|
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)
|
|
246
|
+
return self.nextPC()
|
|
247
|
+
|
|
248
|
+
def k_on(self, command):
|
|
249
|
+
token = self.nextToken()
|
|
250
|
+
if token in ['click', 'tap']:
|
|
251
|
+
command['type'] = 'tap'
|
|
252
|
+
if self.nextIsSymbol():
|
|
253
|
+
target = self.getSymbolRecord()
|
|
254
|
+
else:
|
|
255
|
+
FatalError(self.program.compiler, f'{self.getToken()} is not a screen element')
|
|
256
|
+
return False
|
|
257
|
+
command['target'] = target['name']
|
|
258
|
+
command['goto'] = self.getPC() + 2
|
|
259
|
+
self.add(command)
|
|
260
|
+
self.nextToken()
|
|
261
|
+
pcNext = self.getPC()
|
|
262
|
+
cmd = {}
|
|
263
|
+
cmd['domain'] = 'core'
|
|
264
|
+
cmd['lino'] = command['lino']
|
|
265
|
+
cmd['keyword'] = 'gotoPC'
|
|
266
|
+
cmd['goto'] = 0
|
|
267
|
+
cmd['debug'] = False
|
|
268
|
+
self.addCommand(cmd)
|
|
269
|
+
self.compileOne()
|
|
270
|
+
cmd = {}
|
|
271
|
+
cmd['domain'] = 'core'
|
|
272
|
+
cmd['lino'] = command['lino']
|
|
273
|
+
cmd['keyword'] = 'stop'
|
|
274
|
+
cmd['debug'] = False
|
|
275
|
+
self.addCommand(cmd)
|
|
276
|
+
# Fixup the link
|
|
277
|
+
self.getCommandAt(pcNext)['goto'] = self.getPC()
|
|
278
|
+
return True
|
|
279
|
+
return False
|
|
280
|
+
|
|
281
|
+
def r_on(self, command):
|
|
282
|
+
pc = command['goto']
|
|
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')
|
|
291
|
+
return self.nextPC()
|
|
292
|
+
|
|
293
|
+
def k_rectangle(self, command):
|
|
294
|
+
return self.compileVariable(command)
|
|
295
|
+
|
|
296
|
+
def r_rectangle(self, command):
|
|
297
|
+
return self.nextPC()
|
|
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}
|
|
306
|
+
def k_render(self, command):
|
|
307
|
+
command['spec'] = self.nextValue()
|
|
308
|
+
self.add(command)
|
|
309
|
+
return True
|
|
310
|
+
|
|
311
|
+
def r_render(self, command):
|
|
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)
|
|
317
|
+
return self.nextPC()
|
|
318
|
+
|
|
319
|
+
# run graphics
|
|
320
|
+
def k_run(self, command):
|
|
321
|
+
if self.nextIs('graphics'):
|
|
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)
|
|
329
|
+
return True
|
|
330
|
+
return False
|
|
331
|
+
|
|
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()
|
|
338
|
+
|
|
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
|
|
357
|
+
|
|
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)
|
|
364
|
+
return self.nextPC()
|
|
365
|
+
|
|
366
|
+
#############################################################################
|
|
367
|
+
# Modify a value or leave it unchanged.
|
|
368
|
+
def modifyValue(self, value):
|
|
369
|
+
return value
|
|
370
|
+
|
|
371
|
+
#############################################################################
|
|
372
|
+
# Compile a value in this domain
|
|
373
|
+
def compileValue(self):
|
|
374
|
+
value = {}
|
|
375
|
+
value['domain'] = self.getName()
|
|
376
|
+
if self.tokenIs('the'):
|
|
377
|
+
self.nextToken()
|
|
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
|
|
394
|
+
return None
|
|
395
|
+
|
|
396
|
+
#############################################################################
|
|
397
|
+
# Value handlers
|
|
398
|
+
|
|
399
|
+
def v_attribute(self, v):
|
|
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)
|
|
421
|
+
|
|
422
|
+
#############################################################################
|
|
423
|
+
# Compile a condition
|
|
424
|
+
def compileCondition(self):
|
|
425
|
+
condition = {}
|
|
426
|
+
return condition
|
|
427
|
+
|
|
428
|
+
#############################################################################
|
|
429
|
+
# Condition handlers
|
|
@@ -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
|