Skip to content

Instantly share code, notes, and snippets.

@planetis-m
Created October 28, 2025 14:39
Show Gist options
  • Select an option

  • Save planetis-m/3c7eed75a6acf6dc2e4135240420ae0f to your computer and use it in GitHub Desktop.

Select an option

Save planetis-m/3c7eed75a6acf6dc2e4135240420ae0f to your computer and use it in GitHub Desktop.
Prompts for Nimony release announcement

Prompt: Demonstration Example Generator

You are an AI assistant tasked with writing a demonstration code example showcasing the currently working features of the Nimony toolchain and standard library ports. This example is aimed at experienced programmers who prefer clarity and grounded demonstrations over hype.

Important: You must only use features and modules that are confirmed working in the implementation state described in the extracted feature list. Do not assume or invent features.

I will provide:

  1. A feature list of constructs currently working
  2. Any known limitations
  3. A list of modules that are functional
  4. Example fragments taken from the progress reports

Your job is to produce a single coherent code example that:

Goals

  • Demonstrates several practical features working together
  • Uses std/rawthreads to spawn and join at least one thread

proc getThreadId*(): int

proc join*(t: var RawThread)

proc create*(t {.noinit.}: out RawThread; fn: proc (arg: pointer) {.nimcall.}; arg: pointer; stackSize = 0; pinnedToCpu = -1) {.raises.}

  • Uses std/monotimes for timing comparisons:

    let a = getMonoTime()
    let b = getMonoTime()
    assert a <= b
  • Uses std/tables to collect and aggregate values

  • Uses std/math for a small numerical computation

  • Uses std/strutils or std/unicode for simple text handling

  • Uses std/parseopt to process at least one CLI argument

  • Demonstrates at least one nimonyplugins feature if available (e.g., a custom lowering, cps block, special compiler hook, or syntax adaptation)

  • Uses paths where appropriate (e.g., resolving a file path)

  • Compiles based on the currently available syntax and semantics

Tone and Style Requirements

  • The example must be realistic, not contrived or "toy‐like"
  • Avoid hype language
  • Code should be clear, modest, and instructive
  • No comments explaining “why Nimony is great”
  • Comments should explain how the code works, not why the project matters

Structure of the Output

  1. Short introduction paragraph (1–4 sentences max), stating the purpose of the example.

  2. Final demonstration code snippet, complete, runnable if possible.

  3. Follow-up note describing:

    • Which features were used
    • Which limitations were accounted for

Do not output discussion, analysis, or marketing commentary.

If something is unclear or incomplete

Ask clarifying questions instead of guessing.

