You are browsing as a guest. Sign up (or log in) to start making projects!

Open comments for this post

5h 26m 53s logged

Devlog: Giving Flower Real Module Support

v1.2.x was the point where Flower’s impors had to stop being “you can import stuff.. and there’s a fake layer of security” to a proper (get it?) module system.

Before this work, imports and aliases mostly behaved like naming conveniences. You could write:

import "math.flo" as math
math.add(1, 2)

but the compiler was still too loose about what that really meant. Alias names were in emitted C symbol names, top-level declarations were not private, and prop existed more as syntax than as a real feature.

That was fine for early bootstrap work, but it was not strong enough for the next stage of the language.

So the main goal of v1.2.x became:

  • make imported aliases act like real namespaces
  • make prop define the public interface of a module
  • make top-level declarations private by default
  • lay groundwork for field visibility rules like hidden and readonly

Module Semantics Instead of Alias Tricks

One of the biggest changes was separating Flower semantics from C lowering.

Previously, imported aliases were drifting toward becoming part of emitted symbol identity. A local alias should just be a source-level name bound to a module, not the backend symbol.

So now each module has its own lowered symbol prefix, and alias lookup happens semantically during compilation. That means:

import "math.flo" as math
math.add(1, 2)

is resolved as “look up exported add in module math.flo,” not “invent a C symbol from the local alias text as math_add().”

That change also forced a cleanup of emitted names so they stopped leaking absolute filesystem paths. Generated symbols now use project-relative module prefixes instead of machine-specific paths.

prop Became Real

Another major part of this was making prop actually do something.

Instead of treating it as a thin wrapper around only functions, the compiler now recognizes prop as a real top-level export marker. That means the module’s public interface is defined by what it explicitly exports, while non-prop declarations remain internal.

This moved Flower closer to the model I wanted all along: explicit modules, explicit public APIs, no heavy object system (OOP), no fake privacy delegated to the C backend.

Dot Access, Pointers, and the Annoying Middle Part

This work also exposed a weakness in the compiler’s dot-access resolution.

Flower source always uses ., while the C backend must decide whether a given access becomes . or ->. That mostly worked already, but nested pointer-heavy field chains exposed cases where the type tracker was not propagating enough information, which caused bad fallback behavior during self-hosting.

So before field visibility could be trusted, I had to harden nested dot-access resolution. Not fun, but necessary. As it turns out, I was missing several AST kinds which caused the logic to fall through. Very tedious work, but it was well-worth it in the end!

Field Flags Groundwork

With module ownership and access resolution in better shape, I added the first field visibility modifiers:

  • hidden
  • readonly
  • frozen

Originally I debated having these as bitwise operations, but I decided it’d be best to stay within the current update’s scope, so sometime in the future I’ll refactor.

Right now, hidden and readonly are the meaningful additions:

  • hidden blocks external field access
  • readonly blocks external assignment

frozen is groundwork for later. It is parsed, stored, and carried through the compiler, but full assignment-once enforcement is still deferred. Unsure how I’ll go about it, but that’s an issue for future me :p

0
11

Comments 0

No comments yet. Be the first!