⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 attr.java

📁 java编译器gjc源码 java编译环境
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
        chk.validate(tree.vartype);
        VarSymbol v = tree.sym;
        if (tree.init != null) {
            v.pos = Position.MAXPOS;
            if ((v.flags_field & FINAL) != 0) {
                evalInit(v);
            } else {
                Type itype = attribExpr(tree.init, enter.initEnv((VarDef) tree, env),
                        v.type);
            }
            v.pos = tree.pos;
        }
        result = tree.type = v.type;
    }

    public void visitSkip(Skip tree) {
        result = null;
    }

    public void visitBlock(Block tree) {
        if (((AttrContext) env.info).scope.owner.kind == TYP) {
            Env localEnv = env.dup(tree,
                    ((AttrContext) env.info).dup(
                    ((AttrContext) env.info).scope.dupUnshared()));
            ((AttrContext) localEnv.info).scope.owner =
                    new MethodSymbol(tree.flags | BLOCK, names.empty, null,
                    ((AttrContext) env.info).scope.owner);
            if ((tree.flags & STATIC) != 0)
                ((AttrContext) localEnv.info).staticLevel++;
            attribStats(tree.stats, localEnv);
        } else {
            Env localEnv = env.dup(tree,
                    ((AttrContext) env.info).dup(
                    ((AttrContext) env.info).scope.dup()));
            attribStats(tree.stats, localEnv);
            ((AttrContext) localEnv.info).scope.leave();
        }
        result = null;
    }

    public void visitDoLoop(DoLoop tree) {
        attribStat(tree.body, env.dup(tree));
        attribExpr(tree.cond, env, syms.booleanType);
        result = null;
    }

    public void visitWhileLoop(WhileLoop tree) {
        attribExpr(tree.cond, env, syms.booleanType);
        attribStat(tree.body, env.dup(tree));
        result = null;
    }

    public void visitForLoop(ForLoop tree) {
        Env loopEnv = env.dup(env.tree,
                ((AttrContext) env.info).dup(((AttrContext) env.info).scope.dup()));
        attribStats(tree.init, loopEnv);
        if (tree.cond != null)
            attribExpr(tree.cond, loopEnv, syms.booleanType);
        loopEnv.tree = tree;
        attribStats(tree.step, loopEnv);
        attribStat(tree.body, loopEnv);
        ((AttrContext) loopEnv.info).scope.leave();
        result = null;
    }

    public void visitLabelled(Labelled tree) {
        Env env1 = env;
        while (env1 != null && env1.tree.tag != Tree.CLASSDEF) {
            if (env1.tree.tag == Tree.LABELLED &&
                    ((Labelled) env1.tree).label == tree.label) {
                log.error(tree.pos, "label.already.in.use", tree.label.toJava());
                break;
            }
            env1 = env1.next;
        }
        attribStat(tree.body, env.dup(tree));
        result = null;
    }

    public void visitSwitch(Switch tree) {
        Type seltype = attribExpr(tree.selector, env, syms.intType);
        Env switchEnv = env.dup(tree,
                ((AttrContext) env.info).dup(((AttrContext) env.info).scope.dup()));
        Set labels = Set.make();
        boolean hasDefault = false;
        for (List l = tree.cases; l.nonEmpty(); l = l.tail) {
            Case c = (Tree.Case) l.head;
            Env caseEnv = switchEnv.dup(c,
                    ((AttrContext) env.info).dup(
                    ((AttrContext) switchEnv.info).scope.dup()));
            if (c.pat != null) {
                Type pattype = attribExpr(c.pat, switchEnv, syms.intType);
                if (pattype.tag != ERROR) {
                    if (pattype.constValue == null) {
                        log.error(c.pat.pos, "const.expr.req");
                    } else if (labels.contains(pattype.constValue)) {
                        log.error(c.pos, "duplicate.case.label");
                    } else {
                        chk.checkType(c.pat.pos, pattype, seltype);
                        labels.put(pattype.constValue);
                    }
                }
            } else if (hasDefault) {
                log.error(c.pos, "duplicate.default.label");
            } else {
                hasDefault = true;
            }
            attribStats(c.stats, caseEnv);
            ((AttrContext) caseEnv.info).scope.leave();
            addVars(c.stats, ((AttrContext) switchEnv.info).scope);
        }
        ((AttrContext) switchEnv.info).scope.leave();
        result = null;
    }

    /**
      * Add any variables defined in stats to the switch scope.
      */
    private static void addVars(List stats, Scope switchScope) {
        for (; stats.nonEmpty(); stats = stats.tail) {
            Tree stat = (Tree) stats.head;
            if (stat.tag == Tree.VARDEF)
                switchScope.enter(((VarDef) stat).sym);
        }
    }

    public void visitSynchronized(Synchronized tree) {
        chk.checkRefType(tree.pos, attribExpr(tree.lock, env, syms.objectType));
        attribStat(tree.body, env);
        result = null;
    }

    public void visitTry(Try tree) {
        attribStat(tree.body, env.dup(tree, ((AttrContext) env.info).dup()));
        for (List l = tree.catchers; l.nonEmpty(); l = l.tail) {
            Catch c = (Tree.Catch) l.head;
            Env catchEnv = env.dup(c,
                    ((AttrContext) env.info).dup(
                    ((AttrContext) env.info).scope.dup()));
            Type ctype = attribStat(c.param, catchEnv);
            chk.checkType(c.param.vartype.pos, ctype, syms.throwableType);
            attribStat(c.body, catchEnv);
            ((AttrContext) catchEnv.info).scope.leave();
        }
        if (tree.finalizer != null)
            attribStat(tree.finalizer, env);
        result = null;
    }

    public void visitConditional(Conditional tree) {
        attribExpr(tree.cond, env, syms.booleanType);
        attribExpr(tree.truepart, env, pt);
        attribExpr(tree.falsepart, env, pt);
        result = check(tree,
                condType(tree.pos, tree.cond.type, tree.truepart.type,
                tree.falsepart.type), VAL, pkind, pt);
    }

    /**
      * Compute the type of a conditional expression, after
      *  checking that it exists. See Spec 15.25.
      *
      *  @param pos      The source position to be used for error diagnostics.
      *  @param condtype The type of the expression's condition.
      *  @param thentype The type of the expression's then-part.
      *  @param elsetype The type of the expression's else-part.
      */
    private Type condType(int pos, Type condtype, Type thentype, Type elsetype) {
        Type ctype = condType1(pos, condtype, thentype, elsetype);
        return ((condtype.constValue != null) && (thentype.constValue != null) &&
                (elsetype.constValue != null)) ? cfolder.coerce(
                (((Number) condtype.constValue).intValue() != 0) ? thentype :
                elsetype, ctype):
               ctype;
    }

    /**
      * Compute the type of a conditional expression, after
      *  checking that it exists.  Does not take into
      *  account the special case where condition and both arms are constants.
      *
      *  @param pos      The source position to be used for error diagnostics.
      *  @param condtype The type of the expression's condition.
      *  @param thentype The type of the expression's then-part.
      *  @param elsetype The type of the expression's else-part.
      */
    private Type condType1(int pos, Type condtype, Type thentype, Type elsetype) {
        if (thentype.tag < INT && elsetype.tag == INT &&
                elsetype.isAssignable(thentype))
            return thentype.baseType();
        else if (elsetype.tag < INT && thentype.tag == INT &&
                thentype.isAssignable(elsetype))
            return elsetype.baseType();
        else if (thentype.tag <= DOUBLE && elsetype.tag <= DOUBLE)
            for (int i = BYTE; i <= DOUBLE; i++) {
                Type candidate = syms.typeOfTag[i];
                if (thentype.isSubType(candidate) && elsetype.isSubType(candidate))
                    return candidate;
            }
        if (thentype.tsym == syms.stringType.tsym &&
                elsetype.tsym == syms.stringType.tsym)
            return syms.stringType;
        else if (thentype.isSubType(elsetype))
            return elsetype.baseType();
        else if (elsetype.isSubType(thentype))
            return thentype.baseType();
        else {
            log.error(pos, "neither.conditional.subtype", thentype.toJava(),
                    elsetype.toJava());
            return thentype.baseType();
        }
    }

    public void visitIf(If tree) {
        attribExpr(tree.cond, env, syms.booleanType);
        attribExpr(tree.thenpart, env, pt);
        if (tree.elsepart != null)
            attribExpr(tree.elsepart, env, pt);
        result = null;
    }

    public void visitExec(Exec tree) {
        attribExpr(tree.expr, env);
        result = null;
    }

    public void visitBreak(Break tree) {
        tree.target = findJumpTarget(tree.pos, tree.tag, tree.label, env);
        result = null;
    }

    public void visitContinue(Continue tree) {
        tree.target = findJumpTarget(tree.pos, tree.tag, tree.label, env);
        result = null;
    }

    /**
      * Return the target of a break or continue statement, if it exists,
      *  report an error if not.
      *  Note: The target of a labelled break or continue is the
      *  (non-labelled) statement tree referred to by the label,
      *  not the tree representing the labelled statement itself.
      *
      *  @param pos     The position to be used for error diagnostics
      *  @param tag     The tag of the jump statement. This is either
      *                 Tree.BREAK or Tree.CONTINUE.
      *  @param label   The label of the jump statement, or null if no
      *                 label is given.
      *  @param env     The environment current at the jump statement.
      */
    private Tree findJumpTarget(int pos, int tag, Name label, Env env) {
        Env env1 = env;
        LOOP:
        while (env1 != null) {
            switch (env1.tree.tag) {
            case Tree.LABELLED:
                Labelled labelled = (Labelled) env1.tree;
                if (label == labelled.label) {
                    if (tag == Tree.CONTINUE) {
                        if (labelled.body.tag != Tree.DOLOOP &&
                                labelled.body.tag != Tree.WHILELOOP &&
                                labelled.body.tag != Tree.FORLOOP)
                            log.error(pos, "not.loop.label", label.toJava());
                        return TreeInfo.referencedStatement(labelled);
                    } else {
                        return labelled;
                    }
                }
                break;

            case Tree.DOLOOP:

            case Tree.WHILELOOP:

            case Tree.FORLOOP:
                if (label == null)
                    return env1.tree;
                break;

            case Tree.SWITCH:
                if (label == null && tag == Tree.BREAK)
                    return env1.tree;
                break;

            case Tree.METHODDEF:

            case Tree.CLASSDEF:
                break LOOP;

            default:

            }
            env1 = env1.next;
        }
        if (label != null)
            log.error(pos, "undef.label", label.toJava());
        else if (tag == Tree.CONTINUE)
            log.error(pos, "cont.outside.loop");
        else
            log.error(pos, "break.outside.switch.loop");
        return null;
    }

    public void visitReturn(Return tree) {
        if (env.enclMethod == null || env.enclMethod.sym.owner != env.enclClass.sym) {
            log.error(tree.pos, "ret.outside.meth");
        } else {
            Symbol m = env.enclMethod.sym;
            if (m.type.restype().tag == VOID) {
                if (tree.expr != null)
                    log.error(tree.expr.pos, "cant.ret.val.from.meth.decl.void");
            } else if (tree.expr == null) {
                log.error(tree.pos, "missing.ret.val");
            } else {
                attribExpr(tree.expr, env, m.type.restype());
            }
        }
        result = null;
    }

    public void visitThrow(Throw tree) {
        Type t = attribExpr(tree.expr, env, syms.throwableType);
        result = null;
    }

    public void visitAssert(Assert tree) {
        Type ct = attribExpr(tree.cond, env, syms.booleanType);
        if (tree.detail != null) {
            chk.checkNonVoid(tree.detail.pos, attribExpr(tree.detail, env));
        }
        result = null;
    }

    /**
      * Visitor method for method invocations.
      *  NOTE: The method part of an application will have in its type field
      *        the return type of the method, not the method's type itself!
      */
    public void visitApply(Apply tree) {
        Env localEnv = env;
        List argtypes;
        Name methName = TreeInfo.name(tree.meth);
        boolean isConstructorCall =
                methName == names._this || methName == names._super;
        if (isConstructorCall) {
            if (checkFirstConstructorStat(tree, env)) {
                localEnv = env.dup(env.tree, ((AttrContext) env.info).dup());
                ((AttrContext) localEnv.info).isSelfCall = true;
                argtypes = attribArgs(tree.args, localEnv);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -