Search in sources :

Example 31 with SoyValue

use of com.google.template.soy.data.SoyValue in project closure-templates by google.

the class SimplifyExprVisitor method attemptPreeval.

// -----------------------------------------------------------------------------------------------
// Helpers.
/**
 * Attempts to preevaluate a node. If successful, the node is replaced with a new constant node in
 * the tree. If unsuccessful, the tree is not changed.
 */
private void attemptPreeval(ExprNode node) {
    // Note that we need to catch RenderException because preevaluation may fail, e.g. when
    // (a) the expression uses a bidi function that needs bidiGlobalDir to be in scope, but the
    // apiCallScope is not currently active,
    // (b) the expression uses an external function (Soy V1 syntax),
    // (c) other cases I haven't thought up.
    SoyValue preevalResult;
    try {
        preevalResult = preevalVisitor.exec(node);
    } catch (RenderException e) {
        // failed to preevaluate
        return;
    }
    PrimitiveNode newNode = InternalValueUtils.convertPrimitiveDataToExpr((PrimitiveData) preevalResult, node.getSourceLocation());
    if (newNode != null) {
        node.getParent().replaceChild(node, newNode);
    }
}
Also used : PrimitiveNode(com.google.template.soy.exprtree.ExprNode.PrimitiveNode) RenderException(com.google.template.soy.sharedpasses.render.RenderException) SoyValue(com.google.template.soy.data.SoyValue)

Example 32 with SoyValue

use of com.google.template.soy.data.SoyValue in project closure-templates by google.

the class EvalVisitor method visitNullSafeItemAccessNode.

private SoyValue visitNullSafeItemAccessNode(ItemAccessNode itemAccess) {
    SoyValue base = visitNullSafeNodeRecurse(itemAccess.getBaseExprChild());
    // attempting item access on non-SoyMap
    if (!(base instanceof SoyLegacyObjectMap || base instanceof SoyMap)) {
        if (base == NullSafetySentinel.INSTANCE) {
            // Bail out if base expression failed a null-safety check.
            return NullSafetySentinel.INSTANCE;
        }
        if (itemAccess.isNullSafe()) {
            if (isNullOrUndefinedBase(base)) {
                // Return the sentinel value that indicates that a null-safety check failed.
                return NullSafetySentinel.INSTANCE;
            } else {
                throw RenderException.create(String.format("While evaluating \"%s\", encountered non-map/list just before accessing \"%s\".", itemAccess.toSourceString(), itemAccess.getSourceStringSuffix()));
            }
        }
        // TODO: If feasible, find and fix existing instances, then throw RenderException here.
        return UndefinedData.INSTANCE;
    }
    // base is a valid SoyMap or SoyLegacyObjectMap: get value
    maybeMarkBadProtoAccess(itemAccess, base);
    SoyValue key = visit(itemAccess.getKeyExprChild());
    SoyType baseType = SoyTypes.tryRemoveNull(itemAccess.getBaseExprChild().getType());
    // We need to know whether to invoke the SoyMap or SoyLegacyObjectMap method.
    // An instanceof check on the runtime value of base is insufficient, since
    // DictImpl implements both interfaces. Instead, look at the declared type of the base
    // expression.
    boolean shouldUseNewMap = MapType.ANY_MAP.isAssignableFrom(baseType);
    SoyValue value = shouldUseNewMap ? ((SoyMap) base).get(key) : ((SoyLegacyObjectMap) base).getItem(key);
    if (value != null && !TofuTypeChecks.isInstance(itemAccess.getType(), value)) {
        throw RenderException.create(String.format("Expected value of type '%s', but actual type was '%s'.", itemAccess.getType(), value.getClass().getSimpleName()));
    }
    if (value != null) {
        return value;
    } else if (shouldUseNewMap) {
        // UndefinedData is a misfeature. The new map type should return null for failed lookups.
        return NullData.INSTANCE;
    } else {
        return UndefinedData.INSTANCE;
    }
}
Also used : SoyLegacyObjectMap(com.google.template.soy.data.SoyLegacyObjectMap) SoyType(com.google.template.soy.types.SoyType) SoyMap(com.google.template.soy.data.SoyMap) SoyValue(com.google.template.soy.data.SoyValue)

Example 33 with SoyValue

use of com.google.template.soy.data.SoyValue in project closure-templates by google.

the class EvalVisitor method visitLegacyObjectMapLiteralOrMapLiteralNode.

