TurboScript icon indicating copy to clipboard operation
TurboScript copied to clipboard

TypeScript compiler integration.

Open nidin opened this issue 7 years ago • 33 comments

In order to move fast forward we need to integrate turboscript with typescript compiler. I will create a new branch for it.

nidin avatar May 16 '17 04:05 nidin

Hmm... that's the one decision I regret. It made the code horribly complicated, and the compiler supports the wrong features.

Main issues I had

  • The API is just not intended to be used for a compiler. It is mainly a type checker. You will face many situations where the API just does not provide the information you need, or you need to hack around to get to the information
  • There is no API documentation
  • TypeScript lacks support for many base types like int, uint...
  • TypeScript is unsound
  • TypeScript supports features that cannot be compiled efficiently to native code --- as does JavaScript. The result thereof is that TurboScript will be slower than JavaScript. Furthermore, you still need your own analyzer to determine any unsupported features. Here I strongly encourage you starting benchmarking and comparing your results with JS soon to ensure that performance does not drop because some unessential feature has been added.

I think, having your own simple type checker is actually a benefit.

MichaReiser avatar May 17 '17 07:05 MichaReiser

Good points. These were the initial reasons I don't choose modifying TypeScript compiler. Mainly I don't understand TypeScript compiler due to lack of documentation. 🙏 Thanks for the valuable input.

nidin avatar May 17 '17 09:05 nidin

The TypeScript API is quite simple in most cases. However, it's often unclear what result you get (in some cases you will find out that the result seems not to return what you have expected but behaves well for others).

However, I understand that you don't want to maintain your own type checker. But at the moment I don't know of any TypeChecker that has support for "low-level types". Supporting these low-level types has the disadvantages that TurboScript (or Speedy.js) does not embed nicely into TypeScript or Flow because it supports additional types. Right know, I don't know what the best solution is. My goal would be to have my own type checker that can parse either TypeScript or Flow code but also allows to have base types like int... However, it does not seem as TypeScript intends to add support for more base types in the near future and therefore, the IDEs will show a bunch of errors if unsupported base types are used. So, I begin to believe that separating the JavaScript and the TurboScript code might have been the better chose than allowing directly embedding it into TypeScript code. Even though I believe the latter is far more elegant.

So, I'm very interested in where this is going as I'm facing the same issues.

MichaReiser avatar May 17 '17 09:05 MichaReiser

For the time being I will continue supporting current TurboScript type checker. The primary goal is not supporting complete TypeScript instead make TypeScript like language (TurboScript) faster in WebAssembly

nidin avatar May 17 '17 09:05 nidin

I think language grammar and typescript the same, while adding new types, and for efficiency do not have to support all the typescript syntax, if all support is better.

"use turboscript";
class User{
......
}

izengliang avatar May 17 '17 10:05 izengliang

@MichaReiser in speedy.js you are using custom transform for visitor of AST Walker, right? But what if using someting lower level like this: https://github.com/Microsoft/TypeScript/blob/02547fe664a1b5d1f07ea459f054c34e356d3746/tests/cases/conformance/parser/ecmascript5/parserRealSource11.ts

MaxGraey avatar May 17 '17 14:05 MaxGraey

@MaxGraey The AST walking part isn't the problem. Most compiler use AST walking for generating the source code. The custom transform is needed to remove the source of the compiled function from the emitted code and to rewrite the entry functions (a function that is called from pure js).

The main problem of the TypeScript API are the missing base types. These are one of the main reasons why WebAssembly achieves better performance compared to a pure JS implementation. Today's JavaScript engines are surprisingly fast! Without good consideration of the language features and heavy offline optimization, the WebAssembly implementation is most certainly slower than a pure JS implementation (when talking about peak performance).

MichaReiser avatar May 17 '17 14:05 MichaReiser

What about using LLVM?

winksaville avatar May 17 '17 14:05 winksaville

@winksaville I believe that is a totally different topic, isn't it?

I believe LLVM is great and offers many optimizations for free. However, it requires that the users have an llvm installation, making the setup much harder --- especially as the web assembly backend is not yet part of the prebuilt binaries. I personally would use the optimizer that is part of binaryen and compare the runtime of TurboScript implementations to ones in Emscripten. If there is a significant difference, you may consider switching to LLVM.

MichaReiser avatar May 17 '17 14:05 MichaReiser

@MichaReiser so implement for example SyntaxKind.Float32Keyword, and create it as intrinsic type is huge problem?

MaxGraey avatar May 17 '17 15:05 MaxGraey

@winksaville someone told that emscripten or other tool allow optimize wasm files. So we can generate unoptimized wasm and optimize it later if needed.

MaxGraey avatar May 17 '17 15:05 MaxGraey

@MaxGraey Yes it is. You need to maintain your own version of TypeScript. And, since TypeScript is written in TypeScript you may need to make further adjustments to the TypeScript code just that it still compiles. I don't know if this is any better than maintain a custom, very simple type checker instead?

However, I would say create a simple prototype. See if you face the same issues as I did and do some benchmarking. Maybe, you find some trick I did not or you can gain the favor of the TypeScript team so that they add support for base types.

MichaReiser avatar May 17 '17 15:05 MichaReiser

