Slide 1

Slide 1 text

Implementing inline-* Embedding languages in Haskell Facundo Dom´ ınguez October 12, 2018 Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 1 / 26

Slide 2

Slide 2 text

Take aways 1 Relation of embedding foreign code to other approaches 2 Overview of the implementation challenges Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 2 / 26

Slide 3

Slide 3 text

Multi-language systems Desktop applications Web applications Computing frameworks and libraries Haskell compilers! There many problems already solved. Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 3 / 26

Slide 4

Slide 4 text

Language interoperability Split in processes communicating with some IPC. e.g. client programs and RESTful backends Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 4 / 26

Slide 5

Slide 5 text

Language interoperability Split in processes communicating with some IPC. e.g. client programs and RESTful backends Compile the languages for the same runtime. e.g. .Net Eta Scala Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 4 / 26

Slide 6

Slide 6 text

Language interoperability Split in processes communicating with some IPC. e.g. client programs and RESTful backends Compile the languages for the same runtime. e.g. .Net Eta Scala Have the runtimes of the various languages cooperating on a single process. e.g. FFI clr-inline, inline-java, inline-c, inline-r, inline-rust, language-c-inline Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 4 / 26

Slide 7

Slide 7 text

Why embedded code? Unaddressed costs Converting values from one runtime to the other (a.k.a. marshaling) Managing references to objects in a foreign heap. Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 5 / 26

Slide 8

Slide 8 text

Why embedded code? String showInputDialog(Object message) Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 6 / 26

Slide 9

Slide 9 text

Why embedded code? String showInputDialog(Object message) showInputDialog :: JObject -> IO String Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 6 / 26

Slide 10

Slide 10 text

Why embedded code? String showInputDialog(Object message) showInputDialog :: JObject -> IO String Cost: Maintaining the whole interfaces aligned Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 6 / 26

Slide 11

Slide 11 text

Why embedded code? static bool challengeDialog(int x, int y) { String question = "How much is " + x + " + " + y + "?"; String response = javax.swing.JOptionPane.showInputDialog(question); try { return Integer.parseInt(response) == x + y; } catch (NumberFormatException e) { return false; } } Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 7 / 26

Slide 12

Slide 12 text

Why embedded code? static bool challengeDialog(int x, int y) { String question = "How much is " + x + " + " + y + "?"; String response = javax.swing.JOptionPane.showInputDialog(question); try { return Integer.parseInt(response) == x + y; } catch (NumberFormatException e) { return false; } } challengeDialog :: Int32 -> Int32 -> IO Bool Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 7 / 26

Slide 13

Slide 13 text

Why embedded code? static bool challengeDialog(int x, int y) { String question = "How much is " + x + " + " + y + "?"; String response = javax.swing.JOptionPane.showInputDialog(question); try { return Integer.parseInt(response) == x + y; } catch (NumberFormatException e) { return false; } } challengeDialog :: Int32 -> Int32 -> IO Bool Cost: Managing files with auxiliary foreign definitions Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 7 / 26

Slide 14

Slide 14 text

Why embedded code? challengeDialog :: Int32 -> Int32 -> IO Bool challengeDialog x y = [java| { String question = "How much is " + $x + " + " + $y + "?"; String response = javax.swing.JOptionPane.showInputDialog(question); try { return Integer.parseInt(response) == $x + $y; } catch (NumberFormatException e) { return false; } } |] Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 8 / 26

Slide 15

Slide 15 text

Implementation overview 1 Produce code for a foreign compiler 2 Invoke foreign compiler and link/embed output 3 Generate Haskell code to invoke foreign code Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 9 / 26

Slide 16

Slide 16 text

