The goal behind this project was to implement the mathematical model behind a programming language - our language being Python. We thought this would be very easy since Python was such a popular language and we were pretty familiar with it. But there are are just so many intricacies about the Python language.
If you don't want to look at our Walmart remake of something beautiful, allow me to redirect you directly to the original paper and model which is much much much better and complete than what we created. Since this page is pretty long, this is your chance to leave.
Now that you've had your chance to leave, allow me to highlight some parts in our model.
All of the code is in this Github
Our main takeaways from the paper were regarding scope in Python, which is used in a way that's unique to Python and doesn't quite work the same in pretty much every other programming langauge. We also targeted the pass-by-reference data representation of data - a concept related to Python's weird scoping rules. We also implemented a two-register system - which returns the current expression and a store.
This model was made using Racket (a super popular language) and using Redex, a package that is commonly used to implement models of programming languages.
If we start at the top,


Reference 1
The define-language section is our creation of this model. Here we're defining every possible thing that can be created, such as variables, expressions, types, primitive functions. Using these, we want to define the behavior of Python using this language base when we see certain keywords (see Github for examples).
So this is what's going on:
There's some more various parts that aren't really too relevant because we either don't implement them or they're not very important, but this is our model language called λπ!
There's a lot of stuff covered in the paper that we look over and didn't really cover in depth since they were pretty basic. They're all implemented in the model if you want to check it out but otherwise I'm only going to give a quick summary.
Figures 2, 3, 5, and 6 define creating and accessing identifiers and objects in Python. The paper defines the mathematics and logic behind these operations pretty clearly so we implemented them as is, for the most part. Figure 4 defines the primitive operations on a list, but since our focus for this project wasn't on lists, we decided not to implement this.
Here's a quick summary of these figures:

Reference 2
So the type implementation we see here defines the object using the same three categories as defined in our triple values from Reference 1. The first field of the type is the name of the class (in this case X), the second field is the metavalue (where X is an instance of an object), and finally in the third field is the list of methods that this object holds, so we initialize our object using an empty dictionary since we aren't given what methods the object has.
Now this is what most of our focus was on. Figure 7 was undoubtedly the most interesting and complicated part of this paper. Although it's just one function - and a pretty basic one at that - it took a lot of understanding to determine what it's doing. Figure 7 defines the algorithm for field lookups on classes


Reference 3
As you see here, our code pretty much matches exactly the description of the GetField-Class method in the paper. There's a lot of helper functions that we created, but they also match the mathematics closely.
When the model looks for a method within an object, it will either find it or it doesn't. If the expression exists, it will simply get you that method. But otherwise, it will use the "__mro__" (method resolution order) field to determine where to find the field. This field isn't ever defined by the programmer and is done automatically. The "__mro__" field is set to be the inheretence graph of the current object - all the parent objects for this current object (e.g. monkey -> mammal -> animal, so the monkey's "__mro__" field will be set to include the class and methods of the mammal class and animal class).
As seen in Reference 3, the GetField-Class also has helper functions class-lookup, class-lookup-mro, and fetch-pointer.
In order of most to least self-explanitory, these are what the helper functions do:
As a quick side note, probably the most comedic thing about this paper was their description of undefined values. THe actual concept itself was pretty bland but the paper continuously referenced this nonexistent value as skull (no literally: ☠ was written everywhere - page 2 of the pdf). It's really humorous to consider that undefined values are literally symbolized by death (thinking about how much my programs error due to uninitialized variables). That's about it. There's not really much to say about it - I just wanted to highlight this aspect of the paper (great writing).
Here are some examples of the traces (basically Redex breaking down our program to show what's happening) of our model. There are some helpful arrows that show the order the program is running. The most important thing to pay attention to is the top of each box, or the first element of each expression, which shows what function is about to run.




