While searching about the difference, I came across these definitions:
Compiling is the general term for taking source code written in one language and transforming into another.
Transpiling is a specific term for taking source code written in one language and transforming into another language that has a similar level of abstraction.
I understand what Abstraction is.
But what does "similar level of abstraction" mean in the above definition? And how do we find the level of abstraction in a language?
The definition you have quoted above is too general for a beginner to understand completely and so let me just simplify it to something we see practically.
Compiler: is an umbrella term to describe a program that takes source code written in one language and produce a (or many) output file in some other language.
In practice we mostly use this term to describe a compiler such as gcc which takes in C code as input and produces a binary executable (machine code) as output.
Transpilers are also known as source-to-source compilers. So in essence they are a subset of compilers which take in a source code file and convert it to another source code file in some other language or a different version of the same language. The ouput is generally understandable by a human. This output still has to go through a compiler or interpreter to be able to run on the machine.
Some examples of transpilers:
Emscripten: Transpiles C/C++ to JavaScript
Babel: Transpiles ES6+ code to ES5 (ES6 and ES5 are different versions or generations of the JavaScript language)
Now, what do they mean by "similar level of abstraction":
As I said it compiles/transpiles to a source file, one can argue that assembly language is also a source file and thus gcc is also a transpiler. So, this argument is what this similar level of abstraction voids.
The notion of categorizing languages into lower, middle and higher level is based on the level of abstraction they provide from the actual working of the machine/architecture.
Lower level languages like assembly are very close to the processor architecture i.e. have different instructions for different processors. While C/C++/Java/JavaScript, abstract all this away providing more abstraction.
So, a transpiler compiles to a language that is closer to the language you started with in the terms of this abstraction (or is closer to the level of that language in the lower-middle-higher level language ladder).
Here's a sort of descriptive way to answer
If you think of layers of abstraction as this example:
(1) CPU-level (actual logic gates on the CPU)
(2)machine code
(3)assembly code
(4)[C/C++, JVM/bytecode]
(5)[JavaScript, Python]
A compiler goes to a lower level (lower number). A transpiler switches from one language (or version of a language) to another at the same number.
Ex: TypeScript ( a Microsoft superset of JavaScript with type safe checking) transpiles to JavaScript code which can run on different types of browsers.
https://en.wikipedia.org/wiki/Microsoft_TypeScript
"Microsoft TypeScript is an open-source programming language developed and maintained by Microsoft. It is a strict syntactical superset of JavaScript, and adds optional static typing to the language.
TypeScript is designed for development of large applications and transcompiles to JavaScript.[5] As TypeScript is a superset of JavaScript, existing JavaScript programs are also valid TypeScript programs. TypeScript may be used to develop JavaScript applications for both client-side and server-side (Node.js) execution."
I mostly agree with tapananand answer, but...
definition
Words are "made", so they serve a purpose. And this also changes with time.
We now tend to use transpiler to specify a compiler that translates code into some other code "more similar" to the source one, that what a compiler might do. And is used to differentiate both mostly when both of them are mentioned in the same context (again mostly implying that a transpile language will have to get compiled at least once more)
examples
So everything is very subjective. At the time of this writing:
Coming from the Java world I could call CoffeeScript/TypeScript transpilers to depict that the resulting code is no more efficient than the original one.
CoffeScript documentation says it's a compiler, and babel is a transpiler. The want do say that CoffeeScript, although very similar, is not Javascript. At least not a version of it, as that is what babel produces.
Babel calls itself a compiler.
fazit
So transpile is at this time very rarely used anymore, and only to tell two compilers apart.
It will probably dissapear as concept, since compilation is much more complicated than that (same/higher/lower language, version, etc), and the word doesn't seem to be useful anymore ("transpilers" are now ubiquitous)
Meaning of "similar level of abstraction"
Higher level languages are more abstracted than lower level languages. By abstracted I mean easier to understand.
Higher level language(highly abstracted)---- Similar level -----> Higher level Another language(highly abstracted)
(TypeScript Source code to JavaScript Source code)
Mid level language(poorly abstracted) ---- Similar level-----> Mid level language(poorly abstracted)
Higher level language(highly abstracted) ---- Not Similar level of abstraction -----> Mid level Another language(poorly abstracted)
Computers only understand 1s and 0s: You can think of computer as being a box, crammed full of switches - kinda like a light switch: they can either be "on" or "off" - they can either be a "1" or a "0". You can instruct a computer which switches you want on or off, with a series of "1s" and "0s".
People need programming languages: Human beings are not very good at reading/understanding hundreds of thousands of lines of "1s" and "0s"........ but we can be trained to understand human words: like: class and break.
Programming languages allow us to write computer instructions, which can be translated into 1s and 0s (compiling), or which can be translated into other programming languages. for example: if you have elm code, you can easily transform that into javascript (transpiling).
The word "preprocessor" often used as synonym for "transpiler".
The word "preprocessor" was already well-known in the 90th and emphasises that something is processed before something else. It is also used in a context of removing comments before code is compiled.
The word "transpiler" became more popular in the 2010th (I heared it first 2015 from a colleague with contact to AngularJS community), calling the process of bringing TypeScript to JavaScript as "transpiling" - as some kind of translation that is like a compilation (checking data-types etc.).
To sum it up:
"Transpilation" fits best when something is translated with some compilation-like functionalities.
"Preprocessor" is a more generic term where basically something is processed before.
Compilers are used to compile source code written in one language to another. A compiler will often use the same syntax as the input language, but it may also be designed for some other type of input, like bytecode.
Transpilers are different because they translate code from one programming language to another. The original program may have been written in JavaScript, but the transpiler converts it into HTML.
Related
I was wondering why do we need the RN Bridge in the React Native engine which connects the Javascript VM (JavascriptCore) with the Native Modules. This bridge and message passing setup only slows down the app speed and creates a bottleneck. Why can't the package bundler spawned by React Native CLI, instead of just bundling javascript codes to main.bundle.js, also convert it to native code? one reason I've heard is coz javascript is not strongly typed, but this reason doesn't seem unsolvable. Any other reasons?
Indeed transpiling javascript into native code will provide tremendous performance improvements however it is not an easy thing to do at all. That being said, there are a lot of reasons why transpilation from one language to another is hard, and this is especially true if we consider the host language to be javascript and the target language to be java or something similar like C# and objective c.
Javascript is extremely different from these languages, many of the ideas are hard to map into a one to one, and the mindset is completely different.
Another thing that is special about javascript, and that makes it hard to transpile it to another language, is that javascript can never be a versioned language, and that since its the language of the web it has to always support backward compatibility. This means if a tool were to transpile from javascript to another language, this tool needs to support everything that javascript supports - one might argue that a tool might support only a recent subset of javascript, something like es6, however this is dangerous for two reasons, one it will be hard to define this subset exactly since a lot of es6 features are working by polyfills from es5, and two that this means that this tool wont be able to support all the javascript ecosystem.
here are some of details about some challenging parts of javascript to be transpiled into a language like java:
javascript is a dynamic language, not only there are no restrictions on types, but javascript do an extremely complex type coercing techniques in different operations under different conditions
consider this
true + 1 === 1 + '1' // false
true + 1 === 1 + +1 // true
Javascript introduced modules system only recently (starting from es6) this practically means that any program is one huge chunk of code, where variables live through out the entire program.
Javascript inheritance system (the Prototypal Inheritance system) is extremely different from classical inheritance systems in these languages, for example in javascript at runtime you can change the the class of an object, at the same time in runtime you can also change the methods of a class.
Now on top of all the technical challenges, notice that there is a product wise decision here, in making RN like this. This enabled RN to go to market faster, and not be tied to certain native language, this means its much more easier this way to support new environments by just transpiling ui controls to the native ui of that environment, and keeping javascript as it is. And on top of that if tomorrow, someone find a way to transpile javascript to java, this tool can be easily integrated into RN pipeline, without affecting the other components and supported environments of RN.
I have recently been working on a small to medium sized game in JavaScript to familiarize myself with it and come from a background in C and Java. In my game I am using a few constant numbers to render all of my objects and I was wondering about the performance impact those would have. Both C and Java are languages with compilers that will automatically simplify simple statements such as 2 + 3 into 5 before the code is actually run. This is great because it means I can make my code more readable by having something like WINDOW_MAX_Y - SHIP_Y in my code and understand what it does later. Looking over my code recently however, I found a few lines of code that become very long when written in this style, and because JavaScript does not have a compiler I was wondering whether it would improve performance if I simplified everything into "magic numbers" or if JavaScript had some function that would automatically simplify the lines before execution like the C compiler. I would like to keep my code readable, however, if JavaScript does not simplify those statements I would love to know as they are run thousands of times per second.
Not necessarily before execution but when the interpreter detects that the code is being used heavily.
You mention Java and this is good because I think you may be familiar with the concept since Java was one of the first languages to implement it. It's called just-in-time compilation (or JIT for short).
There is no standard that covers how JIT is to be implemented in Javascript. And there is no standard that mandates that a javascript interpreter must implement JIT (this is exactly the same for Java by the way, it is perfectly legal to implement a JVM that does not implement a JIT compiler). However, market forces have ensured that all current major javascript interpreters have implemented JIT (which may seem bit odd since all major javascript interpreters are free but they are competing for market share, not profit).
Similarly you mentioned C, which is nice because it also means you should be familiar with another concept. In C there is no standard defining how a = 1 + 2 should be compiled to. There is a concept in the C standard that specifies the behaviour of such optimisations though: the as-if rule. It basically states that if a complier was to implement optimisations, the end result must be exactly the same as if there was no optimisation.
All major javascript interpreters currently have most of the common optimisations that compilers typically have. They are all slightly different (just as all C compilers are slightly different) but they all compile code just-in-time. In addition, most interpreters also perform optimisations during compilation to byte code.
Yes, there is byte code, just like Java. While there is no compilation step performed by the programmer, all current javascript interpreters compile to bytecode before execution just like Java. This is true for all modern "scripting" languages such as Python and Ruby.
My advice is basically if you don't worry about such things in C or Java then you should not need to worry about it in javascript. For things that you need to worry about in C (such as micro-optimisations) there is a subset of javascript called asm.js that is guaranteed to be compiled down to machine code instead of bytecode (if set up correctly).
I've been using Babel for a while now, and I've always been under the impression that Babel was a transpiler for converting my ES6 and ES7 JavaScript into ES5 JavaScript, as I was under the assumption that you could technically treat ES5 and ES6 as two different language.
However, I couldn't help but notice that Babel's website title describes it as a compiler, which I believe is something very different from a transpiler.
Is Babel a transpiler or a compiler, or perhaps offers both options? Or is the website's title simply incorrect?
Disclosure: I know this sounds like a very pedantic question, but I am writing documentation relating to Babel, and I want to ensure my description is accurate
The definitions of "transpiler" and "compiler" are blurry. Both of them do translate a program from one language to another language while keeping the behaviour.
We usually name it a "compiler" when it produces an executable binary. However, binary is just another language, which can be interpreted by a CPU. Every program is "executable" on the respective machine.
We usually name it a "compiler" when it produces a lower-level output than the input was, e.g. C to assembler. Or Java to Java bytecode. Or ES8 to ES5. Wait… is that really a different level?
We usually name it a "transpiler" when its output is on a similar level as the input, e.g. Python to JavaScript or the other way round. However, there always will be parts that use an abstraction available in one language that need to be "compiled" to a lower-level implementation in the other language.
So to answer your questions:
I believe a compiler is something very different from a transpiler.
No.
Is Babel a transpiler or a compiler, or perhaps offers both options?
Yes.
Or is the website's title 'Babel - The compiler for writing next generation JavaScript' simply incorrect?
No. That title focuses on next-generation features, i.e. higher-level abstractions that really need to be compiled into a very different output. Even though the output is still ordinary, mostly human-readable, JavaScript.
I am writing documentation relating to Babel, and I want to ensure my description is accurate
In that case, I'd use their own terminology from the official website. If you want to compare the tool to others, choose your own description.
Babel is a transpiler, which is a special type of compiler, so both terms are techincally correct. You may use either at your preference.
It's irrefutable that Babel is a source-to-source compiler (aka transpiler) since its source and target languages are both some flavor of JavaScript:
A source-to-source compiler, transcompiler or transpiler is a type of compiler that takes the source code of a program written in one programming language as its input and produces the equivalent source code in another programming language.
However, not everyone agrees that the distinction between the terms is helpful, so some people prefer simply, "compiler".
I personally like the distinction because, to me, it implies something about the difference in level of abstraction from machine langauge between the source (input) and target (output) languages. That is, typical "compilers" translate from higher-to-lower level languages, "decompilers" translate from lower-to-higher level languages, and "transpilers" translate between languages at similar levels of abstraction.
Transpilers, or source-to-source compilers, are tools that read source code written in one programming language, and produce the equivalent code in another language.
Babel is both a transpiler and compiler as the words can be used interchangeably.
Just FYI, 'compiler' is defined as
a program that converts instructions into a machine-code or
lower-level form so that they can be read and executed by a computer.
So I personally disagree that Babel is a compiler but I don't really care if others use them interchangeably.
I've just started to explore new JavaScript ideas and I'm pretty impressed. At first sight both CoffeeScript and TypeScript have some great features. They're both compiled to JavaScript. CoffeeScript is great because it makes code shorter and clearer. TypeScript on the other hand gives us possibility to build complex applications.
Is it possible to mix TypeScript and CoffeeScript? I mean - take advantage of both of them in the same file?
Short answer: no.
You need to compile a CoffeeScript/TypeScript file to a JavaScript file, which means that this file, as a whole, must be syntactically correct for the given language.
CoffeeScript and TypeScript are not syntactically-interchangeable. At best, you would have to resort to some lowest common denominator in terms of syntax use, but that would completely defeat the purpose of using any of the two instead of plain JavaScript.
You can't and it is really a bad idea.
Let's suppose that you can have CoffeeScript and TypeScript in one file, then you need developers who can program in both of them, so your product will be more expensive. Moreover, you will lose any reasonable chance of using lints to check your code.
I can't even imagine what kind of troubles you would go through with modules (commonjs, AMD, ES6, ...) when combining CoffeeScript and TypeScript.
If you use one language, you typically get from its authors tutorials how to do things in the language properly. When you mix languages, you would have to come up with "what is proper way to do X in my environment". These challenges sounds petty but for any serious project they can be deadly.
If you can choose, I would recommend TypeScript because it saves you from a ton of runtime errors. It's not that visually nice as CoffeeScript but that's not what you are paid for typically.
Have a look at compiled-coffee wich states:
Do you like the type safety of TypeScript and the concise syntax of
CoffeeScript? In that case CompiledCoffee is for you! It combines
CoffeeScript with TypeScript's type system via the definition files.
You create a *.coffee file and a *.d.ts file with the same name, in
which you (optionally) type stuff. Rest is handled automatically.
Not currently, both CS and TS have a bunch of incompatible syntax. You'd need a dedicated compiler for those types of CoffeeTypeScript files and that compiler does not exist.
I'm very interested in how a language like that would look but I'm afraid it will have too many options and be hard to learn (relative to either CS or TS). I would imagine programming in it would be somewhat similar to python.
By now, most mainstream browsers have started integrating optimizing JIT compilers to their JavaScript interpreters/virtual machines. That's good for everyone. Now, I'd be hard-pressed to know exactly which optimizations they do perform and how to best take advantage of them. What are references on optimizations in each of the major JavaScript engines?
Background:
I'm working on a compiler that generates JavaScript from a higher-level & safer language (shameless plug: it's called OPA and it's very cool) and, given the size of applications I'm generating, I'd like my JavaScript code to be as fast and as memory-efficient as possible. I can handle high-level optimizations, but I need to know more about which runtime transformations are performed, so as to know which low-level code will produce best results.
One example, from the top of my mind: the language I'm compiling will soon integrate support for laziness. Do JIT engines behave well with lazy function definitions?
This article series discusses the optimisations of V8. In summary:
It generates native machine code - not bytecode (V8 Design Elements)
Precise garbage collection (Wikipedia)
Inline caching of called methods (Wikipedia)
Storing class transition information so that objects with the same properties are grouped together (V8 Design Elements)
The first two points might not help you very much in this situation. The third might show insight into getting things cached together. The last might help you create objects with same properties so they use the same hidden classes.
This blog post discusses some of the optimisations of SquirrelFish Extreme:
Bytecode optimizations
Polymorphic inline cache (like V8)
Context threaded JIT (introduction of native machine code generation, like V8)
Regular expression JIT
TraceMonkey is optimised via tracing. I don't know much about it but it looks like it detects the type of a variable in some "hot code" (code run in loops often) and creates optimised code based on what the type of that variable is. If the type of the variable changes, it must recompile the code - based off of this, I'd say you should stay away from changing the type of a variable within a loop.
I found an additional resource:
What does V8 do with that loop?