Producing foreign code module MyHaskellModule { f = ... [java| |] ... g = ... [java| |] ... Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 10 / 26

Slide 17

Slide 17 text

Producing foreign code module MyHaskellModule { f = ... [java| |] ... g = ... [java| |] ... class inline_java_MyPackage_MyHaskellModule123 { static ... method_qq1(...) { } static ... method_qq2(...) { } } Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 10 / 26

Slide 18

Slide 18 text

Finding antiquotations [java| { final Oid krb5Mechanism = new Oid( "1.2.840.113554.1.2.2"); final Oid krb5PrincipalNameType = new Oid("1.2.840.113554.1.2.2.1"); final GSSName serverName = $gssManager.createName ( $subject.getPrincipals().iterator().next().getName() , krb5PrincipalNameType); return Subject.doAs( $subject, new PrivilegedAction() { public GSSCredential run() { try { return $gssManager.createCredential(serverName, GSSCredential.INDEFINITE_LIFETIME, krb5Mechanism, GSSCredential.ACCEPT_ONLY); } catch (Exception e) { throw new RuntimeException(e); } } }); } |] -- find $, lex in Haskell, or lex in foreign language Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 11 / 26

Slide 19

Slide 19 text

Producing foreign code class inline_java_MyPackage_MyHaskellModule123 { static ... method_qq1(...) { } static ... method_qq2(... $gssManager, ... $subject) { } } Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 12 / 26

Slide 20

Slide 20 text

Finding the types subject :: J (Class "javax.security.auth.Subject") gssManager :: J (Class "org.ietf.jgss.GSSManager") [java| ... |] :: IO (J (Class "org.ietf.jgss.GSSCredentials")) Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 13 / 26

Slide 21

Slide 21 text

Finding the types Language.Haskell.TH.reify :: Name -> Q Info f = ... where x = ... y = $(do z <- newName "z" z_decl <- [d| $(return (VarP z)) = 2 |] infox <- reify 'x infoy <- reify 'y infoz <- reify z ... ) Parsing Typechecking Optimizations and Core plugins Executable code generation TH Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 14 / 26

Slide 22

Slide 22 text

Finding the types data Expr = Var Id Lit Literal App Expr Arg Lam Id Expr ... idType :: Id -> Type inlineJavaPlugin :: [(Var, Expr)] -> [(Var, Expr)] Parsing Typechecking Optimizations and Core plugins Executable code generation TH Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 15 / 26

Slide 23

Slide 23 text

Finding types [C.block| JavaVM * { JavaVM *jvm; JavaVMInitArgs vm_args; JavaVMOption *options = malloc(sizeof(JavaVMOption) * $(int n)); for(int i = 0; i < $(int n); i++) options[i].optionString = $(char **coptions)[i]; vm_args.version = JNI_VERSION_1_6; vm_args.nOptions = $(int n); vm_args.options = options; vm_args.ignoreUnrecognized = 0; JNI_CreateJavaVM(&jvm, (void**)&jniEnv, &vm_args); free(options); return jvm; } |] Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 16 / 26

Slide 24

Slide 24 text

Producing foreign code class inline_java_MyPackage_MyHaskellModule123 { static ... method_qq1(...) { } static GSSCredentials method_qq2 (GSSManager $gssManager, Subject $subject) { } } Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 17 / 26

Slide 25

Slide 25 text

Implementation overview 1 Produce code for a foreign compiler 2 Invoke foreign compiler and link/embed output 3 Generate Haskell code to invoke foreign code Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 18 / 26

Slide 26

Slide 26 text

Foreign compiler output After compiling the generated foreign code, store it somewhere. inline-c, inline-rust: link it together with the Haskell module. Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 19 / 26

Slide 27

Slide 27 text

Foreign compiler output After compiling the generated foreign code, store it somewhere. inline-c, inline-rust: link it together with the Haskell module. inline-java: store the bytecode in a global table Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 19 / 26

Slide 28

Slide 28 text

Bytecode in inline-java Haskell runtime JVM Bytecode table One entry per module Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 20 / 26

Slide 29

Slide 29 text

Bytecode in inline-java Haskell runtime JVM Bytecode table One entry per module static void hs_inline_java_init(void) __attribute__((constructor)); static void hs_inline_java_init(void) { ... } Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 20 / 26

Slide 30

Slide 30 text

Implementation overview 1 Produce code for a foreign compiler 2 Invoke foreign compiler and link/embed output 3 Generate Haskell code to invoke foreign code Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 21 / 26

Slide 31

Slide 31 text

Producing foreign calls inline-java: JNI defineClass :: ClassName -> ByteString -> IO JClass findClass :: ClassName -> IO JClass getStaticMethodID :: JClass -> MethodName -> MethodTypeSignature -> IO JMethodID callStaticMethod :: JClass -> JMethodID -> [...] -> IO ... Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 22 / 26

Slide 32

Slide 32 text

Producing foreign calls inline-java: JNI defineClass :: ClassName -> ByteString -> IO JClass findClass :: ClassName -> IO JClass getStaticMethodID :: JClass -> MethodName -> MethodTypeSignature -> IO JMethodID callStaticMethod :: JClass -> JMethodID -> [...] -> IO ... inline-c, inline-rust: FFI foreign import cap function_name :: ... -> IO ... Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 22 / 26

Slide 33

Slide 33 text

Producing foreign calls inline-java: JNI defineClass :: ClassName -> ByteString -> IO JClass findClass :: ClassName -> IO JClass getStaticMethodID :: JClass -> MethodName -> MethodTypeSignature -> IO JMethodID callStaticMethod :: JClass -> JMethodID -> [...] -> IO ... inline-c, inline-rust: FFI foreign import cap function_name :: ... -> IO ... inline-js, inline-r: eval :: String -> [...] -> IO ... Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 22 / 26

Slide 34

Slide 34 text

Implementation overview 1 Produce code for a foreign compiler 2 Invoke foreign compiler and link/embed output 3 Generate Haskell code to invoke foreign code Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 23 / 26

Slide 35

Slide 35 text

GHC tweaking inline-c addForeignSource :: ForeignSrcLang -> String -> Q () inline-rust addForeignFilePath :: ForeignSrcLang -> FilePath -> Q () inline-java addCorePlugin :: String -> Q () Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 24 / 26

Slide 36

Slide 36 text

Language interoperability Split in processes communicating with some IPC. e.g. client programs and RESTful backends Compile the languages for the same runtime. e.g. .Net Eta Scala Have the runtimes of the various languages cooperating on a single process. e.g. FFI clr-inline, inline-java, inline-c, inline-r, inline-rust, language-c-inline Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 25 / 26

Slide 37

Slide 37 text

Final impressions Embedding code avoids large binding libraries, has the compiler automate (foreign) build tasks, and admits relatively simple implementations. Facundo Dom´ ınguez (tweag.io) Implementing inline-* October 12, 2018 26 / 26