diff --git a/sjsonnet/src/sjsonnet/Materializer.scala b/sjsonnet/src/sjsonnet/Materializer.scala index 42a891bc..1fe40b6e 100644 --- a/sjsonnet/src/sjsonnet/Materializer.scala +++ b/sjsonnet/src/sjsonnet/Materializer.scala @@ -33,10 +33,7 @@ abstract class Materializer { case Val.False(_) => "false" case Val.Null(_) => "null" case Val.Num(_, _) => - val d = v.asDouble - val l = d.toLong - if (l.toDouble == d) java.lang.Long.toString(l) - else RenderUtils.renderDouble(d) + RenderUtils.renderDouble(v.asDouble) case _ => apply0(v, new sjsonnet.Renderer()).toString } } diff --git a/sjsonnet/src/sjsonnet/Renderer.scala b/sjsonnet/src/sjsonnet/Renderer.scala index 5f925330..54069186 100644 --- a/sjsonnet/src/sjsonnet/Renderer.scala +++ b/sjsonnet/src/sjsonnet/Renderer.scala @@ -268,12 +268,18 @@ final case class MaterializeJsonRenderer( object RenderUtils { + // Pre-cached string representations of small integers (0-255) + private val intStrCache: Array[String] = Array.tabulate(256)(_.toString) + /** * Custom rendering of Doubles used in rendering */ def renderDouble(d: Double): String = { - if (d.toLong == d) d.toLong.toString - else if (d % 1 == 0) { + val l = d.toLong + if (l.toDouble == d) { + if (l >= 0 && l < 256) intStrCache(l.toInt) + else l.toString + } else if (d % 1 == 0) { BigDecimal(d).setScale(0, BigDecimal.RoundingMode.HALF_EVEN).toBigInt.toString() } else d.toString } diff --git a/sjsonnet/src/sjsonnet/Val.scala b/sjsonnet/src/sjsonnet/Val.scala index c717c93c..9377aabc 100644 --- a/sjsonnet/src/sjsonnet/Val.scala +++ b/sjsonnet/src/sjsonnet/Val.scala @@ -1869,6 +1869,15 @@ object Val { tailstrictMode: TailstrictMode): Val = if (namedNames == null && argVals.length == 1) evalRhs(argVals(0).value, ev, outerPos) else super.apply(argVals, namedNames, outerPos) + + override def apply1(argVal: Eval, outerPos: Position)(implicit + ev: EvalScope, + tailstrictMode: TailstrictMode): Val = + if (params.names.length != 1) apply(Array(argVal), null, outerPos) + else { + if (tailstrictMode == TailstrictModeEnabled) argVal.value + evalRhs(argVal.value, ev, outerPos) + } } abstract class Builtin2(fn: String, pn1: String, pn2: String, defs: Array[Expr] = null) @@ -1912,6 +1921,19 @@ object Val { if (namedNames == null && argVals.length == 3) evalRhs(argVals(0).value, argVals(1).value, argVals(2).value, ev, outerPos) else super.apply(argVals, namedNames, outerPos) + + override def apply3(argVal1: Eval, argVal2: Eval, argVal3: Eval, outerPos: Position)(implicit + ev: EvalScope, + tailstrictMode: TailstrictMode): Val = + if (params.names.length != 3) apply(Array(argVal1, argVal2, argVal3), null, outerPos) + else { + if (tailstrictMode == TailstrictModeEnabled) { + argVal1.value + argVal2.value + argVal3.value + } + evalRhs(argVal1.value, argVal2.value, argVal3.value, ev, outerPos) + } } abstract class Builtin4(