Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
NIR: Nim Intermediate Representation (github.com/nim-lang)
188 points by michaelsbradley on Sept 30, 2023 | hide | past | favorite | 83 comments


I do really like Nim, being a sister to D lang with similar benefits. The language wars feels like it's getting hotter lately, and I'd live to see D/Nim make a comeback. If any language is going to see new traction, it's going to need to be a compelling alternative for Go/Rust/JS/Python/Java. I'm keeping an eye on Zig here too.


I really enjoy writing code in Nim. The move to the new memory management system turns it into a true systems-language (comparable to C++ + SharedPtr's or Rust + ARC's everywhere). I've been working on a multi-threaded pure Nim GUI which runs 60fps like a charm and compiles down to a ~3MB binary with no deps outside the system UI libs!

The other part is that Nim's strongly typed and compiles to native code but allows you to do dependent typing like things that lets you be flexible on types:

    type
      X = object
      Y = object
      Z = object
      NotXY = not (X | Y)

    proc doSomething(_: NotXY) = echo "hi!"
edit: I forgot the mention, but NIR is cool and part of an overall initiative to improve the Nim compiler which will hopefully reduce bugs and improve performance. Plus hopefully enable native WASM support which would be handy for GUI stuff!


> I've been working on a multi-threaded pure Nim GUI

Any plans to develop this into something beyond a hobby project? I think a Qt rival in a language safer and more pleasant than C++ would be welcomed by more than a few people.


That's good to hear! I've been considering it. Not sure if as a commercial product in it's own right - what to sell, maybe first class mobile app support?

At least I personally would like to use it to ship commercial cross-platform apps w/o needing electron or something huge like QT. Nim is much more pleasant than C++! You can actually embed the Nim compiler (~8MB) and run Nim as scripts too, so in theory you could remotely update your app as a nimscript.

P.S. drop me a line (emails on my github profile) if you're interested


> something huge like QT

In defence of Qt, there's a lot of functionality in there, and they've made it modular.

To my knowledge Qt's library binaries have roughly the same file sizes as, say, their Gtk equivalents. I wouldn't expect a new competitor to be that different.


Delphi is still around as well,

https://www.embarcadero.com/products/delphi


> I've been working on a multi-threaded pure Nim GUI which runs 60fps like a charm and compiles down to a ~3MB binary with no deps outside the system UI libs!

Like the sibling I'd be very much interested in this! Have you considered open-sourcing the GUI library part?


Are you considering accessibility in your project at all?

What do you use for controls, native OS objects or something custom drawn? If the latter, you're in for a word of pain with screen reader compatibility, internationalization, right-to-left languages, handling of Asian input methods etc.


Not currently but it's on my mind and I'm using utf8 for text with utf-32 for rendering. Good links for screen reader info are welcome!

> If the latter, you're in for a word of pain with screen reader compatibility, internationalization, right-to-left languages, handling of Asian input methods etc.

Custom drawn, and yep it's a pain! Actually emoji's seem the hardest (e.g. smiley face + skin tone).

The windowing library I'm building upon uses the OS'es input method editors (IME). For example MacOS'es functions for composing letters like `é` already works. Hopefully Asian input methods will work via the OS'es IME. Luckily I know a bit of (modern) Hebrew, so I'll can add basic RTL languages soon.


Why not use something like pango, libschrift, etc ? Text rendering is a hard problem, moreso one cross-platform...


Is it hard! Font rendering is handled by Pixie and the guys who wrote it made a great NimConf video showing that https://www.youtube.com/watch?v=8acDfUIwLnk

Pixie can render svg and ttf fonts with unicode in addition to drawing the shapes used for boxes and lines (e.g. like pango+cairo). It's SIMD optimized, very fast, and pure Nim so cross platform.

The challenge I mentioned with emojis is text selection and cursor movement when dealing with multi-grapheme characters. :)

edit: see https://youtu.be/8acDfUIwLnk?si=1EAUwUNZqje88J86&t=382 where they discuss how hard Text is


I didn't know Pixie, thanks !


What is `object` here? Effectively a ⊤?


It's effectively a struct with no members.

(Nim compiles to C, so in fact it compiles to exactly that).


Nope, it's just an empty object, aka an empty C struct. Generics would be like:

    type MyObject[T] = object
        val: int
        other: T


