def compiler_third_pass(lines: Lines, supported_opcodes: SupportedOpcodes) -> Lines: rtn = [] ids_defined = {} # type: Dict[str, Command] for i, x in enumerate(lines.items): x # type: Command # todo: check that all arguments referencing addresses are existing. if x.label.name in ids_defined: prev = ids_defined[x.label.name] raise CompilerException( x.label.loc, reason=f"Redefinition of label `{x.label.name}`", subsequent=CompilerException( prev.label.loc, "Location of the previous definition")) ids_defined[x.label.name] = x if x.opcode.name in supported_opcodes: supported_opcodes[x.opcode.name].check(x) else: raise CompilerException( x.opcode.loc, reason=f"Unsupported opcode `{x.opcode.name}`", ) rtn.append(x) return Lines(rtn, loc=lines.loc)
def check(self, c: Command): if len(c.args) != 1: raise CompilerException(c.loc, "`frz_fork` requires 1 arguments")
def check(self, c: Command): if len(c.args) != 2: raise CompilerException(c.loc, "`frz` requires 2 arguments")
def decorate_exception(self, exc: CompilerException): return exc.with_text(self.p_text).with_filename(self.p_filename)
def compiler_first_pass(text) -> Lines: try: xx = lines.parseString(text, parseAll=True)[0] return xx except ParseException as e: raise CompilerException(e.loc, f'Tokenizer error: "{e}"') from None
def check(self, c: Command): if len(c.args) != 2: raise CompilerException( c.loc, f"{self.name} not enough args: {c.args} (must be 2)")
def check(self, c: Command): if len(c.args) != 0: raise CompilerException(c.loc, f"{self.name} does not accept arguments")
def check(self, c: Command): if len(c.args) != 3: raise CompilerException(c.loc, f"{self.name} needs 3 arguments")