Mercerenies / gdlisp

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

Importing non-GDLisp Resources #6

Open Mercerenies opened 3 years ago

Mercerenies commented 3 years ago

This is the main issue for importing resources that are not .lisp files. This includes, but is not limited to, GDScript files, packed scenes, images, and audio files.

First, let's get the easy stuff out of the way. Syntactically, importing is very similar to importing .lisp files; we use a use statement, and it must be named or use the default name; restricted import lists or open import lists are not allowed in this case.

(use "res://Example.tscn" as Example)

Now, theoretically, all we really need to do is check that the file exists; I don't plan to do any syntax checking or anything with preexisting GDScript files, nor do I (for the foreseeable future) plan to parse GDScript and identify what functions are available; it's all duck typed for now.

However, macros are a thing. If a GDLisp macro uses a GDScript source, we need to consider mirroring that source file on the running server. Moreover, even if we don't use macros, a GDLisp source file is still loaded on the running server, so anything it loads (and any transitive dependencies, such as GDScript files which preload other resources) must exist on the server side. I have no idea how to reconcile this right now, and it completely blocks us from being able to load non-GDLisp resources.

Mercerenies commented 3 years ago

It's even worse than I thought. There are some resources that apparently can only be loaded in the editor and not in release mode, and it looks like my runner server operates in release mode. For instance,

const Example = preload("res://Example.png")

works perfectly well if you put it into a new Godot project and run it from the editor, but it doesn't work from the runner server. My guess is that Godot is internally converting the png to some other more convenient internal format, and it's not doing that if I don't open the editor.

Regardless, a temporary solution is in place. All non-GDLisp resources (which includes GDScript source files) are treated as null during macro expansion. This means that a line like

(use "res://Example.png" as Example)

will get compiled in the actual GDScript source to

const Example = preload("res://Example.png")

but for the purposes of macro expansion on the server side, it will get compiled instead to

const Example = null

So macros can't see external resources. I don't consider this a permanent solution necessarily, hence this issue is still open, but at least it sort of works for now.

The downside, of course, is that macros can't leverage files that aren't GDLisp source files. This isn't necessarily the end of the world, except that it also means macros can't call code written in GDScript. That's an unfortunate proviso, as macros can only call pure GDLisp code for now, whereas the runtime code written in GDLisp has free access to files that were originally GDScript as well.