Skip to content

Commit 0fbfdbd

Browse files
authored
chore: Make aggressive optimization default (#643)
Address @stephenamar-db 's comment in #628
1 parent 725f287 commit 0fbfdbd

9 files changed

Lines changed: 384 additions & 1088 deletions

File tree

sjsonnet/src/sjsonnet/Expr.scala

Lines changed: 59 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,17 @@ import scala.collection.immutable.IntMap
1212
* into the file that is later used to provide error messages.
1313
*/
1414
trait Expr {
15-
def pos: Position
15+
16+
/**
17+
* Source position of this expression, used for error messages.
18+
*
19+
* This is a `var` (not `val` or `def`) so that [[StaticOptimizer]] can update positions in-place
20+
* when it replaces an expression with a sub-expression (e.g. branch elimination:
21+
* `IfElse(pos, true, thenExpr, _)` → `thenExpr` with `thenExpr.pos = pos`). Without mutable
22+
* `pos`, the optimizer would need to wrap the result in a `LocalExpr` just to carry the original
23+
* position, adding unnecessary AST nodes. Do not change this to `val` or `def`.
24+
*/
25+
var pos: Position
1626
private[sjsonnet] def tag: Byte = ExprTags.UNTAGGED
1727

1828
/** The name of this expression type to be shown in error messages */
@@ -60,26 +70,26 @@ object Expr {
6070
if (a == null) "null" else a.mkString("[", ", ", "]")
6171
}
6272

63-
final case class Self(pos: Position) extends Expr {
73+
final case class Self(var pos: Position) extends Expr {
6474
final override private[sjsonnet] def tag = ExprTags.Self
6575
}
66-
final case class Super(pos: Position) extends Expr {
76+
final case class Super(var pos: Position) extends Expr {
6777
final override private[sjsonnet] def tag = ExprTags.Super
6878
}
69-
final case class $(pos: Position) extends Expr {
79+
final case class $(var pos: Position) extends Expr {
7080
final override private[sjsonnet] def tag = ExprTags.`$`
7181
}
7282

73-
final case class Id(pos: Position, name: String) extends Expr {
83+
final case class Id(var pos: Position, name: String) extends Expr {
7484
final override private[sjsonnet] def tag = ExprTags.Id
7585
override def exprErrorString: String = s"${super.exprErrorString} $name"
7686
}
7787

78-
final case class ValidId(pos: Position, name: String, nameIdx: Int) extends Expr {
88+
final case class ValidId(var pos: Position, name: String, nameIdx: Int) extends Expr {
7989
final override private[sjsonnet] def tag = ExprTags.ValidId
8090
override def exprErrorString: String = s"${super.exprErrorString} $name"
8191
}
82-
final case class Arr(pos: Position, value: Array[Expr]) extends Expr {
92+
final case class Arr(var pos: Position, value: Array[Expr]) extends Expr {
8393
final override private[sjsonnet] def tag = ExprTags.Arr
8494
override def toString: String = s"Arr($pos, ${arrStr(value)})"
8595
}
@@ -101,7 +111,7 @@ object Expr {
101111
case object Unhide extends Visibility
102112
}
103113
final case class Field(
104-
pos: Position,
114+
var pos: Position,
105115
fieldName: FieldName,
106116
plus: Boolean, // see https://jsonnet.org/ref/language.html#nested-field-inheritance
107117
args: Params,
@@ -120,7 +130,7 @@ object Expr {
120130
override def toString: String = s"Params(${arrStr(names)}, ${arrStr(defaultExprs)})"
121131
}
122132

123-
final case class UnaryOp(pos: Position, op: Int, value: Expr) extends Expr {
133+
final case class UnaryOp(var pos: Position, op: Int, value: Expr) extends Expr {
124134
final override private[sjsonnet] def tag = ExprTags.UnaryOp
125135
override def exprErrorString: String = s"${super.exprErrorString} ${UnaryOp.name(op)}"
126136
}
@@ -132,13 +142,13 @@ object Expr {
132142
private val names = IntMap(OP_! -> "!", OP_- -> "-", OP_~ -> "~", OP_+ -> "+")
133143
def name(op: Int): String = names.getOrElse(op, "<unknown>")
134144
}
135-
final case class And(pos: Position, lhs: Expr, rhs: Expr) extends Expr {
145+
final case class And(var pos: Position, lhs: Expr, rhs: Expr) extends Expr {
136146
final override private[sjsonnet] def tag = ExprTags.And
137147
}
138-
final case class Or(pos: Position, lhs: Expr, rhs: Expr) extends Expr {
148+
final case class Or(var pos: Position, lhs: Expr, rhs: Expr) extends Expr {
139149
final override private[sjsonnet] def tag = ExprTags.Or
140150
}
141-
final case class BinaryOp(pos: Position, lhs: Expr, op: Int, rhs: Expr) extends Expr {
151+
final case class BinaryOp(var pos: Position, lhs: Expr, op: Int, rhs: Expr) extends Expr {
142152
final override private[sjsonnet] def tag = ExprTags.BinaryOp
143153
override def exprErrorString: String = s"${super.exprErrorString} ${BinaryOp.name(op)}"
144154
}
@@ -185,11 +195,12 @@ object Expr {
185195
)
186196
def name(op: Int): String = names.getOrElse(op, "<unknown>")
187197
}
188-
final case class AssertExpr(pos: Position, asserted: Member.AssertStmt, returned: Expr)
198+
final case class AssertExpr(var pos: Position, asserted: Member.AssertStmt, returned: Expr)
189199
extends Expr {
190200
final override private[sjsonnet] def tag = ExprTags.AssertExpr
191201
}
192-
final case class LocalExpr(pos: Position, bindings: Array[Bind], returned: Expr) extends Expr {
202+
final case class LocalExpr(var pos: Position, bindings: Array[Bind], returned: Expr)
203+
extends Expr {
193204
final override private[sjsonnet] def tag = ExprTags.LocalExpr
194205
override def toString: String = s"LocalExpr($pos, ${arrStr(bindings)}, $returned)"
195206
override def equals(o: Any): Boolean = o match {
@@ -202,21 +213,21 @@ object Expr {
202213
}
203214
}
204215

205-
final case class Bind(pos: Position, name: String, args: Params, rhs: Expr) extends Member
206-
final case class Import(pos: Position, value: String) extends Expr {
216+
final case class Bind(var pos: Position, name: String, args: Params, rhs: Expr) extends Member
217+
final case class Import(var pos: Position, value: String) extends Expr {
207218
final override private[sjsonnet] def tag = ExprTags.Import
208219
}
209-
final case class ImportStr(pos: Position, value: String) extends Expr {
220+
final case class ImportStr(var pos: Position, value: String) extends Expr {
210221
final override private[sjsonnet] def tag = ExprTags.ImportStr
211222
}
212-
final case class ImportBin(pos: Position, value: String) extends Expr {
223+
final case class ImportBin(var pos: Position, value: String) extends Expr {
213224
final override private[sjsonnet] def tag = ExprTags.ImportBin
214225
}
215-
final case class Error(pos: Position, value: Expr) extends Expr {
226+
final case class Error(var pos: Position, value: Expr) extends Expr {
216227
final override private[sjsonnet] def tag = ExprTags.Error
217228
}
218229
final case class Apply(
219-
pos: Position,
230+
var pos: Position,
220231
value: Expr,
221232
args: Array[Expr],
222233
namedNames: Array[String],
@@ -225,23 +236,23 @@ object Expr {
225236
final override private[sjsonnet] def tag = ExprTags.Apply
226237
override def exprErrorString: String = Expr.callTargetName(value)
227238
}
228-
final case class Apply0(pos: Position, value: Expr, tailstrict: Boolean)
239+
final case class Apply0(var pos: Position, value: Expr, tailstrict: Boolean)
229240
extends TailstrictableExpr {
230241
final override private[sjsonnet] def tag = ExprTags.Apply0
231242
override def exprErrorString: String = Expr.callTargetName(value)
232243
}
233-
final case class Apply1(pos: Position, value: Expr, a1: Expr, tailstrict: Boolean)
244+
final case class Apply1(var pos: Position, value: Expr, a1: Expr, tailstrict: Boolean)
234245
extends TailstrictableExpr {
235246
final override private[sjsonnet] def tag = ExprTags.Apply1
236247
override def exprErrorString: String = Expr.callTargetName(value)
237248
}
238-
final case class Apply2(pos: Position, value: Expr, a1: Expr, a2: Expr, tailstrict: Boolean)
249+
final case class Apply2(var pos: Position, value: Expr, a1: Expr, a2: Expr, tailstrict: Boolean)
239250
extends TailstrictableExpr {
240251
final override private[sjsonnet] def tag = ExprTags.Apply2
241252
override def exprErrorString: String = Expr.callTargetName(value)
242253
}
243254
final case class Apply3(
244-
pos: Position,
255+
var pos: Position,
245256
value: Expr,
246257
a1: Expr,
247258
a2: Expr,
@@ -252,26 +263,30 @@ object Expr {
252263
override def exprErrorString: String = Expr.callTargetName(value)
253264
}
254265
final case class ApplyBuiltin(
255-
pos: Position,
266+
var pos: Position,
256267
func: Val.Builtin,
257268
argExprs: Array[Expr],
258269
tailstrict: Boolean)
259270
extends TailstrictableExpr {
260271
final override private[sjsonnet] def tag = ExprTags.ApplyBuiltin
261272
override def exprErrorString: String = func.qualifiedName
262273
}
263-
final case class ApplyBuiltin0(pos: Position, func: Val.Builtin0, tailstrict: Boolean)
274+
final case class ApplyBuiltin0(var pos: Position, func: Val.Builtin0, tailstrict: Boolean)
264275
extends TailstrictableExpr {
265276
final override private[sjsonnet] def tag = ExprTags.ApplyBuiltin0
266277
override def exprErrorString: String = func.qualifiedName
267278
}
268-
final case class ApplyBuiltin1(pos: Position, func: Val.Builtin1, a1: Expr, tailstrict: Boolean)
279+
final case class ApplyBuiltin1(
280+
var pos: Position,
281+
func: Val.Builtin1,
282+
a1: Expr,
283+
tailstrict: Boolean)
269284
extends TailstrictableExpr {
270285
final override private[sjsonnet] def tag = ExprTags.ApplyBuiltin1
271286
override def exprErrorString: String = func.qualifiedName
272287
}
273288
final case class ApplyBuiltin2(
274-
pos: Position,
289+
var pos: Position,
275290
func: Val.Builtin2,
276291
a1: Expr,
277292
a2: Expr,
@@ -281,7 +296,7 @@ object Expr {
281296
override def exprErrorString: String = func.qualifiedName
282297
}
283298
final case class ApplyBuiltin3(
284-
pos: Position,
299+
var pos: Position,
285300
func: Val.Builtin3,
286301
a1: Expr,
287302
a2: Expr,
@@ -292,7 +307,7 @@ object Expr {
292307
override def exprErrorString: String = func.qualifiedName
293308
}
294309
final case class ApplyBuiltin4(
295-
pos: Position,
310+
var pos: Position,
296311
func: Val.Builtin4,
297312
a1: Expr,
298313
a2: Expr,
@@ -303,56 +318,56 @@ object Expr {
303318
override private[sjsonnet] def tag = ExprTags.ApplyBuiltin4
304319
override def exprErrorString: String = func.qualifiedName
305320
}
306-
final case class Select(pos: Position, value: Expr, name: String) extends Expr {
321+
final case class Select(var pos: Position, value: Expr, name: String) extends Expr {
307322
final override private[sjsonnet] def tag = ExprTags.Select
308323
override def exprErrorString: String = s"${super.exprErrorString} $name"
309324
}
310-
final case class SelectSuper(pos: Position, selfIdx: Int, name: String) extends Expr {
325+
final case class SelectSuper(var pos: Position, selfIdx: Int, name: String) extends Expr {
311326
final override private[sjsonnet] def tag = ExprTags.SelectSuper
312327
override def exprErrorString: String = s"${super.exprErrorString} $name"
313328
}
314-
final case class InSuper(pos: Position, value: Expr, selfIdx: Int) extends Expr {
329+
final case class InSuper(var pos: Position, value: Expr, selfIdx: Int) extends Expr {
315330
final override private[sjsonnet] def tag = ExprTags.InSuper
316331
}
317-
final case class Lookup(pos: Position, value: Expr, index: Expr) extends Expr {
332+
final case class Lookup(var pos: Position, value: Expr, index: Expr) extends Expr {
318333
final override private[sjsonnet] def tag = ExprTags.Lookup
319334
}
320-
final case class LookupSuper(pos: Position, selfIdx: Int, index: Expr) extends Expr {
335+
final case class LookupSuper(var pos: Position, selfIdx: Int, index: Expr) extends Expr {
321336
final override private[sjsonnet] def tag = ExprTags.LookupSuper
322337
}
323338
final case class Slice(
324-
pos: Position,
339+
var pos: Position,
325340
value: Expr,
326341
start: Option[Expr],
327342
end: Option[Expr],
328343
stride: Option[Expr])
329344
extends Expr {
330345
final override private[sjsonnet] def tag = ExprTags.Slice
331346
}
332-
final case class Function(pos: Position, params: Params, body: Expr) extends Expr {
347+
final case class Function(var pos: Position, params: Params, body: Expr) extends Expr {
333348
final override private[sjsonnet] def tag = ExprTags.Function
334349
}
335-
final case class IfElse(pos: Position, cond: Expr, `then`: Expr, `else`: Expr) extends Expr {
350+
final case class IfElse(var pos: Position, cond: Expr, `then`: Expr, `else`: Expr) extends Expr {
336351
final override private[sjsonnet] def tag = ExprTags.IfElse
337352
}
338353

339354
sealed trait CompSpec extends Expr
340-
final case class IfSpec(pos: Position, cond: Expr) extends CompSpec
341-
final case class ForSpec(pos: Position, name: String, cond: Expr) extends CompSpec
355+
final case class IfSpec(var pos: Position, cond: Expr) extends CompSpec
356+
final case class ForSpec(var pos: Position, name: String, cond: Expr) extends CompSpec
342357

343-
final case class Comp(pos: Position, value: Expr, first: ForSpec, rest: Array[CompSpec])
358+
final case class Comp(var pos: Position, value: Expr, first: ForSpec, rest: Array[CompSpec])
344359
extends Expr {
345360
final override private[sjsonnet] def tag = ExprTags.Comp
346361
override def exprErrorString: String = "array comprehension"
347362
}
348-
final case class ObjExtend(pos: Position, base: Expr, ext: ObjBody) extends Expr {
363+
final case class ObjExtend(var pos: Position, base: Expr, ext: ObjBody) extends Expr {
349364
final override private[sjsonnet] def tag = ExprTags.ObjExtend
350365
}
351366

352367
trait ObjBody extends Expr
353368
object ObjBody {
354369
final case class MemberList(
355-
pos: Position,
370+
var pos: Position,
356371
binds: Array[Bind],
357372
fields: Array[Member.Field],
358373
asserts: Array[Member.AssertStmt])
@@ -362,7 +377,7 @@ object Expr {
362377
s"MemberList($pos, ${arrStr(binds)}, ${arrStr(fields)}, ${arrStr(asserts)})"
363378
}
364379
final case class ObjComp(
365-
pos: Position,
380+
var pos: Position,
366381
preLocals: Array[Bind],
367382
key: Expr,
368383
value: Expr,

sjsonnet/src/sjsonnet/ScopedExprTransform.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class ScopedExprTransform extends ExprTransform {
1313

1414
// Marker for Exprs in the scope that should not be used because they need to be evaluated in a different scope
1515
val dynamicExpr: Expr = new Expr {
16-
def pos: Position = ???; override def toString = "dynamicExpr"
16+
var pos: Position = null; override def toString = "dynamicExpr"
1717
}
1818

1919
def transform(e: Expr): Expr = e match {

sjsonnet/src/sjsonnet/Settings.scala

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,7 @@ final case class Settings(
1313
brokenAssertionLogic: Boolean = false,
1414
maxMaterializeDepth: Int = 1000,
1515
materializeRecursiveDepthLimit: Int = 128,
16-
maxStack: Int = 500,
17-
/**
18-
* Enable aggressive static optimizations in the optimization phase, including: constant folding
19-
* for arithmetic, comparison, bitwise, and shift operators; branch elimination for if-else with
20-
* constant conditions; short-circuit elimination for And/Or with constant lhs. These reduce AST
21-
* node count, benefiting long-running Jsonnet programs.
22-
*/
23-
aggressiveStaticOptimization: Boolean = false
16+
maxStack: Int = 500
2417
)
2518

2619
object Settings {

0 commit comments

Comments
 (0)