def gencode(self, env, opt): if opt.bp is None: g.r.addReport( m.Report('error', self.tok, 'break in unbreakable point')) return m.Insts() else: return m.Insts(m.Type(), [m.Inst(opc.JUMP, opt.bp)])
class Funccall(AST): def __init__(self, tok, name, args): self.tok = tok self.name = name self.args = args def gencode(self, env, opt): if (result := self.assertOnlyRValue(env, opt)) is not None: return result try: define = env.functionLookup(self.name) except m.SymbolNotFoundException: g.r.addReport( m.Report('error', self.tok, f"function '{self.name}' not defined")) return m.Insts() if self.args is None: self.args = [] selfArgLength = len(self.args) definedArgLength = len(define.args) if selfArgLength != definedArgLength: g.r.addReport( m.Report( 'error', self.tok, f'too {"many" if selfArgLength > definedArgLength else "few"} arguments to function call, expected {definedArgLength}, have {selfArgLength}' )) return m.Insts() mytype = define.typ codes = [] argtypes = [] for elem in reversed(self.args): arg = elem.gencode(env, newopt(opt, 1)) codes.extend(arg.bytecodes) argtypes.append(arg.typ) argtypes = list(reversed(argtypes)) for i in range(selfArgLength): if argtypes[i] != define.args[i].typ: g.r.addReport( m.Report( 'error', self.tok, f'{"%d%s" % (i+1,"tsnrhtdd"[(i+1//10%10!=1)*((i+1)%10<4)*(i+1)%10::4])} parameter type mismatches' )) return m.Insts() codes.append(m.Inst(opc.CALL, self.name)) codes.append(m.Inst(opc.POPR, len(self.args))) if (opt.popc == 0): codes.append(m.Inst(opc.POP, self.nullarg)) env.markCalledFunc(self.name) return m.Insts(mytype, codes)
def gencode(self, env, opt): if opt.cp is None: g.r.addReport( m.Report( 'error', self.tok, 'to continue, you need extra gem! (you can\'t continue here.)' )) return m.Insts() else: return m.Insts(m.Type(), [m.Inst(opc.JUMP, opt.cp)])
def gencode(self, env, opt): if self.body: codes = self.body.gencode(env, newopt(opt, 1)).bytecodes else: codes = [m.Inst(opc.PUSH, 0)] codes.append(m.Inst(opc.RET, self.nullarg)) return m.Insts(m.Type(), codes)
class Post_dec(AST): def __init__(self, tok, left): self.tok = tok self.left = left def gencode(self, env, opt): if (result := self.assertOnlyRValue(env, opt)) is not None: return result left = self.left.gencode(env, newopt(opt, 1, 'r')) codes = left.bytecodes typ = copy(left.typ) if (opt.popc == 1): codes.append(m.Inst(opc.DUP, self.nullarg)) else: typ = m.Type() if typ.isPointer(): codes.append(m.Inst(opc.DEC, env.calcPointeredSize(typ))) else: codes.append(m.Inst(opc.DEC, 1)) codes.extend(self.left.gencode(env, newopt(opt, 0, 'l')).bytecodes) return m.Insts(typ, codes)
def gencode(self, env, opt): label = env.currentFuncName + self.name expr = self.expr.gencode(env, newopt(opt, 0)) codes = [m.Inst(opc.LABEL, label)] codes.extend(expr.bytecodes) return m.Insts(expr.typ, codes)
def assertOnlyRValue(self, env, opt): if (opt.lr != 'r'): g.r.addReport( m.Report( 'error', self.tok, f'expression \'{self.__class__.__name__}\' is not assignable' )) return m.Insts()
def gencode(self, env, opt): body = self.body.gencode(env, newopt(opt, 1)) codes = body.bytecodes if opt.lr == 'r': if (result := self.assertOnlyPop1(env, opt)) is not None: return result codes.append(m.Inst(opc.LOADP, self.nullarg)) return m.Insts(copy(body.typ).addRefcount(-1), codes)
def gencode(self, env, opt): env.pushScope() insts = [] for elem in self.body: insts.extend(elem.gencode(env, newopt(opt, 0)).bytecodes) env.popScope() return m.Insts(m.Type(), insts)
def gencode(self, env, opt): # self.typ.resolve(env) insts = [] for elem in reversed(self.bodys): insts.extend(elem.gencode(env, newopt(opt, 1)).bytecodes) #insts.append(m.Inst(opc[self.opc], self.arg.eval())) insts.append(m.Inst(opc[self.opc], self.arg)) return m.Insts(self.typ, insts)
def gencode(self, env, opt): cond = self.cond.gencode(env, newopt(opt, 1)).bytecodes then = self.then.gencode(env, newopt(opt, 0)).bytecodes l0 = env.issueLabel() codes = cond codes.append(m.Inst(opc.JIF0, l0)) codes.extend(then) codes.append(m.Inst(opc.LABEL, l0)) return m.Insts(m.Type(), codes)
class Cast(AST): def __init__(self, tok, targetType, body): self.tok = tok self.targetType = targetType self.body = body def gencode(self, env, opt): if (result := self.assertOnlyPop1(env, opt)) is not None: return result bodyc = self.body.gencode(env, newopt(opt, 1)) codes = bodyc.bytecodes if bodyc.typ.basetype == 'int': if self.targetType.basetype == 'float': codes.append(m.Inst(opc.ITOF, self.nullarg)) return m.Insts(m.Type('float'), codes) else: g.r.addReport( m.Report( 'fatal', self.tok, 'Program error occurred while evaluating \'Cast\' #0')) return m.Insts() elif bodyc.typ.basetype == 'float': if self.targetType.basetype == 'int': codes.append(m.Inst(opc.FTOI, self.nullarg)) return m.Insts(m.Type('int'), codes) else: g.r.addReport( m.Report( 'fatal', self.tok, 'Program error occurred while evaluating \'Cast\' #1')) return m.Insts() else: g.r.addReport( m.Report( 'fatal', self.tok, 'Program error occurred while evaluating \'Cast\' #2')) return m.Insts()
def gencode(self, env, opt): left = self.left.gencode(env, newopt(opt, 1)) codes = left.bytecodes field = env.getField(left.typ, self.fieldname) # TODO handle exception # g.r.addReport(m.Report('error', self.tok, f"cannot get field '{self.fieldname}' of type '{left.typ}'")) # return m.Insts() codes.append(m.Inst(opc.PUSH, field[0])) codes.append(m.Inst(opc.ADDI, self.nullarg)) return m.Insts(field[1], codes)
def gencode(self, env, opt): if isinstance(self.body, m.Type): return m.Insts(m.Type('int'), [m.Inst(opc.PUSH, env.calcTypeSize(self.body))]) elif isinstance(self.body, Symbol): try: var = env.variableLookup(self.body.symbolname) except m.SymbolNotFoundException as e: g.r.addReport( m.Report('fatal', self.tok, f"cannot eval size of type '{type(self.body)}'")) return m.Insts() return m.Insts(m.Type('int'), [m.Inst(opc.PUSH, env.calcTypeSize(var.typ))]) else: g.r.addReport( m.Report('fatal', self.tok, f"cannot eval size of type '{type(self.body)}'")) return m.Insts()
def gencode(self, env, opt): env.calcTypeSize(self.typ, self.init) var = env.addLocal(m.Symbol(self.symbolname, self.typ)) if self.init is None: return m.Insts() elif isinstance(self.init, list): codes = [] for i, elem in enumerate(self.init): codes.extend(elem.gencode(env, newopt(opt, 1)).bytecodes) codes.append(var.genAddrCode()) codes.append(m.Inst(opc.PUSH, i)) codes.append(m.Inst(opc.ADDI, self.nullarg)) codes.append(m.Inst(opc.STOREP, self.nullarg)) return m.Insts(m.Type(), codes) else: codes = self.init.gencode(env, newopt(opt, 1)).bytecodes codes.append(m.Inst(opc.STOREL, var.id)) return m.Insts(m.Type(), codes)
def gencode(self, env, opt): l0 = env.issueLabel() body = self.body.gencode(env, newopt(opt, cp=l0, bp=None)).bytecodes cond = self.cond.gencode(env, newopt(opt, 1)).bytecodes codes = [m.Inst(opc.LABEL, l0)] codes.extend(body) codes.extend(cond) codes.append(m.Inst(opc.INV, self.nullarg)) codes.append(m.Inst(opc.JIF0, l0)) return m.Insts(m.Type(), codes)
def gencode(self, env, opt): right = self.right.gencode(env, newopt(opt, 1)) left = self.left.gencode(env, newopt(opt, 1, 'l')) typ = m.Type() codes = right.bytecodes if opt.popc == 1: codes.append(m.Inst(opc.DUP, 1)) typ = right.typ codes.extend(left.bytecodes) return m.Insts(typ, codes)
def gencode(self, env, opt): try: var = env.variableLookup(self.symbolname) except m.SymbolNotFoundException as e: # 変数が見つからなかったら、Enumとして解決を試みる try: value = env.enumLookup(self.symbolname) except m.SymbolNotFoundException as e: g.r.addReport(m.Report('error', self.tok, f'{e} not found')) return m.Insts() if (result := self.assertOnlyRValue(env, opt)) is not None: return result if (result := self.assertOnlyPop1(env, opt)) is not None: return result
def gencode(self, env, opt): cond = self.cond.gencode(env, newopt(opt, 1)) then = self.then.gencode(env, newopt(opt, 1)) elst = self.elst.gencode(env, newopt(opt, 1)) # TODO check if then.typ != elst.typ l0 = env.issueLabel() l1 = env.issueLabel() codes = cond.bytecodes codes.append(m.Inst(opc.JIF0, l0)) codes.extend(then.bytecodes) codes.append(m.Inst(opc.JUMP, l1)) codes.append(m.Inst(opc.LABEL, l0)) codes.extend(elst.bytecodes) codes.append(m.Inst(opc.LABEL, l1)) return m.Insts(then.typ, codes)
def gencode(self, env, opt): tableCodes = self.cond.gencode(env, newopt(opt, 1)).bytecodes bodyCodes = [] end = env.issueLabel() default = None for elem in self.cases: label = env.issueLabel() if elem[0] == 'default': default = label bodyCodes.append(m.Inst(opc.LABEL, label)) for e in elem[1]: bodyCodes.extend( e.gencode(env, newopt(opt, 1, bp=end)).bytecodes) else: tableCodes.append(m.Inst(opc.DUP, 1)) tableCodes.extend(elem[0].gencode(env, newopt(opt, 1)).bytecodes) tableCodes.append(m.Inst(opc.NEQI, self.nullarg)) #TODO Int以外にも対応させる tableCodes.append(m.Inst(opc.JIF0, label)) bodyCodes.append(m.Inst(opc.LABEL, label)) for e in elem[1]: bodyCodes.extend( e.gencode(env, newopt(opt, 1, bp=end)).bytecodes) if default is not None: tableCodes.append(m.Inst(opc.JUMP, default)) else: tableCodes.append(m.Inst(opc.JUMP, end)) bodyCodes.append(m.Inst(opc.LABEL, end)) bodyCodes.append(m.Inst(opc.POP, self.nullarg)) codes = tableCodes codes.extend(bodyCodes) return m.Insts(m.Type(), codes)
def gencode(self, env, opt): l0 = env.issueLabel() l1 = env.issueLabel() if self.init is None: # TODO 1ライン化するか関数化して全部に適用 init = [] else: init = self.init.gencode(env, newopt(opt, 0)).bytecodes cond = self.cond.gencode(env, newopt(opt, 1)).bytecodes loop = self.loop.gencode(env, newopt(opt, 0)).bytecodes body = self.body.gencode(env, newopt(opt, 0, cp=l0, bp=l1)).bytecodes codes = init codes.append(m.Inst(opc.LABEL, l0)) codes.extend(cond) codes.append(m.Inst(opc.JIF0, l1)) codes.extend(body) codes.extend(loop) codes.append(m.Inst(opc.JUMP, l0)) codes.append(m.Inst(opc.LABEL, l1)) return m.Insts(m.Type(), codes)
class Symbol(AST): def __init__(self, tok, symbolname): self.tok = tok self.symbolname = symbolname def gencode(self, env, opt): try: var = env.variableLookup(self.symbolname) except m.SymbolNotFoundException as e: # 変数が見つからなかったら、Enumとして解決を試みる try: value = env.enumLookup(self.symbolname) except m.SymbolNotFoundException as e: g.r.addReport(m.Report('error', self.tok, f'{e} not found')) return m.Insts() if (result := self.assertOnlyRValue(env, opt)) is not None: return result if (result := self.assertOnlyPop1(env, opt)) is not None: return result return m.Insts(m.Type('int'), [m.Inst(opc.PUSH, value)])
if (result := self.assertOnlyRValue(env, opt)) is not None: return result if (result := self.assertOnlyPop1(env, opt)) is not None: return result left = self.left.gencode(env, newopt(opt, 1)) right = self.right.gencode(env, newopt(opt, 1)) code = right.bytecodes code.extend(left.bytecodes) if self.isCompOP: # 比較演算子ならポインタ同士の演算が可能 if left.typ.isPointer() or right.typ.isPointer(): code.append(m.Inst(self.opI, self.nullarg)) return m.Insts(m.Type('int'), code) else: # そうでないならスカラーしか演算できない if not (left.typ.isScalar() and right.typ.isScalar()): g.r.addReport( m.Report( 'error', self.tok, f"invalid operands to binary expression('{left.typ}' and '{right.typ}')" )) return m.Insts() if (not left.typ.isBasetype()): left.typ = env.getType(left.typ.basetype) if (not right.typ.isBasetype()): right.typ = env.getType(right.typ.basetype)
def gencode(self, env, opt): env.addEnum(self.symbolname, self.typ) return m.Insts(m.Type(), [])
def assertOnlyPop1(self, env, opt): if (opt.popc != 1): g.r.addReport( m.Report('warning', self.tok, 'expression result unused')) return m.Insts()
def gencode(self, env, opt): label = env.currentFuncName + self.name return m.Insts(m.Type(), [m.Inst(opc.JUMP, label)])