Skip to content

Commit

Permalink
Merge pull request #88 from szeiger/issue/87
Browse files Browse the repository at this point in the history
Add strict mode
  • Loading branch information
szeiger authored Aug 25, 2020
2 parents 0eaea66 + fc657aa commit dd62b1d
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 11 deletions.
8 changes: 7 additions & 1 deletion sjsonnet/src-jvm/sjsonnet/Cli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ object Cli{
varBinding: Map[String, ujson.Value] = Map(),
tlaBinding: Map[String, ujson.Value] = Map(),
indent: Int = 3,
preserveOrder: Boolean = false)
preserveOrder: Boolean = false,
strict: Boolean = false)


def genericSignature(wd: os.Path) = Seq(
Expand Down Expand Up @@ -134,6 +135,11 @@ object Cli{
"Preserves order of keys in the resulting JSON",
(c, v) => c.copy(preserveOrder = true)
),
Arg[Config, Unit](
"strict", None,
"Enforce some additional syntax limitations",
(c, v) => c.copy(strict = true)
),

)
def showArg(arg: Arg[_, _]) =
Expand Down
3 changes: 2 additions & 1 deletion sjsonnet/src-jvm/sjsonnet/SjsonnetMain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ object SjsonnetMain {
config.jpaths.map(os.Path(_, wd)).map(OsPath(_)),
allowedInputs
),
config.preserveOrder
preserveOrder = config.preserveOrder,
strict = config.strict
)

def handleWriteFile[T](f: => T): Either[String, T] =
Expand Down
11 changes: 10 additions & 1 deletion sjsonnet/src/sjsonnet/Evaluator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ class Evaluator(parseCache: collection.mutable.Map[String, fastparse.Parsed[(Exp
val extVars: Map[String, ujson.Value],
val wd: Path,
importer: (Path, String) => Option[(Path, String)],
override val preserveOrder: Boolean = false) extends EvalScope{
override val preserveOrder: Boolean = false,
strict: Boolean) extends EvalScope{
implicit def evalScope: EvalScope = this

val loadedFileContents = mutable.Map.empty[Path, String]
Expand Down Expand Up @@ -80,12 +81,20 @@ class Evaluator(parseCache: collection.mutable.Map[String, fastparse.Parsed[(Exp
case Comp(offset, value, first, rest) =>
Val.Arr(visitComp(first :: rest.toList, Seq(scope)).map(s => Val.Lazy(visitExpr(value)(s, implicitly))))
case ObjExtend(offset, value, ext) => {
if(strict && isObjLiteral(value))
Error.fail("Adjacent object literals not allowed in strict mode - Use '+' to concatenate objects", offset)
val original = visitExpr(value).cast[Val.Obj]
val extension = visitObjBody(ext)
extension.addSuper(original)
}
} catch Error.tryCatch(expr.offset)

private def isObjLiteral(expr: Expr): Boolean = expr match {
case _: Obj => true
case _: ObjExtend => true
case _ => false
}

def visitId(offset: Int, value: Int)(implicit scope: ValScope, fileScope: FileScope): Val = {
val ref = scope.bindings(value)
.getOrElse(
Expand Down
6 changes: 3 additions & 3 deletions sjsonnet/src/sjsonnet/Expr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ object Expr{
sealed trait Visibility
object Visibility{

object Normal extends Visibility
object Hidden extends Visibility
object Unhide extends Visibility
case object Normal extends Visibility
case object Hidden extends Visibility
case object Unhide extends Visibility
}
case class Field(offset: Int,
fieldName: FieldName,
Expand Down
6 changes: 4 additions & 2 deletions sjsonnet/src/sjsonnet/Interpreter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ class Interpreter(parseCache: collection.mutable.Map[String, fastparse.Parsed[(E
tlaVars: Map[String, ujson.Value],
wd: Path,
importer: (Path, String) => Option[(Path, String)],
preserveOrder: Boolean = false) {
preserveOrder: Boolean = false,
strict: Boolean = true) {

val evaluator = new Evaluator(
parseCache,
extVars,
wd,
importer,
preserveOrder
preserveOrder,
strict
)

def interpret(txt: String, path: Path): Either[String, ujson.Value] = {
Expand Down
27 changes: 24 additions & 3 deletions sjsonnet/test/src/sjsonnet/EvaluatorTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,28 @@ package sjsonnet

import utest._
object EvaluatorTests extends TestSuite{
def eval(s: String) = {
def interpret(s: String, strict: Boolean) =
new Interpreter(
SjsonnetMain.createParseCache(),
Map(),
Map(),
DummyPath(),
(_, _) => None
).interpret(s, DummyPath("(memory)")) match{
(_, _) => None,
strict = strict
).interpret(s, DummyPath("(memory)"))
def eval(s: String, strict: Boolean = false) = {
interpret(s, strict) match{
case Right(x) => x
case Left(e) => throw new Exception(e)
}
}
def evalErr(s: String, strict: Boolean = false) = {
interpret(s, strict) match{
case Right(x) => throw new Exception(s"Expected exception, got result: $x")
case Left(e) =>
e.split('\n').map(_.trim).mkString("\n") // normalize inconsistent indenation on JVM vs JS
}
}
def tests = Tests{
test("arithmetic") {
eval("1 + 2 + 3") ==> ujson.Num(6)
Expand Down Expand Up @@ -300,5 +310,16 @@ object EvaluatorTests extends TestSuite{
eval("'%--+5.5f' % -123.456") ==> ujson.Str("-123.45600")
eval("'%#-0- + 5.5f' % -123.456") ==> ujson.Str("-123.45600")
}
test("strict") {
eval("({ a: 1 } { b: 2 }).a", false) ==> ujson.Num(1)
evalErr("({ a: 1 } { b: 2 }).a", true) ==>
"""sjsonnet.Error: Adjacent object literals not allowed in strict mode - Use '+' to concatenate objects
|at .(:1:11)""".stripMargin
eval("local x = { c: 3 }; (x { a: 1 } { b: 2 }).a", false) ==> ujson.Num(1)
eval("local x = { c: 3 }; (x { a: 1 }).a", true) ==> ujson.Num(1)
evalErr("local x = { c: 3 }; ({ a: 1 } { b: 2 }).a", true) ==>
"""sjsonnet.Error: Adjacent object literals not allowed in strict mode - Use '+' to concatenate objects
|at .(:1:31)""".stripMargin
}
}
}

0 comments on commit dd62b1d

Please # to comment.