@MichaReiser it is a different subject, but it seemed that using TypeScript to generate wasm wasn't practical based on your comments so I just threw it out. And you're right there are no prebuilt binaries yet but apparently it will be in the next release. I have compiled the a tool chain using these instructions and it was able to compile a couple trivial things. So its coming along.

@MaxGraey my assumption is that in the foreseeable future LLVM will probably have the best tool set.

winksaville avatar May 17 '17 15:05 winksaville

@winksaville That's the toolchain I'm using in Speedy.js

MichaReiser avatar May 17 '17 15:05 MichaReiser

I would wait for TypeScript team's official support for low level types, otherwise we might need to spent more time on patching TypeScript. At this point I would suggest freeze adding features to TurboScript and make current version bug free. @MichaReiser I dropped class inheritance for now. I need to fix the issue with generics and we will make some benchmarks against TypeScript version then we can move forward. These initial benchmarks will be useful for further developments.

On Wed 17. May 2017 at 5:46 PM, Micha Reiser [email protected] wrote:

@winksaville https://github.com/winksaville That's the toolchain I'm using in Speedy.js (see draft of documentation https://github.com/MichaReiser/speedy.js-paper/releases/latest)

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/01alchemist/TurboScript/issues/87#issuecomment-302132960, or mute the thread https://github.com/notifications/unsubscribe-auth/AAMGZjTnwF39puhuk3Chs-mMN-KWXMSOks5r6xZWgaJpZM4Nb-ZN .

nidin avatar May 17 '17 15:05 nidin

@MichaReiser an FYI its confusing to me that you say Speedy.js is a JavaScript to wasm compiler but then you say it takes TypeScript source.

So I think @nidin's goal "TypeScript like language (TurboScript) faster in WebAssembly" is the good goal.

winksaville avatar May 17 '17 16:05 winksaville

I find it https://github.com/jeremyfa/node-ts2hx
have help ?

Typscript -> c++ -> wasm ?

izengliang avatar May 17 '17 22:05 izengliang

find it https://github.com/andrei-markeev/ts2c

typescript -> c -> wasm ?

izengliang avatar May 17 '17 22:05 izengliang

@liangzeng I don't think it's a good idea. A lot of tools and compile time and we should support 3-4 tools in the same time instead just one

MaxGraey avatar May 17 '17 22:05 MaxGraey

By the way this tools stack in my opinion js -> haxe -> c -> emscripten -> wasm already used in NectarJS and it has a huge bundle size

MaxGraey avatar May 17 '17 22:05 MaxGraey

ts -> wast -> wasm
Whether to reduce the workload?

izengliang avatar May 17 '17 22:05 izengliang

ts2c is completely unusable. For example it can't transpile this simple example:

class Vec3 {
   x: number;
   y: number;
   z: number;

   constructor(x: number, y: number, z: number) {
       this.x = x;
       this.y = y;
       this.z = z;
   }

   add(other: Vec3): Vec3 {
       return new Vec3(
           this.x + other.x,
           this.y + other.y,
           this.z + other.z
       );
   }
}

MaxGraey avatar May 17 '17 23:05 MaxGraey

@liangzeng I think ts -> wasm and optional wasm -> wasm optimization via binaryen

MaxGraey avatar May 17 '17 23:05 MaxGraey

There will be no more features in TurboScript v1 until we get a decent test coverage. TurboScript v2 scope will be like this. TurboScript Scope emitted code will share common runtime in WebAssembly like malloc, free and stdlib. Unsupported features will emit to JavaScript and imported to WebAssembly. its not really bad because when importing javascript functions to WebAssembly it will generate optimised machine code and hopefully it will be faster, lets see. We will eventually implement these unsupported features in WebAssembly and switch off javascript emission.

nidin avatar May 18 '17 04:05 nidin

@nidin good idea . c/c++ also can not use webassembly to achieve all features .

javascript + webassembly = c/c++ all features

izengliang avatar May 18 '17 06:05 izengliang

The real effect of webassembly is loop and recursion ,so first implement. other language features can be added step by step.

izengliang avatar May 18 '17 06:05 izengliang

Typescript ------compile ---> JavascriptWrap + WebAssembly WebAssembly is preview , the way is flexible .

izengliang avatar May 18 '17 06:05 izengliang

In the future, can implement the full Typescript features.

Typescript / Javascript ------ compile ---> dynamic (javascript) + static (webassembly)

Feature

Compile life cycle plugins Compile parameters "Use wasm" tag Smart tips Other

☯ Dynamic and static combined into one.

izengliang avatar May 18 '17 06:05 izengliang

test.ts

"use wasm";
// compile to javascript
export function test(){}

// compile to wasm
export class User{
     constructor(public name:string){}
}

// compile to js + wasm
export {
    // compile to js
    a(){},

    // compile to wasm
    b(num:number){
       for(let i=0;i<num;i++) {}
    }
} 

test.js

// section compile to js 
module.exports = {
     a(){ },
      
     b(num){   //  inference is number type 
            "use wasm";   // compile to wasm
             for(;num;num--){ ... }
     }

}

izengliang avatar May 18 '17 06:05 izengliang

So now we have three ts -> wasm projects with three different approach:

MaxGraey avatar May 23 '17 14:05 MaxGraey