You are viewing archived messages.
Go here to search the history.

Pavel Mikhailovskii 2024-09-04 07:55:52

Hi everyone!

I’d like to give an account of the research project we’re doing at JetBrains.

It is called Ludwig after Ludwig Wittgenstein and has an ambitious goal of re-engineering the foundations of the software development stack.

At the moment, we are still at a very early design and prototyping stage, but we believe that this project will let us create the next generation of development tools.

Here are the most important ideas we’re trying to materialize:

Liberation of code from the shackles of textual representation

Human-readable textual notations were a great innovation back in the 1950s. However, we have made great progress in the ways we store complex data structures since then, and the typical codebase sizes have also grown by a few orders of magnitude.

Code is essentially a graph with one tree-like perspective more important than others. An adequate way of storing such complex and evolving data as code would be to put it in a versioned graph / linked document database, supporting Git-like branching and merging. That would get rid of the need for continuous parsing, indexing, symbol resolution and typechecking that constitute the code editing workflow in modern IDEs. We would resolve symbols once, at the moment of typing and store their unique identifiers (not just names!) in an indexed by construction and preserving referential integrity database.

That would also make such intentions as Rename, Move, Find Usages or Go To Definition trivial to implement. Of course, structural representation of code will come hand-in-hand with structural (semantic) diff and merge.

This graph-like representation should allow for a fine-grained tracking of changes and dependencies and dramatically reduce feedback times in such scenarios as incremental compilation.

A minimalist approach towards programming language design

To prevent our language from becoming “fat and weak” as John Backus has put it in his famous lecture, we want to pass our language through a series of aggressive optimization rounds or distillation passes.

This should result in something comparable with Smalltalk’s “syntax on a postcard”. Actually, we believe that we could make it even more symmetric by eliminating the distinctions between methods, named and anonymous functions, operators and statements. (As you know, Smalltalk has different syntaxes and different behavior of return statements for methods and blocks and “surprising” execution order rules for different kinds of messages).

The goal is to come up with a language that would be easy to learn and read and straightforward to reason about for all kinds of agents-be it humans, static analysis tools or AI.

In terms of notation, it will look like an indentation-based syntax for a tiny subset of Lisp, but without its macros or the zoo of “special forms”. Being freed from the limitations of plain text, we’re going to use semantic coloring to make the notation even more expressive and compact.

Obviously, our programming language, as any other, should be able to express computation logic and code structure; what is less common is that we also want it to be able to express data, configurations and knowledge, thus eliminating the need for additional DSLs. A YAML-like data notation emerges from our tiny language as naturally as JSON emerged from JavaScript. The only difference is that JSON was discovered by chance, and our language is consciously designed to be able to declaratively describe complex data structures.

Unification of Object-Oriented and Functional programming

As a part of our minimalist program, we are aiming to heal the great schism that divided programming into the object-oriented and the functional worlds.

We believe that the class-free approach in the form proposed by Douglas Crockford will let us make OOP an integral part of functional programming, thus converging the two into what could be called unified programming. This form of OOP will keep the best parts—encapsulation and polymorphism and get rid of the "considered harmful" implementation inheritance. There will be no need for classes, constructors, prototypes, visibility modifiers, this and new - just immutable structures and anonymous functions.

An IDE designed for focus and context awareness

We want to build an immersive Smalltalk-like environment with structural navigation, a smaller editing scope and richer and more dynamic context compared to the traditional file- and text-based IDEs. This seems well-aligned with both the minimalist design of the language and the non-textual storage format. The latter should allow us to store some additional information alongside the code. That will include all kinds of metadata, normally invisible to the users, but also some unusual forms of embedded content. Think of a documentation comment containing a video explaining the algorithm or a discussion between multiple developers linked to a certain place in the code.

Smart typing

We also have some ideas on how we could implement some smart typing techniques, combining the convenience of automatic type inference with the solidness and discipline of explicit type annotations.

The key idea is that the flexibility of the non-textual representation will eliminate the need for the user to choose between the two worlds. Manual annotations can be hidden to reduce visual distraction, automatically inferred types can be displayed and persisted in the code database, etc.

Designed to be AI-fitting

