@@ -15,29 +15,89 @@ def __init__(self, pos, writer, namespace, page_size=64, **kwargs):
1515 self .add_page ()
1616
1717 def add_page (self ):
18- setter = Subsequence ()
19- getter = Subsequence ()
20- dump = ["[" ]
21-
2218 mbr = Var ('memory_buffer' )
2319 mar = Var ('memory_address' )
2420
25- for i in range (self .page_size ):
26- slot = Var ('memory_slot' , i )
27- dump .append (slot )
28- if i != self .page_size - 1 :
29- dump .append ("," )
21+ def pair_name (fn , pair ):
22+ return 'memory/%s_%d_%d' % (fn , pair .min , pair .max )
3023
31- setter .add_command (OpAssign (slot , mbr ).where (SelEquals (mar , i )))
32- getter .add_command (OpAssign (mbr , slot ).where (SelEquals (mar , i )))
24+ def create_function (pair , force = False ):
25+ getter = Subsequence ()
26+ setter = Subsequence ()
27+ def gen_fn (fn , p ):
28+ return Function (pair_name (fn , p ), cond_type = 'if' ,
29+ cond = SelRange (mar , min = p .min , max = p .max ))
30+ def gen_assign (n , g = True ):
31+ slot = Var ('memory_slot' , n )
32+ return OpAssign (mbr if g else slot , slot if g else mbr ) \
33+ .where (SelEquals (mar , n ))
3334
34- self .scope .add_function_names (('mem_set' , 'mem_get' , 'mem_dump' ))
35- self .add_subsequence ('mem_set' , setter )
35+ if pair .left and pair .left .left :
36+ getter .add_command (gen_fn ('mem_get' , pair .left ))
37+ setter .add_command (gen_fn ('mem_set' , pair .left ))
38+ if pair .right and pair .right .right :
39+ getter .add_command (gen_fn ('mem_get' , pair .right ))
40+ setter .add_command (gen_fn ('mem_set' , pair .right ))
41+
42+ if not pair .left and not pair .right and not force :
43+ # Don't do anything here, it's done in the next level up
44+ return
45+
46+ if pair .left and not pair .left .left or force :
47+ getter .add_command (gen_assign (pair .min ))
48+ setter .add_command (gen_assign (pair .min , False ))
49+ if pair .right and not pair .right .right :
50+ getter .add_command (gen_assign (pair .max ))
51+ setter .add_command (gen_assign (pair .max , False ))
52+
53+ name_get = pair_name ('mem_get' , pair )
54+ name_set = pair_name ('mem_set' , pair )
55+ self .scope .add_function_names ((name_get , name_set ))
56+ self .add_subsequence (name_get , getter )
57+ self .add_subsequence (name_set , setter )
58+
59+ entry_point = self .generate_bin_tree (self .page_size , create_function )
60+ if not entry_point .left and not entry_point .right :
61+ create_function (entry_point , force = True )
62+
63+ # Redirect mem_get and mem_set to the actual entry point
64+ getter = Subsequence ()
65+ setter = Subsequence ()
66+ getter .add_command (Function (pair_name ('mem_get' , entry_point )))
67+ setter .add_command (Function (pair_name ('mem_set' , entry_point )))
68+ self .scope .add_function_names (('mem_get' , 'mem_set' ))
3669 self .add_subsequence ('mem_get' , getter )
37- s = Subsequence ()
38- dump .append ("]" )
39- s .add_command (Tellraw (dump , 'a' ))
40- self .add_subsequence ('mem_dump' , s )
70+ self .add_subsequence ('mem_set' , setter )
71+
72+
73+ def generate_bin_tree (self , size , callback ):
74+ assert size > 0
75+ from collections import namedtuple
76+ Pair = namedtuple ('Pair' , 'left right min max' )
77+ old_pairs = []
78+ for n in range (size ):
79+ pair = Pair (None , None , n , n )
80+ old_pairs .append (pair )
81+ callback (pair )
82+ while len (old_pairs ) > 1 :
83+ pairs = []
84+ waiting = None
85+ for pair in old_pairs :
86+ if waiting is None :
87+ waiting = pair
88+ else :
89+ new_pair = Pair (waiting , pair , waiting .min , pair .max )
90+ pairs .append (new_pair )
91+ callback (new_pair )
92+ waiting = None
93+
94+ if waiting is not None :
95+ # Dangling node, occurs if size is not a power of 2
96+ pairs .append (waiting )
97+ callback (waiting )
98+
99+ old_pairs = pairs
100+ return old_pairs [0 ]
41101
42102 def extended_setup (self , up , down ):
43103 for i in range (self .page_size ):
0 commit comments