Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions bench/src/main/scala/sjsonnet/MainBenchmark.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ object MainBenchmark {
Map.empty[String, String],
Map.empty[String, String],
OsPath(wd),
importer = SjsonnetMain
importer = SjsonnetMainBase
.resolveImport(config.getOrderedJpaths.map(os.Path(_, wd)).map(OsPath(_)), None),
parseCache = parseCache
)
Expand Down Expand Up @@ -65,7 +65,7 @@ class MainBenchmark {
@Benchmark
def main(bh: Blackhole): Unit = {
bh.consume(
SjsonnetMain.main0(
SjsonnetMainBase.main0(
MainBenchmark.mainArgs,
new DefaultParseCache,
System.in,
Expand Down Expand Up @@ -102,7 +102,7 @@ object MemoryBenchmark {
} else {
false
}
SjsonnetMain.main0(
SjsonnetMainBase.main0(
MainBenchmark.mainArgs,
cache,
System.in,
Expand Down
2 changes: 1 addition & 1 deletion bench/src/main/scala/sjsonnet/MaterializerBenchmark.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class MaterializerBenchmark {
Map.empty[String, String],
Map.empty[String, String],
OsPath(wd),
importer = SjsonnetMain
importer = SjsonnetMainBase
.resolveImport(
config.getOrderedJpaths.map(os.Path(_, wd)).map(OsPath(_)).toIndexedSeq,
None
Expand Down
2 changes: 1 addition & 1 deletion bench/src/main/scala/sjsonnet/MultiThreadedBenchmark.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class MultiThreadedBenchmark {
pool.submit {
(() =>
if (
SjsonnetMain.main0(
SjsonnetMainBase.main0(
MainBenchmark.mainArgs,
cache, // new DefaultParseCache
System.in,
Expand Down
2 changes: 1 addition & 1 deletion bench/src/main/scala/sjsonnet/RunProfiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ object RunProfiler extends App {
Map.empty[String, String],
Map.empty[String, String],
OsPath(wd),
importer = SjsonnetMain
importer = SjsonnetMainBase
.resolveImport(config.getOrderedJpaths.map(os.Path(_, wd)).map(OsPath(_)).toIndexedSeq, None),
parseCache = parseCache
) {
Expand Down
3 changes: 2 additions & 1 deletion build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ object sjsonnet extends VersionFileModule {
def jsEnvConfig = JsEnvConfig.NodeJs(args = List("--stack-size=" + stackSizekBytes))
def resources = T.sources(
this.millSourcePath / "resources" / "test_suite",
this.millSourcePath / "resources" / "go_test_suite"
this.millSourcePath / "resources" / "go_test_suite",
this.millSourcePath / "resources" / "new_test_suite",
)
def generatedSources = T {
resources().map(_.path).flatMap { testSuite =>
Expand Down
2 changes: 1 addition & 1 deletion sjsonnet/server/src/sjsonnet/SjsonnetServerMain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ object SjsonnetServerMain extends SjsonnetServerMain[DefaultParseCache] {
scala.Console.withIn(stdin) {
scala.Console.withOut(stdout) {
scala.Console.withErr(stderr) {
sjsonnet.SjsonnetMain.main0(args, stateCache2, stdin, stdout, stderr, wd) == 0
sjsonnet.SjsonnetMainBase.main0(args, stateCache2, stdin, stdout, stderr, wd) == 0
}
}
}
Expand Down
17 changes: 0 additions & 17 deletions sjsonnet/src-js/sjsonnet/Platform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,11 @@ package sjsonnet

import org.virtuslab.yaml.*

import java.io.File
import java.util
import java.util.regex.Pattern
import scala.collection.mutable

object Platform {
def gzipBytes(s: Array[Byte]): String = {
throw new Exception("GZip not implemented in Scala.js")
}
def gzipString(s: String): String = {
throw new Exception("GZip not implemented in Scala.js")
}
def xzBytes(s: Array[Byte], compressionLevel: Option[Int]): String = {
throw new Exception("XZ not implemented in Scala.js")
}
def xzString(s: String, compressionLevel: Option[Int]): String = {
throw new Exception("XZ not implemented in Scala.js")
}

private def nodeToJson(node: Node): ujson.Value = node match {
case _: Node.ScalarNode =>
YamlDecoder.forAny.construct(node).getOrElse("") match {
Expand Down Expand Up @@ -98,9 +84,6 @@ object Platform {
def sha3(s: String): String = {
throw new Exception("SHA3 not implemented in Scala.js")
}
def hashFile(file: File): String = {
throw new Exception("hashFile not implemented in Scala.js")
}

private val regexCache = new util.concurrent.ConcurrentHashMap[String, Pattern]
private val namedGroupPattern = Pattern.compile("\\(\\?<(.+?)>.*?\\)")
Expand Down
5 changes: 4 additions & 1 deletion sjsonnet/src-js/sjsonnet/SjsonnetMain.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package sjsonnet

import sjsonnet.stdlib.NativeRegex

import scala.collection.mutable
import scala.scalajs.js
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
Expand Down Expand Up @@ -39,7 +41,8 @@ object SjsonnetMain {
}
},
parseCache = new DefaultParseCache,
new Settings(preserveOrder = preserveOrder)
settings = new Settings(preserveOrder = preserveOrder),
std = new Std(nativeFunctions = Map.from(new NativeRegex().functions)).Std
)
interp.interpret0(text, JsVirtualPath("(memory)"), ujson.WebJson.Builder) match {
case Left(msg) => throw new js.JavaScriptException(msg)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import java.nio.file.NoSuchFileException
import scala.annotation.unused
import scala.util.Try

object SjsonnetMain {
object SjsonnetMainBase {
def resolveImport(
searchRoots0: Seq[Path], // Evaluated in order, first occurrence wins
allowedInputs: Option[Set[os.Path]] = None,
Expand Down Expand Up @@ -60,19 +60,6 @@ object SjsonnetMain {
}
}

def main(args: Array[String]): Unit = {
val exitCode = main0(
args,
new DefaultParseCache,
System.in,
System.out,
System.err,
os.pwd,
None
)
System.exit(exitCode)
}

def main0(
args: Array[String],
parseCache: ParseCache,
Expand Down
19 changes: 19 additions & 0 deletions sjsonnet/src-jvm-native/sjsonnet/stdlib/NativeGzip.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package sjsonnet.stdlib

import sjsonnet.functions.AbstractFunctionModule
import sjsonnet.{Error, EvalScope, Lazy, Platform, Position, Val}

class NativeGzip extends AbstractFunctionModule {
def name = "gzip"

val functions: Seq[(String, Val.Builtin)] = Seq(
"gzip" -> new Val.Builtin1("gzip", "v") {
override def evalRhs(v: Lazy, ev: EvalScope, pos: Position): Val = v.force match {
case Val.Str(_, value) => Val.Str(pos, Platform.gzipString(value))
case arr: Val.Arr =>
Val.Str(pos, Platform.gzipBytes(arr.iterator.map(_.cast[Val.Num].asInt.toByte).toArray))
case x => Error.fail("Cannot gzip encode " + x.prettyName)
}
}
)
}
21 changes: 21 additions & 0 deletions sjsonnet/src-jvm/sjsonnet/SjsonnetMain.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package sjsonnet

import sjsonnet.stdlib.{NativeGzip, NativeRegex, NativeXz}

object SjsonnetMain {
def main(args: Array[String]): Unit = {
val exitCode = SjsonnetMainBase.main0(
args,
new DefaultParseCache,
System.in,
System.out,
System.err,
os.pwd,
None,
std = new Std(nativeFunctions =
Map() ++ new NativeXz().functions ++ new NativeGzip().functions ++ new NativeRegex().functions
).Std
)
System.exit(exitCode)
}
}
43 changes: 43 additions & 0 deletions sjsonnet/src-jvm/sjsonnet/stdlib/NativeXz.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package sjsonnet.stdlib

import sjsonnet.functions.AbstractFunctionModule
import sjsonnet.{Error, EvalScope, Lazy, Platform, Position, Val}

class NativeXz extends AbstractFunctionModule {
def name = "xz"

private val dummyPos: Position = new Position(null, 0)

val functions: Seq[(String, Val.Builtin)] = Seq(
"xz" -> new Val.Builtin2(
"xz",
"v",
"compressionLevel",
Array(Val.Null(dummyPos), Val.Null(dummyPos))
) {
override def evalRhs(arg1: Lazy, arg2: Lazy, ev: EvalScope, pos: Position): Val = {
val compressionLevel: Option[Int] = arg2.force match {
case Val.Null(_) =>
// Use default compression level if the user didn't set one
None
case Val.Num(_, n) =>
Some(n.toInt)
case x =>
Error.fail("Cannot xz encode with compression level " + x.prettyName)
}
arg1.force match {
case Val.Str(_, value) => Val.Str(pos, Platform.xzString(value, compressionLevel))
case arr: Val.Arr =>
Val.Str(
pos,
Platform.xzBytes(
arr.iterator.map(_.cast[Val.Num].asInt.toByte).toArray,
compressionLevel
)
)
case x => Error.fail("Cannot xz encode " + x.prettyName)
}
}
}
)
}
21 changes: 21 additions & 0 deletions sjsonnet/src-native/sjsonnet/SjsonnetMain.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package sjsonnet

import sjsonnet.stdlib.{NativeGzip, NativeRegex}

object SjsonnetMain {
def main(args: Array[String]): Unit = {
val exitCode = SjsonnetMainBase.main0(
args,
new DefaultParseCache,
System.in,
System.out,
System.err,
os.pwd,
None,
std = new Std(nativeFunctions =
Map.from(new NativeGzip().functions ++ new NativeRegex().functions)
).Std
)
System.exit(exitCode)
}
}
47 changes: 3 additions & 44 deletions sjsonnet/src/sjsonnet/Std.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,53 +15,17 @@ import scala.collection.mutable
* `builtin` and other helpers to handle the common wrapper logic automatically
*/
class Std(
private val additionalNativeFunctions: Map[String, Val.Func] = Map.empty,
private val nativeFunctions: Map[String, Val.Func] = Map.empty,
private val additionalStdFunctions: Map[String, Val.Func] = Map.empty)
extends FunctionBuilder {
// keep for binary compatibility
def this(additionalNativeFunctions: Map[String, Val.Func]) =
this(additionalNativeFunctions, Map.empty)
def this(nativeFunctions: Map[String, Val.Func]) =
this(nativeFunctions, Map.empty)

private val dummyPos: Position = new Position(null, 0)
private val emptyLazyArray = new Array[Lazy](0)
private val leadingWhiteSpacePattern = Platform.getPatternFromCache("^[ \t\n\f\r\u0085\u00A0']+")
private val trailingWhiteSpacePattern = Platform.getPatternFromCache("[ \t\n\f\r\u0085\u00A0']+$")
private val builtinNativeFunctions = Map(
builtin("gzip", "v") { (_, _, v: Val) =>
v match {
case Val.Str(_, value) => Platform.gzipString(value)
case arr: Val.Arr =>
Platform.gzipBytes(arr.iterator.map(_.cast[Val.Num].asInt.toByte).toArray)
case x => Error.fail("Cannot gzip encode " + x.prettyName)
}
},
builtinWithDefaults("xz", "v" -> null, "compressionLevel" -> Val.Null(dummyPos)) {
(args, _, _) =>
val compressionLevel: Option[Int] = args(1) match {
case Val.Null(_) =>
// Use default compression level if the user didn't set one
None
case Val.Num(_, n) =>
Some(n.toInt)
case x =>
Error.fail("Cannot xz encode with compression level " + x.prettyName)
}
args(0) match {
case Val.Str(_, value) => Platform.xzString(value, compressionLevel)
case arr: Val.Arr =>
Platform.xzBytes(
arr.iterator.map(_.cast[Val.Num].asInt.toByte).toArray,
compressionLevel
)
case x => Error.fail("Cannot xz encode " + x.prettyName)
}
}
) ++ StdRegex.functions
require(
builtinNativeFunctions.forall(k => !additionalNativeFunctions.contains(k._1)),
"Conflicting native functions"
)
private val nativeFunctions = builtinNativeFunctions ++ additionalNativeFunctions

private object AssertEqual extends Val.Builtin2("assertEqual", "a", "b") {
def evalRhs(v1: Lazy, v2: Lazy, ev: EvalScope, pos: Position): Val = {
Expand Down Expand Up @@ -2000,11 +1964,6 @@ class Std(
}
},
builtin(Native)
) ++ builtinNativeFunctions

require(
functions.forall(k => !additionalStdFunctions.contains(k._1)),
"Conflicting std functions"
)

private def toSetArr(args: Array[Val], idx: Int, pos: Position, ev: EvalScope) = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package sjsonnet
package sjsonnet.stdlib

import sjsonnet.Expr.Member.Visibility
import sjsonnet.Val.Obj
import sjsonnet._
import sjsonnet.functions.AbstractFunctionModule

class NativeRegex extends AbstractFunctionModule {
def name = "regex"

object StdRegex {
private final def regexPartialMatch(pos: Position, pattern: String, str: String): Val = {
val compiledPattern = Platform.getPatternFromCache(pattern)
val matcher = compiledPattern.matcher(str)
Expand Down Expand Up @@ -39,7 +43,7 @@ object StdRegex {
}
}

def functions: Map[String, Val.Builtin] = Map(
val functions: Seq[(String, Val.Builtin)] = Seq(
"regexPartialMatch" -> new Val.Builtin2("regexPartialMatch", "pattern", "str") {
override def evalRhs(pattern: Lazy, str: Lazy, ev: EvalScope, pos: Position): Val = {
regexPartialMatch(pos, pattern.force.asString, str.force.asString)
Expand Down
8 changes: 5 additions & 3 deletions sjsonnet/test/src-js/sjsonnet/BaseFileTests.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package sjsonnet

import sjsonnet.stdlib.NativeRegex

import java.nio.charset.StandardCharsets
import scala.scalajs.js
import utest._

abstract class BaseFileTests extends TestSuite {
private val stderr = new StringBuffer()
private val std = new Std(
additionalNativeFunctions = Map(
nativeFunctions = Map(
"jsonToString" -> new Val.Builtin1("jsonToString", "x") {
override def evalRhs(arg1: Lazy, ev: EvalScope, pos: Position): Val = {
Val.Str(
Expand All @@ -29,7 +31,7 @@ abstract class BaseFileTests extends TestSuite {
override def evalRhs(ev: EvalScope, pos: Position): Val =
throw new RuntimeException("native function panic")
}
)
) ++ new NativeRegex().functions
)

def importResolver(
Expand Down Expand Up @@ -103,7 +105,7 @@ abstract class BaseFileTests extends TestSuite {
}

def check(files: Map[String, () => Array[Byte]], fileName: String, testSuite: String): Unit = {
println(s"Checking $fileName")
println(s"Checking $testSuite/$fileName")
val goldenContent = if (files.contains(fileName + ".golden_js")) {
new String(files(fileName + ".golden_js")(), StandardCharsets.UTF_8)
} else {
Expand Down
Loading