|
Post by aurel on Aug 15, 2023 12:52:23 GMT -6
..in interpreter
hello boys...n00b
me and the gangs on basic4us forum talking about how to add user defined function in interpreter or functions with local variables
can you made observation? what is good ..what is bad ? thanks
ps ..i hope that i not bothering you?
|
|
|
Post by n00b on Aug 15, 2023 14:53:54 GMT -6
I can try to cover how I would handle this. I am not going to go over how to tokenize it just to try to keep this short. I am going to use C++ since I think it would be easier to read for this example.
Inside my interpreter code I would have some arrays setup to store variables and functions:
struct interp_variable { string name; int type; // 0 is a number and 1 is a string string scope; // this is a string that will identify where the variable can be accessed // if type is number then we will use n_value // if type is a string then we will use s_value string s_value; float n_value; }
interp_variable user_variables[99]; // all the variables in the program int user_variables_count = 0;
struct interp_function { string name; int args[99]; // each arg will be a number for the index in the user_variables array int args_count; // number of arguments in the function int line_number; // the line number to jump to for this function, it will be the line after the function is made }
interp_function user_functions[99]; // all the functions in the program int user_functions_count = 0;
Now lets assume we have the following example:
def_fn myFunction(a, b) ... code ...
endfn
So for the above example we would create 2 variables in the user_variables array and store the index to those variables as args in the user_functions:
NOTE: All the following would probably be in a loop in your code. I am typing it all out here to make it obvious whats happening.
user_functions[ user_functions_count ].name = "myFunction"; user_functions[ user_functions_count ].line_number = current_line + 1; // current_line would be the current line being parsed
int args_count = 0;
user_variables[ user_variables_count ].name = "A"; user_variables[ user_variables_count ].type = 0; // this is saying "A" is a number variable user_variables[ user_variables_count ].scope = "main.myFunction"; user_variables[ user_variables_count ].n_value = 0;
user_functions[ user_functions_count ].args[ args_count ] = user_variables_count;
user_variables_count++; args_count++;
user_variables[ user_variables_count ].name = "B"; user_variables[ user_variables_count ].type = 0; // this is saying "B" is a number variable user_variables[ user_variables_count ].scope = "main.myFunction"; user_variables[ user_variables_count ].n_value = 0;
user_functions[ user_functions_count ].args[ args_count ] = user_variables_count;
user_variables_count++; args_count++;
user_functions[ user_functions_count ].args_count = args_count;
user_functions_count++;
Inside your program, when the function is called you would want to set the functions arguments and then jump to the line number stored in the function. You should use a stack to store the current line so you can return to that line when "endfn" is reached.
So if we called the function like this:
myFunction(3, 7)
Then we would want the parser to do something like this:
for(int i = 0; i < user_functions_count; i++) // loop through all the functions to find one with the name "myFunction" { if( user_functions[i].name.compare("myFunction") == 0) { line_stack.push(current_line); current_line = user_functions[i].line_number; NOTE: You should probably loop through user_functions[i].args[] here but I am typing it out to make it obvious what is happening int arg_a = user_functions[i].args[0]; user_variables[arg_a].n_value = 3; int arg_b = user_functions[i].args[1]; user_variables[arg_b].n_value = 7; break; } }
This is basically how RCBasic's parser works. I would also suggest that you try to replace string comparisons with integer comparisons wherever you can to optimize for speed.
|
|
|
Post by aurel on Aug 17, 2023 5:27:37 GMT -6
WOW Thank you very much You really give me very simple but great explanation
Just one thing. You use term line_number ,,,can i replace it token_position because all my code is based on token positions in token array I think that should work the same ? Also ..as i think before i need extra variable list or array for function arguments and should not be i problem.. Once again BIG THANKS !
|
|
|
Post by n00b on Aug 17, 2023 19:00:10 GMT -6
You use term line_number ,,,can i replace it token_position because all my code is based on token positions in token array I think that should work the same ? Yeah. I just used line number because I assumed thats how you were storing the code but you just want to store the location you are jumping to. You want to push the current line onto a stack so that you have the location you want to return to. The reason why it needs to be a stack is because you may need to store more than one location if you are using multiple user functions back to back. When you reach endfn, just pop the last location you pushed off the stack and go to that line/token.
|
|