coco-tools 0.17__tar.gz → 0.19__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.
- {coco-tools-0.17 → coco-tools-0.19}/PKG-INFO +11 -4
- {coco-tools-0.17 → coco-tools-0.19}/README.md +10 -3
- {coco-tools-0.17 → coco-tools-0.19}/coco/__init__.py +1 -1
- {coco-tools-0.17 → coco-tools-0.19}/coco/b09/compiler.py +16 -2
- coco-tools-0.19/coco/b09/configs.py +37 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco/b09/elements.py +76 -21
- {coco-tools-0.17 → coco-tools-0.19}/coco/b09/grammar.py +3 -3
- {coco-tools-0.17 → coco-tools-0.19}/coco/b09/parser.py +10 -4
- {coco-tools-0.17 → coco-tools-0.19}/coco/b09/visitors.py +63 -24
- {coco-tools-0.17 → coco-tools-0.19}/coco/decb_to_b09.py +8 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco/resources/ecb.b09 +8 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco_tools.egg-info/PKG-INFO +11 -4
- {coco-tools-0.17 → coco-tools-0.19}/coco_tools.egg-info/SOURCES.txt +1 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco_tools.egg-info/requires.txt +2 -0
- {coco-tools-0.17 → coco-tools-0.19}/setup.py +3 -1
- {coco-tools-0.17 → coco-tools-0.19}/LICENSE +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco/b09/__init__.py +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco/b09/error_handler.py +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco/b09/procbank.py +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco/b09/prog.py +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco/cm3toppm.py +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco/hrstoppm.py +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco/maxtoppm.py +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco/mge_viewer2.py +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco/mgetoppm.py +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco/pixtopgm.py +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco/rattoppm.py +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco/resources/__init__.py +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco/util.py +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco/veftopng.py +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco_tools.egg-info/dependency_links.txt +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco_tools.egg-info/entry_points.txt +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/coco_tools.egg-info/top_level.txt +0 -0
- {coco-tools-0.17 → coco-tools-0.19}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: coco-tools
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.19
|
|
4
4
|
Summary: TRS-80 Color Computer Tools
|
|
5
5
|
Home-page: https://github.com/jamieleecho/coco-tools
|
|
6
6
|
Author: Jamie Cho
|
|
@@ -38,27 +38,33 @@ python3 setup.py
|
|
|
38
38
|
### [decb-to-b09](./README.decb-to-b09.md)
|
|
39
39
|
|
|
40
40
|
```
|
|
41
|
-
usage: decb-to-b09 [-h] [--version] [-l] [-z] [-D] [-w]
|
|
41
|
+
usage: decb-to-b09 [-h] [--version] [-l] [-z] [-s DEFAULT_STRING_STORAGE] [-D] [-w]
|
|
42
|
+
[-c CONFIG_FILE]
|
|
43
|
+
program.bas program.b09
|
|
42
44
|
|
|
43
45
|
Convert a Color BASIC program to a BASIC09 program
|
|
44
46
|
Copyright (c) 2023 by Jamie Cho
|
|
45
|
-
Version: 0.
|
|
47
|
+
Version: 0.18
|
|
46
48
|
|
|
47
49
|
positional arguments:
|
|
48
50
|
program.bas input DECB text program file
|
|
49
51
|
program.b09 output BASIC09 text program file
|
|
50
52
|
|
|
51
|
-
|
|
53
|
+
optional arguments:
|
|
52
54
|
-h, --help show this help message and exit
|
|
53
55
|
--version show program's version number and exit
|
|
54
56
|
-l, --filter-unused-linenum
|
|
55
57
|
Filter out line numbers not referenced by the program
|
|
56
58
|
-z, --dont-initialize-vars
|
|
57
59
|
Don't pre-initialize all variables
|
|
60
|
+
-s DEFAULT_STRING_STORAGE, --default-string-storage DEFAULT_STRING_STORAGE
|
|
61
|
+
Bytes to allocate for each string
|
|
58
62
|
-D, --dont-output-dependencies
|
|
59
63
|
Don't output required dependencies
|
|
60
64
|
-w, --dont-run-width-32
|
|
61
65
|
if set don't run the default width 32
|
|
66
|
+
-c CONFIG_FILE, --config-file CONFIG_FILE
|
|
67
|
+
Optional compiler configuration file
|
|
62
68
|
```
|
|
63
69
|
|
|
64
70
|
### cm3toppm
|
|
@@ -263,6 +269,7 @@ The programs in the examples/decb and examples/other-decb-examples-to-try direct
|
|
|
263
269
|
* banner.bas -- https://colorcomputerarchive.com/repo/MC-10/Software/Books/TRS-80%20Color%20Computer%20%26%20MC-10%20Programs/banner.c10
|
|
264
270
|
* cadnza.bas -- https://colorcomputerarchive.com/repo/MC-10/Software/Books/TRS-80%20Color%20Computer%20%26%20MC-10%20Programs/cadnza.c10
|
|
265
271
|
* cflip.bas -- https://colorcomputerarchive.com/repo/MC-10/Software/Books/TRS-80%20Color%20Computer%20%26%20MC-10%20Programs/cflip.c10
|
|
272
|
+
* flip.bas -- https://github.com/daftspaniel/RetroCornerRedux/blob/main/Dragon/Originals/FlipBits/flip.bas
|
|
266
273
|
* loops.bas -- https://colorcomputerarchive.com/repo/Documents/Manuals/Hardware/Color%20Computer%203%20Extended%20Basic%20(Tandy).pdf
|
|
267
274
|
* f15eagle.bas -- https://colorcomputerarchive.com/repo/Disks/Magazines/Rainbow%20On%20Disk.zip
|
|
268
275
|
* mars.bas -- https://github.com/jggames/trs80mc10/tree/9df4c9578250009d68a03101d626faa3c22e7445/quicktype/Text%20Adventures/WorkInProgress/Mars
|
|
@@ -20,27 +20,33 @@ python3 setup.py
|
|
|
20
20
|
### [decb-to-b09](./README.decb-to-b09.md)
|
|
21
21
|
|
|
22
22
|
```
|
|
23
|
-
usage: decb-to-b09 [-h] [--version] [-l] [-z] [-D] [-w]
|
|
23
|
+
usage: decb-to-b09 [-h] [--version] [-l] [-z] [-s DEFAULT_STRING_STORAGE] [-D] [-w]
|
|
24
|
+
[-c CONFIG_FILE]
|
|
25
|
+
program.bas program.b09
|
|
24
26
|
|
|
25
27
|
Convert a Color BASIC program to a BASIC09 program
|
|
26
28
|
Copyright (c) 2023 by Jamie Cho
|
|
27
|
-
Version: 0.
|
|
29
|
+
Version: 0.18
|
|
28
30
|
|
|
29
31
|
positional arguments:
|
|
30
32
|
program.bas input DECB text program file
|
|
31
33
|
program.b09 output BASIC09 text program file
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
optional arguments:
|
|
34
36
|
-h, --help show this help message and exit
|
|
35
37
|
--version show program's version number and exit
|
|
36
38
|
-l, --filter-unused-linenum
|
|
37
39
|
Filter out line numbers not referenced by the program
|
|
38
40
|
-z, --dont-initialize-vars
|
|
39
41
|
Don't pre-initialize all variables
|
|
42
|
+
-s DEFAULT_STRING_STORAGE, --default-string-storage DEFAULT_STRING_STORAGE
|
|
43
|
+
Bytes to allocate for each string
|
|
40
44
|
-D, --dont-output-dependencies
|
|
41
45
|
Don't output required dependencies
|
|
42
46
|
-w, --dont-run-width-32
|
|
43
47
|
if set don't run the default width 32
|
|
48
|
+
-c CONFIG_FILE, --config-file CONFIG_FILE
|
|
49
|
+
Optional compiler configuration file
|
|
44
50
|
```
|
|
45
51
|
|
|
46
52
|
### cm3toppm
|
|
@@ -245,6 +251,7 @@ The programs in the examples/decb and examples/other-decb-examples-to-try direct
|
|
|
245
251
|
* banner.bas -- https://colorcomputerarchive.com/repo/MC-10/Software/Books/TRS-80%20Color%20Computer%20%26%20MC-10%20Programs/banner.c10
|
|
246
252
|
* cadnza.bas -- https://colorcomputerarchive.com/repo/MC-10/Software/Books/TRS-80%20Color%20Computer%20%26%20MC-10%20Programs/cadnza.c10
|
|
247
253
|
* cflip.bas -- https://colorcomputerarchive.com/repo/MC-10/Software/Books/TRS-80%20Color%20Computer%20%26%20MC-10%20Programs/cflip.c10
|
|
254
|
+
* flip.bas -- https://github.com/daftspaniel/RetroCornerRedux/blob/main/Dragon/Originals/FlipBits/flip.bas
|
|
248
255
|
* loops.bas -- https://colorcomputerarchive.com/repo/Documents/Manuals/Hardware/Color%20Computer%203%20Extended%20Basic%20(Tandy).pdf
|
|
249
256
|
* f15eagle.bas -- https://colorcomputerarchive.com/repo/Disks/Magazines/Rainbow%20On%20Disk.zip
|
|
250
257
|
* mars.bas -- https://github.com/jggames/trs80mc10/tree/9df4c9578250009d68a03101d626faa3c22e7445/quicktype/Text%20Adventures/WorkInProgress/Mars
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# __version__ MUST be defined on line 2
|
|
2
|
-
__version__ = "0.
|
|
2
|
+
__version__ = "0.19"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from pathlib import Path
|
|
1
2
|
from typing import List
|
|
2
3
|
|
|
3
4
|
from coco import b09
|
|
@@ -12,6 +13,7 @@ from coco.b09.elements import (
|
|
|
12
13
|
BasicRunCall,
|
|
13
14
|
BasicVar,
|
|
14
15
|
)
|
|
16
|
+
from coco.b09.configs import CompilerConfigs
|
|
15
17
|
from coco.b09.grammar import grammar, PROCNAME_REGEX
|
|
16
18
|
from coco.b09.parser import BasicVisitor
|
|
17
19
|
from coco.b09.procbank import ProcedureBank
|
|
@@ -32,6 +34,7 @@ from coco.b09.visitors import (
|
|
|
32
34
|
LineReferenceVisitor,
|
|
33
35
|
LineZeroFilterVisitor,
|
|
34
36
|
SetDimStringStorageVisitor,
|
|
37
|
+
SetInitializeVisitor,
|
|
35
38
|
StatementCollectorVisitor,
|
|
36
39
|
StrVarAllocatorVisitor,
|
|
37
40
|
VarInitializerVisitor,
|
|
@@ -47,6 +50,7 @@ def convert(
|
|
|
47
50
|
*,
|
|
48
51
|
add_standard_prefix: bool = True,
|
|
49
52
|
add_suffix: bool = True,
|
|
53
|
+
compiler_configs: CompilerConfigs = None,
|
|
50
54
|
default_str_storage: int = b09.DEFAULT_STR_STORAGE,
|
|
51
55
|
default_width32: bool = True,
|
|
52
56
|
filter_unused_linenum: bool = False,
|
|
@@ -55,6 +59,7 @@ def convert(
|
|
|
55
59
|
procname: str = "",
|
|
56
60
|
skip_procedure_headers: bool = False,
|
|
57
61
|
) -> str:
|
|
62
|
+
compiler_configs = compiler_configs or CompilerConfigs()
|
|
58
63
|
tree = grammar.parse(progin)
|
|
59
64
|
bv = BasicVisitor()
|
|
60
65
|
basic_prog: BasicProg = bv.visit(tree)
|
|
@@ -124,7 +129,8 @@ def convert(
|
|
|
124
129
|
basic_prog.visit(BasicFunctionalExpressionPatcherVisitor())
|
|
125
130
|
|
|
126
131
|
set_string_storage_vistor: SetDimStringStorageVisitor = SetDimStringStorageVisitor(
|
|
127
|
-
default_str_storage=default_str_storage
|
|
132
|
+
default_str_storage=default_str_storage,
|
|
133
|
+
string_configs=compiler_configs.string_configs,
|
|
128
134
|
)
|
|
129
135
|
basic_prog.visit(set_string_storage_vistor)
|
|
130
136
|
|
|
@@ -133,9 +139,10 @@ def convert(
|
|
|
133
139
|
basic_prog.visit(dimmed_array_visitor)
|
|
134
140
|
declare_array_visitor = DeclareImplicitArraysVisitor(
|
|
135
141
|
dimmed_var_names=dimmed_array_visitor.dimmed_var_names,
|
|
142
|
+
initialize_vars=initialize_vars,
|
|
136
143
|
)
|
|
137
144
|
basic_prog.visit(declare_array_visitor)
|
|
138
|
-
basic_prog.
|
|
145
|
+
basic_prog.insert_lines_at_beginning(declare_array_visitor.dim_statements)
|
|
139
146
|
|
|
140
147
|
# allocate sufficient string storage
|
|
141
148
|
str_var_allocator: StrVarAllocatorVisitor = StrVarAllocatorVisitor(
|
|
@@ -150,6 +157,8 @@ def convert(
|
|
|
150
157
|
var_initializer = VarInitializerVisitor()
|
|
151
158
|
basic_prog.visit(var_initializer)
|
|
152
159
|
basic_prog.extend_prefix_lines(var_initializer.assignment_lines)
|
|
160
|
+
set_init_visitor = SetInitializeVisitor(initialize_vars)
|
|
161
|
+
basic_prog.visit(set_init_visitor)
|
|
153
162
|
|
|
154
163
|
# remove unused line numbers
|
|
155
164
|
line_ref_visitor = LineReferenceVisitor()
|
|
@@ -238,6 +247,7 @@ def convert_file(
|
|
|
238
247
|
output_program_file: str,
|
|
239
248
|
*,
|
|
240
249
|
add_standard_prefix: bool = True,
|
|
250
|
+
config_file: str = None,
|
|
241
251
|
default_width32: bool = True,
|
|
242
252
|
default_str_storage: int = b09.DEFAULT_STR_STORAGE,
|
|
243
253
|
filter_unused_linenum: bool = False,
|
|
@@ -246,9 +256,13 @@ def convert_file(
|
|
|
246
256
|
procname: str = "",
|
|
247
257
|
) -> None:
|
|
248
258
|
progin = input_program_file.read()
|
|
259
|
+
compiler_configs = (
|
|
260
|
+
CompilerConfigs.load(Path(config_file)) if config_file else CompilerConfigs()
|
|
261
|
+
)
|
|
249
262
|
progout = convert(
|
|
250
263
|
progin,
|
|
251
264
|
add_standard_prefix=add_standard_prefix,
|
|
265
|
+
compiler_configs=compiler_configs,
|
|
252
266
|
default_str_storage=default_str_storage,
|
|
253
267
|
default_width32=default_width32,
|
|
254
268
|
filter_unused_linenum=filter_unused_linenum,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from pydantic import BaseModel, Field, field_validator
|
|
4
|
+
from pydantic_yaml import parse_yaml_raw_as
|
|
5
|
+
from typing import Dict
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class StringConfigs(BaseModel):
|
|
9
|
+
strname_to_size: Dict[str, int] = Field(default_factory=lambda: {})
|
|
10
|
+
|
|
11
|
+
@field_validator("strname_to_size")
|
|
12
|
+
@classmethod
|
|
13
|
+
def check_mappings(cls, val: Dict[str, int]):
|
|
14
|
+
valid_var_regex = re.compile(r"[A-Z][A-Z_0-9]?")
|
|
15
|
+
|
|
16
|
+
for key, sz in val.items():
|
|
17
|
+
assert key.endswith("$") or key.endswith(
|
|
18
|
+
"$()"
|
|
19
|
+
), f"{key} must end with a $ or $()"
|
|
20
|
+
assert key == key.upper(), f"{key} must be all caps"
|
|
21
|
+
var_only = key[: key.find("$")]
|
|
22
|
+
assert 1 <= len(var_only) <= 2, f"{var_only} must be 1 or 2 characters"
|
|
23
|
+
assert valid_var_regex.match(
|
|
24
|
+
var_only
|
|
25
|
+
), f"{var_only} must be a valid BASIC name"
|
|
26
|
+
assert 0 < sz < 32767, f"{sz} for {key} must be between 0 and 32767"
|
|
27
|
+
return val
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class CompilerConfigs(BaseModel):
|
|
31
|
+
string_configs: StringConfigs = Field(default_factory=lambda: StringConfigs())
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
def load(cls, path: Path) -> "CompilerConfigs":
|
|
35
|
+
with open(path) as handle:
|
|
36
|
+
yaml = handle.read()
|
|
37
|
+
return parse_yaml_raw_as(cls, yaml)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
|
+
from collections import defaultdict
|
|
2
3
|
from itertools import chain
|
|
3
|
-
from typing import List, Literal, TYPE_CHECKING, Union
|
|
4
|
+
from typing import Dict, List, Literal, TYPE_CHECKING, Union
|
|
4
5
|
|
|
5
6
|
from coco.b09 import DEFAULT_STR_STORAGE
|
|
6
7
|
|
|
@@ -969,8 +970,15 @@ class BasicJoystkExpression(BasicFunctionalExpression):
|
|
|
969
970
|
class BasicDimStatement(AbstractBasicStatement):
|
|
970
971
|
_default_str_storage: int
|
|
971
972
|
_dim_vars: List["BasicArrayRef | BasicVar"]
|
|
973
|
+
_initialize_vars: bool
|
|
974
|
+
_strname_to_size: Dict[str, int]
|
|
972
975
|
|
|
973
|
-
def __init__(
|
|
976
|
+
def __init__(
|
|
977
|
+
self,
|
|
978
|
+
dim_vars: List["BasicArrayRef | BasicVar"],
|
|
979
|
+
*,
|
|
980
|
+
initialize_vars: bool = False,
|
|
981
|
+
):
|
|
974
982
|
super().__init__()
|
|
975
983
|
self._default_str_storage = DEFAULT_STR_STORAGE
|
|
976
984
|
self._dim_vars = [
|
|
@@ -990,20 +998,48 @@ class BasicDimStatement(AbstractBasicStatement):
|
|
|
990
998
|
)
|
|
991
999
|
for var in dim_vars
|
|
992
1000
|
]
|
|
1001
|
+
self._initialize_vars = initialize_vars
|
|
1002
|
+
self._strname_to_size = {}
|
|
993
1003
|
|
|
994
1004
|
@property
|
|
995
1005
|
def default_str_storage(self):
|
|
996
1006
|
return self._default_str_storage
|
|
997
1007
|
|
|
1008
|
+
@default_str_storage.setter
|
|
1009
|
+
def default_str_storage(self, val):
|
|
1010
|
+
self._default_str_storage = val
|
|
1011
|
+
|
|
998
1012
|
@property
|
|
999
1013
|
def dim_vars(self) -> List["BasicArrayRef | BasicVar"]:
|
|
1000
1014
|
return self._dim_vars
|
|
1001
1015
|
|
|
1002
|
-
@
|
|
1003
|
-
def
|
|
1004
|
-
self.
|
|
1016
|
+
@property
|
|
1017
|
+
def initialize_vars(self) -> bool:
|
|
1018
|
+
return self._initialize_vars
|
|
1019
|
+
|
|
1020
|
+
@initialize_vars.setter
|
|
1021
|
+
def initialize_vars(self, val: bool) -> None:
|
|
1022
|
+
self._initialize_vars = val
|
|
1023
|
+
|
|
1024
|
+
@property
|
|
1025
|
+
def strname_to_size(self):
|
|
1026
|
+
return self._strname_to_size
|
|
1027
|
+
|
|
1028
|
+
@strname_to_size.setter
|
|
1029
|
+
def strname_to_size(self, val):
|
|
1030
|
+
self._strname_to_size = val
|
|
1031
|
+
|
|
1032
|
+
def init_text_for_var(self, dim_var: "BasicArrayRef | BasicVar") -> str:
|
|
1033
|
+
if isinstance(dim_var, BasicVar):
|
|
1034
|
+
return BasicStatements(
|
|
1035
|
+
[
|
|
1036
|
+
BasicAssignment(
|
|
1037
|
+
dim_var, BasicLiteral("" if dim_var.is_str_expr else 0)
|
|
1038
|
+
),
|
|
1039
|
+
],
|
|
1040
|
+
multi_line=False,
|
|
1041
|
+
).basic09_text(0)
|
|
1005
1042
|
|
|
1006
|
-
def init_text_for_var(self, dim_var):
|
|
1007
1043
|
for_statements = (
|
|
1008
1044
|
BasicForStatement(
|
|
1009
1045
|
BasicVar(f"tmp_{ii + 1}"),
|
|
@@ -1057,19 +1093,39 @@ class BasicDimStatement(AbstractBasicStatement):
|
|
|
1057
1093
|
)
|
|
1058
1094
|
]
|
|
1059
1095
|
|
|
1060
|
-
|
|
1096
|
+
str_var_names_to_exp = {
|
|
1097
|
+
str_var.name()
|
|
1098
|
+
if isinstance(str_var, BasicVar)
|
|
1099
|
+
else str_var.var.name(): str_var
|
|
1100
|
+
for str_var in str_vars
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
str_var_to_size = {
|
|
1104
|
+
str_var: self.strname_to_size[str_name]
|
|
1105
|
+
if str_name in self.strname_to_size
|
|
1106
|
+
else self.default_str_storage
|
|
1107
|
+
for str_name, str_var in str_var_names_to_exp.items()
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
str_size_to_strs: Dict[int, List[BasicVar | BasicArrayRef]] = defaultdict(list)
|
|
1111
|
+
for var, size in str_var_to_size.items():
|
|
1112
|
+
str_size_to_strs[size].append(var)
|
|
1113
|
+
|
|
1114
|
+
str_vars_text_list: List[str] = [
|
|
1061
1115
|
self._basic09_text(
|
|
1062
|
-
|
|
1063
|
-
""
|
|
1064
|
-
if self.default_str_storage == DEFAULT_STR_STORAGE
|
|
1065
|
-
else f": STRING[{self._default_str_storage}]",
|
|
1116
|
+
list_vars,
|
|
1117
|
+
"" if size == DEFAULT_STR_STORAGE else f": STRING[{size}]",
|
|
1066
1118
|
indent_level,
|
|
1067
1119
|
)
|
|
1068
|
-
|
|
1069
|
-
|
|
1120
|
+
for size, list_vars in str_size_to_strs.items()
|
|
1121
|
+
]
|
|
1122
|
+
|
|
1123
|
+
str_vars_text = (
|
|
1124
|
+
("\n".join(str_vars_text_list) + ("\n" if non_str_vars else ""))
|
|
1125
|
+
if str_vars_text_list
|
|
1070
1126
|
else ""
|
|
1071
1127
|
)
|
|
1072
|
-
non_str_vars_text
|
|
1128
|
+
non_str_vars_text = (
|
|
1073
1129
|
self._basic09_text(non_str_vars, "", indent_level) if non_str_vars else ""
|
|
1074
1130
|
)
|
|
1075
1131
|
|
|
@@ -1081,14 +1137,13 @@ class BasicDimStatement(AbstractBasicStatement):
|
|
|
1081
1137
|
dim_var_text: str = ", ".join(
|
|
1082
1138
|
(dim_var.basic09_text(indent_level) for dim_var in dim_vars)
|
|
1083
1139
|
)
|
|
1084
|
-
|
|
1085
|
-
(
|
|
1086
|
-
self.init_text_for_var(dim_var)
|
|
1087
|
-
for dim_var in dim_vars
|
|
1088
|
-
if isinstance(dim_var, BasicArrayRef)
|
|
1140
|
+
if self.initialize_vars:
|
|
1141
|
+
init_text = "\n".join(
|
|
1142
|
+
(self.init_text_for_var(dim_var) for dim_var in dim_vars)
|
|
1089
1143
|
)
|
|
1090
|
-
|
|
1091
|
-
|
|
1144
|
+
init_text = "\n" + init_text if init_text else ""
|
|
1145
|
+
else:
|
|
1146
|
+
init_text = ""
|
|
1092
1147
|
|
|
1093
1148
|
return (
|
|
1094
1149
|
f"{super().basic09_text(indent_level)}"
|
|
@@ -49,7 +49,7 @@ QUOTED_STR3_FUNCTION_NAMES = [f'"{name}"' for name in STR3_FUNCTIONS]
|
|
|
49
49
|
|
|
50
50
|
STR_NUM_FUNCTIONS = {
|
|
51
51
|
"ASC": "ASC",
|
|
52
|
-
"VAL": "
|
|
52
|
+
"VAL": "RUN ecb_val",
|
|
53
53
|
"LEN": "LEN",
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -214,7 +214,7 @@ KEYWORDS = "|".join(
|
|
|
214
214
|
|
|
215
215
|
grammar = Grammar(
|
|
216
216
|
rf"""
|
|
217
|
-
aaa_prog = multi_line eol* ~r"\x00?" eof
|
|
217
|
+
aaa_prog = (space* eol+)* multi_line eol* ~r"\x00?" eof
|
|
218
218
|
multi_line = line space* multi_line_elements
|
|
219
219
|
multi_line_elements = multi_line_element*
|
|
220
220
|
multi_line_element = eol+ line space*
|
|
@@ -380,7 +380,7 @@ grammar = Grammar(
|
|
|
380
380
|
comment_text = ~r".*"
|
|
381
381
|
comment_token = ~r"(REM|')"
|
|
382
382
|
eof = ~r"$"
|
|
383
|
-
eol = ~r"[\n\r]
|
|
383
|
+
eol = ~r"[\n\r]"
|
|
384
384
|
linenum = ~r"[0-9]+"
|
|
385
385
|
literal = num_literal
|
|
386
386
|
hex_literal = ~r"& *H *[0-9A-F][0-9A-F]?[0-9A-F]?[0-9A-F]?[0-9A-F]?[0-9A-F]?"
|
|
@@ -134,7 +134,7 @@ class BasicVisitor(NodeVisitor):
|
|
|
134
134
|
return node
|
|
135
135
|
|
|
136
136
|
def visit_aaa_prog(self, _, visited_children):
|
|
137
|
-
return BasicProg(visited_children[
|
|
137
|
+
return BasicProg(visited_children[1])
|
|
138
138
|
|
|
139
139
|
def visit_arr_assign(self, _, visited_children):
|
|
140
140
|
let_kw, _, array_ref_exp, _, _, _, val_exp = visited_children
|
|
@@ -518,9 +518,15 @@ class BasicVisitor(NodeVisitor):
|
|
|
518
518
|
|
|
519
519
|
def visit_func_str_exp(self, _, visited_children) -> AbstractBasicExpression:
|
|
520
520
|
func, _, _, _, exp, _, _, _ = visited_children
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
521
|
+
func_name = STR_NUM_FUNCTIONS[func.text]
|
|
522
|
+
if func_name.startswith("RUN "):
|
|
523
|
+
return BasicFunctionalExpression(
|
|
524
|
+
STR_NUM_FUNCTIONS[func.text], BasicExpressionList([exp])
|
|
525
|
+
)
|
|
526
|
+
else:
|
|
527
|
+
return BasicFunctionCall(
|
|
528
|
+
STR_NUM_FUNCTIONS[func.text], BasicExpressionList([exp])
|
|
529
|
+
)
|
|
524
530
|
|
|
525
531
|
def visit_num_assign(self, _, visited_children):
|
|
526
532
|
let_kw, _, var, _, _, _, val = visited_children
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
from typing import Dict, List, Set, TYPE_CHECKING
|
|
2
|
+
|
|
1
3
|
from coco import b09
|
|
4
|
+
from coco.b09.configs import StringConfigs
|
|
2
5
|
from coco.b09.elements import (
|
|
3
6
|
AbstractBasicExpression,
|
|
4
7
|
AbstractBasicStatement,
|
|
@@ -27,8 +30,6 @@ from coco.b09.elements import (
|
|
|
27
30
|
BasicVar,
|
|
28
31
|
)
|
|
29
32
|
|
|
30
|
-
from typing import List, Set, TYPE_CHECKING
|
|
31
|
-
|
|
32
33
|
if TYPE_CHECKING:
|
|
33
34
|
from coco.b09.prog import BasicProg
|
|
34
35
|
|
|
@@ -220,33 +221,51 @@ class StatementCollectorVisitor(BasicConstructVisitor):
|
|
|
220
221
|
|
|
221
222
|
|
|
222
223
|
class VarInitializerVisitor(BasicConstructVisitor):
|
|
224
|
+
_vars: Set[str]
|
|
225
|
+
_dimmed_var_names: Set[str]
|
|
226
|
+
|
|
223
227
|
def __init__(self):
|
|
224
228
|
self._vars = set()
|
|
229
|
+
self._dimmed_var_names = set()
|
|
225
230
|
|
|
226
231
|
@property
|
|
227
232
|
def assignment_lines(self) -> List[BasicLine]:
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
233
|
+
vars_to_assign = self._vars - self._dimmed_var_names
|
|
234
|
+
return (
|
|
235
|
+
[
|
|
236
|
+
BasicLine(
|
|
237
|
+
None,
|
|
238
|
+
BasicStatements(
|
|
239
|
+
[
|
|
240
|
+
BasicAssignment(
|
|
241
|
+
BasicVar(var, is_str_expr=var.endswith("$")),
|
|
242
|
+
BasicLiteral(
|
|
243
|
+
"" if var.endswith("$") else 0.0,
|
|
244
|
+
is_str_expr=var.endswith("$"),
|
|
245
|
+
),
|
|
246
|
+
)
|
|
247
|
+
for var in sorted(vars_to_assign)
|
|
248
|
+
if ((var.endswith("$") and len(var) <= 3) or len(var) <= 2)
|
|
249
|
+
]
|
|
250
|
+
),
|
|
251
|
+
)
|
|
252
|
+
]
|
|
253
|
+
if vars_to_assign
|
|
254
|
+
else []
|
|
255
|
+
)
|
|
246
256
|
|
|
247
257
|
def visit_var(self, var) -> None:
|
|
248
258
|
self._vars.add(var.name())
|
|
249
259
|
|
|
260
|
+
def visit_statement(self, statement: BasicForStatement) -> None:
|
|
261
|
+
if isinstance(statement, BasicDimStatement):
|
|
262
|
+
self._dimmed_var_names.update(
|
|
263
|
+
[
|
|
264
|
+
var.var.name() if isinstance(var, BasicArrayRef) else var.name()
|
|
265
|
+
for var in statement.dim_vars
|
|
266
|
+
]
|
|
267
|
+
)
|
|
268
|
+
|
|
250
269
|
|
|
251
270
|
class StrVarAllocatorVisitor(BasicConstructVisitor):
|
|
252
271
|
_vars: Set[str]
|
|
@@ -287,14 +306,22 @@ class StrVarAllocatorVisitor(BasicConstructVisitor):
|
|
|
287
306
|
class SetDimStringStorageVisitor(BasicConstructVisitor):
|
|
288
307
|
_default_str_storage: int
|
|
289
308
|
_dimmed_var_names: Set[str]
|
|
309
|
+
_string_configs: StringConfigs
|
|
310
|
+
_strname_to_size: Dict[str, int]
|
|
290
311
|
|
|
291
|
-
def __init__(self, *, default_str_storage: int):
|
|
312
|
+
def __init__(self, *, default_str_storage: int, string_configs: StringConfigs):
|
|
292
313
|
self._default_str_storage = default_str_storage
|
|
293
314
|
self._dimmed_var_names = set()
|
|
315
|
+
self.string_configs = string_configs
|
|
316
|
+
self._strname_to_size = {
|
|
317
|
+
var if var.endswith("$") else f"arr_{var[:-3]}$": size
|
|
318
|
+
for var, size in string_configs.strname_to_size.items()
|
|
319
|
+
}
|
|
294
320
|
|
|
295
321
|
def visit_statement(self, statement: BasicStatement) -> None:
|
|
296
322
|
if isinstance(statement, BasicDimStatement):
|
|
297
323
|
statement.default_str_storage = self._default_str_storage
|
|
324
|
+
statement.strname_to_size = self._strname_to_size
|
|
298
325
|
self._dimmed_var_names.update(
|
|
299
326
|
[
|
|
300
327
|
var.name() if isinstance(var, BasicVar) else var.var.name()
|
|
@@ -330,10 +357,12 @@ class GetDimmedArraysVisitor(BasicConstructVisitor):
|
|
|
330
357
|
|
|
331
358
|
class DeclareImplicitArraysVisitor(BasicConstructVisitor):
|
|
332
359
|
_dimmed_var_names: Set[str]
|
|
360
|
+
_initialize_vars: bool
|
|
333
361
|
_referenced_var_names: Set[str]
|
|
334
362
|
|
|
335
|
-
def __init__(self, *, dimmed_var_names: Set[str]):
|
|
363
|
+
def __init__(self, *, dimmed_var_names: Set[str], initialize_vars: bool = False):
|
|
336
364
|
self._dimmed_var_names = dimmed_var_names
|
|
365
|
+
self._initialize_vars = initialize_vars
|
|
337
366
|
self._referenced_var_names = set()
|
|
338
367
|
|
|
339
368
|
def visit_array_ref(self, array_ref: BasicArrayRef) -> None:
|
|
@@ -352,8 +381,9 @@ class DeclareImplicitArraysVisitor(BasicConstructVisitor):
|
|
|
352
381
|
BasicVar(var[4:], is_str_expr=var.endswith("$")),
|
|
353
382
|
BasicExpressionList([BasicLiteral(10)]),
|
|
354
383
|
is_str_expr=var.endswith("$"),
|
|
355
|
-
)
|
|
356
|
-
]
|
|
384
|
+
),
|
|
385
|
+
],
|
|
386
|
+
initialize_vars=self._initialize_vars,
|
|
357
387
|
)
|
|
358
388
|
for var in self.implicitly_declared_arrays
|
|
359
389
|
]
|
|
@@ -507,3 +537,12 @@ class BasicHbuffPresenceVisitor(BasicConstructVisitor):
|
|
|
507
537
|
@property
|
|
508
538
|
def has_hbuff(self) -> bool:
|
|
509
539
|
return self._hasHbuff
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
class SetInitializeVisitor(BasicConstructVisitor):
|
|
543
|
+
def __init__(self, initialize_vars: bool):
|
|
544
|
+
self._initialize_vars = initialize_vars
|
|
545
|
+
|
|
546
|
+
def visit_statement(self, statement: BasicStatement) -> None:
|
|
547
|
+
if isinstance(statement, BasicDimStatement):
|
|
548
|
+
statement.initialize_vars = self._initialize_vars
|
|
@@ -73,6 +73,13 @@ def start(argv):
|
|
|
73
73
|
action="store_true",
|
|
74
74
|
help="if set don't run the default width 32",
|
|
75
75
|
)
|
|
76
|
+
parser.add_argument(
|
|
77
|
+
"-c",
|
|
78
|
+
"--config-file",
|
|
79
|
+
type=str,
|
|
80
|
+
help="Optional compiler configuration file",
|
|
81
|
+
required=False,
|
|
82
|
+
)
|
|
76
83
|
|
|
77
84
|
args = parser.parse_args(argv)
|
|
78
85
|
procname = os.path.splitext(
|
|
@@ -82,6 +89,7 @@ def start(argv):
|
|
|
82
89
|
convert_file(
|
|
83
90
|
args.input_decb_text_program_file,
|
|
84
91
|
args.output_b09_text_program_file,
|
|
92
|
+
config_file=args.config_file,
|
|
85
93
|
default_width32=not args.dont_run_width_32,
|
|
86
94
|
default_str_storage=args.default_string_storage,
|
|
87
95
|
filter_unused_linenum=args.filter_unused_linenum,
|
|
@@ -1005,6 +1005,14 @@ for ii=1 to count
|
|
|
1005
1005
|
next ii
|
|
1006
1006
|
|
|
1007
1007
|
|
|
1008
|
+
PROCEDURE ecb_val
|
|
1009
|
+
PARAM str: STRING
|
|
1010
|
+
PARAM valout: REAL
|
|
1011
|
+
valout = 0.0
|
|
1012
|
+
ON ERROR GOTO 10
|
|
1013
|
+
valout = VAL(str)
|
|
1014
|
+
10 REM
|
|
1015
|
+
|
|
1008
1016
|
procedure _ecb_cursor_color
|
|
1009
1017
|
param v: integer
|
|
1010
1018
|
dim tmp_buffer(2): byte
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: coco-tools
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.19
|
|
4
4
|
Summary: TRS-80 Color Computer Tools
|
|
5
5
|
Home-page: https://github.com/jamieleecho/coco-tools
|
|
6
6
|
Author: Jamie Cho
|
|
@@ -38,27 +38,33 @@ python3 setup.py
|
|
|
38
38
|
### [decb-to-b09](./README.decb-to-b09.md)
|
|
39
39
|
|
|
40
40
|
```
|
|
41
|
-
usage: decb-to-b09 [-h] [--version] [-l] [-z] [-D] [-w]
|
|
41
|
+
usage: decb-to-b09 [-h] [--version] [-l] [-z] [-s DEFAULT_STRING_STORAGE] [-D] [-w]
|
|
42
|
+
[-c CONFIG_FILE]
|
|
43
|
+
program.bas program.b09
|
|
42
44
|
|
|
43
45
|
Convert a Color BASIC program to a BASIC09 program
|
|
44
46
|
Copyright (c) 2023 by Jamie Cho
|
|
45
|
-
Version: 0.
|
|
47
|
+
Version: 0.18
|
|
46
48
|
|
|
47
49
|
positional arguments:
|
|
48
50
|
program.bas input DECB text program file
|
|
49
51
|
program.b09 output BASIC09 text program file
|
|
50
52
|
|
|
51
|
-
|
|
53
|
+
optional arguments:
|
|
52
54
|
-h, --help show this help message and exit
|
|
53
55
|
--version show program's version number and exit
|
|
54
56
|
-l, --filter-unused-linenum
|
|
55
57
|
Filter out line numbers not referenced by the program
|
|
56
58
|
-z, --dont-initialize-vars
|
|
57
59
|
Don't pre-initialize all variables
|
|
60
|
+
-s DEFAULT_STRING_STORAGE, --default-string-storage DEFAULT_STRING_STORAGE
|
|
61
|
+
Bytes to allocate for each string
|
|
58
62
|
-D, --dont-output-dependencies
|
|
59
63
|
Don't output required dependencies
|
|
60
64
|
-w, --dont-run-width-32
|
|
61
65
|
if set don't run the default width 32
|
|
66
|
+
-c CONFIG_FILE, --config-file CONFIG_FILE
|
|
67
|
+
Optional compiler configuration file
|
|
62
68
|
```
|
|
63
69
|
|
|
64
70
|
### cm3toppm
|
|
@@ -263,6 +269,7 @@ The programs in the examples/decb and examples/other-decb-examples-to-try direct
|
|
|
263
269
|
* banner.bas -- https://colorcomputerarchive.com/repo/MC-10/Software/Books/TRS-80%20Color%20Computer%20%26%20MC-10%20Programs/banner.c10
|
|
264
270
|
* cadnza.bas -- https://colorcomputerarchive.com/repo/MC-10/Software/Books/TRS-80%20Color%20Computer%20%26%20MC-10%20Programs/cadnza.c10
|
|
265
271
|
* cflip.bas -- https://colorcomputerarchive.com/repo/MC-10/Software/Books/TRS-80%20Color%20Computer%20%26%20MC-10%20Programs/cflip.c10
|
|
272
|
+
* flip.bas -- https://github.com/daftspaniel/RetroCornerRedux/blob/main/Dragon/Originals/FlipBits/flip.bas
|
|
266
273
|
* loops.bas -- https://colorcomputerarchive.com/repo/Documents/Manuals/Hardware/Color%20Computer%203%20Extended%20Basic%20(Tandy).pdf
|
|
267
274
|
* f15eagle.bas -- https://colorcomputerarchive.com/repo/Disks/Magazines/Rainbow%20On%20Disk.zip
|
|
268
275
|
* mars.bas -- https://github.com/jggames/trs80mc10/tree/9df4c9578250009d68a03101d626faa3c22e7445/quicktype/Text%20Adventures/WorkInProgress/Mars
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import setuptools
|
|
4
4
|
|
|
5
5
|
# VERSION MUST be defined on line 6
|
|
6
|
-
VERSION = "0.
|
|
6
|
+
VERSION = "0.19"
|
|
7
7
|
|
|
8
8
|
with open("README.md", "r") as fh:
|
|
9
9
|
long_description = fh.read()
|
|
@@ -37,6 +37,8 @@ setuptools.setup(
|
|
|
37
37
|
"parsimonious>=0.10.0",
|
|
38
38
|
"Pillow>=7.0.0",
|
|
39
39
|
"pypng>=0.0.18",
|
|
40
|
+
"pydantic>=2.0.0",
|
|
41
|
+
"pydantic-yaml>=1.3.0",
|
|
40
42
|
],
|
|
41
43
|
python_requires=">=3.9.19",
|
|
42
44
|
# What does your project relate to?
|
|
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
|
|
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
|
|
File without changes
|