sci

jyn 2025-07-30T14:25:58.476509Z

i'm compiling a clojure program to Graal that has an embedded SCI interpreter. when i try to call (hiccup2.core/html), it gives a syntax error:

Exception in thread "main" clojure.lang.ExceptionInfo: Syntax error compiling fn* at (0:0). {:type :sci/error, :line 1, :column 1, :message "Syntax error compiling fn* at (0:0).", :sci.impl/callstack #object[clojure.lang.Volatile 0x71bca854 {:status :ready, :val ({:ns #object[sci.lang.Namespace 0x373a6109 "user"], :file nil, :sci.impl/f-meta nil} {:ns #object[sci.lang.Namespace 0x373a6109 "user"], :file nil, :sci.impl/f-meta nil} {:ns #object[sci.lang.Namespace 0x373a6109 "user"], :file nil, :sci.impl/f-meta {:name eval, :doc "Evaluates the form data structure (not text!) and returns the result.", :arglists ([form]), :sci/built-in true, :ns #object[sci.lang.Namespace 0x1562e300 "clojure.core"]}} {:line 1, :column 1, :ns #object[sci.lang.Namespace 0x373a6109 "user"], :file nil} {:line 1, :column 1, :ns #object[sci.lang.Namespace 0x373a6109 "user"], :file nil, :sci.impl/f-meta {:ns #object[sci.lang.Namespace 0x32eff675 "hiccup2.core"], :name html, :macro true, :doc "Render Clojure data structures to a compiled representation of HTML. To turn\n  the representation into a string, use clojure.core/str. Strings inside the\n  macro are automatically HTML-escaped. To insert a string without it being\n  escaped, use the [[raw]] function.\n\n  A literal option map may be specified as the first argument. It accepts two\n  keys that control how the HTML is outputted:\n\n  `:mode`\n  : One of `:html`, `:xhtml`, `:xml` or `:sgml` (defaults to `:xhtml`).\n    Controls how tags are rendered.\n\n  `:escape-strings?`\n  : True if strings should be escaped (defaults to true).", :arglists ([options & content])}})}], :file nil}
what is going wrong here? i found https://github.com/babashka/sci/issues/370#issuecomment-664241814 which maybe looks related? but i know babashka supports hiccup so i'm not sure why it only breaks for me

jyn 2025-07-30T14:27:27.316509Z

i did see that babashka has its own version of html, but i'm not sure how it's different or why it's necessary ... https://github.com/babashka/babashka/blob/bd20a5f973fcf1ed33131eb1079927be9de0d1d8/feature-hiccup/babashka/impl/hiccup.clj#L12-L34

borkdude 2025-07-30T14:28:45.967999Z

have you tried using babashka's config?

borkdude 2025-07-30T14:28:59.056959Z

might solve the problem. I don't remember the exact issue but it's there for a reason

jyn 2025-07-30T14:29:01.213239Z

what config do you mean?

borkdude 2025-07-30T14:29:07.569869Z

the config you are linking to

jyn 2025-07-30T14:29:16.843659Z

oh i see

jyn 2025-07-30T14:29:40.813789Z

i suppose that works but i worry about reimplementing parts of public libraries, what if their api changes

borkdude 2025-07-30T14:30:08.170169Z

The error "Syntax error compiling fn*" isn't coming from SCI, but from Clojure itself

👀 1
jyn 2025-07-30T14:30:39.743579Z

i can post the backtrace if it's helpful?

borkdude 2025-07-30T14:30:43.114329Z

> i suppose that works but i worry about reimplementing parts of public libraries, what if their api changes tests, tests, tests. you control the version of the dependency for your graal binary

borkdude 2025-07-30T14:33:49.008879Z

sure, post the stack trace in a gist, not as plain text here

borkdude 2025-07-30T14:33:59.641009Z

I have to go for a while, brb

jyn 2025-07-30T14:35:14.821119Z

oh wait actually at the end of the long backtrace is another exception

Caused by: java.lang.UnsupportedOperationException: Crema
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.VMError.unimplemented(VMError.java:195)
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk.ClassLoaderHelper.defineClass(Target_java_lang_ClassLoader.java:330)
	at java.base@24.0.2/java.lang.ClassLoader.defineClass(ClassLoader.java:271)
	at java.base@24.0.2/java.lang.ClassLoader.defineClass(ClassLoader.java:265)
	at clojure.lang.DynamicClassLoader.defineClass(DynamicClassLoader.java:46)
	at clojure.lang.Compiler$ObjExpr.getCompiledClass(Compiler.java:5503)
	at clojure.lang.Compiler$FnExpr.parse(Compiler.java:4633)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:7628)
	... 143 more

jyn 2025-07-30T14:36:17.918969Z

full trace here https://gist.github.com/jyn514/2ae5b11e607a41069d7792aaaee2a35b

borkdude 2025-07-30T14:36:57.378249Z

I bet you are running into clojure.core/eval usage here: https://github.com/weavejester/hiccup/blob/master/src/hiccup/compiler.clj scan that file for (eval ..)

borkdude 2025-07-30T14:37:06.282269Z

and this isn't supported by graalvm native-image

borkdude 2025-07-30T14:37:17.978789Z

which version are you using of graalvm native-image btw?

jyn 2025-07-30T14:37:32.532079Z

native-image 24.0.2 2025-07-15

borkdude 2025-07-30T14:37:48.612509Z

ok. I'm fairly sure that's the issue and why babashka has its own html macros

jyn 2025-07-30T14:38:02.200059Z

gotcha, thank you

jyn 2025-07-30T14:39:31.562569Z

i think this is https://github.com/oracle/graal/issues/11327

borkdude 2025-07-30T14:41:06.094569Z

native-image not being able to eval is a fundamental problem. you can read more about it here: https://github.com/clj-easy/graal-docs?tab=readme-ov-file#runtime-evaluation

borkdude 2025-07-30T14:41:41.881609Z

or actually it doesnt' really have that much text. but it's the reason why SCI even exists ;)

jyn 2025-07-30T14:41:48.950549Z

haha

jyn 2025-07-30T14:42:20.243899Z

i wonder if we can convince the hiccup maintainers to have SCI as an optional feature and do platform detection to decide when to use it for eval

jyn 2025-07-30T14:42:41.816389Z

i know clojure supports platform detection for JVM/CLJS, idk if it has something similar for graal

borkdude 2025-07-30T14:43:27.846899Z

the hiccup maintainer actually regrets complicating things so much to have compile time optimizations using eval. just don't go there and accept the workaround

👍 1
borkdude 2025-07-30T14:44:11.120859Z

the API won't change that much that you have to worry about it, but do make a few tests to see if your hiccup works

borkdude 2025-07-30T14:44:50.768359Z

the custom macro calls compiler/render-html which is the dynamic version

jyn 2025-07-30T14:46:13.792799Z

neat, thank you

jyn 2025-07-30T14:46:36.171569Z

my standard library is going to have a bunch of calls to all these libraries so i'm not too worried about things being obviously broken, but i'll add a couple tests for the dynamic bindings

👍 1
jyn 2025-07-30T14:47:50.249309Z

(i'm hitting all these weird issues before i even hit hello world in my DSL lol)

borkdude 2025-07-30T15:33:04.758979Z

first test on the JVM before running with native-image, usually saves time

jyn 2025-07-30T15:54:28.111339Z

yes, i've been using JVM up until now

jyn 2025-07-30T15:54:38.429339Z

just started compiling to Graal last night

👍 1