C⏚ v3.0.0Updated 2026-08-23·Language

Bundles

A bundle is a stateless entity that holds types, constants, and pure helper functions. Bundles let tasks and networks share definitions without coupling their behaviour.

package com.neosyn.sha256;
 
bundle SHACommon {
  typedef u6 addr_t;
  u9 HASH_SIZE = 256;
 
  u32 Ch(u32 x, u32 y, u32 z) {
    return (x & y) ^ (~x & z);
  }
 
  u32 Maj(u32 x, u32 y, u32 z) {
    return (x & y) ^ (x & z) ^ (y & z);
  }
}

A bundle has no ports, no state variables, and no setup or loop. Every function it declares is implicitly const - the keyword is optional.

Referencing a bundle

There are three ways to use a bundle's members from another entity. Pick the shortest one that doesn't cause name conflicts.

Import everything, refer by short name:

import com.neosyn.sha256.SHACommon.*;
// addr_t, HASH_SIZE, Ch(), Maj() are now in scope

Import the bundle, refer by qualified name:

import com.neosyn.sha256.SHACommon;
// SHACommon.addr_t, SHACommon.Ch(), …

Refer by fully qualified name, no import:

com.neosyn.sha256.SHACommon.addr_t

Wildcard imports are convenient but can cause collisions when two bundles export the same name. Qualified imports avoid that.

What goes in a bundle

KindAllowedNotes
typedefYesShared type aliases
ConstantYesCompile-time values
structYesShared record types
enumYesLiterals are always written Mode.RUN, never bare
FunctionYesImplicitly const
State variableNoBundles are stateless
PortNoBundles have no interface
setup / loopNoBundles have no behaviour

If a bundle needs state or behaviour, it should be a task instead.

Declarations at file scope

When the definitions are used by only one file, writing a whole bundle for them is ceremony. Since v2.9.6 you can declare const, typedef, struct and enum directly in the file, above the first entity:

package com.neosyn.fir;
 
const u8 TAPS = 8;
typedef u16 acc_t;
 
task Fir {
  sync { in u8 x; out acc_t y; }
  // TAPS and acc_t are in scope here, unqualified
}

These become an unnamed bundle that the file imports for you, so you refer to them by short name with no import line and no qualifier.

Two rules follow from that:

  • They must sit above the first task, network or bundle, after any imports. A declaration below the first entity is a syntax error.
  • A file gets one such group. Declarations cannot be interleaved between entities.

File-scope declarations are private to their file. Other files cannot import them, so anything shared belongs in a named bundle.


Next: Tasks, Networks.