Transpiling between any programming languages (2019)
engineering.mongodb.com
engineering.mongodb.com
I have a different solution in mind: designing a language specifically for transpilation, so that it could be used to generate high quality, readable code for various programming languages (I call it "idiomatic translation"). I've recently started exploring that topic as a part of Zygote project [1].
Creating yet another "high level" language that compile to all other languages would mean designing something that is the least common denominator between all languages, which is OK for a language that is not supposed to be written by hand, AKA bytecode, it's not OK for a language developers are supposed to write.
> designing something that is the least common denominator between all languages
My vision is rather finding some patterns, higher abstractions in various languages: e.g. imperative loop summing squares of all odd elements is semantically similar to filter -> map -> fold functional chain. Building whole language on such patterns will definitely be hard, but I believe it is possible and worth pursuing.
We started with just transpiling data definitions based on Apache Thrift [1], but later expanded it to also be able to transpile code checking invariants on the data and integration tests.
Jetbrains' Meta Programming Studio (MPS) [2] was a really great tool for this, as it does a lot of what is mentioned in the article for you. It makes it really easy to define new nodes, syntax rules, parse rules from text, ast-to-ast transformations etc.
There's a subset of operators that are similar (but not identical) between programming languages. For instance you can add numbers like
const a = b + c
in javascript int a = b + c
in java, etc, you can even write (b+c) as a
in the select statement of a SQL query. If you look at basic operations on numbers and strings it is not hard to translate expressions between conventional languages and query languages. Now query languages have different ideas about control structures, but working at the expression level you can mostly avoid that.Now there are issues around data types (are we adding ints or floats, what to do about overflow, when you index the Nth element of a string is it 8 bits (maybe part of a Unicode char), is it a basic plane unicode char, or could it be any codepoint, or something else...) but those problems don't turn up 100% of the time when you try to translate.
The full project report: https://gist.github.com/LakshyAAAgrawal/33eee2d33c4788764087...
However, AFAIK modern MT systems are pretty much blackboxes and the language models cannot be separated from the rest of the model. In any case, it wouldn't be as easy as plugging a compiler into the system to check if the output compiles.
print_hello = gen_expression()
eval(print_hello)
The result of the program is "Hello", but the only way a transpiler would be able to reproduce this is by knowing the expression generated by 'gen_expression', and converting the expression to the target language (also assume target language has equivalent of 'eval'). However, then the transpiler needs to know 'gen_expression' will halt, and we have the halting problem.
As I said it is logically impossible in general, but you can perhaps restrict the problem to a practical narrower case in which transpilation is always possible.
I'm not sure what this means.
If you take some code that generates langX at runtime, and compile/transpile that code to langY, you get some langY code that generates the same langX code value. So you need a eval(langX) that can be invoked from langY. Given an X-to-Y transpiler available at runtime, you can create the needed evaluator by composing the transpiler with the langY's eval(langY) function, with ordinary function composition.
I may be explaining this poorly (or misunderstanding you?), but I'm quite sure about the conclusion I'm trying to express. As a concrete example, you can generate some TypeScript at runtime, transpile it, and pass it to the JS eval function. The transpiled-at-compile-time code halts iffi the pre-transpilation version would halt, as does the transpiled-at-runtime code. The transpiler never halts. https://stackoverflow.com/questions/45153848/evaluate-typesc...
My understanding of 'transpiling' is that it is meant to convert, say, idiomatic Python into idiomatic Java.
Maybe one day the field of literate programming will come to maturity.
With enough effort and smart transformation passes however, I think you could come pretty close to something resembling "native" code. It might not always be worth it to spend that development time though.
Programming languages aren't languages. They're arithmetic calculations wearing linguistic clothing.
Making it idiomatic and fast, is very, very difficult. Achievable for a subset focused on querying MongoDB? Absolutely.