package org.yinwang.pysonar.ast; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.yinwang.pysonar.Binding; import org.yinwang.pysonar.Indexer; import org.yinwang.pysonar.Scope; import org.yinwang.pysonar.types.Type; import org.yinwang.pysonar.types.UnionType; import java.util.ArrayList; import java.util.List; public class Block extends Node { @Nullable public List<Node> seq; public Block(@Nullable List<Node> seq, int start, int end) { super(start, end); if (seq == null) { seq = new ArrayList<Node>(); } this.seq = seq; addChildren(seq); } /** * First mark all the global names then resolve each statement in the sequence. * Notice that we don't distinguish class and function definitions here. * Their statements will return None type and bind the names themselves in the scope. * If the sequence contains escaping control-flow, None type will appear in the return type. * This can be used to generate warnings such as "This function may not return a value." */ @NotNull @Override public Type resolve(@NotNull Scope scope, int tag) { // find global names and mark them for (Node n : seq) { if (n.isGlobal()) { for (Name name : n.asGlobal().getNames()) { scope.addGlobalName(name.getId()); Binding nb = scope.lookup(name.getId()); if (nb != null) { Indexer.idx.putRef(name, nb); } } } } boolean returned = false; Type retType = Indexer.idx.builtins.unknown; for (Node n : seq) { Type t = resolveExpr(n, scope, tag); if (!returned) { retType = UnionType.union(retType, t); if (!UnionType.contains(t, Indexer.idx.builtins.Cont)) { returned = true; retType = UnionType.remove(retType, Indexer.idx.builtins.Cont); } } else if (scope.getScopeType() != Scope.ScopeType.GLOBAL && scope.getScopeType() != Scope.ScopeType.MODULE) { Indexer.idx.putProblem(n, "unreachable code"); } } return retType; } public boolean isEmpty() { return seq.isEmpty(); } @NotNull @Override public String toString() { return "<Block:" + seq + ">"; } @Override public void visit(@NotNull NodeVisitor v) { if (v.visit(this)) { visitNodeList(seq, v); } } }