Advertisement
Advertisement
⚡ Community Insights
Discussion Sentiment
80% Positive
Analyzed from 3768 words in the discussion.
Trending Topics
#runtime#typescript#perry#code#project#express#https#type#compiler#types
Discussion Sentiment
Analyzed from 3768 words in the discussion.
Trending Topics
Discussion (95 Comments)Read Original on HackerNews
Edit: as discussed in the thread below, the most likely reason for that is that Express is pure JS with types from @types/express, so the TypeScript compiler bails on it. Reasonable, but still frustrating.
Overall, it seems like every time I decide to try a vibe coded compiler I get this feeling like when you see a plate with fruits on a table but, coming closer, see that they are fake plastic fruits. No, I cannot use it to build a native binary of my project without V8 as easy as shown on the front page. Maybe some other project, yes, but not a real one.
Unrelated: if a project is called Perry, should the icon be a platypus in a hat, you know?
(I'm the founder of Perry) thanks for giving it a try and let me be upfront with you: Compiling express has been one of the hardest challenges for Perry. I'm 99% sure it still does not work out of the box just yet - which is why we pivoted to fastify more than express.
That said, the last few days we made great progress to get Perry to compile packages "lik" Express (lot's of dynamic imports) much better.
I'll retry this once our current batch of Nodejs parity issues are resolved.
Just to be clear though: No v8 runtime, we actually took out the v8 engine we had optionally included thus far because the benefits no longer outweight the disadvantages.
If you want to tag along the progres follow me on X (@proggeramlug), that's where I share the most up to date progress on Perry.
Also, it is definetely a goal to compile apps that use Express and that will happen - not commiting to a timeline but just in the last few days we got so much closer.
> Perry exposes a faithful subset of Node.js’s stdlib HTTP server modules on top of hyper + rustls + tokio-tungstenite. The whole shape — handler signature, IncomingMessage / ServerResponse properties + methods, TLS opts, ALPN-negotiated HTTP/2, WebSocket upgrade dispatch — works unmodified, so unmodified Node servers (Express / Koa / Polka / hono via @hono/node-server / etc.) compile and run natively[1]
It's pretty standard for "no runtime" to mean nothing on the device you install the compiled target app.
I think iOS development still needs Ruby for Pod installation but no one says Swift apps need a Ruby runtime for example.
[1] https://docs.perryts.com/stdlib/http.html
Only by layman that don't understand compilers.
Currently tsz passes nearly 100% of TypeScript tests but that is not enough. I want it to be able to type check complex things like type-challenges solutions or complex utility type packages. I'm stress testing it with a repo with 1.5 million lines of code.
I'm constantly assigning AI agents tasks to find bugs in tsz and open issues.
I'll say this is "alpha" when it can do all those things plus matching tsc exactly in thousands of open source projects where tsc reported type errors. It's easy to find CI runs that tsc reported errors. I'll build a database of all the cases I've verified tsz with and will publish those. Hoping that can give folks confidence that tsz is robust
For now, tsz is just a work in progress.
https://tsz.dev
The website doesn't explain how it works in a lot of detail. I am the author of tsonic [1], a TS compiler that produces binaries via Clr NativeAOT (on Linux/Mac). The hardest parts were numbers (TS has no ints or shorts), Generics, and TS Utility Types. I've been on it for the last 6 months (almost every day); getting to near complete TS compatibility is a very long journey because of its expressiveness.
Add: A request is to explain how it works on the website. I did take a look at https://www.perryts.com/en/internals/ but are those techniques described really sufficient to express TS? Based on my experience, I must say I'm surprised. But the proof is in the pudding, and if it's compiling those examples it must be working somehow!
[1]: https://tsonic.org
thanks for your comment. I'm Ralph, the founder of Perry (though at this point we are quite a few core contributors + maintainers).
You are right to be skeptical and yes, numbers are the hardest. In fact we started adding some native numbers to make things easier (i64, i32 etc.), types that are not natively available in Javascript/Typescript but make it much easier for the compiler. And they'll internally work as numbers for any other runtime.
The docs I must admit are not quite up to date. We have been pushing hard for Nodejs parity the last few dayys/weeks and are making great progress, however the docs and the site have not been updated in the same time just yet, so apologies for that.
Also, just as a fun fact: I noticed a spike in traffic and found this threat, so happy to take any requests but I'm not the OG of this threat haha.
Two things I found a little confusing from the docs though:
I couldn't easily find a page describing what it can't do yet. I saw that it only works with a "strict, deterministic subset of TypeScript", but is there a page showing what's included and not included in that subset?
Also, what's an "ambient surface" in this context? Is that a compiler term I'm just not familiar with?
I'll add that page, thanks. Today, almost all of idiomatic TS is supported including most of its utility classes. Dynamic JS-style code is not supported, for example adding a function or a field into an object, prototype-based class modifications etc. I'll compile a list, and include it along with the large docs cleanup planned before v1.
> Also, what's an "ambient surface" in this context?
The idea is that when JS gets transpiled into C# (or Rust, upcoming), JS globals and built-ins are invalid. The native "surface" is C#, meaning the string is .Net's string type and the methods that you expect on JS strings would be missing. But when you opt in to a surface, such as the "JS surface", the compiler applies surface defined translations such as substring becoming SubString, either directly or via a companion helper class. This allows you to write against standard JS and Node APIs, instead of relying on the stdlib/builtins of the target framework (currently CLR). And you get the JS "stdlib" - console, JSON, Date, Map, Set etc.
For example, all the projects you see under this use the JS surface: https://github.com/tsoniclang/proof-is-in-the-pudding/tree/m...
FYI, just in case you didn't know, there is an ExpandoObject type in the System.Dynamic namespace that you could use to do this. IDK if you want to, but it's one of those less common .NET features that people tend to not be aware of.
The easy way to handle that would be to just treat "number" as 64-bit float, since that is semantically how Javascript defines them. But that can hurt performance.
Another option is to define your own integer types
This is what I did. Most int usage is inferred, but if they had to define it explicitly, I make them import { int } from "@tsonic/core/types.js";
That said, the more I think about it the more dubious I am. The site boasts no runtime dependencies but clearly it’s going to need things like a garbage collector, you can’t just magic that requirement away. At a certain point is it just doing what a JS engine’s JIT compilation does… except ahead of time?
Also doesn't inspire confidence that the text on the site is very clearly AI generated and the GitHub log shows an endless stream of AI powered commits. About 15 per hour, every hour? Doesn’t scream stability.
The whole site is very jarring to read.
X. Y. SUPER Z. heading
X. Y. SUPER Z. in subheading
excessive purple and gradients
--> arrows
cards, cards, cards, cards
doesn't just X, emdash, it [SUPER Y]
more cards
ridiculous awful contrast in copy that makes things unreadable (grey on black etc)
Once you see a few, it becomes obvious
There is also, https://en.wikipedia.org/wiki/Wikipedia:Signs_of_AI_writing
...wait, I went and looked up that file.
"The Three Optimizations That Would Close the Gap"
You're presenting the data from there in an extremely misleading way! They in no way need to drop any Typescript semantics to go faster.
But this case I think they do know the number type for sure, they're just failing to optimize around that fact.
If you encounter code with the same hash as last time, load up the previously generated binary and run that... or is that already happening?
Like you really built a backend that lowers to LLVM, integrated it with a generational gc, wrote a cross-platform reactive runtime, and built support for eleven different targets within like a year? Are you just prompting the model to tack on the next coolest thing or do you understand how these features work?
I worry how many of these kinds of projects will show up now. How do you guarantee stability? If there's a memory corruption error in the GC implementation, who's going to debug it?
thanks for bringing up the concern. I am proggeramlug (or amlug, either way), Ralph, founder of perry.
Yes, Perry is heavily AI-assisted - similar to the Bun to Rust port is too. Your concern is real and I don't claim to have all the answers for that.
I do know that AI is much better at finding bugs when it comes to compilers than most humans will ever be. Decoding bytecode and knowing what it should be is nothing humans are good at - AI does it trivially.
So yes, lots of AI, but this is not a "vibe-coded" slop project either. I have decades of experience in programming (native) and so I'm quite confident that this will work out well - but I totally see your skepticism.
Now, to tell you the truth, for a lot of tickets AI does generate legit the better answers than me. And my time is quite limited.
That said, I will always stand behind my posts, AI-assisted or not.
Now the thread you specifically point at here is ironic in many ways. The other guy says "and claude won't tell you that", while in fact Claude said (in my response) the exact thing he claimed Claude would not be able to do. Anyways, the technical merrits of the conversation are certainly worthwhile and important.
The models are good enough that this works.
You can keep disagreeing for a while, but know that almost all the code in the industry is written like this now.
The concern basically boils down to how large and serious is the team and what if they abandon the project in few weeks or months .
These were always the risks, many here have been burned by betting years of their career building against promising but what turned out to be weak projects
OP is alluding to the fact that today commit frequency, lines of code or how active the contributors in the issue trackers are no longer good signals to use as proxy.
When the underlying project to yours is few million lines of code written by machines only it is not going to be feasible fork and maintain or in-house it if the maintainers abandon it
To be clear users of a library or a tool aren’t owed anything when it available gratis and fully open source .
However not everyone has access to unlimited tokens to disregard the quality (in terms of history and usage ) or size of the underlying project completely
IMO the maintenance story is more or less solved if you can keep AI agents refactoring and improving it in a loop.
> However not everyone has access to unlimited tokens
Apologies. I did not consider this when writing my comment, being spoilt by unlimited 'free' AI.
Free in quotes because, presumably, training agents on AI usage from developers is worth more than the cost of providing free AI.
It was a valid concern last year. We have seen tremendous progress on this in the last 4-6 months.
Even if your initial prototypes are unmaintainable slop, the state of the art models are fairly good at refactoring and fixing things.
In many places AI tools aren't even allowed to touch customer repos.
In compiler speak, a runtime provides all infrastructure required by the language for program startup, shutdown, infrastructure for the standard library execution.
Of course there is a (native) runtime, as there is for all languages (like you said) :)
https://docs.perryts.com/language/supported-features.html#ga...
`Error: JavaScript modules found but libperry_jsruntime.a not found. Build it with: cargo build --release -p perry-jsruntime`
Turns out jsruntime was removed one week ago, but the error messages probably not have been updated as they should.
https://github.com/PerryTS/perry/commit/848339fa4ee4b00a53f5...
It looks like others had a similar idea too, adding a "sound mode" to TypeScript, such as this project which is converting tsgo to Rust, also with LLMs.
https://news.ycombinator.com/item?id=48189156#48189573
https://tsz.dev/
It's already showing results that is nearly 3x faster than tsgo. For multi-file large projects I have some ideas to implement to make it faster there too.
Once tsz is fast and stable I'll shift focus on making sound mode a reality.
https://makecode.com/language
https://www.microsoft.com/en-us/research/publication/static-...
Much saner than a vibe coded compiler.
If you'd like to follow, here's my attempt at converting tsgo to typescript (called tsts [1]). Admittedly there's AI involved, but it's a very mechanical job. Going from golang to ts is not a very difficult problem, the other way around would have been way harder. The plan is to then compile tsts to binary via tsonic.
[1]: https://github.com/tsoniclang/tsts
It's mostly a mechanical port. Hoping to do a Show HN maybe in a month.
P.S: does it have PGO for collapsing numbers to ints when possible etc
What? How is this possible, even with something as simple as:
[1]: https://github.com/PerryTS/perry/blob/39d5ba2e9db5adf7f7fc90...
I am still inclined to believe AI just made up the documentation though, because this has its own tradeoffs.
Oh yeah, very often. Especially if it's a loop and resolves the same way very often.
Modern CPUs just blaze through code like this, after three decades optimizing for object oriented and dynamic languages.
Otherwise the best you can do is be solid on common special cases. Which is what a modern (non-static) JS/TS runtime is.
There are a bunch of tools that JIT somewhat optimized assembly.
Is that true? It just goes right into the code with no initialization of any other libraries needed?
Would love to see more about it, or see more about the actual compiler docs.
While the UI framework part is neat, I prefer not to force everything into TS. Combining it means UI definitions and semantics get mixed into AST, making the unbundling of them a humongous task in itself.
Exactly the reason I built my own with pretty similar native UI semantics which supports Rust, Go, Kotlin and more (https://hypen.space) - would love to integrate Perry with it to compile TS apps directly into the runtime - but while the idea itself is great, looking at the documentation makes it hard to implement, and a lot of parts seem confusing.
Can I just use the compiler without the rest of the framework? What is the architecture? What are the limits?
After digging through the documentation, I'm unfortunately just more confused honestly. There are dozens of packages and slop markdown files such as `BUG_STRING_COMPARISON.md` and or `PERRY_UI_IMPLEMENTATION.md` which is an instruction file left for the LLM that just makes me trust the project less.
So while the idea is cool and the performance seems cool, the AI slop presentation would definitely need improvement. Adding a human touch would make it much, much better, as one could actually understand what they are dealing with.