All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jdt.internal.compiler.ast.EitherOrMultiPattern Maven / Gradle / Ivy

/*******************************************************************************
* Copyright (c) 2024 Advantest Europe GmbH 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:
*     Srikanth Sankaran - initial implementation
*******************************************************************************/

package org.eclipse.jdt.internal.compiler.ast;

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.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;

public class EitherOrMultiPattern extends Pattern {

	private Pattern [] patterns;
	private int patternsCount;

	public EitherOrMultiPattern(Pattern [] patterns) {
		this.patterns = patterns;
		this.patternsCount = patterns.length;
		this.sourceStart = patterns[0].sourceStart;
		this.sourceEnd = patterns[this.patternsCount - 1].sourceEnd;
		setIsEitherOrPattern();
	}

	@Override
	public Pattern[] getAlternatives() {
		return this.patterns;
	}

	@Override
	public void setIsEitherOrPattern() {
		for (int i = 0; i < this.patternsCount; i++)
			this.patterns[i].setIsEitherOrPattern();
	}

	@Override
	public void setIsGuarded() {
		for (int i = 0; i < this.patternsCount; i++)
			this.patterns[i].setIsGuarded();
	}

	@Override
	public TypeBinding resolveType(BlockScope scope) {
		boolean hasError = false;
		for (int i = 0; i < this.patternsCount; i++) {
			TypeBinding t = this.patterns[i].resolveType(scope);
			if (t == null || !t.isValidBinding())
				hasError = true;
		}
		return this.resolvedType = hasError ? null : this.patterns[0].resolvedType; // for now, we don't have a union type abstraction
	}

	@Override
	public boolean matchFailurePossible() {
		if (!isUnguarded())
			return true;
		for (Pattern p : this.patterns) {
			if (p.matchFailurePossible())
				return true;
		}
		return false;
	}

	@Override
	public void generateCode(BlockScope currentScope, CodeStream codeStream, BranchLabel patternMatchLabel, BranchLabel matchFailLabel) {
		/* JVM Stack on entry - [expression] // && expression instanceof _one of the_ EitherOrMultiPattern, we don't know which one
		   JVM stack on exit with successful pattern match or failed match -> []
		 */
		BranchLabel [] checkNextLabel = new BranchLabel [this.patternsCount];
		for (int i = 0; i < this.patternsCount; i++) {
			checkNextLabel[i] = new BranchLabel(codeStream);
			Pattern p = this.patterns[i];
			codeStream.dup();
			codeStream.instance_of(p.resolvedType); // mandatory since we don't know which alternative instance we have on stack
			codeStream.ifeq(checkNextLabel[i]);
			codeStream.dup();
			this.patterns[i].generateCode(currentScope, codeStream, patternMatchLabel, checkNextLabel[i]);
			codeStream.pop();
			codeStream.goto_(patternMatchLabel);
			checkNextLabel[i].place();
		}
		codeStream.pop();
		codeStream.goto_(matchFailLabel);
	}

	@Override
	public boolean dominates(Pattern p) {
		if (!isUnguarded())
			return false;
		for (Pattern thiz : this.patterns) {
			if (thiz.dominates(p))
				return true;
		}
		return false;
	}

	@Override
	public boolean coversType(TypeBinding type) {
		if (!isUnguarded())
			return false;
		for (Pattern p : this.patterns) {
			if (p.coversType(type))
				return true;
		}
		return false;
	}

	@Override
	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
		return flowInfo;
	}

	@Override
	public LocalVariableBinding[] bindingsWhenTrue() {
		return NO_VARIABLES; // emphatically.
	}

	@Override
	public StringBuilder printExpression(int indent, StringBuilder output) {
		for (int i = 0; i < this.patternsCount; i++) {
			if (i > 0) output.append(", "); //$NON-NLS-1$
			this.patterns[i].print(0, output);
		}
		return output;
	}

	@Override
	public void traverse(ASTVisitor visitor, BlockScope scope) {
		if (visitor.visit(this, scope)) {
			for (Pattern p : this.patterns) {
				p.traverse(visitor, scope);
			}
		}
		visitor.endVisit(this, scope);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy