Ask HN: Memory-safe low level languages?

24 points by hyperbrainer 11 hours ago

I am looking for memory-safe languages that can be used for systems/graphics programming. I love Rust, but it often feels like too massive a language with too much stuff going on. Is there a language like C, which is simpler (obviously without all the UB and other problems)?

This is an especially hard ask, given how useful the FP-like features of Rust are, and I find it almost impossible to live without them. Basically, I am looking for a middle ground between C/Zig and Rust.

One such language I have found is Austral[0]. What other such languages are there?

[0] https://austral-lang.org/

codr7 11 hours ago

There have several attempts at cleaning up C without giving up too much of its simplicity; from what I can see, Zig is the only one even close to reaching critical mass.

A programming language is always going to make some kind of compromise; better at some things, worse at others.

Simplicity/power and safety pull the design in different directions.

  • hyperbrainer 11 hours ago

    I don't mind the language having substantially worse "something" as long as it can be a smaller alternative for Rust, for the lack of a better word. Of course, there always needs to be some compromise. I don't mind that. I just have two requirements, and am curious to see how people have tackled that problem.

    • codr7 10 hours ago

      Sure, and I'm just as curious.

      But at the same time, I'm pretty sure that smaller/simpler is going to mean less safe.

      • uecker 10 hours ago

        I think the opposite is true. The Rust philosophy is the idea that a complicated type system should ensure safety. This may work to some degree, but the overall complexity will introduce new issues. I say this as someone who was really excited about type systems in the past, but Rust is ... meh.

        • SkiFire13 9 hours ago

          > The Rust philosophy is the idea that a complicated type system should ensure safety.

          I don't think the "complicated" is part of the philosophy. Rather the idea is that a "strong" type system should ensure safety. The general consequence of this however is that the language becomes quite restricting and limiting. Hence the need for more more complex feature that allow for greater expressibility.

        • hyperbrainer 10 hours ago

          I think the problem is that some of the more advanced things related to generics or traits are half-baked or maybe somewhat function only in unstable, leading to horribly written code, or code which takes far more complexity to run than it should.

tiffanyh 10 hours ago

SPARK (Ada) is about as memory-safe as it gets.

https://github.com/AdaCore/spark2014

efficax 10 hours ago

https://dlang.org/articles/safed.html check out the safed subset of the D language

  • hyperbrainer 10 hours ago

    Unfortunately, it seems to use a GC for the safety, which makes it unsuitable for a variety of tasks in the systems programming domain. Seems to me like an alternative to Go more than Rust or C or Zig

andrewflnr 10 hours ago

F-star, which was used to build a verified TLS implementation. https://fstar-lang.org/ Though I guess that's actually on the far side of Rust relative to what you're looking for.

  • hyperbrainer 10 hours ago

    The full language is indeed even further ahead of Rust on the spectrum I am looking at, but this seems like a cool effort. I love proof-based languages and dependent types, so this is an absolute win.

    What intrigues me quite a bit relative to the main topic of the HN thread is Low[0]

    > Low is not only a language subset, but also a set of F* libraries that model a curated set of C features: the C memory model, stack- and heap-allocated arrays, machine integers, C string literals, and a few system-level functions from the C standard library. Writing in Low, the programmer enjoys the full power of F for proofs and specifications. At compile-time, proofs are erased, leaving only the low-level code to be compiled to C. In short: the code is low-level, but the verification is not.

    [0] https://fstarlang.github.io/lowstar/html/Introduction.html#t...

thih9 10 hours ago

(link from the description, clickable)

https://austral-lang.org/

> Austral is a new systems programming language. It uses linear types to provide memory safety and capability-secure code, and is designed to be simple enough to be understood by a single person, with a focus on readability, maintainbility, and modularity.

jedimastert 2 hours ago

Side question and possibly off topic, but is there a formal definition to the term "memory safe"? It seems to mean different things to different people and I'm unsure if I'm just out of the loop and there is an actual definition.

carterschonwald 10 hours ago

So one kinda cool direction is what they do for the sel4 prject. They have a sequence of high to low level impls and prove correctness wrt spec of the high level etc and prove that each lowering is an implementation of a refinement of the higher level implementation

pron 10 hours ago

If you love Rust -- use Rust. Trying to find a language that's just right for you risks it being just that: right for you and few others.

