{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreiarwdoa5siu6n5gwn7hgmnwyggpphrbhuk5fa6fkr6rj3qnivhjii",
    "uri": "at://did:plc:pi6woz4d47bkuws673w2il2r/app.bsky.feed.post/3mna47ticirx2"
  },
  "path": "/t/h2jvm-a-haskell-library-for-writing-jvm-bytecode/14182#post_1",
  "publishedAt": "2026-06-01T12:06:19.000Z",
  "site": "https://discourse.haskell.org",
  "tags": [
    "GitHub - ElaraLang/h2jvm: Haskell library for writing JVM bytecode in a high level format · GitHub",
    "@StackMapError"
  ],
  "textContent": "Hi everyone!\nI have been working on a new library for writing JVM bytecode with Haskell in a nice, high level way and I’d love some feedback on it! The motivation here is for compilers to the JVM so they can focus on the actual code generation, meanwhile H2JVM takes care of all the messy details like `StackMapTable` analysis, label/offset resolution, etc.\n\nHere is a quick example taken from the readme. It generates a simple class file with a single method `static int add(int, int)` which adds 2 numbers:\n\n\n    main :: IO ()\n    main = do\n      -- Define the class name, method descriptor, and access flags\n      let className = \"Calculator\"\n          methodDesc = MethodDescriptor -- int (int, int)\n            [PrimitiveFieldType JInt, PrimitiveFieldType JInt]\n            (TypeReturn (PrimitiveFieldType JInt))\n\n      -- Construct the class using ClassBuilder\n      result <- runPureEff $ runErrorNoCallStack @StackMapError $ runClassBuilder className java8 $ do\n        addAccessFlag CPublic\n\n        -- add the method, which automatically handles stack map analysis, max stack/locals, etc\n        addMethodWithCode \"add\" [MPublic, MStatic] methodDesc $ do\n          emit $ ILoad 0\n          emit $ ILoad 1\n          emit IAdd\n          emit IReturn\n\n      case result of\n        Left err -> putStrLn $ \"Error building class: \" <> show err\n        Right (classFile, _) -> do\n          -- Serialise the class to a file\n          let path = classFilePath classFile -- returns \"Calculator.class\"\n          case classFileBytes classFile of\n            Left err -> putStrLn $ \"Error generating bytecode: \" <> show err\n            Right bytes -> LBS.writeFile path bytes\n\n\nThis is a less contrived example from real usage of the library in my compiler, which shows how label resolution “just works”. This implements the `>` operator in my language in the way you’d probably expect\n\n\n    IR.BinaryOp op lhs rhs -> do\n        emitExpr lhs\n        emitExpr rhs\n        case op of\n            IR.GreaterThan -> do\n                trueLabel <- newLabel\n                endLabel <- newLabel\n                emit $ JVM.IfICmp (IfGt trueLabel) -- if_icmpgt jump to trueLabel\n                -- false case\n                emit JVM.IConst0 -- push 0 onto stack\n                emit $ Goto endLabel -- jump to end\n                -- true case\n                emit $ JVM.Label trueLabel\n                emit JVM.IConst1 -- push 1 onto stack\n                emit $ JVM.Label endLabel -- jump to end\n\n\nThe generated code here looks something like this:\n\n\n    29: blah (pushing lhs and rhs onto stack)\n    32: if_icmpgt     39 -- trueLabel resolved as offset 39\n    35: iconst_0\n    36: goto          40 -- endLabel resolved as offset 40\n    39: iconst_1\n    40: blah blah (code after the binaryop, whatever that may be)\n\n\nThe library is still in very very _very_ early stages (only a very small subset of the instructions and attributes are supported), but I would love some preliminary feedback on things like the design!\n\nHappy to answer any questions anyone might have too\n\nIf you’re interested, here’s the GitHub repo: GitHub - ElaraLang/h2jvm: Haskell library for writing JVM bytecode in a high level format · GitHub\n\nThanks in advance!",
  "title": "H2JVM - A Haskell Library for writing JVM Bytecode"
}