Skip to content

Releases: Neat-Lang/neat

Neat 0.4.0: Let's try something else

07 Oct 16:21
Compare
Choose a tag to compare

Introducing breakelse!

If inside an if block, breakelse will jump to the else block.
If there is no else block, it will jump to the end of the if.

? has been expanded: if the expression type contains an :else, it will cause a breakelse. This is a shortcut for .case(:else: breakelse).

The .else(X) expression will directly replace the :else case with X. This is a shortcut for .case(:else: X).

The idea is to augment error handling with something like null: a type that represents "the operation failed, but in a normal way."

Neat 0.3.2: Arguably Minor

24 Sep 16:02
Compare
Choose a tag to compare

The help page (neat -h) had become more and more out of date with the actual options available.
Now that neat uses the new std.argparse for its own command line processing, we can just generate the help page from the actual options available.

  • std.argparse allows parsing command-line arguments (in Unix or GCC style).
  • std.macro.assert is now an expression.
  • Templated methods may now appear inside classes.
    • Though of course they won't be virtual.
  • Template type inference can now recurse into delegate types.

Neat 0.3.1: Small Fry Edition

17 Sep 16:07
Compare
Choose a tag to compare

I haven't really done much of anything for the past two weeks. (I blame COVID.) Annoying, but here's some small stuff that's accumulated.

  • Float literals are now polysemous (0.3 implicitly converts to float).
  • Alias matches expressions without extra parentheses.
  • Borrow array members for loop iteration iff array is immutable.

Neat 0.3.0: Mutable Arrays are a separate type now

06 Aug 19:36
Compare
Choose a tag to compare

I think this is a good idea, but people may disagree. It's gonna allow some refcounter optimizations in the long term, and I think it's just correct as a matter of language semantics. Immutable arrays can be reliably treated as values.

T[] is now an immutable array. You can append it and append to it, but you cannot change members via index assignment.

T mut[] is a mutable array. You can append it and append to it, and members can be assigned via a[0] = value, but it cannot be implicitly converted to a T[].

array.freeze converts a mutable array to an immutable array. It is forbidden to do this when the array still has live references, or to mutate members of the original array after freeze has been called. (Eventually the language will enforce this.)

Conversely, array.dup will convert an immutable array to a mutable one.

Neat 0.2.5: Refcounting for functions

24 Jul 05:03
Compare
Choose a tag to compare

The big new thing here is delegate refcounting. There's a new type, void delegate!(), for delegates that can't be refcounted, ie. stack-scoped delegates; it cannot be copied for that reason, but it can be passed to functions and called, which is often all you need.

To create a proper delegate, use new &nestfn. This will create a copy of the stackframe. This copy is not shared with any other new allocated nested functions!

void delegate!() is a bit too restrictive for lambdas: ie. you can't return it or store it in a struct, which we absolutely need for std.algorithm. So lambdas use a different strategy called "quarantining", which is a bit complicated to explain, but tl,dw: you can't return a lambda from the function it was declared in, and you can't stick a lambda anywhere where the compiler could lose track of it and so return it from the function it was declared in by accident.

super:

class A { int i; this(this.i) { } }
class B : A { int j; this(int i, this.j) { super(i); } }
// but also, equivalently
class C : A { int j; this(super, this.j) { } }

Does exactly what you'd expect.

Changes

  • Add delegate refcounting.
  • void delegate!() marks a delegate as noncopyable.
  • Nested functions and lambdas can be heap allocated with new.
  • lambdas are quarantine checked.
  • super() calls the super constructor
  • super token in the constructor parameter list generates an implicit super call.
  • Change: this is now a reference in structs.
  • Quote rewrite: all of the base language should now be quotable.
  • Various compilation speedups.
  • Fix propagation of bottom value.
  • Fix multithreading.

Neat 0.2.4: This is a placeholder.

26 May 19:42
Compare
Choose a tag to compare

This release mostly exists to get the void delegate!() syntax in so I can use it in the compiler during bootstrapping.

I'll explain what that does once it actually does something. :)

