提交 eb7db21c 编写于 作者: A Andrey Breslav

Some CF generated for closures

上级 01105c8c
......@@ -94,6 +94,8 @@ public interface JetNodeTypes {
JetNodeType OPERATION_REFERENCE = new JetNodeType("OPERATION_REFERENCE", JetSimpleNameExpression.class);
JetNodeType LABEL_REFERENCE = new JetNodeType("LABEL_REFERENCE", JetSimpleNameExpression.class);
JetNodeType LABEL_QUALIFIER = new JetNodeType("LABEL_QUALIFIER", JetContainerNode.class);
JetNodeType THIS_EXPRESSION = new JetNodeType("THIS_EXPRESSION", JetThisExpression.class);
JetNodeType BINARY_EXPRESSION = new JetNodeType("BINARY_EXPRESSION", JetBinaryExpression.class);
JetNodeType BINARY_WITH_TYPE = new JetNodeType("BINARY_WITH_TYPE", JetBinaryExpressionWithTypeRHS.class);
......
......@@ -196,7 +196,7 @@ public class ExpressionCodegen extends JetVisitor {
public void visitConstantExpression(JetConstantExpression expression) {
myStack.push(StackValue.constant(expression.getValue()));
/*
Object value = expression.getValue();
Object value = element.getValue();
v.aconst(value);
if (value instanceof Integer) {
......
......@@ -40,8 +40,8 @@ public interface JetControlFlowBuilder {
void exitTryFinally();
// Subroutines
void enterSubroutine(@NotNull JetElement subroutine);
void exitSubroutine(@NotNull JetElement subroutine);
void enterSubroutine(@NotNull JetElement subroutine, boolean isFunctionLiteral);
void exitSubroutine(@NotNull JetElement subroutine, boolean functionLiteral);
@Nullable
JetElement getCurrentSubroutine();
......
package org.jetbrains.jet.lang.cfg;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetBlockExpression;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
/**
* @author abreslav
*/
public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
protected JetControlFlowBuilder builder;
public JetControlFlowBuilderAdapter(JetControlFlowBuilder builder) {
this.builder = builder;
}
@Override
public void readNode(@NotNull JetExpression expression) {
builder.readNode(expression);
}
@Override
@NotNull
public Label createUnboundLabel() {
return builder.createUnboundLabel();
}
@Override
public void bindLabel(@NotNull Label label) {
builder.bindLabel(label);
}
@Override
public void jump(@NotNull Label label) {
builder.jump(label);
}
@Override
public void jumpOnFalse(@NotNull Label label) {
builder.jumpOnFalse(label);
}
@Override
public void jumpOnTrue(@NotNull Label label) {
builder.jumpOnTrue(label);
}
@Override
public void nondeterministicJump(Label label) {
builder.nondeterministicJump(label);
}
@Override
public Label getEntryPoint(@NotNull JetElement labelElement) {
return builder.getEntryPoint(labelElement);
}
@Override
public Label getExitPoint(@NotNull JetElement labelElement) {
return builder.getExitPoint(labelElement);
}
@Override
public Label enterLoop(@NotNull JetExpression expression, Label loopExitPoint) {
return builder.enterLoop(expression, loopExitPoint);
}
@Override
public void exitLoop(@NotNull JetExpression expression) {
builder.exitLoop(expression);
}
@Override
@Nullable
public JetElement getCurrentLoop() {
return builder.getCurrentLoop();
}
@Override
public void enterTryFinally(@NotNull JetBlockExpression expression) {
builder.enterTryFinally(expression);
}
@Override
public void exitTryFinally() {
builder.exitTryFinally();
}
@Override
public void enterSubroutine(@NotNull JetElement subroutine, boolean isFunctionLiteral) {
builder.enterSubroutine(subroutine, isFunctionLiteral);
}
@Override
public void exitSubroutine(@NotNull JetElement subroutine, boolean functionLiteral) {
builder.exitSubroutine(subroutine, functionLiteral);
}
@Override
@Nullable
public JetElement getCurrentSubroutine() {
return builder.getCurrentSubroutine();
}
@Override
public void returnValue(@NotNull JetElement subroutine) {
builder.returnValue(subroutine);
}
@Override
public void returnNoValue(@NotNull JetElement subroutine) {
builder.returnNoValue(subroutine);
}
@Override
public void unsupported(JetElement element) {
builder.unsupported(element);
}
}
......@@ -155,8 +155,8 @@ package org.jetbrains.jet.lang.cfg;
// }
//
// @Override
// public void readNode(JetExpression expression) {
// createNode(expression);
// public void readNode(JetExpression element) {
// createNode(element);
// }
//
// @Override
......@@ -236,7 +236,7 @@ package org.jetbrains.jet.lang.cfg;
// }
//
// @Override
// public void enterTryFinally(JetBlockExpression expression) {
// public void enterTryFinally(JetBlockExpression element) {
// throw new UnsupportedOperationException(); // TODO
// }
//
......
package org.jetbrains.jet.lang.cfg;
import com.intellij.lang.ASTNode;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.BindingTrace;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.*;
......@@ -18,10 +19,12 @@ public class JetControlFlowProcessor {
private final JetSemanticServices semanticServices;
private final JetControlFlowBuilder builder;
private final BindingTrace trace;
public JetControlFlowProcessor(JetSemanticServices semanticServices, JetControlFlowBuilder builder) {
public JetControlFlowProcessor(JetSemanticServices semanticServices, BindingTrace trace, JetControlFlowBuilder builder) {
this.semanticServices = semanticServices;
this.builder = builder;
this.trace = trace;
}
public void generate(@NotNull JetElement subroutineElement, @NotNull JetExpression body) {
......@@ -29,11 +32,16 @@ public class JetControlFlowProcessor {
}
public void generateSubroutineControlFlow(@NotNull JetElement subroutineElement, @NotNull List<? extends JetElement> body, boolean preferBlocks) {
builder.enterSubroutine(subroutineElement);
if (subroutineElement instanceof JetNamedDeclaration) {
JetNamedDeclaration namedDeclaration = (JetNamedDeclaration) subroutineElement;
enterLabeledElement(namedDeclaration.getName(), namedDeclaration);
}
boolean functionLiteral = subroutineElement instanceof JetFunctionLiteralExpression;
builder.enterSubroutine(subroutineElement, functionLiteral);
for (JetElement statement : body) {
statement.accept(new CFPVisitor(preferBlocks));
}
builder.exitSubroutine(subroutineElement);
builder.exitSubroutine(subroutineElement, functionLiteral);
}
private void enterLabeledElement(@NotNull String labelName, @NotNull JetElement labeledElement) {
......@@ -46,16 +54,36 @@ public class JetControlFlowProcessor {
}
private void exitElement(JetElement element) {
// for (Iterator<Map.Entry<String, JetElement>> iterator = labeledElements.entrySet().iterator(); iterator.hasNext(); ) {
// Map.Entry<String, JetElement> entry = iterator.next();
// if (entry.getValue() == element) {
// iterator.remove();
// }
// }
// TODO : really suboptimal
for (Iterator<Map.Entry<String, Stack<JetElement>>> mapIter = labeledElements.entrySet().iterator(); mapIter.hasNext(); ) {
Map.Entry<String, Stack<JetElement>> entry = mapIter.next();
Stack<JetElement> stack = entry.getValue();
for (Iterator<JetElement> stackIter = stack.iterator(); stackIter.hasNext(); ) {
JetElement recorded = stackIter.next();
if (recorded == element) {
stackIter.remove();
}
}
if (stack.isEmpty()) {
mapIter.remove();
}
}
}
private JetElement resolveLabel(@NotNull String labelName, @NotNull ASTNode labelNode) {
throw new UnsupportedOperationException(); // TODO
@Nullable
private JetElement resolveLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression) {
Stack<JetElement> stack = labeledElements.get(labelName);
if (stack == null || stack.isEmpty()) {
semanticServices.getErrorHandler().unresolvedReference(labelExpression);
return null;
}
else if (stack.size() > 1) {
semanticServices.getErrorHandler().genericWarning(labelExpression.getNode(), "There is more than one label with such a name in this scope");
}
JetElement result = stack.peek();
trace.recordLabelResolution(labelExpression, result);
return result;
}
private class CFPVisitor extends JetVisitor {
......@@ -74,6 +102,7 @@ public class JetControlFlowProcessor {
visitor = new CFPVisitor(preferBlock);
}
element.accept(visitor);
exitElement(element);
}
@Override
......@@ -88,8 +117,14 @@ public class JetControlFlowProcessor {
@Override
public void visitLabelQualifiedExpression(JetLabelQualifiedExpression expression) {
enterLabeledElement(expression.getLabelName(), expression.getLabeledExpression());
value(expression.getLabeledExpression(), false);
String labelName = expression.getLabelName();
JetExpression labeledExpression = expression.getLabeledExpression();
visitLabeledExpression(labelName, labeledExpression);
}
private void visitLabeledExpression(@NotNull String labelName, @NotNull JetExpression labeledExpression) {
enterLabeledElement(labelName, labeledExpression);
value(labeledExpression, false);
}
@Override
......@@ -121,6 +156,17 @@ public class JetControlFlowProcessor {
}
}
@Override
public void visitUnaryExpression(JetUnaryExpression expression) {
IElementType operationType = expression.getOperationSign().getReferencedNameElementType();
if (JetTokens.LABELS.contains(operationType)) {
visitLabeledExpression(expression.getOperationSign().getReferencedName().substring(1), expression.getBaseExpression());
}
else {
visitElement(expression);
}
}
@Override
public void visitIfExpression(JetIfExpression expression) {
value(expression.getCondition(), false);
......@@ -135,7 +181,7 @@ public class JetControlFlowProcessor {
value(elseBranch, true);
}
builder.bindLabel(resultLabel);
// builder.readNode(expression);
// builder.readNode(element);
}
@Override
......@@ -210,7 +256,7 @@ public class JetControlFlowProcessor {
public void visitBreakExpression(JetBreakExpression expression) {
JetSimpleNameExpression labelElement = expression.getTargetLabel();
Label exitPoint = (labelElement != null)
? builder.getExitPoint(labelElement)
? builder.getExitPoint(resolveLabel(expression.getLabelName(), expression.getTargetLabel()))
: builder.getExitPoint(builder.getCurrentLoop());
builder.jump(exitPoint);
}
......@@ -219,7 +265,7 @@ public class JetControlFlowProcessor {
public void visitContinueExpression(JetContinueExpression expression) {
JetSimpleNameExpression labelElement = expression.getTargetLabel();
if (labelElement != null) {
builder.jump(builder.getEntryPoint(labelElement));
builder.jump(builder.getEntryPoint(resolveLabel(expression.getLabelName(), expression.getTargetLabel())));
}
else {
builder.jump(builder.getEntryPoint(builder.getCurrentLoop()));
......@@ -234,7 +280,7 @@ public class JetControlFlowProcessor {
}
JetSimpleNameExpression labelElement = expression.getTargetLabel();
JetElement subroutine = (labelElement != null)
? resolveLabel(expression.getLabelName(), expression.getTargetLabel().getNode())
? resolveLabel(expression.getLabelName(), expression.getTargetLabel())
: builder.getCurrentSubroutine();
if (returnedExpression == null) {
builder.returnNoValue(subroutine);
......
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
/**
* @author abreslav
*/
public class FunctionLiteralValueInstruction extends InstructionWithNext {
private Pseudocode body;
public FunctionLiteralValueInstruction(@NotNull JetElement element) {
super(element);
}
public Pseudocode getBody() {
return body;
}
public void setBody(Pseudocode body) {
this.body = body;
}
@Override
public void accept(InstructionVisitor visitor) {
visitor.visitFunctionLiteralValue(this);
}
@Override
public String toString() {
return "rf(" + element.getText() + ")";
}
}
......@@ -4,8 +4,12 @@ package org.jetbrains.jet.lang.cfg.pseudocode;
* @author abreslav
*/
public class InstructionVisitor {
public void visitRead(ValueInstruction instruction) {
visitInstruction(instruction);
public void visitReadValue(ReadValueInstruction instruction) {
visitInstructionWithNext(instruction);
}
public void visitFunctionLiteralValue(FunctionLiteralValueInstruction instruction) {
visitInstructionWithNext(instruction);
}
public void visitUnconditionalJump(UnconditionalJumpInstruction instruction) {
......@@ -24,6 +28,14 @@ public class InstructionVisitor {
visitJump(instruction);
}
public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) {
visitJump(instruction);
}
public void visitUnsupportedElementInstruction(UnsupportedElementInstruction instruction) {
visitInstructionWithNext(instruction);
}
public void visitSubroutineExit(SubroutineExitInstruction instruction) {
visitInstruction(instruction);
}
......@@ -32,10 +44,10 @@ public class InstructionVisitor {
visitInstruction(instruction);
}
public void visitInstruction(Instruction instruction) {
public void visitInstructionWithNext(InstructionWithNext instruction) {
visitInstruction(instruction);
}
public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) {
visitJump(instruction);
public void visitInstruction(Instruction instruction) {
}
}
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
/**
* @author abreslav
*/
public abstract class InstructionWithNext extends ExpressionInstruction {
public abstract class InstructionWithNext extends JetElementInstruction {
private Instruction next;
public InstructionWithNext(JetExpression expression) {
super(expression);
protected InstructionWithNext(@NotNull JetElement element) {
super(element);
}
public Instruction getNext() {
......
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.JetControlFlowBuilder;
import org.jetbrains.jet.lang.cfg.JetControlFlowBuilderAdapter;
import org.jetbrains.jet.lang.cfg.Label;
import org.jetbrains.jet.lang.psi.JetBlockExpression;
import org.jetbrains.jet.lang.psi.JetElement;
......@@ -14,7 +16,55 @@ import java.util.Stack;
/**
* @author abreslav
*/
public class JetControlFlowInstructionsGenerator implements JetControlFlowBuilder {
public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAdapter {
private int labelCount = 0;
private final Stack<JetControlFlowInstructionsGeneratorWorker> builders = new Stack<JetControlFlowInstructionsGeneratorWorker>();
public JetControlFlowInstructionsGenerator() {
super(null);
pushBuilder();
}
private void pushBuilder() {
Pseudocode parentPseudocode = builder == null ? new Pseudocode(null) : builders.peek().getPseudocode();
JetControlFlowInstructionsGeneratorWorker worker = new JetControlFlowInstructionsGeneratorWorker(parentPseudocode);
builders.push(worker);
builder = worker;
}
private JetControlFlowInstructionsGeneratorWorker popBuilder() {
JetControlFlowInstructionsGeneratorWorker worker = builders.pop();
builder = builders.peek();
return worker;
}
@Override
public void enterSubroutine(@NotNull JetElement subroutine, boolean isFunctionLiteral) {
if (isFunctionLiteral) {
pushBuilder();
builder.enterSubroutine(subroutine, false);
}
else {
super.enterSubroutine(subroutine, isFunctionLiteral);
}
}
@Override
public void exitSubroutine(@NotNull JetElement subroutine, boolean functionLiteral) {
super.exitSubroutine(subroutine, functionLiteral);
if (functionLiteral) {
JetControlFlowInstructionsGeneratorWorker worker = popBuilder();
JetControlFlowInstructionsGeneratorWorker builder = builders.peek();
FunctionLiteralValueInstruction instruction = new FunctionLiteralValueInstruction(subroutine);
builder.add(instruction);
instruction.setBody(worker.getPseudocode());
}
}
public Pseudocode getPseudocode() {
return builders.peek().getPseudocode();
}
private static class BlockInfo {
private final JetElement element;
......@@ -40,137 +90,141 @@ public class JetControlFlowInstructionsGenerator implements JetControlFlowBuilde
}
}
private final Stack<BlockInfo> loopInfo = new Stack<BlockInfo>();
private final Stack<BlockInfo> subroutineInfo = new Stack<BlockInfo>();
private final Map<JetElement, BlockInfo> elementToBlockInfo = new HashMap<JetElement, BlockInfo>();
private class JetControlFlowInstructionsGeneratorWorker implements JetControlFlowBuilder {
private final Stack<BlockInfo> loopInfo = new Stack<BlockInfo>();
private final Stack<BlockInfo> subroutineInfo = new Stack<BlockInfo>();
private int labelCount = 0;
private final Map<JetElement, BlockInfo> elementToBlockInfo = new HashMap<JetElement, BlockInfo>();
private final Pseudocode pseudocode = new Pseudocode();
private final Pseudocode pseudocode;
public Pseudocode getPseudocode() {
return pseudocode;
}
private JetControlFlowInstructionsGeneratorWorker(@Nullable Pseudocode parent) {
this.pseudocode = new Pseudocode(parent);
}
private void add(Instruction instruction) {
pseudocode.getInstructions().add(instruction);
}
public Pseudocode getPseudocode() {
return pseudocode;
}
@NotNull
@Override
public final Label createUnboundLabel() {
return new Label("l" + labelCount++);
}
private void add(Instruction instruction) {
pseudocode.addInstruction(instruction);
}
@Override
public final Label enterLoop(@NotNull JetExpression expression, Label loopExitPoint) {
Label label = createUnboundLabel();
bindLabel(label);
BlockInfo blockInfo = new BlockInfo(expression, label, loopExitPoint);
loopInfo.push(blockInfo);
elementToBlockInfo.put(expression, blockInfo);
return label;
}
@NotNull
@Override
public final Label createUnboundLabel() {
return new Label("l" + labelCount++);
}
@Override
public final void exitLoop(@NotNull JetExpression expression) {
BlockInfo info = loopInfo.pop();
elementToBlockInfo.remove(expression);
bindLabel(info.getExitPoint());
}
@Override
public final Label enterLoop(@NotNull JetExpression expression, Label loopExitPoint) {
Label label = createUnboundLabel();
bindLabel(label);
BlockInfo blockInfo = new BlockInfo(expression, label, loopExitPoint);
loopInfo.push(blockInfo);
elementToBlockInfo.put(expression, blockInfo);
return label;
}
@Override
public JetElement getCurrentLoop() {
return loopInfo.empty() ? null : loopInfo.peek().getElement();
}
@Override
public final void exitLoop(@NotNull JetExpression expression) {
BlockInfo info = loopInfo.pop();
elementToBlockInfo.remove(expression);
bindLabel(info.getExitPoint());
}
@Override
public void enterSubroutine(@NotNull JetElement subroutine) {
Label entryPoint = createUnboundLabel();
BlockInfo blockInfo = new BlockInfo(subroutine, entryPoint, createUnboundLabel());
subroutineInfo.push(blockInfo);
elementToBlockInfo.put(subroutine, blockInfo);
bindLabel(entryPoint);
}
@Override
public JetElement getCurrentLoop() {
return loopInfo.empty() ? null : loopInfo.peek().getElement();
}
@Override
public JetElement getCurrentSubroutine() {
return subroutineInfo.empty() ? null : subroutineInfo.peek().getElement();
}
@Override
public void enterSubroutine(@NotNull JetElement subroutine, boolean isFunctionLiteral) {
Label entryPoint = createUnboundLabel();
BlockInfo blockInfo = new BlockInfo(subroutine, entryPoint, createUnboundLabel());
subroutineInfo.push(blockInfo);
elementToBlockInfo.put(subroutine, blockInfo);
bindLabel(entryPoint);
}
@Override
public Label getEntryPoint(@NotNull JetElement labelElement) {
return elementToBlockInfo.get(labelElement).getEntryPoint();
}
@Override
public JetElement getCurrentSubroutine() {
return subroutineInfo.empty() ? null : subroutineInfo.peek().getElement();
}
@Override
public Label getExitPoint(@NotNull JetElement labelElement) {
return elementToBlockInfo.get(labelElement).getExitPoint();
}
@Override
public Label getEntryPoint(@NotNull JetElement labelElement) {
return elementToBlockInfo.get(labelElement).getEntryPoint();
}
@Override
public Label getExitPoint(@NotNull JetElement labelElement) {
return elementToBlockInfo.get(labelElement).getExitPoint();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Override
public void exitSubroutine(@NotNull JetElement subroutine) {
bindLabel(getExitPoint(subroutine));
add(new SubroutineExitInstruction(subroutine));
elementToBlockInfo.remove(subroutine);
}
@Override
public void exitSubroutine(@NotNull JetElement subroutine, boolean functionLiteral) {
bindLabel(getExitPoint(subroutine));
add(new SubroutineExitInstruction(subroutine));
elementToBlockInfo.remove(subroutine);
}
@Override
public void returnValue(@NotNull JetElement subroutine) {
add(new ReturnValueInstruction(getExitPoint(subroutine)));
}
@Override
public void returnValue(@NotNull JetElement subroutine) {
add(new ReturnValueInstruction(getExitPoint(subroutine)));
}
@Override
public void returnNoValue(@NotNull JetElement subroutine) {
add(new ReturnNoValueInstruction(getExitPoint(subroutine)));
}
@Override
public void returnNoValue(@NotNull JetElement subroutine) {
add(new ReturnNoValueInstruction(getExitPoint(subroutine)));
}
@Override
public void readNode(@NotNull JetExpression expression) {
add(new ValueInstruction(expression));
}
@Override
public void readNode(@NotNull JetExpression expression) {
add(new ReadValueInstruction(expression));
}
@Override
public void jump(@NotNull Label label) {
add(new UnconditionalJumpInstruction(label));
}
@Override
public void jump(@NotNull Label label) {
add(new UnconditionalJumpInstruction(label));
}
@Override
public void jumpOnFalse(@NotNull Label label) {
add(new ConditionalJumpInstruction(false, label));
}
@Override
public void jumpOnFalse(@NotNull Label label) {
add(new ConditionalJumpInstruction(false, label));
}
@Override
public void jumpOnTrue(@NotNull Label label) {
add(new ConditionalJumpInstruction(true, label));
}
@Override
public void jumpOnTrue(@NotNull Label label) {
add(new ConditionalJumpInstruction(true, label));
}
@Override
public void bindLabel(@NotNull Label label) {
pseudocode.getLabels().put(label, pseudocode.getInstructions().size());
}
@Override
public void bindLabel(@NotNull Label label) {
pseudocode.addLabel(label);
}
@Override
public void nondeterministicJump(Label label) {
add(new NondeterministicJumpInstruction(label));
}
@Override
public void nondeterministicJump(Label label) {
add(new NondeterministicJumpInstruction(label));
}
@Override
public void enterTryFinally(@NotNull JetBlockExpression expression) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public void enterTryFinally(@NotNull JetBlockExpression expression) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public void exitTryFinally() {
throw new UnsupportedOperationException(); // TODO
}
@Override
public void exitTryFinally() {
throw new UnsupportedOperationException(); // TODO
}
@Override
public void unsupported(JetElement element) {
throw new IllegalStateException("Unsupported element: " + element.getText() + " " + element);
@Override
public void unsupported(JetElement element) {
add(new UnsupportedElementInstruction(element));
}
}
}
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetElement;
/**
* @author abreslav
*/
public abstract class ExpressionInstruction extends Instruction {
protected final JetExpression expression;
public abstract class JetElementInstruction extends Instruction {
protected final JetElement element;
public ExpressionInstruction(@NotNull JetExpression expression) {
this.expression = expression;
public JetElementInstruction(@NotNull JetElement element) {
this.element = element;
}
@NotNull
public JetExpression getExpression() {
return expression;
public JetElement getElement() {
return element;
}
}
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.Label;
import java.io.PrintStream;
......@@ -13,12 +14,28 @@ public class Pseudocode {
private final List<Instruction> instructions = new ArrayList<Instruction>();
private final Map<Label, Integer> labels = new LinkedHashMap<Label, Integer>();
public List<Instruction> getInstructions() {
return instructions;
@Nullable
private final Pseudocode parent;
public Pseudocode(Pseudocode parent) {
this.parent = parent;
}
public void addInstruction(Instruction instruction) {
instructions.add(instruction);
}
public void addLabel(Label label) {
labels.put(label, instructions.size());
}
public Map<Label, Integer> getLabels() {
return labels;
@Nullable
private Integer resolveLabel(Label targetLabel) {
Integer result = labels.get(targetLabel);
if (result == null && parent != null) {
return parent.resolveLabel(targetLabel);
}
return result;
}
public void postProcess() {
......@@ -27,7 +44,7 @@ public class Pseudocode {
final int currentPosition = i;
instruction.accept(new InstructionVisitor() {
@Override
public void visitRead(ValueInstruction instruction) {
public void visitInstructionWithNext(InstructionWithNext instruction) {
instruction.setNext(getNextPosition(currentPosition));
}
......@@ -57,6 +74,12 @@ public class Pseudocode {
visitJump(instruction);
}
@Override
public void visitFunctionLiteralValue(FunctionLiteralValueInstruction instruction) {
instruction.getBody().postProcess();
super.visitFunctionLiteralValue(instruction);
}
@Override
public void visitSubroutineExit(SubroutineExitInstruction instruction) {
// Nothing
......@@ -72,7 +95,7 @@ public class Pseudocode {
@NotNull
private Instruction getJumpTarget(@NotNull Label targetLabel) {
Integer targetPosition = labels.get(targetLabel);
Integer targetPosition = resolveLabel(targetLabel);
return getTargetInstruction(targetPosition);
}
......@@ -87,7 +110,7 @@ public class Pseudocode {
}
Label label = ((UnconditionalJumpInstruction) targetInstruction).getTargetLabel();
targetPosition = labels.get(label);
targetPosition = resolveLabel(label);
}
}
......@@ -111,15 +134,19 @@ public class Pseudocode {
}
public void dumpGraph(@NotNull final PrintStream out) {
out.println("digraph g {");
String graphHeader = "digraph g";
dumpSubgraph(out, graphHeader, new int[1], "");
}
private void dumpSubgraph(final PrintStream out, String graphHeader, final int[] count, String style) {
out.println(graphHeader + " {");
final Map<Instruction, String> nodeToName = new HashMap<Instruction, String>();
int count = 0;
for (Instruction node : instructions) {
if (node instanceof UnconditionalJumpInstruction) {
continue;
}
String name = "n" + count++;
String name = "n" + count[0]++;
nodeToName.put(node, name);
String text = node.toString();
int newline = text.indexOf("\n");
......@@ -133,11 +160,25 @@ public class Pseudocode {
else if (node instanceof NondeterministicJumpInstruction) {
shape = "Mdiamond";
}
else if (node instanceof UnsupportedElementInstruction) {
shape = "box, fillcolor=red, style=filled";
}
else if (node instanceof FunctionLiteralValueInstruction) {
shape = "Mcircle";
}
out.println(name + "[label=\"" + text + "\", shape=" + shape + "];");
}
for (final Instruction fromInst : instructions) {
fromInst.accept(new InstructionVisitor() {
@Override
public void visitFunctionLiteralValue(FunctionLiteralValueInstruction instruction) {
int index = count[0];
instruction.getBody().dumpSubgraph(out, "subgraph f" + index, count, "color=blue;\ntlabel = \"process #" + index + "\";");
printEdge(out, nodeToName.get(instruction), "n" + index, null);
visitInstructionWithNext(instruction);
}
@Override
public void visitUnconditionalJump(UnconditionalJumpInstruction instruction) {
// Nothing
......@@ -145,13 +186,13 @@ public class Pseudocode {
@Override
public void visitJump(AbstractJumpInstruction instruction) {
writeEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getResolvedTarget()), null);
printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getResolvedTarget()), null);
}
@Override
public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) {
visitJump(instruction);
writeEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getNext()), null);
printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getNext()), null);
}
@Override
......@@ -167,13 +208,13 @@ public class Pseudocode {
@Override
public void visitConditionalJump(ConditionalJumpInstruction instruction) {
String from = nodeToName.get(instruction);
writeEdge(out, from, nodeToName.get(instruction.getNextOnFalse()), "no");
writeEdge(out, from, nodeToName.get(instruction.getNextOnTrue()), "yes");
printEdge(out, from, nodeToName.get(instruction.getNextOnFalse()), "no");
printEdge(out, from, nodeToName.get(instruction.getNextOnTrue()), "yes");
}
@Override
public void visitRead(ValueInstruction instruction) {
writeEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getNext()), null);
public void visitInstructionWithNext(InstructionWithNext instruction) {
printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getNext()), null);
}
@Override
......@@ -187,11 +228,11 @@ public class Pseudocode {
}
});
}
out.println(style);
out.println("}");
out.close();
}
private void writeEdge(PrintStream out, String from, String to, String label) {
private void printEdge(PrintStream out, String from, String to, String label) {
if (label != null) {
label = "[label=\"" + label + "\"]";
}
......
......@@ -6,19 +6,19 @@ import org.jetbrains.jet.lang.psi.JetExpression;
/**
* @author abreslav
*/
public class ValueInstruction extends InstructionWithNext {
public class ReadValueInstruction extends InstructionWithNext {
public ValueInstruction(@NotNull JetExpression expression) {
public ReadValueInstruction(@NotNull JetExpression expression) {
super(expression);
}
@Override
public void accept(InstructionVisitor visitor) {
visitor.visitRead(this);
visitor.visitReadValue(this);
}
@Override
public String toString() {
return "r(" + expression.getText() + ")";
return "r(" + element.getText() + ")";
}
}
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
/**
* @author abreslav
*/
public class UnsupportedElementInstruction extends InstructionWithNext {
protected UnsupportedElementInstruction(@NotNull JetElement element) {
super(element);
}
@Override
public void accept(InstructionVisitor visitor) {
visitor.visitUnsupportedElementInstruction(this);
}
@Override
public String toString() {
return "unsupported(" + element + " : " + element.getText() + ")";
}
}
......@@ -227,9 +227,9 @@ public class JetExpressionParsing extends AbstractJetParsing {
}
/*
* expression
* : attributes expression
* : "(" expression ")" // see tupleLiteral
* element
* : attributes element
* : "(" element ")" // see tupleLiteral
* : literalConstant
* : functionLiteral
* : tupleLiteral
......@@ -238,7 +238,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
* : expressionWithPrecedences
* : if
* : try
* : "typeof" "(" expression ")"
* : "typeof" "(" element ")"
* : "new" constructorInvocation
* : objectLiteral
* : declaration
......@@ -249,14 +249,14 @@ public class JetExpressionParsing extends AbstractJetParsing {
*/
public void parseExpression() {
if (!atSet(EXPRESSION_FIRST)) {
error("Expecting an expression");
error("Expecting an element");
return;
}
parseBinaryExpression(Precedence.ASSIGNMENT);
}
/*
* expression (operation expression)*
* element (operation element)*
*
* see the precedence table
*/
......@@ -427,7 +427,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
}
/*
* expression (getEntryPoint? functionLiteral)?
* element (getEntryPoint? functionLiteral)?
*/
protected boolean parseCallWithClosure() {
boolean success = false;
......@@ -447,9 +447,9 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* atomicExpression
* : tupleLiteral // or parenthesized expression
* : tupleLiteral // or parenthesized element
* : "this" getEntryPoint? ("<" type ">")?
* : "typeof" "(" expression ")"
* : "typeof" "(" element ")"
* : "new" constructorInvocation
* : objectLiteral
* : jump
......@@ -535,8 +535,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
parseFunctionLiteral();
}
else if (!parseLiteralConstant()) {
// TODO: better recovery if FIRST(expression) did not match
errorWithRecovery("Expecting an expression", EXPRESSION_FOLLOW);
// TODO: better recovery if FIRST(element) did not match
errorWithRecovery("Expecting an element", EXPRESSION_FOLLOW);
}
}
......@@ -581,7 +581,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* when
* : "when" "(" (modifiers "val" SimpleName "=")? expression ")" "{"
* : "when" "(" (modifiers "val" SimpleName "=")? element ")" "{"
* whenEntry*
* "}"
* ;
......@@ -622,8 +622,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* whenEntry
* // TODO : consider empty after =>
* : whenConditionIf{","} (when | "=>" expression SEMI)
* : "else" ("continue" | "=>" expression SEMI)
* : whenConditionIf{","} (when | "=>" element SEMI)
* : "else" ("continue" | "=>" element SEMI)
* ;
*/
private void parseWhenEntry() {
......@@ -633,7 +633,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
advance(); // ELSE_KEYWORD
if (!at(CONTINUE_KEYWORD) && !at(DOUBLE_ARROW)) {
errorUntil("Expecting 'continue' or '=> expression'", TokenSet.create(CONTINUE_KEYWORD, DOUBLE_ARROW,
errorUntil("Expecting 'continue' or '=> element'", TokenSet.create(CONTINUE_KEYWORD, DOUBLE_ARROW,
RBRACE, EOL_OR_SEMICOLON));
}
......@@ -641,14 +641,14 @@ public class JetExpressionParsing extends AbstractJetParsing {
advance(); // DOUBLE_ARROW
if (atSet(WHEN_CONDITION_RECOVERY_SET)) {
error("Expecting an expression");
error("Expecting an element");
} else {
parseExpression();
}
} else if (at(CONTINUE_KEYWORD)) {
advance(); // CONTINUE_KEYWORD
} else if (!atSet(WHEN_CONDITION_RECOVERY_SET)) {
errorAndAdvance("Expecting 'continue' or '=> expression'");
errorAndAdvance("Expecting 'continue' or '=> element'");
}
} else {
parseWhenEntryNotElse();
......@@ -659,7 +659,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
}
/*
* : whenConditionIf{","} (when | "=>" expression SEMI)
* : whenConditionIf{","} (when | "=>" element SEMI)
*/
private void parseWhenEntryNotElse() {
while (true) {
......@@ -673,7 +673,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
} else {
expect(DOUBLE_ARROW, "Expecting '=>' or 'when'", WHEN_CONDITION_RECOVERY_SET);
if (atSet(WHEN_CONDITION_RECOVERY_SET)) {
error("Expecting an expression");
error("Expecting an element");
} else {
parseExpression();
}
......@@ -683,7 +683,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* whenConditionIf
* : pattern ("if" "(" expression ")")?
* : pattern ("if" "(" element ")")?
* ;
*/
private void parseWhenConditionIf() {
......@@ -705,9 +705,9 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* whenCondition
* : expression
* : element
* : "." postfixExpression typeArguments? valueArguments?
* : ("in" | "!in") expression
* : ("in" | "!in") element
* : ("is" | "!is") isRHS
* ;
*/
......@@ -718,7 +718,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
advance(); // IN_KEYWORD or NOT_IN
if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_DOUBLE_ARROW)) {
error("Expecting an expression");
error("Expecting an element");
} else {
parseExpression();
}
......@@ -739,7 +739,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
}
} else {
if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_DOUBLE_ARROW)) {
error("Expecting an expression, is-condition or in-condition");
error("Expecting an element, is-condition or in-condition");
} else {
parseExpression();
}
......@@ -782,7 +782,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
myJetParsing.parseTypeRef();
if (at(AT)) {
errorAndAdvance("'@' is allowed only after a decomposer expression, not after a type");
errorAndAdvance("'@' is allowed only after a decomposer element, not after a type");
}
if (myBuilder.getCurrentOffset() < expressionEndOffset) {
rollbackMarker.rollbackTo();
......@@ -853,8 +853,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
* binding
* : "is" pattern
* : "!is" pattern
* : "in" expression
* : "!in" expression
* : "in" element
* : "!in" element
* : ":" type
* ;
*/
......@@ -882,7 +882,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* arrayAccess
* : "[" expression{","} "]"
* : "[" element{","} "]"
* ;
*/
private void parseArrayAccess() {
......@@ -894,9 +894,9 @@ public class JetExpressionParsing extends AbstractJetParsing {
advance(); // LBRACKET
while (true) {
if (at(COMMA)) errorAndAdvance("Expecting an index expression");
if (at(COMMA)) errorAndAdvance("Expecting an index element");
if (at(RBRACKET)) {
error("Expecting an index expression");
error("Expecting an index element");
break;
}
parseExpression();
......@@ -1073,13 +1073,13 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* expressions
* : SEMI* expression{SEMI+} SEMI*
* : SEMI* element{SEMI+} SEMI*
*/
public void parseExpressions() {
while (at(SEMICOLON)) advance(); // SEMICOLON
while (!eof() && !at(RBRACE)) {
if (!atSet(EXPRESSION_FIRST)) {
errorAndAdvance("Expecting an expression");
errorAndAdvance("Expecting an element");
}
if (atSet(EXPRESSION_FIRST)) {
parseExpression();
......@@ -1126,7 +1126,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* doWhile
* : "do" expression "while" "(" expression ")"
* : "do" element "while" "(" element ")"
* ;
*/
private void parseDoWhile() {
......@@ -1149,7 +1149,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* while
* : "while" "(" expression ")" expression
* : "while" "(" element ")" element
* ;
*/
private void parseWhile() {
......@@ -1168,7 +1168,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* for
* : "for" "(" attributes valOrVar? SimpleName (":" type)? "in" expression ")" expression
* : "for" "(" attributes valOrVar? SimpleName (":" type)? "in" element ")" element
* ;
*
* TODO: empty loop body (at the end of the block)?
......@@ -1207,7 +1207,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
}
/*
* expression
* element
*/
private void parseControlStructureBody() {
PsiBuilder.Marker body = mark();
......@@ -1263,7 +1263,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* if
* : "if" "(" expression ")" expression SEMI? ("else" expression)?
* : "if" "(" element ")" element SEMI? ("else" element)?
* ;
*/
private void parseIf() {
......@@ -1296,7 +1296,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
}
/*
* "(" expression ")"
* "(" element ")"
*/
private void parseCondition() {
myBuilder.disableNewlines();
......@@ -1321,13 +1321,13 @@ public class JetExpressionParsing extends AbstractJetParsing {
advance(); // BREAK_KEYWORD or CONTINUE_KEYWORD
if (!eol() && atSet(LABELS)) advance(); // LABELS
parseLabel();
marker.done(type);
}
/*
* "return" getEntryPoint? expression?
* "return" getEntryPoint? element?
*/
private void parseReturn() {
assert _at(RETURN_KEYWORD);
......@@ -1336,9 +1336,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
advance(); // RETURN_KEYWORD
if (atSet(LABELS)) {
advance(); // LABELS
}
parseLabel();
if (atSet(EXPRESSION_FIRST) && !at(EOL_OR_SEMICOLON)) parseExpression();
......@@ -1346,7 +1344,22 @@ public class JetExpressionParsing extends AbstractJetParsing {
}
/*
* : "throw" expression
* labels
*/
private void parseLabel() {
if (!eol() && atSet(LABELS)) {
PsiBuilder.Marker labelWrap = mark();
PsiBuilder.Marker mark = mark();
advance(); // LABELS
mark.done(LABEL_REFERENCE);
labelWrap.done(LABEL_QUALIFIER);
}
}
/*
* : "throw" element
*/
private void parseThrow() {
assert _at(THROW_KEYWORD);
......@@ -1379,7 +1392,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
}
/*
* "typeof" "(" expression ")"
* "typeof" "(" element ")"
*/
private void parseTypeOf() {
assert _at(TYPEOF_KEYWORD);
......@@ -1399,13 +1412,13 @@ public class JetExpressionParsing extends AbstractJetParsing {
}
/*
* tupleLiteral // Ambiguity when after a SimpleName (infix call). In this case (e) is treated as an expression in parentheses
* tupleLiteral // Ambiguity when after a SimpleName (infix call). In this case (e) is treated as an element in parentheses
* // to put a tuple, write write ((e))
* : "(" ((SimpleName "=")? expression){","} ")"
* : "(" ((SimpleName "=")? element){","} ")"
* ;
*
* expression
* : "(" expression ")"
* element
* : "(" element ")"
* ;
*
* TODO: duplication with valueArguments (but for the error messages)
......@@ -1422,7 +1435,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
while (true) {
while (at(COMMA)) {
tuple = true;
errorAndAdvance("Expecting a tuple entry (expression)");
errorAndAdvance("Expecting a tuple entry (element)");
}
if (at(IDENTIFIER) && lookahead(1) == EQ) {
......@@ -1441,7 +1454,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
tuple = true;
if (at(RPAR)) {
error("Expecting a tuple entry (expression)");
error("Expecting a tuple entry (element)");
break;
}
}
......@@ -1463,11 +1476,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
PsiBuilder.Marker mark = mark();
advance(); // THIS_KEYWORD
if (atSet(LABELS)) {
PsiBuilder.Marker label = mark();
advance(); // LABELS
label.done(LABEL_REFERENCE);
}
parseLabel();
if (at(LT)) {
// This may be "this < foo" or "this<foo>", thus the backtracking
......@@ -1492,7 +1501,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* valueArguments
* : "(" (SimpleName "=")? ("out" | "ref")? expression{","} ")"
* : "(" (SimpleName "=")? ("out" | "ref")? element{","} ")"
* ;
*/
public void parseValueArgumentList() {
......@@ -1521,7 +1530,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
}
/*
* (SimpleName "=")? ("out" | "ref")? expression
* (SimpleName "=")? ("out" | "ref")? element
*/
private void parseValueArgument() {
PsiBuilder.Marker argument = mark();
......
......@@ -311,7 +311,7 @@ public class JetParsing extends AbstractJetParsing {
/*
* attribute
* // : SimpleName{"."} (valueArguments | "=" expression)?
* // : SimpleName{"."} (valueArguments | "=" element)?
* [for recovery: userType valueArguments?]
* ;
*/
......@@ -683,7 +683,7 @@ public class JetParsing extends AbstractJetParsing {
* : modifiers ("val" | "var")
* typeParameters? (type "." | attributes)?
* SimpleName (":" type)?
* ("=" expression SEMI?)?
* ("=" element SEMI?)?
* (getter? setter? | setter? getter?) SEMI?
* ;
*/
......@@ -883,7 +883,7 @@ public class JetParsing extends AbstractJetParsing {
/*
* functionBody
* : block
* : "=" expression
* : "=" element
* ;
*/
private void parseFunctionBody() {
......@@ -975,7 +975,7 @@ public class JetParsing extends AbstractJetParsing {
* ;
*
* explicitDelegation
* : userType "by" expression
* : userType "by" element
* ;
*/
private void parseDelegationSpecifier() {
......@@ -1336,7 +1336,7 @@ public class JetParsing extends AbstractJetParsing {
* ;
*
* functionParameterRest
* : parameter ("=" expression)?
* : parameter ("=" element)?
* ;
*/
public void parseValueParameterList(boolean isFunctionTypeContents, TokenSet recoverySet) {
......@@ -1376,7 +1376,7 @@ public class JetParsing extends AbstractJetParsing {
/*
* functionParameter
* : modifiers ("val" | "var")? parameter ("=" expression)?
* : modifiers ("val" | "var")? parameter ("=" element)?
* ;
*/
private boolean tryParseValueParameter() {
......@@ -1408,7 +1408,7 @@ public class JetParsing extends AbstractJetParsing {
/*
* functionParameterRest
* : parameter ("=" expression)?
* : parameter ("=" element)?
* ;
*/
private boolean parseFunctionParameterRest() {
......
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
/**
......@@ -15,4 +17,9 @@ public class JetContainerNode extends JetElement {
protected <T> T findChildByClass(Class<T> aClass) {
return super.findChildByClass(aClass);
}
@Override // for visibility
protected PsiElement findChildByType(IElementType type) {
return super.findChildByType(type);
}
}
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lexer.JetTokens;
/**
* @author max
......@@ -19,9 +16,4 @@ public class JetContinueExpression extends JetLabelQualifiedExpression {
visitor.visitContinueExpression(this);
}
@Nullable
public String getLabelName() {
PsiElement id = findChildByType(JetTokens.IDENTIFIER);
return id != null ? id.getText() : null;
}
}
......@@ -3,7 +3,7 @@ package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.JetNodeTypes;
/**
* @author abreslav
......@@ -16,7 +16,9 @@ public class JetLabelQualifiedExpression extends JetExpression {
@Nullable
public JetSimpleNameExpression getTargetLabel() {
return (JetSimpleNameExpression) findChildByType(JetTokens.LABELS);
JetContainerNode qualifier = (JetContainerNode) findChildByType(JetNodeTypes.LABEL_QUALIFIER);
if (qualifier == null) return null;
return (JetSimpleNameExpression) qualifier.findChildByType(JetNodeTypes.LABEL_REFERENCE);
}
@Nullable @IfNotParsed
......
......@@ -14,6 +14,7 @@ import java.util.Map;
public class BindingTraceContext extends BindingTrace implements BindingContext {
private final Map<JetExpression, JetType> expressionTypes = new HashMap<JetExpression, JetType>();
private final Map<JetReferenceExpression, DeclarationDescriptor> resolutionResults = new HashMap<JetReferenceExpression, DeclarationDescriptor>();
private final Map<JetReferenceExpression, PsiElement> labelResolutionResults = new HashMap<JetReferenceExpression, PsiElement>();
private final Map<JetTypeReference, JetType> types = new HashMap<JetTypeReference, JetType>();
private final Map<DeclarationDescriptor, PsiElement> descriptorToDeclarations = new HashMap<DeclarationDescriptor, PsiElement>();
private final Map<PsiElement, DeclarationDescriptor> declarationsToDescriptors = new HashMap<PsiElement, DeclarationDescriptor>();
......@@ -31,6 +32,11 @@ public class BindingTraceContext extends BindingTrace implements BindingContext
resolutionResults.put(expression, descriptor);
}
@Override
public void recordLabelResolution(@NotNull JetReferenceExpression expression, @NotNull PsiElement element) {
labelResolutionResults.put(expression, element);
}
@Override
public void removeReferenceResolution(@NotNull JetReferenceExpression referenceExpression) {
resolutionResults.remove(referenceExpression);
......@@ -107,7 +113,7 @@ public class BindingTraceContext extends BindingTrace implements BindingContext
public PsiElement resolveToDeclarationPsiElement(JetReferenceExpression referenceExpression) {
DeclarationDescriptor declarationDescriptor = resolveReferenceExpression(referenceExpression);
if (declarationDescriptor == null) {
return null;
return labelResolutionResults.get(referenceExpression);
}
return descriptorToDeclarations.get(declarationDescriptor.getOriginal());
}
......
......@@ -177,7 +177,7 @@ public class ClassDescriptorResolver {
}
} else {
if (bodyExpression == null) {
semanticServices.getErrorHandler().genericError(function.getNode(), "This function must either declare a return type or have a body expression");
semanticServices.getErrorHandler().genericError(function.getNode(), "This function must either declare a return type or have a body element");
returnType = ErrorUtils.createErrorType("No type, no body");
} else {
// TODO : Recursion possible
......
......@@ -234,7 +234,7 @@ public class TopDownAnalyzer {
if (bodyExpression != null) {
System.out.println("-------------");
JetControlFlowInstructionsGenerator instructionsGenerator = new JetControlFlowInstructionsGenerator();
new JetControlFlowProcessor(semanticServices, instructionsGenerator).generate(function, bodyExpression);
new JetControlFlowProcessor(semanticServices, trace, instructionsGenerator).generate(function, bodyExpression);
Pseudocode pseudocode = instructionsGenerator.getPseudocode();
pseudocode.postProcess();
pseudocode.dumpInstructions(System.out);
......
......@@ -18,6 +18,10 @@ public class BindingTrace {
}
public void recordLabelResolution(@NotNull JetReferenceExpression expression, @NotNull PsiElement element) {
}
public void recordDeclarationResolution(@NotNull PsiElement declaration, @NotNull DeclarationDescriptor descriptor) {
}
......
......@@ -185,7 +185,7 @@ public class JetTypeInferrer {
@Override
public void visitJetElement(JetElement elem) {
semanticServices.getErrorHandler().genericError(elem.getNode(), "Unsupported in call expression"); // TODO : Message
semanticServices.getErrorHandler().genericError(elem.getNode(), "Unsupported in call element"); // TODO : Message
}
});
return wrapForTracing(result[0], reference[0], argumentList, true);
......@@ -894,7 +894,7 @@ public class JetTypeInferrer {
}
else if (selectorExpression != null) {
// TODO : not a simple name -> resolve in scope, expect property type or a function type
semanticServices.getErrorHandler().genericError(selectorExpression.getNode(), "Unsupported selector expression type: " + selectorExpression);
semanticServices.getErrorHandler().genericError(selectorExpression.getNode(), "Unsupported selector element type: " + selectorExpression);
}
return receiverType;
}
......@@ -1312,7 +1312,7 @@ public class JetTypeInferrer {
String counterpartName = binaryOperationNames.get(assignmentOperationCounterparts.get(operationType));
getTypeForBinaryCall(expression, counterpartName, scope, true);
}
result = null; // not an expression
result = null; // not an element
}
@Override
......@@ -1335,7 +1335,7 @@ public class JetTypeInferrer {
}
}
}
result = null; // This is not an expression
result = null; // This is not an element
}
private void resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign) {
......
......@@ -640,7 +640,7 @@ class _JetLexer implements FlexLexer {
/**
* Returns the text matched by the current regular expression.
* Returns the text matched by the current regular element.
*/
public final CharSequence yytext() {
return zzBuffer.subSequence(zzStartRead, zzMarkedPos);
......@@ -727,7 +727,7 @@ class _JetLexer implements FlexLexer {
/**
* Resumes scanning until the next regular expression is matched,
* Resumes scanning until the next regular element is matched,
* the end of input is encountered or an I/O-Error occurs.
*
* @return the next token
......
......@@ -30,17 +30,17 @@ JetFile: Expressions_ERR.jet
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('dfsd')
PsiWhiteSpace('\n ')
PsiErrorElement:Expecting an expression
PsiErrorElement:Expecting an element
PsiElement(RPAR)(')')
PsiElement(SEMICOLON)(';')
PsiElement(SEMICOLON)(';')
PsiElement(SEMICOLON)(';')
PsiErrorElement:Expecting an expression
PsiErrorElement:Expecting an element
PsiElement(RPAR)(')')
PsiElement(SEMICOLON)(';')
PsiElement(SEMICOLON)(';')
PsiElement(SEMICOLON)(';')
PsiErrorElement:Expecting an expression
PsiErrorElement:Expecting an element
PsiElement(BAD_CHARACTER)('~')
PsiElement(SEMICOLON)(';')
PsiElement(SEMICOLON)(';')
......@@ -49,10 +49,10 @@ JetFile: Expressions_ERR.jet
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('srgsdfg')
PsiWhiteSpace('\n\n ')
PsiErrorElement:Expecting an expression
PsiErrorElement:Expecting an element
PsiElement(BAD_CHARACTER)('~')
PsiWhiteSpace('\n\n ')
PsiErrorElement:Expecting an expression
PsiErrorElement:Expecting an element
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
\ No newline at end of file
......@@ -60,7 +60,7 @@ JetFile: When_ERR.jet
WHEN_ENTRY
WHEN_CONDITION
PsiElement(in)('in')
PsiErrorElement:Expecting an expression
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
PsiElement(DOUBLE_ARROW)('=>')
......@@ -71,7 +71,7 @@ JetFile: When_ERR.jet
WHEN_ENTRY
WHEN_CONDITION
PsiElement(NOT_IN)('!in')
PsiErrorElement:Expecting an expression
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
PsiElement(DOUBLE_ARROW)('=>')
......@@ -81,7 +81,7 @@ JetFile: When_ERR.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION
PsiErrorElement:Expecting an expression, is-condition or in-condition
PsiErrorElement:Expecting an element, is-condition or in-condition
<empty list>
PsiElement(DOUBLE_ARROW)('=>')
PsiWhiteSpace(' ')
......@@ -90,7 +90,7 @@ JetFile: When_ERR.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
PsiElement(else)('else')
PsiErrorElement:Expecting 'continue' or '=> expression'
PsiErrorElement:Expecting 'continue' or '=> element'
<empty list>
PsiWhiteSpace('\n ')
PsiElement(RBRACE)('}')
......@@ -112,7 +112,7 @@ JetFile: When_ERR.jet
<empty list>
PsiWhiteSpace(' ')
PsiElement(DOUBLE_ARROW)('=>')
PsiErrorElement:Expecting an expression
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n ')
WHEN_ENTRY
......@@ -122,59 +122,59 @@ JetFile: When_ERR.jet
<empty list>
PsiWhiteSpace(' ')
PsiElement(DOUBLE_ARROW)('=>')
PsiErrorElement:Expecting an expression
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION
PsiElement(in)('in')
PsiErrorElement:Expecting an expression
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
PsiElement(DOUBLE_ARROW)('=>')
PsiErrorElement:Expecting an expression
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION
PsiElement(NOT_IN)('!in')
PsiErrorElement:Expecting an expression
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
PsiElement(DOUBLE_ARROW)('=>')
PsiErrorElement:Expecting an expression
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION
PsiElement(NOT_IN)('!in')
PsiErrorElement:Expecting an expression
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
PsiElement(DOUBLE_ARROW)('=>')
PsiErrorElement:Expecting an expression
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
PsiElement(SEMICOLON)(';')
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION
PsiErrorElement:Expecting an expression, is-condition or in-condition
PsiErrorElement:Expecting an element, is-condition or in-condition
<empty list>
PsiElement(DOUBLE_ARROW)('=>')
PsiErrorElement:Expecting an expression
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n ')
WHEN_ENTRY
PsiElement(else)('else')
PsiErrorElement:Expecting 'continue' or '=> expression'
PsiErrorElement:Expecting 'continue' or '=> element'
<empty list>
PsiWhiteSpace('\n ')
WHEN_ENTRY
PsiElement(else)('else')
PsiWhiteSpace(' ')
PsiElement(DOUBLE_ARROW)('=>')
PsiErrorElement:Expecting an expression
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n ')
PsiElement(RBRACE)('}')
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册