Listoflectures IntroductionandFunctionalProgramming ImperativeProgrammingandDataStructures 3 Environment 4 Evaluation 5 ObjectOrientedProgramming 6 Macrosanddecorators 7 VirtualMachinesandBytecode 8 GarbageCollectionandNativeCode 9 DistributedComputing 10 Logic 11 Guestlecture 12 Summary 1 2 TDDA69DataandProgramStructure Macrosanddecorators CyrilleBerger 2/39 Lecturegoal Howisaprograminterpreted? Learnhowcomputerprograms canbemodifiedbyother programs 3/39 Sourcecode Parser Parser Treevisitor AbstractSyntaxTree Transformation Generator Sourcecode Bytecode VirtualMachine Assembler Assembly ... OperatingSystem CPU 4/39 Lecturecontent Mutable Macrosanddecorators MutableValues Decorators Macros 5/39 States Anassignmentchangesthe valueofavariable Allnamesareaffectedby themutation a= Object() b=a a.v=1 print(b.v) Mutationwithinafunctioncall(1/2) array=[1,2,3,4] len(array)->4 f(array) len(array)->2 deff(s): s.pop() s.pop() 7 f:func(...) s->array (global)I (f)II 8 Mutationwithinafunctioncall,always?(1/2) value=2 print(value)->2 f(value) print(value)->2 deff(s): s=1 f:func(...) Mutationwithinafunctioncall,always?(2/2) (global)I (f)II s:2 array=[1,2,3,4] len(array)->4 f(array) len(array)->4 deff(s): s=list(s) s.pop() s.pop() f:func(...) s:[1,2,3,4] 9 f:func(...) (f)II 10 Drawbacksofmutability Mutationwithinafunctioncall(2/2) array=[1,2,3,4] len(array)->4 f() len(array)->2 deff(): globalarray array.pop() array.pop() (global)I pi=2 Whathappenifyoudothis? (global)I (f)II 11 deff(s=[]): s.append(5) returnlen(s) print(f()) print(f()) print(f()) 12 Comparison(1/2) MutableDefaultarguments deff(s=[]): s.append(5) return len(s) print(f()) print(f()) print(f()) s:[5] f:func(...) (f)II s:[5,5] InPython: Valuecomparison (global)I (f)II (f)II s:[5,5,5] a=[1,2] b=[1,2] c=a print(a==b)->true print(a==c)->true Identitycomparison print(aisb)->false print(aisc)->true 13 Comparison(2/2) 14 Constantvalues(1/2) InJavaScript: Valuecomparison ['set'['x' defevaluate(node): ... elifnode[0]=='set': currentFrame.set( node[1][0], evaluate(node[1] [1])) a=5 b="5" Identitycomparison console.log(a==b)->true console.log(a===b)->false 15 16 Constantvalues(2/2) ['set'['x'10]] defevaluate(node): ... elifnode[0]=='set': if(currentFrame.isConstant(node[1][0])): throwError() else: currentFrame.set( node[1][0], evaluate(node[1][1])) Macrosanddecorators 17 MutableFunctions Afunctionwhose behaviorvariesover time Example: (global)I withdraw:func(...) Decorators defmake_withdraw(balance): (make_withdraw)II defwithdraw(amount): balance=balance-amount balance:25 returnbalance returnwithdraw withdraw=make_withdraw(100) (withdraw)III withdraw(25)-> withdraw(25)-> amount:25 withdraw(25)-> 19 Decorators Memoization(1/2) Whataboutchangingthe behaviorofafunctionwithout changingitscode? Fibonacci: deffib(n): print(n) ifn==0: return0 elifn==1: return1 else: returnfib(n-2)+fib(n-1) 21 Memoization(2/2) 22 Memoizationdecorator(1/2) Manuallyrewritten defmemoization(func): cache={} defmemoized(*args): ifargsincache: returncache[args] else: val=func(*args) cache[x]=val returncache[x] returnmemoized fib=memoization(fib) __fib_cache={0:0,1:1} deffib_cached(n): ifnin__fib_cache: return__fib_cache[n] else: __fib_cache[n]=fib_cached(n-2) +fib_cached(n-1) return__fib_cache[n] 23 24 NoconstantsinPython Memoizationdecorator(2/2) Thefollowingis Pythondoesnothaveconstants print(math.pi)->3.141592653589793 math.pi=2 print(math.pi)->2 @memoization deffib(n): returnnifn<2elsefib(n-2)+fib(n-1) Youcanfakethemwithproperties: equivalent class_math: defPI(self): return3.141592653589793 pi=property(PI,None) deffib(n): returnnifn<2elsefib(n-2)+fib(n-1) fib=memoization(fib) math=_math() print(math.pi) math.pi=2 25 26 Adjustabledecorators ConstantsinPythonwithadecorator Decoratorscantake defconstant(f): deffget(self): returnf() returnproperty(fget,None) class_Math(object): @constant defpi(): return 3.141592653589793 math=_Math() @decorator(args...) deffunc(fargs...): pass isequivalent decorators(args)(func) print(math.pi)-> math.pi=2->AttributeError:can'tsetattribute 27 28 Bound-checking Chaindecorators defbound_checking_decorator(min,max): defmake_decorator(func): defdecorator(x): if(x<minorx>max): throwError() returnf(x) @bound_checking_decorator(0,float('inf')) deffib(n): returnnifn<2elsefib(n-2)+fib(n-1) @bound_checking_decorator(0,float('inf')) @memoization deffib(n): returnnifn<2elsefib(n-2)+fib(n-1) 29 30 ASTManipulations Macros Givethepossibilitytowrite functionsthattransforman expressionintoanotherbeforeit isevaluated Macroexpansioncantake Duringinterpretation Duringcompilation 32 BuildingAST GetASTofafunction importast importinspect importast node=ast.Expression(ast.BinOp( ast.Num(2),ast.Mult(), ast.Num(3))) deffunc(x): returnx+1 source=inspect.getsource(func) ast_tree=ast.parse(source) fixed=ast.fix_missing_locations(node) codeobj=compile(fixed,'<string>', 'eval') print(eval(codeobj)) ast_tree.body[0].body[0].value.right.n=2 exec(compile(ast_tree,__file__,mode='exec')) print(func(1)) 33 34 Template(1/2) Incrementallnumbers defmy_template(): forxinrange(1,10): __body__ returnv @apply_template(my_template) deffunc(v): v=v*x deffunc(v): forxinrange(1,10): v=v*x returnv defincrement(f): source=inspect.getsource(f) ast_tree=ast.parse(source) ast_tree.body[0].decorator_list=[] classT(ast.NodeTransformer): defvisit_Num(self,node): node.n+=1 returnnode exec(compile(T().visit(ast_tree),__file__, mode='exec')) returnlocals()[ast_tree.body[0].name] @increment deffunc(n): return (2+n)*3 print(func(1)) 35 36 Template(2/2) Whenaremacrosuseful? InPython,ASTmanipulationsareseldomused Functionscover99%ofthe Butsometimemacroswillworkbetter defapply_template(template): deft(f): f_ast=ast.parse(inspect.getsource(f)).body[0] body_node=f_ast.body[0] template_ast=ast.parse(inspect.getsource(template)) template_ast.body[0].args=f_ast.args classT(ast.NodeTransformer): defvisit_Expr(self,node): if(node.value.id=='__body__'): returnbody_node else: returnnode exec(compile(T().visit(template_ast),__file__,mode='exec')) returnlocals()[template_ast.body[0].name] returnt Forexample,ifthereisaneedtoreturn Macroscanbeusedforoptimization Macroscanbeusedfortail-calloptimization Whencallingafunction,allargumentsare executed ...only Macroscansavefunction Butmacrosareobfuscated 37 Conclusion Mutablevariablesand Decorators MacrosandASTtransformations 39/39 38