Giter Site home page Giter Site logo

japgolly / scala-graal Goto Github PK

View Code? Open in Web Editor NEW
194.0 8.0 4.0 1.32 MB

Make usage of Graal features easy and safe from Scala. Also features Scala-based React SSR.

License: Apache License 2.0

Scala 100.00%
scala graal graalvm scalajs react ssr fp

scala-graal's Introduction

scala-graal

libraryDependencies ++= Seq(
  "com.github.japgolly.scala-graal"  %% "core"           % "2.0.0"
  "com.github.japgolly.scala-graal" %%% "core-js"        % "2.0.0"
  "com.github.japgolly.scala-graal" %%% "ext-boopickle"  % "2.0.0"
  "com.github.japgolly.scala-graal"  %% "ext-prometheus" % "2.0.0"
)

Goals

  • Make it quick, easy and safe to interface with embedded languages from Scala
  • Hide and automate a lot of required GraalVM boilerplate
  • Support React SSR for Scala.JS applications

Demo

import japgolly.scalagraal._

// Use semantics and implicit config for JS
// (GraalVM also supports Python, R, Ruby, LLVM)
import japgolly.scalagraal.js._
import GraalJs._

// 1. Pre-compile expression functions for fast invocation.
// 2. Typeclasses translate and/or marshall data between JVM and JS.
val expr: (Int, Int) => Expr[String] =
  Expr.apply2((a, b) => s"($a + $b) * 2 + '!'").compile(_.asString)

// Use a basic synchronous JS environment
val ctx = GraalContext()

val result = ctx.eval(expr(3, 8))
assert(result == Right("22!"))

Learning

Features

  • Expressions
    • composition
    • purity
    • result parsing
    • error handling
    • null handling
    • binding typeclasses
    • binding codecs (eg binary/json/whatever)
  • Service
    • single-threaded
    • multi-threaded pool
    • synchronous
    • asynchronous
    • optional time limits
    • before/around/after hooks
    • automatic metrics
  • Warmup
    • ability to warmup VM
    • rules (eg. up to 10000 reps/thread & up to 30 sec | until completes within 20ms)
  • React SSR (Server-Side Rendering)
    • support for rendering JS components from JVM
    • conversion to constant-time (conditionally)
    • window and especially window.location management
  • Integrations
    • Prometheus - export metrics to Prometheus
    • BooPickle - marshall data back and forth using binary codecs

scala-graal's People

Contributors

japgolly avatar scala-steward avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

scala-graal's Issues

Simple demo

I have been looking for a simple demo app that I can just compile and run that just calls a scala.js function. I can see your demo code but not a full project. I have put together my own project but I cannot get it to make the call to a function properly. I always get something like
Left(japgolly.scalagraal.ExprError$EvalError: ReferenceError: myScalaJsFn1 is not defined)

I can see the functions in the generated Js file though. This is just a simple function passing in and returning a string. If I try and use the Pickled data I see an error about "ScalaGraalBookpicklePickled is not defined". So I just want to get a simple version working.

Any suggestions would be appreciated.

Contexts are impure - need sync effect type

Evaluating an Expr with an impure body is impure.

Submitting an async task is a side-effect.

Results when using awaitResultsWithTimeout aren't referentially-transparent at all.

Include Template (?)

/** Takes a potentially slow `String* => String` function and makes it super fast by executing it once,
  * turning the result into a template, then using the template for all subsequent calls.
  *
  * This assumes provided functions are pure.
  */
object Template {

  def apply1(f: String => String): String => String = ...
  def apply2(f: (String, String) => String): (String, String) => String = ...
  ...
}

Bindings for other languages

Hiya -- if I wanted to use this library but instead of JS, use IE the Python bindings, I would need to write something like this?

import japgolly.scalagraal._

object LanguagePython extends Language("python"):
  override def polyglotImport(b: Binding) = s"Polyglot.import('${b.bindingName}')"
  override protected def setBinding(a: String, b: String) = a + "=" + b
  override protected def unsetBinding(a: String) = a + "=undefined"

object GraalPythonComponents:
  import ExprParam._

  trait PythonValues:
    given exprParamJsUnit: ExprParam[Unit] = SourceConst("undefined")

  trait Stdlib:
    implicit def exprParamOptionF[A](implicit p: SourceFn[A]): SourceFn[Option[A]] =
      SourceFn {
        case Some(a) => p.mkSource(a)
        case None    => "null"
      }

    implicit def exprParamOptionV[A](implicit p: ValueFn[A]): ValueFn[Option[A]] =
      ValueFn {
        case Some(a) => p.mkValue(a)
        case None    => RawValue.Null
      }

    implicit def exprParamOptionC[A](implicit p: CtxValueFn[A]): CtxValueFn[Option[A]] =
      CtxValueFn {
        case Some(a) => p.mkValue(a)
        case None    => _ => RawValue.Null
      }
   end Stdlib
end GraalPythonComponents

trait GraalPython
  extends ExprParam.Defaults
     with GraalPythonComponents.PythonValues
     with GraalPythonComponents.Stdlib:
  implicit final def graalLanguage: LanguagePython.type = LanguagePython

object GraalPython extends GraalPython

Expr methods are confusing

final def compile2      [A,B](mkExpr: (String,String) => String): CompileDsl2[A,B] =
final def compileExpr2  [A,B](mkExpr: (String,String) => String)(implicit lang: Language,   final def apply2[A,B](mkExpr: (String,String) => String, a: A, b: B)(implicit lang: Language, A:ExprParam[A], B:ExprParam[B]): Expr[Value] =
final def compileFnCall2[A,B](fnName: String): CompileDsl2[A,B] =
final def callFn2       [A,B](fnName: String, a: A, b: B)(implicit lang: Language, A:ExprParam[A], B:ExprParam[B]): Expr[Value] =

I long ago thought that helpers in different shapes would be useful but really it's just confusing. The mental cost of figuring out which method to call is greater than any effort saved specifying a single type param (or whatever). Simplify and be consistent!

Add ...

  implicit def exprParamValueFn: ExprParam.ValueFn[Value] = ExprParam.RawValueFn // TODO wtf! this should be in SG
  val initExpr =
    for {
      v <- Expr.requireFileOnClasspath("scalacss.js") // TODO assign to <name> would be a good method in SG
      _ <- Expr.apply1("var X = " + _, v)
    } yield ()
final class AsyncFunctionFailed(val failure: Value) extends RuntimeException(s"AsyncFunctionFailed: $failure")

  def exprAsync[A](expr: Expr[Value], f: Value => A): Expr[Future[A]] =
    for {
      v <- expr
      p = Promise[A]()
      onThen = (v => p.complete(Try(f(Value.asValue(v))))) : Consumer[AnyRef]
      onFail = (v => p.failure(new AsyncFunctionFailed(Value.asValue(v)))) : Consumer[AnyRef]
      _ <- Expr.apply3((a, b, c) => s"$a.then($b).catch($c)", v, onThen, onFail)
    } yield p.future

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.