Just remember that even if writing memory-safe programs is your goal, using a memory-safe language is just a means to that goal, and even Rust isn't really memory-safe. Many Rust programs try to achieve memory safety while using a non-memory-safe language (be it C or unsafe Rust), and there's an entire spectrum of combining language features that offer sound guarantees with careful analysis and testing of unsafe code to achieve a safe program. On that spectrum, Zig is much closer to Rust than to C, even though it offers fewer guarantees than Rust (but more than C).

  • hyperbrainer 10 hours ago

    I love Rust, and will continue to use it. But sometimes it feels like "too much". If you have programmed in Rust, you know what I mean. I want to use and experience a language that is to Rust almost like what C is to C++.

    This is primarily an educational exercise to see how people find compromises that work for them, and languages in the same space as Rust using alternative strategies.

    • JoshTriplett 9 hours ago

      I've programmed in Rust extensively, and I'm on the Rust language team. I don't quite know what you mean, and I would genuinely like to. If Rust feels like "too much", I'd be interested in knowing what makes it feel that way and how we might be able to improve Rust to avoid that feeling.

      Is this something you experience when writing your code, or is this something you experience when reading other people's code?

      If it's the former, I'd really love to hear more about those experiences.

      If it's the latter, are there particular features that crop up that make code feel like too much?

      (To be clear, Rust isn't perfect for everyone, despite our best efforts. And if you want to work with another language, you should! I'm not looking to defend it; your experiences are valid. We'd love to make Rust better, so I didn't want to miss the opportunity to ask, because we so rarely hear from people in the intersection of "I love Rust" and "Rust is too much".)

      • hyperbrainer 9 hours ago

        It's hard to pinpoint the problem, because I love and adore Rust. So, thank you for all the work you have put in -- it's a great language.

        I feel like my biggest struggle is simply how hard (tedious?) it is to properly work with generics and some more complex applications of traits. Any time I am working with (especially writing, somehow reading is easier) these, I always take an ungodly amount of time to do anything productive.

        I am almost certainly sure this is a skill issue -- I am simply not "Rusting" like I am supposed to. Maybe I overuse generics, maybe I rely on traits too much, maybe I am trying to abstract stuff away too much. But this is one of the reasons I want to also explore other languages in the space, especially ones which make it impossible for me to make this so complex.

        Don't get me wrong -- all of this complexity is a joy to work with when I can use my brain. But sometimes, it's just too much effort to do stuff, and it feels like I could be getting away with less. Curiously, I never had a problem with the borrow checker, even though people often complaining about how much it forces them to "stop and think".

        Another thing is that C, for some weird reason, always feels "lower level" than Rust, and seeing it gives me some sort of weird satisfaction that Rust does not. Maybe it's just a greener grass syndrome, but wanted to mention it nonetheless.

        All this said, I want to just emphasise, that despite this shortcoming (if it even is one), if I were forced to choose a language to spend the rest of my life with, I would not be the least bit sad to only ever use Rust again. I absolutely love it.

        • JoshTriplett 9 hours ago

          > I feel like my biggest struggle is simply how hard (tedious?) it is to properly work with generics and some more complex applications of traits. Any time I am working with (especially writing, somehow reading is easier) these, I always take an ungodly amount of time to do anything productive.

          > Maybe I overuse generics, maybe I rely on traits too much, maybe I am trying to abstract stuff away too much.

          Is this related to the problem where, if you want to put a generic in a data structure (e.g. an implementation of `Write`), you find yourself propagating a generic bound up an entire hierarchy of data structures and functions using those structures?

          Asking because one thing that's common amongst Rust developers is a bit of an aversion to using `dyn Trait` types, and using a `Box<dyn Write>` (for instance) in the right place can wildly simplify your program.

          > But sometimes, it's just too much effort to do stuff, and it feels like I could be getting away with less.

          The next times you find this feeling arising, please feel free to reach out, if you'd like; I would genuinely love to hear about it. You can reach me by DM on the Rust Zulip, or by the email in my profile.

          > Another thing is that C, for some weird reason, always feels "lower level" than Rust, and seeing it gives me some sort of weird satisfaction that Rust does not. Maybe it's just a greener grass syndrome, but wanted to mention it nonetheless.

          I was originally a C developer, and I can sympathize. I don't tend to crave that "lower level" feeling often, but for me, there was something satisfying about C in the old DOS days, where you could make a pointer to video memory and scribble on it.

          • hyperbrainer 8 hours ago

            Okay this is really funny because I was messing about with generics relating to the Write trait just yesterday, leading to much frustration.

            > you find yourself propagating a generic bound up an entire hierarchy of data structures and functions using those structures

            And I did exactly that. I did eventually get around to using dyn Write, but that still gave me headaches because of how I cannot use impl Write as a result type in closures, which I need to do if I want to use tracing_subscriber::fmt::with_writer() and pass in these trait objects.

            Despite being this close to the solution, I somehow again wound up propagating generics back at least four functions.

            I ended up not writing any generic-based stuff and resigned to just manually writing each type's implementation out, but I am going to tinker with this again today. Hopefully, I can use your advice.

            Thank you so much for taking the time to write this. Means a lot!

            > there was something satisfying about C in the old DOS days, where you could make a pointer to video memory and scribble on it

            Exactly.

            • JoshTriplett 8 hours ago

              > I did eventually get around to using dyn Write, but that still gave me headaches because of how I cannot use impl Write as a result type in closures,

              I hope we manage to fix that! We're working on making `impl Trait` usable everywhere a type works. I'll check where "return type of a closure" is on the `impl Trait` radar.

              https://rust-lang.zulipchat.com/#narrow/channel/213817-t-lan...

              > which I need to do if I want to use tracing_subscriber::fmt::with_writer() and pass in these trait objects.

              Would https://docs.rs/tracing-subscriber/0.3.19/tracing_subscriber... help you?

              > Thank you so much for taking the time to write this. Means a lot!

              Thank you as well for taking the time to fill in more details!

              • structural 7 hours ago

                I was just looking for something very similar, this is neat!

                I think even moreso I can understand the sense of Rust feeling too large not because the language itself is, but because there are SO many of these neat tricks and little utility functions that are necessary to express what you want, and it's quite impossible to remember each and every one and how to go back and find them later.

          • zoechi 4 hours ago

            The first thing the compiler tells after using dyn is, that the value is not object safe. Then you just got yourself another problem ;) With a lot of experience it becomes more obvious from the start what approach can work out, but with little knowledge, the compiler only sends you in circles and the great error messages tell you what you need to change to make the code compile, but usually pushes you in the direction you tried to avoid. I'm reasonably productive now, but it was bloody hard time to get there.

            I never worked with low level languages except some university lession, but I think I have good general understanding how a CPU and memory works (just for some context)

    • uecker 10 hours ago

      I do not see any serious contender to C. And considering that most people developing alternative languages that aim to replace C do not seem to have a good understanding what makes a good system programming language, I also do not see this changing soon. Tooling for memory safety will improve and I expect we will also have something complete in ISO C at some point. But already today, one does not have to write modern C as your parents did, e.g. there is no need to do unsafe pointer arithmetic and many other unsafe features can simply be avoided. Signed integer overflow can be checked at run-time. Only temporal memory safety is missing a good solution that ensures safety, but I do not find this is to be a major problem in my projects (with some discipline about pointer ownership)

      • pron an hour ago

        Isn't C++ already a serious contender to C? It clearly has not replaced C everywhere, but it's taken over much of C's market. And if C++ could do it, I don't see why another language couldn't do the same (that's not to say that the next language to do that already exists today).

        One thing that's important to notice, I think, is that low-level languages' combined market share has fallen sharply since the 1970s, and it doesn't seem that the trend is about to sharply reverse direction. To me that suggests that if a low-level language wants to be more popular than C++, it should focus on low-level programming and shouldn't try to also be a good applications programming language (as C++ has tried to do that, but the overall market share of C and C++ is lower now than it was in, say, 1990), but I could be wrong about that.

    • pron 7 hours ago

      If it's for educational purposes and you want to explore various tradeoffs, then you shouldn't necessarily restrict yourself to languages that make similar tradeoffs regarding safety guarantees in the language as Rust. Again, the goal of writing a memory-safe program is understandable, but there's more than one way to achieve that goal when it comes to language guarantees. That doesn't only apply to languages that offer fewer guarantees than Rust, but also to languages that are possibly less low-level (e.g. OCaml, Nim).

      But even for educational purposes, using a language with a poor selection of libraries is likely to lead to a bad experience if what you want to produce is working, non-trivial software. Every project includes some "boring" aspects -- such as parsing configuration and data files -- that you won't necessarily enjoy writing from scratch. The overall programming experience is shaped by much more than the design of the language alone.

    • api 10 hours ago

      Rust can feel like "too much" at times. It's a very feature rich language. But that doesn't mean you have to use every feature. With all feature-rich languages I think that's good advice, since code that does use every single feature often ends up being an unreadable mess. Each feature is there for a certain use case, not for every use case.

  • Ygg2 9 hours ago

    > even Rust isn't really memory-safe.

    [Heavy citation needed]

    Rust isn't memory safe if and only if:

    - You messed up writing safe to unsafe interface (and forgot to sanitize your binary afterwards).

    - You tripped one of the few unsound bugs in compiler, which either require washing pointers via allocators or triggering some tangle of traits that runs into compiler bugs

    - Somewhere in dependecy tree someone did the one of other things.

    • pron 8 hours ago

      > You messed up writing safe to unsafe interface (and forgot to sanitize your binary afterwards).

      That is the definition of a language not being memory-safe. Memory-safety in the language means a guarantee that the resulting program is memory safe, and that you could not mess it up even if you tried.

      Taking that to the extreme, it's like saying that a C program isn't memory safe only if you mess up and have UB in your program, something that C program must not have. But C is not a memory safe language precisely because the language doesn't guarantee that. My point is that there's a spectrum here, the goal isn't memory-safety in the language but in the resulting program, and that is usually achieved by some combination of sound guarantees in the language and some care in the code. Of course, languages differ in that balance.

      • Ygg2 7 hours ago

        > That is the definition of a language not being memory-safe. Memory-safety in the language means a guarantee that the resulting program is memory safe, and that you could not mess it up even if you tried.

        By your definition no language ever would be deemed safe. Even Java/C# has to interface with C. Or you have to write bindings for C libs/ kernel calls.

        > But C is not a memory safe language precisely because the language doesn't guarantee that.

        C isn't memory safe because it has 212 different ways to cause memory unsafety. And only offers externals runtime tools to deal with it.

        I mean Rust will never be perfect due to Rice Theorem. It doesn't have to be either. It's at close to ideal as you can get, without mandating that programmers are perfect (no language errors) or that everything be written in safe Rust (no C bindings).

        This is a well known Nirvana fallacy. E.g. If a cure doesn't cure fatal disease in 100% of cases why not let disease take its course?

        • pron 2 hours ago

          > By your definition no language ever would be deemed safe. Even Java/C# has to interface with C. Or you have to write bindings for C libs/ kernel calls.

          That's correct. My point is that even if we talk about memory safety only, languages are on a spectrum (e.g. Java programs don't need to use unsafe code as much as Rust programs), and there's always some situations where we don't rely on sound guarantees. In practice, we call languages that easily demarcate their unsafe code "safe languages".

          > I mean Rust will never be perfect due to Rice Theorem.

          That's nothing to do with Rice's theorem. A language that's completely, 100% memory-safe is not hard to do, but it will need to sacrifice some things that we don't want to sacrifice even for a 100% guarantee of memory safety.

          > If a cure doesn't cure fatal disease in 100% of cases why not let disease take its course?

          That's not a good analogy for software correctness. A better one would be that every cure has some side-effects. There are languages that, at least in principle, "cure" far, far more than Rust or even Java do, such as ATS or Idris. Why don't we always use them? Because it's hard! What we've gradually learned since the 70s (when a prevailing thought was that we'll have to use proofs to scale software) is that the cost of soundness can be high, and unsound methods (such as tests) are surprisingly effective in practice, and so "more sound guarantees" is not always the best answer. We now believe that for the best correctness per unit of effort we don't want no guarantees at all as in C, and we also don't want to guarantee everything as in ATS, but we're looking for some sweet spots in between. We haven't yet figured out what "the best" sweet spot is or, indeed, if there even is only one.

SloopJon 9 hours ago

Personally, I don't know what you mean about Rust being too massive. One thing I am wary of is using a truly massive language like C++ on a multi-programmer project without consensus on which features to use and how to use them. Maybe you have in mind something like that?

If you want the simplicity of C with more safety, maybe tooling like Frama-C, a MISRA C conformance checker, or just aggressive use of static and dynamic analysis tools like ASAN and UBSAN. You can also disable certain optimizations (e.g., strict aliasing) to steer away from some of the major pitfalls of UB.

shakna 10 hours ago

V [0] aims for something along those lines, but I've had a few issues with the safety aspects of the language. Breaking through the checker isn't that difficult.

I absolutely adore Ada [1], but the Pascal-syntax isn't for everyone.

I haven't used it yet, but have been hearing rumblings about Odin [2] a fair bit in these kinds of discussions. I tend to avoid too many symbol-heavy langs, but it's probably still less than Rust (I use a screenreader half the time).

[0] https://vlang.io/

[1] https://ada-lang.io/

[2] https://odin-lang.org/

  • arp242 3 hours ago

    I just so happened to use Odin a bit this week, and I hit several different problems: two compiler bugs and a stdlib bug. I'm not having a go at the Odin people, just pointing out it's very much an "in development" language with some fairly sharp edges.

  • n42 10 hours ago

    I see so much controversy every time V comes up; can someone explain why, without devolving into name calling and personal attacks? What specific design choices or implementation details are contentious, and what legitimate concerns exist beyond interpersonal conflicts?

    • andrewflnr 10 hours ago

      Having only watched the discussion: The main problem seems to be grossly inflated claims about its capabilities. As in, the docs say it already does X Y and Z, and when you try them they plainly don't work. And then the creator starts with the personal attacks when you point this out.

    • detaro 10 hours ago

      When it launched it proudly claimed to do a lot of things, some of which most people would consider still open research questions. Unsurprisingly, it didn't actually do these things or have a concrete plan of achieving them, and they didn't handle people pointing that out very well. Some other language developers were unhappy about the support V gathered based on these claims vs languages that were further along but honest about what they actually had.

      (I have no idea what the current state is)

      • arp242 3 hours ago

        > they didn't handle people pointing that out very well

        I think that's a fair thing to say. But in all honesty, the people pointing that out were not exactly polite about it, to put it mildly.

        I never really looked at V myself and have no opinion, but I do know unpleasant behaviour when I see it and quite a few of the people "pointing out" some of the shortcomings of V were engaging in it.

    • shakna 10 hours ago

      V... Overpromised, and underdelivered, on what it could do. Promised complete Type Safety, before the type checker was even implemented, for example.

      As for concerns... The main developer is a concern. Hard to trust them to support the language well, with some of the... Well, tantrums. This isn't aimed at a personal attack. But it is very hard to describe their responses in another manner.

      This [0] thread on HN covers some of all of the above.

      But, probably also important to point out that V and its drama have had dang threaten to ban the topic altogether [1]. There's a lot of drama.

      [0] https://news.ycombinator.com/item?id=39492680

      [1] https://news.ycombinator.com/item?id=37335249

      • n42 10 hours ago

        Oh. I fear that I have unwittingly summoned HN demons.

        • -__---____-ZXyw 8 hours ago

          Yes, you seem to have done so.

          If, of course, by "demons" you mean people who write nicely formatted, polite, well-written responses attempting to answer your question fully, including links to further reading.

          • n42 8 hours ago

            I was referring specifically to dang's post in the linked thread. I realized I had accidentally stumbled onto a topic with such a controversial history on this site that it might have been banned outright. As in, HN's personal demons; unresolved controversy.

            The comment wasn't about anyone in particular.

  • hyperbrainer 10 hours ago

    V looks exactly like one of the languages I was talking about. Some controversy about the project, it seems like, but very cool nonetheless. Even if it doesn't actually work like described, the description seems quite interesting.

    > But I've had a few issues with the safety aspects of the language. Breaking through the checker isn't that difficult.

    What do you mean? Can you "break through the checker" outside of unsafe blocks?

hardwaregeek 10 hours ago

If performance is not ultra critical, I'd use Go. It's simple and a small-ish language. Otherwise there's not many options. Not to belittle your question, because it's a good one, but it's a little like asking if there's a simpler aircraft. There can be, but there's a certain amount of required machinery to keep it in the air. Rust's memory safety rules are as simple as we can get it for now. Maybe in a few years it'll be different!

noam_k 9 hours ago

You may want to look at Lua[0]. It's often used as an embedded scripting language in larger projects (and games), has good performance, is memory safe, and is extensible in the same manner as Python (write your performance bottleneck in C/C++).

I don't remember specifics, but there are some odd footguns to look out for.

[0] https://www.lua.org/

pjmlp 9 hours ago

GCC nowadays offers Modula-2, Ada and D in the box.

Then you have FreePascal, as FOSS ObjectPascal dialect.

On Apple's turf, Swift naturally, given its bindings for all Metal anything frameworks.

gus_massa 9 hours ago

Have you tried "modern" Fortran? I've seen horrible "old" Fortran programs, but once you add modules it get's much better.

  • tiu 6 hours ago

    I was playing around with Fortran (modern-ish) recently was pretty impressed with the entire ecosystem. `fpm` is really really nice to work, pretty decent LSP server (fortls) as well as good enough documentation.

    I am not sure however I like the verbosity of it where if you are using 'raw' editors without snippet support, it becomes a chore very soon.

    All in all it is nice to use and play around with.

SkiFire13 9 hours ago

Have you considered trying one of the older Rust versions (e.g. 1.0.0 or a bit after that) without all the new shiny features?

MelodyUwU 7 hours ago

i was actually looking for an answer to a similiar question, so this thread is very much useful! as of now, i looked somewhat at odin

tiu 9 hours ago

See https://wiki.alopex.li/SurveyOfSystemLanguages2024

and the related discussion https://lobste.rs/s/c3dbkh

Serious total MSLs that have a defined memory model to allow "low level" operations seem to be scarce if not any. Hence I do not think there is any single one that comes between C/Zig and Rust.

I would have said https://www.hylo-lang.org/ but, personal opinion, seems like there is too much going on as well. See also https://vale.dev/

P.S Mind mentioning what FP-like features are in Rust? (Genuinely have not looked into Rust that much but I am interested).

foota 9 hours ago

It's not really recommended for us, but maybe Carbon?

sargstuff 3 hours ago

Very old school:

ASP[0] was old way to do character animations for unix finger command .plan.

Recall HN post using python to do the same (handled animation independent of serial terminal speed).

Related HN post "John Carmack's .plan file" [3]

hascii mation [1]; Use standard graphics techniques and run through [2] or .plan with unscii[4]

"sheltered code" via mindcraft : https://youtu.be/7sNge0Ywz-M

------

ascii animation tutorial : https://www.youtube.com/watch?v=o5v-NS9o4yc

[0] :Ah, ASP link has been merged with /dev/null. :(

     ASP and related things for animated .plan : https://superuser.com/questions/253308/scrolling-plan-file
[1] : https://github.com/octobanana/asciimation

[2] : https://www.geeksforgeeks.org/converting-image-ascii-image-p...

[3] : "John Carmack's .plan file" : https://news.ycombinator.com/item?id=3367230\

[4] : unscii : http://viznut.fi/unscii/

p_ing 10 hours ago

C# has been used as the primary language in various hobby/research kernels.

  • DaiPlusPlus 10 hours ago

    > C# has been used as the primary language in various hobby/research kernels.

    That's quite the oversimplification...

    C# is not a systems-programming language: it's an application-programming language that is heavily dependent on the CLR runtime environment. While those research-kernels certainly do bring a-kind-of-CLR into the kernel it's far from being like the CLR in .NET; but they don't use C# - at least, not the same C# you use in Visual Studio: those research kernels: Singularity, Midori and Verve - used not only the Sing# and Spec# extensions to C#, they had their own compiler (Bartok) which itself enabled other language-extensions.

    That said, those extensions are fascinating reads:

    Sing# concerns message-passing ( https://www.microsoft.com/en-us/research/wp-content/uploads/... )

    Spec# added Ada-style (i.e. compiler-enforced) invariants and pre/post-conditions (this was the basis for the Code Contracts feature which was annoyingly/tragically killed-off during the .NET Core reboot in 2016); see https://www.microsoft.com/en-us/research/project/spec/

    Bartok: https://www.microsoft.com/en-us/research/wp-content/uploads/...

    • neonsunset 8 hours ago

      > C# is not a systems-programming language

      Incorrect, the main restriction are the targets supported by CoreCLR/NativeAOT/Mono(to an extent).

      Or, at least, if you pick all memory-safe languages with GC, C# offers the most when it comes to low-level access.

frizlab 10 hours ago

Swift can now be used on embedded platforms