def program(env, p, heap = int( macros.HEAP_START ) ): if p == "End": return ( [], 0, heap ) Tag = str( id( p )) for label in p: if label == "Print": exp = p[ label ][ 0 ] doc = [ "doc print " + str( exp )] (insts, heap, nextHeap) = expression( env, exp, heap ) insts += macros.copy( heap, macros.OUTPUT_REG ) ( contInsts, resultLoc, nextHeap ) = program( env, p[ label ][ 1 ], nextHeap ) return ( doc + insts + contInsts , resultLoc, nextHeap ) if label == "Assign": a = p[ label ] varExp = a[ 1 ] varName = a[0][ "Variable"][ 0 ] if env.get( varName ) == None: heap = heap + 1 varAddr = str( heap ) env[ varName ] = varAddr else: varAddr = int( env[ varName ]) (insts, resultAddr, nextHeap) = expression( env, varExp, heap ) code = [ "doc assign " + varName + str( varExp )] code += insts code += macros.copy( resultAddr, varAddr ) (cont, resultAddr, nextHeap) = program( env, a[2], heap + 1 ) return ( code + cont , resultAddr, nextHeap ) if label == "Call": call = p[ label ] procName = call[0][ "Variable"][ 0 ] callCode = macros.call( procName, Tag) (rest_insts, rest_resultAddr, rest_nextHeap ) = program( env, call[ 1 ], heap ) return ( callCode + rest_insts , rest_resultAddr, rest_nextHeap+1 ) if label == "Procedure": proc = p[ label ] procName = proc[0][ "Variable"][ 0 ] (proc_insts, ignore, nextHeap ) = program( env, proc[ 1 ], heap ) procCode = macros.procedure( procName, proc_insts ) (rest_insts, rest_resultAddr, rest_nextHeap ) = program( env, proc[ 2 ], nextHeap ) return ( procCode + rest_insts , rest_resultAddr, nextHeap+1 ) if label == "If": ifs = p[ label ] (cond_insts, cond_resultAddr, cond_nextHeap ) = expression( env, ifs[ 0 ], heap ) (ifTrue_insts, ifTrue_resultAddr, ifTrue_nextHeap ) = program( env, ifs[ 1 ], cond_nextHeap ) (rest_insts, rest_resultAddr, rest_nextHeap ) = program( env, ifs[ 2 ], ifTrue_nextHeap ) insts = [ 'doc ' + 'if (' + str( ifs[ 0 ]) + ' ... '] insts += cond_insts insts += macros.copy( cond_resultAddr, macros.ADD_RESULT ) insts += [ 'branch ' + 'ifTrue_' + Tag + ' ' + macros.ADD_RESULT ] insts += [ 'goto ' + 'ifFalse_' + Tag ] insts += [ 'label ' + 'ifTrue_' + Tag ] insts += ifTrue_insts insts += [ 'label ' + 'ifFalse_' + Tag ] insts += rest_insts return ( insts, rest_resultAddr, rest_nextHeap + 1 )
def macroTests(): testRelJump = ''' set 200 0 set 100 3 ''' + toStr( macros.relativeJump( 100 ) ) + ''' set 200 1 goto finish set 200 2 goto finish set 200 3 goto finish label finish assert 200 2 ''' test( testRelJump ) testCopy = ''' set 100 1 ''' + toStr( macros.copy( 100, 200 ) ) + ''' assert 200 1 ''' test( testCopy ) testAdd = ''' set 100 1000 set 101 2000 ''' + toStr( macros.add( 100, 101, 102 ) ) + ''' assert 102 3000 ''' test( testAdd ) testIncr = ''' set 100 2000 set 200 2000 ''' + toStr( macros.incrementBy( 100, 1 ) ) + ''' ''' + toStr( macros.incrementBy( 200, -1 ) ) + ''' assert 100 2001 assert 200 1999 ''' test( testIncr ) testDeref = ''' set 100 200 set 200 1000 set 300 0 ''' + toStr( macros.deref( 100, 300 ) ) + ''' assert 300 1000 ''' test( testDeref ) testIndirectSet = ''' set 100 101 set 101 1000 set 200 201 set 201 0 ''' + toStr( macros.indirectSet( 100, 200 ) ) + ''' assert 201 1000 ''' test( testIndirectSet ) testIndirectSetLiteral = ''' set 100 200 set 200 0 ''' + toStr( macros.indirectSetLiteral( 100, 123 ) ) + ''' assert 200 123 ''' test( testIndirectSet ) testIndirectIncrement = ''' set 100 101 set 101 1000 ''' + toStr( macros.indirectIncrement( 100, 50 ) ) + ''' assert 101 1050 ''' test( testIndirectIncrement ) testIndirectIncrement = ''' set 100 101 set 101 1000 ''' + toStr( macros.indirectIncrement( 100, 50 ) ) + ''' assert 101 1050 ''' test( testIndirectIncrement ) testStack = ''' set 100 2222 set 200 0 ''' + toStr( macros.push( 100 ) ) + ''' assert -1 2222 ''' + toStr( macros.pop( 200 ) ) + ''' doc assert 200 2222 ''' + toStr( macros.pushLiteral( 10 ) ) + ''' assert -1 10 '''+ toStr( macros.pushLiteral( 4 ) ) + ''' assert -2 4 '''+ toStr( macros.pop( 100 ) ) + ''' assert 100 4 '''+ toStr( macros.pop( 200 ) ) + ''' assert 200 10 ''' test( testStack ) pcall = ''' ''' + toStr( macros.procedure( "foo", [ 'set 300 1 ', 'set 301 2'])) + ''' ''' + toStr( macros.call( "foo", "blah" ) ) + ''' assert 300 1 assert 301 2 ''' test( pcall )