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.
Files changed (34) hide show
  1. {coco-tools-0.17 → coco-tools-0.19}/PKG-INFO +11 -4
  2. {coco-tools-0.17 → coco-tools-0.19}/README.md +10 -3
  3. {coco-tools-0.17 → coco-tools-0.19}/coco/__init__.py +1 -1
  4. {coco-tools-0.17 → coco-tools-0.19}/coco/b09/compiler.py +16 -2
  5. coco-tools-0.19/coco/b09/configs.py +37 -0
  6. {coco-tools-0.17 → coco-tools-0.19}/coco/b09/elements.py +76 -21
  7. {coco-tools-0.17 → coco-tools-0.19}/coco/b09/grammar.py +3 -3
  8. {coco-tools-0.17 → coco-tools-0.19}/coco/b09/parser.py +10 -4
  9. {coco-tools-0.17 → coco-tools-0.19}/coco/b09/visitors.py +63 -24
  10. {coco-tools-0.17 → coco-tools-0.19}/coco/decb_to_b09.py +8 -0
  11. {coco-tools-0.17 → coco-tools-0.19}/coco/resources/ecb.b09 +8 -0
  12. {coco-tools-0.17 → coco-tools-0.19}/coco_tools.egg-info/PKG-INFO +11 -4
  13. {coco-tools-0.17 → coco-tools-0.19}/coco_tools.egg-info/SOURCES.txt +1 -0
  14. {coco-tools-0.17 → coco-tools-0.19}/coco_tools.egg-info/requires.txt +2 -0
  15. {coco-tools-0.17 → coco-tools-0.19}/setup.py +3 -1
  16. {coco-tools-0.17 → coco-tools-0.19}/LICENSE +0 -0
  17. {coco-tools-0.17 → coco-tools-0.19}/coco/b09/__init__.py +0 -0
  18. {coco-tools-0.17 → coco-tools-0.19}/coco/b09/error_handler.py +0 -0
  19. {coco-tools-0.17 → coco-tools-0.19}/coco/b09/procbank.py +0 -0
  20. {coco-tools-0.17 → coco-tools-0.19}/coco/b09/prog.py +0 -0
  21. {coco-tools-0.17 → coco-tools-0.19}/coco/cm3toppm.py +0 -0
  22. {coco-tools-0.17 → coco-tools-0.19}/coco/hrstoppm.py +0 -0
  23. {coco-tools-0.17 → coco-tools-0.19}/coco/maxtoppm.py +0 -0
  24. {coco-tools-0.17 → coco-tools-0.19}/coco/mge_viewer2.py +0 -0
  25. {coco-tools-0.17 → coco-tools-0.19}/coco/mgetoppm.py +0 -0
  26. {coco-tools-0.17 → coco-tools-0.19}/coco/pixtopgm.py +0 -0
  27. {coco-tools-0.17 → coco-tools-0.19}/coco/rattoppm.py +0 -0
  28. {coco-tools-0.17 → coco-tools-0.19}/coco/resources/__init__.py +0 -0
  29. {coco-tools-0.17 → coco-tools-0.19}/coco/util.py +0 -0
  30. {coco-tools-0.17 → coco-tools-0.19}/coco/veftopng.py +0 -0
  31. {coco-tools-0.17 → coco-tools-0.19}/coco_tools.egg-info/dependency_links.txt +0 -0
  32. {coco-tools-0.17 → coco-tools-0.19}/coco_tools.egg-info/entry_points.txt +0 -0
  33. {coco-tools-0.17 → coco-tools-0.19}/coco_tools.egg-info/top_level.txt +0 -0
  34. {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.17
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] program.bas program.b09
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.8
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
- options:
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] program.bas program.b09
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.8
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
- options:
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.17"
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.extend_prefix_lines(declare_array_visitor.dim_statements)
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__(self, dim_vars: List["BasicArrayRef | BasicVar"]):
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
- @default_str_storage.setter
1003
- def default_str_storage(self, val):
1004
- self._default_str_storage = val
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
- str_vars_text: str = (
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
- str_vars,
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
- + ("\n" if non_str_vars else "")
1069
- if str_vars
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: str = (
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
- init_text = "\n".join(
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
- init_text = "\n" + init_text if init_text else ""
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": "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[0])
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
- return BasicFunctionCall(
522
- STR_NUM_FUNCTIONS[func.text], BasicExpressionList([exp])
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
- return [
229
- BasicLine(
230
- None,
231
- BasicStatements(
232
- [
233
- BasicAssignment(
234
- BasicVar(var, is_str_expr=var.endswith("$")),
235
- BasicLiteral(
236
- "" if var.endswith("$") else 0.0,
237
- is_str_expr=var.endswith("$"),
238
- ),
239
- )
240
- for var in sorted(self._vars)
241
- if ((var.endswith("$") and len(var) <= 3) or len(var) <= 2)
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.17
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] program.bas program.b09
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.8
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
- options:
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
@@ -14,6 +14,7 @@ setup.py
14
14
  ./coco/veftopng.py
15
15
  ./coco/b09/__init__.py
16
16
  ./coco/b09/compiler.py
17
+ ./coco/b09/configs.py
17
18
  ./coco/b09/elements.py
18
19
  ./coco/b09/error_handler.py
19
20
  ./coco/b09/grammar.py
@@ -1,3 +1,5 @@
1
1
  parsimonious>=0.10.0
2
2
  Pillow>=7.0.0
3
3
  pypng>=0.0.18
4
+ pydantic>=2.0.0
5
+ pydantic-yaml>=1.3.0
@@ -3,7 +3,7 @@
3
3
  import setuptools
4
4
 
5
5
  # VERSION MUST be defined on line 6
6
- VERSION = "0.17"
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