This thread is supposed to become a progress report for Nimony. Tonight the following program worked for the first time:
import std / syncio
echo "hi", "abc"
This might not look impressive but it is (IMO): Nimony is a new Nim compiler which does not use much of the old codebase. A good dozen subsystems have been reimplemented from scratch:
Precompiled modules.
Semantic checking. (Symbol lookup rules, type checking.)
Generic instantiations. Generics are type checked and Nimony already has an implementation of Nim's concept keyword!
Template expansions.
For loop inlining.
ARC based memory management.
Code generation is done via NIFC.
Of course, this is still not ready for anybody. But once ARC has received more bugfixes we have a minimal Nim that offers seqs+objects and modularity.
For more information about its architecture, read: https://github.com/nim-lang/nimony/blob/master/doc/design.md
For more information about its planned design, read: https://github.com/nim-lang/nimony/discussions/529
Blog post: https://nim-lang.org/araq/nimony.html
The next milestone is to get our seq implementation to work. I hope to get there within the next 2 weeks, but that might be overly optimistic as the interaction between generics and ARC hooks is hard.
Once seq works, our table implementation needs to compile. Once that is done, parseopt and then you can write super simple CLI programs with it while we implement ref...
It's just
template foobar(x, y: int): int {.plugin: "foobar.nim".}
And then in foobar.nim you have a program that receives two command line parameters, two filenames <input.nif> and <output.nif> and you use the NIF APIs (or APIs on top of that that emulate macros.nim) for the transformation logic.
The compiler caches the output and only runs the plugin logic if the input changed. The plugin is compiled to an .exe/binary file and thus runs at native speed.
Slightly related how does this coincide with previous plans of removing untyped?
The compiler typechecks the foobar template like any other template. This means that the plugin's output is sem'checked.
Well this toy example works in Nimony:
type
Fibable = concept
proc `<=`(a, b: Self): bool
proc `+`(x, y: Self): Self
proc `-`(x, y: Self): Self
proc fib[T: Fibable](a: T): T =
if a <= 2:
result = 1
else:
result = fib(a-1) + fib(a-2)
discard fib(8)
And it doesn't work without the concept as generics are type-checked. That's good enough for me. The rest is uninteresting details. ;-)
Another progress report. This code does semcheck:
type
openArray*[T] {.view.} = object
a: ptr UncheckedArray[T]
len: int
proc `[]`*[T](x: openArray[T]; idx: int): var T {.inline, requires: idx >= 0 and idx < x.len.} = x.a[idx]
proc `[]=`*[T](x: openArray[T]; i: int; elem: sink T) {.inline, requires: i >= 0 and i < x.len.} =
(x[i]) = elem
converter toOpenArray*[I, T](x {.byref.}: array[I, T]): openArray[T] {.inline.} =
if len(x) == 0:
openArray[T](a: nil, len: 0)
else:
openArray[T](a: cast[ptr UncheckedArray[T]](addr(x)), len: len(x))
converter toOpenArray*(s: string): openArray[char] {.inline.} =
openArray[char](a: rawData(s), len: s.len)
func len*[T](a: openArray[T]): int {.inline.} = a.len
type
Equatable* = concept
proc `==`(a, b: Self): bool
func find*[T: Equatable](a: openArray[T]; elem: T): int =
var i = 0
while i < len(a):
if a[i] == elem: return i
inc i
return -1
func contains*[T: Equatable](a: openArray[T]; elem: T): bool {.inline.} =
find(a, elem) >= 0
iterator items*[T](a: openArray[T]): var T =
var i = 0
while i < len(a):
yield a[i]
inc i
proc `==`*[T: Equatable](a, b: openArray[T]): bool =
if a.len == b.len:
for i in 0..<a.len:
if a[i] != b[i]: return false
return true
return false
Thanks to the new .view pragma openArray does not have to be a magic type anymore, simplifying the compiler.
.requires annotations allow us to do bound check elimination in a principled manner.
The required type annotations for generic code are not overwhelming.
Thanks to polymorphic accessors a single [] proc is now enough.
Next milestone reached: This program compiles&runs and produces correct output:
import std/[parseopt, syncio]
proc test =
for kind, key, val in getopt():
echo "##", key, "##", val
test()
That's what it means, yes. Something like oomTrap can be used to turn allocation failures into traps with little effort:
template oomTrap[T](x: ref T): ref T =
let tmp = x
if tmp == nil: quit "out of memory"
tmp
proc createObjects() =
let a = oomTrap MyObjectRef()
let b = oomTrap MyObjectRef()
# compiler now understands that a and b are not nil:
use(a, b)
case of string now works:
import std / [syncio]
proc dispatch(x: string) =
case x
of "foo":
echo "foo"
of "bar":
echo "bar"
else:
echo "unknown"
dispatch("foo")
dispatch("bar")
dispatch("other")
It should also produce better code than Nim as it produces dispatch trees and doesn't use hashing anymore. Hashing requires 2 complete scans over the input string, our trees only a single scan in the best case.
Seqs are starting to work:
import std / syncio
proc x(count: int; data: string) =
var s = newSeq[string](count)
for i in 0..<count:
s[i] = data
echo s.len, " ", s[40]
x(1000, "hi")
But as predicted the hook generation is not there yet, no destructor for s is synthesized.
Update: This program works now.
Right now Nimony focuses on a "minimal viable product" (MVP), a Nim variant that combines IC + ARC + typechecked generics. As such many many features will not be available. The focus is on this combination as I consider it the hardest nut to crack. Once that works sufficiently well, we will add features until Nimony can compile most Nim 2.0 code out there and then call it Nim 3.0.
However, I consider the MVP to be an interesting beautiful language of its own, so I anticipate it to stick around under a flag --mode:aufbruch. If you ask the question "what would a 10 times smaller Nim compressed to its essentials look like?", that is Nimony's "aufbruch" mode.
Next milestone reached. This program compiles and produces the correct output:
import std / syncio
proc sort(a: var openArray[int]) =
var n = a.len
while true:
var swapped = false
var i = 0
while i < n-1:
if a[i] > a[i+1]:
swap a[i], a[i+1]
swapped = true
inc i
dec n
if not swapped: break
var x = [3, 2, 1, 6, 7, 4, 5]
sort x
var i = 0
while i < x.len:
echo x[i]
inc i
import std/[hashes, syncio, tables]
block:
var t = initTable[int, int]()
assert not t.contains(123)
assert not t.hasKey(123)
assert t.getOrDefault(123) == 0
assert t.len == 0
t[123] = 321
assert t.len == 1
assert t.contains(123)
assert t.hasKey(123)
assert t.getOrDefault(123) == 321
assert t[123] == 321
assert t.mgetOrPut(123, -1) == 321
inc t[123]
assert t[123] == 322
It's a new feature of Nimony, it does type-check generics when they are declared, not only when they are instantiated. And this check requires the usage of concepts, without the concept annotation, the code wouldn't compile.
(We also have untyped generics for backwards compat, but as I keep saying, the current focus is on a coherent MVP.)
I don't know what you mean but openArray is not a magic type anymore so Table[openArray[char], T] should cause no trouble. (Well no trouble beyond the massive borrow checking problems...)
Progress report. This program works:
import std / [syncio]
type
BinaryTree = ref object
le, ri: BinaryTree
data: string
proc newNode*(data: sink string): BinaryTree = BinaryTree(data: data)
proc append*(root: var BinaryTree; n: BinaryTree) =
# insert a node into the tree
if root == nil:
root = n
else:
var it = root
while it != nil:
var c = cmp(n.data, it.data)
if c < 0:
if it.le == nil:
it.le = n
return
it = it.le
else:
if it.ri == nil:
it.ri = n
return
it = it.ri
proc append*(root: var BinaryTree, data: sink string) =
append(root, newNode(data))
proc toString(n: BinaryTree; result: var string) =
if n == nil: return
result.add n.data
toString n.le, result
toString n.ri, result
proc `$`*(n: BinaryTree): string =
result = ""
toString n, result
proc main =
var x = newNode("abc")
x.append "def"
echo $x
main()
It does not leak memory either, recursive ref destructors seem to work well.
Pleasant suprise: This test program works without any compiler bugfix:
import std / syncio
type
X = object
s: seq[string]
proc use(x: int) = discard
template copyInto(x: var X; body: untyped) =
let oldLen = x.s.len
body
use oldLen
type SymId = distinct int
template `[]`*(syms: seq[string]; s: SymId): string = syms[s.int]
proc main =
var x = X(s: @["abc", "def"])
copyInto x:
copyInto x:
echo "yes ", x.s[SymId(1)]
main()
Another milestone reached. Our std/intset implementation works:
import std / [syncio, intsets]
proc main =
echo "start"
var s = initIntSet()
for i in 5000..<6000:
s.incl i
assert s.contains i
echo "500..<600"
for i in 500..<600:
s.incl i
assert s.contains i
echo "50000..<60000"
for i in 50000..<60000:
s.incl i
assert s.contains i
echo "0..<500"
for i in 0..<500:
assert not s.contains i
echo "excl 50100"
s.excl 50100
assert not s.contains 50100
assert not containsOrIncl(s, 7)
assert containsOrIncl(s, 7)
echo "success"
main()
This intset implementation uses our hash table implementation which in turn uses our seq implementation that works entirely without compiler magic as the ARC based memory management loses no efficiency when compared to a compiler builtin type.
Progress: Overflow checking that does not rely on exception handling has been designed and implemented:
import std / [syncio]
proc main(a, b: int) =
{.keepOverflowFlag.}:
let x = a + b
echo overflowFlag()
main(1, high(int))
This is mapped directly to NIFC's new overflow checking support which is then mapped to GCC/clang's builtins.
No complaints about the syntax please, we will make it beautiful later and map it to try except OverflowDefect. Eventually... :-)
Well I need to write many blog posts... Nimony's strings are easily explained:
I want some support for O(1) slicing, that pretty much rules out terminating zeros. That's bad for C interop. But 10 years ago I did some measurements with a bootstrapping compiler -- the zeros cause every string to be longer by one byte which means the allocation sizes might be longer by 8 bytes due to alignment. The memory overhead was surprising, 5% or something like that. So terminating zeros are just a bad idea when you have the length information ready elsewhere.
We already have the typical wasMoved check in the destructor and the corresponding state. We can exploit that state for the new borrowCStringUnsafe operation.
I don't have any benchmarks and the current implementation focuses on simplicity. But I'm reasonably certain that the API is strict enough to allow for lots of implementation changes without breaking client code. The new string implementation is much easier to change as there is almost no compiler magic.
I don't like SSO if it implies some avoidable code bloat as all of Nimony's runtime is developed with an eye to embedded devices. But recently many people found ways to have "slim" SSO implementations so it's likely such a design will win.
Progress: Builtin arrays now have index checking.
This program fails at runtime with a nice error message:
import std / [syncio]
type
TA = array[0..3, int]
proc main(a: TA) =
for i in 0..4:
echo a[i]
main([1, 2, 3, 4])
Now the same need to be done for seq. Which is actually easier to implement as we only have to map the .requires annotation to runtime checks...
Progress report. fields and fieldPairs iterators have been implemented. For example, this program works:
import std / [syncio]
type Obj = object
a, b: int
c: string
var o = Obj(a: 1, b: 2, c: "xyz")
for f in fields(o):
echo f
This is a key component for my plans to offer a macro emulation/VM layer...
Progress: Source code filters are now supported. (This was easy as we reuse all of the parsing code from the existing compiler already.)
Another milestone reached. Methods and inheritance begin to work:
import std / [syncio]
type
RootObj {.inheritable.} = object
type Obj = object of RootObj
a, b: int
c: string
method m(o: RootObj) =
echo "RootObj"
method m(o: Obj) =
echo "Obj"
proc test(o: RootObj) =
m o
test(Obj(a: 1, b: 2, c: "3"))
The implementation is based on good old v-tables. The of operator is again implemented by "displays". These operations are all O(1).
Destructors are "virtual" if they have to be. Virtual calls are optimized to static calls if applicable.
Progress: Today the first plugin worked!
As a simple example I wrote
template generateEcho(s: string) = echo s
generateEcho("Hello, world!")
as a compiler plugin:
import std / syncio
template generateEcho(s: string) {.plugin: "deps/mplugin1".}
generateEcho("Hello, world!")
As there is currently no API for plugins, we have to import parts of the Nimony compiler and the code is a bit ugly:
# file: deps/mplugin1.nim
import nimonyplugins
proc tr(n: Node): Tree =
result = createTree()
let info = n.info
var n = n
if n.stmtKind == StmtsS: inc n
result.withTree StmtsS, info:
result.withTree CallS, info:
result.addIdent "echo"
result.takeTree n
var inp = loadTree()
saveTree tr(beginRead inp)
But it works! And the results are cached so compile-times shouldn't suffer.
Progress report: This program works now:
import std / syncio
proc willFail() {.raises.} =
raise Failure
try:
willFail()
except:
echo "failed"
But for now only raising the new ErrorCode enum is supported. The implementation maps it to tuples+gotos so the overhead is comparable with Nim's goto based exception handling. In fact, the produced code should be slightly better as the thread local storage is avoided and hardware registers can be used for error propagation.
This way of error handling also composes well with the idea that new can return nil on OOM: If new is in a .raises proc and it returns nil we can map this to OOM automatically and when you're not in a .raises proc the nil checking will enforce you checked for nil.
This is what good design does: It opens up new solutions. :-)
Mini progress. The following program parses:
import std / [syncio]
type
Obj = ref object of RootRef
Obj2 = ref object of Obj
proc testNil() =
var nilRootObj: nil ref RootObj = nil
var other: nil RootRef
var nn: RootRef not nil
var nn2: ref RootRef not nil
testNil()
But not-nil checking based on a control flow graph is not implemented yet as I debug our control flow graph. :-)
However, I expect nil-checking to work in the next couple of days...
Progress: The construction of the control flow graph has been rewritten to use the standard "split streams" algorithm (that is nowhere documented in the compiler literature afaict). This replaces lots of fragile logic. (Some background here: I thought I had found a better way than the split streams algorithm but it turns out, it was just a terrible hack...)
Now that the control flow graph is solid, work on the not nil checking can finally continue.
Progress report. This program works:
import std / syncio
type
Myref = ref object
x: int
proc p(): Myref not nil {.raises.} = Myref(x: 5)
proc hah2 {.raises.} =
var r: nil Myref
r = p()
echo r[].x
proc other =
var r: nil Myref = nil
if r != nil:
echo r[].x
else:
echo "is nil"
try:
hah2()
other()
except:
echo "god riddance"
Nimony is now feature complete. In the sense that all important features for a MVP have been implemented. Now the "polish" phase begins. Error messages must improve, bugs must be fixed and a minimal stdlib must be added.
After we released the MVP the focus will shift to better compatibility with Nim so that we can use its stdlib (and of course compile most of the wild Nim code out there). You will notice this shift when I start talking about Nim 3 instead of Nimony. ;-)
There are 3 modes:
unchecked ref/ptr: Just like in Nim.
nil ref: can explicitly be nil and we want derefs to be protected by analysis.
not nil ref: cannot be nil and we want analysis to ensure it.
The default is still "unchecked ref" as we haven't implemented the mode switch.
> About concepts, would abstract generics still work?
When you mark your generic as .untyped, yes.
Part 2:
The first Nimony progress thread became too long to manage. This thread is the 2nd progress report for Nimony.
Recently this program compiled (and produced the correct output):
import std / [syncio]
type
BinaryTree[T] = ref object
le, ri: nil BinaryTree[T]
data: T
proc newNode*[T](data: sink T): BinaryTree[T] = BinaryTree[T](data: data)
proc append*[Ty: Comparable](root: var nil BinaryTree[Ty], n: BinaryTree[Ty]) =
# insert a node into the tree
if root == nil:
root = n
else:
var it = root
while it != nil:
var c = cmp(n.data, it.data)
if c < 0:
if it.le == nil:
it.le = n
return
it = it.le
else:
if it.ri == nil:
it.ri = n
return
it = it.ri
proc append*[Ty](root: var BinaryTree[Ty], data: sink Ty) =
append(root, newNode(data))
type
Stringable = concept
proc `$`(x: Self): string
proc toString[T: Stringable](n: nil BinaryTree[T]; result: var string) =
if n == nil: return
result.add $n.data
toString n.le, result
toString n.ri, result
proc `$`*[T](n: BinaryTree[T]): string =
result = ""
toString n, result
proc main =
var x = newNode("abc")
x.append "def"
echo $x
main()
Feel free to continue the discussion about what syntax to use for nil ref T, ref T not nil, unchecked ref T here.
Progress: Nimony now uses its own build tool called "nifmake" instead of "make".
Progress: import module {.plugin: "v2".} worked for the first time. I wrote a simple module abc that contained fib:
proc fib*(n: int): int =
if n < 2:
return n
else:
return fib(n - 1) + fib(n - 2)
Then I imported this module via the new import plugin system:
import std / syncio
import abc {.plugin: "v2".}
echo fib(10)
And the result compiled and linked and produced the correct result!
This used the Nim v2 compiler to precompile `fib` and it was imported successfully into Nimony!
It's been integrated into the IC pipeline, it only invokes nim nif when your dependency changed. So actually you do benefit. However! When you change your v2 dependency nim nif compiles all the imported modules as it has no IC.
> Can nimony solve the circular dependency problem?
The compiler was built with solving this problem in mind but it's not been implemented yet.
Progress: Closures begin to work:
import std / [syncio]
proc testClosure() =
var x = 40
proc inner =
echo x
inner()
testClosure()
Progress: The compiler optimizes the closure heap allocations away in certain cases. We can make this technique part of the spec as it means capturing var T parameters can be allowed if the heap allocation can be avoided.
In other words:
proc outer(s: var string) =
proc inner =
s.add "abc"
s.add "def"
inner()
becomes possible.
Progress: The terrible and popular defer statement has been implemented.
Progress:
packed and union pragmas have been implemented.
case object is beginning to work.
proc types are more stable.
Porting of hard test cases from Nim's extensive test suite has begun.
The plan keeps changing. I am working on continuation-passing-style as the foundation for async+multi-threading. Then we can develop a standard library that is async-ready from the beginning, skipping multiple development iterations.
Once we have more of a library, I think it's ready for a first release. I'm still optimistic for autumn this year, but who knows.
Progress:
The using statement has been implemented.
The "prefer iterators in a for loop context" logic has been implemented.
Progress: The simplest "passive" proc works now:
import std / [syncio]
proc passiveProc(x: string) {.passive.} =
echo x
passiveProc("abc")
A .passive proc is one that is turned into its CPS representation. Usually this is called an async proc but for now "passive" is the working title. (It's a better name than "async" anyway.)
Progress:
astToStr exists now.
The do notation has been implemented.
Progress: system.compiles has been implemented.
Progress: This program worked for the first time:
import std/[assertions, syncio]
proc myecho(inp: string) {.passive.} =
echo inp
proc pa(inp: string) {.passive.} =
for i in 0..<3:
myecho inp & " a"
pa "abcdef"
However, to make it play nice with try finally and raise we likely need to do the CPS transformation much later in the pipeline than we currently do. This then implies we need to generate the =hooks on our own as we then transform the code after the hook injections have been performed. These phase ordering problems are the truely hard stuff in compiler development.
The compiler transforms .passive procs into their CPS representation which is the foundation for async.
Progress: push/pop pragmas have been implemented.
We are working on these stdlib modules:
math, strutils, unicode, encodings.
Once we have these we'll have a first release, version 0.4 or something. Most probably this will still lack the .passive features though. (September 2025)
Then we need to bootstrap the compiler. (December 2025?!) Once that works, we can call it version 1. During bootstrapping we learn how to port Nim 2 code to Nimony and should document the process. This is not Nim 3 then but you can write code that works with both Nim 2 and Nimony. I wouldn't call that Nim 3 though as for Nim 3 the import v2 feature needs to work well which is full of evil details to get right...
Progress:
unicode.nim has been ported.
the passL pragma has been implemented.
Progress:
Terrible bugs have been fixed.
math.nim contains many consts & procs.
Progress:
The rewrite rule proc p {.t.}... --> t: proc p... has been implemented.
The dynlib pragma has been implemented.
We now have std/locks.
Bugs have been fixed.
Progress:
std/encodings has been ported.
std/monotimes has been ported.
Overloading based on var T is gone as accessors become polymorphic instead: It is tracked if a write to a location like a[i].x.z is allowed. It is allowed if a is mutable. The builtin array indexing has always worked this way so this is a most natural extension.
# Nimony
proc `[]`(x: Container): var Element # polymorphic accessor
It also means we know in the type system if a container access can resize the container or not as the resize would still require the var-ness for the parameter!
Progress: There are now beginnings of an API for plugins.
Progress: We now have Nimony documentation here
The single page design is somewhat impractical, sorry. Will improve it later.
Ever since Nimony gained a string implementation. That said, I agree that it's annoying... We should probably stop chasing the slices (which you can get with openarrays already anyway) and instead go for SSO strings that keep the zero terminator.
Part 3:
Progress: The beginnings of our stdlib now use Nimony's new ErrorCode based error handling. I'm particularly pleased with how this works, so far. The result still feels like Nim, it's just a better variant of it.
> What about additional payload in the error? It seems that this option does not allow you to add it.
That's some library specific getMoreErrorInfo API which can then decide of whether to use threadlocal storage for it or if some object that you have lying around somewhere (typically called a X-"Context") can keep this information.
> In the same vein, would the standard library be built on top of it? i.e Optionals wherever relevant?
They simply are not relevant when you have exceptions. (Or more generally speaking, when you have some version of raise.)
Progress: Nimony now supports threads via its rawthreads module. This porting effort also made me aware of a bug in Nim's core threading support that I'm sure was reported multiple times but only now I actually understand the issue... :-)
Progress. You nerd-sniped me into implementing a decent compile-time engine via a staticExec like mechanism. So now this program works:
import std / [syncio]
proc myop(a, b: string): string = a & ";" & b
const
MyConst = myop("Hello", "World")
echo MyConst
This also means we can add macro support to Nimony...
Progress:
The backend now does dead-code-elimination on entire programs (Nim 2 does too). It also merges generic instances so that generics become "0 overhead".
The frontend now supports check combined with --usages or --def (find usages, goto definition).
Part 4:
Progress. Generic inner procs are now moved to a position where lambda lifting can handle them.
In other words, this code now works:
import std/[syncio]
proc outer =
var x = 120
proc inner[T] = echo x
inner[int]()
outer()
It also does not use the heap as the closure does not escape. The echo implementation also does not allocate as it does not delegate to $ but to write.
Progress: Bugs are fixed at a very good pace due to the superior compiler architecture.
Progress. std/dirs is a thing and this program compiles&runs:
try:
for k, p in walkDir(path"nimcache"):
echo $k, " ", $p
except:
echo "problem!"

