Franck Pommereau

new example, fixed bugs

......@@ -14,4 +14,4 @@
*.tikz
__pycache__
examples/codanim
examples/out.tikz
examples/out.*
......
class ExecEnv (dict) :
_ValueClass = None
def __init__ (self, *l, **k) :
super().__init__(*l, **k)
def __setitem__ (self, key, val) :
old = self.get(key, None)
try :
old.set(val)
except AttributeError :
except :
if not isinstance(val, self._ValueClass) :
val = self._ValueClass(val)
super().__setitem__(key, val)
def __getitem__ (self, key) :
old = self.get(key, None)
try :
return old.get()
except AttributeError :
except :
return super().__getitem__(key)
def exec (self, code) :
exec(code, self)
......@@ -25,13 +28,13 @@ class CAni (object) :
return self._env.get("IP", 1)
@IP.setter
def IP (self, val) :
self._env["IP"] = val
dict.__setitem__(self._env, "IP", val)
@property
def RET (self) :
return self._env.get("RET", None)
@RET.setter
def RET (self, val) :
self._env["RET"] = val
dict.__setitem__(self._env, "RET", val)
def exec (self, code) :
self._env.exec(code)
def eval (self, code) :
......
from itertools import chain
from inspect import cleandoc
from collections import defaultdict
from . import CAni
from . import CAni, ExecEnv
class dopt (dict) :
def __str__ (self) :
......@@ -48,6 +48,7 @@ class TikZ (object) :
"inner sep": "0pt",
"outer sep": "0pt"},
"alloc": {},
"index": {"scale": ".9"},
"ticks": {"gray": None,
"scale": ".7"}}
def __init__ (self, options, **default) :
......@@ -79,13 +80,13 @@ class CAniTikZ (CAni) :
self._nodeid[char] = num + 1
self._o = TikZ(tikz, **self._defaults)
def __matmul__ (self, key) :
if key == 0 :
if key == None :
return self
else :
raise ValueError("invalid index %r for %s object"
% (key, self.__class__.__name__))
def ptr (self) :
return Pointer(self@0)
return Pointer(self)
def tex (self, **tikz) :
opt = TikZ(tikz)
return cleandoc(r"""\begin{{tikzpicture}}[{opt.tikzpicture}]
......@@ -102,8 +103,12 @@ class Pointer (CAniTikZ) :
if self._d is None :
return ""
else :
tgt = (self._d@0).nodeid
tgt = (self._d@None).nodeid
return fr"\draw[{opt.pointer}] ({src}) -- ({tgt});"
def __getitem__ (self, key) :
return self._d[key]
def __setitem__ (self, key, val) :
self._d[key] = val
class Value (CAniTikZ) :
def __init__ (self, init=None, **tikz) :
......@@ -173,6 +178,8 @@ class Value (CAniTikZ) :
except :
return f"\node at ({self.nodeid}) {{{value}\strut}};"
ExecEnv._ValueClass = Value
class Aggregate (CAniTikZ) :
def __init__ (self, init, **tikz) :
super().__init__(tikz)
......@@ -199,10 +206,8 @@ class Aggregate (CAniTikZ) :
def __matmul__ (self, key) :
if key in self._d :
return self._d[key]
elif key == 0 :
elif key == None :
return self._first
elif key == -1 :
return self._last
else :
raise ValueError("invalid index %r for %s object"
% (key, self.__class__.__name__))
......@@ -240,16 +245,11 @@ class Aggregate (CAniTikZ) :
def _nodes (self, opt) :
grow = opt.aggregate["grow"]
anchor = opp(grow)
prev = None
for key, val in self._d.items() :
if prev is None :
yield val._node(opt)
opt = (opt / "pos") + {"value": {"anchor": anchor},
"pos": {"at": f"({val.nodeid}.{grow})"}}
else :
yield val._node(opt)
prev = val
first, last = (self@0).nodeid, (self@-1).nodeid
yield val._node(opt)
opt = (opt / "pos") + {"value": {"anchor": anchor},
"pos": {"at": f"({val.nodeid}.{grow})"}}
first, last = self._first.nodeid, self._last.nodeid
yield fr"\node[{opt.group},fit=({first}) ({last})] ({self.nodeid}) {{}};"
def _ticks (self, opt) :
side = opt.aggregate.get("ticks", None)
......@@ -305,24 +305,71 @@ class Aggregate (CAniTikZ) :
yield "}"
class Array (Aggregate) :
_defaults = {"aggregate": {"index": "west"}}
_defaults = {"aggregate": {"index": "north"}}
def __init__ (self, init, index=[], **tikz) :
super().__init__(init, **tikz)
self._o.aggregatescope = self._o.arrayscope
# register index
self._i = {}
for i in index :
self.index(i)
def index (self, name, init=None) :
self._i[name] = self._env[name] = Value(init)
def _ticks (self, opt) :
for t in super()._ticks(opt) :
yield t
# yield index
side = opt.aggregate.get("index", None)
if not side :
return
anchor = opp(side)
anim = defaultdict(list)
for name, value in self._i.items() :
value.stop()
for val, start, stop in value._h :
for step in range(start, stop+1) :
anim[step].append((name, val))
mina = defaultdict(set)
for step, keys in anim.items() :
mina[tuple(sorted(keys))].add(step)
def minstep (item) :
return tuple(sorted(item[1]))
for info, steps in sorted(mina.items(), key=minstep) :
xpos = defaultdict(list)
for name, value in info :
if value is not None :
xpos[value].append(name)
if not xpos :
continue
when = ",".join(str(s) for s in sorted(steps))
yield fr"\uncover<{when}>{{"
for value, names in xpos.items() :
label = self._index(names, opt)
try :
cell = (self@value).nodeid
except ValueError :
continue
yield (fr" \node[{opt.index},anchor={anchor},at=({cell}.{side})]"
fr" {{{label}}};")
yield "}"
def _index (self, names, opt) :
label = ",".join(sorted(names))
return fr"{label}\strut"
class Struct (Aggregate) :
_defaults = {"aggregate": {"grow": "south",
"ticks": "west"}}
def __init__ (self, init, **tikz) :
self.__dict__.update(_d={}, _o=None, _first=None, _last=None, nodeid=None)
super().__init__(init, **tikz)
self._o.aggregatescope = self._o.structscope
def _tick (self, key, opt) :
return fr".{key}\strut"
def __getattr__ (self, name) :
return self[name]
def __setattr__ (self, name, value) :
if name in self._d :
self[name] = value
else :
self.__dict__[name] = value
class Heap (CAniTikZ) :
_defaults = {"group": {"opacity": 0,
......@@ -360,7 +407,7 @@ class Heap (CAniTikZ) :
yield r" }"
opt = opt + {"pos": {opt.heap["grow"]:
"{dist} of {prev}".format(dist=opt.heap["distance"],
prev=(data@0).nodeid)}}
prev=(data@None).nodeid)}}
children = " ".join(f"({nid})" for nid in fit)
yield fr" \node[{opt.group},fit={children}] ({self.nodeid}) {{}};"
yield r"\end{scope}"
......
......@@ -130,7 +130,7 @@ class XDECL (_CODE) :
class DECL (_CODE) :
_fields = ["name"]
_options = ["init"]
_options = ["init", "animate"]
def __call__ (self) :
if self.init is not None :
self.init()
......@@ -147,7 +147,7 @@ class DECL (_CODE) :
return src + " " + "".join(self._tex())
def _tex (self) :
tail = r"\PY{{c+c1}}{{/* {value} */}}"
for value, start, stop in self._cell.hist :
for value, start, stop in self._env.get(self.name)._h :
if value is not None :
yield (r"\onlyshow{{{start}-{stop}}}{{{value}}}"
r"").format(start=start or 1,
......
all: heap.pdf
all: heap.pdf qs-partition.pdf
%.pdf: %.py tpl.tex
ln -sf ../codanim .
python $< > out.tikz
rm -f out.*
python $<
latexmk -pdf tpl
cp tpl.pdf $@
latexmk -C tpl
......
No preview for this file type
......@@ -6,4 +6,5 @@ p = h.new(Struct({"data": 2, "next": p}))
p = h.new(Struct({"data": 3, "next": p}))
h.new(Value(p, value={"yshift": "-1cm"}))
print(h.tex(tikzpicture={"scale": .7}))
with open("out.tikz", "w") as out :
out.write(h.tex(tikzpicture={"scale": .7}))
......
\ProvidesPackage{pygments}
\usepackage{fancyvrb}
\usepackage{color}
\makeatletter
\def\PY@reset{\let\PY@it=\relax \let\PY@bf=\relax%
\let\PY@ul=\relax \let\PY@tc=\relax%
\let\PY@bc=\relax \let\PY@ff=\relax}
\def\PY@tok#1{\csname PY@tok@#1\endcsname}
\def\PY@toks#1+{\ifx\relax#1\empty\else%
\PY@tok{#1}\expandafter\PY@toks\fi}
\def\PY@do#1{\PY@bc{\PY@tc{\PY@ul{%
\PY@it{\PY@bf{\PY@ff{#1}}}}}}}
\def\PY#1#2{\PY@reset\PY@toks#1+\relax+\PY@do{#2}}
\expandafter\def\csname PY@tok@w\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.73,0.73}{##1}}}
\expandafter\def\csname PY@tok@c\endcsname{\let\PY@it=\textit\def\PY@tc##1{\textcolor[rgb]{0.25,0.50,0.50}{##1}}}
\expandafter\def\csname PY@tok@cp\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.74,0.48,0.00}{##1}}}
\expandafter\def\csname PY@tok@k\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\expandafter\def\csname PY@tok@kp\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\expandafter\def\csname PY@tok@kt\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.69,0.00,0.25}{##1}}}
\expandafter\def\csname PY@tok@o\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\expandafter\def\csname PY@tok@ow\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.67,0.13,1.00}{##1}}}
\expandafter\def\csname PY@tok@nb\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\expandafter\def\csname PY@tok@nf\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.00,0.00,1.00}{##1}}}
\expandafter\def\csname PY@tok@nc\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.00,1.00}{##1}}}
\expandafter\def\csname PY@tok@nn\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.00,1.00}{##1}}}
\expandafter\def\csname PY@tok@ne\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.82,0.25,0.23}{##1}}}
\expandafter\def\csname PY@tok@nv\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\expandafter\def\csname PY@tok@no\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.53,0.00,0.00}{##1}}}
\expandafter\def\csname PY@tok@nl\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.63,0.63,0.00}{##1}}}
\expandafter\def\csname PY@tok@ni\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.60,0.60,0.60}{##1}}}
\expandafter\def\csname PY@tok@na\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.49,0.56,0.16}{##1}}}
\expandafter\def\csname PY@tok@nt\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\expandafter\def\csname PY@tok@nd\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.67,0.13,1.00}{##1}}}
\expandafter\def\csname PY@tok@s\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\expandafter\def\csname PY@tok@sd\endcsname{\let\PY@it=\textit\def\PY@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\expandafter\def\csname PY@tok@si\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.73,0.40,0.53}{##1}}}
\expandafter\def\csname PY@tok@se\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.73,0.40,0.13}{##1}}}
\expandafter\def\csname PY@tok@sr\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.40,0.53}{##1}}}
\expandafter\def\csname PY@tok@ss\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\expandafter\def\csname PY@tok@sx\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\expandafter\def\csname PY@tok@m\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\expandafter\def\csname PY@tok@gh\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.00,0.50}{##1}}}
\expandafter\def\csname PY@tok@gu\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.50,0.00,0.50}{##1}}}
\expandafter\def\csname PY@tok@gd\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.63,0.00,0.00}{##1}}}
\expandafter\def\csname PY@tok@gi\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.00,0.63,0.00}{##1}}}
\expandafter\def\csname PY@tok@gr\endcsname{\def\PY@tc##1{\textcolor[rgb]{1.00,0.00,0.00}{##1}}}
\expandafter\def\csname PY@tok@ge\endcsname{\let\PY@it=\textit}
\expandafter\def\csname PY@tok@gs\endcsname{\let\PY@bf=\textbf}
\expandafter\def\csname PY@tok@gp\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.00,0.50}{##1}}}
\expandafter\def\csname PY@tok@go\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.53,0.53,0.53}{##1}}}
\expandafter\def\csname PY@tok@gt\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.00,0.27,0.87}{##1}}}
\expandafter\def\csname PY@tok@err\endcsname{\def\PY@bc##1{\setlength{\fboxsep}{0pt}\fcolorbox[rgb]{1.00,0.00,0.00}{1,1,1}{\strut ##1}}}
\expandafter\def\csname PY@tok@kc\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\expandafter\def\csname PY@tok@kd\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\expandafter\def\csname PY@tok@kn\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\expandafter\def\csname PY@tok@kr\endcsname{\let\PY@bf=\textbf\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\expandafter\def\csname PY@tok@bp\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.00,0.50,0.00}{##1}}}
\expandafter\def\csname PY@tok@fm\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.00,0.00,1.00}{##1}}}
\expandafter\def\csname PY@tok@vc\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\expandafter\def\csname PY@tok@vg\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\expandafter\def\csname PY@tok@vi\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\expandafter\def\csname PY@tok@vm\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.10,0.09,0.49}{##1}}}
\expandafter\def\csname PY@tok@sa\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\expandafter\def\csname PY@tok@sb\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\expandafter\def\csname PY@tok@sc\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\expandafter\def\csname PY@tok@dl\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\expandafter\def\csname PY@tok@s2\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\expandafter\def\csname PY@tok@sh\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\expandafter\def\csname PY@tok@s1\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.73,0.13,0.13}{##1}}}
\expandafter\def\csname PY@tok@mb\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\expandafter\def\csname PY@tok@mf\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\expandafter\def\csname PY@tok@mh\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\expandafter\def\csname PY@tok@mi\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\expandafter\def\csname PY@tok@il\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\expandafter\def\csname PY@tok@mo\endcsname{\def\PY@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
\expandafter\def\csname PY@tok@ch\endcsname{\let\PY@it=\textit\def\PY@tc##1{\textcolor[rgb]{0.25,0.50,0.50}{##1}}}
\expandafter\def\csname PY@tok@cm\endcsname{\let\PY@it=\textit\def\PY@tc##1{\textcolor[rgb]{0.25,0.50,0.50}{##1}}}
\expandafter\def\csname PY@tok@cpf\endcsname{\let\PY@it=\textit\def\PY@tc##1{\textcolor[rgb]{0.25,0.50,0.50}{##1}}}
\expandafter\def\csname PY@tok@c1\endcsname{\let\PY@it=\textit\def\PY@tc##1{\textcolor[rgb]{0.25,0.50,0.50}{##1}}}
\expandafter\def\csname PY@tok@cs\endcsname{\let\PY@it=\textit\def\PY@tc##1{\textcolor[rgb]{0.25,0.50,0.50}{##1}}}
\def\PYZbs{\char`\\}
\def\PYZus{\char`\_}
\def\PYZob{\char`\{}
\def\PYZcb{\char`\}}
\def\PYZca{\char`\^}
\def\PYZam{\char`\&}
\def\PYZlt{\char`\<}
\def\PYZgt{\char`\>}
\def\PYZsh{\char`\#}
\def\PYZpc{\char`\%}
\def\PYZdl{\char`\$}
\def\PYZhy{\char`\-}
\def\PYZsq{\char`\'}
\def\PYZdq{\char`\"}
\def\PYZti{\char`\~}
% for compatibility with earlier versions
\def\PYZat{@}
\def\PYZlb{[}
\def\PYZrb{]}
\makeatother
No preview for this file type
from codanim.data import Array, Struct, Value, Heap
from codanim.flow import FUNC, BLOCK, ENV, WS, DECL, WHILE, EXPR, DO, STMT, RETURN, IF
a = Array([3, 13, 5, 0, 7, 11, 4, 9, 14, 2, 10, 1, 12, 8, 6],
index=["a", "b"])
t = Struct({"len": Value(15), "val": a.ptr()})
h = Heap()
h.new(a)
h.new(t)
partition = FUNC(BLOCK(ENV("t", t),
WS(" "),
DECL("pivot", EXPR("t.val[(t.len-1)//2]",
src="t.val[(t.len-1)/2]"),
animate=True,
src="int {name} = {init};"),
WS("\n "),
DECL("a", EXPR("-1"),
animate=True,
src="uint {name} = {init};"),
WS("\n "),
DECL("b", EXPR("t.len"),
animate=True,
src="uint {name} = {init};"),
WS("\n "),
WHILE(EXPR("1", src="1"),
BLOCK(WS(" "),
DO(STMT("a+=1", src="a++;"),
EXPR("t.val[a] < pivot"),
src="do {{ {body} }} while ({cond});"),
WS("\n "),
DO(STMT("b-=1", src="b--;"),
EXPR("t.val[b] > pivot"),
src="do {{ {body} }} while ({cond});"),
WS("\n "),
IF(EXPR("a >= b"),
RETURN(EXPR("b"),
src="return {value};"),
src="if ({cond}) {{ {then} }}"),
WS("\n "),
STMT("_old = t.val[a], t.val[b]",
"t.val[b], t.val[a] = _old",
src="swap(t, a, b);"),
WS("\n")),
src="while ({cond}) {{\n{body} }}"),
WS("\n")),
src="uint partition (Tab t) {{\n{body}}}\n")
partition.IP += 1 # do not highlight first step
partition() # simulate execution
# save code animation
with open("out.code", "w") as out :
out.write(partition.tex())
# save data animation
with open("out.tikz", "w") as out :
out.write(h.tex(tikzpicture={"scale": .6}))
......@@ -4,6 +4,7 @@
\usepackage{fancyvrb}
\usepackage{adjustbox}
\usepackage{pygments}
\usepackage{tikz}
\usetikzlibrary{arrows}
......@@ -25,8 +26,9 @@
\begin{document}
\begin{frame}
\input{out.tikz}
\begin{frame}[fragile]
\IfFileExists{out.code}{\VerbatimInput[commandchars=\\\{\}]{out.code}}{}
\IfFileExists{out.tikz}{\input{out.tikz}}{}
\end{frame}
\end{document}
......