Skip to content

Commit

Permalink
Parser changes + UnnamedPattern DOM node
Browse files Browse the repository at this point in the history
Signed-off-by: David Thompson <[email protected]>
  • Loading branch information
datho7561 committed Nov 8, 2023
1 parent 7169ef4 commit bb31692
Show file tree
Hide file tree
Showing 38 changed files with 2,157 additions and 1,862 deletions.
45 changes: 39 additions & 6 deletions org.eclipse.jdt.core.compiler.batch/grammar/java.g
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ $Terminals
BeginCaseElement
RestrictedIdentifierWhen
BeginRecordPattern
UNDERSCORE

-- BodyMarker

Expand Down Expand Up @@ -179,6 +180,7 @@ $Alias
'...' ::= ELLIPSIS
'@308' ::= AT308
'@308...' ::= AT308DOTDOTDOT
'_' ::= UNDERSCORE

$Start
Goal
Expand Down Expand Up @@ -832,6 +834,8 @@ RestoreDiet ::= $empty
VariableDeclaratorId ::= 'Identifier' Dimsopt
/:$readableName VariableDeclaratorId:/
/:$recovery_template Identifier:/
VariableDeclaratorId ::= '_'
/.$putCase consumeUnnamedVariable(); $break ./

VariableInitializer -> Expression
VariableInitializer -> ArrayInitializer
Expand Down Expand Up @@ -1269,30 +1273,48 @@ TypePattern ::= Modifiersopt Type 'Identifier'
-- 20 preview feature : record patterns
-----------------------------------------------

RecordPattern ::= Modifiersopt ReferenceType PushLPAREN PatternListopt PushRPAREN
RecordPattern ::= Modifiersopt ReferenceType PushLPAREN ComponentPatternListopt PushRPAREN
/.$putCase consumeRecordPattern(); $break ./
/:$readableName RecordPattern:/
/:$compliance 20:/

PatternListopt ::= $empty
ComponentPatternListopt ::= $empty
/.$putCase consumePatternListopt(); $break ./
/:$readableName PatternListopt:/
/:$compliance 20:/

PatternListopt -> PatternList
ComponentPatternListopt -> ComponentPatternList
/:$readableName PatternListopt:/
/:$compliance 20:/

PatternList -> Pattern
PatternList ::= PatternList ',' Pattern
ComponentPatternList -> ComponentPattern
ComponentPatternList ::= ComponentPatternList ',' ComponentPattern
/.$putCase consumePatternList(); $break ./
/:$readableName PatternList:/
/:$readableName ComponentPatternList:/
/:$compliance 20:/

ComponentPattern -> Pattern

-----------------------------------------------
-- 20 preview feature : end of record patterns
-----------------------------------------------

---
TypePattern ::= Modifiersopt Type '_'
/.$putCase consumeTypePattern(); $break ./
/:$readableName TypePattern:/
/:$compliance 21:/

ComponentPattern -> UnnamedPattern
/:$compliance 21:/

UnnamedPattern ::= '_'
/.$putCase consumeUnnamedPattern(); $break ./
/:$readableName UnnamedPattern:/
/:$compliance 21:/

---

ConstantDeclaration -> FieldDeclaration
/:$readableName ConstantDeclaration:/

Expand Down Expand Up @@ -1868,6 +1890,11 @@ NestedLambda ::= $empty
/.$putCase consumeNestedLambda(); $break ./
/:$readableName NestedLambda:/

LambdaParameters ::= '_' NestedLambda
/.$putCase consumeTypeElidedLambdaParameter(false); $break ./
/:$readableName TypeElidedUnnamedFormalParameter:/
/:$compliance 21:/

LambdaParameters ::= Identifier NestedLambda
/.$putCase consumeTypeElidedLambdaParameter(false); $break ./
/:$readableName TypeElidedFormalParameter:/
Expand Down Expand Up @@ -1901,6 +1928,11 @@ TypeElidedFormalParameter ::= Modifiersopt Identifier
/:$readableName TypeElidedFormalParameter:/
/:$compliance 1.8:/

TypeElidedFormalParameter ::= Modifiersopt '_'
/.$putCase consumeTypeElidedLambdaParameter(true); $break ./
/:$readableName TypeElidedFormalParameter:/
/:$compliance 21:/

-- A lambda body of the form x is really '{' return x; '}'
LambdaBody -> ElidedLeftBraceAndReturn Expression ElidedSemicolonAndRightBrace
LambdaBody -> Block
Expand Down Expand Up @@ -3173,6 +3205,7 @@ AT308DOTDOTDOT ::= '@'
ELLIPSIS ::= '...'
ARROW ::= '->'
COLON_COLON ::= '::'
UNDERSCORE ::= '_'