Finally, we want the whole thing to be future-proof and provide better support for AI-aided development compared to the traditional languages. The simplicity of the language as well as its fine granularity and its property of always having all the symbols resolved should allow for high-quality “understanding” and retrieval-augmented generation of code compared to such languages as Python or Java.


As I said, at the moment we’re still at a very early stage. Many of our challenges are not technical, but about finding the way of how we could shape this set of ideas into a product vision. We are, of course, open to collaboration with like-minded people.

I will be happy to answer your questions and hear your feedback.

Pavel Mikhailovskii 2024-09-04 07:56:34

A little example, illustrating the syntax:

image.png

Jarno Montonen 2024-09-04 15:13:05

Very interesting. Thanks for sharing and great to see JetBrains represented here!

Your "liberation from textual representation" and the "context aware IDE" -paragraphs describe my thoughts exactly while building my textual projectional language workbench (some demo videos at: levlo.com). Although, I suppose one wouldn't build a projectional language at all if those paragraphs wouldn't resonate.. Is there a reason you don't seem to be referring to your language as a projectional language? To not compete with MPS 😅 ?

I certainly agree that having all the symbols resolved, and generally the AST/semantic tree in a valid state at all times, helps in guiding AI to produce semantically valid code and I'm heavily utilizing this for Levlo's AI Copilot. However, I feel that new programming languages might be at an disadvantage in the new AI era as there aren't large amount of samples for the LLMs to train on (and it would take a while for the common LLMs to train on new public samples). Coincidentally this doesn't seem to be an issue if the language is very natural language like.. I suppose having a similar syntax to existing languages could also help. Although, if the semantics are different it could also hurt. I'm not sure I understand what you mean when you say that the "fine granularity" of the language should make it more AI-fitting. Can you elaborate on that?

Pavel Mikhailovskii 2024-09-04 16:45:18

Your project indeed has a lot of similarities with our work. Many of the ideas I described had been proposed as early as in the 1960-70s. I know that Erik Meijer is also working on something very similar to what you are doing—programming in plain English that gets translated into something Prolog-like, able to call external functions.

I avoid the term "projectional editing" for two reasons. First, in my opinion, projectional editors have got a bad reputation for being pain to use. Problems typically start with arithmetic operators and handling of parenthesis. I am not saying that those problems are unsolvable, but the fact is that way too many attempts to implement projectional editing resulted in a terrible experience. We hope to avoid the usual pitfalls by having really minimalist and uniform syntax without precedence rules and by not trying to imitate text.

The other reason is that I think that a more specific term like "autocompletion-driven editing" would better reflect the idea of having most of the symbols resolved at the time they are typed. The term "projectional editor" is oversaturated, and it's hard to impress anyone by saying that you're building yet another one.

With regard to your question about LLMs, we hope that we will be able to transpile a reasonably big corpus of programs written in some mainstream language into our tiny little Lisp, preserving most of the structure, and then use that transpiled code to train the LLM. Another possibility is that the advancement of AI will soon allow us to simply teach LLMs to program in our simple language without feeding them with a large number of examples.

Paul Tarvydas 2024-09-04 17:44:58

FWIW: brainstorming...

(1) Get LLMs to generate code in some large-corpus language, like JS, Python. Use text-to-text transpilation to convert the generated code, syntactically, into tiny little lisp (going from JS to Lisp-y, or Python to Lisp-y is straight-forward using PEGs)

(1a) Get LLMs to generate code in full-blown lisp, then ask nicely to get it to remove the hoary bits (special forms, macros)

(1b) No need to re-train LLMs with tiny little lisp if conversion can be done.

(2) Steve Philips used an LLM to generate OhmJS code to create a new language over top of an existing language (in his case, he built his new language using Golang as "assembly code"), he might have advice on how to ask an LLM to build syntax converters

Pavel Mikhailovskii 2024-09-04 18:05:07

Paul Tarvydas Thanks for your suggestions. There's indeed a number of techniques that can be used to LLM-generated transform code in some traditional language into our "Lisp". However, that would only increase the complexity of the development stack, and our goal is to radically simplify it. That's why we want the LLM to be able to generate code and "think" in terms of our language. That would be a faster, cheaper and more robust solution. Ideally, the LLM should be able to generate neat code without any knowledge about the bloated languages of the past 😉 This doesn't mean we couldn't use any dirty tricks and hacks for the initial training.

