feat: converter reads the Phone library's register statement, named stores and generators
`init phone register` becomes a default (the group chat) plus a function of library calls that runs with the other defaults of a new game (phone_register.py). `init/python [early|hide] in some.store` wraps its code in an in_store node and `default some.store.name` may name a store; yield works as an expression (generator functions are marked gen); `import x as y`, `transform -150 name(...)`, `init:` with if/else, `config.special_namespaces` lines, `at` lists and tuples, transforms made by Python functions, `choice` weights that are expressions, `__len__`/`__bool__`, and the whitelist for os, calendar, itertools, pygame_sdl2 and the new runtime. The converter also records the size of every picture it converts (`imageSizes`) so `renpy.image_size` answers without loading. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e94f9b0d9e
commit
83cc7fdd5c
11 files changed
+379
-26
No files matched your search
@@ -178,7 +178,7 @@ class ScreenParser:
|
||||
while i < len(lines):
|
||||
line = lines[i]
|
||||
text = line.text.rstrip(":").strip() if line.block else line.text.strip()
|
||||
text = re.sub(r"^(add|text|label|image|textbutton)(?=[\"'])", r"\1 ", text) # `add"cover"`
|
||||
text = re.sub(r"^(add|text|label|image|textbutton)(?=[\"'(])", r"\1 ", text) # `add"cover"`, `textbutton(_("x"))`
|
||||
words = tokens(re.sub(r"^(if|elif|showif)\(", r"\1 (", text))
|
||||
i += 1
|
||||
if not words:
|
||||
@@ -412,6 +412,18 @@ class ScreenParser:
|
||||
spec["atl"] = animation
|
||||
props["at"] = [*props.get("at", []), spec]
|
||||
|
||||
def at_refs(self, source: str, line: Line) -> list[Node]:
|
||||
"""The entries of one `at` item: `(a, b)` is two of them."""
|
||||
text = source.strip()
|
||||
if text[:1] in "([" and text[-1:] in ")]":
|
||||
try:
|
||||
tree = ast.parse(text, mode="eval").body
|
||||
except SyntaxError:
|
||||
tree = None
|
||||
if isinstance(tree, (ast.Tuple, ast.List)):
|
||||
return [spec for element in tree.elts for spec in self.at_refs(ast.unparse(element), line)]
|
||||
return [self.at_ref(source, line)]
|
||||
|
||||
def at_ref(self, source: str, line: Line) -> Node:
|
||||
"""One `at` entry; `(a if cond else b)` picks a transform while the screen is shown."""
|
||||
text = source.strip()
|
||||
@@ -427,7 +439,7 @@ class ScreenParser:
|
||||
"else": self.at_ref(ast.unparse(tree.orelse), line)}}
|
||||
if text == "None":
|
||||
return {}
|
||||
if re.fullmatch(r"[A-Za-z_]\w*(?:\.\w+)*\[[^\]]+\]|[A-Za-z_]\w*\.\w+", text): # `icon["at"]`, `item.at`
|
||||
if re.fullmatch(r"[A-Za-z_]\w*(?:\.\w+)*\[[^\]]+\]|[A-Za-z_]\w*(?:\.\w+)+", text): # `icon["at"]`, `item.at`
|
||||
dynamic = self.expr(text, line)
|
||||
if dynamic is not None:
|
||||
return {"dyn": dynamic}
|
||||
@@ -466,7 +478,7 @@ class ScreenParser:
|
||||
i += 1
|
||||
if not more:
|
||||
break
|
||||
props["at"] = [self.at_ref(item, line) for item in items if item]
|
||||
props["at"] = [spec for item in items if item for spec in self.at_refs(item, line)]
|
||||
continue
|
||||
if glued is not None:
|
||||
source, i = glued, i + 1
|
||||
|
||||
Reference in new issue
Block a user