Example #1
0
 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)])
Example #2
0
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)
Example #3
0
 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)
Example #4
0
    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)
Example #5
0
 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)])
Example #6
0
    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)
Example #7
0
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()
Example #8
0
    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()
Example #9
0
    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)
Example #10
0
    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)
Example #11
0
    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)
Example #12
0
    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)
Example #13
0
    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)
Example #14
0
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)])
Example #15
0
 def gencode(self, env, opt):
     for elem in self.body:
         dumps = elem.gencode(env, newopt(opt, 0))
     env.addStatic(m.Symbol("__MAGIC_RETADDR__", m.Type(), 0))
     env.addStatic(m.Symbol("__MAGIC_RETFP__", m.Type(), 0))
     return env
Example #16
0
    def gencode(self, env, opt):

        env.addEnum(self.symbolname, self.typ)

        return m.Insts(m.Type(), [])
Example #17
0
 def gencode(self, env, opt):
     label = env.currentFuncName + self.name
     return m.Insts(m.Type(), [m.Inst(opc.JUMP, label)])
Example #18
0
def projectAST(ast, s=0):

    if (ast is None):
        return None

    elif isinstance(ast, c_ast.ArrayDecl):
        return projectAST(ast.type,
                          s).setLength(projectAST(ast.dim,
                                                  s))  #MEMO dim_quals unused

    elif isinstance(ast, c_ast.ArrayRef):  # [name*, subscript*]
        return node.Indirect(
            a2t(ast),
            node.Add(a2t(ast), projectAST(ast.name, s),
                     projectAST(ast.subscript, s)))

    elif isinstance(ast, c_ast.Assignment):  # [op, lvalue*, rvalue*]
        if ast.op == '=':
            return node.Assign(a2t(ast), projectAST(ast.lvalue, s),
                               projectAST(ast.rvalue, s))
        elif ast.op == '+=':
            return node.Assign(
                a2t(ast), projectAST(ast.lvalue, s),
                node.Add(a2t(ast), projectAST(ast.lvalue, s),
                         projectAST(ast.rvalue, s)))
        elif ast.op == '-=':
            return node.Assign(
                a2t(ast), projectAST(ast.lvalue, s),
                node.Sub(a2t(ast), projectAST(ast.lvalue, s),
                         projectAST(ast.rvalue, s)))
        elif ast.op == '*=':
            return node.Assign(
                a2t(ast), projectAST(ast.lvalue, s),
                node.Mul(a2t(ast), projectAST(ast.lvalue, s),
                         projectAST(ast.rvalue, s)))
        elif ast.op == '/=':
            return node.Assign(
                a2t(ast), projectAST(ast.lvalue, s),
                node.Div(a2t(ast), projectAST(ast.lvalue, s),
                         projectAST(ast.rvalue, s)))
        elif ast.op == '%=':
            return node.Assign(
                a2t(ast), projectAST(ast.lvalue, s),
                node.Mod(a2t(ast), projectAST(ast.lvalue, s),
                         projectAST(ast.rvalue, s)))
        elif ast.op == '<<=':
            return node.Assign(
                a2t(ast), projectAST(ast.lvalue, s),
                node.LShift(a2t(ast), projectAST(ast.lvalue, s),
                            projectAST(ast.rvalue, s)))
        elif ast.op == '>>=':
            return node.Assign(
                a2t(ast), projectAST(ast.lvalue, s),
                node.RShift(a2t(ast), projectAST(ast.lvalue, s),
                            projectAST(ast.rvalue, s)))
        elif ast.op == '&=':
            return node.Assign(
                a2t(ast), projectAST(ast.lvalue, s),
                node.And(a2t(ast), projectAST(ast.lvalue, s),
                         projectAST(ast.rvalue, s)))
        elif ast.op == '|=':
            return node.Assign(
                a2t(ast), projectAST(ast.lvalue, s),
                node.Or(a2t(ast), projectAST(ast.lvalue, s),
                        projectAST(ast.rvalue, s)))
        elif ast.op == '^=':
            return node.Assign(
                a2t(ast), projectAST(ast.lvalue, s),
                node.Xor(a2t(ast), projectAST(ast.lvalue, s),
                         projectAST(ast.rvalue, s)))
        else:
            g.r.addReport(
                m.Report('fatal', a2t(ast),
                         f"unsupported assignment op '{ast.op}'"))
            return

    elif isinstance(ast, c_ast.BinaryOp):  # [op, left* right*]
        if ast.op == '+':
            return node.Add(a2t(ast), projectAST(ast.left, s),
                            projectAST(ast.right, s))
        elif ast.op == '-':
            return node.Sub(a2t(ast), projectAST(ast.left, s),
                            projectAST(ast.right, s))
        elif ast.op == '*':
            return node.Mul(a2t(ast), projectAST(ast.left, s),
                            projectAST(ast.right, s))
        elif ast.op == '/':
            return node.Div(a2t(ast), projectAST(ast.left, s),
                            projectAST(ast.right, s))
        elif ast.op == '%':
            return node.Mod(a2t(ast), projectAST(ast.left, s),
                            projectAST(ast.right, s))
        elif ast.op == '<<':
            return node.LShift(a2t(ast), projectAST(ast.left, s),
                               projectAST(ast.right, s))
        elif ast.op == '>>':
            return node.RShift(a2t(ast), projectAST(ast.left, s),
                               projectAST(ast.right, s))
        elif ast.op == '&':
            return node.And(a2t(ast), projectAST(ast.left, s),
                            projectAST(ast.right, s))
        elif ast.op == '|':
            return node.Or(a2t(ast), projectAST(ast.left, s),
                           projectAST(ast.right, s))
        elif ast.op == '^':
            return node.Xor(a2t(ast), projectAST(ast.left, s),
                            projectAST(ast.right, s))
        elif ast.op == '<':
            return node.Lt(a2t(ast), projectAST(ast.left, s),
                           projectAST(ast.right, s))
        elif ast.op == '<=':
            return node.Lte(a2t(ast), projectAST(ast.left, s),
                            projectAST(ast.right, s))
        elif ast.op == '>':
            return node.Gt(a2t(ast), projectAST(ast.left, s),
                           projectAST(ast.right, s))
        elif ast.op == '>=':
            return node.Gte(a2t(ast), projectAST(ast.left, s),
                            projectAST(ast.right, s))
        elif ast.op == '==':
            return node.Eq(a2t(ast), projectAST(ast.left, s),
                           projectAST(ast.right, s))
        elif ast.op == '!=':
            return node.Neq(a2t(ast), projectAST(ast.left, s),
                            projectAST(ast.right, s))
        elif ast.op == '&&':
            return node.And(a2t(ast), projectAST(ast.left, s),
                            projectAST(ast.right, s))
        elif ast.op == '||':
            return node.Or(a2t(ast), projectAST(ast.left, s),
                           projectAST(ast.right, s))
        else:
            g.r.addReport(
                m.Report('fatal', a2t(ast),
                         f"unsupported binary op '{ast.op}'"))
            return

    elif isinstance(ast, c_ast.Break):  # []
        return node.Break(a2t(ast))

    elif isinstance(ast, c_ast.Case):  # [expr*, stmts**]
        return [
            projectAST(ast.expr, s), [projectAST(e, s + 1) for e in ast.stmts]
        ]

    elif isinstance(ast, c_ast.Cast):  # [to_type*, expr*]
        return node.Cast(a2t(ast), projectAST(ast.to_type, s),
                         projectAST(ast.expr, s))

    elif isinstance(ast, c_ast.Compound):  # [block_items**]
        if ast.block_items is None:
            return node.Block(a2t(ast), [])
        else:
            return node.Block(a2t(ast),
                              [projectAST(e, s + 1) for e in ast.block_items])

    elif isinstance(ast, c_ast.CompoundLiteral):  #TODO [type*, init*]
        pass
    elif isinstance(ast, c_ast.Constant):  # [type, value]
        if (ast.type == 'int'):
            return node.NumberI(a2t(ast), ast.value)
        elif (ast.type == 'float'):
            return node.NumberF(a2t(ast), ast.value)
        elif (ast.type == 'char'):
            ast.value = escapeString(ast.value)
            return node.NumberI(
                a2t(ast),
                int.from_bytes(ast.value[1].encode('utf-32be'),
                               byteorder='big'))
        elif (ast.type == 'string'):
            ast.value = escapeString(ast.value)
            return node.String(a2t(ast), ast.value[1:-1])
        g.r.addReport(
            m.Report(
                'fatal', a2t(ast),
                f"unsupported constant type '{ast.type}' for value '{ast.value}'"
            ))

    elif isinstance(ast, c_ast.Continue):  # []
        return node.Continue(a2t(ast))

    elif isinstance(
            ast, c_ast.Decl
    ):  # [name, quals, storage, funcspec, type*, init*, bitsize*]

        if type(ast.type) in (c_ast.TypeDecl, c_ast.PtrDecl, c_ast.ArrayDecl):
            init = projectAST(ast.init, s)
            if isinstance(init, node.String):  # 初期化がstirngだった場合、リストに展開
                string = init.eval()
                li = list(
                    map(
                        lambda a: node.NumberI(
                            a2t(ast),
                            int.from_bytes(a.encode('utf-32be'),
                                           byteorder='big')), string))
                li.append(node.NumberI(a2t(ast), 0))
                init = li

            if (s == 0):
                return node.GlobalVar(a2t(ast), ast.name,
                                      projectAST(ast.type, s), init)
            else:
                return node.LocalVar(a2t(ast), ast.name,
                                     projectAST(ast.type, s), init)

        elif isinstance(ast.type, c_ast.FuncDecl):  # 関数定義
            decl = projectAST(ast.type, s)
            return node.Func(a2t(ast), decl['type'].name, decl['type'],
                             decl['args'], None)

        else:
            return projectAST(ast.type, s)

    elif isinstance(ast, c_ast.DeclList):  #TODO [decls**]
        pass
    elif isinstance(ast, c_ast.Default):  # [stmts**]
        return ['default', [projectAST(e, s + 1) for e in ast.stmts]]

    elif isinstance(ast, c_ast.DoWhile):  # [cond*, stmt*]
        return node.DoWhile(a2t(ast), projectAST(ast.stmt, s),
                            projectAST(ast.cond, s))

    elif isinstance(ast, c_ast.EllipsisParam):  #TODO []
        pass
    elif isinstance(ast, c_ast.EmptyStatement):  #TODO []
        pass
    elif isinstance(ast, c_ast.Enum):  # [name, values*]
        if ast.values is None:  # is type define
            return m.Type(ast.name).setHint('enum')
        else:  # is enum define
            return node.Enum(a2t(ast), ast.name, projectAST(ast.values, s))

    elif isinstance(ast, c_ast.Enumerator):  # [name, value*]
        if ast.value is None:
            return (ast.name, None)
        else:
            if isinstance(ast.value, c_ast.Constant):
                return (ast.name, int(ast.value.value))
            elif isinstance(ast.value, c_ast.UnaryOp):
                return (ast.name, -int(ast.value.expr.value))
            else:
                g.r.addReport(
                    m.Report('fatal', a2t(ast), f"enum must be \'int\'"))

    elif isinstance(ast, c_ast.EnumeratorList):  # [enumerators**]
        itr = 0
        typ = m.Type('enum')
        for elem in ast.enumerators:
            tmp = projectAST(elem, s)
            if tmp[1] is None:
                typ.addMember((tmp[0], itr))
                itr += 1
            else:
                typ.addMember(tmp)
                itr = tmp[1] + 1

        return typ

    elif isinstance(ast, c_ast.ExprList):  #[exprs**]
        return [projectAST(e, s) for e in ast.exprs]

    elif isinstance(ast, c_ast.FileAST):
        return node.Program(a2t(ast), [projectAST(e, s) for e in ast.ext])

    elif isinstance(ast, c_ast.For):  # [init*, cond*, next*, stmt*]
        return node.For(a2t(ast), projectAST(ast.init, s),
                        projectAST(ast.cond, s), projectAST(ast.next, s),
                        projectAST(ast.stmt, s))

    elif isinstance(ast, c_ast.FuncCall):  # [name*, args*]
        return node.Funccall(a2t(ast), ast.name.name, projectAST(ast.args, s))

    elif isinstance(ast, c_ast.FuncDecl):  # [args*, type*]
        return {
            "args": projectAST(ast.args, s) if ast.args is not None else [],
            "type": projectAST(ast.type, s)
        }

    elif isinstance(ast, c_ast.FuncDef):  # [args*, type*]
        return projectAST(ast.decl, s).setBody(projectAST(ast.body, s))

    elif isinstance(ast, c_ast.Goto):  # [name]
        return node.Goto(a2t(ast), ast.name)

    elif isinstance(ast, c_ast.ID):  # [name]
        return node.Symbol(a2t(ast), ast.name)

    elif isinstance(ast, c_ast.IdentifierType):
        if len(ast.names) == 1:
            return m.Type(ast.names[0])
        g.r.addReport(
            m.Report('fatal', a2t(ast),
                     f"program error while processing IdentifierType"))

    elif isinstance(ast, c_ast.If):  # [cond*, iftrue*, iffalse*]
        if ast.iffalse is None:
            return node.If(a2t(ast), projectAST(ast.cond, s),
                           projectAST(ast.iftrue, s))
        else:
            return node.Ifelse(a2t(ast), projectAST(ast.cond, s),
                               projectAST(ast.iftrue, s),
                               projectAST(ast.iffalse, s))

    elif isinstance(ast, c_ast.InitList):  # [exprs**]
        return [projectAST(e, s) for e in ast.exprs]  #XXX

    elif isinstance(ast, c_ast.Label):  # [name, stmt*]
        return node.Label(a2t(ast), ast.name, projectAST(ast.stmt))

    elif isinstance(ast, c_ast.NamedInitializer):  #TODO [name**, expr*]
        pass
    elif isinstance(ast, c_ast.ParamList):  # [params**]
        tmp = []
        for elem in ast.params:
            typ = projectAST(elem.type, s)
            tmp.append(m.Symbol(typ.name, typ))
        return tmp

    elif isinstance(ast, c_ast.PtrDecl):
        return projectAST(ast.type, s).addQuals(ast.quals).addRefcount(1)

    elif isinstance(ast, c_ast.Raw):  # [type*, opc, arg, exprs**]
        return node.Raw(a2t(ast), projectAST(ast.type, s), ast.opc[1:-1],
                        int(ast.arg.value),
                        [projectAST(e, s) for e in ast.exprs])

    elif isinstance(ast, c_ast.Return):  # [expr*]
        return node.Return(a2t(ast), projectAST(ast.expr, s))

    elif isinstance(ast, c_ast.Struct):  # [name, decls**]
        if ast.decls is None:
            return m.Type(ast.name).setHint('struct')
        else:
            typ = m.Type('struct')
            for elem in ast.decls:
                typ.addMember((elem.name, projectAST(elem.type)))
            return node.Struct(a2t(ast), ast.name, typ)

    elif isinstance(ast, c_ast.StructRef):  # [name*, type, filed*] type unused
        if ast.type == '.':
            return node.Indirect(
                a2t(ast),
                node.FieldAccess(
                    a2t(ast), node.Address(a2t(ast), projectAST(ast.name, s)),
                    ast.field.name))
        elif ast.type == '->':
            return node.Indirect(
                a2t(ast),
                node.FieldAccess(a2t(ast), projectAST(ast.name, s),
                                 ast.field.name))
        else:
            g.r.addReport(
                m.Report('fatal', a2t(ast),
                         f"unsupported field access type '{ast.type}'"))

    elif isinstance(ast, c_ast.Switch):  # [cond*, stmt*]
        return node.Switch(a2t(ast), projectAST(
            ast.cond, s), [projectAST(e, s + 1) for e in ast.stmt.block_items])

    elif isinstance(ast, c_ast.TernaryOp):  # [cond*, ifture*, iffalse*]
        return node.Ternary(a2t(ast), projectAST(ast.cond, s),
                            projectAST(ast.iftrue, s),
                            projectAST(ast.iffalse, s))

    elif isinstance(ast, c_ast.TypeDecl):
        typ = projectAST(ast.type, s)
        if isinstance(typ, m.Type):
            return typ.addQuals(ast.quals).setName(ast.declname)
        elif type(typ) in (node.Struct, node.Enum):
            return typ.typ
        else:
            return typ

    elif isinstance(ast, c_ast.Typedef):  # [name, quals, storage, type*]
        typ = projectAST(ast.type, s)
        if isinstance(typ, node.Struct) or isinstance(typ, node.Enum):
            return node.Typedef(a2t(ast), ast.name,
                                typ.typ.addQuals(ast.quals))
        else:
            return node.Typedef(a2t(ast), ast.name, typ.addQuals(ast.quals))

    elif isinstance(ast, c_ast.Typename):  # [name, quals, type*]
        return projectAST(ast.type, s).addQuals(ast.quals)

    elif isinstance(ast, c_ast.UnaryOp):  # [op, expr*]
        if ast.op == '!':
            return node.Inv(a2t(ast), projectAST(ast.expr, s))
        elif ast.op == '+':
            return projectAST(ast.expr, s)
        elif ast.op == '-':
            return node.Minus(a2t(ast), projectAST(ast.expr, s))
        elif ast.op == '++':
            return node.Pre_inc(a2t(ast), projectAST(ast.expr, s))
        elif ast.op == '--':
            return node.Pre_dec(a2t(ast), projectAST(ast.expr, s))
        elif ast.op == 'p++':
            return node.Post_inc(a2t(ast), projectAST(ast.expr, s))
        elif ast.op == 'p--':
            return node.Post_dec(a2t(ast), projectAST(ast.expr, s))
        elif ast.op == '*':
            return node.Indirect(a2t(ast), projectAST(ast.expr, s))
        elif ast.op == '&':
            return node.Address(a2t(ast), projectAST(ast.expr, s))
        elif ast.op == 'sizeof':
            return node.Sizeof(a2t(ast), projectAST(ast.expr, s))
        else:
            g.r.addReport(
                m.Report('fatal', a2t(ast),
                         f"unsupported unary op '{ast.op}'"))
            return

    elif isinstance(ast, c_ast.Union):  #TODO [name, decls**]
        pass
    elif isinstance(ast, c_ast.While):  # [cond*, stmt*]
        return node.While(a2t(ast), projectAST(ast.cond, s),
                          projectAST(ast.stmt, s))

    elif isinstance(ast, c_ast.Pragma):  #TODO [string]
        pass
    else:
        g.r.addReport(
            m.Report('fatal', a2t(ast), f"{type(ast)} is not listed!"))
        return

    g.r.addReport(
        m.Report('fatal', a2t(ast), f"{type(ast)} is not yet implemented!"))
Example #19
0
        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)