📜 ⬆️ ⬇️

Liscript - web REPL: kisses, bikes and excavators



Some time ago, I wrote a lis-like interpreter that called Liscript. Has published several articles on Habré on the features of the implementation of the kernel, TCO, GUI, REPL bots, etc. Recently added a web-interface REPL (link at the end of the article).

What does kisses and excavators? I think most people know such abbreviations as KISS (keep it simple stupid - make it easier, you fool), YAGNI (you ain't gonna need it - you won't need it), as well as people of various degrees say about architectural astronauts, " everything should be made as simple as possible, but not simpler ”, etc.
')
Suppose you have a task to dig a hole. What are the solutions? Take a shovel and dig yourself - cheap and cheerful, but for a long time and possibly suboptimal (depending on your level of possession of the shovel and the size of the pit). To outsource to Tajik (we will not consider this option here, although I should have mentioned it). Taking an excavator is quick and efficient, but costly: gasoline / rent, plus not the fact that it will travel to your garden gate, it means you have to demolish / repair the fence, etc. Also, it is necessary to determine the model (sometimes out of 100,500 options), and if you control it yourself, you need to understand all its levers and pedals.

Of course, if you are a professional excavator, you dig 200 holes a day, or you aspire to become one, and you do not need the initial task (to dig a hole) by itself, but as a training or demonstration of your skills, then the choice is clear ( model question). But even a professional will take a shovel, planting flowers.

In general, about the choice of tools for the tasks, and the specific (I suspect that the controversial) decisions that I chose during the project, under the cut.

The implementation of a singly linked list

In Liscript, there are no point pairs (cons cells), so the basic structure of both the code and the data in it is a list. In the Java version of the interpreter, I wrote my own simplest class with the fields car and cdr. It was possible to take standard Java collections such as LinkedList or ArrayList - most likely they are better optimized in terms of allocations and friendship with the garbage collector. But I chose my own bike, although it is easy to refactor to the second option.

Tokenizer / Lexer / Parser

This is an example more interesting. You need to read the input text / string and convert it into a ready-made AST (abstract syntax tree), selecting tokens from the text and organizing them into a hierarchical structure. The task is more than known, there is a whole extensive theory of parsing and parsing, and many library implementations of various parsers, for example www.antlr.org But I decided to write my simple bike on a state machine - Lisp has a very simple grammar and syntax, although of course I had to consider multiline string literals and comments. Moreover, I have 3 such bikes: in the Haskell implementation (despite the many ready-made solutions: parsec, attoparsec, etc.), in the core of the Java implementation, and in the Swing GUI for syntactic highlighting of the code text.

WEB backend


Case history: this is my first web project, I chose Heroku, a free data plan, as the hosting application. From the build systems in one Java chat, I was advised by Gradle, not Maven, motivating with various attractive words. I believed, I chose the Gradle-build option on Heroku, and the demos that I downloaded to the disk used Ratpack (I don’t know what the Maven-assembly example uses, it’s possible the same thing). Since I had no experience with other web servers (and web technologies in general), I had to make a choice - either not to use this demo example, but to install some Jetty, for which there is much more information available on the Internet, or to use Ratpack, ready and tuned, but somehow deal with it. I chose the second option, among the examples found, two thirds was on Groovy, but eventually I managed to figure out how to implement long synchronous operations, and with page rendering everything was simple.

WEB frontend


There is generally just a sea of ​​options for choosing the most diverse technologies, for the region has been developing rapidly for many years. And apologists of different frameworks prove to the whole world (and each other) that their choice is better / more efficient / more promising and only this way you need to “write WEB in 2017” (C) Each of them is right in his own way, but what choice did I have? To solve a purely utilitarian task - to dig a hole to write the web- mor interface of your REPL.


As you probably guess, of course, I chose the third option :). Even without using jQuerry, because this machine would also have to be studied. Without Babel / Webpack and another 100,500 fashionable words on the front. For the first time in my life, having felt the joy of debugging under various browsers, including IE, I had to hard-code CSS constants, instead of declaring them at the beginning of the file, which is poor in itself, but IE didn’t want to see these ads from me formats, as suggested by various fashionable frameworks, implied the use of the frameworks mentioned.

But of course I’m not as upset as a cyclist might have seemed to you , and not an excavator driver . In a couple of tasks of the web interface, I selected ready-made libraries:

Split panel

I was very necessary for the REPL. Powerful web GUI frameworks implement them in their composition, but, having eliminated heavy equipment, I considered smaller ready-made implementations, and after trying 3-4, I chose one. Although it pulls jQuerry behind me, which I don’t really like (I don’t need it for anything yet), but it responds much better in terms of responsiveness of the interface. If there is time / desire, I can rewrite it on my bike, without jQuerry.

Code highlighting

Here I think I was lucky - to solve this problem, I immediately found an excellent codemirror.net library, figured out its capabilities, wrote a plugin for the syntax of my language and theme. I did not write my bicycle parsers / lexers, because this library is simple, lightweight and does a good job with its work, both in static text areas and in dynamics when editing text of a code by a user.

Conclusion


Of course, I am aware that the decisions I have made above are at least debatable and ambiguous. What is possible (and even better from some point of view) was to use ready-made technological tools. What did I gain by writing my parsers / lexers? Experience in writing such bikes on state machines, full control of what is happening, the possibility of easy customization. What is lost? I did not understand the existing parsers, I did not master them, and if I have to apply them in the future, I will have to master them from scratch. And the same verdict for each of the above options for individual local tasks. But in any such case, it is necessary to make a choice, so you have to weigh all the pros and cons, and take the consequences. What do you think about this?

Liscript Home Page
Online REPL

Source: https://habr.com/ru/post/336006/


All Articles