Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
How to initialize variable assignment in a non-OOP interpreter?
I'm still in the process of making MarkFuncs and having given up from copy-pasting open-source interpreters, them using OOP too, I decided to make one without OOP and with scratch alongside with the help of @Moshi in the Discord server.
test4
is where I'm currently at right now. interpreter.py
currently has an output syntax for strings, and 2 functions that solve a challenge each in Code Golf CD. Right now, I want to do some math, in other words, deal with integers. The first problem to encounter, however is variable assignment.
I still have no idea how to get a specific keyword stored into the program and its value, then be reused and/or outputted. Here's what I have in mind for the syntax to be like:
x=9;y=10;→x+y; # Full program
x=9 # Assign 9 in variable named x
; # Semicolon to terminate the assigning process
y=10 # Assign 10 in variable named y
; # Semicolon to terminate the assigning process
→x+y # Output the sum of x and y (uses the in-progress calculate() function)
; # Semicolon to terminate the outputting process
This will be put in the Input section of the TIO link.
Since I'm not using OOP--and I want to keep it that way--, it'll be tricky to even make variable assigning possible, and that's why I need help here.
Question: How to make variable assigning possible in my Python-written interpreter?
1 answer
I honestly have no idea why you feel that OOP would be necessary in order to keep track of variable assignments in a language interpreter. People wrote both interpreters and compilers long before object-oriented programming was even invented.
It might help to start by going back to what a "variable" in a computer program actually is in the first place.
A variable name is a symbolic name for a memory location, typically associated with a data size and some kind of semantic about the type of data stored at that memory location, or semantic about how what is stored at that memory location should be interpreted by the program.
Some languages, particularly older ones such as BCPL, have only a single data type, and thus don't need to keep track of the size or type of the data. In these cases, a variable name becomes simply a symbolic name for a memory location.
Either way, by consequence, a variable is simply a memory location.
It's possible to combine the "data size" and "type of data" into a single representation; for example, if you keep track of the fact that a variable name refers to a memory location holding a "16-bit signed integer value", then there is no need to separately track the fact that it's "16 bits" and that it's a "signed integer". There are pros and cons to tracking size and type together or separately; which way you do it is a design decision to be made for your interpreter implementation, and done right, the decision should have no impact on the behavior of a program that is being interpreted.
Since you are mainly interested in integers, you can take the BCPL approach; define a standard integer type for your language and leave it at that. For example, you could declare that every variable is a signed 64-bit integer; in C parlace, an int64_t
. (Apparently, in Python, int
type integer variables are of unlimited magnitude.)
That only leaves mapping from a name to its value within the program being interpreted.
As hkotsubo suggested in a comment, an obvious way to do that within a modern programming language and runtime such as Python is by using a dictionary to map from one to the other. The key (for the dictionary entry) becomes the variable name, or some transformation of the variable name that somehow includes its scope, and the value (of the dictionary entry) becomes the value held by that variable within the program being interpreted.
Once you want to support multiple types, simply replace the dictionary entry value with something like (in Python) a dict
instance that includes both type and value. Other languages have different names for much the same concept; for example, C-derived languages like C, C++, Java and C# have struct
(some also have class
), and Pascal and derivatives such as Ada have record
. The concept remains the same: the value that your interpreter is keeping track of itself contains information on both the type and the value of the variable within the scope of the program being interpreted.
1 comment thread