Nucleoid is a logic programming language for LLMs.
A Nucleoid program is a set of statements that remain true. An assignment is not
an instruction that runs once and finishes; it is a relationship the runtime
records and maintains. Writing c = a + b states that c is the sum of a and
b, and that stays true as a and b change.
This document is the consolidated reference, assembled from the NUC documents.
See NUC 0 for the index and NUC 1 for the
conventions. nucleoid.spec.md is normative; where this document and the
specification disagree, the specification wins.
Each NUC is a language proposal. New or updated proposals get a fresh
nuc-proposal agent to draft, prototype, and rewrite equivalent executable
cases, followed by an independent fresh nuc-evaluate agent to check the
frozen candidate and compare lexer tokens per case without rewriting it.
Acceptance requires every case to use the same or fewer tokens and behavior
checks to pass; any increase rejects it. Draft or rejected proposals do not
change this implemented reference. See NUC 1.
The entries below are abbreviated to the behaviour they state. examples.md covers the same ground as complete programs, each one runnable as written.
- Statements and State
- Variables
- Expressions
- Types and Instances
- Properties
- Class-Level Rules
- Blocks and Scope
- Control Flow
- Functions
- Transactions
- Built-in Objects
- Reasoning Operations
- Error Reference
- Syntax Summary
- A statement is run against the state and changes it.
- An assignment records a relationship, not just a result.
- An expression statement returns its value.
- Statements are applied in the order received; when two assign the same target, the last one holds.
- One statement per line, or several on a line separated by
;. - Every statement runs in a transaction.
i = 1
k = 1
k
- Returns
1.
- Accepted NUC 45 adds
assert: actual, expectedas an optional statement spelling of the existing two-argumentassert(actual, expected)helper. - Both lower to the same call expression statement. Arguments run once, left to right, with the same deep equality, failure collection, counters and transaction behavior. A check is not a standing model rule, graph observer, or replacement for the preceding program result.
- Ordinary calls remain supported in every existing context and retain their existing argument-count behavior. The colon-led form requires two expressions and one separating comma, with no extra/trailing comma, truthiness mode, generic bare call, new keyword, or layout continuation.
- Typed declarations win first:
assert: intremains a declaration withReferenceError("Missing definition"). Bindings, parameter annotations, fields and keys namedassertremain unchanged. Direct identifier calls namedassertinvoke the helper even when the name is bound. - The accepted specification contract
and five appended entries cover values, reasoning exclusion, scopes,
returns, evaluation order, caught errors and rollback.
The executable reference counterpart is
Nucleoid preserves assert names and declarations beside compact checks. - Independent evaluation accepted all 603 paired cases: eight use fewer lexer tokens, 595 are unchanged, and none increased. All 2,736 protected assertions executed and all 48 explicit expected returns matched.
assert(record.amount, 3)
assert: record.amount, 3
Full detail: NUC 2.
- A variable is created by assigning to it; no keyword is required.
- An assignment evaluates to the assigned value.
- A declaration with a type but no value is rejected.
a: int
- Raises
ReferenceError("Missing definition").
- Naming a variable on the right-hand side establishes a dependency.
- Dependents re-evaluate when a dependency changes.
- Dependencies are transitive.
- Queued upstream dependencies settle before their dependents, even after an upstream declaration is replaced.
- Re-evaluation preserves declaration priority; only an explicit re-declaration changes it.
a = 1
b = 2
c = a + b
cis3; aftera = 2,cis4.
- Assigning again discards the previous dependencies and records the new ones.
c = a + 3
c = b + 3
cnow followsb, nota.
- A variable's own occurrence on the right is read as its current value.
- This is not a cycle.
radius = 10
radius += 10
radiusis20.
- Accepted NUC 13 defines
+=,-=,*=,/=, and%=. target op= expressionlowers totarget = target op (expression).- Compound syntax has the existing assignment precedence and right associativity; it is not a new imperative update path.
- A target is a name or a plain dotted path rooted in a name,
$Class,this, orself; class and receiver roots require a property. - Parentheses may group a path, but calls, indexes, slices, and assignment expressions inside a target are unsupported.
- Self-reference reads the current value while other right-hand references remain tracked;
.valuestill takes a snapshot. - Local parameters, property receivers, expression return values, graph keys, and transaction rollback are unchanged.
- Class-level self-reference remains
TypeError("Circular Dependency"); compound syntax does not make it a one-time update. - These forms passed independent per-case evaluation; existing assignment syntax remains valid.
amount = 10
step = 2
amount += step
amountis12; afterstep = 3, it is15.amount += step.valuemakes it18; a laterstep = 5leaves it18.- The executable counterpart is
Nucleoid preserves compound assignment relationshipsintests/reference.md.
- Accepted NUC 26 defines optional
&&=and||=as one token each; every paired case passed independent evaluation without an increase. target &&= rhslowers exactly totarget = target && (rhs);target ||= rhslowers exactly totarget = target || (rhs).- The full right operand keeps assignment precedence and right associativity;
a ||= b &&= 9meansa = a || (b = b && 9). - A standing assignment always installs the expanded relationship, even when logical evaluation skips the right operand. It is not a JavaScript-style conditional write.
- Logical operators keep operand values and short-circuiting. Existing
null/deferred handling and pre-evaluation
.valuefreezing are unchanged; snapshot reads may still occur in a skipped logical operand. - The same plain-path validation permits at most 128 dotted links across grouped paths, rejects computed targets before cloning, and shares the existing expression/statement nesting budget.
- Local parameters,
this/self, property self-reference, class-level cycle errors, expression returns, dependencies, rollback, graph keys and canonical expanded rendering retain the existing assignment behavior. - All arithmetic compound forms remain valid. The expanded symbolic and word
forms also remain supported, for example
enabled = enabled || fallback,enabled = enabled or fallback,ready = ready && allowed, andready = ready and allowed. - The executable counterpart is
Nucleoid preserves logical compound assignment relationshipsintests/reference.md. - New variants in the exhaustive public Rust
Tokenenum are source-breaking for downstream exhaustive matches. A human must decide the API semver action; no version or dependency change is part of this revision.
.valuereads the current value and records no dependency.- Its snapshot remains fixed inside lists, object literals, templates, and slices when other dependencies update.
- It breaks what would otherwise be a cycle.
- The value of a
nullproperty is0.
goldenRatio = 1.618
altitude = 10
width = goldenRatio.value * altitude
widthis16.18; unchanged bygoldenRatio = 1.62; becomes161.8afteraltitude = 100.
- Any
nulldependency yieldsnull. - Reading something undefined yields
nulland re-evaluates when it arrives.
deleteremoves a variable and returns whether anything was removed.- Dependents of a deleted variable become
null. - Using a deleted variable raises a reference error.
- Temporary undefined reads end when the deletion's propagation finishes, including deletions performed by a standing rule.
base = 10
tax = base * 0.1
total = base + tax
delete base
taxandtotalarenull; usingbaseraisesReferenceError("base is not defined").
Full detail: NUC 2.
- Numbers, including negatives and fractions.
- Strings in single quotes, double quotes, or backticks.
- Template literals interpolate with
${...}and track their dependencies. true,false,null.- Lists in brackets; objects in braces, with quoted or bare keys.
- Regular expressions between slashes.
host = "localhost"
port = 8080
url = `http://${host}:${port}`
- After
port = 9090,urlis"http://localhost:9090".
- In this isolated Draft NUC 17 candidate, an ordinary identifier
field
amountin an object-literal expression means exactlyamount: amount. - Explicit fields may mix with shorthand, nest in objects and lists, and keep the existing comma, trailing-comma, newline, and semicolon rules.
- The identifier must be followed by a comma or closing brace, looking through only the existing newline/semicolon separators; this shorthand qualification is unchanged by the NUC 44 explicit-property separator rule below.
- Quoted and numeric keys need explicit values; keywords,
$Class, dotted paths, and computed keys do not become bare shorthand keys. - Canonical source remains quoted and expanded, such as
{"amount":amount}. - Values use the same scope, parameter/receiver bindings, object aliases, dependencies, duplicate-key replacement, snapshots, and rollback.
- A missing value name inside an object raises
ReferenceError("missing is not defined"), not a silentnullfield. .valuesnapshots still need explicit fields, such asamount: amount.value.- Statement-leading
{ amount }stays a block; nameddef wrap(amount) => { amount }returns an object, while anonymousamount => { amount }stays a block and needsamount => ({ amount })to return an object. - This does not add closure capture, indentation inside unparenthesized braces, colon continuation, new key grammar, or destructuring.
amount = 4
unit = "C"
reading = { amount, unit }
assert(reading.amount, 4)
assert(reading.unit, "C")
amount = 6
assert(reading.amount, 6)
- The executable counterpart is
Object property shorthandintests/reference.md; the five paired specification entries in NUC 17 cover the runtime behavior. - These isolated prototype forms await independent evaluation and integration; they are not a change to the accepted reference.
- NUC 44 makes an explicit-property comma
optional only after parsing the preceding value's entire ordinary expression.
{kind: kind lane: lane(urgent) active: true}has the same complete ordered AST as{kind: kind, lane: lane(urgent), active: true}. - Keep an existing comma first. Without one, after only the original
newline/semicolon skipping, inspect the next two unconsumed tokens:
an existing string, ordinary identifier or number key immediately followed
by
:continues the same object. The guard consumes nothing and never speculatively parses, stops early or reinterprets a value. - Operators, assignments, postfixes, function/arrow bodies and nested objects retain priority. Lists, calls, parameters, statement blocks and key grammar do not change. No new brace indentation or colon continuation is added.
- Shorthand still needs its own comma-or-closing-brace lookahead.
{amount, unit: "C" active: true}is valid, but{amount unit: "C"}and{amount: 1 unit}are not. Keep commas around shorthand where its original rule needs them; trailing commas and mixed explicit separators remain valid. - Duplicate keys retain every ordered value evaluation before replacement.
Numeric keys use the same formatting; canonical source remains quoted and
comma-separated. Actual dependencies, aliases, scopes, receivers,
.valuesnapshots, whole caught errors, rollback and resource limits are unchanged.
def lane(urgent):
if urgent: return "fast"
return "normal"
kind = "invoice"
urgent = false
summary = {kind: kind lane: lane(urgent) active: true}
assert(summary.kind, "invoice")
assert(summary.lane, "normal")
urgent = true
assert(summary.lane, "fast")
kind = "alert"
assert(summary.kind, "alert")
- This is the exact
Nucleoid builds compact routing recordsexecutable counterpart intests/reference.md, paired with its accepted comma form. The five appended specification entries trace live construction, keys/replacement, nesting, snapshots and rollback. - A failed guard keeps the original closing-brace diagnostic.
Exact
record = { amount: 1 next }retainsSyntaxError("Expected '}' but found identifier 'next'")at line 1, column 22.record = { amount other }retainsSyntaxError("Expected ':' but found identifier 'other'")at line 1, column 19. record = { amount\n: amount }still raisesSyntaxError("Expected ':' but found end of line")at line 1, column 12; unparenthesizedrecord = {\n amount: amount,\n}still raisesSyntaxError("Expected a key but found an indented block")at line 2, column 5. Existing computed-key writes, exporter splitting and receiver-frame limits are not repaired.
- Arithmetic:
+,-,*,/,%. - Compound assignment:
+=,-=,*=,/=,%=; each operator is one token. - Logical compound assignment:
&&=,||=; adjacent characters form one token.&& =,|| =,and=, andor=do not form compound operators. - Comparison:
==,!=,<,>,<=,>=. - Logical:
and/&&,or/||,not/!. - Parentheses override precedence.
+concatenates when an operand is a string.
assert(a + b * c, 14)
assert((a + b) * c, 20)
- A comparison may be assigned directly:
alarm = reading > threshold.
- Lists and instance lists index with brackets; the index may be a variable.
- Object bracket access has the same null, undefined, and dependency behavior as a dotted property read.
- A range is written
[start:end]; either bound may be omitted, and a negative bound counts from the end. - Both slice bounds are expressions whose references are checked when a class-level rule is declared.
.lengthis a dependency on the collection.
meeting.time[-17:]
- The last 17 characters.
Full detail: NUC 10.
class Entitydeclares an empty type without a placeholder body.- The explicit
class Entity:form with an indentedpassremains valid. - A bare header ends at a statement boundary and does not adopt the next statement as a constructor.
- An indented body still requires a colon; inheritance keeps its existing colon grammar.
$Nameis the type;Nameis the list of its instances.typeof $NameisClass;typeof NameisList.- Every declared type is added to the global
Classlist. - Assignments reading
Class.lengthupdate when a type is declared; re-declaring a type does not increase the count.
class Entity
- Parameters may be declared on the type, with optional annotations.
- A bodyless header may keep the same parameter list, such as
class Shell(code: int); parameters alone do not create or assign properties. - An equivalent form declares attributes plus an
initfunction. - A missing argument leaves the attribute
null.
class Shape(type: str):
this.type = type
class Shape:
type: str
def init(type: str):
this.type = type
thisandselfare interchangeable keywords for the current instance in constructors, methods, and class-level rules.- Either spelling reads and writes the same properties; both may be mixed in one body without declaring a receiver parameter.
- Neither keyword may be rebound. Using either without a current instance raises
ReferenceError("this is not defined"); rebinding either raisesTypeError("Cannot assign to 'this'").
- Creating an instance registers it in the type's list and returns it.
- The variable name becomes the instance
id. - An instance created without a variable name gets a generated
id. - Instances are addressed by index
Name[0], by idName["id"], or by queryName.find(...).
- A subtype names its supertype after the colon;
super(...)invokes its constructor. super(...)advances from the constructor currently executing; subtypes without constructors use the nearest ancestor constructor.- Class-level rules on the supertype apply to subtype instances.
- Direct or indirect inheritance cycles are rejected when the type is declared or re-declared.
class Truck: Vehicle
def init make, payload:
super(make)
this.payload = payload
- Bare
superis the primary expressionsuper(); it always passes zero arguments and returnsnullon success. - The parent's constructor runs on the same receiver, without adding an instance to the parent's population.
- In a constructor, resolution advances from the constructor currently executing; in a method, it falls back to the actual receiver's class.
- A receiver with no parent makes the call a no-op returning
null; missing parent parameters remainnull. - Without an instance receiver, either spelling raises
ReferenceError("super is not defined"). - An immediate
(still introduces explicit arguments, including when whitespace precedes it;super(arguments...)is unchanged. - A logical newline or semicolon is not skipped to find arguments;
superfollowed by(7)on the next logical line is a zero-argument call and then a separate expression. - Line breaks already suppressed inside
(or[retain their existing meaning;(superfollowed by(7))inside the same parentheses is still the explicit callsuper(7). - Existing postfix and operator grammar applies; bare
superis also usable in assignments, returns, and expression bodies. - The existing adjacent-statement grammar is unchanged:
super amountparses as a zero-argument call followed by the expressionamount, not an argument-bearing call.
class Parent:
def init():
this.ready = true
class Child: Parent
def init():
super
this.code = 7
child = Child()
assert(child.ready, true)
assert(child.code, 7)
- Re-declaring a type preserves the class list and existing instances.
- New attributes are
nullon existing instances. deleteremoves an instance and returns whether anything was removed.- Deletion is refused while the instance still has properties.
- A variable name is reusable after its instance is deleted.
Full detail: NUC 3; accepted compact headers: NUC 14; candidate bare calls: NUC 16.
- A property is created by assigning to it, and behaves like a variable assignment.
- A property may be assigned from one that does not exist yet; the result is
nulluntil it does. - Assigning again replaces the relationship; self-reference reads the current value.
order1.upc = "04061" + order1.barcode
nulluntilorder1.barcodeis set, then"0406194067".
- A property may read through another instance, and the dependency follows the reference.
- Replacing the referenced instance re-points the dependency.
- Writing through a reference records the rule on the referenced instance.
user1.plan = basic
user1.bill = user1.plan.rate * 12
120; afteruser1.plan = pro,360; afterpro.rate = 40,480.
- Reading through a missing link yields
null; writing through one raises. valuemay not be used as a property name.- Deleting a property makes its dependents
nulland leaves others untouched.
Full detail: NUC 4.
$Name.property = ...states a rule for every instance of the type.- Rules apply to instances created before and after them.
- Rules may chain, read variables, and read through references into other types.
class Human(name: str):
this.name = name
$Human.mortal = true
- Every
Humanhasmortaltrue.
if,else if, andelsemay be written over$Name; each instance is evaluated independently.- Instances whose inputs are missing are left untouched.
- Rules on the same type apply in the order received; when several assign the same property, the last matching one wins.
- Assigning the property on one instance overrides the rule for that instance only.
- A rule on a subtype overrides the supertype's.
- Parent rule changes also apply to existing subtype instances, while subtype property rules retain precedence over inherited assignments.
- Rules validate references and dependency cycles before instances exist, including expressions nested inside collections, templates, and slices.
if $Grade.score > 89:
$Grade.letter = "A"
else if $Grade.score > 79:
$Grade.letter = "B"
else:
$Grade.letter = "C"
- A rule may aggregate another type's list.
$Category.revenue = Product.filter(p => p.category == $Category).reduce((sum, p) => sum + p.price, 0)
Full detail: NUC 5.
- A block is written with braces and introduces a scope.
- A name first assigned inside a block is local to it and does not survive it.
- Dependencies carried through a local do survive.
- Blocks nest; an inner block sees enclosing locals.
- A local shadows an outer name; lookup takes the lowest enclosing binding.
h = 1
{
value = h * 2
j = value * 2
}
jis4; afterh = 2,jis8.
- Instances may be created in a block and assigned outward.
- A local may hold an instance from the state; properties assigned through it are recorded on that instance.
returnyields a value; the firstreturnreached wins.- A block may return a local, a property of a local, or an inline object or list.
{
device = Device.find(d => d.code == "A0")
if not device:
throw "INVALID_DEVICE"
return device
}
Full detail: NUC 6.
- A conditional is a standing rule, re-evaluated when its condition or its branches change.
- A false condition leaves the target untouched rather than clearing it.
- Re-declaring a conditional replaces it.
- Conditionals apply in the order received; when several match, the last one holds.
- Re-evaluating one conditional does not move it after the others.
- A conditional can run again when an input changes later in the same cascade. An unchanged write does not restart feedback.
- Accepted NUC 34 makes the colon after a final
elseoptional only before a genuine indented suite. The unchangedelse:spelling is equivalent;ifandelse ifstill require their existing colons. - Require immediate newline/indent after
elseand a real indent after only normal newline/semicolon layout. Blank/comment lines create no indent; same-line statements, semicolons and braces cannot qualify for omission. - Reuse the whole existing body and nested/dangling-else association. Inline, semicolon-separated and braced alternatives retain their required colon. All other headers, canonical rendering, live rules, scopes, returns, throws, rollback and limits remain unchanged.
if toy1.color == "RED":
toy1.shape = "CIRCLE"
nulluntiltoy1.coloris"RED".
The executable reference's Nucleoid preserves live property relationships in indented else suites counterpart covers both branches and later input changes:
class Signal
signal = Signal()
signal.enabled = false
base = 4
if signal.enabled:
signal.output = base
else
signal.output = -base
assert(signal.output, -4)
base = 6
assert(signal.output, -6)
signal.enabled = true
assert(signal.output, 6)
base = 8
assert(signal.output, 8)
if false: pass\nelseraisesSyntaxError("Expected ':' but found end of input")at line 2, column 5. A final newline, comments-only body or unindentedpassinstead raisesSyntaxError("Expected ':' but found end of line")at line 2, column 1.if false: pass\nelse;\n passraisesSyntaxError("Expected ':' but found ';'")at line 2, column 5. Same-lineelse passandelse { pass }retain their missing-colon errors.- The authoritative colon-free indented else suites section records layout, exact inherited diagnostics and executable traces.
- The CLI already buffers a conditional from its initial colon header.
Bare final
elsestays in that buffer until blank-line commit or EOF; no new continuation heuristic or literal/comment delimiter is added. - NUC 43 also permits
else condition:orelif condition:in an existing chain, only with a complete balanced colon-bearing header and a genuine indented suite. Both lower exactly to the nested conditional ofelse if condition:. elifis still the lexical alias forelse. Explicitelif ifworks just likeelse if; unconditionalelif:and colon-free indented finalelifkeep their accepted behavior. No new keyword or standalone alternative statement is introduced.- Direct conditions cannot use inline/braced bodies,
:;, a missing colon or header separators. A non-consuming balanced token scan ignores nested colons and checks the existing real-indent predicate. Failed qualification leaves the final-else parser and original-source diagnostics untouched; qualified conditions and bodies report ordinary parsing errors. - The document/JSONL exporter retains complete
elseandelifkeywords with their top-level chain for spaced, tabbed and lexer-supported compact headers, including balanced multiline conditions and comments. Identifier prefixes such aselsewhere,else1andelif_nameremain independent statements. The parser alone validates the grammar; canonical AST rendering remains unchanged. Generated specification coverage includes a direct top-levelelseclass rule. - First-match order, short-circuit reads, reactive dependency replacement,
per-instance rules, scopes, returns, frozen functions and rollback remain
unchanged. Inherited queued-method receiver failures are not repaired.
The five new specification entries and
Nucleoid routes records through direct alternativesin the executable reference cover the normative contract.
- A condition need not be a comparison; a bare value is tested for presence.
null, an undefined property, and0are false; a non-empty value is true.- An instance is true, so a query result can be tested directly.
notinverts the test.
if $Device.profile:
$Device.active = true
- Only devices that have a profile become active.
for <name> of <source>andfor <name> in <source>iterate a class population or a list of registered typed instances.- The body runs once, over the values present at the time; it does not re-run later.
- Nested conditions and blocks are part of that one-shot body, not independent standing rules.
- Primitive/null elements, unregistered objects, plain
Object()instances and literal objects in lists are skipped; order and duplicates are retained. - Loops may nest, producing the cross product.
- Explicit sources keep arbitrary expressions and inline/braced/indented suites.
for question of Question:
Summary(question)
- Accepted NUC 31 specifies
for NAME:with a genuine indented body as exactlyfor it of NAME:with that same body;NAMEis one ordinary identifier source, not the iteration variable. - Require the immediate identifier and colon, an immediate newline or indent,
then a real indent after only existing newline/semicolon layout. Do not skip
header separators;
:;, inline/braced/missing-indent shorthand and property/index/call/literal/class-reference/parenthesized shorthand sources are not added. - Source lookup precedes binding local
it, sofor it:reads the outer source namedit. Nested/global bindings and receivers are restored on completion, return and error. - The snapshot, imperative body, return propagation, graph dependencies, transactions and rollback are those of the explicit form. The body is never re-run merely because an input or class population later changes.
- A named noniterable source, including
broken = null, raisesTypeError("broken is not iterable"); callable sources are not invoked. - Nonqualifying
for values:headers retainSyntaxError("Expected 'of' in for statement")at line 1, column 11; existing explicit-loop and body diagnostics remain unchanged.
for Task:
it.done = true
Normative detail: implicit iterator indented loops and the unchanged explicit-loop entries in the root specification.
defdefines a function in the state; a function with noreturnyieldsnull.def name(params) => expressionis exactly a named block containingreturn expression; methods and parameter annotations use the same form.- Accepted NUC 32 optionally places that expression in a genuinely indented body after
=>; it preserves the same sole-return block and every accepted parameter spelling. - NUC 18 specifies
def name amount => expressionas exactlydef name(amount) => expressionfor one untyped ordinary identifier parameter, including methods andinit. - NUC 19 specifies
def name amount:followed by an indented suite as exactlydef name(amount):with that same suite. - NUC 20 specifies
def name amount: int => expressionas exactlydef name(amount: int) => expressionfor one ordinary identifier parameter and one existing ordinary-identifier annotation, including methods andinit. - NUC 24 describes
def name amount: int:followed by a real indented suite as exactlydef name(amount: int):with that same suite, including methods andinit. - Accepted NUC 27 adds optional
def name left, right => expression, exactly equivalent todef name(left, right) => expression, including methods andinit. - NUC 28 adds optional
def name left, right:with a real indented body, exactly equivalent todef name(left, right):with that same body, including methods andinit. - NUC 29 adds optional typed/mixed multiple-parameter named arrows, for example
def name left: int, right: int => expression, exactly equivalent todef name(left: int, right: int) => expression, including methods andinit. - NUC 30 separately adds optional typed/mixed multiple-parameter indented blocks, for example
def name left: int, right:with exactly the body ofdef name(left: int, right):, including methods andinit. - The legacy comma-bearing multiple-parameter arrow guard requires the complete immediate sequence
Identifier (Colon Identifier)? (Comma Identifier (Colon Identifier)?)+ Arrowon the same logical header line. At least one annotation identifies NUC29's new typed/mixed forms; entirely untyped comma lists remain NUC27 behavior. The linear non-consuming guard allocates nothing and skips no separators, indentation or comment-induced logical breaks. - NUC 37 adds an additional, optional untyped bare-arrow guard: after unchanged
Def Identifier, the entire prefix must beIdentifier Identifier Identifier* Arrow. Require at least two ordinary names with no annotations or commas, consuming nothing, allocating no parameter names and skipping no logical layout. This does not replace or relax NUC27's comma grammar or any typed/mixed/block guard. - The multiple-parameter block guard shares the complete-list scan: NUC28's untyped lists and NUC30's separate typed/mixed lists may end in the suite
Colon. Its complete immediate grammar isIdentifier (Colon Identifier)? (Comma Identifier (Colon Identifier)?)+ Colon. Require immediateNewlineorIndentand then a realIndentafter only normal newline/semicolon layout;:;never qualifies. The final colon and all layout/body tokens are left for the existing suite parser. - A final untyped parameter's following colon belongs to the suite, not the parameter's annotation parser. A final typed parameter has a separate annotation colon/name and suite colon. Failed complete lookahead consumes nothing; existing malformed parenthesized annotations keep their diagnostics.
- The single-parameter typed-arrow guard requires immediate
Identifier,Colon,Identifier,Arrowtokens after the required definition name. The parameter name andtype_name: Some(annotation)metadata are unchanged; the annotation is not a resolved variable or a new runtime type constraint. - The typed-block guard requires immediate
Identifier,Colon,Identifier,Colontokens. The next token isNewlineorIndent, and the first other token after only newline/semicolon layout isIndent; the guard consumes nothing before the existing parameter and suite parsers. - For the single-parameter untyped forms, a bare identifier must be immediately followed by
=>, or by:whose body starts with a logical newline/indent and supplies a realIndentafter normal newline/semicolon layout. The colon guard only looks ahead; the existing suite parser consumes the body. - No logical newline, semicolon or comment-induced logical break is skipped within a bare header. Blank/comment lines before an indented body retain the existing layout rules.
- All parenthesized definitions remain available, including
def add(left, right) => left + right,def add(left: int, right: int) => left + rightand typed/untypeddef add(left, right):alternatives with the same indented body. Nullary, multiline-parameter, inline and brace-suite definitions keep their parentheses, as do calls; typed single/multiple-parameter indented blocks have the optional spellings below. - Bare inline/braced or missing-indent blocks, trailing bare commas, defaulted/destructured/variadic parameters, dotted/union/generic/nullable/keyword/dollar/literal annotations, anonymous colon blocks, return annotations and call-parenthesis omissions are not added; class and anonymous parameter lists keep their existing grammar.
- NUC18/20 single-parameter arrows and NUC19/24's exact untyped/typed indented-colon guards are unchanged; named return-block lowering, parameter metadata/order, argument binding, runtime behavior and canonical rendering remain those of the parenthesized counterparts.
- Braces after a named arrow are object literals, not statement blocks. Parenthesized expressions may span physical lines, starting either on the header line or in the optional NUC32 real-indented body.
- A call in an assignment depends on the function and its arguments.
- Redefining a function updates existing dependents.
- A named function and a variable binding under the same name replace one another; reads and calls both use the latest binding.
- Named function references stay live when aliased, returned, or passed as callbacks.
- Static Math method reads are not callable references;
Math.clampretains that limitation, as specified by NUC 21. - Accepted NUC 33 keeps
Math.smoothstepsubject to the same unsupported method-read limitation. - Accepted NUC 35 keeps
Math.smootherstepsubject to that same limitation; it adds only a static call, not a callable method value. - Calls through variables, list items, and object properties depend on the callable's storage location.
- A null callable, an unassigned callable property, or a callable deleted during propagation leaves its dependent result null until rebound. Other non-callable values raise
TypeError. .valuefreezes the function definition, not the state read when its body executes.- Functions may recurse and may have multiple
returnstatements.
def generate number => number * 10
random = 10
number = generate(random)
100; afterrandom = 20,200.
def double amount => amount * 2
double(3)is6;double(5)is10, with the same named return-block AST and canonical rendering asdef double(amount) => amount * 2.
scale = 1
def area width height => width * height * scale
width = 3
height = 4
result = area(width, height)
assert(result, 12)
scale = 2
assert(result, 24)
width = 5
assert(result, 40)
- This is the executable reference's exact paired
Nucleoid preserves bare multiple parameter arrow relationshipsexample using NUC37's optional comma-free header;def area width, height => width * height * scaleanddef area(width, height) => width * height * scaleremain valid and behavior-equivalent. - Reuse the existing named return block and expression-body parser, with no new lexer/public AST/runtime types, capture, parameter-count bound or canonical spelling.
def f left, right, => left, missing types such asdef f left, right: => left, multiple-parameter blocks without real indentation, bare inline/braced suites and logical header breaks retainSyntaxError("Expected '(' but found identifier 'left'")at line 1, column 7; unsupported prefixes are not consumed. NUC30 separately adds real-indented typed/mixed blocks without changing this arrow guard.def f left, right =>givesSyntaxError("Unexpected end of input")at line 1, column 21; a final newline without a real body givesSyntaxError("Unexpected end of line")at line 2, column 1. Named-arrow braces remain objects; the existing inline body beginning with(may span physical lines. NUC32 separately permits the real-indented body below.- Full grammar and error positions are in the authoritative bare multiple-parameter named arrows section.
scale = 1
def area width height => width * height * scale
width = 3
height = 4
result = area(width, height)
assert(result, 12)
scale = 2
assert(result, 24)
width = 5
assert(result, 40)
- This is the exact executable
Nucleoid preserves comma-free named arrow relationshipscounterpart intests/reference.md, paired with the unchanged accepted comma-bearing program. - Consume only checked untyped names and reuse the entire named-arrow body path: ordered untyped parameters and the same named sole-return block, canonical source, graph and runtime. NUC32's indented expression, leading objects and header-line parentheses remain available.
- Methods,
init, nesting/redefinition, binding/arity, receivers/super/adoption, noncapture, locals, aliases/snapshots, reactive dependencies, transactions/rollback and resource limits are unchanged; no new parameter cap, lexer, public AST or API is added. - This optional arrow form does not add mixed comma/whitespace separators, comma-free typed/mixed lists, parenthesized or anonymous comma omission, class/call changes, defaults/rest/destructuring, return annotations or bare nullary definitions. NUC37 itself adds no colon suites; the separate NUC40 section below adds their wholly untyped real-indented counterpart. Existing comma/typed/parenthesized/block forms remain supported.
- Unsupported prefixes such as
def f left right, third => left,def f left right: int => leftanddef f left right: return leftfall through at the originalleft, retainingSyntaxError("Expected '(' but found identifier 'left'")at line 1, column 7. - Exact
def f left right =>givesSyntaxError("Unexpected end of input")at line 1, column 20; a final newline without a real body givesSyntaxError("Unexpected end of line")at line 2, column 1. Body grammar and diagnostics remain inherited; only physical columns shortened by an omitted comma move. - Full grammar, exact errors and executable traces are in the authoritative comma-free bare named arrows section. The implementation was independently accepted with no per-case token increase.
def increment amount: int => amount + 1
def text value: str => value
assert(increment(4), 5)
assert(text("ok"), "ok")
- This is the executable reference's paired typed-arrow example;
def increment(amount: int) => amount + 1anddef text(value: str) => valueremain valid and behavior-equivalent.
scale = 2
def area width: number, height: number => width * height * scale
result = area(3, 4)
assert(result, 24)
scale = 3
assert(result, 36)
- This is the executable reference's exact paired
Nucleoid preserves bare typed multiple parameter arrow relationshipsexample;def area(width: number, height: number) => width * height * scaleremains valid and exactly equivalent. - Any annotation positions may mix with untyped identifiers in a list of at least two parameters;
def scaled left: number, right, factor: number => (left + right) * factorkeeps each existingSome(annotation)/Nonein order. Only ordinaryColon Identifierannotations qualify. - The complete-list guard consumes nothing before the existing parameter parser and named return-block lowering. It adds no type checking, capture, parameter cap, public AST/runtime/generator/API or resource-bound change.
def f left: int, right, => left, missing annotations, logical breaks and bare inline/braced blocks retainSyntaxError("Expected '(' but found identifier 'left'")at line 1, column 7. NUC29 itself adds no blocks; NUC30 separately extends the shared scanner to typed/mixed blocks with real indentation. NUC28 untyped blocks and all single guards remain exact.def f left: int, right =>givesSyntaxError("Unexpected end of input")at line 1, column 26; a final newline without a real body givesSyntaxError("Unexpected end of line")at line 2, column 1. Leading named-arrow braces remain objects; a parenthesis beginning on the header line may continue over physical lines. NUC32 separately permits a real-indented expression without changing this header guard.- Arity/shadowing, null callable deferral, non-callable errors, receivers/init/super, reactivity, live aliases,
.valuesnapshots, redefinition, graph dependencies, rollback and inherited noncapturing errors are unchanged. - Full grammar, exact errors and positions are in the authoritative bare typed multiple-parameter named arrows section.
scale = 2
def area width: number, height: number =>
width * height * scale
result = area(3, 4)
assert(result, 24)
scale = 3
assert(result, 36)
- This is the exact executable
Nucleoid preserves indented named arrow relationshipscounterpart intests/reference.md. - It is exactly the accepted colon spelling
def area width: number, height: number:with the sole body statementreturn width * height * scale; both that form and inline=> width * height * scaleremain valid. - Preserve parenthesized nullary/single/multiple/annotated lists and every accepted bare single/multiple spelling, including methods, nested definitions and
init. Bare-nullarydef f =>anddef f:remain invalid. - Non-consumingly require immediate newline/indent and then a real indent after only newline/semicolon layout. A same-line semicolon after
=>cannot qualify, even before a later indent. Failed qualification preserves the original inline error and position. - Skip normal body layout, parse one unchanged expression, skip trailing newline/semicolon layout and require its closing dedent. Semicolon-only layout lines and trailing semicolons are permitted;
value; otheror another body statement is rejected, not silently dropped. - This is not an arbitrary statement suite or an implicit last-statement return. Colon suites and anonymous arrow/function bodies retain all their existing grammar; anonymous arrows gain no indented-body path.
- Blank/comment lines, CRLF/tabs and parenthesized multiline expressions use existing layout. Named braces remain object expressions; anonymous braced arrows remain statement blocks.
- The native REPL buffers a lexical named header ending in its only actual arrow, including a trailing comment. Blank-line commit and stdin EOF execute the complete input; structured errors allow subsequent recovery. Arrow text in literals/comments, inline arrows and direct/anonymous expressions keep their old interaction.
- Exact
def f x =>\nxstill givesSyntaxError("Unexpected end of line")at line 2, column 1. Exactdef f x =>\n x\n x + 1instead givesSyntaxError("Expected the end of a block but found identifier 'x'")at line 3, column 5. - Binding, annotations, receivers/init/super/adoption, null deferral, non-callable errors, noncapture, live references/snapshots, state propagation, graph/reasoning, transactions and resource bounds remain unchanged.
- Full layout, exact errors, legacy alternatives and executable traces are in the authoritative indented named arrow expressions section.
def double amount:
offset = 1
return amount * 2 + offset
assert(double(3), 7)
assert(double(5), 11)
- The same suite under
def double(amount):remains valid; literal locals, multiple statements and explicit returns use the existing block behavior. - A body without
returnyieldsnull, never an implicit last-expression return. def f amount:without an indented body,def f amount: int:at EOF without a body, and bare inline/brace suites retainSyntaxError("Expected '(' but found identifier 'amount'")at line 1, column 7.
def double amount: int:
offset = 1
return amount * 2 + offset
assert(double(3), 7)
assert(double(5), 11)
- This is the executable reference's exact paired example; the same suite under
def double(amount: int):remains valid with the same complete AST and canonical rendering. - The ordinary annotation remains
Some("int")metadata, not a lookup, dependency or new runtime type constraint; missing/null/extra/string arguments retain their existing binding. - Require the immediate header prefix and a real indent. Blank/comment lines and normal semicolons after the initial body newline are allowed; header-line breaks/semicolons, inline/braced bare suites and comments-only bodies do not qualify.
- The NUC19 untyped suite colon still belongs to the suite, never to an annotation. NUC18/20 arrows, explicit typed alternatives, class/anonymous lists, receivers/init/super, no implicit return, live references/snapshots, transactions and resource limits are unchanged.
- Inherited parameter-dependent local and nested noncapturing failures remain paired, not repaired by this spelling.
scale = 2
def area width, height:
return width * height * scale
result = area(3, 4)
assert(result, 24)
scale = 3
assert(result, 36)
- This legacy colon example remains equivalent to
def area(width, height):with the same body. The executableNucleoid preserves bare multiple parameter block relationshipscounterpart now uses NUC32's equivalent indented arrow for this sole return; the colon syntax is still supported. - Two or more untyped ordinary identifiers retain their order and
type_name: None; the complete named block AST and canonical rendering are identical to the parenthesized form. There is no parameter-count cap. - The body uses the existing suite grammar, including multiple statements, nested definitions, branches and existing inner inline/braced statements. Explicit returns, bare returns and no return keep their existing semantics; the latter two return
null. def f left, right:without a real indent, malformed annotations, trailing bare commas, inline/braced bare suites,:;and logical header breaks keepSyntaxError("Expected '(' but found identifier 'left'")at line 1, column 7. NUC30 separately adds typed/mixed multiple indented headers, not inline/braced bare suites.- After the qualifying header, four-space-indented
return left +)keepsSyntaxError("Unexpected ')'")at line 2, column 19;return @keepsSyntaxError("Unexpected character '@'")at line 2, column 12. - Full grammar, exact errors and positions are in the authoritative bare multiple-parameter indented block definitions section. Receiver/init/super behavior, shadowing, arity, live references, definition snapshots, redefinition, dependencies, graph keys, transactions and resource limits are unchanged.
scale = 1
def area width height:
return width * height * scale
width = 3
height = 4
result = area(width, height)
assert(result, 12)
scale = 2
assert(result, 24)
width = 5
assert(result, 40)
- NUC 40 adds this exact executable
Nucleoid preserves comma-free block relationshipscounterpart intests/reference.md.def area width, height:anddef area(width, height):with the same body remain valid and equivalent; the legacy comma-bearing control above is retained. - Require the complete
Identifier Identifier Identifier* Colonprefix afterdefand the ordinary name, with at least two wholly untyped identifiers and every parameter comma omitted or none. Share the identifier-run scan with the arrow guard without changing its arrow-only meaning; allocate/consume/skip nothing on failure. - Keep the required final colon for unchanged
suite(). Its next token must beNewlineorIndent, then only accepted newline/semicolon separators may precede a genuineIndent. Same-line:;, missing colon/indent and bare inline/braced suites do not qualify. - Ordered untyped parameters, full named block AST/metadata/canonical source, explicit/bare/no returns, receiver/init/super/adoption behavior, argument binding/shadowing/noncapture, aliases/snapshots and all live graph/rollback behavior are unchanged. This does not change inherited method lookup.
- Typed/mixed lists keep commas. Mixed omission, parenthesized/anonymous/call/class comma omission, defaults/rest/destructuring, return annotations and bare nullary headers are not added; all accepted forms, including NUC37 arrows, remain available.
def f left right:with no actual indented body,def f left right: return left, mixed separators/types and logical header breaks retainSyntaxError("Expected '(' but found identifier 'left'")at line 1, column 7. Body errors retain their physical positions.- Full grammar, exact errors and normative traces are in the authoritative comma-free bare indented blocks section.
scale = 2
def area width: number, height: number:
return width * height * scale
result = area(3, 4)
assert(result, 24)
scale = 3
assert(result, 36)
- This legacy colon example remains exactly equivalent to
def area(width: number, height: number):with the same body. The executableNucleoid preserves bare typed multiple parameter block relationshipscounterpart now uses NUC32's equivalent indented arrow for this sole return; the colon syntax is still supported. - Two or more ordinary identifier parameters may annotate any position using only the existing
Colon Identifiermetadata. At least one annotation describes NUC30's new forms; entirely untyped lists retain NUC28 behavior. Arbitrary undeclared ordinary annotation names need no lookup, dependency or enforcement. - The complete non-consuming allocation-free scan skips no logical header breaks. The suite colon needs immediate
NewlineorIndent, then a realIndentafter only normal newline/semicolon layout;:;never qualifies. Blank/comment lines remain normal suite layout. - Consume names and optional annotations in order, leaving the final suite colon and the entire body/layout for the unchanged suite parser. A final untyped parameter's colon is not an annotation; a final typed parameter needs both its annotation colon/name and suite colon.
- Preserve the full named block AST, metadata and canonical rendering, including local assignments, multiple statements, branches, nested definitions and ordinary inner inline/braced statements. Explicit, bare and absent returns retain their meanings; bare/absent returns yield
null, never an implicit final-expression return. def f left: int, right:without a real indent, inline/braced bare suites, trailing commas,:;, logical header breaks and unsupported type/parameter syntax keepSyntaxError("Expected '(' but found identifier 'left'")at line 1, column 7.def f(left: int, right:):keepsSyntaxError("Expected a type but found ')'")at line 1, column 25.- After a qualifying header, four-space-indented
return left +)keepsSyntaxError("Unexpected ')'")at line 2, column 19;return @keepsSyntaxError("Unexpected character '@'")at line 2, column 12. Other lexical/body/runtime errors and positions retain their existing rules. - Keep NUC24 single typed blocks, NUC28 untyped blocks, NUC29 arrows, every parenthesized alternative and calls. Arity/unchecked arguments, shadowing, null callable deferral/non-callable errors, noncapturing scopes, receivers/init/super/adoption/identity, reactive inputs, aliases/snapshots, redefinition, graph dependencies/reasoning, transactions/rollback and existing bounds remain unchanged.
- Full grammar and exact errors are in the authoritative bare typed multiple-parameter indented block definitions section.
- Three equivalent forms; parameters shadow outer names, including outer functions when the parameter is null or non-callable.
list.find(function(element) { return element == 3 })
list.find(element => { return element == 2 })
list.find(element => element == 1)
- Calls over class lists depend on the population and the properties they read.
Full detail: NUC 8, NUC 12, NUC 18, NUC 19, NUC 20, NUC 24, NUC 27, NUC 28, NUC 29, NUC 30, and NUC 32.
- A statement and every rule it triggers form one transaction.
- If anything throws, the whole transaction is rolled back and the state is exactly as before.
throwraises a value: a string, a number, or a resolved reference.- Blocks, including nested blocks, are single transactions.
- An instance rejected at creation is not registered and its name is not bound.
- Instances created earlier in a failing loop are rolled back too.
- A class-level rule that throws for any existing instance is not installed at all.
- Propagation that does not settle raises
TypeError("Propagation did not settle")and rolls back the transaction. - A caught failure restores the failing body's pending propagation and deletion tracking before the catch body runs. Work queued before the body is preserved, including across nested catches.
a = 5
if a > 5:
throw 'INVALID_VALUE'
- Assigning
a = 6throws; afterwardsais5.
- Accepted NUC 46 allows
tryand a complete existingcatchheader to omit the suite colon independently, only before a genuine indent. Colon-bearing indented, inline, semicolon-separated and braced forms remain valid. The wholeStmt::Try, defaulterrorbinding and runtime are shared. - This is the paired executable reference entry
Nucleoid preserves catch bindings and mixed exception suite forms, without its title comment. The inline pair keeps both colons; the two indented pairs demonstrate omission in each direction.
try: throw "INLINE"
catch issue: assert(issue, "INLINE")
try
throw "PAREN"
catch (problem):
assert(problem, "PAREN")
try:
throw "DEFAULT"
catch
assert(error, "DEFAULT")
- Complete parameter parsing precedes qualification. Default, ordinary-name
and parenthesized-name headers retain their accepted meanings; no filters,
catch expressions, multi-catch,
finallyor new scope/throw behavior. - Existing lexer layout and
has_indented_bodydecide whether a real body follows, before any layout is consumed. Blank/comment-only lines or a header-line semicolon do not suffice. Other header grammars are unchanged. - The native REPL buffers a complete lexical bare
tryheader, including a trailing comment, through its catch until blank-line commit or EOF. A standalonecatch, literal/comment text, identifier prefix or malformed header does not start that buffer; committed errors are still reported. - Savepoints restore failed-body state and pending work before recovery. Dependencies, rules, receivers, returns and reasoning remain the accepted behavior. Already implemented exceptions are baseline, not a pending NUC dependency. Exact grammar and errors are in the root contract.
- Independent evaluation accepted all 611 paired cases: eight use fewer lexer tokens, 603 are unchanged, and none increased. All 2,763 protected assertions executed and all 50 explicit expected returns matched.
- Built-in calls participate in the dependency graph like any other expression.
- Mutating a list re-evaluates its dependents.
Math.maxandMath.minpropagateNaN, including when an argument cannot be coerced to a number.- NUC 21 specifies static
Math.clamp(value, lower, upper); its proposal header records its status. - Numeric clamping is exactly the ordered
Math.min(Math.max(value, lower), upper)after existing numeric coercion, not range validation: reversed bounds yield the upper bound, equal bounds and infinities retain that composition's result, and signed zeros follow the same ordered min/max folds. - Numbers, literal
null, booleans, trimmed numeric strings, empty/singleton lists and dates retain their existing conversions; nonnumeric conversions and numericNaNin any of the first three positions yield numericNaN. - Each omitted first/second/third argument supplies numeric
NaN. Extra values are ignored numerically, but every argument expression is evaluated left to right and its reads remain dependencies. - Any supplied
Undefinedvalue, including an extra, defers the Math call; a dependent assignment storesnulluntil the missing property is defined. Existing live-null assignment handling is also unchanged; literalnullstill coerces numerically to zero. - Strict unknown identifiers still throw
ReferenceError("<name> is not defined")before dispatch. Existing transaction rollback and recovery remain intact. - Static namespace shadowing and ordinary
.Mathmembers are unchanged;Math.clampread as a value stays unsupported/undefined, not a callable reference. - This capability adds no bounds error, type enforcement or grammar change; other Math functions/constants and their exact errors are unchanged.
- NUC 22 specifies static
Math.lerp(start, end, weight); its proposal header records its status. - Interpolation intrinsically converts the first three values numerically, then
computes
delta = end - start,scaled = delta * weight,start + scaled, using exactly those ordinaryf64operations in order. It does not call a shadowableNumber()function or concatenate strings. - Weights below zero or above one extrapolate: there is no weight clamping, endpoint validation/reordering, midpoint/endpoint shortcut, fused operation, higher precision or alternative weighted formula.
- Equal/reversed endpoints, overflow, cancellation, infinities, numeric
NaNin any position and signed zeros follow that ordered arithmetic. In particular,0 + Infinity * 0andInfinity - Infinityyield numericNaN, not endpoints. - The existing numeric conversions above apply, including literal
nullas zero, booleans, trimmed strings, empty/singleton lists and millisecond dates. Nonnumeric conversion yields numericNaN, not a new type error. - Every omitted first/second/third interpolation input supplies numeric
NaN. Extras are ignored numerically, but all supplied expressions run exactly once left to right and all reads remain dependencies. - The unchanged any-
UndefinedMath gate includes extras. Live-null and deferred-read assignment handling, class/property recovery, strict argument errors and transactional rollback take precedence as before. - Static
Mathshadowing and ordinary.Mathmembers retain their existing resolution.Math.lerpread as a value is unsupported/undefined, not a first-class callable or alias; noNumberlookup dependency is introduced. Math.clamp,min,max,round, other Math members, syntax and public representations are unchanged. Unknown static methods andMath.random()retain their exact inherited errors and existing pre-dispatch undefined gate.- NUC 23 specifies static
Math.saturate(value)as exactly orderedMath.clamp(value, 0, 1), through the existing maximum fold followed by the existing minimum fold. - Convert the first value intrinsically with
Value::to_number, using numericNaNwhen omitted; do not call or track shadowableNumberorMath.clamp. - The existing numeric conversions, numeric
NaN, infinities, subnormal values and signed-zero bits retain that composition's behavior, without hostf64::clamp, input validation or endpoint shortcuts. - Every supplied expression runs once left to right, including numerically
ignored extras; their reads, effects and the any-
Undefinedgate remain. - Literal-null conversion does not override live-null/deferred assignments. Class rules, deletion/recovery, strict errors and rollback remain unchanged.
- Static
Mathshadowing and ordinary.Mathmembers retain their lookup.Math.saturateread as a value remains unsupported/undefined, not callable. - All other Math members, accepted syntax and public representations stay unchanged.
- Accepted NUC 33 defines only static
Math.smoothstep(lower, upper, value). Bounds precede the value; this is deliberately notMath.clamp's value/lower/upper order. - After the existing any-supplied-
Undefinedgate, intrinsically convert lower, upper and value, in order, withValue::to_number; each omission is numericNaN. Do not convert unused extras or invoke/track shadowableNumberorMath.saturate. - Compute
numerator = value - lower,denominator = upper - lower,normalize = numerator / denominator, then clamp with the existing maximum fold followed by minimum against numeric zero and one. - With that
t, compute separatesquare = t * t,scaled = 2.0 * t,falloff = 3.0 - scaled, thensquare * falloff. Do not fuse, reorder, shortcut endpoints, clamp the polynomial afterward or validate ranges. - Equal/reversed bounds, infinities, overflow, subnormals and signed zeros
follow the accepted normalization and cubic composition. Expected numeric
NaNuses classification; non-NaN bits, including zero bits, match the host composition rather than a portable sign promise. - Literal
nullconverts to zero intrinsically without overriding live-null or parameter/deferred assignment handling. Other nonnumeric conversions yield numericNaN, not new type errors. - Every provided expression, including extras, runs exactly once left to right;
effects, reads and dependencies remain. A supplied
Undefined, even an extra, defers before conversion; strict later unknown identifiers still throw. - Namespace/local shadowing, ordinary
.Mathmembers, wrappers, methods, initializers, class rules, property deletion/recovery and rollback are unchanged. No first-classMath.smoothstepalias or new lookup is added. - The intrinsic reuses the private numeric clamp without calling public Math methods. All other Math behavior, accepted syntax, APIs and inherited scope/resource boundaries remain unchanged.
| Object | Members |
|---|---|
Object |
Object() -- a plain object, not an instance of any type |
Boolean |
Boolean(value) |
Number |
Number.MAX_INTEGER |
Math |
pow, sqrt, floor, round, max, min, clamp (NUC 21), lerp (NUC 22), saturate (NUC 23), smoothstep(lower, upper, value) (accepted NUC 33), smootherstep(lower, upper, value) (accepted NUC 35), remap(start, end, targetStart, targetEnd, value) (accepted NUC 39) |
String |
String.fromCharCode; instance charAt, length, lower, replace, replaceAll (accepted NUC 42), repeat, split |
Date |
Date(), Date(string), Date(number), Date.now(), Date.parse(); instance getTime, getYear, toDateString |
List |
push, pop, filter, map, flatMap (accepted NUC 41), reduce, find, some, every, slice, sort, join, length |
Class |
the global list of declared types; Class.length |
prices = [10, 20, 30]
rate = 2
doubled = prices.map(p => p * rate)
-
doubled[2]is60; afterrate = 3,90; afterprices.push(40),doubled[3]is120. -
Class lists support the same functions and depend on the population.
open = Task.filter(t => not t.done).length
- Regular expressions support
.test(...)and may be used in any condition.
- Accepted NUC 42 adds the string-instance method
replaceAll(search, replacement), without changing accepted syntax. - Replace literal, non-overlapping matches left to right; replacement strings have no regex, dollar or backslash expansion. Return a new string.
- Empty search visits Unicode scalar boundaries, including start/end; an empty
receiver has one boundary. Existing indexing and empty
splituse the same scalar model, not UTF-16 units. - Snapshot the receiver before arguments; evaluate every supplied expression
once left to right, including extras. Then coerce the first two values as
replacedoes; omissions spell"undefined". - Default/literal values do not imply binding reads. Actual null/undefined reads keep inherited deferred assignment behavior, dependencies, skipped arguments on nullish receivers and recovery. No simulated reads are added.
- Global/property/class rules, ordinary scopes/noncapture, frozen/live functions,
.value, transactional rollback and source positions remain unchanged. - Checked output sizing or failed output reservation raises
TypeError("Replaced string is too large"), without an arbitrary cap. - Existing
replacestays first-only;split,joinand custom functions, properties or instance methods namedreplaceAllretain their old behavior. Native method properties are not first-class. StaticString.replaceAllstill raisesTypeError("String.replaceAll is not a function")after arguments.
labels = ["first name", "last name", "first name"]
normalized = labels.map(label => label.replaceAll(" ", "_"))
assert(normalized, ["first_name", "last_name", "first_name"])
labels.push("display name")
assert(normalized, ["first_name", "last_name", "first_name", "display_name"])
labels = ["given name", "last name"]
assert(normalized, ["given_name", "last_name"])
- This is the paired executable entry
Nucleoid normalizes live text recordsintests/reference.md. The normative root section and its five appended entries define results, Unicode, reactivity, class rules and failure rollback; native regressions cover the call/coercion boundaries.
reading = -3
floor = 0
ceiling = 10
bounded = Math.clamp(reading, floor, ceiling)
assert(bounded, 0)
reading = 12
assert(bounded, 10)
ceiling = 8
assert(bounded, 8)
- This is the sealed executable reference example in
tests/reference.md. - All three inputs remain live through the ordinary builtin call path.
- The
Reactive numeric clampingsection and its five paired entries innucleoid.spec.mddefine the behavior; NUC 21 explains the deliberately ordered contract.
Full detail: NUC 10.
start = 0
end = 20
weight = 0.25
position = Math.lerp(start, end, weight)
assert(position, 5)
end = 40
assert(position, 10)
weight = 0.5
assert(position, 20)
- This is the sealed executable reference example in
tests/reference.md. - The start, end and weight remain live through the ordinary builtin call path.
- The
Reactive numeric interpolationsection and its five paired entries innucleoid.spec.mddefine the behavior; NUC 22 explains the deliberately ordered contract.
reading = -0.2
fraction = Math.saturate(reading)
assert(fraction, 0)
reading = 0.6
assert(fraction, 0.6)
reading = 1.4
assert(fraction, 1)
- This is the sealed executable reference example in
tests/reference.md, omitting only its title comment. - The input stays live; the fixed numeric zero/one bounds are not dependencies.
- The authoritative saturation section and its five executable entries define the behavior.
- NUC 23 explains the ordered unit-interval contract.
lower = 0
upper = 8
value = 2
unit = Math.saturate((value - lower) / (upper - lower))
eased = Math.smoothstep(lower, upper, value)
assert(unit, 0.25)
assert(eased, 0.15625)
value = 6
assert(eased, 0.84375)
upper = 16
assert(eased, 0.31640625)
- This is the sealed executable reference entry in
tests/reference.md, omitting only its title comment. - The
unitnormalization remains an independent asserted control. - The authoritative smoothstep section and its five executable entries define this accepted behavior.
- Accepted NUC 33 records the lower/upper/value order, exact maximum-then-minimum normalization and separate ordered cubic operations.
lower = 0
upper = 8
value = 2
unit = Math.saturate((value - lower) / (upper - lower))
eased = Math.smootherstep(lower, upper, value)
assert(unit, 0.25)
assert(eased, 0.103515625)
value = 6
assert(eased, 0.896484375)
upper = 16
assert(eased, 0.27520751953125)
- This is the sealed executable reference entry in
tests/reference.md, omitting only its title comment;unitremains an independent live control. - Accepted NUC 35 adds only static
Math.smootherstep(lower, upper, value)beside unchanged cubic smoothstep. The authoritative quintic section and its five entries specify the accepted contract. - After the existing any-supplied-
Undefinedgate, convert lower, upper and value intrinsically withValue::to_number, in order; each omission is numeric NaN. Do not invoke or track shadowableNumberorMath.saturate. - Compute separate
numerator = value - lower,denominator = upper - lower,normalize = numerator / denominator, then use the unchanged maximum-fold followed by minimum-fold unit clamp to obtaint. - Compute separate
square = t * t,cube = square * t,scaled = 6.0 * t,offset = scaled - 15.0,weighted = t * offset,polynomial = weighted + 10.0, thencube * polynomial, in that order. - Do not expand/reassociate the polynomial, fuse operations, use
powfor host clamp, validate/reorder bounds, shortcut endpoints or clamp the result. Rounded polynomial results can overshoot[0, 1]. - Equal/reversed/infinite/overflow bounds, NaNs, subnormals and zero bits follow the exact accepted composition. Compare expected NaNs by classification and all other numeric bits, including zeros, against host controls; no portable NaN-payload or zero-sign promise is added.
- Literal null converts numerically to zero without overriding live-null assignment or parameter deferral. Other values keep existing conversion; nonnumeric conversions yield numeric NaN rather than new type errors.
- Every supplied expression runs once left to right, including extras. Extra values are unconverted but keep reads, effects, strict errors and the supplied-Undefined gate, including deferred property deletion/recovery.
- State/local Math shadowing, ordinary members, unsupported method reads, typed wrappers, call frames, receivers, class rules and transactional rollback remain unchanged. Immediate intrinsic dependencies differ from the emulation's unit node, while controls and transitive behavior agree.
- The mathematical quintic has smoother endpoint transitions than the cubic; no exact floating-point derivative claim is made. All sibling Math methods, accepted syntax, public APIs and inherited scope/resource limits remain.
class Signal
signal = Signal()
signal.sample = 1.75
whole = Math.floor(signal.sample)
fraction = Math.fract(signal.sample)
assert(whole, 1)
assert(fraction, 0.75)
signal.sample = -1.5
assert(whole, -2)
assert(fraction, 0.5)
signal.sample = 4.125
assert(fraction, 0.125)
- This is the sealed
tests/reference.mdentry, omitting only its title comment;whole = Math.floor(signal.sample)stays independent. - Accepted NUC 36 adds only unshadowed static
Math.fract(value). The authoritative fractional-part section and its five entries define the accepted contract. - After Math's unchanged any-supplied-
Undefinedgate, convert the first value intrinsically withValue::to_number; omission supplies numeric NaN. - Compute separate ordinary
floor = first.floor()andfirst - floor, in that order. The acceptedvalue - Math.floor(value)remains available. Do not use hostf64::fract, truncation, remainder, sign correction, absolute value, conversion skips, normalization or result clamping. - Negative fractions subtract floor:
-1.25yields0.75. Tiny negative input-0.00000000000000000001can round to exactly one; the result has no strict[0, 1)guarantee. Infinities yield numeric NaN by subtraction. - Expected NaNs use classification; every other result, including zero, matches independent accepted arithmetic/floor controls by bits, without a portable NaN-payload or zero-sign promise.
- Literal null converts to zero without overriding live assignment or parameter-null deferral. Numbers, booleans, strings, lists and dates retain existing conversion; nonnumeric values produce numeric NaN, not new errors.
- Every supplied expression runs once left to right, including ignored extras. Extra values are not converted, but retain effects, reads, dependencies, strict errors and the supplied-Undefined gate, deletion and recovery.
- Intrinsic conversion and host floor never invoke or track shadowable
NumberorMath.floor. State/local Math shadowing and ordinary.Mathmembers keep lookup; readingMath.fractas a value remains unsupported/ Undefined, not a first-class callable. - Wrappers, frames, receivers, scopes, class rules, property deletion,
graph transactions, rollback, error positions and recovery are unchanged.
Unknown methods and
Math.random()retain their exact inherited errors. - No sibling Math arm/helper/control, accepted syntax, parser, lexer, AST, generator, CLI implementation, API/representation, dependency, version, MSRV or resource limit changes. Inherited scope limitations remain.
start = 2
end = 10
sample = 4
weight = Math.inverseLerp(start, end, sample)
assert(weight, 0.25)
sample = 6
assert(weight, 0.5)
start = 0
assert(weight, 0.6)
end = 12
assert(weight, 0.5)
sample = 18
assert(weight, 1.5)
- This is the sealed
tests/reference.mdentry, omitting only its title comment. - Accepted NUC 38 adds only unshadowed static
Math.inverseLerp(start, end, value). The authoritative inverse-interpolation section and its five entries specify the accepted contract. - After Math's unchanged any-supplied-Undefined gate, including extras,
intrinsically convert start, end and value with
Value::to_number. The dispatcher already converts start; each omitted input is numeric NaN. - Compute separate ordinary
numerator = value - start,denominator = end - start, thennumerator / denominator, in that order. The accepted(value - start) / (end - start)remains available. - Do not clamp, smooth, validate or reorder ranges, factor, fuse, scale to avoid overflow or shortcut endpoints or zero width. Descending ranges and results below zero or above one are intentional.
- Equal finite endpoints give ordinary NaN or signed infinity. Nonfinite
inputs, span overflow, cancellation, underflow, subnormals and signed zeros
retain exactly that composition. The overflow span from
-Number.MAX_VALUEtoNumber.MAX_VALUEwith value zero yields zero, not0.5. - Expected NaNs compare by classification; every non-NaN result, including zero, matches independent accepted binary subtraction/division controls by bits. No portable NaN-payload or zero-sign promise is added.
- Literal null converts to zero without overriding live assignment or parameter-null deferral. All Value kinds retain their existing numeric conversion; nonnumeric values yield numeric NaN, not new errors.
- Every supplied expression runs once left to right, including expressions after Undefined. Ignored extras are neither converted nor used, but retain reads, effects, dependencies, strict failures, deferral and rollback.
- Intrinsic conversion never resolves, invokes or tracks shadowable Number
or Math methods. State/local Math shadowing and ordinary
.Mathmembers keep lookup; readingMath.inverseLerpas a value stays unsupported/ Undefined, not a callable reference. - Wrappers, frames, receivers, aliases, scopes, per-instance class rules,
property deletion/recovery and graph transactions remain unchanged.
Strict unknown arguments keep
ReferenceError("<name> is not defined"); unknown Math methods andMath.random()retain their exact inherited errors. - No sibling Math arm/helper/control, accepted syntax, parser, lexer, AST, generator, CLI implementation, API/representation, namespace, dependency, version, MSRV, edition or resource bound changes. Inherited limitations remain.
- New intrinsic RHS ASTs and immediate dependency graphs may differ from emulation; non-RHS source/ASTs, assertions, independent controls, values, transitive reads/effects/errors, returns and executed coverage are protected.
start = 2
end = 10
targetStart = 10
targetEnd = 30
sample = 4
mapped = Math.remap(start, end, targetStart, targetEnd, sample)
assert(mapped, 15)
sample = 6
assert(mapped, 20)
targetStart = 0
assert(mapped, 15)
targetEnd = 40
assert(mapped, 20)
sample = 18
assert(mapped, 80)
- This is the sealed
tests/reference.mdentry, omitting only its title comment. - Accepted NUC 39 adds only unshadowed static
Math.remap(start, end, targetStart, targetEnd, value)as an accepted intrinsic. - The authoritative range-remapping section and its five executable entries specify the accepted contract.
- Retain Math's any-supplied-Undefined gate, including extras, and its existing first-input conversion for start. Convert end, targetStart, targetEnd and value intrinsically in that order; each omission supplies numeric NaN.
- Compute six separate ordinary operations:
numerator = value - start,denominator = end - start,weight = numerator / denominator,delta = targetEnd - targetStart,scaled = delta * weight,result = targetStart + scaled, in that order. - The accepted nested spelling
Math.lerp(targetStart, targetEnd, Math.inverseLerp(start, end, value))remains available. It evaluates target arguments first; the new call uses its listed five-argument order. The sealed counterparts use pure reads. - Do not clamp, smooth, validate, reorder, factor, fuse, raise precision, rescale or shortcut endpoints, equal targets or zero source width. Descending ranges and extrapolation are intentional.
- NaNs, infinities, overflow, underflow, cancellation, subnormals and signed
zeros retain that exact numeric composition. An overflowing source span
can normalize to zero, not a midpoint. Equal targets with infinite weight
give NaN; overflowing target span at weight
0.25can give positive infinity. - NaNs compare by classification; every other result, including zero, matches independent accepted arithmetic by bits, with no portable zero-sign promise.
- Intrinsic literal null converts to zero without overriding live assignment or parameter-null deferral. All Value kinds keep existing conversion; nonnumeric values yield numeric NaN, not new errors.
- Every supplied expression runs once left to right, including expressions after Undefined and extras. Extra values are not converted or used, but retain effects, reads, dependencies, strict errors, deletion and recovery.
- Intrinsic conversion never resolves, invokes or tracks shadowable Number
or Math methods. State/local Math shadowing and ordinary
.Mathmembers keep lookup. ReadingMath.remapremains unsupported/Undefined, not callable. - Wrappers, frames, receivers, aliases, scopes, per-instance class rules, property deletion/recovery, error positions, transactions and rollback remain.
- Strict missing arguments retain
ReferenceError("missing is not defined"). NumericMath = 7retainsTypeError("number.remap is not a function"). Unknown Math methods andMath.random()retain their inherited errors. - Literal
Math.remap(at EOF givesSyntaxError("Unexpected end of input")at line 1, column 12; a final newline moves that EOF to line 2, column 1. - Existing Math arms/helpers/constants/conversions, accepted syntax, parser, lexer, AST, generator, CLI implementation, public APIs, dependencies, versions, MSRV, edition and resource bounds remain unchanged.
- Protect historical source/full ASTs and new non-RHS source/typed metadata, independent inverseLerp controls, ordered assertions, expected returns and actual coverage, not intentional new-RHS/immediate-graph differences.
- Accepted NUC 41 specifies
list.flatMap(callback)andClassName.flatMap(callback)as the same shared read-only list query. - Snapshot the receiver before arguments, evaluate every supplied expression
left to right (including unused extras), then validate the first value as
a function. A missing or non-function callback raises exactly
TypeError("flatMap expects a function"), including on empty inputs. - Invoke once per snapshotted item, in order, with only that item as the
argument, as for
map. Missing callback parameters remainnull; no index, receiver argument, closure capture or automaticthisis added. - Flatten a returned list exactly one level, preserving deeper lists, duplicates and object/function identities; other values contribute one item, and an empty returned list contributes none. The query itself never writes its receiver, although callbacks retain their normal effects.
- Returning null or undefined does not manufacture a read. Actual null reads still affect enclosing assignment settlement; missing/deleted reads retain their existing behavior. A null/undefined receiver keeps ordinary method routing, including skipping argument evaluation.
- Callback/member reads, population changes, redefinitions,
.valuesnapshots, obsolete dependency removal, errors, rollback and recovery use the existing machinery. A frozen function keeps its definition, not a frozen copy of state read from its body. - The executable reference entry
Nucleoid flat maps live related collectionstracks team-tag updates. The root specification also covers ordered projection, list mutation, population growth, snapshots and failed redefinition. map,reduce,concatand custom object/instance/global bindings namedflatMapremain available unchanged. Native methods do not gain first-class bound-property lookup, recursion, a depth option or a feature-specific cap.- The accepted map/reduce/concat composition can read a null intermediate through its reducer; native flat mapping adds no artificial read to emulate that effect. Intentional runtime-call RHS rewrites change AST and canonical graph source; full-AST/graph-source equality is not promised.
why referenceselects the reference and its transitive dependencies.affects referenceselects its transitive dependents, not the reference itself.reference |> whyis equivalent towhy reference; pipelines compose left to right.model |> whyselects the current model, excluding pending nodes and reasoning observers.- A selection is an ordered list of steps with
node,holds,rule,state, andfromfields. stateis"stated"for an independent fact or"derived"for a relationship or class-level rule.- List functions such as
map,find, andsomecan inspect the steps.
a = 1
b = a + 2
c = b * 2
trace = why c
trace[0]namesc, holds6, and derives from["b"].
- A reasoning assignment follows both values and graph structure.
- Declaring, replacing, or deleting a relationship refreshes its derivation and impact, even when its value stays the same.
- Subscriptions are replaced on every evaluation, including reasoning evaluated through a function or a class-level property rule.
- An empty impact selection still follows its source; an empty model selection still follows model membership.
- Replacing an observer with an ordinary relationship adds it to the model; restoring the reasoning expression removes it again.
- An explanation of an absent property is empty and fills in when the property is defined.
- Deleting an explained source empties its selection; defining it again restores the explanation.
- A name that was never defined raises
ReferenceError, as an ordinary read does.
a = 1
exposure = affects a
b = a + 1
c = b * 2
exposurechanges from[]to steps forbandcwithout changinga.- After
b = 0,exposureis empty again.
- Reasoning observers are neither selected nor traversed by graph walks; observing a model does not change its derivation or impact.
.valuefreezes a selection just as it freezes any other reading.- Structural refreshes use the propagation queue and wait for queued upstream changes to settle.
- A failed transaction restores the selection, its subscriptions, and its pending work.
- A caught failure discards only structural refreshes queued by its failing body, retaining work queued before it.
- Only selections, pipelines,
model,why, andaffectsare implemented; the other NUC 11 operations remain proposals.
Full detail: NUC 11.
Messages are exact and are part of the observable behaviour of the language.
| Condition | Message |
|---|---|
| Reading an undefined variable | <name> is not defined |
| Throwing an undefined reference | <name> is not defined |
| Using a deleted variable or instance | <name> is not defined |
| Creating an instance of an undeclared type | <Name> is not defined |
| Writing through an undefined instance property | <path> is not defined |
| Writing through an undefined class-level reference | <Name>.<property> is not defined |
Reading .value of an undefined property |
<path> is not defined |
| Declaring a variable with no value | Missing definition |
| Condition | Message |
|---|---|
| An assignment that would close a dependency cycle | Circular Dependency |
| A type declaration that would close an inheritance cycle | Circular Inheritance |
| Deleting an instance that still has properties | Cannot delete object '<id>' |
Using value as a property name |
Cannot use 'value' as a property |
| Calling an unknown function of a built-in or list | <Object>.<name> is not a function |
Missing or non-function flatMap callback, even on an empty receiver |
flatMap expects a function |
| Repeated string output is too large to represent or allocate | Repeated string is too large |
| Condition | Message |
|---|---|
| Declaring a class-level rule in a non-class block | Cannot define class declaration in non-class block |
| A character that begins no token | Unexpected character '<character>' |
| A token other than the one required | Expected <what> but found <what> |
| An unsupported compound target | Invalid compound assignment target |
| A block or template that is never closed | Unterminated block, Unterminated template expression |
| Nesting or a chain past the runtime's limit | Expressions are nested too deeply, Expression has too many operands |
| A postfix chain or a compound path beyond its limit | Expression has too many parts |
- Every error records a line and column: a syntax error at the token the parser stopped at, a runtime error at the start of the top-level statement that was running.
- The position is part of how an error is reported, not part of what it is. What a
catchbinds is<Kind>: <message>with no position, so a program can compare against it wherever the statement is written.
ReferenceError: e is not defined (line 3, column 1)
Full detail: NUC 9.
name = expression variable assignment
name += expression compound assignment; also -=, *=, /=, %=
name = a; name = b several statements on one line
name: type declaration without value -- rejected
name.property = expression property assignment
$Type.property = expression class-level rule
delete name remove a variable, property, or instance
class Name empty type declaration
class Name(param: type) empty type with parameters; no implicit properties
class Name(param: type): type with a constructor
this.param = param
class Name: type with a typed attribute
attribute: type
def init(param: type):
this.attribute = param
class Sub: Super subtype
def init(a, b):
super(a)
this.b = b
super zero-argument super() expression
super(arguments) explicit parent-constructor arguments
if condition: conditional
statement
else if condition:
statement
else condition: optional direct alternative, indented only (NUC 43)
statement
elif condition: equivalent existing Else alias, indented only
statement
else:
statement
elif: existing unconditional Else alias
statement
else existing colon-free final indented suite
statement
elif same unconditional alias without a colon
statement
for name of source: iteration
for name in source: equivalent explicit iteration
for source: indented iteration with local it
statement
def name(params) => expression single-return function
def name(params) => optional indented single expression (NUC 32)
expression
def name left, right => expression untyped multiple-parameter named arrow
def name left right => expression optional comma-free untyped named arrow (NUC 37)
def name left right: optional comma-free untyped block (NUC 40)
def name left: int, right => expression typed/mixed multiple-parameter arrow (NUC 29)
def name amount => expression one untyped parameter (NUC 18)
def name amount: type => expression one typed parameter (NUC 20)
def name(params): block function
statement
def name left, right: untyped multiple parameters, indented only (NUC 28)
statement
def name left: int, right: typed/mixed multiple parameters, indented only (NUC 30)
statement
def name amount: one untyped parameter, indented only (NUC 19)
statement
def name amount: type: one typed parameter, indented only (NUC 24)
statement
{ statement; statement } block
record = { amount, label } object shorthand (candidate NUC 17)
record = {amount: amount unit: "C"} optional explicit-property comma (NUC 44)
throw value raise a value
return expression yield from a block or function
assert(actual, expected) existing equality-check helper
assert: actual, expected optional statement spelling (Accepted NUC 45)
name.value read without depending
items.flatMap(callback) ordered one-level projection (Accepted NUC 41)
Math.remap(start, end, targetStart, targetEnd, value) unclamped static remapping (Accepted NUC 39)
Name[0] Name["id"] Name.find(...) address an instance
value[start:end] value[-n:] slice, negative counts from the end
why reference derive a live explanation
affects reference inspect live downstream impact
reference |> why |> affects compose reasoning stages
model |> why inspect the current model
Copyright 2020 Nucleoid
This document is licensed under the Apache License, Version 2.0. See LICENSE for the full text.