Skip to content

Commit 2e0d2df

Browse files
committed
Add macro() and op() DSL features
1 parent 1a5356b commit 2e0d2df

File tree

4 files changed

+42
-26
lines changed

4 files changed

+42
-26
lines changed

Python/bytecodes.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ do { \
7070
#define DISPATCH_SAME_OPARG() ((void)0)
7171

7272
#define inst(name, ...) case name:
73+
#define op(name, ...) /* NAME is ignored */
74+
#define macro(name) static int MACRO_##name
7375
#define super(name) static int SUPER_##name
7476
#define family(name, ...) static int family_##name
7577

@@ -156,10 +158,7 @@ dummy_func(
156158
res = NULL;
157159
}
158160

159-
inst(END_FOR, (value1, value2 --)) {
160-
Py_DECREF(value1);
161-
Py_DECREF(value2);
162-
}
161+
macro(END_FOR) = POP_TOP + POP_TOP;
163162

164163
inst(UNARY_POSITIVE, (value -- res)) {
165164
res = PyNumber_Positive(value);

Python/generated_cases.c.h

Lines changed: 14 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tools/cases_generator/generate_cases.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,8 @@ def __init__(self, filename: str):
179179
with open(filename) as f:
180180
self.src = f.read()
181181

182-
instrs: dict[str, Instruction]
183-
supers: dict[str, parser.Super]
182+
instrs: dict[str, Instruction] # Includes ops
183+
supers: dict[str, parser.Super] # Includes macros
184184
families: dict[str, parser.Family]
185185

186186
def parse(self) -> None:
@@ -303,6 +303,8 @@ def write_instructions(self, filename: str) -> None:
303303

304304
# Write regular instructions
305305
for name, instr in self.instrs.items():
306+
if instr.kind != "inst":
307+
continue # ops are not real instructions
306308
f.write(f"\n{indent}TARGET({name}) {{\n")
307309
if instr.predicted:
308310
f.write(f"{indent} PREDICTED({name});\n")
@@ -316,7 +318,7 @@ def write_instructions(self, filename: str) -> None:
316318
components = [self.instrs[name] for name in sup.ops]
317319
f.write(f"\n{indent}TARGET({sup.name}) {{\n")
318320
for i, instr in enumerate(components):
319-
if i > 0:
321+
if i > 0 and sup.kind == "super":
320322
f.write(f"{indent} NEXTOPARG();\n")
321323
f.write(f"{indent} next_instr++;\n")
322324
f.write(f"{indent} {{\n")

Tools/cases_generator/parser.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Parser for bytecodes.inst."""
22

33
from dataclasses import dataclass, field
4-
from typing import NamedTuple, Callable, TypeVar
4+
from typing import NamedTuple, Callable, TypeVar, Literal
55

66
import lexer as lx
77
from plexer import PLexer
@@ -74,16 +74,22 @@ class CacheEffect(Node):
7474

7575
@dataclass
7676
class InstHeader(Node):
77+
kind: Literal["inst", "op"]
7778
name: str
7879
inputs: list[InputEffect]
7980
outputs: list[OutputEffect]
8081

8182

8283
@dataclass
8384
class InstDef(Node):
85+
# TODO: Merge InstHeader and InstDef
8486
header: InstHeader
8587
block: Block
8688

89+
@property
90+
def kind(self) -> str:
91+
return self.header.kind
92+
8793
@property
8894
def name(self) -> str:
8995
return self.header.name
@@ -99,6 +105,7 @@ def outputs(self) -> list[StackEffect]:
99105

100106
@dataclass
101107
class Super(Node):
108+
kind: Literal["macro", "super"]
102109
name: str
103110
ops: list[str]
104111

@@ -122,10 +129,12 @@ def inst_def(self) -> InstDef | None:
122129

123130
@contextual
124131
def inst_header(self) -> InstHeader | None:
125-
# inst(NAME) | inst(NAME, (inputs -- outputs))
132+
# inst(NAME)
133+
# | inst(NAME, (inputs -- outputs))
134+
# | op(NAME, (inputs -- outputs))
126135
# TODO: Error out when there is something unexpected.
127136
# TODO: Make INST a keyword in the lexer.
128-
if (tkn := self.expect(lx.IDENTIFIER)) and tkn.text == "inst":
137+
if (tkn := self.expect(lx.IDENTIFIER)) and (kind := tkn.text) in ("inst", "op"):
129138
if (self.expect(lx.LPAREN)
130139
and (tkn := self.expect(lx.IDENTIFIER))):
131140
name = tkn.text
@@ -134,9 +143,10 @@ def inst_header(self) -> InstHeader | None:
134143
if self.expect(lx.RPAREN):
135144
if ((tkn := self.peek())
136145
and tkn.kind == lx.LBRACE):
137-
return InstHeader(name, inp, outp)
138-
elif self.expect(lx.RPAREN):
139-
return InstHeader(name, [], [])
146+
return InstHeader(kind, name, inp, outp)
147+
elif self.expect(lx.RPAREN) and kind == "inst":
148+
# No legacy stack effect if kind is "op".
149+
return InstHeader(kind, name, [], [])
140150
return None
141151

142152
def stack_effect(self) -> tuple[list[InputEffect], list[OutputEffect]]:
@@ -200,13 +210,13 @@ def output(self) -> OutputEffect | None:
200210

201211
@contextual
202212
def super_def(self) -> Super | None:
203-
if (tkn := self.expect(lx.IDENTIFIER)) and tkn.text == "super":
213+
if (tkn := self.expect(lx.IDENTIFIER)) and (kind := tkn.text) in ("super", "macro"):
204214
if self.expect(lx.LPAREN):
205215
if (tkn := self.expect(lx.IDENTIFIER)):
206216
if self.expect(lx.RPAREN):
207217
if self.expect(lx.EQUALS):
208218
if ops := self.ops():
209-
res = Super(tkn.text, ops)
219+
res = Super(kind, tkn.text, ops)
210220
return res
211221

212222
def ops(self) -> list[str] | None:
@@ -278,7 +288,7 @@ def c_blob(self) -> list[lx.Token]:
278288
filename = sys.argv[1]
279289
if filename == "-c" and sys.argv[2:]:
280290
src = sys.argv[2]
281-
filename = None
291+
filename = "<string>"
282292
else:
283293
with open(filename) as f:
284294
src = f.read()
@@ -287,7 +297,7 @@ def c_blob(self) -> list[lx.Token]:
287297
end = srclines.index("// END BYTECODES //")
288298
src = "\n".join(srclines[begin+1 : end])
289299
else:
290-
filename = None
300+
filename = "<default>"
291301
src = "if (x) { x.foo; // comment\n}"
292302
parser = Parser(src, filename)
293303
x = parser.inst_def() or parser.super_def() or parser.family_def()

0 commit comments

Comments
 (0)