KSP-KOS / KOS

Fully programmable autopilot mod for KSP. Originally By Nivekk
Other
697 stars 230 forks source link

A way to allow a RUN statement to work on runtime-changing instructions. #1257

Closed Dunbaratu closed 8 years ago

Dunbaratu commented 8 years ago

Currently (0.18.1 and before) You cannot RUN on a varying filename string.

i.e. you can do this:

run myprog.

but you cannot do this:

set filename to "myprog".
run filename.

And the main reason for this restriction is that the compiler, at compile time builds the thing we've been calling the "maybe compile function" in the program header before the values of variables are known and it needs to know the hardcoded filename at that time, because it's using that to choose the name of the program instruction pointer variable.

But this seriously needs to be fixed before we can allow multiple directories to work.

Here's one approach: When the compiler builds the "maybe compile function", instead of building one per instance of run, just build one global one only, no matter how many run statements there are. However, make it able to receive the name of the program instruction pointer variable as an argument. This is essentially an indirect pass by reference (i.e. pass in the instruction pointer variable so it can be set by the maybe-compile-function, rather than its value). Such a pass by reference would be impossible in kerboscript directly, but we can do it in the underlying kRISC, by just pushing the variable name as a bareword string with an asterisk at the end of it.

gisikw commented 8 years ago

Mind pointing me at the "maybe compile function"? I've been trying to trace it up, but got myself a bit confused, but would love to take a look at this, especially as it would offer a workaround for the lib_exec breakage (since users could time/version-stamp files prior to execution).

Dunbaratu commented 8 years ago

@gisikw In general one hint about getting a dump of what the actual opcodes of a program look like is this: Just put a runtime-error in the bottom of the script - something that will compile but will barf when it runs it. I usually use print 1 / 0. to force a divide-by-zero runtime exception for this purpose. Anyway, the point is that when you get such a runtime exception, the program dumps a bit of the program out to the output log file as part of the error. If you're running the debug DLL (the one compiled from source here, rather than the public one) then it tends to print the entire program's opcodes out (the public one just prints a few lines of context, I believe) on any runtime error.

If you want to look at the section of the compiler that builds this "maybe compile function", it's in this file: src/kOS.Safe/Compilation/KS/Compiler.cs -- look for a method titled PreProcessRunInstruction()

That method has a big chunk of opcodes it inserts into the program that effectively does this:

Create a low level "function" that will be put into the the top of the program as follows:

Then when you actually visit the run statement for real in a later pass of the compiler (the method called VisitRunStatement), where the 'run' command was, you should make an OpcodeCall to the above pre-built maybe-compile-function.

It's a bit messy because of the indirect call inserted here - when you run a program it needs to nest two sets of arguments and arg bottom markers onto the stack because of the intermediary 'maybe-compile' function that happens before the actual call to the program.

Dunbaratu commented 8 years ago

Just a warning, the thing I intend to make a PR for tonight may affect the method mentioned above so be careful to re-read it after that PR is merged.

gisikw commented 8 years ago

Cheers!

Dunbaratu commented 8 years ago

oops - it's called PreProcessRunStatement, not PreProcessRunInstruction.