Hacker News new | ask | show | jobs
by orangea 932 days ago
When I see "powered by WebAssembly", I take it as a sign that the language is going to be designed around WebAssembly's VM interface rather than the implicit standard of the C memory model and POSIX-like API which basically all popular programming languages are designed for. Even languages like Python have the concepts of stdin/stdout/stderr, a filesystem, threads, and a single globally accessible heap baked into their design. It would take a lot of work to amend Python's design to be able to easily use features that are somewhat unique to WebAssembly like the various things a .wasm file can import or export. As it stands, languages like Python can be run on WASM, but they use inelegant hacks in order to be able to replicate the execution environment features that their interpreters require such as malloc, and usually it is assumed that the target will be WASI. A language that is designed for WASM from the ground up would make it so that WASM can be used to its fullest potential as a lightweight execution environment that makes extremely minimal assumptions about what interfaces are going to be provided to the program.
2 comments

That is exactly the way that I see it too.

While Onyx does have core library support for doing standard POSIX things like stdin/stdout/stderr, file operations, and networking, Onyx can be used in an entirely different environment without any of these things. In fact, the standard libraries are (almost) entirely separate from the compiler (i.e. the compiler makes no assumptions about what the standard library is), so if the standard library does not suite your use case for one reason or another, you can write your own. It will be a bit of work, but there would be nothing in your way.

> Onyx can be used in an entirely different environment without any of these things. In fact, the standard libraries are (almost) entirely separate from the compiler (i.e. the compiler makes no assumptions about what the standard library is), so if the standard library does not suite your use case for one reason or another, you can write your own. It will be a bit of work, but there would be nothing in your way.

Isn't that true for most native languages as well ? C++ have multiple stdlibs.Rust,C and c++ can be used against bare metals.

The orthogonality of the std lib and the compiler and language semantic (maybe at the exception of the types) seems pretty common these days.

C/C++ compilers are tightly coupled to their runtimes, including their standard libraries. GCC is particularly bad about this.

On MacOS there is only one C standard library, and it is the interface to the operating system.

On Windows, your choice of standard library is tightly coupled to your tool chain.

On Linux, you can kind of mix and match, but it also impacts your loader.

Your comment seems a bit self contradictory to me. You mentioned a strong coupling between runtime and compilers, but then go on giving example of the same compilers runtime with different runtime.

I suspect that the terminology we are using might be the culprit. Thinking of it as compilers, distribution/package and target might be helpful. Both LLVM and GCC are quite flexible in how they can be packaged and distributed to target various platform. A compiler distribution typically would include a (default) runtime, default options, std libraries and supporting tools (linker,debugger etc... etc...) for each supported target in the case of X-compilation.

A distribution is definitely strongly coupled to a host os/configuration. But the compiler proper not really.

That is a good point. I don't do a lot of embedded bare metal work, so I kind of forgot that is possible. I guess it's something that is not unique to Onyx, but a good thing to know nonetheless.
As a related fun example that I use at work all the time, take a look at newlib sometime!

https://sourceware.org/newlib/

And related to that again is https://keithp.com/picolibc/

I don't think i fully agree. Yes it might be possible to design a programming language that have a better synergy with wasm than the one we currently have, but IMO this won't have a particularly big impact on dev prod or performance. wasm was design to be the target of current languages, so in a sense it does capture a lot of things that already exists or can be mapped easily to existing languages. Designing against wasm might create a case of overfiting. But only the future will tell.
Here is a specific example, again using Python, of how a programming language not designed for WASM might not be ideal: suppose you are writing a Python script which is to be compiled to WASM and needs to import a function. How do you specify that in the script? There could be some Python function like `wasm_import("my_function", "u32", ["u32"])`, which allows the programmer to specify a function to be imported... and the problem with that is that in Python everything normally happens at runtime, but the compiler which is turning your script into a .wasm file needs to know in advance what functions you are going to import. So you face a dilemma: either you mess with the fundamental assumption of Python that everything happens at runtime, or you add new syntax which allows specifying metadata, or you use magic comments, or do some other hacky thing.

This might seem strange to those who are used to today's dominant WASM paradigm, where the programmer usually controls both the VM and the .wasm program — such as website developers who create a .wasm file and then also write the Javascript to load it into the browser. But one of the most exciting things about WASM, to me, is the potential for domain-specific execution environments in which the code which loads and executes the WASM is written much earlier and by a different entity than whoever writes the WASM.

I think the relatively less-hacky approach would be to have the python code use the 'import' syntax to get those functions, and then how you intercept those and redirect them to DTRT is a decision with multiple possible approaches depending on your preferred set of trade-offs.

In Perl I'd probably do something like having a .pm file that does

    package MyBindings;
    
    use v5.38;
    use Exporter 'import';
    
    our @EXPORT_OK = qw(function names to export go here);
    
    use Wasm::Bindings;
    
    my_function u32 [u32]
    other_function ...
    ...
where the stuff after 'use Wasm::Bindings' is some sort of import-defining DSL (I invented one to pseudocode in, there's probably a 'real' one already you'd be better using in practice) and the 'use Wasm::Bindings;' statement switches in a different parser for the rest of the file when you load it normally. Then you could have external tools that simply know 'ignore everything up to that use line, those lines are Perl code, everything after it is yours though and should be handled however required.'

You can register custom loaders in https://bun.sh/ that I think would let me provide similar functionality there (maybe via a .wasmbind file extension or similar) and vague memory says python has ways and means to do such things but I've not looked in some years.

(I suspect you're still right that a language designed for WASM will end up being more ergonomic in that regard even so, and also that over time we'll likely find other ways it's more ergonomic that I haven't currently thought of, but I still don't think the situation for other languages is -quite- as bad as you suggest)

The problem you are describing isn't really related to WASM or any particular target system or programming language. And targeting wasm wouldn't really address it. It looks to me like a packaging issue.

If i follow you correctly, you are simply saying that in python it's possible to refer to some code in a way that the compiler can't anticipate and thus can't make sure the relevant code is present at runtime.

First this a problem in pretty much every language. Even in very static languages like c++, one can dlopen his way into this exact situation. JVM/.Net also have missing classes situation when someone screw up the packaging

This is solved by having a sensible code laoding API. Java classloader or .NET equivalent manage that.