Mercerenies / gdlisp

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

GDScript Built-in Functions with Varargs #79

Closed Mercerenies closed 2 years ago

Mercerenies commented 2 years ago

Similar to #78, some GDScript built-in functions like print take variable arguments. The signature

(defn print (&arr args))

looks superficially close but will not behave correctly after a #' is applied to it. Consider how to encapsulate these functions.

Mercerenies commented 2 years ago

For varargs functions, we observe that all of the existing varargs functions in GDScript are trivial extensions of an equivalent unary function. That is, str simply applies str to each argument and concatenates, print simply prints each argument separately on one line, etc. This covers str, print, printerr, printraw, prints, and printt.

So, for all such functions, we will write an explicit wrapper that does the exact same thing. For str, this will be

(defn str (x &arr args)
  (sys/call-magic VARARG-STR)
  (let ((result (str x)))
    (for arg args
       (set result (+ result (str arg))))
    result))

Then the call magic, naturally, calls the GDScript function explicitly. (Note: str is explicitly required to take at least one argument in GDScript; functions like print which can accept zero will be reflected as such in their implementation as well) We'll treat all built-in GDScript function names as keywords (#88), so the function str we've defined in GDLisp will get called _str in GDScript, and our delegation to the original str will work as intended.

The only vararg function that doesn't fit into this mold is range. And I'm not sure why range is documented as a vararg function in the first place. It takes one to three arguments, so I'll probably just translate it as though it has optional arguments, not varargs (i.e. using whatever our solution to #78 ends up being)

Mercerenies commented 2 years ago

This solution has been implemented and tested for str (e7d45c9). Once we've done so for the other varargs functions, this issue will be closed.

Mercerenies commented 2 years ago

All vararg functions (except range, as discussed above) have been implemented as of c96064a.