[gameprogrammer] Re: Scripting engines: Upvalues and function refs

  • From: Stephane Marchesin <stephane.marchesin@xxxxxxxxxx>
  • To: gameprogrammer@xxxxxxxxxxxxx
  • Date: Sun, 04 Apr 2004 16:08:48 +0200

  David Olofson wrote:

>Dunno if this is the best list for this question, but I guess some 
>people around here have some experience with implementing scripting 
>engines. (And either way, if this gets through, it means I'm still on 
>the new list. ;-)
>
>Anyway, here goes:
>
>I'm hacking a new version of EEL; the scripting engine used in 
>Audiality. (A major rewrite. This one's using a mostly RT safe 
>virtual machine instead of executing from the source.)
>
>       A. I have local functions with upvalues. (Full
>          lexical scoping, implemented by backtracing
>          the call stack.)
>
>       B. The top level of a source file (module) is
>          compiled as a top level functions, so any
>          "top level" functions are actually local
>          functions to that module.
>
>       C. The language supports only dynamically typed
>          variables at this point. (Statically typed
>          variables on the TODO, for performance and
>          improved compile time error checking.)
>
>       D. Function calls can be either "hardwired" at
>          compile time, or called through references.
> 
>
>Now, if you consider the above, you'll probably realize that this 
>causes some problems:
>
>       1. When calling via references, you have no clue
>          what you're calling at compile time. (Not a
>          major issue in itself, though the run time
>          checking will impact performance a bit.)
>
That's more a feature than an issue, IMO :)

>
>       2. All directly callable functions are actually
>          local functions, and may try to use upvalues.
>          What looks like global variables in a module
>          are actually locals of the top level function,
>          and "normal" functions access them as upvalues.
>
Attach an implicit reference to the corresponding context to the function.
i.e., if a function calls upvalues, it has a reference to the 
corresponding frame(s).

>
>       3. You can't easilly tell what register frame to
>          pass as "upvalue frame" to a function.
>
First, look at the implicit reference(s), the go through the call stack.

>
>       4. You may end up violating the scoping rules,
>          trying to call functions that are not callable
>          from the current context. (Even if you grab
>          the function reference when the function has
>          a valid context, that context may no longer
>          exist when someone decides to call via that
>          reference!)
>
I think a reference counter would do. Although you would need one 
counter per object, it's probably more realtime safe than a garbage 
collector.
(and of course here, the implicit reference that a function can have on 
a given frame must also be counted).
I tend to dislike garbage collectors (probably since the time of the 
amstrad CPC, where your program written in basic would slow down to a 
crawl when the garbage collector kicked in) but that's just a personal 
view :)

In both cases, you might also need to handle the "cyclical reference" 
problem, where two or more objects are kept alive only because they have 
references to each other (that really depends on your language, whether 
or not you have objects able to reference themselves).

Stephane



Other related posts: