Implementing partial functions

This next section I had a lot of fun with, and originally I didn’t plan on implementing it at all. The only reason I did it is because I had a stroke of genius while in the shower one morning. Today, I’m going to talk about how I supported partial functions in my toy programming language.

First let’s look at what a partial function looks like in my language. I took an F# approach where any function whose argument count is less than the declared count becomes a new function (even though F# functions are curried by default but mine are not). For example, in ML type notation you could have a function of type

'a -> 'b -> 'c

Which means that it takes something of type a and type b as arguments, and returns a type c. If we pass this function only a 'a then it’ll return to us a new function of type

The partial variable is a function who now expects only 1 argument (since the first string argument to func was already applied). This outputs

guy
1
guy
2
girl
3

Manipulating the syntax tree

If a function invoke AST has fewer arguments than the corresponding method symbol it’s paired with then it needs to be partially applied. [Note: I should mention that partial functions and currying are not technically the same, even though in practice the terminology is interchangeable. I only realized this after I named all the functions, so even if things are called “curry” this and “curry” that, it really means “partially apply”]

The captured argument becomes a variable declaration of the same name as the argument name with the value that was captured! At this point the rest of the code works as is, because what does it care if it was defined this way by the user or by tree manipulation? It doesn’t. There is one caveat. I created the concept of “converted expressions” for syntax trees. This means that what used to be a type inferred variable declaration, should now be treated as a method declaration. This is important. partial (in our original example) is no longer a variable, it is now a method. When I go to interpret this syntax tree, and use type definitions, I first need to check if the tree has been converted to something else (via the converted expression property).

Building out the partial function

Building the actual partial function isn’t that hard.

For each captured argument create a variable declaration syntax tree representing the argument name and the argument value

Resolve the argument symbol. If the passed in argument was a user defined value, we need to validate that the type of that user defined value matches the expected type of the argument we are capturing.

Add the new variable declaration to a list

Create a new method where the variable declarations we just made are prepended to the original methods body

From here on out we can treat this method just like any other regularly declared method. The MethodSymbol type of the original method has a reference to its source syntax tree. This way we can get access back to the data that this method symbol contains