Implementing a Full Interpreter?
This issue is for discussing the proposal of implementing a full interpreter, to replace the current transpiler to JS. (see #18 )
Some things that I can think of:
Pros:
- More control over everything, easier to add features (like @0918nobita said)
- Thoroughly prevent executing arbitrary JavaScript code in XML attributes.
- Potentially easier to catch user errors and produce friendly messages
- Easier for third-party PSVG implementations that don't want to depend on JS to base their interpreters on our code instead of having to write their own from scratch.
- In PSVG variables of the form
"1 2 3 42 666 ..."has an Array/String "duality", and the current JS solution can be a bit slow in some situations. If we have our own interpreter, we might be able to optimize specifically for this language feature. - It's cooler. Transpiling to JS is not much of a challenge :)
Cons:
- Speed. The JavaScript V8 JIT is like, crazy good. I think we're unlikely to beat it. (or there's still a chance? since PSVG is a much "smaller" language)
- Potentially a lot more work and debugging. Instead of throwing all the heavy-lifting to JS, we need to take care of many things on our own.
- This is not a big deal, but the the library size will sure become larger/heavyweight.
- @LingDong- has never written an interpreter before. He'll be learning stuff as he goes. Or maybe that's a pros :)
Please feel free to add to this list!
I am working on a Rust implementation of PSVG as my practice of learning it (it was painful, but I starting liking some of the ways of doing things it offers). So far I have implemented the basic interpreter which supports numeric operators and some built-in functions. It's now able to compile koch.psvg and sierpinski.psvg which should cover your points on not relying on JS while being relatively smaller and faster (need to do benchmark later).
Not sure if you are interested in this approach (or will it higher the contribution barrier?), just offering an idea here. It's currently private and I will let you know when I feel more confident about it :P
@antfu
Cool! I'm down to give Rust a shot. @0918nobita I saw a thumbs up so perhaps you're thinking the same? ;)
Looks like we're at a real "crossroads" here (even the number of options match that of a crossroad):
- TypeScript interpreter and Rust interpreter coexist[1]
- TypeScript transpiler and Rust interpreter coexist[2]
- Abandon TypeScript, we all work on Rust interpreter[3]
What do you guys think?
[1] Great for users, double effort for us. Every time we want to add a feature we need to do it twice?
[2] Then maybe we can use acorn/astring to improve the TypeScript transpiler? Sounds like this might be the best option to me?
[3] Theoretically we can target WebAssembly so node/browser can still use PSVG. Seems like all modern devices are ready for wasm (but how many users of the library will feel ready?). Also, how big is the binary size compared to JS? Also it seems that wasm always need to be asynchronously loaded, which is pretty annoying most of the time.
Yeah, maybe don't take the Rust thing too seriously? I guess it would be much easier to use TypeScript the write the interpreter than Rust (at least to me) also not sure how much perf can Rust gain in return. I am not sure about its future but I might probably continue doing it as I am learning before moving on.
Also mention that if we only keep the syntax a very small subset of JavaScript or PSVG script (numeric operators + functions are actually quite good enough to me), we can probably handwrite them quite easily, and then there might be not needed for introducing heavy parsers like acorn/astring.
Aha ok! That makes sense. Sounds like we should proceed with the TypeScript interpreter plan then.
I'm still curious what the implementation will look like in Rust, I bet there's a ton of Option<Rc<RefCell<Box<...>>>> :P
Option<Rc<RefCell<Box<...>>>>
...Yeah exactly. But I found Result<Ok, Err> quite handy in terms of error handling.
Sent you the access invitation if you want to check out :P https://github.com/antfu-sponsors/psvg-rust
I'm also in favor of proceeding with the implementation of the interpreter in TypeScript. I have started to implement it in my repository.
By the way, there are many parts of the standard library, such as error handling, that I feel are cumbersome and redundant (compared to that of Rust). If there is a library that enhances the standard library, such as fp-ts (includes Either<A, B> type, which is used like Result<Ok, Err> type), the implementation will be a little easier. (My thinking is greatly influenced by functional programming languages such as F#, OCaml, and Haskell.)
Cool! I think fp-ts looks good. (Maybe later if we end up only using a couple features from fp-ts, we can implement those ourselves to make things more compact). Good luck with the implementation! I'm happy to help too.