Changes

  • Switch to LLVM 15 with opaque pointers.
  • Implement polysemous array literal conversion.
  • Implement nested function mutual recursion.
  • Add new syntax: void delegate!(). This is a placeholder.
  • Small parser speedups.

Neat 0.2.3: In the Background

28 Feb 07:21
Compare
Choose a tag to compare

Hashmaps are fully in! Delegates are now the biggest remaining hole in the language concept.

Changes:

  • Add -loop flag: Rerun the compiler, only rebuilding files that have changed.
  • Add -watch flag: Rerun the compiler immediately if a used source file changes.
  • Add __hash builtin to compute a hash for an arbitrary value.
  • Support most built-in types as hashmap keys.
  • .case() and ? will now treat nullable Class as (Class | fail nullptr_t).
  • Support accessing declarations in classes as static members.
  • All created threads now explicitly demand 8MB stacksize. (Fixed #25)

Neat 0.2.2: New Year of Lexing

01 Jan 20:31
Compare
Choose a tag to compare

Small release. Biggest impact is a change in parser API: several operations no longer return an Error, as the error case now happens during lexing. This will require some change in macro use, but largely just removing ?s.

Oh, and depending on codebase, you might see a 20% to 200% speedup, as the C importer now only depends on the neat.base module, reducing the cost to use this macro. (I'm pretty happy with that one.) There's some other speedups around sumtype case expressions as well: the LLVM backend now tries to more aggressively avoid large structure load and store instructions, which are not well optimized by LLVM.

As compared to 0.2.1, neat building itself is down to 0.85s. Still not as big as hoped, but I'll take it.

Neat 0.2.1: Advent of Lexing

19 Dec 17:46
Compare
Choose a tag to compare

When building Neat, the new lexer gives a 60ms speedup: 1.07s to 1.01s. Not the most spectacular, but hopefully more gains later.

I've also been doing the Advent of Code '22 puzzles to shake out bugs. Language is holding up so far; no show-stoppers.

  • Change operator precedence to raise shift operators
    • It is now & ^ <<>> | */ +- <> && || if
  • Add character literals: 'a'
  • The -release switch disables array bounds checking.
  • The -run switch executes the built binary.
    • Command line arguments after -- are passed to the program.
  • Add std.algorithm.splitter
  • Add formatting for chars, named tuples, vectors, enums
  • Add hashmap.remove, hashmap.clear
  • .() now parses as a tuple, removing the need for .(())
  • with() { } now supports types, such as enums
  • value.case(...) now supports non-sumtype value
  • Ret foo() => value is equivalent to Ret foo() return value;
  • Support bool || bottom.
  • a ~= b; now detects if a is non-mutable.
  • Fix long literals. Numbers that are too big for int are now automatically typed as long.
  • The input text is now lexed before parsing, providing a marginal speedup.

Neat 0.2.0: "We live in a society / Bottom type." --Donald Knuth

17 Nov 05:29
Compare
Choose a tag to compare

Oh yeah, I make releases. I forgot.

  • Tuple field names are now part of the type.
    • A tuple implconvs to another by the rule that fields without names convert to fields with names. Fields with conflicting names do not implconv.
    • Tuple literals can specify names as (a=2, b=3).
    • A tuple implconving to another where only names are changed is called a "trivial conversion", ie. a conversion with no effect on the stored data.
    • If T trivially converts to U, then T[] implicitly converts to U[].
  • Support template shortcut syntax: keyword name(T) => template name(T) { keyword name {} }.
  • Implement nontrivial IFTI.
    • Function template calls can now infer template parameters even with indirect relations, such as (T)(T[] array).
  • Array index access is now bounds checked.
  • Support class method overloading.
  • Add bottom type.
    • bottom is a type that contains no values. The D equivalent is called noreturn.
    • break, continue and return are expressions of type bottom. This enables .case(foo: break) and the like.

And many fixes, the most important one maybe being that-j should now work reliably.

I also want to direct special attention at the GTK demo, which uses macros to make the GTK object system pretend to be Neat classes.