easycoder 241211.3__tar.gz → 241215.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-241211.3/README.md → easycoder-241215.1/PKG-INFO +18 -1
- easycoder-241211.3/PKG-INFO → easycoder-241215.1/README.md +6 -12
- {easycoder-241211.3 → easycoder-241215.1}/doc/README.md +1 -1
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/if.md +1 -1
- easycoder-241215.1/doc/core/import.md +13 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/increment.md +1 -1
- {easycoder-241211.3 → easycoder-241215.1}/easycoder/__init__.py +2 -1
- {easycoder-241211.3 → easycoder-241215.1}/easycoder/ec_compiler.py +1 -1
- {easycoder-241211.3 → easycoder-241215.1}/easycoder/ec_core.py +16 -14
- easycoder-241215.1/easycoder/ec_graphics.py +376 -0
- {easycoder-241211.3 → easycoder-241215.1}/easycoder/ec_program.py +15 -7
- easycoder-241215.1/easycoder/ec_renderer.py +330 -0
- {easycoder-241211.3 → easycoder-241215.1}/plugins/example.py +2 -1
- {easycoder-241211.3 → easycoder-241215.1}/pyproject.toml +4 -2
- easycoder-241215.1/scripts/graphics-demo.ecs +70 -0
- easycoder-241215.1/scripts/graphics-demo.json +36 -0
- easycoder-241211.3/test.ecs +0 -10
- {easycoder-241211.3 → easycoder-241215.1}/LICENSE +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/add.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/append.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/assert.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/begin.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/clear.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/close.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/create.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/debug.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/decrement.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/delete.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/divide.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/exit.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/file.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/fork.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/get.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/go.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/gosub.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/index.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/init.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/input.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/multiply.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/open.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/pop.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/post.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/print.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/push.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/put.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/read.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/replace.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/return.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/script.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/set.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/split.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/stack.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/stop.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/system.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/take.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/toggle.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/truncate.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/variable.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/wait.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/while.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/doc/core/write.md +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/easycoder/ec_classes.py +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/easycoder/ec_condition.py +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/easycoder/ec_handler.py +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/easycoder/ec_timestamp.py +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/easycoder/ec_value.py +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/plugins/ec_p100.py +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/scripts/benchmark.ecs +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/scripts/fizzbuzz.ecs +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/scripts/hello.ecs +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/scripts/points.ecs +0 -0
- {easycoder-241211.3 → easycoder-241215.1}/scripts/tests.ecs +0 -0
|
@@ -1,9 +1,20 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: easycoder
|
|
3
|
+
Version: 241215.1
|
|
4
|
+
Summary: Rapid scripting in English
|
|
5
|
+
Keywords: compiler,scripting,prototyping,programming,coding,python,low code,hypertalk,computer language,learn to code
|
|
6
|
+
Author-email: Graham Trott <gtanyware@gmail.com>
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Requires-Dist: pytz
|
|
10
|
+
Project-URL: Home, https://github.com/easycoder/easycoder-py
|
|
11
|
+
|
|
1
12
|
# Introduction
|
|
2
13
|
This is the Python version of **_EasyCoder_**, a high-level English-like scripting language suited for prototyping and rapid testing of ideas. It operates on the command line.
|
|
3
14
|
|
|
4
15
|
The JavaScript version of **_EasyCoder_**, which provides a full set of graphical features to run in a browser, is at
|
|
5
16
|
|
|
6
|
-
Repository: [https://github.com/easycoder/easycoder.github.io](https://github.com/easycoder/easycoder.github.io)
|
|
17
|
+
Repository: [https://github.com/easycoder/easycoder.github.io](https://github.com/easycoder/easycoder.github.io)
|
|
7
18
|
Website: [https://easycoder.github.io](https://easycoder.github.io)
|
|
8
19
|
|
|
9
20
|
## Quick Start
|
|
@@ -48,6 +59,11 @@ Here in the repository is a folder called `scripts` containing some sample scrip
|
|
|
48
59
|
`tests.ecs` is a test program containing many of the EasyCoder features
|
|
49
60
|
`fizzbuzz.ecs` is a simple programming challenge often given at job interviews
|
|
50
61
|
|
|
62
|
+
## Graphical programmming
|
|
63
|
+
**_EasyCoder_** is currently being extended to include a graphical programming environment. A single demo script `graphics-demo.ecs` is included in the `scripts` directory. To run it, first install the Python graphics library if it's not already present on your system. On Linux this is done with `sudo apt install python3-tk`. On Windows it's `pip install tk`. Then give the command `easycoder -g scripts/graphics-demo.ecs`.
|
|
64
|
+
|
|
65
|
+
As development progresses this demo script will be extended to include new features as they are added. **_EasyCoder_** graphics are handled by a library module, `ec_renderer` that can be used outside of the **EasyCoder_** environment, in other Python programs.
|
|
66
|
+
|
|
51
67
|
## EasyCoder programming reference
|
|
52
68
|
|
|
53
69
|
The language comprises a general-purpose core package, which can be enhanced by plugins to provide special features on demand.
|
|
@@ -59,3 +75,4 @@ The language comprises a general-purpose core package, which can be enhanced by
|
|
|
59
75
|
**_EasyCoder_** can be extended to add new functionality with the use of 'plugins'. These contain compiler and runtime modules for the added language features. **_EasyCoder_** can use the added keywords, values and conditions freely; the effect is completely seamless. There is an outline example in the `plugins` directory called `example.py`, which comprises a module called `Points` with new language syntax to deal with two-valued items such as coordinates. In the `scripts` directory there is `points.ecs`, which exercises the new functionality.
|
|
60
76
|
|
|
61
77
|
A plugin can act as a wrapper around any Python functionality that has a sensible API, thereby hiding its complexity. The only challenge is to devise an unambiguous syntax that doesn't clash with anything already existing in **_EasyCoder_**
|
|
78
|
+
|
|
@@ -1,19 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.3
|
|
2
|
-
Name: easycoder
|
|
3
|
-
Version: 241211.3
|
|
4
|
-
Summary: EasyCoder for Python
|
|
5
|
-
Author-email: Graham Trott <gtanyware@gmail.com>
|
|
6
|
-
Description-Content-Type: text/markdown
|
|
7
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
-
Requires-Dist: pytz
|
|
9
|
-
Project-URL: Home, https://github.com/easycoder
|
|
10
|
-
|
|
11
1
|
# Introduction
|
|
12
2
|
This is the Python version of **_EasyCoder_**, a high-level English-like scripting language suited for prototyping and rapid testing of ideas. It operates on the command line.
|
|
13
3
|
|
|
14
4
|
The JavaScript version of **_EasyCoder_**, which provides a full set of graphical features to run in a browser, is at
|
|
15
5
|
|
|
16
|
-
Repository: [https://github.com/easycoder/easycoder.github.io](https://github.com/easycoder/easycoder.github.io)
|
|
6
|
+
Repository: [https://github.com/easycoder/easycoder.github.io](https://github.com/easycoder/easycoder.github.io)
|
|
17
7
|
Website: [https://easycoder.github.io](https://easycoder.github.io)
|
|
18
8
|
|
|
19
9
|
## Quick Start
|
|
@@ -58,6 +48,11 @@ Here in the repository is a folder called `scripts` containing some sample scrip
|
|
|
58
48
|
`tests.ecs` is a test program containing many of the EasyCoder features
|
|
59
49
|
`fizzbuzz.ecs` is a simple programming challenge often given at job interviews
|
|
60
50
|
|
|
51
|
+
## Graphical programmming
|
|
52
|
+
**_EasyCoder_** is currently being extended to include a graphical programming environment. A single demo script `graphics-demo.ecs` is included in the `scripts` directory. To run it, first install the Python graphics library if it's not already present on your system. On Linux this is done with `sudo apt install python3-tk`. On Windows it's `pip install tk`. Then give the command `easycoder -g scripts/graphics-demo.ecs`.
|
|
53
|
+
|
|
54
|
+
As development progresses this demo script will be extended to include new features as they are added. **_EasyCoder_** graphics are handled by a library module, `ec_renderer` that can be used outside of the **EasyCoder_** environment, in other Python programs.
|
|
55
|
+
|
|
61
56
|
## EasyCoder programming reference
|
|
62
57
|
|
|
63
58
|
The language comprises a general-purpose core package, which can be enhanced by plugins to provide special features on demand.
|
|
@@ -69,4 +64,3 @@ The language comprises a general-purpose core package, which can be enhanced by
|
|
|
69
64
|
**_EasyCoder_** can be extended to add new functionality with the use of 'plugins'. These contain compiler and runtime modules for the added language features. **_EasyCoder_** can use the added keywords, values and conditions freely; the effect is completely seamless. There is an outline example in the `plugins` directory called `example.py`, which comprises a module called `Points` with new language syntax to deal with two-valued items such as coordinates. In the `scripts` directory there is `points.ecs`, which exercises the new functionality.
|
|
70
65
|
|
|
71
66
|
A plugin can act as a wrapper around any Python functionality that has a sensible API, thereby hiding its complexity. The only challenge is to devise an unambiguous syntax that doesn't clash with anything already existing in **_EasyCoder_**
|
|
72
|
-
|
|
@@ -10,7 +10,7 @@ The core package contains all the keywords values and conditionals needed for ge
|
|
|
10
10
|
|
|
11
11
|
The core keywords are:
|
|
12
12
|
|
|
13
|
-
[add](core/add.md) [append](core/append.md) [assert](core/assert.md) [begin](core/begin.md) [clear](core/clear.md) [close](core/close.md) [create](core/create.md) [debug](core/debug.md) [decrement](core/decrement.md) [delete](core/delete.md) [divide](core/divide.md) [exit](core/exit.md) [file](core/file.md) [fork](core/fork.md) [get](core/get.md) [go](core/go.md) [gosub](core/gosub.md) [if](core/if.md) [increment](core/increment.md) [index](core/index.md) [init](core/init.md) [input](core/input.md) [multiply](core/multiply.md) [open](core/open.md) [pop](core/pop.md) [post](core/post.md) [print](core/print.md) [push](core/push.md) [put](core/put.md) [read](core/read.md) [replace](core/replace.md) [return](core/return.md) [script](core/script.md) [set](core/set.md) [split](core/split.md) [stack](core/stack.md) [stop](core/stop.md) [system](core/system.md) [take](core/take.md) [toggle](core/toggle.md) [truncate](core/truncate.md) [variable](core/variable.md) [wait](core/wait.md) [while](core/while.md) [write](core/write.md)
|
|
13
|
+
[add](core/add.md) [append](core/append.md) [assert](core/assert.md) [begin](core/begin.md) [clear](core/clear.md) [close](core/close.md) [create](core/create.md) [debug](core/debug.md) [decrement](core/decrement.md) [delete](core/delete.md) [divide](core/divide.md) [exit](core/exit.md) [file](core/file.md) [fork](core/fork.md) [get](core/get.md) [go](core/go.md) [gosub](core/gosub.md) [if](core/if.md) [import](core/import.md) [increment](core/increment.md) [index](core/index.md) [init](core/init.md) [input](core/input.md) [multiply](core/multiply.md) [open](core/open.md) [pop](core/pop.md) [post](core/post.md) [print](core/print.md) [push](core/push.md) [put](core/put.md) [read](core/read.md) [replace](core/replace.md) [return](core/return.md) [script](core/script.md) [set](core/set.md) [split](core/split.md) [stack](core/stack.md) [stop](core/stop.md) [system](core/system.md) [take](core/take.md) [toggle](core/toggle.md) [truncate](core/truncate.md) [variable](core/variable.md) [wait](core/wait.md) [while](core/while.md) [write](core/write.md)
|
|
14
14
|
|
|
15
15
|
The core values are:
|
|
16
16
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
## Description:
|
|
9
9
|
`if` tests the condition that follows. If the result is `true` then control resumes at the named label; otherwise if there's an `else` section this is executed, then the program resumes at the next instruction after the `if`. See also [while](while.md).
|
|
10
10
|
|
|
11
|
-
Next: [
|
|
11
|
+
Next: [import](import.md)
|
|
12
12
|
Prev: [gosub](gosub.md)
|
|
13
13
|
|
|
14
14
|
[Back](../README.md)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
## Syntax:
|
|
2
|
+
`import {classname} from {path}`
|
|
3
|
+
|
|
4
|
+
## Examples:
|
|
5
|
+
`import Points from plugins/example.py`
|
|
6
|
+
|
|
7
|
+
## Description:
|
|
8
|
+
As with [script](script.md), `import` is a compiler directive that should be placed at the top of the script, under the [script](script.md) directive. It's used to call in a plugin language extension where needed. The example above is provided in the repository, to be used as a starting point for your own extra functionality.
|
|
9
|
+
|
|
10
|
+
Next: [increment](increment.md)
|
|
11
|
+
Prev: [if](if.md)
|
|
12
|
+
|
|
13
|
+
[Back](../README.md)
|
|
@@ -101,7 +101,7 @@ class Compiler:
|
|
|
101
101
|
|
|
102
102
|
def showWarnings(self):
|
|
103
103
|
for warning in self.warnings:
|
|
104
|
-
print(f'Line {self.getLino() + 1}: {warning}')
|
|
104
|
+
print(f'Warning: Line {self.getLino() + 1}: {warning}')
|
|
105
105
|
|
|
106
106
|
def getSymbolRecord(self):
|
|
107
107
|
token = self.getToken()
|
|
@@ -38,7 +38,7 @@ class Core(Handler):
|
|
|
38
38
|
command['target'] = self.getToken()
|
|
39
39
|
self.add(command)
|
|
40
40
|
return True
|
|
41
|
-
self.warning(f'
|
|
41
|
+
self.warning(f'Core.add: Expected value holder')
|
|
42
42
|
else:
|
|
43
43
|
# Here we have 2 values so 'giving' must come next
|
|
44
44
|
command['value2'] = self.getValue()
|
|
@@ -46,7 +46,7 @@ class Core(Handler):
|
|
|
46
46
|
command['target'] = self.nextToken()
|
|
47
47
|
self.add(command)
|
|
48
48
|
return True
|
|
49
|
-
self.warning(f'
|
|
49
|
+
self.warning(f'Core.add: Expected "giving"')
|
|
50
50
|
return False
|
|
51
51
|
|
|
52
52
|
def r_add(self, command):
|
|
@@ -90,7 +90,7 @@ class Core(Handler):
|
|
|
90
90
|
command['target'] = symbolRecord['name']
|
|
91
91
|
self.add(command)
|
|
92
92
|
return True
|
|
93
|
-
self.warning(f'Variable "{symbolRecord["name"]}" does not hold a value')
|
|
93
|
+
self.warning(f'Core.append: Variable "{symbolRecord["name"]}" does not hold a value')
|
|
94
94
|
return False
|
|
95
95
|
|
|
96
96
|
def r_append(self, command):
|
|
@@ -248,7 +248,7 @@ class Core(Handler):
|
|
|
248
248
|
command['target'] = self.getToken()
|
|
249
249
|
self.add(command)
|
|
250
250
|
return True
|
|
251
|
-
self.warning(f'Variable "{symbolRecord["name"]}" does not hold a value')
|
|
251
|
+
self.warning(f'Core.decrement: Variable "{symbolRecord["name"]}" does not hold a value')
|
|
252
252
|
return False
|
|
253
253
|
|
|
254
254
|
def r_decrement(self, command):
|
|
@@ -272,9 +272,9 @@ class Core(Handler):
|
|
|
272
272
|
self.add(command)
|
|
273
273
|
return True
|
|
274
274
|
else:
|
|
275
|
-
self.warning(f'"of" expected; got {self.getToken()}')
|
|
275
|
+
self.warning(f'Core.delete: "of" expected; got {self.getToken()}')
|
|
276
276
|
else:
|
|
277
|
-
self.warning(f'"file" or "property" expected; got {token}')
|
|
277
|
+
self.warning(f'Core.delete: "file" or "property" expected; got {token}')
|
|
278
278
|
return False
|
|
279
279
|
|
|
280
280
|
def r_delete(self, command):
|
|
@@ -570,7 +570,7 @@ class Core(Handler):
|
|
|
570
570
|
command['target'] = self.getToken()
|
|
571
571
|
self.add(command)
|
|
572
572
|
return True
|
|
573
|
-
self.warning(f'Variable "{symbolRecord["name"]}" does not hold a value')
|
|
573
|
+
self.warning(f'Core.increment: Variable "{symbolRecord["name"]}" does not hold a value')
|
|
574
574
|
return False
|
|
575
575
|
|
|
576
576
|
def r_increment(self, command):
|
|
@@ -729,7 +729,7 @@ class Core(Handler):
|
|
|
729
729
|
else:
|
|
730
730
|
FatalError(self.compiler, f'Variable "{self.getToken()}" is not a file')
|
|
731
731
|
else:
|
|
732
|
-
self.warning(f'
|
|
732
|
+
self.warning(f'Core.open: Variable "{self.getToken()}" not declared')
|
|
733
733
|
return False
|
|
734
734
|
|
|
735
735
|
def r_open(self, command):
|
|
@@ -1215,7 +1215,7 @@ class Core(Handler):
|
|
|
1215
1215
|
command['target'] = self.getToken()
|
|
1216
1216
|
self.add(command)
|
|
1217
1217
|
return True
|
|
1218
|
-
self.warning(f'
|
|
1218
|
+
self.warning(f'Core.take: Expected value holder')
|
|
1219
1219
|
else:
|
|
1220
1220
|
# Here we have 2 values so 'giving' must come next
|
|
1221
1221
|
command['value2'] = self.getValue()
|
|
@@ -1227,7 +1227,7 @@ class Core(Handler):
|
|
|
1227
1227
|
else:
|
|
1228
1228
|
FatalError(self.program.compiler, f'\'{self.getToken()}\' is not a symbol')
|
|
1229
1229
|
else:
|
|
1230
|
-
self.warning(f'
|
|
1230
|
+
self.warning(f'Core.take: Expected "giving"')
|
|
1231
1231
|
return False
|
|
1232
1232
|
|
|
1233
1233
|
def r_take(self, command):
|
|
@@ -1402,6 +1402,8 @@ class Core(Handler):
|
|
|
1402
1402
|
RuntimeError(self.program, f'{symbolRecord["name"]} does not hold a value')
|
|
1403
1403
|
return None
|
|
1404
1404
|
value = self.getSymbolValue(symbolRecord)
|
|
1405
|
+
if value == None:
|
|
1406
|
+
RuntimeError(self.program, f'{symbolRecord["name"]} has not been initialised')
|
|
1405
1407
|
if mode == '+':
|
|
1406
1408
|
value['content'] += 1
|
|
1407
1409
|
else:
|
|
@@ -1467,7 +1469,7 @@ class Core(Handler):
|
|
|
1467
1469
|
if symbolRecord['valueHolder']:
|
|
1468
1470
|
value['target'] = symbolRecord['name']
|
|
1469
1471
|
return value
|
|
1470
|
-
self.warning(f'Token \'{self.getToken()}\' does not hold a value')
|
|
1472
|
+
self.warning(f'Core.compileValue: Token \'{self.getToken()}\' does not hold a value')
|
|
1471
1473
|
return None
|
|
1472
1474
|
|
|
1473
1475
|
if token == 'property':
|
|
@@ -1478,7 +1480,7 @@ class Core(Handler):
|
|
|
1478
1480
|
if symbolRecord['valueHolder']:
|
|
1479
1481
|
value['target'] = symbolRecord['name']
|
|
1480
1482
|
return value
|
|
1481
|
-
self.warning(f'Token \'{self.getToken()}\' does not hold a value')
|
|
1483
|
+
self.warning(f'Core.compileValue: Token \'{self.getToken()}\' does not hold a value')
|
|
1482
1484
|
return None
|
|
1483
1485
|
|
|
1484
1486
|
if token == 'arg':
|
|
@@ -1640,7 +1642,7 @@ class Core(Handler):
|
|
|
1640
1642
|
return value
|
|
1641
1643
|
return None
|
|
1642
1644
|
|
|
1643
|
-
self.warning(f'Core: Unknown token {token}')
|
|
1645
|
+
self.warning(f'Core.compileValue: Unknown token "{token}"')
|
|
1644
1646
|
return None
|
|
1645
1647
|
|
|
1646
1648
|
#############################################################################
|
|
@@ -2115,7 +2117,7 @@ class Core(Handler):
|
|
|
2115
2117
|
condition.type = 'boolean'
|
|
2116
2118
|
return condition
|
|
2117
2119
|
|
|
2118
|
-
self.warning(f'I can\'t get a conditional:')
|
|
2120
|
+
self.warning(f'Core.compileCondition: I can\'t get a conditional:')
|
|
2119
2121
|
return None
|
|
2120
2122
|
|
|
2121
2123
|
def isNegate(self):
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
from .ec_classes import FatalError, RuntimeError
|
|
2
|
+
from .ec_handler import Handler
|
|
3
|
+
from .ec_renderer import *
|
|
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 \'{id}\'')
|
|
32
|
+
return -1
|
|
33
|
+
if element['type'] != target['keyword']:
|
|
34
|
+
FatalError(self.program.compiler, f'Mismatched element type ({element['type']} and {target['keyword']})')
|
|
35
|
+
self.putSymbolValue(target, {'type': 'text', 'content': id})
|
|
36
|
+
return self.nextPC()
|
|
37
|
+
|
|
38
|
+
def k_close(self, command):
|
|
39
|
+
if self.nextIs('screen'):
|
|
40
|
+
self.add(command)
|
|
41
|
+
return True
|
|
42
|
+
return False
|
|
43
|
+
|
|
44
|
+
def r_close(self, command):
|
|
45
|
+
closeScreen()
|
|
46
|
+
return self.nextPC()
|
|
47
|
+
|
|
48
|
+
def k_create(self, command):
|
|
49
|
+
if self.nextIs('screen'):
|
|
50
|
+
while True:
|
|
51
|
+
token = self.peek()
|
|
52
|
+
if token == 'at':
|
|
53
|
+
self.nextToken()
|
|
54
|
+
command['left'] = self.nextValue()
|
|
55
|
+
command['top'] = self.nextValue()
|
|
56
|
+
elif token == 'size':
|
|
57
|
+
self.nextToken()
|
|
58
|
+
command['width'] = self.nextValue()
|
|
59
|
+
command['height'] = self.nextValue()
|
|
60
|
+
elif token == 'fill':
|
|
61
|
+
self.nextToken()
|
|
62
|
+
command['fill'] = self.nextValue()
|
|
63
|
+
else:
|
|
64
|
+
break
|
|
65
|
+
self.add(command)
|
|
66
|
+
return True
|
|
67
|
+
return False
|
|
68
|
+
|
|
69
|
+
def r_create(self, command):
|
|
70
|
+
createScreen(command)
|
|
71
|
+
return self.nextPC()
|
|
72
|
+
|
|
73
|
+
def k_ellipse(self, command):
|
|
74
|
+
return self.compileVariable(command)
|
|
75
|
+
|
|
76
|
+
def r_ellipse(self, command):
|
|
77
|
+
return self.nextPC()
|
|
78
|
+
|
|
79
|
+
def k_image(self, command):
|
|
80
|
+
return self.compileVariable(command)
|
|
81
|
+
|
|
82
|
+
def r_image(self, command):
|
|
83
|
+
return self.nextPC()
|
|
84
|
+
|
|
85
|
+
def k_move(self, command):
|
|
86
|
+
if self.nextIsSymbol():
|
|
87
|
+
record = self.getSymbolRecord()
|
|
88
|
+
if record['keyword'] in ['rectangle', 'ellipse', 'text', 'image']:
|
|
89
|
+
command['name'] = record['name']
|
|
90
|
+
if self.nextToken() in ['by', 'to']:
|
|
91
|
+
command['type'] = self.getToken()
|
|
92
|
+
command['x'] = self.nextValue()
|
|
93
|
+
command['y'] = self.nextValue()
|
|
94
|
+
self.add(command)
|
|
95
|
+
return True
|
|
96
|
+
return False
|
|
97
|
+
|
|
98
|
+
def r_move(self, command):
|
|
99
|
+
target = self.getVariable(command['name'])
|
|
100
|
+
id = self.getSymbolValue(target)['content']
|
|
101
|
+
type = command['type']
|
|
102
|
+
x = self.getRuntimeValue(command['x'])
|
|
103
|
+
y = self.getRuntimeValue(command['y'])
|
|
104
|
+
if type == 'by':
|
|
105
|
+
moveElement(id, x, y)
|
|
106
|
+
elif type == 'to':
|
|
107
|
+
moveElementTo(id, x, y)
|
|
108
|
+
return self.nextPC()
|
|
109
|
+
|
|
110
|
+
def k_on(self, command):
|
|
111
|
+
token = self.nextToken()
|
|
112
|
+
command['type'] = token
|
|
113
|
+
if token == 'click':
|
|
114
|
+
command['event'] = token
|
|
115
|
+
if self.peek() == 'in':
|
|
116
|
+
self.nextToken()
|
|
117
|
+
if self.nextIs('screen'):
|
|
118
|
+
command['target'] = None
|
|
119
|
+
elif self.isSymbol():
|
|
120
|
+
target = self.getSymbolRecord()
|
|
121
|
+
command['target'] = target['name']
|
|
122
|
+
else:
|
|
123
|
+
FatalError(self.program.compiler, f'{self.getToken()} is not a screen element')
|
|
124
|
+
return False
|
|
125
|
+
command['goto'] = self.getPC() + 2
|
|
126
|
+
self.add(command)
|
|
127
|
+
self.nextToken()
|
|
128
|
+
pcNext = self.getPC()
|
|
129
|
+
cmd = {}
|
|
130
|
+
cmd['domain'] = 'core'
|
|
131
|
+
cmd['lino'] = command['lino']
|
|
132
|
+
cmd['keyword'] = 'gotoPC'
|
|
133
|
+
cmd['goto'] = 0
|
|
134
|
+
cmd['debug'] = False
|
|
135
|
+
self.addCommand(cmd)
|
|
136
|
+
self.compileOne()
|
|
137
|
+
cmd = {}
|
|
138
|
+
cmd['domain'] = 'core'
|
|
139
|
+
cmd['lino'] = command['lino']
|
|
140
|
+
cmd['keyword'] = 'stop'
|
|
141
|
+
cmd['debug'] = False
|
|
142
|
+
self.addCommand(cmd)
|
|
143
|
+
# Fixup the link
|
|
144
|
+
self.getCommandAt(pcNext)['goto'] = self.getPC()
|
|
145
|
+
return True
|
|
146
|
+
elif token == 'tick':
|
|
147
|
+
command['event'] = token
|
|
148
|
+
command['goto'] = self.getPC() + 2
|
|
149
|
+
self.add(command)
|
|
150
|
+
self.nextToken()
|
|
151
|
+
pcNext = self.getPC()
|
|
152
|
+
cmd = {}
|
|
153
|
+
cmd['domain'] = 'core'
|
|
154
|
+
cmd['lino'] = command['lino']
|
|
155
|
+
cmd['keyword'] = 'gotoPC'
|
|
156
|
+
cmd['goto'] = 0
|
|
157
|
+
cmd['debug'] = False
|
|
158
|
+
self.addCommand(cmd)
|
|
159
|
+
self.compileOne()
|
|
160
|
+
cmd = {}
|
|
161
|
+
cmd['domain'] = 'core'
|
|
162
|
+
cmd['lino'] = command['lino']
|
|
163
|
+
cmd['keyword'] = 'stop'
|
|
164
|
+
cmd['debug'] = False
|
|
165
|
+
self.addCommand(cmd)
|
|
166
|
+
# Fixup the link
|
|
167
|
+
self.getCommandAt(pcNext)['goto'] = self.getPC()
|
|
168
|
+
return True
|
|
169
|
+
return False
|
|
170
|
+
|
|
171
|
+
def r_on(self, command):
|
|
172
|
+
pc = command['goto']
|
|
173
|
+
if command['type'] == 'click':
|
|
174
|
+
event = command['event']
|
|
175
|
+
if event == 'click':
|
|
176
|
+
target = command['target']
|
|
177
|
+
if target == None:
|
|
178
|
+
value = 'screen'
|
|
179
|
+
else:
|
|
180
|
+
widget = self.getVariable(target)
|
|
181
|
+
value = widget['value'][widget['index']]
|
|
182
|
+
setOnClick(value['content'], lambda: self.run(pc))
|
|
183
|
+
elif command['type'] == 'tick':
|
|
184
|
+
setOnTick(lambda: self.run(pc))
|
|
185
|
+
return self.nextPC()
|
|
186
|
+
|
|
187
|
+
def k_rectangle(self, command):
|
|
188
|
+
return self.compileVariable(command)
|
|
189
|
+
|
|
190
|
+
def r_rectangle(self, command):
|
|
191
|
+
return self.nextPC()
|
|
192
|
+
|
|
193
|
+
def k_render(self, command):
|
|
194
|
+
command['value'] = self.nextValue()
|
|
195
|
+
command['parent'] = 'screen'
|
|
196
|
+
if self.peek() == 'in':
|
|
197
|
+
self.nextToken()
|
|
198
|
+
if self.nextIsSymbol():
|
|
199
|
+
record = self.getSymbolRecord()
|
|
200
|
+
type = record['type']
|
|
201
|
+
name = record['name']
|
|
202
|
+
if type in ['rectangle', 'ellipse']:
|
|
203
|
+
command['parent'] = record['name']
|
|
204
|
+
self.add(command)
|
|
205
|
+
return True
|
|
206
|
+
else:
|
|
207
|
+
self.warning(f'Graphics.render: {name} cannot be a parent of another element')
|
|
208
|
+
return False
|
|
209
|
+
self.add(command)
|
|
210
|
+
return True
|
|
211
|
+
FatalError(self.program.compiler, 'Nothing specified to render')
|
|
212
|
+
return False
|
|
213
|
+
|
|
214
|
+
def r_render(self, command):
|
|
215
|
+
parent = command['parent']
|
|
216
|
+
value = self.getRuntimeValue(command['value'])
|
|
217
|
+
render(value, parent)
|
|
218
|
+
return self.nextPC()
|
|
219
|
+
|
|
220
|
+
def k_set(self, command):
|
|
221
|
+
if self.peek() == 'the':
|
|
222
|
+
self.nextToken()
|
|
223
|
+
token = self.peek()
|
|
224
|
+
if token == 'text':
|
|
225
|
+
self.nextToken()
|
|
226
|
+
command['variant'] = 'setText'
|
|
227
|
+
if self.peek() == 'of':
|
|
228
|
+
self.nextToken()
|
|
229
|
+
if self.nextIsSymbol():
|
|
230
|
+
record = self.getSymbolRecord()
|
|
231
|
+
command['name'] = record['name']
|
|
232
|
+
if record['keyword'] != 'text':
|
|
233
|
+
RuntimeError(command['program'], f'Symbol type is not \'text\'')
|
|
234
|
+
if self.peek() == 'to':
|
|
235
|
+
self.nextToken()
|
|
236
|
+
command['value'] = self.nextValue()
|
|
237
|
+
self.add(command)
|
|
238
|
+
return True
|
|
239
|
+
return False
|
|
240
|
+
elif token == 'background':
|
|
241
|
+
self.nextToken()
|
|
242
|
+
command['variant'] = 'setBackground'
|
|
243
|
+
if self.peek() == 'color':
|
|
244
|
+
self.nextToken()
|
|
245
|
+
if self.peek() == 'of':
|
|
246
|
+
self.nextToken()
|
|
247
|
+
if self.nextIsSymbol():
|
|
248
|
+
record = self.getSymbolRecord()
|
|
249
|
+
command['name'] = record['name']
|
|
250
|
+
if not record['keyword'] in ['rectangle', 'ellipse']:
|
|
251
|
+
RuntimeError(command['program'], f'Symbol type is not \'rectangle\' or \'ellipse\'')
|
|
252
|
+
if self.peek() == 'to':
|
|
253
|
+
self.nextToken()
|
|
254
|
+
command['value'] = self.nextValue()
|
|
255
|
+
self.add(command)
|
|
256
|
+
return True
|
|
257
|
+
return False
|
|
258
|
+
return False
|
|
259
|
+
|
|
260
|
+
def r_set(self, command):
|
|
261
|
+
variant = command['variant']
|
|
262
|
+
if variant == 'setText':
|
|
263
|
+
variable = self.getVariable(command['name'])
|
|
264
|
+
element = self.getSymbolValue(variable)
|
|
265
|
+
value = self.getRuntimeValue(command['value'])
|
|
266
|
+
setText(element['content'], value)
|
|
267
|
+
elif variant == 'setBackground':
|
|
268
|
+
variable = self.getVariable(command['name'])
|
|
269
|
+
element = self.getSymbolValue(variable)
|
|
270
|
+
value = self.getRuntimeValue(command['value'])
|
|
271
|
+
setBackground(element['content'], value)
|
|
272
|
+
return self.nextPC()
|
|
273
|
+
|
|
274
|
+
def k_show(self, command):
|
|
275
|
+
if self.nextIs('screen'):
|
|
276
|
+
command['name'] = None
|
|
277
|
+
self.add(command)
|
|
278
|
+
return True
|
|
279
|
+
return False
|
|
280
|
+
|
|
281
|
+
def r_show(self, command):
|
|
282
|
+
showScreen()
|
|
283
|
+
return self.nextPC()
|
|
284
|
+
|
|
285
|
+
def k_spec(self, command):
|
|
286
|
+
return self.compileVariable(command, True)
|
|
287
|
+
|
|
288
|
+
def r_spec(self, command):
|
|
289
|
+
return self.nextPC()
|
|
290
|
+
|
|
291
|
+
def k_text(self, command):
|
|
292
|
+
return self.compileVariable(command)
|
|
293
|
+
|
|
294
|
+
def r_text(self, command):
|
|
295
|
+
return self.nextPC()
|
|
296
|
+
|
|
297
|
+
#############################################################################
|
|
298
|
+
# Compile a value in this domain
|
|
299
|
+
def compileValue(self):
|
|
300
|
+
value = {}
|
|
301
|
+
value['domain'] = 'graphics'
|
|
302
|
+
token = self.getToken()
|
|
303
|
+
if self.isSymbol():
|
|
304
|
+
value['name'] = token
|
|
305
|
+
symbolRecord = self.getSymbolRecord()
|
|
306
|
+
keyword = symbolRecord['keyword']
|
|
307
|
+
if keyword == 'module':
|
|
308
|
+
value['type'] = 'module'
|
|
309
|
+
return value
|
|
310
|
+
|
|
311
|
+
if symbolRecord['valueHolder'] == True or keyword == 'dictionary':
|
|
312
|
+
value['type'] = 'symbol'
|
|
313
|
+
return value
|
|
314
|
+
return None
|
|
315
|
+
|
|
316
|
+
if self.tokenIs('the'):
|
|
317
|
+
self.nextToken()
|
|
318
|
+
token = self.getToken()
|
|
319
|
+
|
|
320
|
+
value['type'] = token
|
|
321
|
+
|
|
322
|
+
if token == 'color':
|
|
323
|
+
name = self.nextToken()
|
|
324
|
+
value = {}
|
|
325
|
+
value['type'] = 'string'
|
|
326
|
+
value['content'] = name
|
|
327
|
+
return value
|
|
328
|
+
|
|
329
|
+
elif token == 'attribute':
|
|
330
|
+
value['attribute'] = self.nextValue()
|
|
331
|
+
if (self.nextIs('of')):
|
|
332
|
+
if (self.nextIsSymbol()):
|
|
333
|
+
value['name'] = self.getToken()
|
|
334
|
+
return value
|
|
335
|
+
return None
|
|
336
|
+
|
|
337
|
+
#############################################################################
|
|
338
|
+
# Modify a value or leave it unchanged.
|
|
339
|
+
def modifyValue(self, value):
|
|
340
|
+
return value
|
|
341
|
+
|
|
342
|
+
#############################################################################
|
|
343
|
+
# Value handlers
|
|
344
|
+
|
|
345
|
+
def v_symbol(self, symbolRecord):
|
|
346
|
+
result = {}
|
|
347
|
+
if symbolRecord['valueHolder']:
|
|
348
|
+
symbolValue = self.getSymbolValue(symbolRecord)
|
|
349
|
+
if symbolValue == None:
|
|
350
|
+
return None
|
|
351
|
+
result['type'] = symbolValue['type']
|
|
352
|
+
content = symbolValue['content']
|
|
353
|
+
if content == None:
|
|
354
|
+
return ''
|
|
355
|
+
result['content'] = content
|
|
356
|
+
return result
|
|
357
|
+
else:
|
|
358
|
+
return ''
|
|
359
|
+
|
|
360
|
+
def v_attribute(self, v):
|
|
361
|
+
target = self.getVariable(v['name'])
|
|
362
|
+
attribute = self.getRuntimeValue(v['attribute'])
|
|
363
|
+
name = target['value'][target['index']]['content']
|
|
364
|
+
value = {}
|
|
365
|
+
value['type'] = 'int'
|
|
366
|
+
value['content'] = getAttribute(name, attribute)
|
|
367
|
+
return value
|
|
368
|
+
|
|
369
|
+
#############################################################################
|
|
370
|
+
# Compile a condition
|
|
371
|
+
def compileCondition(self):
|
|
372
|
+
condition = {}
|
|
373
|
+
return condition
|
|
374
|
+
|
|
375
|
+
#############################################################################
|
|
376
|
+
# Condition handlers
|