Javaish: An English-like Programming Language Nathaniel Kemme Nash March 2024 1 Summary Programming languages are essential for communicating with computers, and new ones are constantly being developed. However, learning a programming lan- guage can be difficult, especially for beginners. Javaish is a new programming language that aims to make programming more accessible to beginners. Javaish has all the fundamentals of a programming language: a parser, an interpreter, and an integrated development environment (IDE), but it also has a translator, debugger, and robot integration which makes it a better choice for beginners. It is designed to be more readable and understandable than traditional pro- gramming languages while still providing the same functionality. Javaish can potentially make programming more accessible to a wider range of people. 2 Background This paper explores the creation of a new programming language called Javaish. A programming language is a way for programmers to communicate with a computer using a language that both the programmer and the computer can understand. Programming languages have been around for some time, and new ones mostly focus on efficiency and simpler syntax. 3 Problem Learning a new spoken language is very hard. Programming languages, with difficult grammar, is equally challenging. The technical difficulty of program- ming language creates a barrier to entering the world of programming and can cause people once interested in computer science to lose interest. Block coding is one attempt at lowering the barrier to entry. However, block programming is very limited in its capabilities and is not widely used in the real world. In addition, the similarities between block coding and programming languages are few. Unfortunately, the skills learned from block coding do not translate well enough to the skills needed for programming languages. 1 4 Solution Javaish is a programming language designed to bridge the gap between English and programming. Javaish closely matches the grammar of English which makes it easier for beginners to master. In addition, Javaish is not block coding; it is a text-based programming language. As a text-based programming language, one will learn necessary skills in Javaish that can be transferred to any popular program language. 5 Features Javaish has many features that make it a very useful programming language. The three major innovations Javaish has that most popular programming lan- guages don’t have are a built-in translator, debugger, and robot integration. The built-in translator allows for Javaish code to be translated into Java or Python. This makes Javaish a viable programming language that beginners can use and then they can translate the code to run it on another application. The translator can also help in the process of a beginner learning Java or Python be- cause they can write code in Javaish which they already know and then translate it to Java or Python and see how the syntax varies. The built-in debugger allows programmers to easily visualize how the code is being executed. The debugger executes the program line by line and shows the state of the program after each execution. The programmer can then change variable values and add items to lists to see how the changes would affect the program. The debugger can also go back and execute previously executed lines with the changed variables to show how the changes affected the program. This makes it easy to identify and find a fix for logic errors without having to change and run the program repeatedly. The robot integration allows for a simple way for programmers to see their code in action in the real world with only writing two lines of code. It is common for most ways of running code on robots to write a lot of code just to connect to the robot and the lines of code to make the robot do actions are long and complicated. In Javaish, the robot commands are as simple as two words “robot move().”. Some of Javaish’s smaller features are its’ easy-to-read error messages that tell you what went wrong and where and are very easy for beginners to under- stand, behind-the-scenes conversion of integers to booleans, and easy setup. 6 Design Making a programming language is a great undertaking. To be successful, this project needed to be broken down into small, manageable parts. The main three parts of a programming language include grammar, parser, and inter- preter/compiler. 2 The Javaish programming language includes a grammar, a parser, and an interpreter, but it also has a unique IDE, debugger, translator, and robot in- tegration which will make Javaish great for beginners. Javaish was written in about 20,000 lines of code over 3 months. The following sections are an examination of each part of the building and design of the Javaish programming language. 6.1 Grammar The most important part of a programming language is the grammar. Just like in English grammar, there is a defined grammar in all programming languages to dictate the specific rules for writing code. Using Java as a baseline, which is a very popular programming language, but isn’t made for beginners. Javaish’s grammar needed to be more friendly, so the grammar of Java was mixed with English’s grammar. To make Javaish grammar more like English and less like Java, the follwing changes were made: 1. Each line of code ends with a period instead of a semicolon as used in Java. 2. To make the language more similar to English, simply use the word “equal” instead of using the symbol and the same goes for other popular symbols like “plus” for the plus symbol and “greater than” for the greater than symbol. 3. When mutating variables in Java, to add 5 to x looks like this: “x += 5;” which isn’t like English at all and can seem confusing to beginners, so in Javaish, to do the same thing, the code is now “add 5 to x.” 3 Java int x = 5 + 3; x += 5; if( x > 5) { x -= 4; } Javaish let int x equal 5 plus 3. add 5 to x. if x greater than 5 { subtract 4 from x. } English x is 5. add 5 to x. if x is greater than 5 then remove 4 from x. Javaish is much closer to English than Java is. The grammar of Javaish is meant to resemble the sentence structure in English making it more natural for people to read. When reading Javaish code, it is written very similar to how you would speak the code. As seen the figure above, Javaish is a mix between Java and English, it has curly brackets like Java, and Javaish ends in periods like English. 6.2 Base Language After deciding upon the grammar, the next step seems kind of counterintuitive. To write a programming language you must use a separate programming lan- guage to write the new language in. The programming language should have type safety and be relatively fast. Javaish was written in Java since Java is strictly typed, meaning the types of each variable are checked before runtime, and run relatively fast. 6.3 Parser The parser is how the language reads a text file with the written code and prepares it to be executed by the computer. A typical parser works by splitting the file by every line and then parsing each line separately. In Javaish, the parser looks for a keyword at the start of each line, like “let” for a declaration statement and “if” for an if statement, and then parses the statement based on the keyword. For each statement, the parser goes character by character and builds a string until it matches the current term 4 and then resets the string and looks for the next term repeatedly until the end of the statement has been reached. For example, when parsing a declaration statement, the parser goes character by character and checks the string every time the current character is a space. So if the declaration statement looked like this: “let int x equal 5.” the parser would add each character to a string till it got to a space, so the first string would be “let” telling the parser that the statement is a declaration statement then the parser reset the string and continue to the next space which would make the string be “int” telling the parser the variable’s type is an integer, this would continue for each term forward until the period has been reached. Once the parser has parsed the entire line, the parsed line is made into an object for the executor to run. An object for a declaration statement would look something like this: “DECLARATIONSTMT: name: “x”, type: “int”, value: “JavaishInt(5)”, lineNumber: 1”. The parser is the first file written in code and tends to be pretty long. As Javaish was meant for beginners, the parser had to constantly check if something was typed wrong in the inputted code and output an error message that was easy for a beginner to understand. When writing the parser, it’s important to decide whether the language is going to be statically typed or dynamically typed. A statically typed language checks types of variables and expressions while the code is being parsed before runtime, this can help reduce the number of errors by catching them before the code is run. A dynamically typed language checks types of variables and expressions at runtime, this can make the code faster to write as you don’t have to specify the type of a variable, but can lead to unseen errors in the code during runtime making it difficult for beginners to understand what is going wrong in their code. Javaish is a statically typed language as it is meant for beginners and stati- cally typed languages tend to be better for beginners. In the parser, after each variable and expression is parsed, the parser checks to make sure that the types match, and if they don’t then an error is outputted to the user. In Javaish, there is a base statement and then all the specific statements are implemented and built upon the base statement. The base statement can hold a list of statements if the statement is a block, holds the line number of the statement, and the statement type. 6.4 Interpreter Interpreter There are two ways languages are executed, either they are compiled or interpreted. A compiled language translates the language into a low-level lan- guage like a machine or assembly language so the computer can understand and run the code. Compiled code runs faster and is more secure for applications. However, it takes time to compile the code which takes away time testing and running the code. Compiled code also can’t catch as many errors. An inter- preted language translates the language into a comprehensible language like an 5 intermediate language like Java and then converts the code statement by state- ment to that language. Interpreted code is easier to debug and more flexible. Javaish was chosen to be an interpreted language because detecting errors and debugging code is easier in an interpreted language, and these abilities are crucial for a language made for beginners. The interpreter is one of the more complex parts of a language as it has to handle many things including the scope of variables, evaluation of complex expressions, execution of functions, and ensuring everything is running in the correct order. The interpreter has two public variables, one holding the current line number and the other holding an object, of type “Variables” for the global variables. The Variables object holds a hashmap linking the name of a variable to the type of the variable, so then the list corresponding to the variable type can be used to retrieve the value of the variable. The interpreter starts by taking in one statement known as the main statement which holds a list of all the statements in this file. The main statement acts like any other function statement so that there is only one main function that deals with interpreting functions. The interpreter first makes sure that the number of arguments required matches the number of parameters given. Then the interpreter creates temporary variables based on the parameters and adds them to the local variables object. The interpreter then creates an object that will hold the return value of the function if there is any and then calls a function to interpret the body. The body is interpreted statement by statement based on the statement type. For example, when interpreting a declaration statement, first the interpreter gets the type and name of the variable and then calls another function to evaluate the expression held in the statement to determine the value of the variable. An expression is a list of elements, like an integer, string, plus sign, minus sign, etc. When evaluating an expression, the interpreter goes element by element and if the element is a value, like string, bool, integer, or float, the interpreter stores the value and then checks if an operator (plus, minus, divide, times) has been read, if so, the interpreter will perform the operation and store the new value, if not, the interpreter will continue reading each element. Once the end of the list has been reached the last stored value is returned as the value of the expression. After getting the value of the variable, the interpreter checks if the statement is global or local based on a boolean value and adds the variable to the respective object, global variables if global, or local variables if local. When interpreting if statements the result of the condition has to be stored for the interpreter to know if the else or else if statements should be interpreted or not. The interpreter is in charge of outputting all the errors and making sure that the programmer can understand the error messages. 6.5 IDE After finishing writing the interpreter, there has to be a way for a programmer to write code in Javaish. This is the job of the IDE. The IDE, which is called ProfessorJavaish (specifically made for Javaish) is 6 a website made with React and hosted by Github pages. The main problem that had to be overcome was Javaish being written in Java, but React uses JavaScript, so a way to compile Java code to JavaScript code had to be found. Luckily, the open-source project called TeaVM makes it easy to compile Java code to Javascript. With that problem out of the way, all that had to be done was to create the user interface, known as the UI, for the IDE, and integrate the IDE with Javaish. The IDE would be a single page with different windows. The welcome window welcomes the user and lists all the projects they are working on. There is a files window on the left, which is always visible, that holds all the files in the selected project. When a file is selected the code window replaces the welcome window and displays a big input box with the code. In most IDE’s the code is highlighted based on keywords, like type names and variable names, and often provides varying levels of autocorrect. To achieve this in ProfessorJavaish, another open-source project called CodeMir- ror was utilized. Since Javaish isn’t a popular language, a custom Lezer, a text file full of the grammar of the language, was required for code highlighting and autocomplete to work. After this text file was written, CodeMirror was fully implemented. The next problem to solve was a way to save the code. ProfessorJavaish uses the browser’s built-in local storage to store most of the projects. To allow cloud syncing, ProfessorJavaish utilized Google’s Firebase authentication and database service to allow users to sign in and sync code on an online database. Above the code window is a top bar that holds the run button, save button, and dictionary button. The dictionary button shows a window to the right of the code window that displays all the syntax of Javaish and how to do everything with Javaish, like declaring variables and functions, mutating variables, and creating functions. 6.6 Debugger Most programming languages do have debuggers. The debugger allows pro- grammers to add breakpoints to their program where the program would stop running and then allow the program to be run line by line. Unfortunately, most modern debuggers lack the ability to run the program backward or change the state of the program before each execution. In most modern debuggers, when a bug is found, the program then has to be debugged again to see what was happening before the bug occurred, and this can cause the programmer to have to debug the program several times just to fix one bug. The debugger for Javaish is very special as it has the ability to run the code line by line forward and backward. and the state of the program can changed before and after each execution to see how changes affect the program. This makes it very easy for beginners to visualize how their program is being run and quickly find where their program is breaking and quickly fix the problem. 7 In order to enable backward debugging, the debugger needed to store the previous states and be able to execute the program with just the context of a state. A state is a snapshot of the program that holds the line at which the snapshot was taken and all the variables that are present in the snapshot. The debugger stores a list of all the states, and when a line is requested to be run, the debugger loads the state corresponding to the chosen line number. In the IDE, a debug button is added in addition to the run button, and when clicked shows a debug window. The debug window has a step back, stop, and step forward button so that the user can debug the file line by line. The window displays a list of all the variables to allow the programmer to change the variables while debugging. At the start of debugging, the debugger runs the first line and then saves the variables in a state. When the next line is run, the previous state’s variables are used for execution. After the line is executed, a new state is made with the new variables. This state is added to a list of states held by the debugger to allow for the program to be run backward as well. Since the IDE is written in JavaScript and Javaish is written in Java, the state object can’t simply be passed to the IDE because Java and JavaScript are two different programming languages. So there needs to be a common formatting option that Java and JavaScript can read. Javaish converts the current state to a serialized JSON, which can also be read by JavaScript. The IDE reads the serialized JSON, extracts the variables and displays them in the debug window, and then sends the changed JSON back to Javaish to be debugged. Javaish then has to convert the JSON back to a state which is a Java object. 6.7 Translator Another special part of Javaish is its ability to translate Javaish code to Java or Python. Javaish’s translator transpiles the code into the target language. This was accomplished by re-purposing the interpreter by changing how statements are interpreted. When each statement is interpreted, a string is made that rewrites the statement in Java or Python. For example, when translating ”add 5 to x.” to Java, the new string would be ”x += 5;”. Both of these strings have the same outcome, they’re just in two different languages. Proper indentation is then added to the string to make the translated code more readable, the final string is then added to a list of all the translated lines. let int x equal 5 plus 3. add 5 to x. if x greater than 5 { print("Greater than"). } Figure 1: Javaish Code int x = 5 + 3; x += 5; if (x > 5) { System.out.println("Greater Than"); } Figure 2: Converted Java Code 8 In the IDE, a convert button is added that when clicked asks the user what language they want to translate the code and then displays a window over the code window with the translated code and a button to copy the code. 6.8 Robot Integration The final part of Javaish is the ability to run Javaish code on a NAO robot. The NAO robot provides a Python API to program the robot remotely. Javaish can already be translated into Python, so all that was needed was to add some NAO-specific statements and find a way to run the Python code. Python has an “eval” function that runs whatever string is entered into it, so that combined with an HTTP server will allow Javaish to communicate with a Python server that executes the translated Python code. In the IDE, a robot button is added, next to the translate button, that when clicked prompts the user for the IP address of the Python server and the IP address of the NAO robot. 7 What’s Next Javaish has yet to be used by anyone to teach them to program but there are plans to teach Javaish in a middle school computer science club. This will be a great way to prove that Javaish has succeeded in being a language that is easy for beginners to learn. Javaish’s parser was written in a way where it was hard to add type checking and the code for evaluating expressions was unnecessarily complicated due to the way the parser was written. There are plans to rewrite the parser to use an abstract syntax tree for its way of grouping expressions and statements. There also needs to be more specific parser error messages to avoid any confusing errors for beginners. In the long term, the parser might be replaced with natural language pro- cessing (NLP). NLP is a form of artificial intelligence (AI) that specializes in reading and manipulating human language. The introduction of NLP could al- low for the syntax of Javaish to look much more like English and be more lax in the requirements of what each statement had to look like. For example, the statement “subtract 5 from x.” with NLP could also be written as “take away 5 from x.”. This can lead to fewer syntax errors and more readable code. Javaish’s debugger currently stores a copy of the entire snapshot of the pro- gram at each line, not just the changes to the variables. This would make the data stored in each state very big and could lead to issues when trying to debug larger files. If a program that at one point had 10 MB of variable data to store, each new state would store the 10 MB, so after debugging 10 lines, 100 MB of data is now being stored instead of just 10 MB. With only storing the changes made to each new state, the amount of data stored will be decreased signifi- cantly and will allow much larger files to be debugged. This won’t be a huge 9 issue for now, since Javaish is meant for beginners, so they won’t be writing big enough files to overwhelm the current debugger. 8 Conclusion In conclusion, Javaish is a great programming language for beginners. The simplicity of the syntax, the readability of errors, and the custom line-by-line debugger make Javaish a perfect fit for a programmer’s first language. Focusing on bridging the gap between traditional programming languages is important as technology has become an integral part of everyone’s daily lives and knowing how the technology you use is important in making sure that your privacy is being respected and to keep you safe online. In the past, programs like Scratch and Code.org were made as an introduction to programmers for kids but didn’t translate well enough to actual programming languages. When designing a beginner programming language, as seen in Javaish, it’s important to have a balance between making things easier for beginners and keeping things as close to traditional programming languages. Javaish does have limitations and shouldn’t be the only programming language a programmer uses. Javaish is a great introduction to other programming languages but is lacking in features necessary to write very complex programs. 9 Source Code Javaish’s Robot Integration Server: https://github.com/TrackerJo/javaish-nao-server Javaish’s Lezer: https://github.com/TrackerJo/JavaishLezer Javaish’s IDE Code: https://github.com/TrackerJo/ProfessorJavaish Javaish’s IDE Web- site: https://trackerjo.github.io/ProfessorJavaish/ Javaish’s Language Code: https://github.com/TrackerJo/Javaish 10 References Crafting Interpreters. www.craftinginterpreters.com CodeMirror. codemirror.net DeepLearning.AI. “Natural Language Processing (NLP) [a Complete Guide].” DeepLearning.AI, 11 Jan. 2023, www.deeplearning.ai/resources/natural-language-processing GfG. “Advantages and Disadvantages of Compiler.” GeeksforGeeks, 18 Oct. 2023, www.geeksforgeeks.org/advantages-and-disadvantages-of-compiler TeaVM. www.teavm.org Science, Baeldung on Computer, and Baeldung on Computer Science. “Stati- cally Typed Vs Dynamically Typed Languages — Baeldung on Computer Sci- ence.” Baeldung on Computer Science, 17 May 2023, www.baeldung.com/cs/ statically-vs-dynamically-typed-languages “What Is an Interpreter? Types, Differences, Advantages and Disadvantages.” Toppr-guides, 12 Sept. 2022, www.toppr.com/guides/computer-science/computer-fundamentals/ 10 system-software/interpreter Jdb - the Java Debugger. docs.oracle.com/javase//7/docs/technotes/ tools/windows/jdb.html Devopedia. 2019. ”Transpiler.” Version 5, January 24. Accessed 2023-11-12. https://devopedia.org/transpiler 11 Appendix 11.1 Tic-Tac-Toe in Javaish let String[] board = ["0", "1", "2", "3", "4", "5", "6", "7", "8"]. function isMovesLeft(){ for each cell in board { if cell equals "_" { return true. } } return false. } function evaluate() { //Check for Horizontal Then Vertical Then Diagonal Wins if board sub 0 == board sub 1 and board sub 1 == board sub 2 and board sub 0 not equals "_ if board sub 3 equals "X" { return 10. } else { return -10. } } else if board sub 3 == board sub 4 and board sub 4 == board sub 5 and board sub 3 not eq if board sub 3 equals "X" { return 10. } else { return -10. } } else if board sub 6 == board sub 7 and board sub 7 == board sub 8 and board sub 6 not eq if board sub 6 equals "X" { return 10. } else { return -10. } } else if board sub 0 == board sub 3 and board sub 3 == board sub 6 and board sub 0 not eq if board sub 0 equals "X" { 11 return 10. } else { return -10. } } else if board sub 1 == board sub 4 and board sub 4 == board sub 7 and board sub 1 not eq if board sub 1 equals "X" { return 10. } else { return -10. } } else if board sub 2 == board sub 5 and board sub 5 == board sub 8 and board sub 2 not eq if board sub 2 equals "X" { return 10. } else { return -10. } } else if board sub 0 == board sub 4 and board sub 4 == board sub 8 and board sub 0 not eq if board sub 0 equals "X" { return 10. } else { return -10. } } else if board sub 2 == board sub 4 and board sub 4 == board sub 6 and board sub 2 not eq if board sub 2 equals "X" { return 10. } else { return -10. } } return 0. } function printBoard(){ let String firstRow = board sub 0 plus " | " plus board sub 1 plus " | " plus board sub 2. let String secondRow = board sub 3 plus " | " plus board sub 4 plus " | " plus board sub 5 let String thirdRow = board sub 6 plus " | " plus board sub 7 plus " | " plus board sub 8. print(firstRow). print(secondRow). print(thirdRow). print("----------"). } let bool hasWon = false. let bool XTurn = true. 12 while not hasWon { printBoard(). if XTurn { let int move = toInt(input("Where do you want to move as X?")). while board sub move not equals toString(move) { dialog("Invalid Move"). move = toInt(input("Where do you want to move as X?")). } set board sub move to "X". } else { let int move = toInt(input("Where do you want to move as O?")). while board sub move not equals toString(move) { dialog("Invalid Move"). move = toInt(input("Where do you want to move as O?")). } set board sub move to "O". } XTurn = not XTurn. let int eval = evaluate(). if eval == 10 { hasWon = true. dialog("X WON!"). printBoard(). } else if eval == -10 { hasWon = true. dialog("O WON!"). printBoard(). } } 11.2 Cookie Clicker in Javaish let int cookies = 0. let int inc = 1. function displayCookie(){ //Get choice let int choice = toInt(showInputDialog("You have " + toString(cookies) + " cookies! Do y if choice == 0 { add inc to cookies. displayCookie(). } else if choice == 1 { showShop(). 13 } else { print(choice). showMessageDialog("Thats not a valid choice!"). displayCookie(). } } function showShop(){ let String choice = showInputDialog("Do you want to buy click upgrade for 5 cookies? (y/ if choice == "y" { if cookies >= 5 { subtract 5 from cookies. add 1 to inc. displayCookie(). } else { showMessageDialog("You don’t have enough cookies"). displayCookie(). } } else if choice == "n" { displayCookie(). } else { showMessageDialog("Thats not a valid choice!"). } } displayCookie(). 14