Skip to content

Commit 03b8421

Browse files
committed
Add "specific" entity local type. This type of variable holds a value belonging to a specific entity
1 parent 624e333 commit 03b8421

File tree

6 files changed

+87
-37
lines changed

6 files changed

+87
-37
lines changed

asm_reader.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,11 @@ def next_constant(self):
113113

114114
def next_entity_local(self):
115115
name = self.read_symbol()
116-
return ('entity_local', name)
116+
specific = ''
117+
if self.head == ' ':
118+
self.read_whitespace()
119+
specific = self.read_at_least_once(lambda c: c != '\n', 'non-newline')
120+
return ('entity_local', (name, specific))
117121

118122
def next_local_label(self):
119123
return ('local_label', self.read_label())

assembler.py

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -48,24 +48,27 @@ def parse(self, text, filename=''):
4848
def consume_reader(self, reader):
4949
for (token, arg) in reader:
5050
self.lineno = reader.lineno
51-
if token == 'const':
52-
name, ref = arg
53-
self.define_const(name, self.resolve_ref(*ref))
54-
elif token == 'entity_local':
55-
self.define_entity_local(arg)
56-
elif token == 'label':
57-
self.handle_label(arg)
58-
elif token == 'instruction':
59-
if self.curr_func == '__unreachable__':
60-
self.warn("Unreachable code")
61-
continue
62-
self.handle_insn(*arg)
63-
elif token == 'local_label':
64-
self.handle_local_label(arg)
65-
elif token == 'directive':
66-
self.handle_directive(*arg)
67-
elif token == 'eof':
51+
if token == 'eof':
6852
break
53+
self.handle_token(token, arg)
54+
55+
def handle_token(self, token, arg):
56+
if token == 'const':
57+
name, ref = arg
58+
self.define_const(name, self.resolve_ref(*ref))
59+
elif token == 'entity_local':
60+
self.define_entity_local(*arg)
61+
elif token == 'label':
62+
self.handle_label(arg)
63+
elif token == 'instruction':
64+
if self.curr_func == '__unreachable__':
65+
self.warn("Unreachable code")
66+
return
67+
self.handle_insn(*arg)
68+
elif token == 'local_label':
69+
self.handle_local_label(arg)
70+
elif token == 'directive':
71+
self.handle_directive(*arg)
6972

7073
def warn(self, message):
7174
import warnings
@@ -76,8 +79,8 @@ def define_const(self, name, value):
7679
raise RuntimeError('Constant %r already defined' % name)
7780
self.constants[name] = value
7881

79-
def define_entity_local(self, name):
80-
self.define_const(name, EntityLocal(name))
82+
def define_entity_local(self, name, specific):
83+
self.define_const(name, EntityLocal(name, specific))
8184

8285
def get_const(self, name):
8386
return self.constants[name]

commands.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ class Ref(Resolvable):
5353
def selector(self, where):
5454
return ETagSelector(where)
5555

56+
@property
57+
def supports_where(self):
58+
return True
59+
5660
class Var(Ref):
5761
def __init__(self, nameref, *args):
5862
self.name = nameref
@@ -69,13 +73,23 @@ def resolve(self, scope):
6973
return scope.memory(self.loc)
7074

7175
class EntityLocal(Ref):
72-
def __init__(self, name):
76+
def __init__(self, name, specific=None):
7377
self.name = name
78+
self.specific = specific
7479

7580
def resolve(self, scope):
7681
return scope.entity_local(self.name)
7782

83+
@property
84+
def supports_where(self):
85+
return not self.specific
86+
7887
def selector(self, where):
88+
if self.specific:
89+
assert where is None, "Cannot apply selector args to specific " \
90+
+ "entity local (%s is specific to %s), tried selector: %s" % (
91+
self.name, self.specific, where)
92+
return SimpleResolve(self.specific)
7993
return Selector('s', where)
8094

8195
class SimpleResolve(Resolvable):
@@ -355,6 +369,8 @@ def __init__(self, varref, value, where=None):
355369
assert self.allows_negative or value >= 0
356370
self.var = varref
357371
self.value = value
372+
if where is not None and not varref.supports_where:
373+
assert False, "TODO"
358374
self.selector = varref.selector(where)
359375

360376
def resolve(self, scope):
@@ -396,8 +412,16 @@ def __init__(self, left, right, where=None):
396412
assert isinstance(right, Ref)
397413
self.left = left
398414
self.right = right
399-
self.left_sel = left.selector(where)
400-
self.right_sel = right.selector(where)
415+
where_l = where_r = where
416+
if where is not None:
417+
if not left.supports_where:
418+
where_l = None
419+
if not right.supports_where:
420+
where_r = None
421+
if where_l is None and where_r is None:
422+
assert False, "TODO"
423+
self.left_sel = left.selector(where_l)
424+
self.right_sel = right.selector(where_r)
401425

