mighty-gerbils/gerbil

Eval behaves differently in compiled binaries

corpix opened this issue · 6 comments

I have faced an issue with eval environment inside compiled binaries. Here is the example...

Gerbil:

 ~/projects/src/git.backbone/corpix/schemered  λ  cat yyy.ss
(export main)
(def x 1)

(def file-path "xxx.ss")
(def (main . args)
  (eval `(include ,file-path)))
 ~/projects/src/git.backbone/corpix/schemered  λ  cat xxx.ss                                                         
(display x)
(display "\n")

 ~/projects/src/git.backbone/corpix/schemered  λ  gxc -static -exe -o yyy yyy.ss
...                    
 ~/projects/src/git.backbone/corpix/schemered  λ  ./yyy
*** ERROR IN "xxx.ss"@1.10-1.11 -- Unbound variable: x
--- continuation backtrace:
[0] ##primordial-exception-handler-hook                                                
 ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ xxx.ss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1┃(display x)
2┃(display "\n")

Gerbil interpreter works fine:

 ~/projects/src/git.backbone/corpix/schemered  λ  gxi
Gerbil v0.18.1-111-g708c85bd on Gambit v4.9.5-130-g09335d95
> (def x 1)
> (eval '(include "xxx.ss"))
1
> 

Gambit works fine:

 ~/projects/src/git.backbone/corpix/schemered  λ  cat yyy.scm
(define x 1)
(define file-path "xxx.scm")
(eval `(include ,file-path))
 ~/projects/src/git.backbone/corpix/schemered  λ  cat xxx.scm                                                        
(display x)
(display "\n")

 ~/projects/src/git.backbone/corpix/schemered  λ  gsc -exe -cc-options '-static' yyy.scm
...        
 ~/projects/src/git.backbone/corpix/schemered  λ  ./yyy
1
vyzo commented

You need to initialize the expander explicitly in binaries!

So, import :getbil/expander in your binary to make sure the relevant code is linked, and then call (gerbil-load-expander!).

Thanks for quick reply! I have changed my code to be:

(import :gerbil/expander)
(export main)
(def x 1)

(def file-path "xxx.ss")
(def (main . args)
  (gerbil-load-expander!)
  (eval `(include ,file-path)))

calling gerbil-load-expander! from main because otherwise it will fail with
*** ERROR IN gerbil-load-expander! --
*** ERROR IN ? [Error]: runtime has not been initialized

But I still getting an error:

*** ERROR IN "xxx.ss"@1.10-1.11 -- Unbound variable: x
--- continuation backtrace:
[0] ##primordial-exception-handler-hook                                                
 ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ xxx.ss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1┃(display x)
2┃(display "\n")
vyzo commented

Yes, gerbil-load-expander! needs to be called from main or childten.

Regarding the unbound variable;
x is defined in your main module, so it is not visible in your top lexical context!

You need to extern declare it for your actual namespace. Alternatively, you can export it in your main module and import that, but it requires your module's ssi to be visible to the binary.

So, i recommend the extern approach.
In the included filr, add something like this:
(extern (x your/package/main-module#x))

Or:
(extern namespace: your/package/main-module x ;; and more symbols )

Now it is working!

Full code for history:

yyy.ss

(import :gerbil/expander)
(export main)
(def x 1)

(def file-path "xxx.ss")
(def (main . args)
  (gerbil-load-expander!)
  (eval `(include ,file-path)))

xxx.ss

(extern (x schemered/yyy#x))
(display x)
(display "\n")

gerbil.pkg

(package: schemered)

I feel like I should document it somewhere... but not sure where... what do you think?

vyzo commented

Agreed, it should be documented!

Not sure where to put it either, maybe somewhere in the guide?
We can also add a new page.

I have started to writing some notes about eval. Not sure I am 100% correct and eval requires a separate page, but we may gather some practices here, so I thought "why not" :)
Closing this, we may continue to improve it in #1254