private SoyValue visitLegacyObjectMapLiteralOrMapLiteralNode(AbstractParentExprNode node) {
    checkState(node.getKind() == ExprNode.Kind.LEGACY_OBJECT_MAP_LITERAL_NODE || node.getKind() == ExprNode.Kind.MAP_LITERAL_NODE);
    int numItems = node.numChildren() / 2;
    boolean isStringKeyed = true;
    ExprNode firstNonstringKeyNode = null;
    List<SoyValue> keys = Lists.newArrayListWithCapacity(numItems);
    List<SoyValue> values = Lists.newArrayListWithCapacity(numItems);
    for (int i = 0; i < numItems; i++) {
        SoyValue key = visit(node.getChild(2 * i));
        if (isStringKeyed && !(key instanceof StringData)) {
            isStringKeyed = false;
            // temporary until we support nonstring key
            firstNonstringKeyNode = node.getChild(2 * i);
        }
        keys.add(key);
        values.add(visit(node.getChild(2 * i + 1)));
    }
    if (node.getKind() == ExprNode.Kind.LEGACY_OBJECT_MAP_LITERAL_NODE) {
        if (!isStringKeyed) {
            throw RenderException.create(String.format("legacy_object_map literals must have string keys (key \"%s\" in map %s does not " + "evaluate to a string).", firstNonstringKeyNode.toSourceString(), node.toSourceString()));
        }
        // Not an ImmutableMap, because map literals allow duplicate keys (last one wins).
        Map<String, SoyValue> map = new LinkedHashMap<>();
        for (int i = 0; i < numItems; i++) {
            map.put(keys.get(i).stringValue(), values.get(i));
        }
        return DictImpl.forProviderMap(map, RuntimeMapTypeTracker.Type.LEGACY_OBJECT_MAP_OR_RECORD);
    } else {
        ImmutableMap.Builder<SoyValue, SoyValue> builder = ImmutableMap.builder();
        for (int i = 0; i < numItems; ++i) {
            SoyValue key = keys.get(i);
            SoyValue value = values.get(i);
            if (isNullOrUndefinedBase(key)) {
                throw RenderException.create(String.format("null key in entry: null=%s", value));
            }
            builder.put(key, value);
        }
        return SoyMapImpl.forProviderMap(builder.build());
    }
}
Also used : AbstractParentExprNode(com.google.template.soy.exprtree.AbstractParentExprNode) ExprNode(com.google.template.soy.exprtree.ExprNode) StringData(com.google.template.soy.data.restricted.StringData) SoyValue(com.google.template.soy.data.SoyValue) ImmutableMap(com.google.common.collect.ImmutableMap) LinkedHashMap(java.util.LinkedHashMap)

Example 34 with SoyValue

use of com.google.template.soy.data.SoyValue in project closure-templates by google.

the class DictImplTest method testSoyValueMethods.

@Test
public void testSoyValueMethods() {
    SoyValue val1 = DictImpl.forProviderMap(ImmutableMap.of(), RuntimeMapTypeTracker.Type.UNKNOWN);
    // DictImpl is always truthy.
    assertThat(val1.coerceToBoolean()).isTrue();
    assertThat(val1.coerceToString()).isEqualTo("{}");
    SoyValue val2 = DictImpl.forProviderMap(ImmutableMap.of(), RuntimeMapTypeTracker.Type.UNKNOWN);
    // DictImpl uses object identity.
    assertThat(val1.equals(val2)).isFalse();
    SoyValue val3 = DictImpl.forProviderMap(ImmutableMap.<String, SoyValue>of("foo", FloatData.forValue(3.14), "too", BooleanData.TRUE), RuntimeMapTypeTracker.Type.UNKNOWN);
    assertThat(val3.coerceToBoolean()).isTrue();
    assertThat(val3.coerceToString()).isEqualTo("{foo: 3.14, too: true}");
}
Also used : SoyValue(com.google.template.soy.data.SoyValue) Test(org.junit.Test)

Example 35 with SoyValue

use of com.google.template.soy.data.SoyValue in project closure-templates by google.

the class MinFunctionTest method testComputeForJava.

@Test
public void testComputeForJava() {
    MinFunction minFunction = new MinFunction();
    SoyValue float0 = FloatData.forValue(7.5);
    SoyValue float1 = FloatData.forValue(7.777);
    assertThat(minFunction.computeForJava(ImmutableList.of(float0, float1))).isEqualTo(FloatData.forValue(7.5));
    SoyValue integer0 = IntegerData.forValue(-7);
    SoyValue integer1 = IntegerData.forValue(-8);
    assertThat(minFunction.computeForJava(ImmutableList.of(integer0, integer1))).isEqualTo(IntegerData.forValue(-8));
}
Also used : SoyValue(com.google.template.soy.data.SoyValue) Test(org.junit.Test)

Aggregations

SoyValue (com.google.template.soy.data.SoyValue)61 Test (org.junit.Test)31 StringData (com.google.template.soy.data.restricted.StringData)5 ExprNode (com.google.template.soy.exprtree.ExprNode)4 SoyLegacyObjectMap (com.google.template.soy.data.SoyLegacyObjectMap)3 SoyList (com.google.template.soy.data.SoyList)3 ParentExprNode (com.google.template.soy.exprtree.ExprNode.ParentExprNode)3 ImmutableMap (com.google.common.collect.ImmutableMap)2 SanitizedContentKind (com.google.template.soy.base.internal.SanitizedContentKind)2 SanitizedContent (com.google.template.soy.data.SanitizedContent)2 ContentKind (com.google.template.soy.data.SanitizedContent.ContentKind)2 SoyDataException (com.google.template.soy.data.SoyDataException)2 SoyDict (com.google.template.soy.data.SoyDict)2 SoyRecord (com.google.template.soy.data.SoyRecord)2 FloatData (com.google.template.soy.data.restricted.FloatData)2 IntegerData (com.google.template.soy.data.restricted.IntegerData)2 SoyString (com.google.template.soy.data.restricted.SoyString)2 UndefinedData (com.google.template.soy.data.restricted.UndefinedData)2 ExprRootNode (com.google.template.soy.exprtree.ExprRootNode)2 SoyPrintDirective (com.google.template.soy.shared.restricted.SoyPrintDirective)2