I am developing my own experimental scripting language with a view to implementing it in my larger application.
Almost everything I wanted to do was programmed smoothly, but the “simple” act of storing variables in memory turned out to be the most difficult here. I do not know how to store them in order to allow all type checks, global variables and special flags. First look at the sample code:
a = 1 b = 2 someFunction() print(a) --> This should read the global variable and print `1` a = 3 --> Now `a` should become a local variable of this function and the global `a` remain unchanged x = 4 --> `x` should always be local of this function end
I call the "locality" of variables their level , so the variables in the nested blocks have a higher level. In the above code, a and b are level 1 variables. The local variables someFunction will have level 2. The first line of the function should read the global variable a (level 1), but the second line should create a variable again called a , but with level 2, which obscures global a from now on. The third line should create a variable x with level 2. How to store and track all this in memory?
What I have tried so far:
Method 1. Saving variable=>value maps in an array of levels:
variables { level=1
But this will make the variable search very slow, since you need to search all levels for a given variable.
Method 2: save pairs (variables, levels) as map keys:
variables { (a, 1) => 1,
This has the same problem as before, because we must try a pair (variable, level) with all possible levels for this variable.
Which method should be used for optimal memory usage and quick access?
Additional notes:
I know how variables in the stack and heaps are controlled in other "real" languages, but it's hard for me to do this in an interpreted language. “It doesn't have to be the way Lua and Python do,” I always think. Correct me if I am wrong. I am trying to save a variable in maps and C ++ internal structures.
And finally, this is how I represent the variable. Do you think this is large and might be more memory efficient? (I also tried to put “Level” as a member here, but he had the same problem as the others).
struct Member { uchar type; //0=num, 1=str, 2=function, 3=array, etc uchar flags; //0x80 = read-only, 0x40 = write-only, etc union { long double value_num; char* value_str; int value_func; //etc }; };