Objective:

You are assisting in analyzing the development progress of the Nimony language. I will paste the Nimony progress reports (parts 1–4) as raw text. Do not summarize them in general. Instead, extract concrete, verifiable details about what is currently implemented.

Your task consists of four phases:


Phase 1 — Extract Working Constructs

Create a structured list of language features and constructs that are confirmed to be working. For each feature, include:

  • Name of construct (e.g., functions, let, records, union types, pattern matching, CPS blocks, etc.)
  • Short description
  • Any usage constraints or limitations noted
  • A short code example, if provided in the text

This should be factual and grounded in the text, not inferred.


Phase 2 — Extract Non-working / partial features

List constructs that:

  • Are implemented but unstable
  • Are experimental or incomplete
  • Are mentioned as planned but not yet functional

For each, note the exact wording or phrasing from the progress reports that indicates its status.


Phase 3 — Extract Modules / Libraries / Subsystems

Make a list of:

  • Modules or subsystems already ported or implemented
  • Modules partially ported
  • Components explicitly not ported yet

Where possible, record:

  • File / module names
  • Responsibility / purpose

Phase 4 — Build a Demonstration Code File

Using only features confirmed as working in Phase 1, assemble a single minimal example code snippet that:

  • Compiles and runs under the current Nimony state (to the best of the reports’ statements)
  • Demonstrates several features together in a cohesive example
  • Avoids features listed as incomplete or unsupported