$end
-- need a carriage return after the $end
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public abstract class Pattern extends Expression {

public int nestingLevel = 0;

public int index = -1; // denoting position

@Override
public boolean containsPatternVariable() {
class PatternVariablesVisitor extends ASTVisitor {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,11 @@ private void setAccessorsPlusInfuseInferredType(BlockScope scope) {
} else {
for (int i = 0; i < components.length; i++) {
Pattern p = this.patterns[i];
if (!(p instanceof TypePattern))
if (!(p instanceof VariablePattern))
continue;
TypePattern tp = (TypePattern) p;
VariablePattern tp = (VariablePattern) p;
RecordComponentBinding componentBinding = components[i];
if (p.getType().isTypeNameVar(scope)) {
if (p.getType() == null || p.getType().isTypeNameVar(scope)) {
infuseInferredType(tp, componentBinding);
if (tp.local.binding != null) // rewrite with the inferred type
tp.local.binding.type = componentBinding.type;
Expand Down Expand Up @@ -225,7 +225,11 @@ private ReferenceBinding inferRecordParameterization(BlockScope scope, Reference
private boolean shouldInitiateRecordTypeInference() {
return this.resolvedType != null && this.resolvedType.isRawType();
}
private void infuseInferredType(TypePattern tp, RecordComponentBinding componentBinding) {
private void infuseInferredType(VariablePattern tp, RecordComponentBinding componentBinding) {
if (tp.local.type == null) {
// unused variable
return;
}
SingleTypeReference ref = new SingleTypeReference(tp.local.type.getTypeName()[0],
tp.local.type.sourceStart,
tp.local.type.sourceEnd) {
Expand Down Expand Up @@ -303,7 +307,7 @@ protected void generatePatternVariable(BlockScope currentScope, CodeStream codeS
if (TypeBinding.notEquals(p.accessorMethod.original().returnType.erasure(),
p.accessorMethod.returnType.erasure()))
codeStream.checkcast(p.accessorMethod.returnType);
if (p instanceof RecordPattern || !p.isTotalTypeNode) {
if (p instanceof RecordPattern || (p instanceof TypePattern && !p.isTotalTypeNode)) {
((TypePattern)p).getSecretVariable(currentScope, p.resolvedType);
((TypePattern)p).initializePatternVariables(currentScope, codeStream);
codeStream.load(p.secretPatternVariable);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,9 @@
import org.eclipse.jdt.internal.compiler.lookup.TypeBindingVisitor;
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;

public class TypePattern extends Pattern {
public class TypePattern extends VariablePattern {

public LocalDeclaration local;
Expression expression;
public int index = -1; // denoting position

public TypePattern(LocalDeclaration local) {
this.local = local;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat, Inc. and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;

import java.util.HashSet;
import java.util.Set;

import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.codegen.BranchLabel;
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.RecordComponentBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBindingVisitor;
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;

public class UnnamedPattern extends VariablePattern {

public UnnamedPattern(LocalDeclaration local) {
this.local = local;
this.isTotalTypeNode = true;
}

@Override
public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel,
BranchLabel falseLabel) {
this.local.generateCode(currentScope, codeStream);
codeStream.pop();
this.local.binding.recordInitializationStartPC(codeStream.position);
}

@Override
protected void generatePatternVariable(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel,
BranchLabel falseLabel) {
this.local.generateCode(currentScope, codeStream);
codeStream.pop();
this.local.binding.recordInitializationStartPC(codeStream.position);
}

@Override
protected void wrapupGeneration(CodeStream codeStream) {
// do nothing
}

@Override
public void resolveWithExpression(BlockScope scope, Expression expression) {
// do nothing
}

@Override
public TypeBinding resolveType(BlockScope scope, boolean isPatternVariable) {
if (this.resolvedType != null)
return this.resolvedType;
// copied from the isTypeNameVar case of TypePattern
Pattern enclosingPattern = this.getEnclosingPattern();
if (enclosingPattern instanceof RecordPattern) {
ReferenceBinding recType = (ReferenceBinding) enclosingPattern.resolvedType;
if (recType != null) {
RecordComponentBinding[] components = recType.components();
if (components.length > this.index) {
RecordComponentBinding rcb = components[this.index];
TypeVariableBinding[] mentionedTypeVariables = findSyntheticTypeVariables(rcb.type);
if (mentionedTypeVariables != null && mentionedTypeVariables.length > 0) {
this.resolvedType = recType.upwardsProjection(scope, mentionedTypeVariables);
} else {
this.resolvedType = rcb.type;
}
}
}
}
this.local.type = new FakeTypeReference(this.resolvedType);
this.local.resolve(scope, true);
return this.local.type.resolveType(scope, true);
}
private TypeVariableBinding[] findSyntheticTypeVariables(TypeBinding typeBinding) {
final Set<TypeVariableBinding> mentioned = new HashSet<>();
TypeBindingVisitor.visit(new TypeBindingVisitor() {
@Override
public boolean visit(TypeVariableBinding typeVariable) {
if (typeVariable.isCapture())
mentioned.add(typeVariable);
return super.visit(typeVariable);
}
}, typeBinding);
if (mentioned.isEmpty()) return null;
return mentioned.toArray(new TypeVariableBinding[mentioned.size()]);
}

@Override
protected boolean isPatternTypeCompatible(TypeBinding other, BlockScope scope) {
return true;
}

@Override
public boolean dominates(Pattern p) {
return false;
}

@Override
public StringBuffer printExpression(int indent, StringBuffer output) {
return this.local.printAsExpression(indent, output);
}

}

class FakeTypeReference extends TypeReference {

public FakeTypeReference(TypeBinding resolvedType) {
this.resolvedType = resolvedType;
}

@Override
public TypeBinding resolveType(BlockScope scope, boolean augment) {
return this.resolvedType;
}

@Override
public TypeReference augmentTypeWithAdditionalDimensions(int additionalDimensions,
Annotation[][] additionalAnnotations, boolean isVarargs) {
// TODO Auto-generated method stub
return null;
}

@Override
public char[] getLastToken() {
// shouldn't be called
return null;
}

@Override
protected TypeBinding getTypeBinding(Scope scope) {
// shouldn't be called
return null;
}

@Override
public char[][] getTypeName() {
// shouldn't be called
return null;
}

@Override
public void traverse(ASTVisitor visitor, BlockScope scope) {
// do nothing
}

@Override
public void traverse(ASTVisitor visitor, ClassScope scope) {
// do nothing
}

@Override
public StringBuffer printExpression(int indent, StringBuffer output) {
return output;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat, Inc. and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;

public abstract class VariablePattern extends Pattern {
public LocalDeclaration local;
}
Loading

0 comments on commit bb31692

Please sign in to comment.