Skip to content

Appa v2.2.0 (Stable)

Latest

Choose a tag to compare

@ApparentlyPlus ApparentlyPlus released this 01 Sep 16:54

Appa v2.2.0 (Stable)

This update fixes a cluster of miscompiles in generics, operator dispatch and ARC lowering, every one of them found while porting a Span[T]-shaped library to Gata and scaffolding the self-hosting example, bringing the compiler to v2.2.0:

  • Fixed operator dispatch firing on pointer-typed values. ClassNameOf follows pointer indirection, so any expression whose type was SomeClass* was treated as eligible for SomeClass's own operator overloads. A generic union's T* payload, pattern-bound inside a generic function and advanced with ptr + n, compiled into a call to the pointee class's + operator instead of pointer arithmetic whenever T was instantiated with a class that declared one. The same confusion reached as casts, prefix and postfix operators, unary operators, binary operators, compound assignment and indexed compound assignment. All nine sites now use a new DirectClassNameOf, which reads a class reference and refuses to look through a pointer, so Adder* is a pointer and only Adder is a class.

  • Fixed a generic method's call to a generic free function silently dropping the callee's definition. DrainGenericInstancesCore drained the free-function queue to empty and then the method queue, in that order and once each. Resolving a queued generic method can enqueue a fresh free-function instantiation, and by then nothing was left to drain it, so a module method with its own type parameter that called a generic free function reachable through no other call site emitted the call and never the function. Both drains now sit inside an outer loop that runs until the two queues are empty together.

  • Fixed a dead release being appended after a return that already released. A function with several early-exit if { return ...; } branches, whose final branch also returned a freshly built managed value, had the block's frame released a second time after its own return statement. Unreachable in C terms, but it emitted a release of a temporary the return had already handed off. LowerBlock now checks whether the statements it produced already end in a return, break or continue before releasing the frame.

  • Fixed void being emitted as the type of a return temporary. The lowered return declares a __ret temp to hold the value across the frame's releases, and typed it from the returned expression rather than from the function. An expression that carries no IR type of its own produced void __ret0 = ...;, which no C compiler accepts. Ownership now tracks the declared return type of the function being lowered and falls back to it, saving and restoring it around nested functions the way it already did for the throws state.

  • Fixed a throws function whose body ends without a return falling off the end of a non-void C function. The lowering that wraps returns in Ok(...) never supplied the implicit one, so the emitted function simply ran out of statements while declaring a Result return type. LowerFunction now appends return Ok(...) to any throws body that is empty or does not already end in a return.

  • Fixed G093 firing on code that manages a union's reference count by hand. The unsafe block warning suppresses itself when the block names retain or release, but it only recognised the two intrinsics by their C names. A union's generated per-type retain/release pair did not match, so hand-counting a union inside unsafe still drew "this builds a value inside an 'unsafe' block, where it is never released". The check now also recognises a single-argument call to a union's own retain or release.

  • Added argc/argv plumbing to the generated hosted main. It was int main(void), which left an environment's _env_argc/_env_argv with nothing to read. It is now int main(int argc, char** argv) and stashes both into the gata_argc/gata_argv globals the hosted environment declares, which is what makes libgata's new Args module work.

  • Extended the C-reserved rename list with the names the Windows headers claim. windows.h, which the hosted preamble includes on that platform, defines min, max, near, far, IN, OUT, OPTIONAL, CONST, VOID, TRUE, FALSE, interface, ERROR, INVALID_HANDLE_VALUE and the calling-convention macros. A local, parameter or struct member named after any of them compiled everywhere except Windows. All of them now take the same trailing-underscore rename as the C keywords.

  • Added CompilerBugRegressionTests, covering the first three fixes above end to end. Each one compiles the emitted C with a real host compiler and asserts on the program's output, rather than settling for "appa accepted it".

Installation

For setting up Appa in your own machine, grab one of the following executables depending on the platform and run appa install:

  • Windows: appa-win.exe
  • Linux: appa-linux
  • MacOS on ARM (Apple Silicon): appa-amac
  • MacOS on Intel (Legacy x64): appa-imac