package org.reldb.rel.v0.vm.instructions.core; import java.util.HashSet; import org.reldb.rel.exceptions.ExceptionSemantic; import org.reldb.rel.v0.generator.Generator; import org.reldb.rel.v0.generator.OperatorDefinition; import org.reldb.rel.v0.generator.OperatorSignature; import org.reldb.rel.v0.types.Type; import org.reldb.rel.v0.values.Value; import org.reldb.rel.v0.values.ValueAlpha; import org.reldb.rel.v0.vm.Context; abstract class DynamicDispatch { private Generator generator; private OperatorSignature invocationSignature; private OperatorDefinition inOperator; DynamicDispatch(Generator generator, OperatorSignature invocationSignature, OperatorDefinition inOperator) { this.generator = generator; this.invocationSignature = invocationSignature; this.inOperator = inOperator; } void locateAndInvoke(Context context) { // TODO - improve performance by caching operators for given run-time invocationSignatureS. Cache should be cleared if type hierarchy changes. Value[] operands = context.peek(invocationSignature.getParmCount()); for (int i=0; i<invocationSignature.getParmCount(); i++) if (operands[i] instanceof ValueAlpha) { Type argumentType = ((ValueAlpha)operands[i]).getType(generator.getDatabase()); invocationSignature.setParameterType(i, argumentType); } HashSet<OperatorSignature> possibleTargets = generator.getPossibleTargetSignatures(inOperator, invocationSignature); if (possibleTargets.size() == 0) throw new ExceptionSemantic("RS0278: No run-time invocation targets found for " + invocationSignature); int closestDistance = Integer.MAX_VALUE; OperatorSignature closestSignature = null; for (OperatorSignature signature: possibleTargets) { int distance = signature.getInvocationDistance(invocationSignature); if (distance <= closestDistance) { closestDistance = distance; closestSignature = signature; } } OperatorDefinition operator = generator.locateOperator(inOperator, closestSignature); if (operator != null) { invoke(operator, context); return; } throw new ExceptionSemantic("RS0279: Operator '" + closestSignature + "' has not been defined, nor has any compatible operator of the same name."); } abstract void invoke(OperatorDefinition operator, Context context); }