Skip to content

Instantly share code, notes, and snippets.

@lilac
Last active March 16, 2023 14:14
Show Gist options
  • Save lilac/e3041bb3fd361a67866a2283a4f95b65 to your computer and use it in GitHub Desktop.
Save lilac/e3041bb3fd361a67866a2283a4f95b65 to your computer and use it in GitHub Desktop.
Starlark interoperation to JVM
package example
import com.google.common.collect.{ImmutableCollection, ImmutableList, ImmutableMap}
import net.starlark.java.annot.{Param, StarlarkBuiltin, StarlarkMethod}
import net.starlark.java.eval.{Dict, EvalException, Module, Mutability, Starlark, StarlarkFunction, StarlarkInt, StarlarkList, StarlarkSemantics, StarlarkThread, Structure, Tuple}
import net.starlark.java.syntax.{FileOptions, ParserInput}
import scala.collection.mutable.ListBuffer
object StarlarkDemo extends App {
if (args.length < 1) {
println("run BUILD.example")
sys.exit(1)
}
val fileName = args(0)
val input = ParserInput.readFile(fileName)
val buf = ListBuffer.empty[Definition]
val env = makeEnvironment(buf)
val module = Module.withPredeclared(StarlarkSemantics.DEFAULT, env)
val ops = Module.create()
module.setGlobal("ops", ops)
withMutability(input.getFile) { mu =>
val thread = new StarlarkThread(mu, StarlarkSemantics.DEFAULT)
Starlark.execFile(input, FileOptions.DEFAULT, module, thread)
val isAdult = module.getGlobal("is_adult")
println(isAdult)
println(module.getGlobal("recall_op"))
println(module.getGlobal("ops"))
val user = new User("a", 1)
val userAttrs = Starlark.dir(mu, StarlarkSemantics.DEFAULT, user)
println(s"dir(user) = $userAttrs")
val age = Starlark.getattr(mu, StarlarkSemantics.DEFAULT, user, "age", null)
println(s"user.age = $age")
println(Starlark.call(thread, isAdult, java.util.List.of(user), java.util.Map.of()))
}
val defs = buf.toList
println(defs.mkString("\n"))
// close mutability to freeze the values
def withMutability(fileName: String)(f: Mutability => Unit): Unit = {
val mu = Mutability.create(fileName)
try {
f(mu)
} finally {
mu.close()
}
}
def makeEnvironment(buf: ListBuffer[Definition]): ImmutableMap[String, AnyRef] = {
val env = ImmutableMap.builder[String, AnyRef]()
Starlark.addMethods(env, new Functions(buf), StarlarkSemantics.DEFAULT)
env.build()
}
}
@StarlarkBuiltin(name = "User")
class User(name: String, age: Int) {
@StarlarkMethod(name = "name", structField = true)
def getName() = name
@StarlarkMethod(name = "age", structField = true)
def getAge() = age
}
class Functions(buf: ListBuffer[Definition]) {
@StarlarkMethod(
name = "op",
parameters = Array(
new Param(name = "name", named = true),
new Param(name = "args", named = true, defaultValue = "{}")
),
doc = "Define an operation."
)
def op(name: String, args: Dict[String, Object]): String = {
println(s"Define operation: $name $args")
name
}
}
def is_adult(user):
return user.age >= 18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment