Showing
4 changed files
with
452 additions
and
18 deletions
... | @@ -47,6 +47,12 @@ class CAni (object) : | ... | @@ -47,6 +47,12 @@ class CAni (object) : |
47 | @RET.setter | 47 | @RET.setter |
48 | def RET (self, val) : | 48 | def RET (self, val) : |
49 | dict.__setitem__(self._env, "RET", val) | 49 | dict.__setitem__(self._env, "RET", val) |
50 | + @property | ||
51 | + def CASE (self) : | ||
52 | + return self._env.get("CASE", None) | ||
53 | + @CASE.setter | ||
54 | + def CASE (self, val) : | ||
55 | + dict.__setitem__(self._env, "CASE", val) | ||
50 | def exec (self, code) : | 56 | def exec (self, code) : |
51 | self._env.exec(code) | 57 | self._env.exec(code) |
52 | def eval (self, code) : | 58 | def eval (self, code) : | ... | ... |
... | @@ -46,6 +46,9 @@ class _CODE (CAni) : | ... | @@ -46,6 +46,9 @@ class _CODE (CAni) : |
46 | for key, val in self.items() : | 46 | for key, val in self.items() : |
47 | if isinstance(val, _CODE) : | 47 | if isinstance(val, _CODE) : |
48 | sub[key] = val.source() | 48 | sub[key] = val.source() |
49 | + elif isinstance(val, (list, tuple)) : | ||
50 | + sub[key] = "".join(v.source() if isinstance(v, _CODE) else str(v) | ||
51 | + for v in val) | ||
49 | else : | 52 | else : |
50 | sub[key] = val | 53 | sub[key] = val |
51 | return self.src.format(**sub) | 54 | return self.src.format(**sub) |
... | @@ -64,8 +67,29 @@ class _CODE (CAni) : | ... | @@ -64,8 +67,29 @@ class _CODE (CAni) : |
64 | else : | 67 | else : |
65 | return tex | 68 | return tex |
66 | 69 | ||
70 | +class RAW (_CODE) : | ||
71 | + _fields = [] | ||
72 | + @autorepr | ||
73 | + def __init__ (self, src) : | ||
74 | + super().__init__(src=src) | ||
75 | + def __call__ (self) : | ||
76 | + pass | ||
77 | + | ||
78 | +class WS (RAW) : | ||
79 | + _fields = [] | ||
80 | + def tex (self) : | ||
81 | + return self.src | ||
82 | + | ||
67 | class BLOCK (_CODE) : | 83 | class BLOCK (_CODE) : |
68 | _fields = ["*body"] | 84 | _fields = ["*body"] |
85 | + def __init__ (self, *l, **k) : | ||
86 | + super().__init__(*l, **k) | ||
87 | + self.body = list(self.body) | ||
88 | + def __repr__ (self) : | ||
89 | + return "{}({}{}{})".format(self.__class__.__name__, | ||
90 | + ", ".join(repr(b) for b in self.body), | ||
91 | + ", " if self.body and self.src else "", | ||
92 | + "src={}".format(self.src) if self.src else "") | ||
69 | def __call__ (self) : | 93 | def __call__ (self) : |
70 | self._at.add(self.IP) | 94 | self._at.add(self.IP) |
71 | for code in self.body : | 95 | for code in self.body : |
... | @@ -74,6 +98,15 @@ class BLOCK (_CODE) : | ... | @@ -74,6 +98,15 @@ class BLOCK (_CODE) : |
74 | return "".join(b.source() for b in self.body) | 98 | return "".join(b.source() for b in self.body) |
75 | def tex (self) : | 99 | def tex (self) : |
76 | return "".join(b.tex() for b in self.body) | 100 | return "".join(b.tex() for b in self.body) |
101 | + def append (self, code) : | ||
102 | + if not self.body : | ||
103 | + self.body.append(code) | ||
104 | + elif isinstance(self.body[-1], RAW) and isinstance(code, RAW) : | ||
105 | + self.body[-1] = RAW(self.body[-1].src + code.src) | ||
106 | + elif isinstance(code, RAW) and not code.src : | ||
107 | + pass | ||
108 | + else : | ||
109 | + self.body.append(code) | ||
77 | 110 | ||
78 | class STMT (_CODE) : | 111 | class STMT (_CODE) : |
79 | _fields = ["*steps"] | 112 | _fields = ["*steps"] |
... | @@ -113,24 +146,6 @@ class ENV (_CODE) : | ... | @@ -113,24 +146,6 @@ class ENV (_CODE) : |
113 | def source (self) : | 146 | def source (self) : |
114 | return "" | 147 | return "" |
115 | 148 | ||
116 | -class WS (_CODE) : | ||
117 | - _fields = [] | ||
118 | - @autorepr | ||
119 | - def __init__ (self, src) : | ||
120 | - super().__init__(src=src) | ||
121 | - def __call__ (self) : | ||
122 | - pass | ||
123 | - def tex (self) : | ||
124 | - return self.src | ||
125 | - | ||
126 | -class RAW (_CODE) : | ||
127 | - _fields = [] | ||
128 | - @autorepr | ||
129 | - def __init__ (self, src) : | ||
130 | - super().__init__(src=src) | ||
131 | - def __call__ (self) : | ||
132 | - pass | ||
133 | - | ||
134 | class XDECL (_CODE) : | 149 | class XDECL (_CODE) : |
135 | _fields = ["*names"] | 150 | _fields = ["*names"] |
136 | def __call__ (self) : | 151 | def __call__ (self) : |
... | @@ -169,6 +184,9 @@ class BreakLoop (Exception) : | ... | @@ -169,6 +184,9 @@ class BreakLoop (Exception) : |
169 | pass | 184 | pass |
170 | 185 | ||
171 | class BREAK (_CODE) : | 186 | class BREAK (_CODE) : |
187 | + def __init__ (self) : | ||
188 | + super().__init__() | ||
189 | + self.src = "break" | ||
172 | def __call__ (self) : | 190 | def __call__ (self) : |
173 | self._at.add(self.IP) | 191 | self._at.add(self.IP) |
174 | self.IP += 1 | 192 | self.IP += 1 |
... | @@ -243,3 +261,26 @@ class FUNC (_CODE) : | ... | @@ -243,3 +261,26 @@ class FUNC (_CODE) : |
243 | self.body() | 261 | self.body() |
244 | except FunctionReturn as exc : | 262 | except FunctionReturn as exc : |
245 | self._env["RET"] = exc.RET | 263 | self._env["RET"] = exc.RET |
264 | + | ||
265 | +class SWITCH (_CODE) : | ||
266 | + _fields = ["cond", "*cases"] | ||
267 | + def __call__ (self) : | ||
268 | + self.cond() | ||
269 | + cond = self.RET | ||
270 | + try : | ||
271 | + for case in self.cases : | ||
272 | + self.CASE = cond | ||
273 | + case() | ||
274 | + except BreakLoop : | ||
275 | + pass | ||
276 | + | ||
277 | +class CASE (_CODE) : | ||
278 | + _fields = ["value", "body"] | ||
279 | + def __call__ (self) : | ||
280 | + self.value() | ||
281 | + if self.RET == self.CASE : | ||
282 | + self.body() | ||
283 | + | ||
284 | +class DEFAULT (BLOCK) : | ||
285 | + def source (self) : | ||
286 | + return self.src.format(body=super().source()) | ... | ... |
codanim/lang/__init__.py
0 → 100644
File mode changed
codanim/lang/c.py
0 → 100644
1 | +import re, sys, itertools | ||
2 | +import pycparser, colorama | ||
3 | + | ||
4 | +from .. import flow | ||
5 | + | ||
6 | +def escape (text) : | ||
7 | + return text.replace("{", "{{").replace("}", "}}") | ||
8 | + | ||
9 | +class String (str): | ||
10 | + def __new__(cls, content): | ||
11 | + self = super().__new__(cls, content) | ||
12 | + self._n = {0: 0} | ||
13 | + for n, match in enumerate(re.finditer("\n", self)) : | ||
14 | + self._n[n+1] = match.end() | ||
15 | + return self | ||
16 | + def last (self) : | ||
17 | + l = len(self._n) - 1 | ||
18 | + return Coord(l, len(self) - self._n[l] + 1) | ||
19 | + def __call__ (self, coord) : | ||
20 | + return self._n[coord.line-1] + coord.column-1 | ||
21 | + def __getitem__ (self, idx) : | ||
22 | + if isinstance(idx, Span) : | ||
23 | + a = self(idx.start) | ||
24 | + b = self(idx.stop) | ||
25 | + return super().__getitem__(slice(a,b)) | ||
26 | + elif isinstance(idx, Coord) : | ||
27 | + return super().__getitem__(self(idx)) | ||
28 | + elif isinstance(idx, slice) : | ||
29 | + if isinstance(idx.start, Coord) : | ||
30 | + a = self(idx.start) | ||
31 | + else : | ||
32 | + a = idx.start | ||
33 | + if isinstance(idx.stop, Coord) : | ||
34 | + b = self(idx.stop) | ||
35 | + else : | ||
36 | + b = idx.stop | ||
37 | + return super().__getitem__(slice(a,b)) | ||
38 | + else : | ||
39 | + return super().__getitem__(idx) | ||
40 | + def index (self, sub, start=None, end=None) : | ||
41 | + if isinstance(start, Coord) : | ||
42 | + start = self(start) | ||
43 | + if isinstance(end, Coord) : | ||
44 | + end = self(end) | ||
45 | + return super().index(sub, start, end) - (start or 0) | ||
46 | + def rindex (self, sub, start=None, end=None) : | ||
47 | + if isinstance(start, Coord) : | ||
48 | + start = self(start) | ||
49 | + if isinstance(end, Coord) : | ||
50 | + end = self(end) | ||
51 | + return super().rindex(sub, start, end) - (end or 0) | ||
52 | + def sub (self, within, pairs) : | ||
53 | + parts = [] | ||
54 | + last = within.start | ||
55 | + for span, text in pairs : | ||
56 | + parts.append(escape(self[last:span.start])) | ||
57 | + parts.append(text) | ||
58 | + last = span.stop | ||
59 | + parts.append(escape(self[last:within.stop])) | ||
60 | + return "".join(parts) | ||
61 | + | ||
62 | +class Coord (object) : | ||
63 | + def __init__ (self, l, c=None) : | ||
64 | + if c is None : | ||
65 | + self.line, self.column = l.line, l.column | ||
66 | + else : | ||
67 | + self.line, self.column = l or 1, c or 1 | ||
68 | + def __eq__ (self, other) : | ||
69 | + return self.line == other.line and self.column == other.column | ||
70 | + def __lt__ (self, other) : | ||
71 | + return (self.line < other.line | ||
72 | + or (self.line == other.line and self.column < other.column)) | ||
73 | + def __add__ (self, other) : | ||
74 | + return self.__class__(self.line, self.column + other) | ||
75 | + def __str__ (self) : | ||
76 | + return f"{self.line}:{self.column}" | ||
77 | + | ||
78 | +class Span (object) : | ||
79 | + def __init__ (self, start, stop) : | ||
80 | + self.start = Coord(start) | ||
81 | + self.stop = Coord(stop) | ||
82 | + def add (self, other) : | ||
83 | + if isinstance(other, Span) : | ||
84 | + if other.start is not None and other.start < self.start : | ||
85 | + self.start = other.start | ||
86 | + if other.stop is not None and other.stop > self.stop : | ||
87 | + self.stop = other.stop | ||
88 | + elif isinstance(other, Coord) : | ||
89 | + if other < self.start : | ||
90 | + self.start = other | ||
91 | + elif other > self.stop : | ||
92 | + self.stop = other | ||
93 | + elif isinstance(other, int) : | ||
94 | + if other > 0 : | ||
95 | + self.stop += other | ||
96 | + elif other < 0 : | ||
97 | + self.start += other | ||
98 | + else : | ||
99 | + raise TypeError(repr(other)) | ||
100 | + def __str__ (self) : | ||
101 | + return f"{self.start}/{self.stop}" | ||
102 | + | ||
103 | +class SpanDict (dict) : | ||
104 | + def __init__ (self, ast, src) : | ||
105 | + super().__init__() | ||
106 | + self.src = String(src) | ||
107 | + self.do(ast) | ||
108 | + def do (self, node) : | ||
109 | + self.generic_do(node) | ||
110 | + name = node.__class__.__name__ | ||
111 | + handler = getattr(self, "do_" + name, None) | ||
112 | + if handler is not None : | ||
113 | + handler(node) | ||
114 | + def generic_do (self, node) : | ||
115 | + coord = getattr(node, "coord", None) | ||
116 | + if coord is not None : | ||
117 | + span = self[node] = Span(Coord(coord), Coord(coord)) | ||
118 | + else : | ||
119 | + span = self[node] = Span(Coord(sys.maxsize, sys.maxsize), Coord(1, 1)) | ||
120 | + for _, child in node.children() : | ||
121 | + self.do(child) | ||
122 | + span.add(self[child]) | ||
123 | + def do_ID (self, node) : | ||
124 | + self[node].add(len(node.name)) | ||
125 | + def do_Constant (self, node) : | ||
126 | + self[node].add(len(node.value)) | ||
127 | + def do_Break (self, node) : | ||
128 | + self[node].add(5) | ||
129 | + def do_Typedef (self, node) : | ||
130 | + if not self.src[self[node].start:self[node].stop].startswith("typedef") : | ||
131 | + self[node].start += self.src.rindex("typedef", 0, self[node].start) | ||
132 | + def do_TypeDecl (self, node) : | ||
133 | + self[node].add(len(node.declname)) | ||
134 | + def do_Struct (self, node) : | ||
135 | + self[node].add(self.src.index("}", self[node].stop) + 1) | ||
136 | + def do_ArrayRef (self, node) : | ||
137 | + self[node].add(self.src.index("]", self[node].stop) + 1) | ||
138 | + def do_FuncCall (self, node) : | ||
139 | + self[node].add(self.src.index(")", self[node].stop) + 1) | ||
140 | + def do_FuncDecl (self, node) : | ||
141 | + self[node].add(self.src.index(")", self[node].stop) + 1) | ||
142 | + def do_FuncDef (self, node) : | ||
143 | + self[node.body].add(self.src.index("}", self[node.body].stop) + 1) | ||
144 | + self[node].add(self[node.body]) | ||
145 | + self[node.body].start = self[node.decl].stop + 1 | ||
146 | + while self.src[self[node.body].start] in " \t" : | ||
147 | + self[node.body].start += 1 | ||
148 | + def do_UnaryOp (self, node) : | ||
149 | + if node.op in ("p++", "p--") : | ||
150 | + self[node].add(self.src.index(node.op[1:], self[node].stop) | ||
151 | + + len(node.op[1:])) | ||
152 | + def do_DoWhile (self, node) : | ||
153 | + self[node].add(self.src.index(")", self[node].stop) + 1) | ||
154 | + self[node].start += self.src.index("do", self[node].start) | ||
155 | + self[node.stmt].start = self[node].start + 2 | ||
156 | + while self.src[self[node.stmt].start] in " \t" : | ||
157 | + self[node.stmt].start += 1 | ||
158 | + if self.src[self[node.stmt].start] == "{" : | ||
159 | + self[node.stmt].add(self.src.index("}", self[node.stmt].stop) + 1) | ||
160 | + self[node].add(self[node.stmt]) | ||
161 | + def do_If (self, node) : | ||
162 | + self[node].start += self.src.index("if", self[node].start) | ||
163 | + self[node.iftrue].start = (self[node.cond].stop | ||
164 | + + self.src.index(")", self[node.cond].stop) + 1) | ||
165 | + while self.src[self[node.iftrue].start] in " \t" : | ||
166 | + self[node.iftrue].start += 1 | ||
167 | + if self.src[self[node.iftrue].start] == "{" : | ||
168 | + self[node.iftrue].add(self.src.index("}", self[node.iftrue].stop) + 1) | ||
169 | + self[node].add(self[node.iftrue]) | ||
170 | + def do_While (self, node) : | ||
171 | + self[node].start += self.src.index("while", self[node].start) | ||
172 | + self[node.stmt].start = (self[node.cond].stop | ||
173 | + + self.src.index(")", self[node.cond].stop) + 1) | ||
174 | + while self.src[self[node.stmt].start] in " \t" : | ||
175 | + self[node.stmt].start += 1 | ||
176 | + if self.src[self[node.stmt].start] == "{" : | ||
177 | + self[node.stmt].add(self.src.index("}", self[node.stmt].stop) + 1) | ||
178 | + self[node].add(self[node.stmt]) | ||
179 | + def do_BinaryOp (self, node) : | ||
180 | + if ")" in self.src[self[node.left].stop:self[node.right].start] : | ||
181 | + while self.src[self[node].start] != "(" : | ||
182 | + self[node].start += -1 | ||
183 | + def do_FileAST (self, node) : | ||
184 | + self[node] = Span(Coord(1,1), self.src.last()) | ||
185 | + def do_Switch (self, node) : | ||
186 | + self[node].start += self.src.index("switch", self[node].start) | ||
187 | + self[node.stmt].start = (self[node.cond].stop | ||
188 | + + self.src.index(")", self[node.cond].stop) + 1) | ||
189 | + while self.src[self[node.stmt].start] in " \t" : | ||
190 | + self[node.stmt].start += 1 | ||
191 | + if self.src[self[node.stmt].start] == "{" : | ||
192 | + self[node.stmt].add(self.src.index("}", self[node.stmt].stop) + 1) | ||
193 | + self[node].add(self[node.stmt]) | ||
194 | + | ||
195 | +class SpanTree (object) : | ||
196 | + def __init__ (self, ast, span) : | ||
197 | + self.span = span[ast] | ||
198 | + self._ast = ast | ||
199 | + self._span = span | ||
200 | + for name in itertools.chain(getattr(ast, "attr_names", []), | ||
201 | + ast.__slots__) : | ||
202 | + attr = getattr(ast, name, None) | ||
203 | + if isinstance(attr, (list, tuple)) : | ||
204 | + setattr(self, name, type(attr)(self.__class__(v, span) | ||
205 | + if isinstance(v, pycparser.c_ast.Node) | ||
206 | + else v for v in attr)) | ||
207 | + self.nodetype = ast.__class__.__name__ | ||
208 | + def __repr__ (self) : | ||
209 | + return f"<ast.{self.nodetype} at {self.span}>" | ||
210 | + def __getattr__ (self, name) : | ||
211 | + ret = getattr(self._ast, name) | ||
212 | + if isinstance(ret, pycparser.c_ast.Node) : | ||
213 | + return self.__class__(ret, self._span) | ||
214 | + else : | ||
215 | + return ret | ||
216 | + def children (self) : | ||
217 | + for name, child in self._ast.children() : | ||
218 | + yield name, self.__class__(child, self._span) | ||
219 | + def dump (self, indent=" ", source=False) : | ||
220 | + print(f"{colorama.Style.BRIGHT}{self.nodetype}{colorama.Style.RESET_ALL} at" | ||
221 | + f" {colorama.Fore.YELLOW}{self.span}{colorama.Style.RESET_ALL}") | ||
222 | + for name in getattr(self, "attr_names", []) : | ||
223 | + attr = getattr(self, name, None) | ||
224 | + if not attr : | ||
225 | + continue | ||
226 | + attr_type = type(attr).__name__ | ||
227 | + print(f"{indent}{colorama.Fore.BLUE}{name}{colorama.Style.RESET_ALL}" | ||
228 | + f" = {attr!r}" | ||
229 | + f" {colorama.Fore.WHITE}<{attr_type}>{colorama.Style.RESET_ALL}") | ||
230 | + if source : | ||
231 | + print(f"{indent}{colorama.Fore.GREEN}source{colorama.Style.RESET_ALL}" | ||
232 | + f" = {self.source!r}") | ||
233 | + for name, child in self.children() : | ||
234 | + print(f"{indent}{colorama.Fore.RED}{name}:{colorama.Style.RESET_ALL} ", | ||
235 | + end="") | ||
236 | + child.dump(indent + " ", source) | ||
237 | + @property | ||
238 | + def source (self) : | ||
239 | + return self._span.src[self.span] | ||
240 | + def get_source (self, start, stop) : | ||
241 | + return escape(self._span.src[start:stop]) | ||
242 | + def sub_source (self, *pairs) : | ||
243 | + return self._span.src.sub(self.span, zip(pairs[::2], pairs[1::2])) | ||
244 | + | ||
245 | +_skip = ["/\\*(?ms:.*?)\\*/", | ||
246 | + "//.*", | ||
247 | + "#define .*", | ||
248 | + "#include .*"] | ||
249 | +_skip_re = re.compile("|".join(f"({e})" for e in _skip), re.M) | ||
250 | +_skip_clean = re.compile("[^\n]") | ||
251 | + | ||
252 | +def parse (source, path="<str>") : | ||
253 | + _src = [] | ||
254 | + _cpp = [] | ||
255 | + pos = 0 | ||
256 | + for match in _skip_re.finditer(source) : | ||
257 | + _src.append(source[pos:match.start()]) | ||
258 | + _cpp.append(match[0]) | ||
259 | + pos = match.end() | ||
260 | + cppsrc = "".join(s + _skip_clean.sub(" ", c) | ||
261 | + for s, c in zip(_src, _cpp)) + source[pos:] | ||
262 | + parser = pycparser.CParser() | ||
263 | + ast = parser.parse(cppsrc, path) | ||
264 | + return SpanTree(ast, SpanDict(ast, source)) | ||
265 | + | ||
266 | +class Translator (object) : | ||
267 | + def __init__ (self) : | ||
268 | + self.typedef = {} | ||
269 | + self.funcdef = {} | ||
270 | + def __call__ (self, node) : | ||
271 | + handler = getattr(self, "do_" + node.nodetype, self.generic_do) | ||
272 | + return handler(node) | ||
273 | + def generic_do (self, node) : | ||
274 | + block = flow.BLOCK() | ||
275 | + last = node.span.start | ||
276 | + for _, child in node.children() : | ||
277 | + if child.span.start > last : | ||
278 | + block.append(flow.RAW(node.get_source(last, child.span.start))) | ||
279 | + block.append(self(child)) | ||
280 | + last = child.span.stop | ||
281 | + if last < node.span.stop : | ||
282 | + block.append(flow.RAW(node.get_source(last, node.span.stop))) | ||
283 | + return block | ||
284 | + def do_Typedef (self, node) : | ||
285 | + self.typedef[node.name] = node | ||
286 | + return flow.RAW(node.source) | ||
287 | + def do_FuncDef (self, node) : | ||
288 | + self.funcdef[node.decl.name] = node | ||
289 | + return flow.FUNC(self(node.body), | ||
290 | + src=node.sub_source(node.body.span, "{body}")) | ||
291 | + def do_Assignment (self, node) : | ||
292 | + src = node.source | ||
293 | + return flow.STMT(f"FIXME {src}", src=src) | ||
294 | + def do_FuncCall (self, node) : | ||
295 | + src = node.source | ||
296 | + return flow.STMT(f"FIXME {src}", src=src) | ||
297 | + def do_Decl (self, node) : | ||
298 | + src = node.source | ||
299 | + if node.init : | ||
300 | + return flow.DECL(node.name, | ||
301 | + flow.EXPR(f"FIXME {src}", src=src), | ||
302 | + animate=False, | ||
303 | + src=node.sub_source(node.init.span, "{init}")) | ||
304 | + else : | ||
305 | + return flow.DECL(node.name, animate=False, src=src) | ||
306 | + def do_If (self, node) : | ||
307 | + cond = node.cond.source | ||
308 | + if node.iffalse is None : | ||
309 | + return flow.IF(flow.EXPR(f"FIXME {cond}", src=cond), | ||
310 | + self(node.iftrue), | ||
311 | + src=node.sub_source(node.iftrue.span, "{then}")) | ||
312 | + else : | ||
313 | + return flow.IF(flow.EXPR(f"FIXME {cond}", src=cond), | ||
314 | + self(node.iftrue), | ||
315 | + self(node.iffalse), | ||
316 | + src=node.sub_source(node.iftrue.span, "{then}", | ||
317 | + node.iffalse.span, "{otherwise}")) | ||
318 | + def do_For (self, node) : | ||
319 | + init = node.init.source | ||
320 | + cond = node.cond.source | ||
321 | + step = node.next.source | ||
322 | + return flow.FOR(flow.STMT(f"FIXME {init}", src=init), | ||
323 | + flow.EXPR(f"FIXME {cond}", src=cond), | ||
324 | + flow.STMT(f"FIXME {step}", src=step), | ||
325 | + self(node.stmt), | ||
326 | + src=node.sub_source(node.init.span, "{init}", | ||
327 | + node.cond.span, "{cond}", | ||
328 | + node.next.span, "{step}", | ||
329 | + node.stmt.span, "{body}")) | ||
330 | + def do_While (self, node) : | ||
331 | + cond = node.cond.source | ||
332 | + return flow.WHILE(flow.EXPR(f"FIXME {cond}", src=cond), | ||
333 | + self(node.stmt), | ||
334 | + src=node.sub_source(node.cond.span, "{cond}", | ||
335 | + node.stmt.span, "{body}")) | ||
336 | + def do_DoWhile (self, node) : | ||
337 | + cond = node.cond.source | ||
338 | + return flow.DO(self(node.stmt), | ||
339 | + flow.EXPR(f"FIXME {cond}", src=cond), | ||
340 | + src=node.sub_source(node.stmt.span, "{body}", | ||
341 | + node.cond.span, "{cond}")) | ||
342 | + def do_Switch (self, node) : | ||
343 | + cond = node.cond.source | ||
344 | + block = flow.BLOCK() | ||
345 | + last = node.stmt.span.start | ||
346 | + for _, child in node.stmt.children() : | ||
347 | + if child.span.start > last : | ||
348 | + block.append(flow.RAW(node.get_source(last, child.span.start))) | ||
349 | + block.append(self(child)) | ||
350 | + last = child.span.stop | ||
351 | + if last < node.span.stop : | ||
352 | + block.append(flow.RAW(node.get_source(last, node.span.stop))) | ||
353 | + return flow.SWITCH(flow.EXPR(f"FIXME {cond}", src=cond), | ||
354 | + *block.body, | ||
355 | + src=node.sub_source(node.cond.span, "{cond}", | ||
356 | + node.stmt.span, "{cases}")) | ||
357 | + def do_Case (self, node) : | ||
358 | + value = node.expr.source | ||
359 | + block = flow.BLOCK() | ||
360 | + last = None | ||
361 | + for child in node.stmts : | ||
362 | + if last is not None and child.span.start > last : | ||
363 | + block.append(flow.RAW(node.get_source(last, child.span.start))) | ||
364 | + block.append(self(child)) | ||
365 | + last = child.span.stop | ||
366 | + if last < node.span.stop : | ||
367 | + block.append(flow.RAW(node.get_source(last, node.span.stop))) | ||
368 | + return flow.CASE(flow.EXPR(f"FIXME {value}", src=value), | ||
369 | + block, | ||
370 | + src=node.sub_source(node.expr.span, "{value}", | ||
371 | + Span(node.stmts[0].span.start, | ||
372 | + node.stmts[-1].span.stop), "{body}")) | ||
373 | + def do_Default (self, node) : | ||
374 | + default = flow.DEFAULT(src=node.sub_source(Span(node.stmts[0].span.start, | ||
375 | + node.stmts[-1].span.stop), | ||
376 | + "{body}")) | ||
377 | + last = None | ||
378 | + for child in node.stmts : | ||
379 | + if last is not None and child.span.start > last : | ||
380 | + default.append(flow.RAW(node.get_source(last, child.span.start))) | ||
381 | + default.append(self(child)) | ||
382 | + last = child.span.stop | ||
383 | + if last < node.span.stop : | ||
384 | + default.append(flow.RAW(node.get_source(last, node.span.stop))) | ||
385 | + return default | ||
386 | + def do_Break (self, node) : | ||
387 | + return flow.BREAK() |
-
Please register or login to post a comment