I don't get it - if empty object doesn't act as a top how does what you wrote demonstrate flexibility?

Edit: oh X, Y, Z are singletons I guess? Still don't see the flexibility or dependent types?


> I don't get it - if empty object doesn't act as a top how does what you wrote demonstrate flexibility?

To quote from Wikipedia:

    dependent types are used to encode logic's quantifiers like "for all" and "there exists". ... dependent types help reduce bugs by enabling the programmer to assign types that further restrain the set of possible implementations
In my example the objects could be any object types, combination of types, or concepts. It allows you to encode logic at the type system level. If you use generics with the example above you can do things roughly like:

    type
      State = enum Open, Closed
      SomeObject[T: State] = object
        val: int
      SomeObjectOpen = not SomeObject[state.Close]

    proc close(obj: SomeObjectOpen) = ...
You can do some simlar things in other languages, but it's hard and more limited and usually can't expressions.


> dependent types are used to encode logic's quantifiers like "for all" and "there exists"

Ya I don't think this is a good definition of dependent type - the prototypical example of a dependent type is a k-length vector. Obviously there's a mapping from what you wrote to this (in the same way there's almost always a mapping from a sequence of decision problems to an optimization problem) but it's still not a good formulation.

> In my example the objects could be any object types, combination of types, or concepts

Um yes this is literally what I was asking with respect to top ⊤.

> usually can't [contain] expressions

ya the negation is interesting - I wonder how it's implemented.


> Ya I don't think this is a good definition of dependent type - the prototypical example of a dependent type is a k-length vector.

Yah that's why I qualified my statement as dependent type like setup as I don't know a good definition of dependent types which I really grok and I've only briefly dabbled in it. It'd be awesome if you could point out a good resource showing a clear example / simple proof.

Well I started working on statically typed vector concepts [1]. The compiler can't do `proc concat[N,M: static int](v1: Vector[N], v2: Vector[M}): Vector[N+M]` and it fails. It might be able to be implemented via a macro like `proc concat(v1: Vector[N], v2: Vector[M}): typeFromSumOf(N,M)`, but I haven't tried yet.

Also just using static ints would require specific values at some point to work I think. Whereas you'd really want "induction" of some sort. Maybe a SAT solver would be required at that point? There's DrNim [2] which does tie Z3 but it's sorta dormant.

> Um yes this is literally what I was asking with respect to top ⊤.

Ah, I didn't know what you meant by top T.

> ya the negation is interesting - I wonder how it's implemented.

Nim's VM runs from Nim AST, so probably running it as a VM expression.

1: https://github.com/elcritch/platonic 2: https://nim-lang.org/docs/drnim.html


> Nim's VM runs from Nim AST

What does this mean? There's a runtime VM or compile time VM?


> What does this mean? There's a runtime VM or compile time VM?

Compile time VM. It's used to run macros / templates / concepts. You can also run most code at compile time in a `static` block except for stuff that needs C calls. You can also compile the VM into a program and use it as a runtime VM (see https://github.com/beef331/nimscripter) which I do in my GUI lib. NIR should enable the compile time VM to run faster too, and possibly use JIT'ed code.


ah so like clang's constexpr. got it. thanks


P.S. I went through Wikipedia's definition a bit more. Not sure it's a full dependent types with the type pairs and stuff. Nim does let you do (constant) value to type conversion with expressions: https://play.nim-lang.org/#ix=4HRz or more oddly https://play.nim-lang.org/#ix=4HRA . That'd seem to satisfy the `Π` definition and lack of fixed codomain. Though I've never taken a set theory course so YMMV.


Nim is incredibly pleasant for actually engineering software. In most scenarios it feels like compiled Python, and when you need it, you get really precise control. The preference for referentially-transparent procedures and stack-managed dynamic data is icing on the cake. You don't have to write just about any memory-semantic code in most business scenarios. Feels like a scripting language, runs 10-100x faster, and add the power of static types.


Just needs good IDE support. That's always the issue. Do not like VSCode or the slowness of the Nim plugin. I think every "goto definition" scans the whole code base instead of using an index, so it's slow. I'm faster working in Java, verbosity be damned.


You may fare better hooking VSCode to nimlangserver:

https://github.com/saem/vscode-nim#nim-lanugage-server-integ...


Thanks! Still don't want to use VSCode. I'd rather not use nim until there's a supported Clion plugin.


There is a number plugin: https://plugins.jetbrains.com/plugin/15128-nim. I haven’t tried it so don’t know how well it works.


Yes, as I said, a supported plugin. The author has not updated it since Jan so its not compatible anymore, and it's in beta at best.


> being a sister to D lang with similar benefits.

That is the fist time I hear this. Other than Python, I always felt Nim is more like Pascal and Ada.


I’d love to see nim become more mainstream. I don’t have much experience with it, but I looked into it a few times and always found it super interesting.


I don't see a value in Zig until they have a sound story for UAF.

We should be getting back what Xerox PARC was already doing in systems programming with Mesa/Cedar, Interlisp-D and Smalltalk in terms of systems programming.

This is where I see a value in languages like D and Nim, Swift, or even Go, regardless of the opinion on much systems it can be used for.

Back in my day writig compilers, linkers and OS services was considered systems programming.


What were they doing? From all I can tell they require to hold down the shift key a lot, other than that it's hard to find good information how they offered anything not offered by contemporary ecosystems. Or how they offered a better set of tradeoffs in some situations than we can have today.


Easy to find out when one cares, all the stuff is on Bitsavers and Computer History Museum sessions.

A small taste,

"Eric Bier demonstrates Cedar"

https://www.computerhistory.org/collections/catalog/10278104...

Full graphics workstation in 1980's, implementated in a systems programming language using reference counting, with a tracing GC as cycle collector, with an object model partially implemented years later as OLE/COM.


Watching the video, thanks. But back to my question, what of those is missing today?


Systems programming in a memory safe language with automatic memory management, across the whole OS, with a type safe ABI supporting dynamic loading, as starting point.

Swift is the closest to it, and it is still not widely adopted across Apple ecosystem, although as per CppCon 2023's Apple talk they even have plans to push it into the kernel (long term).


"Across the whole OS" is nothing special, it just means there hasn't been enough interest by diverse enough users of the OS. This is a research system, which is different from an OS supporting a huge diversity of ecosystems through the past 3 decades or so. There are different forces at play.

I'm sure there are quite a few systems worked on by lone developers today that make for a nice and smooth demo. The hard part is getting adoption and making it ergonomic and performant for a variety of uses, not just demo stuff.


A fundamental problem that I see today ist that most systems end up being either too rigid or too unstructured. We always want guardrails but then we need ways to remove them. What sounds good in theory or looks amazing on a demo often becomes impractical in a realistic development setting.

(There is a hint on something like that wrt. Mesa/Cedar on wikipedia. FWIW -- I've obviously never used it myself)


I've never heard of Nim being a sister to D. Maybe to Python, but not D.

Nim's home page acknowledges borrowing from Python, Ada, and Modula, as well as C/C++. I don't think D is part of the mix.


As I understand, D is a pragmatic vision of how C++ could look like if it was not C++ (that is, not designed by committee, without decades of backward compat needed, without the need to support some exotic hardware, etc.) It aims to completely drop the "C with classes" heritage, bring OOP and FP together while integrating important concepts into the language (delegates instead of function pointers, strings instead of char arrays, slices instead of T[], etc.)

While Nim indeed comes from Wirthian heritage instead of K&R heritage, its goals are pretty similar to D. You could say that Nim is for (Object)Pascal what D is for C(++). I think that's what the GP alluded to - not that Nim borrows directly from D or the other way around.


For the internet archives, this was the correct interpretation. Apologies for the original ambiguity. Also, I believe the creators of Nim where active in D language forum conversations, and I had the impression the Nim authors where very well inspired from D's design.


Nim is closer to D than Python IMO. The syntax is like Python, sure, but in terms of features it's very similar to D (statically typed, supports multiple GCs, fast compiler).


V is doing really well as well. Very exciting times.


"No pointers, no cry" was worth the price of admission. There are features and benefits here that seem magical. I may be misunderstanding, but does this mean that you could compile directly into containers like podman? That is, is the NIR parse able as a container image?


A container image is essentially a generalization of a binary, a folder holding the binary to run with its dependencies in a format that docker/podman can read, unpack/uncompress, mount the folder and thereby its contained dependencies and binary, sets up unix accounting, and run the binary with its support dependencies.

A compiler intermediate representation looks like a collection of data structures that can be used to generate runnable code either immediately as in an interpreter or saved for later use.

I think you’ve compared very different ideas.


I'm getting back into Nim after a little break. I really enjoy the language. I'm having a helluva time trying to get some basic tooling set up though. I wanted to install nimlsp[0] so I uninstalled the nim I had installed with homebrew and started over with choosenim. Still running into issues. `nimble install nimlsp` results in:

      nimble install nimlsp
   Downloading https://github.com/PMunch/nimlsp using git
   Verifying dependencies for nimlsp@0.4.4
      Info:  Dependency on jsonschema@>= 0.2.1 already satisfied
   Verifying dependencies for jsonschema@0.2.1
      Info:  Dependency on ast_pattern_matching@any version already satisfied
   Verifying dependencies for ast_pattern_matching@1.0.0
      Info:  Dependency on asynctools@>= 0.1.1 already satisfied
   Verifying dependencies for asynctools@0.1.1
   Installing nimlsp@0.4.4
      Building nimlsp/nimlsp_debug using c backend
   /Users/me/.nimble/pkgs2/ast_pattern_matching-1.0.0-b5b08c554b072eed227f98a437f7333584cf957e/ast_pattern_matching.nim(575, 28) Error: invalid indentation
      Prompt: Build failed for 'nimlsp@0.4.4', would you like to try installing 'nimlsp@#head' (latest unstable)? [y/N]
      Answer: n
         Tip: 12 messages have been suppressed, use --verbose to show them.
   nimble.nim(729)          install

      Error:  Aborting installation due to build failure.
Then I read on some old issue[1] that I should uninstall ast_pattern_matching. I assumed this meant `nimble uninstall ast_pattern_matching` so I did that, but there's nothing to delete..

  Error:  Failed uninstall - no packages to delete
Anyone have some advice or can provide guidance on getting nimlsp up and running? My ultimate goal is to have some basic stuff working in neovim so I can move on with writing some nim.

[0]: https://github.com/PMunch/nimlsp [1]: https://github.com/PMunch/nimlsp/issues/156


Please report this kind of stuff as a GitHub issue.. The odds of getting a problem solved (and not just by jumping to another solution) is way higher. If I where to guess uninstalling Nim through Homebrew still left some packages behind and now you're seeing some conflicts. Try to delete `~/.nimble/pkgs` and `~/.nimble/pkgs2` to make sure you're starting fresh and then try again.


I appreciate your response, I will give that a try. It's important to acknowledge that while users should ideally report issues to benefit the community, there are situations where immediate problem-solving takes precedence. So, if finding an alternative solution works, that's often the practical choice, even if they plan to report the issue simultaneously.


That did, indeed, resolve the issue. Would it help if I created an Issue for this along with the resolution? Thanks again for the help.


Yes that would be nice. That way it at least shows up in searches. Thanks for trying out my solution.


Maybe give nimlangserver a shot, it's an alternative to nimlsp:

https://github.com/nim-lang/langserver

   nimble install nimlangserver


Thank you! Will give that a shot.


Same experience. It was smooth 2 years ago when I tried it so I thought it be more polished now... Color me frustrated


As recommended by michaelsbradley below, I installed https://github.com/nim-lang/langserver. I'm using coc.nvim (https://github.com/neoclide/coc.nvim) so I followed the instructions here from nim langserver https://github.com/nim-lang/langserver#vimneovim and seems to be working well!


I got it working but I have to restart constantly because it chokes on bad syntax errors. It also doesn't show method docs unless it's being used correctly, so I end up having to browse the web docs.


No to be confused with Mesa's NIR https://docs.mesa3d.org/nir/index.html


Nice to see this evolution, as steping stone into Nim getting its own toolchain.


How is Nim for mobile development?


It isn't. And it would be hard-pressed to be, since there's no JVM backend. It could work on iOS via the C target, but you're probably better off with Swift. It could work in the browser via the C target and emscripten, but again, you probably don't want to go through so much trouble when you could just use C++. There's a JS backend, but at that point you're better off with TypeScript.


You can do Android with the C backend, but that's through some Java interop hackery, and there isn't anything in the ecosystem that would make Nim attractive for mobile development


> that's through some Java interop hackery

Honestly - you don't want to go there. Really. The JVM is known for a high cost for native calls, and JNI is pretty painful to write for in the first place. The Android NDK doesn't provide native equivalents to application-level APIs and concepts. You, technically, can make an app with a GUI in C for Android, but as I said: unless you're a masochist and enjoy the pain, you don't want to do that :)

As an aside: Tizen uses a GUI framework written in C - EFL - and it can be accessed from native and JavaScript code. I'm actually not sure how the JS APIs are mapped to the underlying framework's, if at all, but theoretically it shouldn't matter (other then what's expected between C and JS) whether you use native or JS for your apps. Unfortunately, Samsung is unable to replicate Google's level of development and (even more painful) documentation (maybe unless you're fluent in Korean). This made the transition to Android/Wear OS for new Samsung watches a welcome change, even though Tizen was arguably better in its design and some capabilities. I haven't checked recently, but I think Tizen is basically dead at this point - some smart guys at Samsung will have a blast playing with systems-level programming, but external developers will stop even considering writing for it. A pity. It was an interesting design.


