Code Modes in Jumprope (Patreon)
Content
Greetings ponmitte. In this Saturday post we decided to delve into Jumprope a bit. In case you don't know, Jumprope is a programming language I developed to script dialogue and cut-scenes for Homestead, so if that doesn't sound like something that would interest you, then you can safely take from this post assurance that coding is coming along well and otherwise ignore it. For everyone else, this article will introduce you to a fun idiosyncrasy of Jumprope, which I will refer to as code modes. ^c^
First I will introduce you to my model. All programming languages are composed of islands of code whose respective effects are performed on different systems and at different times and thus have different environments and assumptions relevant to them. I call these code modes, and in this article I will demonstrate how this model manifests in multiple languages and how leveraging this model benefits it's host language.
The first code mode is statement mode. This is the most common code mode and represents code which represents a sequence of statements which are serially executed and produce side effects. In the example of JavaScript, this is the only code mode. All code in a JavaScript file, even that at the top level is a statement, and thus can be executed. All code in JavaScript is executed on the user of that code, usually the system which opened a web page.
The second code mode is declaration mode. This mode is utilized in more structurally strict and compiled languages like C#. This code represents a sequence of code structures which encapsulate statement mode code. This code varies from statement mode code because it is executed at build time on the programmers/builders system and modifies the state of the program executable. The islands inside this, the statement mode code, is executed on the users system and modifies the state of their memory and peripherals. In C# a method declaration is declaration mode, and the content of that method is in statement mode, as is demonstrated in the example code.
The introduction of this mode demonstrates a few important qualities of the relationship between modes.
- Where a declaration mode exists, all statement mode code must be inside it, baring syntactic sugar. The declaration mode code is the ocean and statement mode code are the islands.
- Declaration mode code cannot exist inside statement mode code. You cannot place a class declaration inside the body of method.
- All functionality you have in any given language is grouped into one of these modes, and for any given piece of code, all code it executes must be in the same mode or a lower mode.
- There is a direct hierarchy of these two modes. And you can only return to a higher mode by ending the current mode.
- You can assume that the code of a given mode will always execute in an environment which conforms to certain assumptions. For example; all class declarations will only be executed on a system setup for compiling C#.
This brings us to the final mode, expression mode. This is a mode containing code which is safe, that is, executing it does not have any visible side effects beyond pushing a return value onto the stack. This is functionality like addition, as is present in basically all languages as 1+3 and will then return 4, and code of this style is indeed safe, but cannot be considered it's own mode, because it could look like this 3+functionWhichHasSideEffectAndReturnsNumber(). Because this code would be calling code which does not conform to our definition of the expression code mode, since it is calling code which is not safe, it itself does not conform to our definition of expression mode code. This is where Jumprope comes in. As you can see in the above diagram, Jumprope does enforce code of this nature as in expression mode, and thus implements all the requirements which we have defined for a code mode.
Here is what that means for the Jumprope language
- Syntax level distinction. There is a concept of each code mode in the parser to ensure that code modes are placed in the correct place, and that is indeed the case in Jumprope. Just like you can't put a class declaration inside a method body in C#, you can't put a variable assignment inside a function in Jumprope.
- There is a deep difference between safe and unsafe callable bodies of code and most languages have no concept of the difference between the two. Jumprope is able to apply this concept due to the separation between statement mode code and expression mode code. In jumprope an unsafe callable body of code is called a subroutine and a safe callable body of code is called a function. Each is distinct in their identity, syntax, and functionality.
- Different nature of execution for expression mode code. Statement mode code in Jumprope is designed to be highly transparent to asynchronicity, aka. execution spanning multiple updates. Expression mode code on the other hand is synchronous, all code in a expression mode island executes in one update. Thus the fundamental nature of execution varies for each part.
- You can only go down in hierarchy. You can know with certainty that all expression mode code is safe and can only be executed in expression mode, thus you can never accidental make a function unsafe by calling code from a mode higher in the hierarchy.
There are a few benefits to this approach.
- You can never accidentally make safe functions unsafe.
- You can guarantee that all expression mode code will executed synchronously and return a value instantly
- You can make syntactical optimizations. For example foo+1 in statement mode increments the variable foo by 1, but in expression mode, it returns whatever number is one grater than foo, but does not modify foo. Thus you have added twice the functionality for the same syntactic cost.
- You can structure all functions as one-liners. In most languages, you have to support both mutation operations and safe operations inside every function, but since you can assume that the return value is all that is relevant, you can add features to make for more elegant one-liners. When writing safe code in such languages, the only reason to break code up into separate statements is to store a value in a variable which is referenced in multiple places. This use case is satisfied by the let expression, which is much cleaner.
- Expression mode code can be used outside of a full Jumprope program. Because you do not need to implement the breadth of functionality in expression mode code, you can safely and confidently use it in any situation where you want to do a safe computation. Which is quite handy for interactive development.
- Optimizations. This provides more channels for optimization when it comes to things like memoization and type inference.
In summary. I believe that there is a deep and profound difference between safe code and unsafe code, and introducing a language level separation between these structures is very beneficial, and doing it on Jumprope has increased my confidence in that position. I suspect this approach will not become commonplace in other languages, since it requires such profound change to it, but it is at least fun and useful in my case. I hope this you guys had fun with it too. ^c^
~ ErrorStream