Jarno Montonen 2024-09-04 18:10:22

Interesting, didn't know about Erik Meijer's natural language programming stuff. Are there any material about it? I only found some possible references in his twitter.

And yeah, I'm sure it's possible to build an AI Copilot for a new language. And if your language is always authored using your IDE, there shouldn't be a need for users to go get help from Chat GPT for example.

Pavel Mikhailovskii 2024-09-04 18:12:52

@Jarno Montonen He gave a talk about it at KotlinConf and we had a long talk afterwards. The video of the talk should be published on YouTube. Unfortunately, the talk was interrupted by a false fire alarm.

Pavel Mikhailovskii 2024-09-04 18:14:58

It's hard to predict what AI will be capable of in let's say two years—a very optimistic estimate of how long it's going to take us to build our solution.

Pavel Mikhailovskii 2024-09-04 18:21:02

Sorry, I forgot to clarify what I meant by "fine granularity. I wanted to say that in our system the minimal unit of editing will be something like a function and that function will not be buried in a large file, so we will be able to provide a fully resolved and relatively small context for that single function only, That should make it easier for the AI to understand the meaning of a function and, at the same time, for the IDE to validate AI's output.

Jarno Montonen 2024-09-04 18:22:31

Oh and I sympathize with your thoughts about the term projectional language. The problem is that basically the same things are already called Projectional/Structured/Structural Language/Editor/Editing. I'm not sure one more term would help with the matter. 😅

I feel that both my self and the Hazel folks have basically solved the parenthesis and more generally "just boxes inside boxes" issue in projectional editing. Although, admittedly neither in a battle tested context.

I seriously considered to not implement support for operator precedence in Levlo, but concluded that if the target users are non-programmers, math just has to work the way it's taught in schools.. If the target audience was programmers, I'd probably go the same route you've decided to.. Precedence rules bring so much pain for no gain. Although, I wonder if you'll have some trouble trying to explain the missing operator precedence to LLMs..

Jarno Montonen 2024-09-04 18:26:24

Awesome, thanks! Will certainly check it out.

Pavel Mikhailovskii 2024-09-04 18:32:41

I actually don't want the LLM to understand our indentation- and color-sensitive notation (that's a more correct term than syntax). That notation can be mechanically converted to/from S-expressions). A bigger challenge is that we want to use unique ids, invariant to renames (re-labeling) and moves, and yet, expect the LLM to generate human-readable labels and be able to get some insights from them.

Jarno Montonen 2024-09-04 18:33:35

IDE to validate AI's output

This is what I'm doing. Although I call the component that the LLM feeds into an "language engine". I have a very simple parser that reads through the LLM response and feeds it in appropriate pieces to the engine. The engine maintains the AST and is able to provide all the possible valid sequences at any given location. If LLM output doesn't match any of the valid options, I reprompt and ask it to reformulate the answer so that it continues with one of the valid sequences. Additionally I'm using the language engine to generate semantically valid samples for the LLM.

Pavel Mikhailovskii 2024-09-04 18:37:25

Yes, it's basically RAG. And by IDE I meant "the thing performing analysis of the generated code", not sure if we should distinguish between the IDE and the compiler here.

Pavel Mikhailovskii 2024-09-04 18:38:56

Moonbit seems to take a very similar approach moonbitlang.com/blog/moonbit-ai

📝 MoonBit: Exploring the design of an AI-Native Language Toolchain | MoonBit

Exploring the design of an AI-Native Language Toolchain

Jarno Montonen 2024-09-04 18:43:02

Yeah, I suppose it could also be called language server.. But not an important distinction.

So what kind of usages are you thinking for the color-sensitivity? And as for labels, I think it's beneficial for the LLMs to work with the human readable labels. Although I've faced some challenges getting LLM generate sensible human readable ones. But how else would it work if the LLM needs to define new variables for example? Or do I misunderstand what you meant by "use unique ids". Why couldn't you use human readable labels in the s-expressions when interacting with the LLM? In Levlo the LLM generated labels just go into the language engine and it resolves those into new identities or references to existing identities.

