diff --git a/lang/compile.py b/lang/compile.py index d80e9f0..b155475 100755 --- a/lang/compile.py +++ b/lang/compile.py @@ -5,9 +5,10 @@ import sys # This is a fairly basic compiler for a simple programming language -# It is split to three phases: +# It is split to these phases: # Parsing (AST and parse sections) # IR (IR and IR generator sections) +# Assign classes # Register allocation # Output (Bytecode section) @@ -442,7 +443,7 @@ self.statements = statements def __repr__(self): - return 'ASTFunction(public=%s, class="%s", name="%s", args="%s", statements=%s)' % \ + return 'IRFunction(public=%s, class="%s", name="%s", args="%s", statements=%s)' % \ (self.public, self.class_, self.name, self.args, self.statements) class IRDepthCheck(): @@ -482,6 +483,14 @@ def __repr__(self): return 'IRMetadata(id=%s, name=%s, uses=%s)' % (self.id, self.name, self.uses) +class IRClass(): + def __init__(self, name, functions): + self.name = name + self.functions = functions + + def __repr__(self): + return 'IRClass(name=%s, functions=%s)' % (self.name, self.functions) + ## IR Generator def generate_ir_value(value): @@ -603,6 +612,7 @@ public = ast.public class_ = ast.class_ name = ast.name + args = ast.args ir = [] statement_id = 1 for node in ast.statements: @@ -633,6 +643,78 @@ ir.append(sub_ir) return ir +## Assign classes + +def group_functions(ir): + groups = {} + for node in ir: + if isinstance(node, IRFunction): + class_ = node.class_ + name = node.name + if class_ not in groups: + groups[class_] = [] + group = groups[class_] + if name in group: + print("Duplicate class function: %s" % name) + return None + groups[class_].append(name) + return groups + +def make_module_class(ir): + metadata = None + for node in ir: + if isinstance(node, IRMetadata): + metadata = node + if metadata is None: + print("Unable to find module metadata?") + return None + return IRClass(metadata.name, []) + +def map_class_functions(functions, classes): + mapped_classes = [] + for group in functions: + name = group + class_ = None + for c in classes: + if c.name == name: + class_ = c + if class_ is None: + print("Unknown class %s" % (name)) + return None + funcs = functions[name] + new_class = IRClass(name, funcs) + mapped_classes.append(new_class) + return mapped_classes + +def update_classes(old_ir, new_classes): + ir = [] + for node in old_ir: + sub_ir = node + if isinstance(node, IRClass): + for c in new_classes: + if c.name == node.name: + sub_ir = c + if sub_ir is None: + print("No class for IR: %s" % (node)) + return None + ir.append(sub_ir) + return ir + +def assign_classes(ir): + grouped = group_functions(ir) + if grouped is None: + return None + module_class = make_module_class(ir) + if module_class is None: + return None + old_ir = ir + [module_class] + classes = [module_class] + mapped_classes = map_class_functions(grouped, classes) + if mapped_classes is None: + return None + new_ir = update_classes(old_ir, mapped_classes) + return new_ir + ## Register allocation # Register allocation here is very simple: Each variable gets one stack slot @@ -947,6 +1029,8 @@ elif isinstance(node, IRFunction): next = generate_bytecode(node) functions.append(generate_call(node)) + elif isinstance(node, IRClass): + next = "" # Nothing for now if next is None: print("Can't generate node: %s" % (node)) return None @@ -977,7 +1061,11 @@ if ir is None: print("Failed to generate IR") return None - ir_reg = registers_allocate(module_args, ir) + ir_class = assign_classes(ir) + if ir_class is None: + print("Failed to generate classes") + return None + ir_reg = registers_allocate(module_args, ir_class) if ir_reg is None: print("Failed to allocate registers") return None