Thursday, February 19, 2009

[LSL RUNTIME INTERPRETER] 2.Research

A little further thinking and overlooking on my part has sparked some potential issues with the interpretter and how information will travel between libraries. It sounded great at first using linked messages, but then I remembered that linked messages have their own triggered event (d'oh!). So instead of doing all of the work in the listen event (or data_server event regarding notecards), I would have to constantly wait for the library scripts to return the values I want, which would make things a bit tricky. Every call would trigger the event, so if the owner said a line of code in chat like say...

llSay(0, "Name of sim is: " + llGetRegionName() + " and the name of this script is " + llGetScriptName());

Okay, the interpreter checks if the owner said something on the main channel(channel 0). The owner did, so the script enters the listen event, carrying with it the parameter values: channel, name, key, and message. The first three are unimportant for this example, but the message parameter would be set to our line of code said above. Alright! Now, let's pretend there's some sophisticated syntax checking to make sure the line of code can be properly executed. The whole line of code contains three of LSL's functions: llSay(), llGetRegionName(), and llGetScriptName()Okay, now let's say our none existant syntax checker determines that llSay is some kind of function call (just because it has parameters with it), but it doesn't really know what because it's just a string of characters and it doesn't care what it says until you tell it to with conditional statements. It would be cool and a lot easier if you could just typecast strings into lines of code by simply typing (code) or (function) infront of them. ;P

(code)"llSay(0, \"Hello World!\");"

As cool as that would be, it would be practically useless unless you were making something strange or a form of interpreter. It could also pose some security risks, but anyway...

Okay so the main interpreter script did some more parsing and comparisons on the input and identified the three function calls within that one string, smart huh? It realizes that we have some kind of function, that has two parameters, the first being of type integer or float(automatically typecasts integers), and the second being a string... a string concatenated multiple times with other functions... functions which presumably return string values. Okay, brilliant! Now what to do with this knowledge? If I go with the script library method (having all of LSL's functions listed and segregated into different scripts) then I would have to send llGetRegionName() and llGetScriptName() to the libraries with linked messages first. Otherwise llSay would treat the other functions as strings. Even the plus signs would be treated as characters! That's no good. So those two get sent first. Let's say llGetRegionName() gets sent first and link_message gets triggered in the proper library (maybe a script named sim.lib?). It compares the string with a list of strings that contain all of the simulator functions. The check matches, finds that there are no parameters with it, and performs the function. The value gets returned and immediately sent back to the interpreter script through a linked message, triggering a new link_message event... wait.. what was this script doing while waiting for that message? Well, whatever it was coded to do. Chancers are, it finished and exited the event, making all of the above pointless. So all of that syntax checking and identifying was wasted. So how do we rewind and fix it so that the current input being processed actually finishes and executes the way we want? Hm, good question.

There's the option of using a list to save our spot and everytime a new linked message is recieved, look inside of that list and replace the according function with whatever value was returned. Sounds good so far, but I'm sure there's something I'm overlooking again... Well, let's start from where we left off but only using this method of having our spot saved. Okay, the script enters link_message, looks inside of the cache list to see if anything was waiting for data to be returned. Oh look! llSay is waiting for llGetRegionName() to be returned! Bam, replace the string " + llGetRegionName() + " with whatever value was returned. Much better, but it's not done yet. There's still one function left in the string. So repeat the process and save our point to the list and send a linked message to whatever library for llGetScriptName(). Only problem with this function call is that it's going to give us the name of the library script and not the interpreter script... heh. Oh well. When it's all done we should have the string redone to this:

llSay(0, "Name of sim is: WHATEVER and the name of this script is script.lib");

Great. Now send our last function off to the libraries! Seems like a lot of work, but I'm still looking for other ways to make the interpreter able to handle functions within functions. This could all be done without my library method, but I want the main script to have a lot of memory available for those user instruction sets and saved variables that I have mentioned in my first post. 

The important thing I'm focusing on now is research. I have an example of a runtime interpreter someone has already made in LSL, but it's very limited in what it can handle. It also has a load of scripts which I'm unsure of. She may have used the same idea of making 'libraries' to handle everything rather than one script and a gazillion if statements. That's another issue I'd like to address... How will this be possible without having a if statement for every function?

I think I'll take a small break on this, because it feels like it might be a much larger project than I had originally predicted. Doesn't mean I won't be thinking about it though, and any updates or ideas will be posted.

That's all for now!

No comments:

Post a Comment