It has Android support, but no wrappers for anything you'd actually want to do. Some successful Android builds of things like Raylib games with the Naylib wrapper exist, but nobody's really doing anything.


Is Nim getting contributions from any big players (corporations)?

Does Nim ecosystem feature a SSR web framework with SolidJS-like reactivity?


[flagged]


It’s an article about programming on a website frequently visited by programmers that was posted in the middle of a Saturday afternoon (America time) when a lot of people have read the front page already and might be looking at /new? Doesn’t seem so crazy to me.


is nobody here understanding? i meant what i said. it interests me. i think this is really cool, and a really interesting thing. i enjoyed this, and im happy its on the front page.


I like links like this because I like discussions on programming languages which are just on the periphery of mainstream. Nim, dlang, Odin, Zig, etc


No, the HN algorithm has seemed to stress newer posts recently, which is interesting.


HN seems to like Nim and more exotic (though not esoteric) languages.


My guess is as good as yours, but it could be a moderator action. Sometimes submissions are manually upgraded/downgraded by moderators here (that would be dang).

Related: https://hn.algolia.com/?dateRange=all&page=0&prefix=false&so...


That's not so uncommon. I looked at the vote data and it seemed legit.


I didn't think it was illegitimate. I think the HN algorithm has began to stress newer posts to go the top page. I'm not sure if that's a bad thing or not. This could also mean that you can check HN every thirty minutes and see something completely different. I personally think this is a good thing.