Pavel Mikhailovskii 2024-09-04 18:46:56

Well, it can, for example, have the form (let bf191635-10f4-4032-a90f-3a02e867b345 "the-answer" 42 ...)

Jarno Montonen 2024-09-04 18:56:03

Didn't know about MoonBit. Thanks for bringing up!

Pavel Mikhailovskii 2024-09-04 18:56:35

And I like the idea of indentation- and color-based notation as both techniques allow you to express the structure and the semantics without cluttering the visual field. It works like magic - "show something without showing anything". Like what is called negative space in photography. And we know that at least indentation works very well in Python and YAML

Jarno Montonen 2024-09-04 19:01:35

Yes, I definitely agree about indentation, but I'm not sure I see how handy color-sensitive semantics would be. Or am I getting it wrong. Do you mean that changing the color of say the label in variable definition would change it's type?

Jarno Montonen 2024-09-04 19:04:28

I suppose readability vice it should work, I'm wondering more what the authoring experience would be. Although, I guess user could still type the type, but then the editor would remove it and set the label color instead. I do a bit similar thing with colors in one of my demos. The user can type the hex value (or use a picker) and then the editor just shows a colored circle.

Jarno Montonen 2024-09-04 19:05:13

And if you focus the circle, it turns into the hex value again.

Pavel Mikhailovskii 2024-09-04 19:08:15

The color will depend on the usage type. Look at the factorial example that I posted. The color red means it's a definition of a new symbol, so I can omit let , blue means it's a parameter declaration, white - just passing value as a constant, teal - function application. Same symbol, like factorial can be passed as a value to a high-order function or applied.

Jarno Montonen 2024-09-04 19:11:55

I see, but does the user choose in which color they're going to be typing next or is the color just applied by the IDE after the semantics have been resolved?

Pavel Mikhailovskii 2024-09-04 19:19:45

the idea is that you insert a symbol by typing a special symbol that defines the type of use - for example, d for definition of a new symbol, v - for passing as value, a - for application of as function, etc. You would need to learn less than 10 shortcuts. And that doesn't mean typing more than in a traditional text editor — there you typically press SPACE before starting typing a new identifier. This is just a sketch of the idea—we're actually going to do some empirical and theoretical research to come up with a useful UX

Pavel Mikhailovskii 2024-09-04 19:24:39

This is a screenshot of my presentation where I explain the idea of semantic coloring. Not to be taken as the final design:

image.png

Jarno Montonen 2024-09-04 19:25:08

I see. That could work. It's been great chatting with you! However, getting late here so have to start heading to the bed.. :)

Pavel Mikhailovskii 2024-09-04 19:26:15

Thank you for your interest. Good night!

Jarno Montonen 2024-09-06 12:13:10

Added tabular data and document template import to my notebook demo so now it can be used to fill/generate documents from csv/spreadsheet rows. Would any of you find something like this useful? I know there are a bunch of document generators, but the ones I've seen seem kinda crappy. Happy to hear about experiences using any of the existing solutions and why they suck though 😆.

Duncan Cragg 2024-09-08 14:11:20

Hiya folks, now that many of you have been digging in to Dynamicland's website for a bit and are in the right frame of mind, I was hoping that you may have had your neurons tickled in just the right ways to be open to reading about a project with some similarities: mine! 🤗

So I updated my About page, and I was hoping that it's now short and accessible enough to be just the info needed for you to "get" what my project is all about:

duncancragg.substack.com/about

📝 About - The Parallel Reality Computer

Future operating system research: app-free, Spatial and distributed approaches through pervasive, mashable, cross-host links. Click to read The Parallel Reality Computer, by Duncan Cragg, a Substack publication. Launched a year ago.

Duncan Cragg 2024-09-08 14:14:12

Sunday reading for ya; let me know what you think, and feel free to offer constructive criticism... 😲

Dafydd Rees 2024-09-08 16:24:30

This kind of thing reminds me at least a little about "Open Cobalt" from a programmable environments point of view - and at least a little of the UI that General Magic was building.