Live data from Hacker News

I’m porting the TypeScript type checker tsc to Go

kdy1.dev

121–130 of 252 posts

Re: I’m porting the TypeScript type checker tsc to Go

#121
post #27
post #19

> tsc depends on shared mutability and has a cyclical mutable reference. Rust is designed to prevent this behavior. Having two references to the same data (shared mutability) is undefined behavior in Rust. This problem has numerous solutions in Rust - (A)Rc, RefCell etc. I don't understand how this caused the author of the article to stop considering Rust.

Non-GC languages are bad in general at handling cyclical references (mutable or not), and Rust is especially ill suited for it because of the borrow checker. For example should an arbitrary reference in tsc become an rc::Rc or an rc::Weak? You have to tease out the implicit ownership model and one may not even exist. tsc was designed expecting GC and it makes perfect sense to port it to another fast GC language.

I honestly like the explicit weak ref model and it’s usually trivial (child objects are strong references, parents and siblings are weak), and rust has Gc as a last resort.

But if the author’s more familiar with Go, performance in Go is likely good enough

Re: I’m porting the TypeScript type checker tsc to Go

#122

If anyone happens to know: what are tsc's bottlenecks? I presume that if the bottleneck was just number of loop iterations, V8 would already be about as fast as C or any other language? Is it simply that accessing/mutating javascript data structures like objects, arrays, set, etc. is slow? Are those not fully optimizable by V8 for some reason? Or is it something else like the GC being slow?

This is a problem that can take advantage of good parallelism, Go will give you that and at the same time be more memory efficient.

Re: I’m porting the TypeScript type checker tsc to Go

#123
post #115

Earlier quoted context omitted.

Just today I was triggered that this compiles. declare foo: never[] // it can only be an empty array foo[1] // compiles TypeScript is a nice type system, it's surprisingly expressive and flexible, like e.g. in Haskell I was surprised that there's this strange notion that for a given type you can only have one `Eq` or `Ord` instance for some type A. But in TypeScript you can have as many Ord interfaces as you want. I…

I wouldn't expect never[] to mean 0 length array, tbf. It's a variable length array of _type_ never. It should be something akin to: declare foo: never[0];

I think the correct solution is:

    declare foo: []; // fixed-length array (tuple) without any items

Re: I’m porting the TypeScript type checker tsc to Go

#124

Earlier quoted context omitted.

> This reminds me of when people try to make a new Ruby implementation. They get the basics down and think "this isn't so bad! I can do this!". Fast forward a few months and they're stuck on some nasty little edge case around eval and method_missing that they need to run Rails. Or some weird aspect of C extensions. I think that's exactly why the author wrote this: > Eventually, I realized that rewriting a massive pro…

What is the difference between porting and complete rewrite? I thought they are the same?

I think here “rewrite” means completely changing the internal structure of the code (while preserving the functionality) whereas “port” means copy the structure of the internal code with as little modification as possible. And it’s hard to do the latter in Rust since Rust is not garbage collected.

Re: I’m porting the TypeScript type checker tsc to Go

#125

Earlier quoted context omitted.

> This reminds me of when people try to make a new Ruby implementation. They get the basics down and think "this isn't so bad! I can do this!". Fast forward a few months and they're stuck on some nasty little edge case around eval and method_missing that they need to run Rails. Or some weird aspect of C extensions. I think that's exactly why the author wrote this: > Eventually, I realized that rewriting a massive pro…

What is the difference between porting and complete rewrite? I thought they are the same?

Porting can involve a spectrum of changes. If you are porting to a different language, often for bug-for-bug compatibility you try to maintain the same rough code and class/object structure as the source codebase. This might give you some non-idiomatic code at first, but once you have good test coverage you can refactor. In this case you might maintain some of the upstream code structure to better match future changes.

Re: I’m porting the TypeScript type checker tsc to Go

#126
post #36

>shared mutability Sure but this goes against "Don't communicate by sharing memory", no?

> Sure but this goes against "Don't communicate by sharing memory", no? Yes, but that's advice rather than something Go requires. It's reasonable to say it's outweighed by the desire to avoid significantly restructuring the existing logic. The author is explicitly choosing to match the upstream program's structure to limit the project scope, and whether that structure is good or not is almost besides the point. btw:…

Curious, can you elaborate on what are the issues of mutability in single-threaded code?

Re: I’m porting the TypeScript type checker tsc to Go

#127
post #106

I'm surprised to see no one comment on Zig. It seems like the bun.sh developers are making some bold changes with such a low-level language.

I'm super bullish on Zig, but it's a bit early to bank on for production things as the language is still changing/being developed.

To give another example of where this came up: they were discussing using Zig for the Ruby JIT, but despite really liking Zig the team decided to go with Rust because of its maturity: https://bugs.ruby-lang.org/issues/18481#note-21

Re: I’m porting the TypeScript type checker tsc to Go

#128
post #86

Oof trust me from experience you do _not_ want to write a compiler or parser or anything like that in Go. The string support is so limited -- for example you have to implement basic things like reverse string from scratch instead of them (and much more) being in the standard library. Much better to use something like Crystal or Rust.

ESBuild seems to be doing fine.

I’m a crystal fan though, would love to see more tooling built with it.

Re: I’m porting the TypeScript type checker tsc to Go

#129

Given that ESBuild [0] is a way better replacement for Webpack already (and similarly written in Go) I can see how we could pretty soon have an entire toolchain written in Go for dealing with compiling JS. Hopefully the whole toolchain will be embeddable, too. Being able to do configuration-in-code and produce an executable that does the whole build step in milliseconds would be cool. [0] https://esbuild.github.io/

The author of esbuild also started the implementation of esbuild in rust, found it painful too and switched to build it in go.

For me the ideal use case for Rust is really for places where automatic memory management is a hard sell, even if technically possible, kernels, drivers, hypervisors, firmware, GPGPU, ...

For everything else I rather enjoy the productivity of automatic memory management.

Re: I’m porting the TypeScript type checker tsc to Go

#130
One thing that was not addressed in the post is the option of using a GC library in Rust. I'm not a Rust expert, but to me, it seems like this makes it quite feasible to quickly port a compiler. They could wrap most complex data structures in GC and optimize them as time goes by. That being said, I'd assume that the library's GC would be slower than Go, so perhaps that's a deal-breaker.
Post reply on HN