The HN algorithm hasn't changed recently. Who knows what else may have changed, but not that!


The PR was created a couple of hours ago, and I saw it mentioned in the Nim community's Discord server. I did not mention in Discord that I submitted the link to HN, but I'm guessing a fair number of the participants there also browse HN regularly, so that could be a factor.


Theyre going to change the whole backend essentially just for better not nil and static array bounds checking?


The mention of making CPS (continuous passing style) compiler integration possible is something very important. That would enable Go- or Kotlin-like coroutines to land in the language, which is sorely needed to end the async wars between stdlib's horrible asyncdispatch module, and Status.im's barely documented Chronos async/await implementation.


There has been a more-or-less working CPS implementation for Nim for a few years now:

https://github.com/nim-works/cps

https://github.com/nim-works/cps/tree/master/docs

Nobody seems to care though, as it has gained no traction at all and it has been mostly ignored by the core team.


The issue with the CPS implementation here is that the compile times are too slow, and there are several restrictions due to flaws and limitations of the compiler. That's the reason CPS in the compiler is a big deal. I've used the CPS lib you're showing before, and it's very nice, but the compile times make it absolutely useless for productive development.


that "just" strongly underestimates the value add of those two features!


The features already exist and the topic doesn't indicate how they would get any better.


Having a structured IR could make it pluggable to the MLIR ecosystem, for example.


Just because it has IR in the name doesn't mean there's any connection. If you want to emit MLIR using nim you can already do this using MLIR's C API, if you want to map nim ast to to existing MLIR IR you can already do this if you provide the necessary control flow analysis, if you want to map nim ir to MLIR you will still need a lowering or nim dialect.


Oh look… now we get a name collision for an intermediate representation [0]. That won’t make it difficult for searching at all… Like, this is cool and power to them, but I wish they had a different abbreviation.

[0] https://www.x.org/wiki/Events/XDC2014/XDC2014AbbotNIR/


I know of at least four MIRs. I used NIR as the name of the IR of one of my compilers. It's not a big deal. Just add qualifiers to your searches.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: