Recursive functions

posted in noaktree leaves
Published July 09, 2005
Advertisement
Functions look inside to find answers...

Hey I've got functions that return values to work in my scripting language. I wrote this little test script to demonstrate how functions look and work in my language.

function int Test_Add(int a, int b)
{ return a + b;
}

function int Recursive_Test(int a)
{
if(a > 0)
{ print "Recursive call";
return Recursive_Test(a - 1;);
}
else
{ return a;
}
}

function void main(void)
{ int x = Recursive_Test(5;);
print x;

x = Test_Add(5; 5;) + 2;
print x;
}

Output:
Recursive Call
Recursive Call
Recursive Call
Recursive Call
Recursive Call
0
12

The entry point is main(). Functions are declared similar to C syntax with the added function keyword. A function is called the same as in C except a semicolon is needed after each parameter. Parameters can be complete expressions that may include other function calls.

Next I'll bind C functions to the language so it can be useful.
0 likes 6 comments

Comments

NickGeorgia
Nice, someday you'll have to write about how you use a scripting engine in a game... and how you made it yourself. Please doooo :) I would like to know.
July 09, 2005 09:42 PM
Rob Loach
Any clue of a name yet? I was thinking you were going to name it something tree-like since you seem to be a tree person. Scripting Roots, BrachScript, etc.
July 09, 2005 10:28 PM
noaktree
Quote:Nice, someday you'll have to write about how you use a scripting engine in a game... and how you made it yourself. Please doooo :) I would like to know.
Thanks Nick! I hate writing about how I do things. It bores me to no end. I have tried so many times to write articles. I get started and then... well they just sit there.

But basically I've always used a scripting language by binding application functions to the scripting language. I can then get data from the application by calling Get_Data() from the scripting language and controlling objects or events in a similar way. Often I will have scripts executed (from within the app) when an event is triggered. Scripts can be called for scene setup or any other thing you can think of.

I have created my language by first turning the script into a list of parsable tokens. I push every non empty-space character into a buffer. I use a set of token terminators (; , " . etc.) to determine when the buffer is to be made into a token. The token's type is determined during the creation process. The token type may be unknown. It is during this token parsing that I build a list of function token indices. I use this in the next step.

In the next step I build a function map which stores parameter, return, and token location for all functions found during the tokenizer parsing.

Because my language is interpreted. The next step is to execute the tokens as it parses the list of tokens. This parser or interpreter starts by calling Parse_Tokens(). It is given the function map and the token list. It then begins execution by calling Parse_Function(... "main"); All code is stored inside of functions in my language so it starts at the main function.

The function parser contains its own variable map which is a class designed to allow scoped memory. This variable map stores 'script variables' as a struct which allows integer, float, float2, float3, float4, string, and struct types. The function parser is responsible for executing an entire function's code block and so must handle control statements, conditional parsing, expression parsing, variable declaration, etc. There is really too much going on here to discuss in detail and it calls many helper functions to get the job done. If the return keyword is used with a value and the function is not of type void then the return value is pushed onto a special stack that the code block which called this function can access. This function may call itself in the event that a script function call is made within its code block. This makes the parsing of the tokens a recursive rather than iterative process. I am still debating whether to make it iterative because of possible stack overflow but I think that implementation would be more likely to make me crazy.

Next I'll be binding C functions. I think I'll handle this similar to the way Lua does. It will require that I define two classes of functions (local, external) in the function map. You should note that I am in no way a scripting expert. This is my first time making a language and I may be doing many things wrong.

Oh I forgot to mention that before creating the tokenizer you should define your language in some form such as BNF. I use a hybrid BNF to define my language. My definition seems to always be changing in small ways. But it has served as a good guide along the way to implementing this language.

I hope that helped some. [smile]
July 09, 2005 11:16 PM
noaktree
Quote:Any clue of a name yet? I was thinking you were going to name it something tree-like since you seem to be a tree person. Scripting Roots, BrachScript, etc.
That's a good idea Rob. It's been driving me crazy coming up with a name this time.
July 09, 2005 11:18 PM
Daerax
Knowledge HOARDER!!! If life was an RPG you'd be one of those mages who locks themselves up in a tower guarded with powerfully lethal spells, hehe. I demand more details.

Serioulsy though, there is a great dirth of concise, clear information on scripting language construction. Please fill it?

For a name I said Y, and you said Ynot. How about Y∅ as in Y knot
or Y subzero as in Y0
July 10, 2005 02:11 AM
NickGeorgia
Yeah thanks Noak! That does help a lot. Details would be nice, but I don't wanna cause you too much extra work. I'll go do some researching myself. Keep letting us know the progress and info on some of the finer details if you can. :)
July 10, 2005 10:07 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement