Franck Pommereau

initial import

1 +*~
2 +,*
3 ++*
4 +*.aux
5 +*.log
6 +*.fdb_latexmk
7 +*.fls
8 +*.nav
9 +*.vrb
10 +*.out
11 +*.snm
12 +*.synctex.gz
13 +*.toc
14 +__pycache__
1 +class ExecEnv (dict) :
2 + def __init__ (self, *l, **k) :
3 + super().__init__(*l, **k)
4 + def __setitem__ (self, key, val) :
5 + old = self.get(key, None)
6 + try :
7 + old.set(val)
8 + except AttributeError :
9 + super().__setitem__(key, val)
10 + def __getitem__ (self, key) :
11 + old = self.get(key, None)
12 + try :
13 + return old.get()
14 + except AttributeError :
15 + return super().__getitem__(key)
16 + def exec (self, code) :
17 + exec(code, self)
18 + def eval (self, code) :
19 + return eval(code, self)
20 +
21 +class CAni (object) :
22 + _env = ExecEnv()
23 + @property
24 + def IP (self) :
25 + return self._env.get("IP", 1)
26 + @IP.setter
27 + def IP (self, val) :
28 + self._env["IP"] = val
29 + @property
30 + def RET (self) :
31 + return self._env.get("RET", None)
32 + @RET.setter
33 + def RET (self, val) :
34 + self._env["RET"] = val
35 + def exec (self, code) :
36 + self._env.exec(code)
37 + def eval (self, code) :
38 + RET = self.RET = self._env.eval(code)
39 + return RET
This diff is collapsed. Click to expand it.
1 +from inspect import Signature, Parameter
2 +
3 +from . import CAni
4 +from .highlight import pygmentize
5 +
6 +class _CODE (CAni) :
7 + _fields = []
8 + _options = []
9 + def __init__ (self, *l, **k) :
10 + params = []
11 + for i, name in enumerate(self._fields) :
12 + if name[0] == "*" :
13 + self._fields = self._fields[:]
14 + self._fields[i] = name[1:]
15 + params.append(Parameter(name[1:], Parameter.VAR_POSITIONAL))
16 + else :
17 + params.append(Parameter(name, Parameter.POSITIONAL_OR_KEYWORD))
18 + for name in self._options :
19 + params.append(Parameter(name, Parameter.POSITIONAL_OR_KEYWORD, default=None))
20 + params.append(Parameter("src", Parameter.KEYWORD_ONLY, default=None))
21 + sig = Signature(params)
22 + args = sig.bind(*l, **k)
23 + args.apply_defaults()
24 + for key, val in args.arguments.items() :
25 + setattr(self, key, val)
26 + self._at = set()
27 + def __str__ (self) :
28 + content = []
29 + for key, val in self.items() :
30 + if isinstance(val, _CODE) :
31 + content.append((key, str(val)))
32 + else :
33 + content.append((key, repr(val)))
34 + return "%s(%s)" % (self.__class__.__name__,
35 + ", ".join("%s=%r" % item for item in content))
36 + def items (self) :
37 + for field in self._fields :
38 + yield field, getattr(self, field)
39 + for field in self._options :
40 + member = getattr(self, field, None)
41 + if member is not None :
42 + yield field, member
43 + def source (self) :
44 + sub = {}
45 + for key, val in self.items() :
46 + if isinstance(val, _CODE) :
47 + sub[key] = val.source()
48 + else :
49 + sub[key] = val
50 + return self.src.format(**sub)
51 + def tex (self) :
52 + sub = self.src.format(**{key : "$" for key, val in self.items()}).split("$")
53 + parts = [pygmentize(sub[0])]
54 + for (key, val), txt in zip(self.items(), sub[1:]) :
55 + if isinstance(val, _CODE) :
56 + parts.append(val.tex())
57 + else :
58 + parts.append(pygmentize(str(val)))
59 + parts.append(pygmentize(txt))
60 + tex = "".join(parts)
61 + if self._at :
62 + return r"\onlyhl{%s}{" % ",".join(str(i) for i in self._at) + tex + "}"
63 + else :
64 + return tex
65 +
66 +class BLOCK (_CODE) :
67 + _fields = ["*body"]
68 + def __call__ (self) :
69 + self._at.add(self.IP)
70 + for code in self.body :
71 + code()
72 + def source (self) :
73 + return "".join(b.source() for b in self.body)
74 + def tex (self) :
75 + return "".join(b.tex() for b in self.body)
76 +
77 +class STMT (_CODE) :
78 + _fields = ["*steps"]
79 + def __call__ (self) :
80 + for s in self.steps :
81 + self._at.add(self.IP)
82 + self.exec(s)
83 + self.IP += 1
84 +
85 +class EXPR (_CODE) :
86 + _fields = ["expr"]
87 + def __init__ (self, *l, **k) :
88 + super().__init__(*l, **k)
89 + if self.src is None :
90 + self.src = self.expr
91 + def __call__ (self) :
92 + self._at.add(self.IP)
93 + self.eval(self.expr)
94 + self.IP += 1
95 +
96 +class PY (_CODE) :
97 + _fields = ["py"]
98 + def __call__ (self) :
99 + self.exec(self.py)
100 + def tex (self) :
101 + return ""
102 + def source (self) :
103 + return ""
104 +
105 +class ENV (_CODE) :
106 + _fields = ["name", "value"]
107 + def __call__ (self) :
108 + self._env[self.name] = self.value
109 + def tex (self) :
110 + return ""
111 + def source (self) :
112 + return ""
113 +
114 +class WS (_CODE) :
115 + _fields = []
116 + def __init__ (self, src) :
117 + super().__init__(src=src)
118 + def __call__ (self) :
119 + pass
120 + def tex (self) :
121 + return self.src
122 +
123 +class XDECL (_CODE) :
124 + _fields = ["*names"]
125 + def __call__ (self) :
126 + for name in self.names :
127 + self._env[name] = None
128 + self._at.add(self.IP)
129 + self.IP += 1
130 +
131 +class DECL (_CODE) :
132 + _fields = ["name"]
133 + _options = ["init"]
134 + def __call__ (self) :
135 + if self.init is not None :
136 + self.init()
137 + self._env[self.name] = self.RET
138 + else :
139 + self._env[self.name] = None
140 + self._at.add(self.IP)
141 + self.IP += 1
142 + def tex (self) :
143 + src = super().tex()
144 + if self.animate is None :
145 + return src
146 + else :
147 + return src + " " + "".join(self._tex())
148 + def _tex (self) :
149 + tail = r"\PY{{c+c1}}{{/* {value} */}}"
150 + for value, start, stop in self._cell.hist :
151 + if value is not None :
152 + yield (r"\onlyshow{{{start}-{stop}}}{{{value}}}"
153 + r"").format(start=start or 1,
154 + stop=stop or "",
155 + value=tail.format(value=value))
156 +
157 +class BreakLoop (Exception) :
158 + def __init__ (self) :
159 + super().__init__()
160 +
161 +class BREAK (_CODE) :
162 + def __call__ (self) :
163 + self._at.add(self.IP)
164 + self.IP += 1
165 + raise BreakLoop()
166 +
167 +class FunctionReturn (Exception) :
168 + def __init__ (self, RET) :
169 + super().__init__()
170 + self.RET = RET
171 +
172 +class RETURN (_CODE) :
173 + _fields = ["value"]
174 + def __call__ (self) :
175 + self.value()
176 + self._at.add(self.IP)
177 + self.IP += 1
178 + raise FunctionReturn(self.RET)
179 +
180 +class IF (_CODE) :
181 + _fields = ["cond", "then"]
182 + _options = ["otherwise"]
183 + def __call__ (self) :
184 + self.cond()
185 + if self.RET :
186 + self.then()
187 + elif self.otherwise is not None :
188 + self.otherwise()
189 +
190 +class WHILE (_CODE) :
191 + _fields = ["cond", "body"]
192 + def __call__ (self) :
193 + try :
194 + while True :
195 + self.cond()
196 + if not self.RET :
197 + break
198 + self.body()
199 + except BreakLoop :
200 + return
201 +
202 +class DO (_CODE) :
203 + _fields = ["body", "cond"]
204 + def __call__ (self) :
205 + try :
206 + while True :
207 + self.body()
208 + self.cond()
209 + if not self.RET :
210 + break
211 + except BreakLoop :
212 + pass
213 +
214 +class FOR (_CODE) :
215 + _fields = ["init", "cond", "step", "body"]
216 + def __call__ (self) :
217 + self.init()
218 + try :
219 + while True :
220 + self.cond()
221 + if not self.RET :
222 + break
223 + self.body()
224 + self.step()
225 + except BreakLoop :
226 + pass
227 +
228 +class FUNC (_CODE) :
229 + _fields = ["body"]
230 + def __call__ (self) :
231 + try :
232 + self.body()
233 + except FunctionReturn as exc :
234 + self._env["RET"] = exc.RET
235 +
1 +from pygments import highlight as _pygmentize
2 +import pygments.lexers, pygments.formatters
3 +
4 +##
5 +## code pretty-printing
6 +##
7 +
8 +_lexer = pygments.lexers.get_lexer_by_name("C")
9 +_formatter = pygments.formatters.get_formatter_by_name("latex")
10 +
11 +def pygmentize (src) :
12 + return "\n".join("\n".join(_pygmentize(line, _lexer, _formatter).splitlines()[1:-1])
13 + for line in src.split("\n"))