CommonValueFactory.java
package dev.civl.abc.ast.value.common;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import dev.civl.abc.ast.entity.IF.Entity;
import dev.civl.abc.ast.entity.IF.Entity.EntityKind;
import dev.civl.abc.ast.entity.IF.Function;
import dev.civl.abc.ast.entity.IF.Variable;
import dev.civl.abc.ast.node.IF.ASTNode;
import dev.civl.abc.ast.node.IF.IdentifierNode;
import dev.civl.abc.ast.node.IF.expression.AlignOfNode;
import dev.civl.abc.ast.node.IF.expression.ArrowNode;
import dev.civl.abc.ast.node.IF.expression.CastNode;
import dev.civl.abc.ast.node.IF.expression.CharacterConstantNode;
import dev.civl.abc.ast.node.IF.expression.CompoundLiteralNode;
import dev.civl.abc.ast.node.IF.expression.ConstantNode;
import dev.civl.abc.ast.node.IF.expression.DotNode;
import dev.civl.abc.ast.node.IF.expression.EnumerationConstantNode;
import dev.civl.abc.ast.node.IF.expression.ExpressionNode;
import dev.civl.abc.ast.node.IF.expression.IdentifierExpressionNode;
import dev.civl.abc.ast.node.IF.expression.OperatorNode;
import dev.civl.abc.ast.node.IF.expression.OperatorNode.Operator;
import dev.civl.abc.ast.node.IF.expression.SizeofNode;
import dev.civl.abc.ast.node.IF.expression.StringLiteralNode;
import dev.civl.abc.ast.type.IF.ArrayType;
import dev.civl.abc.ast.type.IF.Enumerator;
import dev.civl.abc.ast.type.IF.Field;
import dev.civl.abc.ast.type.IF.FloatingType;
import dev.civl.abc.ast.type.IF.IntegerType;
import dev.civl.abc.ast.type.IF.ObjectType;
import dev.civl.abc.ast.type.IF.PointerType;
import dev.civl.abc.ast.type.IF.StandardBasicType.BasicTypeKind;
import dev.civl.abc.ast.type.IF.StandardSignedIntegerType;
import dev.civl.abc.ast.type.IF.StandardSignedIntegerType.SignedIntKind;
import dev.civl.abc.ast.type.IF.StandardUnsignedIntegerType;
import dev.civl.abc.ast.type.IF.StandardUnsignedIntegerType.UnsignedIntKind;
import dev.civl.abc.ast.type.IF.StructureOrUnionType;
import dev.civl.abc.ast.type.IF.Type;
import dev.civl.abc.ast.type.IF.TypeFactory;
import dev.civl.abc.ast.value.IF.AddressValue;
import dev.civl.abc.ast.value.IF.ArrayElementReference;
import dev.civl.abc.ast.value.IF.ArrayValue;
import dev.civl.abc.ast.value.IF.CastValue;
import dev.civl.abc.ast.value.IF.CharacterValue;
import dev.civl.abc.ast.value.IF.ComplexFloatingValue;
import dev.civl.abc.ast.value.IF.FunctionReference;
import dev.civl.abc.ast.value.IF.IntegerValue;
import dev.civl.abc.ast.value.IF.MemberReference;
import dev.civl.abc.ast.value.IF.OperatorValue;
import dev.civl.abc.ast.value.IF.RealFloatingValue;
import dev.civl.abc.ast.value.IF.StringValue;
import dev.civl.abc.ast.value.IF.StructureValue;
import dev.civl.abc.ast.value.IF.TypeValue;
import dev.civl.abc.ast.value.IF.TypeValue.TypeValueKind;
import dev.civl.abc.ast.value.IF.UnionValue;
import dev.civl.abc.ast.value.IF.Value;
import dev.civl.abc.ast.value.IF.ValueFactory;
import dev.civl.abc.ast.value.IF.VariableReference;
import dev.civl.abc.config.IF.Configuration;
import dev.civl.abc.token.IF.ExecutionCharacter;
import dev.civl.abc.token.IF.StringLiteral;
import dev.civl.abc.token.IF.SyntaxException;
import dev.civl.abc.token.IF.UnsourcedException;
/**
* Flyweight pattern is used for those values which are immutable. Compound
* values are mutable.
*
* @author siegel
*
*/
public class CommonValueFactory implements ValueFactory {
// Fields...
private TypeFactory typeFactory;
private Map<Value, Value> valueMap = new HashMap<Value, Value>();
private StandardSignedIntegerType SINT;
private IntegerType CHAR;
private BigInteger MAX_JINT = new BigInteger(Integer.toString(Integer.MAX_VALUE));
private Value SINT_ONE, SINT_ZERO;
// Constructors...
public CommonValueFactory(Configuration configuration, TypeFactory typeFactory) {
this.typeFactory = typeFactory;
SINT = typeFactory.signedIntegerType(SignedIntKind.INT);
CHAR = (IntegerType) typeFactory.basicType(BasicTypeKind.CHAR);
SINT_ONE = integerValue(SINT, 1);
SINT_ZERO = integerValue(SINT, 0);
}
// Exported methods...
@Override
public Value evaluate(ExpressionNode expr) throws SyntaxException {
try {
return evaluateHelper(expr);
} catch (UnsourcedException err) {
throw error(err, expr);
}
}
/**
* Evaluates a constant expression.
*
* Should apply conversions to result.
*
* @param expr
* @return
* @throws SyntaxException
* @throws UnsourcedException if expr is not a constant expression
*/
private Value evaluateHelper(ExpressionNode expr) throws SyntaxException, UnsourcedException {
if (expr instanceof AlignOfNode) {
return alignofValue(((AlignOfNode) expr).getArgument().getType());
} else if (expr instanceof ArrowNode) {
ArrowNode arrowNode = (ArrowNode) expr;
ExpressionNode structOrUnionPointer = arrowNode.getStructurePointer();
Field[] navseq = arrowNode.getNavigationSequence();
Value value = evaluateDereference(structOrUnionPointer);
for (Field field : navseq)
value = evaluateMemberAccess(value, field);
return value;
} else if (expr instanceof CastNode) {
CastNode castNode = (CastNode) expr;
return evaluateCast(castNode.getCastType().getType(), evaluate(castNode.getArgument()));
} else if (expr instanceof CharacterConstantNode) {
return ((CharacterConstantNode) expr).getConstantValue();
} else if (expr instanceof CompoundLiteralNode) {
return evaluateCompoundLiteral((CompoundLiteralNode) expr);
} else if (expr instanceof ConstantNode) {
return ((ConstantNode) expr).getConstantValue();
} else if (expr instanceof DotNode) {
DotNode dotNode = (DotNode) expr;
ExpressionNode structOrUnion = dotNode.getStructure();
IdentifierNode fieldIdentifier = dotNode.getFieldName();
Field field = (Field) fieldIdentifier.getEntity();
Value structOrUnionValue = evaluate(structOrUnion);
return evaluateMemberAccess(structOrUnionValue, field);
} else if (expr instanceof OperatorNode) {
OperatorNode opNode = (OperatorNode) expr;
Operator operator = opNode.getOperator();
if (operator == Operator.ADDRESSOF)
return addressValue(opNode.getArgument(0));
else { // evaluate arguments and call apply
int numArgs = opNode.getNumberOfArguments();
Value[] argValues = new Value[numArgs];
Type type = expr.getInitialType();
for (int i = 0; i < numArgs; i++) {
ExpressionNode arg = opNode.getArgument(i);
Value argValue = evaluate(arg);
argValues[i] = applyConversions(arg, argValue);
}
return apply(type, operator, argValues);
}
} else if (expr instanceof SizeofNode) {
return sizeofValue((((SizeofNode) expr).getArgument()).getType());
} else if (expr instanceof StringLiteralNode) {
return ((StringLiteralNode) expr).getConstantValue();
} else if (expr instanceof EnumerationConstantNode) {
IdentifierNode identNode = ((EnumerationConstantNode) expr).getName();
Entity entity = identNode.getEntity();
if (entity.getEntityKind() == EntityKind.ENUMERATOR) {
return ((Enumerator) entity).getValue();
}
return null;
} else if (expr instanceof IdentifierExpressionNode) {
throw new UnsourcedException("Variable in constant expression");
}
return null;
}
@Override
public IntegerValue plusOne(IntegerValue value) {
return integerValue(value.getType(), value.getIntegerValue().add(BigInteger.ONE));
}
@Override
public AddressValue addressValue(ExpressionNode lhs) throws SyntaxException {
if (lhs instanceof IdentifierExpressionNode) {
Entity entity = ((IdentifierExpressionNode) lhs).getIdentifier().getEntity();
EntityKind kind = entity.getEntityKind();
if (kind == EntityKind.VARIABLE) {
return variableReference((Variable) entity);
} else if (kind == EntityKind.FUNCTION) {
return functionReference((Function) entity);
} else {
throw error("Operand of & not variable or function identifier", lhs);
}
} else if (lhs instanceof DotNode) {
AddressValue structureOrUnionReference = addressValue(((DotNode) lhs).getStructure());
Field field = (Field) ((DotNode) lhs).getFieldName().getEntity();
return memberReference(structureOrUnionReference, field);
} else if (lhs instanceof OperatorNode) {
OperatorNode opNode = (OperatorNode) lhs;
Operator operator = ((OperatorNode) lhs).getOperator();
if (operator == Operator.SUBSCRIPT) {
AddressValue arrayReference = addressValue(opNode.getArgument(0));
Value index = evaluate(opNode.getArgument(1));
return arrayElementReference(arrayReference, index);
} else if (operator == Operator.DEREFERENCE) {
return (AddressValue) evaluate(opNode.getArgument(0));
}
}
throw error("Cannot take address of expression", lhs);
}
@Override
public IntegerValue integerValue(IntegerType type, BigInteger integerValue) {
return (IntegerValue) canonic(new CommonIntegerValue(type, integerValue));
}
@Override
public IntegerValue integerValue(IntegerType type, int intValue) {
return integerValue(type, BigInteger.valueOf(intValue));
}
@Override
public RealFloatingValue realFloatingValue(FloatingType type, int radix, BigInteger wholePartValue,
BigInteger fractionPartValue, int fractionLength, BigInteger exponentValue) {
return (RealFloatingValue) canonic(new CommonRealFloatingValue(type, radix, wholePartValue, fractionPartValue,
fractionLength, exponentValue));
}
@Override
public ComplexFloatingValue complexFloatingValue(FloatingType type, RealFloatingValue realPart, RealFloatingValue imaginaryPart) {
return (ComplexFloatingValue) canonic(new CommonComplexFloatingValue(type, realPart, imaginaryPart));
}
@Override
public Value sizeofValue(Type type) {
return (TypeValue) canonic(new CommonTypeValue(typeFactory.size_t(), TypeValueKind.SIZEOF, type));
}
@Override
public TypeValue alignofValue(Type type) {
return (TypeValue) canonic(new CommonTypeValue(typeFactory.size_t(), TypeValueKind.ALIGNOF, type));
}
@Override
public CastValue castValue(Type castType, Value argument) {
return (CastValue) canonic(new CommonCastValue(castType, argument));
}
@Override
public OperatorValue operatorValue(Type type, Operator operator, Value[] arguments) {
return (OperatorValue) canonic(new CommonOperatorValue(type, operator, arguments));
}
@Override
public StructureValue newStructureValue(StructureOrUnionType type) {
return new CommonStructureValue(type);
}
@Override
public UnionValue newUnionValue(StructureOrUnionType unionType, Field field, Value memberValue) {
return (UnionValue) canonic(new CommonUnionValue(unionType, field, memberValue));
}
@Override
public ArrayValue newArrayValue(ArrayType type) {
return new CommonArrayValue(type);
}
@Override
public Answer isZero(Value value) {
return value.isZero();
}
@Override
public CharacterValue characterValue(ExecutionCharacter character) {
IntegerType type;
switch (character.getCharacterKind()) {
case CHAR:
type = CHAR;
break;
case WCHAR:
type = typeFactory.wchar_t();
break;
case CHAR16:
type = typeFactory.char16_t();
break;
case CHAR32:
type = typeFactory.char32_t();
break;
default:
throw new RuntimeException("unreachable");
}
return (CharacterValue) canonic(new CommonCharacterValue(type, character));
}
@Override
/**
* Precondition: string literal should already have the \0 appended. In
* particular, it has at least one character.
*
*/
public StringValue stringValue(StringLiteral literal) {
int length = literal.getNumCharacters();
IntegerValue size = integerValue(SINT, length);
IntegerType characterType;
ArrayType type;
switch (literal.getStringKind()) {
case CHAR:
case UTF_8:
characterType = CHAR;
break;
case WCHAR:
characterType = typeFactory.wchar_t();
break;
case CHAR16:
characterType = typeFactory.char16_t();
break;
case CHAR32:
characterType = typeFactory.char32_t();
break;
default:
throw new RuntimeException("unreachable");
}
type = typeFactory.arrayType(characterType, size);
return (StringValue) canonic(new CommonStringValue(type, literal));
}
public VariableReference variableReference(Variable variable) {
PointerType pointerType = typeFactory.pointerType(variable.getType());
return (VariableReference) canonic(new CommonVariableReference(pointerType, variable));
}
public FunctionReference functionReference(Function function) {
PointerType pointerType = typeFactory.pointerType(function.getType());
return (FunctionReference) canonic(new CommonFunctionReference(pointerType, function));
}
public ArrayElementReference arrayElementReference(AddressValue arrayReference, Value index) {
PointerType arrayReferenceType = arrayReference.getType();
ArrayType arrayType = (ArrayType) arrayReferenceType.referencedType();
// might need to strip qualifiers?
ObjectType elementType = arrayType.getElementType();
PointerType elementReferenceType = typeFactory.pointerType(elementType);
return (ArrayElementReference) canonic(
new CommonArrayElementReference(elementReferenceType, arrayReference, index));
}
public MemberReference memberReference(AddressValue structureOrUnionReference, Field field) {
ObjectType memberType = field.getType();
PointerType memberReferenceType = typeFactory.pointerType(memberType);
return (MemberReference) canonic(
new CommonMemberReference(memberReferenceType, structureOrUnionReference, field));
}
// Helper methods.......................................................
private Value canonic(Value value) {
Value result = valueMap.get(value);
if (result == null) {
valueMap.put(value, value);
return value;
}
return result;
}
/**
* Given expression e of pointer type, evaluate *e. If e had type [qualified]
* pointer to t, resulting value has type t.
*
* @param pointerExpression
* @return
*/
private Value evaluateDereference(ExpressionNode pointerExpression) throws SyntaxException {
return null; // how can this happen in a constant expression?
}
private Value evaluateCast(Type castType, Value value) throws UnsourcedException {
// TODO: cast concrete numeric types if you can, pointer types, ...
if (value == null)
return null;
if (castType.compatibleWith(value.getType()))
return value;
return canonic(new CommonCastValue(castType, value));
}
private Value evaluateCompoundLiteral(CompoundLiteralNode node) {
// TODO
return null;
}
private Value evalMinus(Type type, Value arg0) throws UnsourcedException {
if (arg0 instanceof IntegerValue) {
BigInteger big = ((IntegerValue) arg0).getIntegerValue();
BigInteger neg = big.negate();
Value result = integerValue((IntegerType) type, neg);
return result;
}
throw new UnsourcedException("Unsupported feature: non-integer negative");
}
private Value evalBinaryNumericOp(Type type, Operator operator, Value arg0, Value arg1) throws UnsourcedException {
Object val0, val1;
if (arg0 instanceof IntegerValue) {
val0 = ((IntegerValue) arg0).getIntegerValue();
} else if (arg0 instanceof RealFloatingValue) {
val0 = ((RealFloatingValue) arg0).getDoubleValue();
} else
throw new UnsourcedException("Expected integer or real constant, not " + arg0);
if (arg1 instanceof IntegerValue) {
val1 = ((IntegerValue) arg1).getIntegerValue();
} else if (arg1 instanceof RealFloatingValue) {
val1 = ((RealFloatingValue) arg1).getDoubleValue();
} else
throw new UnsourcedException("Expected integer or real constant, not " + arg1);
if (val0 instanceof BigInteger && val1 instanceof BigInteger) {
BigInteger big0 = ((BigInteger) val0);
BigInteger big1 = ((BigInteger) val1);
BigInteger bigVal;
switch (operator) {
case TIMES:
bigVal = big0.multiply(big1);
break;
case PLUS:
bigVal = big0.add(big1);
break;
case MINUS:
bigVal = big0.subtract(big1);
break;
case DIV:
bigVal = big0.divide(big1);
break;
case MOD:
bigVal = big0.mod(big1);
break;
default:
throw new UnsourcedException("Unexpected operator: " + operator);
}
return integerValue((IntegerType) type, bigVal);
} else {
throw new UnsourcedException("multiplication of floating constants");
}
}
/**
* Applies an operator to some arguments to yield a constant expression.
*
* @param type
* @param operator
* @param args
* @return
* @throws UnsourcedException if result is not a constant expression
*/
private Value apply(Type type, Operator operator, Value[] args) throws UnsourcedException {
int numArgs = args.length;
switch (operator) {
case BITAND: // & bit-wise and
case BITCOMPLEMENT: // ~ bit-wise complement
case BITOR: // | bit-wise inclusive or
case BITXOR: // ^ bit-wise exclusive or
case CONDITIONAL: // ?: the conditional operator
case DEREFERENCE: // * pointer dereference
case SUBSCRIPT: // [] array subscript
break;
case SHIFTLEFT: // << shift left
case SHIFTRIGHT: // >> shift right
case EQUALS: // == equality
case GT: // > greater than
case GTE: // >= greater than or equals
case LT: // < less than
case LTE: // <= less than or equals
case NEQ: // != not equals
if (numArgs == 2)
return evalBinaryIntegerOp(operator, args[0], args[1]);
else
throw new UnsourcedException("Expected two arguments for operator " + operator);
case LAND: // && logical and
if (numArgs == 2) {
Value lval = evalBinaryIntegerOp(Operator.EQUALS, args[0], SINT_ONE);
if (!lval.equals(SINT_ONE))
return SINT_ZERO;
Value rval = evalBinaryIntegerOp(Operator.EQUALS, args[0], SINT_ONE);
if (rval.equals(SINT_ONE))
return SINT_ONE;
else
return SINT_ZERO;
} else
throw new UnsourcedException("Expected two arguments for operator " + operator);
case LOR: // || logical or
if (numArgs == 2) {
Value lval = evalBinaryIntegerOp(Operator.EQUALS, args[0], SINT_ONE);
if (lval.equals(SINT_ONE))
return SINT_ONE;
Value rval = evalBinaryIntegerOp(Operator.EQUALS, args[0], SINT_ONE);
if (rval.equals(SINT_ONE))
return SINT_ONE;
else
return SINT_ZERO;
} else
throw new UnsourcedException("Expected two arguments for operator " + operator);
case NOT: // ! logical not
if (numArgs == 1)
return evalBinaryIntegerOp(Operator.EQUALS, args[0], SINT_ZERO);
else
throw new UnsourcedException("Expected one arguments for operator " + operator);
case PLUS: // + binary addition, numeric or pointer
case DIV: // / numerical division
case TIMES: // numeric multiplication
case MOD: // % integer modulus
case MINUS: // - binary subtraction (numbers and pointers)
if (numArgs == 2)
return evalBinaryNumericOp(type, operator, args[0], args[1]);
else
throw new UnsourcedException("Expected two arguments for operator " + operator);
case UNARYMINUS: // - numeric negative
return evalMinus(type, args[0]);
case UNARYPLUS: // + numeric no-op</li>
return args[0];
default:
throw new UnsourcedException("Illegal operator in constant expression: " + operator);
}
// TODO: handle specials cases for all of above
return canonic(new CommonOperatorValue(type, operator, args));
}
private Value applyConversions(ExpressionNode expr, Value value) {
// TODO
return value;
}
/**
*
* C11 Sec. 6.3.1.2: "When any scalar value is converted to _Bool, the result is
* 0 if the value compares equal to 0; otherwise, the result is 1."
*
* C11 Sec. 6.3.1.3:
*
* <blockquote> When a value with integer type is converted to another integer
* type other than _Bool, if the value can be represented by the new type, it is
* unchanged.
*
* Otherwise, if the new type is unsigned, the value is converted by repeatedly
* adding or subtracting one more than the maximum value that can be represented
* in the new type until the value is in the range of the new type.
*
* Otherwise, the new type is signed and the value cannot be represented in it;
* either the result is implementation-defined or an implementation-defined
* signal is raised. </blockquote>
*
*
* @param value
* @param newType
* @return
*/
@SuppressWarnings("unused")
private Value evaluateIntegerConversion(Value value, IntegerType newType) {
IntegerType oldType = (IntegerType) value.getType();
if (oldType.equals(newType))
return value;
if (value instanceof IntegerValue) {
BigInteger intVal = ((IntegerValue) value).getIntegerValue();
// first: if intVal representable in new type, that's it:
if (newType instanceof StandardSignedIntegerType) {
StandardSignedIntegerType newSigned = (StandardSignedIntegerType) newType;
if (newSigned.inMinimumRange(intVal)) {
return integerValue(newType, intVal);
} else if (oldType instanceof StandardSignedIntegerType) {
SignedIntKind newKind = newSigned.getIntKind();
SignedIntKind oldKind = ((StandardSignedIntegerType) oldType).getIntKind();
if (newKind.compareTo(oldKind) > 0)
return integerValue(newType, intVal);
}
} else if (newType instanceof StandardUnsignedIntegerType) {
StandardUnsignedIntegerType newSigned = (StandardUnsignedIntegerType) newType;
if (newSigned.inMinimumRange(intVal)) {
return integerValue(newType, intVal);
} else if (oldType instanceof StandardUnsignedIntegerType) {
UnsignedIntKind newKind = newSigned.getIntKind();
UnsignedIntKind oldKind = ((StandardUnsignedIntegerType) oldType).getIntKind();
if (newKind.compareTo(oldKind) > 0)
return integerValue(newType, intVal);
}
}
}
return castValue(newType, value);
}
// private Value evaluateAndorOr(Operator operator, ExpressionNode expr1,
// ExpressionNode expr2) throws SyntaxException {
// boolean isAnd = operator == Operator.LAND;
// Value v1 = evaluate(expr1);
//
// return null;
// }
/**
* Evaluates plus in case where both types are integers. NOTE types of these
* values must be converted types from expression.
*
* @param a1
* @param a2
* @return
*/
private Value evalBinaryIntegerOp(Operator operator, Value a1, Value a2) {
IntegerType type1 = (IntegerType) a1.getType();
IntegerType type;
switch (operator) {
case PLUS:
case TIMES:
case MINUS:
case DIV:
case SHIFTLEFT:
case SHIFTRIGHT:
type = type1;
break;
case EQUALS:
case LTE:
case GTE:
case NEQ:
case LT:
case GT:
type = SINT;
break;
default:
throw new RuntimeException("This method should not be called with operator " + operator);
}
if (a1.equals(a2)) {
switch (operator) {
case EQUALS:
case LTE:
case GTE:
return SINT_ONE;
case NEQ:
case LT:
case GT:
return SINT_ZERO;
default:
}
}
if (a1 instanceof IntegerValue && a2 instanceof IntegerValue) {
BigInteger v1 = ((IntegerValue) a1).getIntegerValue();
BigInteger v2 = ((IntegerValue) a2).getIntegerValue();
BigInteger v3 = null;
switch (operator) {
case PLUS:
v3 = v1.add(v2);
break;
case TIMES:
v3 = v1.multiply(v2);
break;
case MINUS:
v3 = v1.subtract(v2);
break;
case DIV:
v3 = v1.divide(v2);
break;
case EQUALS:
v3 = BigInteger.ZERO;
break;
case NEQ:
v3 = BigInteger.ONE;
break;
case LT:
v3 = v1.compareTo(v2) < 0 ? BigInteger.ONE : BigInteger.ZERO;
break;
case GT:
v3 = v1.compareTo(v2) > 0 ? BigInteger.ONE : BigInteger.ZERO;
break;
case LTE:
v3 = v1.compareTo(v2) <= 0 ? BigInteger.ONE : BigInteger.ZERO;
break;
case GTE:
v3 = v1.compareTo(v2) >= 0 ? BigInteger.ONE : BigInteger.ZERO;
break;
case SHIFTLEFT:
case SHIFTRIGHT:
if (v1.signum() >= 0 && v2.signum() >= 0 && MAX_JINT.compareTo(v2) >= 0) {
int v2small = v2.intValue();
if (operator == Operator.SHIFTLEFT)
v3 = v1.shiftLeft(v2small);
else
v3 = v1.shiftRight(v2small);
}
break;
default:
}
if (v3 != null && type instanceof StandardSignedIntegerType
&& ((StandardSignedIntegerType) type).inMinimumRange(v3)
|| type instanceof StandardUnsignedIntegerType
&& ((StandardUnsignedIntegerType) type).inMinimumRange(v3)) {
return integerValue(type, v3);
}
}
return operatorValue(type, operator, new Value[] { a1, a2 });
}
private Value evaluateMemberAccess(Value structureOrUnionValue, Field field) throws UnsourcedException {
if (structureOrUnionValue instanceof StructureValue) {
return ((StructureValue) structureOrUnionValue).getMember(field);
}
if (structureOrUnionValue instanceof UnionValue) {
UnionValue unionValue = (UnionValue) structureOrUnionValue;
Field unionField = unionValue.getField();
if (!unionField.equals(field))
throw new UnsourcedException(
"Union value field differs from requested field:\n" + unionField + "\n" + field);
return unionValue.getMemberValue();
}
// TODO: need to create a new dot value.
throw new UnsourcedException("Cannot evaluate structure or union value: " + structureOrUnionValue);
}
private SyntaxException error(String message, ASTNode node) {
return new SyntaxException(message, node.getSource());
}
private SyntaxException error(UnsourcedException e, ASTNode node) {
return new SyntaxException(e, node.getSource());
}
}