Racket 代码生成器

Racket 代码生成器通过 REPL 命令访问:

Main> :set cg racket

或者,您可以通过 IDRIS2_CG 环境变量进行设置:

$ export IDRIS2_CG=racket

您可以在 REPL 中将类型为 IO () 的表达式 expr 编译为可执行文件,如下所示:

Main> :c execname expr

...其中 execname 是可执行文件的名称。这将生成以下内容:

  • 调用程序的 shell 脚本 build/exec/execname

  • 一个子目录 build/exec/execname_app 中包含运行程序所需的所有数据。这包括 Racket 源代码( execname.rkt )、已编译的 Racket 代码(Windows 上的 execnameexecname.exe )以及外部函数定义所需的任何共享库。

可执行的 execname 可以重新定位到任何子目录,前提是 execname_app 也在同一个子目录中。

你也可以直接执行表达式:

Main> :exec expr

同样, expr 必须具有 IO () 类型。这将在 build/exec 目录中生成一个临时可执行脚本 _tmpracket ,并执行该脚本,而无需先编译为二进制文件(因此会解释生成的 Racket 代码)。

Racket 指令

  • --directive extraRuntime=<path>

    将来自 <path> 的 Scheme 源代码直接嵌入到生成的输出中。可以多次指定,在这种情况下,所有给定的文件都将按指定的顺序包含。

    ; extensions.scm
    (define (my-mul a b)
      (* a b))
    
    -- Main.idr
    %foreign "scheme:my-mul"
    myMul : Int -> Int -> Int
    
    $ idris2 --codegen chez --directive extraRuntime=/path/to/extensions.scm -o main Main.idr
    
  • --directive lazy=weakMemo

    使所有非顶层 LazyInf 值被*弱*记忆化。也就是说,一旦这个表达式在运行时被求值,在后续访问时允许不重新计算,直到记忆化的值被垃圾收集器清除。垃圾收集器可以自行决定是否收集弱记忆化的值,因此当没有可用内存时,弱记忆化的值可以被清除。这就是为什么它比完全记忆化更安全。