Mercerenies / gdlisp

Lisp on the Godot platform
GNU General Public License v3.0
140 stars 1 forks source link

deflazy in imported macros #56

Closed Mercerenies closed 2 years ago

Mercerenies commented 2 years ago

As a follow-on to #50, as of bfa7f47c1eb74dde7e4a15f4eee12abeda9d5f59, deflazy can be used only during runtime. Specifically, consider the following code.

(deflazy foo 1)
(defmacro bar () foo)
(bar)

The deflazy compiles to a private function and a symbol macro. Then bar is literally compiled to

static func bar():
    return load("res://REPL.gd")._lazy_0()

(Assuming this code is running in a REPL and _lazy_0 is the name of the private function in question; these conditions are true in a freshly-opened REPL)

This expansion of the symbol macro foo works perfectly well at runtime, but bar is going to be evaluated at compile-time, during the macro expansion phase, and at that time, the name res://REPL.gd is certainly no good.

Mercerenies commented 2 years ago

This issue concerned a lack of ability to distinguish between which file we wanted to load and which loading mechanism we wanted to use. The existing this-file, this-filename, this-true-filename mechanisms all determine the filename at evaluation time, in the current file and context.

deflazy necessitated the need to determine the filename from one context (i.e. the context where define-symbol-macro was defined) and to determine the loading mechanism from another context (i.e. are we calling the symbol macro from a macro expansion or from the standard Godot runtime). The contextual-load macro decouples this mechanism. It is a macro which takes a literal string as argument and conditionally transforms it. We evaluate this-true-filename in the symbol macro and then return an S-expression containing the result of that passed to the name contextual-load. The contextual-load gets evaluated in the calling context, allowing us to conditionally resolve the preload to a virtual macro name if necessary.

The underlying mechanism for contextual-load is the special form sys/contextual-filename, which is not exposed as the macro is already deadly enough without exposing the internals directly. We should probably make the system directive a bit safer (currently, it can panic on a bad filename).