ShiftJS – Swift to JavaScript transpiler
shiftjs.com
shiftjs.com
One major part of Swift is its value types; many core types, including arrays, are passed by value, like a C struct. So
var a = [1, 2]
var b = a
b.append(3)
should make `a` equal to [1, 2] and `b` equal to [1, 2, 3]. ShiftJS eschews these semantics and instead passes arrays (and other value types) by reference, which makes it basically impossible to share code between real Swift and ShiftJS.Also, the demo compiles
let a = 3 4
to var a = '3 4';
which doesn't instill confidence.Maybe its my own ignorance, but language design often doesn't map 1:1, so wouldn't it end up feeling forced?
If behavior of compiled program matches the original one, that is.
Unfortunately, that does make it difficult when your target is JavaScript. Every mature transpiler I've used has had some semantic gotchas that aren't present in the "proper" compiler.
If there is one thing however that I have learned from using transpilers it is that externs as a whole are a huge waste of time, as it can be difficult to determine their quality upfront. If you are building a Node backend or SPA, you are going to need to rely heavily on existing libraries and will probably find yourself constantly hitting walls while you try to swim against the current of the ecosystem if you try to use a transpiler.
Haxe has a lot of metadata mechanisms that enable mapping language-specific semantics to Haxe standards (@:selfCall, and @:native for example). Haxe also has abstract types, which enable automatic inline runtime conversions (e.g., converting a native type to a standard Haxe type automatically depending on usage in haxe methods).
It's true you can't expect to find a high quality extern for a given version of any given library. However, it's pretty easy to write a small one for the subset of functionality that you require. It always ends up paying off for me.
I agree with what you say about writing your own externs with a subset of the functionality, and I think it is often a better approach than relying on potentially flakey externs. Still I think this sort of workflow is only suited to particular types of projects and especially in a team environment it makes more sense to avoid niche ecosystems.
Yes, languages differ and language features rarely map 1:1 onto each other; that's about the other 5 % (as well as platform differences). But a lot of things can be done automatically if you control the conversion process, e.g. converting C#'s extension methods into default methods in Java. Of course, if you don't require the resulting converted code to be worked with, and just need it to run, then you can do a lot of shortcuts. We translate at the source code level because at least the Java code is still maintained and extended on the Java side. Doing it at the IL level would be simpler in some cases, but is impractical for a lot of others.
I think an important question is whether the compiler output will need to be touched by humans. If it's just going to be run or compiled more or whatever then it doesn't really matter how the various features map.
It is possible to compile Swift to JavaScript.
The only thing impeding that is the quality of the project.
Not to say there's not value in building JS output with semantics very close to to Swift.
[1]: There could conceivably be GPL code linked with your code in the final output, but I don't think people would release a compiler like that without big notices unless they're specifically trying to trick people into having to buy commercial licenses or something like that.
This seems unlikely.
It was not the only one, it crops back up periodically and the purpose/nuances of weakrefs have to be re-explained each time. To be fair, there are a lot of subtleties involved...
I'm currently working on something like this for the Crystal language.
var a = 3
let b = { a * 2 }()
http://i.imgur.com/D1FxZcN.png var a = 1 ^ 2
As it stands, I find the thing entirely useless.for i in 0...10 { print(i) }
Then again, the project does say it's in early development. Perhaps a re-visit in a month or two will yield some nice progress.
This whole project seem like a lot of duplicated, wasted (and error prone) work
I looked for such a project a few days ago but didn't find anything.
If you're taking a higher level language and compiling it to assembly, it's a compiler.
If you're taking a higher level language and compiling it to LLVM IR, it's a compiler.
If you're taking a higher level language, and compiling it to another higher level language...it's a compiler.
I am not sure where this term was first coined, but we've been doing source-to-source compilation for a very long term and it's just within the last 7-10 years I start hearing people use this term, which IMO adds no actual value.
It's perfectly fine to say "Swift to JS compiler".
You shouldn't worry until academia starts using it. Oops. Here's an article with 'transpiler' on the title: http://dl.acm.org/citation.cfm?id=2173694
It's a good thing that English is descriptive and not prescriptive.
cfront compiled C++ to C, so it's a transpiler, right? Or is that just an unimportant implementation detail?
Everything targeting LLVM IR is a transpiler, because it's just source-to-source, with the second source being LLVM IR.
Similarly things targeting the JVM or CLR - all transpilers because both of these are relatively high level targets. They might not be something you would consider a "source language", but for many people assembly language is a perfectly reasonable source language, and thus...
Everything compiling to assembly language is a transpiler. The target language is assembly.
Having worked on compilers for over two decades it just comes across as a made-up term by people who don't understand that what a compiler does is translate from one language to another (be it another "source language", ASTs, linear IRs, VM bytecodes, assembly languages, or executable code).
I don't think I'm being particularly pedantic here. Compilers simply generate another form that one person or another might consider a source language (in fact people working on JITs most definitely think of their input as the source language).
IRs, ASTs and bytecodes are not programming languages. If you insist otherwise because "some might consider it that way", you have no business criticizing the use of words, to be honest.
There are textual representations for these things, but even then people rarely program in those (LISP being an exception). Assembly language is a textual representation for humans to read and sometimes program in. If you have some program that actually translates to assembly language as a target, by all means, call it a transpiler if you want.
That's not what I am saying. The point is that compilers make many transformations from "language" to "language", it just happens that other "source languages" are sometimes the target.
> If you have some program that actually translates to assembly language as a target, by all means, call it a transpiler if you want.
For a very long time that was the model most compilers used, and in fact people (mostly those espousing to be advocates of the UNIX philosophy of building small tools that could be chained together) would rail against compilers that directly generated machine code rather than generating assembly that was run through a separate assembler.
So if a compiler that generates assembly source is a transpiler, then the by definition most compilers are transpilers (and all transpilers are compilers which people seem to agree with).
If I recall, the term arose out of the JS community around the time CoffeeScript, Traceur and other languages that compile to JS got popular. Brendan Eich did a lot of popularization of the term.
> IMO adds no actual value.
I think it's a really useful term. Compilers and transpilers are structurally different and have different high level aims.
If you tell me you are writing a language that compiles to JS, then my assumption is that you treat JS as effectively an "assembly language for the web". You will output whatever bizarre JS code that happens to correctly implement your language's semantics efficiently and compactly. It might make my eyes bleed, but that's OK. I'm not supposed to read it, maintain it, or debug it. Think Emscripten or dart2js.
If you tell me you are writing a language that transpiles to JS, then my assumption is that you treat the output JS as a first-class developer artifact. The generated output should, as much as possible, match the structure, formatting, and naming of the original code. I should be able to read it and step through it in my debugger. If the source language's maintainers disappear, I can check in the compiled output and move on with my life using it as vanilla JS. Think CoffeeScript or TypeScript.
Those are very very different kinds of tools, and it's handy to have words to distinguish them.
Does that make gcc a transpiler for converting portable assembly to platform-specific assembly due to their similar semantics?
GCC is an optimizing compiler, at which point all bets are off for obvious/trivial translation between C and asm. You could, hypothetically, write a optimizing TypeScript compiler that emits asm.js.
However, while you can reasonably argue C started as a portable assembly, significant differences like a type system, pointer arithmetic, a calling convention, etc, exist now. I don't think it's unreasonable to say C is significantly higher-level than assembly.
1. My parenthetical at the end was anticipating this—then again, the translation between C and asm frequently is easy, albeit tedious.
And in the other direction one could argue that those so-called "transpilers" actually compile from a higher-level language when you consider complex type-inference and static type checking. Optimizing is not all a compiler does.
First, the "semantics" had better not change, either by an optimizing or non-optimizing compiler, or you've got a miscompile.
Second, I've seen several source-to-source compilers (that the proponents of the term transpiler would certainly call transpilers) that do non-trivial transformation, e.g. to try to capture certain idioms, or that are required as a result of an "impedance mismatch" between the languages.
If you could just as well program directly in the target output/language for the problem domain, then it's a transpiler.
Perhaps you don't think you could "just as well" program in assembly language, but there are many many people who do, perhaps not in your own problem domain.
I don't think it matters if there are "many people who do" -- as long as they are still a small minority compared to those who don't. After all you can find people believing everything, I'm sure some are even writing web apps in Assembly.
That said, C to Assembly (as opposed to binary executive) could be said to be transpiling too -- from "portable assembly to assembly".
That really makes no sense.
Same for usage of things.
There were always be outliers for whom a thing is better used for Y rather than X, but in the end is what the majority sees the tool as useful for that determines how it's defined (in casual use, dictionaries etc).
Microcode to Electron "Transpiler"
The term has been in use in academic literature since at least the early 1960s.
http://comjnl.oxfordjournals.org/content/7/1/28.full.pdf+htm...
> we've been doing source-to-source compilation for a very long term
Yes and we've been calling them transpilers all along!
I'm a programming language researcher and I think the term is very useful to distinguish between different kinds of compilers.
I've skimmed this several times and have now run it through a PDF OCR program, and am not finding it.
Even if this paper does use the term saying "we've been using it all along!" is hardly accurate because this has hardly been a well-known term until very recently - I've read hundreds of academic compilers (mostly on the optimization & code generation side of things) going back to the late fifties, and it's only a term I've seen used in the very recent past.
Transpiler means high-level to high-level translation. Compilers which implement such a translation have properties and challenges in common. It's a subset of compiler. I don't know how anyone can think it's wrong to have a term, whether it's new or not, to refer to a useful subset like that.
What harm or misunderstanding could it possibly cause?
The harm comes from having a definition that is so loose as to be meaningless. You're now saying "high-level to high-level", but most people use the terms "source language to source language", and several people here have admitted that a compiler that generates assembly should be considered a transpiler.
If you're going to define it as something that goes from a "high-level" language to another, then you need to define high level. Is C high level? is C++? is HLSL (there are lots of HLSL <-> GLSL translators)?
Also, in almost every context that I see "transpiler" used, people say that it's a transpiler from X-to-Y, which adds zero value above saying it's a compiler from X-to-Y.
People usually don't feel the need to qualify what they are compiling from or to, despite the fact that many compilers target (or use as a source) many kinds of languages and/or intermediate representations.
The overall point here is that compilers (of all kinds) are simply translators - some from a high level source language to one form of (textual or otherwise) IR, some from one form of IR to another, some from one source language to another (be it high level or not), etc. Saying one is a "transpiler" and others are not, especially when you give adequate context and say what the source and destination forms are, just doesn't add value.
Swift: var n = m--;
JS var n = --m;
Forget that ++ and -- operators are deprecated and not available in Swift 3.0; simple but profound mistakes like this do not instill confidence at all.
It is a serious piece of work, the compiler is compiled to JS too, so you can play it in the playground(even work offline): https://bloomberg.github.io/bucklescript/js-demo/
It also generates very small code output, for example `hello world` is 20 bytes instead of 100K bytes
However, if the browser only supports a given language than the final target must be that language, similar to how only machine code executes of a CPU, everything else is just a turing machine emulating another turing machine.
Because that's the only actual and in use browser I can think of that supports a language other than JS natively.
ActionScript is only supported through the Flash plugin, and inside the Flash environment -- and even that is taken out altogether in the new Chrome release.
C++, not at all. Except if you mean Chrome is written in C++ itself, or you can use Native Client, which again is another plugin like environment.
So, nothing similar to JS at all.
Might as well have mentioned emscripten, which does end up running as a web page.
Does it act like JS? No, but its still native.
There's no usefulness of TypeScript as a target for a compiler for Swift, because Swift already has static typing.
I wonder why doing this. What's the applicability of doing this? Will this applicability still remain valid when WebAsembly hits with a real swift binary?
Second, nobody (except the Japanese) really gives a duck about Shift JIS (and not many people care about Shift JS either) to warrant anything on either side.