beancode 0.3.2__tar.gz → 0.3.4__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.
- {beancode-0.3.2 → beancode-0.3.4}/PKG-INFO +12 -10
- {beancode-0.3.2 → beancode-0.3.4}/README.md +11 -9
- {beancode-0.3.2 → beancode-0.3.4}/beancode/__init__.py +1 -1
- {beancode-0.3.2 → beancode-0.3.4}/beancode/__main__.py +4 -2
- {beancode-0.3.2 → beancode-0.3.4}/beancode/error.py +15 -3
- {beancode-0.3.2 → beancode-0.3.4}/beancode/interpreter.py +3 -0
- {beancode-0.3.2 → beancode-0.3.4}/beancode/repl.py +29 -10
- {beancode-0.3.2 → beancode-0.3.4}/pyproject.toml +1 -1
- {beancode-0.3.2 → beancode-0.3.4}/LICENSE.md +0 -0
- {beancode-0.3.2 → beancode-0.3.4}/beancode/bean_ast.py +0 -0
- {beancode-0.3.2 → beancode-0.3.4}/beancode/bean_ffi.py +0 -0
- {beancode-0.3.2 → beancode-0.3.4}/beancode/lexer.py +0 -0
- {beancode-0.3.2 → beancode-0.3.4}/beancode/modules/__init__.py +0 -0
- {beancode-0.3.2 → beancode-0.3.4}/beancode/modules/beanray.py +0 -0
- {beancode-0.3.2 → beancode-0.3.4}/beancode/modules/beanstd.py +0 -0
- {beancode-0.3.2 → beancode-0.3.4}/beancode/modules/demo_ffimod.py +0 -0
- {beancode-0.3.2 → beancode-0.3.4}/beancode/parser.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: beancode
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: A cursed IGCSE pseudocode interpreter/transpiler
|
|
5
5
|
License: MPL-2.0
|
|
6
6
|
Author: ezntek
|
|
@@ -118,7 +118,7 @@ There are many extra features, which are not standard to IGCSE Pseudocode.
|
|
|
118
118
|
* `STRING -> INTEGER` (returns `null` on failure)
|
|
119
119
|
* `STRING -> REAL` (returns `null` on failure)
|
|
120
120
|
* `INTEGER -> REAL`
|
|
121
|
-
|
|
121
|
+
*`REAL -> INTEGER`
|
|
122
122
|
* `INTEGER -> BOOLEAN` (`0` is false, `1` is true)
|
|
123
123
|
* `BOOLEAN -> INTEGER`
|
|
124
124
|
6. Declaration and assignment on the same line is also supported: `DECLARE Num:INTEGER <- 5`
|
|
@@ -132,6 +132,15 @@ There are many extra features, which are not standard to IGCSE Pseudocode.
|
|
|
132
132
|
OUTPUT X // works
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
+
### REPL features
|
|
136
|
+
|
|
137
|
+
* `.var` gets information regarding an _existing variable_. It prints its name, type, and value.
|
|
138
|
+
* `.vars` prints information regarding _all variables_.
|
|
139
|
+
* `.func` gets information regarding *existing functions* ***or procedures***.
|
|
140
|
+
* `.funcs` prints information regarding _all functions and procedures_.
|
|
141
|
+
* Delete a variable if you need to with `.delete [name]`. (Version `0.3.4` and up)
|
|
142
|
+
* Or, reset the entire interpreter's state with `.reset`.
|
|
143
|
+
|
|
135
144
|
## quirks
|
|
136
145
|
|
|
137
146
|
* ***Multiple statements in CASE OFs are not supported! Therefore, the following code is illegal:***
|
|
@@ -169,7 +178,7 @@ Python was perfect due to its dynamism, and the fact that I could abuse it to th
|
|
|
169
178
|
|
|
170
179
|
### Performance
|
|
171
180
|
|
|
172
|
-
It's really bad. However, PyPy makes it a lot better. Here's some data for the PrimeTorture benchmark
|
|
181
|
+
It's really bad. However, PyPy makes it a lot better. Here's some data for the PrimeTorture benchmark in the examples, ran on an i7-14700KF with 32GB RAM on Arch Linux:
|
|
173
182
|
|
|
174
183
|
|Language|Time Taken (s)|
|
|
175
184
|
|--------|----------|
|
|
@@ -180,13 +189,6 @@ It's really bad. However, PyPy makes it a lot better. Here's some data for the P
|
|
|
180
189
|
|Python (PyPy3)|0.19|
|
|
181
190
|
|C (gcc 15.2.1)|0.1|
|
|
182
191
|
|
|
183
|
-
beancode+cpython: 148 seconds
|
|
184
|
-
beancode+pypy3: 11 seconds
|
|
185
|
-
beancode+nuitka: 185 seconds
|
|
186
|
-
cpython: 0.88 seconds
|
|
187
|
-
pypy3: 0.19 seconds
|
|
188
|
-
C: 0.1 seconds
|
|
189
|
-
|
|
190
192
|
## Errata
|
|
191
193
|
|
|
192
194
|
* Some errors will report as `unused expression`, like the following:
|
|
@@ -102,7 +102,7 @@ There are many extra features, which are not standard to IGCSE Pseudocode.
|
|
|
102
102
|
* `STRING -> INTEGER` (returns `null` on failure)
|
|
103
103
|
* `STRING -> REAL` (returns `null` on failure)
|
|
104
104
|
* `INTEGER -> REAL`
|
|
105
|
-
|
|
105
|
+
*`REAL -> INTEGER`
|
|
106
106
|
* `INTEGER -> BOOLEAN` (`0` is false, `1` is true)
|
|
107
107
|
* `BOOLEAN -> INTEGER`
|
|
108
108
|
6. Declaration and assignment on the same line is also supported: `DECLARE Num:INTEGER <- 5`
|
|
@@ -116,6 +116,15 @@ There are many extra features, which are not standard to IGCSE Pseudocode.
|
|
|
116
116
|
OUTPUT X // works
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
+
### REPL features
|
|
120
|
+
|
|
121
|
+
* `.var` gets information regarding an _existing variable_. It prints its name, type, and value.
|
|
122
|
+
* `.vars` prints information regarding _all variables_.
|
|
123
|
+
* `.func` gets information regarding *existing functions* ***or procedures***.
|
|
124
|
+
* `.funcs` prints information regarding _all functions and procedures_.
|
|
125
|
+
* Delete a variable if you need to with `.delete [name]`. (Version `0.3.4` and up)
|
|
126
|
+
* Or, reset the entire interpreter's state with `.reset`.
|
|
127
|
+
|
|
119
128
|
## quirks
|
|
120
129
|
|
|
121
130
|
* ***Multiple statements in CASE OFs are not supported! Therefore, the following code is illegal:***
|
|
@@ -153,7 +162,7 @@ Python was perfect due to its dynamism, and the fact that I could abuse it to th
|
|
|
153
162
|
|
|
154
163
|
### Performance
|
|
155
164
|
|
|
156
|
-
It's really bad. However, PyPy makes it a lot better. Here's some data for the PrimeTorture benchmark
|
|
165
|
+
It's really bad. However, PyPy makes it a lot better. Here's some data for the PrimeTorture benchmark in the examples, ran on an i7-14700KF with 32GB RAM on Arch Linux:
|
|
157
166
|
|
|
158
167
|
|Language|Time Taken (s)|
|
|
159
168
|
|--------|----------|
|
|
@@ -164,13 +173,6 @@ It's really bad. However, PyPy makes it a lot better. Here's some data for the P
|
|
|
164
173
|
|Python (PyPy3)|0.19|
|
|
165
174
|
|C (gcc 15.2.1)|0.1|
|
|
166
175
|
|
|
167
|
-
beancode+cpython: 148 seconds
|
|
168
|
-
beancode+pypy3: 11 seconds
|
|
169
|
-
beancode+nuitka: 185 seconds
|
|
170
|
-
cpython: 0.88 seconds
|
|
171
|
-
pypy3: 0.19 seconds
|
|
172
|
-
C: 0.1 seconds
|
|
173
|
-
|
|
174
176
|
## Errata
|
|
175
177
|
|
|
176
178
|
* Some errors will report as `unused expression`, like the following:
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import io
|
|
1
2
|
import os
|
|
2
3
|
import sys
|
|
3
4
|
import argparse
|
|
5
|
+
from typing import NoReturn
|
|
4
6
|
|
|
5
7
|
from .repl import Repl
|
|
6
8
|
|
|
@@ -10,7 +12,6 @@ from .parser import Parser
|
|
|
10
12
|
from .error import *
|
|
11
13
|
from . import __version__
|
|
12
14
|
|
|
13
|
-
|
|
14
15
|
def _error(s: str) -> NoReturn:
|
|
15
16
|
error(s)
|
|
16
17
|
exit(1)
|
|
@@ -104,10 +105,11 @@ def real_main():
|
|
|
104
105
|
|
|
105
106
|
|
|
106
107
|
def main():
|
|
108
|
+
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors="replace")
|
|
109
|
+
sys.stderr = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors="replace")
|
|
107
110
|
try:
|
|
108
111
|
if len(sys.argv) == 1:
|
|
109
112
|
sys.exit(Repl().repl())
|
|
110
|
-
|
|
111
113
|
real_main()
|
|
112
114
|
except KeyboardInterrupt:
|
|
113
115
|
warn("caught keyboard interrupt")
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import sys
|
|
2
|
-
|
|
2
|
+
import os
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class BCError(Exception):
|
|
@@ -69,7 +69,14 @@ class BCError(Exception):
|
|
|
69
69
|
|
|
70
70
|
tildes = f"{spaces()}\033[31;1m{'~' * self.len}\033[0m"
|
|
71
71
|
print(tildes)
|
|
72
|
-
|
|
72
|
+
|
|
73
|
+
indicator = f"{spaces()}\033[31;1m"
|
|
74
|
+
if os.name == "nt":
|
|
75
|
+
indicator += "+-"
|
|
76
|
+
else:
|
|
77
|
+
indicator += "∟"
|
|
78
|
+
|
|
79
|
+
indicator += f" \033[0m\033[1merror at line {line} column {col}\033[0m"
|
|
73
80
|
print(indicator)
|
|
74
81
|
|
|
75
82
|
|
|
@@ -117,7 +124,12 @@ class BCWarning(Exception):
|
|
|
117
124
|
|
|
118
125
|
tildes = f"{spaces()}\033[35;1m{'~' * self.len}\033[0m"
|
|
119
126
|
print(tildes)
|
|
120
|
-
indicator = f"{spaces()}\033[35;1m
|
|
127
|
+
indicator = f"{spaces()}\033[35;1m"
|
|
128
|
+
if os.name == "nt":
|
|
129
|
+
indicator += "+-"
|
|
130
|
+
else:
|
|
131
|
+
indicator += "∟"
|
|
132
|
+
indicator += f" \033[0m\033[1mwarning at line {line} column {col}\033[0m"
|
|
121
133
|
print(indicator)
|
|
122
134
|
|
|
123
135
|
|
|
@@ -1512,6 +1512,9 @@ class Interpreter:
|
|
|
1512
1512
|
self.variables[name] = var
|
|
1513
1513
|
|
|
1514
1514
|
for name, fn in intp.functions.items():
|
|
1515
|
+
if isinstance(fn, BCFunction) or isinstance(fn, BCProcedure):
|
|
1516
|
+
continue
|
|
1517
|
+
|
|
1515
1518
|
if fn.export: # type: ignore
|
|
1516
1519
|
self.functions[name] = fn
|
|
1517
1520
|
|
|
@@ -34,15 +34,16 @@ type ".help" for a list of REPL commands, ".exit" to exit, or start typing some
|
|
|
34
34
|
"""
|
|
35
35
|
|
|
36
36
|
HELP = """\033[1mAVAILABLE COMMANDS:\033[0m
|
|
37
|
-
.var [names]
|
|
38
|
-
.vars
|
|
39
|
-
.func [names]
|
|
40
|
-
.funcs
|
|
41
|
-
.
|
|
42
|
-
.
|
|
43
|
-
.
|
|
44
|
-
.
|
|
45
|
-
.
|
|
37
|
+
.var [names] get information regarding a declared variable/constant
|
|
38
|
+
.vars get information regarding all declared variables/constants
|
|
39
|
+
.func [names] get information regarding a declared procedure/function
|
|
40
|
+
.funcs get information regarding all declared procedures/functions
|
|
41
|
+
.delete [names] delete a variable/constant/procedure/function
|
|
42
|
+
.reset reset the interpreter
|
|
43
|
+
.help show this help message
|
|
44
|
+
.clear clear the screen
|
|
45
|
+
.version print the version
|
|
46
|
+
.exit exit the interpreter (.quit also works)
|
|
46
47
|
"""
|
|
47
48
|
|
|
48
49
|
|
|
@@ -227,8 +228,24 @@ class Repl:
|
|
|
227
228
|
|
|
228
229
|
return DotCommandResult.NO_OP
|
|
229
230
|
|
|
231
|
+
def _delete(self, args: list[str]) -> DotCommandResult:
|
|
232
|
+
if len(args) == 1:
|
|
233
|
+
error("not enough args for delete")
|
|
234
|
+
return DotCommandResult.NO_OP
|
|
235
|
+
|
|
236
|
+
for arg in args[1:]:
|
|
237
|
+
if arg in self.i.variables:
|
|
238
|
+
self.i.variables.__delitem__(arg)
|
|
239
|
+
info(f"deleted variable \"{arg}\"")
|
|
240
|
+
elif arg in self.i.functions:
|
|
241
|
+
self.i.functions.__delitem__(arg)
|
|
242
|
+
info(f"deleted function/procedure \"{arg}\"")
|
|
243
|
+
else:
|
|
244
|
+
error(f"no name \"{arg}\" found")
|
|
245
|
+
return DotCommandResult.NO_OP
|
|
246
|
+
|
|
230
247
|
def handle_dot_command(self, s: str) -> DotCommandResult:
|
|
231
|
-
args = s.split(" ")
|
|
248
|
+
args = s.strip().split(" ")
|
|
232
249
|
base = args[0]
|
|
233
250
|
|
|
234
251
|
match base:
|
|
@@ -255,6 +272,8 @@ class Repl:
|
|
|
255
272
|
return self._func(args)
|
|
256
273
|
case "funcs":
|
|
257
274
|
return self._funcs(args)
|
|
275
|
+
case "delete":
|
|
276
|
+
return self._delete(args)
|
|
258
277
|
|
|
259
278
|
return DotCommandResult.UNKNOWN_COMMAND
|
|
260
279
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|