import sys
class Enum:
def __init__(self):
self.name = ''
self.items = []
def add_item(self, item):
self.items.append(item)
def tree(self, indent=0):
ind = ' ' * indent
out = self.name + '(\n'
for item in self.items:
out += ind + ' '
if type(item) is str:
out += item + ',\n'
else:
out += item.tree(indent + 1) + ',\n'
out += ind + ')'
return out
def get(self, index):
return self.items[index]
def keys(self):
return list(range(len(self.items)))
class Struct:
def __init__(self):
self.name = ''
self.items = {}
def add_item(self, name, value):
self.items[name] = value
def tree(self, indent=0):
ind = ' ' * indent
out = self.name + ' {\n'
for key, item in self.items.items():
out += ind + ' ' + key + ': '
if type(item) is str:
out += item + ',\n'
else:
out += item.tree(indent + 1) + ',\n'
out += ind + '}'
return out
def get(self, index):
return self.items[index]
def keys(self):
return list(self.items.keys())
class Array:
def __init__(self):
self.items = []
def add_item(self, item):
self.items.append(item)
def tree(self, indent=0):
ind = ' ' * indent
out = '[\n'
for item in self.items:
out += ind + ' '
if type(item) is str:
out += item + ',\n'
else:
out += item.tree(indent + 1) + ',\n'
out += ind + ']'
return out
def get(self, index):
return self.items[index]
def keys(self):
return list(range(len(self.items)))
buffer = sys.stdin.read()
lines = [line for line in buffer.split('\n') if line not in ['Compiling source...']]
mode_stack = [None]
data_stack = []
def push_new(symbol, name):
if symbol == '{':
mode_stack.append('struct')
to_push = Struct()
to_push.name = name
data_stack.append(to_push)
elif symbol == '(':
mode_stack.append('enum')
to_push = Enum()
to_push.name = name
data_stack.append(to_push)
elif symbol == '[':
mode_stack.append('array')
to_push = Array()
data_stack.append(to_push)
else:
raise Exception('Unknown data symbol ' + symbol + ' (name ' + name + ')')
def pop():
if (len(data_stack) > 1):
data_stack.pop()
mode_stack.pop()
for line in lines:
line = line.strip()
mode = mode_stack[-1]
if (len(line) <= 1):
continue
if mode == None:
symbol = line[-1]
name = line[:-1].strip()
push_new(symbol, name)
elif mode == 'struct':
if ':' in line:
key = line.split(':')[0]
symbol = line[-1]
name = line.split(':')[1][:-1].strip()
if (symbol == ','):
data_stack[-1].add_item(key, name)
else:
push_new(symbol, name)
data_stack[-2].add_item(key, data_stack[-1])
else:
pop()
elif mode == 'array':
if '],' in line:
pop()
else:
symbol = line[-1]
name = line[:-1].strip()
if symbol == ',':
data_stack[-1].add_item(name)
else:
push_new(symbol, name)
data_stack[-2].add_item(data_stack[-1])
elif mode == 'enum':
if '),' in line:
pop()
else:
symbol = line[-1]
name = line[:-1].strip()
if symbol == ',':
data_stack[-1].add_item(name)
else:
push_new(symbol, name)
data_stack[-2].add_item(data_stack[-1])
root = data_stack[0]
class Variable:
def __init__(self, source):
self.defining_scope = -1
self.name = 'UNNAMED'
self.type_name = ''
self.matching_scope = None
type_declaration = source.get('data_type')
if type(type_declaration) == type(''):
self.type_name = type_declaration
if self.type_name == 'Macro':
self.matching_scope = int(source.get('initial_value').get(0).get('body').get(0))
else:
self.type_name = 'todo...'
def describe(self):
global scopes
scope_name = 'nowhere'
if self.defining_scope != -1:
scope_name = 'in ' + scopes[self.defining_scope].get_name()
return self.name + ' (' + self.type_name + ' defined ' + scope_name + ')' + self.extra()
def extra(self):
return ''
def finalize(self):
global scopes
if self.matching_scope is not None:
scopes[self.matching_scope].name = self.name
variables = []
for variable_source in root.get('variables').items:
variable = Variable(variable_source)
variables.append(variable)
class Scope:
def __init__(self):
self.name = 'unnamed'
self.parent = None
self.body = []
def get_name(self):
global scopes
if self.parent is None:
return self.name
else:
return scopes[self.parent].get_name() + '.' + self.name
def describe(self):
out = 'SCOPE for ' + self.get_name() + '\n'
out += ' body:\n'
for call in self.body:
out += ' ' + call.describe().replace('\n', '\n ') + '\n'
return out
class MacroCall:
def __init__(self, macro, inputs, outputs):
self.macro = macro
self.inputs = inputs
self.outputs = outputs
def describe(self):
global variables
out = 'call ' + variables[self.macro].describe() + '\n'
for index, value in enumerate(self.inputs):
out += ' i' + str(index + 1) + ': ' + variables[value].describe() + '\n'
for index, value in enumerate(self.outputs):
out += ' o' + str(index + 1) + ': ' + variables[value].describe() + '\n'
return out[:-1]
scopes = []
scope_sources = root.get('scopes').items
current_index = -1
for scope_source in scope_sources:
current_index += 1
scope = Scope()
if current_index == 0:
scope.name = 'root'
parent_source = scope_source.get('parent')
if parent_source != 'None':
scope.parent = int(parent_source.get(0).get(0))
scopes.append(scope)
if scope_source.get('body') != '[]':
for call in scope_source.get('body').items:
macro = int(call.get('macro').get(0))
inputs, outputs = [], []
if call.get('inputs') != '[]':
for iinput in call.get('inputs').items:
inputs.append(int(iinput.get('base').get(0)))
if call.get('outputs') != '[]':
for output in call.get('outputs').items:
outputs.append(int(output.get('base').get(0)))
scope.body.append(MacroCall(macro, inputs, outputs))
if type(scope_source.get('symbols')) is not str:
for symbol in scope_source.get('symbols').keys():
real_name = symbol[1:-1] variable_id = scope_source.get('symbols').get(symbol).get(0)
index = int(variable_id)
variables[index].name = real_name
variables[index].defining_scope = current_index
if (scope_source.get('intermediates') == '[]'):
continue
for iindex, intermediate in enumerate(scope_source.get('intermediates').items):
variable_id = intermediate.get(0)
index = int(variable_id)
variables[index].name = '!intermediate_' + str(iindex)
variables[index].defining_scope = current_index
for variable in variables:
variable.finalize()
for scope in scopes:
print(scope.describe())