402426
def resolve(self, scope):
403427
return 'scoreboard players operation %s %s %s %s %s' % (
@@ -431,6 +455,7 @@ class SelRange(SelectorArgs):
431455
def __init__(self, varref, min=None, max=None):
432456
assert min is not None or max is not None
433457
assert isinstance(varref, Ref)
458+
assert varref.supports_where, "TODO"
434459
self.var = varref
435460
self.min = min
436461
self.max = max

compiler/asm_writer.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ def write_constant(self, name, value):
1515
def write_directive(self, name, value):
1616
self.write_line('#%s %s' % (name, value))
1717

18-
def write_entity_local(self, name):
19-
self.write_line('@%s' % name)
18+
def write_entity_local(self, name, specific):
19+
self.write_line('@%s%s' % (name, ' ' + specific if specific else ''))
2020

2121
def write_local_label(self, label):
2222
self.write_line('_%s:' % label)
2323

2424
def write_label(self, label):
2525
self.indent = 0
26-
self.write_line('%s:' % label)
26+
self.write_line('\n%s:' % label)
2727
self.indent = 4
2828

2929
def write_instruction(self, insn, operands, comment=None):
@@ -75,8 +75,8 @@ def write_constant(self, name, value):
7575
def write_directive(self, name, value):
7676
self.add('directive', (name, value))
7777

78-
def write_entity_local(self, name):
79-
self.add('entity_local', name)
78+
def write_entity_local(self, name, specific):
79+
self.add('entity_local', (name, specific))
8080

8181
def write_local_label(self, label):
8282
self.add('local_label', label)
@@ -146,8 +146,8 @@ def write_constant(self, name, value):
146146
def write_directive(self, name, value):
147147
self.backend.write_directive(name, value)
148148

149-
def write_entity_local(self, name):
150-
self.backend.write_entity_local(name)
149+
def write_entity_local(self, name, specific):
150+
self.backend.write_entity_local(name, specific)
151151

152152
def write_subroutine(self, name):
153153
if name == '__setup__':

compiler/compiler.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -818,10 +818,9 @@ def lookup(self, name):
818818
return self.current_table.lookup(name)
819819

820820
def declare_symbol(self, name, type, can_redeclare=False):
821-
if type is self.compiler.types.types['entity_local']:
821+
if type is self.compiler.type('entity_local'):
822822
# hijack entity_local
823823
unit = self.entity_local_storage.insert(type)
824-
self.compiler.emit(IR.EntityLocalVar(name, unit.offset))
825824
else:
826825
unit = self.store(type)
827826
return self.current_table.declare(name, type, unit,
@@ -1206,15 +1205,26 @@ def visit_decl(self, decl):
12061205
return
12071206
for init in decl.init:
12081207
symbol = self.declare_from_node(decl.type, init.decl)
1208+
is_entity_local = symbol.type is self.type('entity_local')
12091209
if init.val is not None:
12101210
if type(init.val) == list:
12111211
data = self.visit_list_init_data(symbol.type, init.val)
12121212
loc = self.offset(symbol.storage.store.relative_base,
12131213
symbol.storage.offset, symbol.type)
12141214
self.move_data_array(data, loc)
12151215
else:
1216+
if is_entity_local:
1217+
# hijack entity local
1218+
val = self.visit_expression(init.val)
1219+
assert isinstance(val, IR.LiteralString)
1220+
local_name = val.val
1221+
self.emit(IR.EntityLocalVar(symbol.name, symbol.storage.offset, local_name))
1222+
return
12161223
self.visit_expression(AssignmentExpr(
12171224
left=init.decl.name_spec, right=init.val))
1225+
else:
1226+
if is_entity_local:
1227+
self.emit(IR.EntityLocalVar(symbol.name, symbol.storage.offset, ''))
12181228
else:
12191229
# structs get defined in these functions, make sure it is created
12201230
if isinstance(decl.type, DeclarationSpecifier):

compiler/ir.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class IR:
1010
FunctionEnd = namedtuple('FunctionEnd', '')
1111

1212
Label = namedtuple('Label', 'label')
13-
EntityLocalVar = namedtuple('EntityLocalVar', 'name offset')
13+
EntityLocalVar = namedtuple('EntityLocalVar', 'name offset specific')
1414

1515
Jump = namedtuple('Jump', 'dest')
1616
JumpIf = namedtuple('JumpIf', 'dest cond')
@@ -294,19 +294,27 @@ def __init__(self, downstream):
294294
optimizer = DeadCodeElimination(loop, optimizer)
295295
super().__init__(optimizer)
296296
self.loop = loop
297-
298-
def handle_entity_local(self, insn):
299-
# This appears before functions begin, pass straight through
300-
self.loop.downstream.handle_insn(insn)
297+
self.outside_fn = True
301298

302299
def handle_fn_begin(self, insn):
303300
self.loop.new_fn()
301+
self.outside_fn = False
302+
self.emit(insn)
303+
304+
def handle_fn_end(self, insn):
304305
self.emit(insn)
306+
self.outside_fn = True
305307

306308
def handle_insn(self, insn):
307309
#print("UPSTREAM", node_debug(insn))
308310
super().handle_insn(insn)
309311

312+
def emit(self, insn):
313+
if self.outside_fn:
314+
self.loop.downstream.handle_insn(insn)
315+
else:
316+
super().emit(insn)
317+
310318
class OptimizerVisitor(IRVisitor):
311319

312320
def __init__(self, loop, downstream):

0 commit comments

Comments
 (0)