This example must be honest and focused on what works now, not what is planned.

The style should be clear, simple, and resemble idiomatic Nim-like usage where appropriate, but strictly following what is confirmed functional.


Output Format

Your final output should include:

  1. Working Features Table
  2. In-Progress / Not Yet Working Features
  3. Modules / Subsystems Status
  4. Demonstration Code Snippet

Do not add commentary, opinions, or extrapolated conclusions. Base everything strictly on the text I will provide.

Objective:

You are an expert technical communicator assisting in writing a release announcement for the Nimony project. Your audience consists of experienced programmers—people who have worked with systems languages and have seen many trends and hypes come and go. They do not respond well to buzzwords, exaggeration, hype, or vague claims. They value clarity, maturity, and honesty about what is actually implemented and what still needs work.

Your task:

  1. Read the provided source materials:

  2. Identify the actual progress made between the previous release and the current release. Do not assume progress; base all claims on confirmed implemented features and discussed milestones.

  3. Write a release announcement that:

    • Is grounded and accurate
    • Avoids hype, trend-following language, and startup-speak
    • Uses precise language and concrete examples
    • Recognizes ongoing work and does not pretend Nimony is "finished"
    • Speaks to programmers who are tired of churn, rewrites, and hype cycles
    • Respects the reader’s time and intelligence

Tone style guidelines:

  • Think “experienced engineer explaining what’s new over coffee,” not marketing.
  • You may emphasize why the changes matter, but only after explaining what they are.
  • Write with calm confidence, not excitement.

If it helps, imagine the announcement is written for someone who has worked in C, C++, Pascal, or Ada, has used multiple build systems over decades, and appreciates clarity and conceptual stability over novelty.

Structure:

  • A short introduction (what Nimony is and where this release fits)
  • A clear, factual list of improvements / changes
  • A brief explanation of why those changes matter in practice
  • A realistic outlook on what’s next, without promises

Avoid:

  • Hype adjectives (e.g., amazing, revolutionary, blazing-fast, game-changing)
  • Claims that are not directly supported by the linked resources
  • Vague “vision” talk
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment