@@ -16,11 +16,39 @@ import scala.util.matching.Regex
1616 * in Scala code. Uses `builtin` and other helpers to handle the common wrapper
1717 * logic automatically
1818 */
19- class Std {
19+ class Std ( private val additionalNativeFunctions : Map [ String , Val . Builtin ] = Map .empty) {
2020 private val dummyPos : Position = new Position (null , 0 )
2121 private val emptyLazyArray = new Array [Lazy ](0 )
2222 private val leadingWhiteSpacePattern = Pattern .compile(" ^[ \t\n\f\r\u0085\u00A0 ']+" )
2323 private val trailingWhiteSpacePattern = Pattern .compile(" [ \t\n\f\r\u0085\u00A0 ']+$" )
24+ private val oldNativeFunctions = Map (
25+ builtin(" gzip" , " v" ){ (_, _, v : Val ) =>
26+ v match {
27+ case Val .Str (_, value) => Platform .gzipString(value)
28+ case arr : Val .Arr => Platform .gzipBytes(arr.iterator.map(_.cast[Val .Num ].value.toByte).toArray)
29+ case x => Error .fail(" Cannot gzip encode " + x.prettyName)
30+ }
31+ },
32+
33+ builtinWithDefaults(" xz" , " v" -> null , " compressionLevel" -> Val .Null (dummyPos)){ (args, pos, ev) =>
34+ val compressionLevel : Option [Int ] = args(1 ) match {
35+ case Val .Null (_) =>
36+ // Use default compression level if the user didn't set one
37+ None
38+ case Val .Num (_, n) =>
39+ Some (n.toInt)
40+ case x =>
41+ Error .fail(" Cannot xz encode with compression level " + x.prettyName)
42+ }
43+ args(0 ) match {
44+ case Val .Str (_, value) => Platform .xzString(value, compressionLevel)
45+ case arr : Val .Arr => Platform .xzBytes(arr.iterator.map(_.cast[Val .Num ].value.toByte).toArray, compressionLevel)
46+ case x => Error .fail(" Cannot xz encode " + x.prettyName)
47+ }
48+ },
49+ )
50+ require(oldNativeFunctions.forall(k => ! additionalNativeFunctions.contains(k._1)), " Conflicting native functions" )
51+ private val nativeFunctions = oldNativeFunctions ++ additionalNativeFunctions
2452
2553 private object AssertEqual extends Val .Builtin2 (" assertEqual" , " a" , " b" ) {
2654 def evalRhs (v1 : Val , v2 : Val , ev : EvalScope , pos : Position ): Val = {
@@ -1285,31 +1313,6 @@ class Std {
12851313 new Val .Arr (pos, Base64 .getDecoder().decode(s).map(i => Val .Num (pos, i)))
12861314 },
12871315
1288- builtin(" gzip" , " v" ){ (pos, ev, v : Val ) =>
1289- v match {
1290- case Val .Str (_, value) => Platform .gzipString(value)
1291- case arr : Val .Arr => Platform .gzipBytes(arr.iterator.map(_.cast[Val .Num ].value.toByte).toArray)
1292- case x => Error .fail(" Cannot gzip encode " + x.prettyName)
1293- }
1294- },
1295-
1296- builtinWithDefaults(" xz" , " v" -> null , " compressionLevel" -> Val .Null (dummyPos)){ (args, pos, ev) =>
1297- val compressionLevel : Option [Int ] = args(1 ) match {
1298- case Val .Null (_) =>
1299- // Use default compression level if the user didn't set one
1300- None
1301- case Val .Num (_, n) =>
1302- Some (n.toInt)
1303- case x =>
1304- Error .fail(" Cannot xz encode with compression level " + x.prettyName)
1305- }
1306- args(0 ) match {
1307- case Val .Str (_, value) => Platform .xzString(value, compressionLevel)
1308- case arr : Val .Arr => Platform .xzBytes(arr.iterator.map(_.cast[Val .Num ].value.toByte).toArray, compressionLevel)
1309- case x => Error .fail(" Cannot xz encode " + x.prettyName)
1310- }
1311- },
1312-
13131316 builtin(EncodeUTF8 ),
13141317 builtin(DecodeUTF8 ),
13151318
@@ -1511,8 +1514,15 @@ class Std {
15111514 builtin(MaxArray ),
15121515 builtin(" primitiveEquals" , " x" , " y" ) { (_, ev, x : Val , y : Val ) =>
15131516 x.isInstanceOf [y.type ] && ev.compare(x, y) == 0
1514- }
1515- )
1517+ },
1518+ builtin(" native" , " name" ) { (pos, ev, name : String ) =>
1519+ if (nativeFunctions.contains(name)) {
1520+ nativeFunctions(name)
1521+ } else {
1522+ Error .fail(" Native function " + name + " not found" , pos)(ev)
1523+ }
1524+ },
1525+ ) ++ oldNativeFunctions
15161526
15171527 private def toSetArrOrString (args : Array [Val ], idx : Int , pos : Position , ev : EvalScope ) = {
15181528 args(idx) match {
0 commit comments