diff --git a/docs/specs/pbs/3. Core Syntax Specification.md b/docs/specs/pbs/3. Core Syntax Specification.md index 3a136967..30e5dc0d 100644 --- a/docs/specs/pbs/3. Core Syntax Specification.md +++ b/docs/specs/pbs/3. Core Syntax Specification.md @@ -140,12 +140,21 @@ For overloaded functions, visibility is per-signature; each exported overload mu ```ebnf BarrelFile ::= BarrelItem* EOF -BarrelItem ::= BarrelFnItem | BarrelTypeItem | BarrelServiceItem | BarrelConstItem | BarrelCallbackItem +BarrelItem ::= BarrelFnItem + | BarrelStructItem + | BarrelContractItem + | BarrelErrorItem + | BarrelEnumItem + | BarrelServiceItem + | BarrelConstItem + | BarrelCallbackItem BarrelVisibility ::= 'mod' | 'pub' BarrelFnItem ::= BarrelVisibility 'fn' Identifier ParamList ReturnAnn? ';' - -BarrelTypeItem ::= BarrelVisibility 'type' Identifier ';' +BarrelStructItem ::= BarrelVisibility 'struct' Identifier ';' +BarrelContractItem ::= BarrelVisibility 'contract' Identifier ';' +BarrelErrorItem ::= BarrelVisibility 'error' Identifier ';' +BarrelEnumItem ::= BarrelVisibility 'enum' Identifier ';' BarrelServiceItem ::= BarrelVisibility 'service' Identifier ';' BarrelConstItem ::= BarrelVisibility 'const' Identifier ';' BarrelCallbackItem ::= BarrelVisibility 'callback' Identifier ';' @@ -158,6 +167,7 @@ Rules: - Duplicate function entries are forbidden by full function signature. - Every barrel item must resolve to an existing top-level declaration in module scope. - `fn` barrel entries MUST use the same signature surface as `fn` declarations. +- Type declarations in `mod.barrel` MUST use their specific declaration kind: `struct`, `contract`, `error`, or `enum`. - Labels are part of the declaration surface, but do not participate in function identity or barrel matching. - Only `pub` symbols may be imported from another module. - Multiple `fn` barrel entries with the same identifier are allowed only when signatures differ (overload set). @@ -170,6 +180,9 @@ Example: ```barrel pub fn func(a: int) -> int; pub fn bla(b: int, c: int) -> (d: float, e: float); +pub struct Struct; +pub contract TickLike; +pub enum GameState; pub callback TickCb; ``` @@ -238,9 +251,11 @@ Rules: - `declare struct Name(...);` declares a heap-backed nominal user type with fields only. - `declare struct Name(...) { ... }` declares a heap-backed nominal user type with fields and methods. - Struct fields are declared positionally in the header and are mutable and accessible by default in v1 core. +- The enclosing struct name is in scope within its own field types, so self-referential headers such as `declare struct Node(next: optional Node);` are valid. - Struct method and `ctor` declarations belong only in the optional struct body. - Struct methods have an implicit `this` receiver and do not declare `this: Self` explicitly. - `ctor` declares a named factory for the enclosing struct type. +- A named `ctor` constructs its enclosing struct by initializing the fields of an implicit under-construction `this`. - Struct values are constructed only through `new Type(...)`. - `declare contract` bodies contain only function signatures. - A contract declaration introduces a nominal runtime-dispatchable method surface. @@ -440,9 +455,9 @@ OrExpr ::= AndExpr (('||' | 'or') AndExpr)* AndExpr ::= EqualityExpr (('&&' | 'and') EqualityExpr)* EqualityExpr ::= CompareExpr (('==' | '!=') CompareExpr)? -CompareExpr ::= CastExpr (('<' | '<=' | '>' | '>=') CastExpr)? +CompareExpr ::= AsExpr (('<' | '<=' | '>' | '>=') AsExpr)? -CastExpr ::= AddExpr ('as' TypeRef)* +AsExpr ::= AddExpr ('as' Identifier)? AddExpr ::= MulExpr (('+' | '-') MulExpr)* MulExpr ::= UnaryExpr (('*' | '/' | '%') UnaryExpr)* @@ -493,7 +508,8 @@ Rules: - `new Type(args...)` is the canonical struct construction surface. - `new Type.ctorName(args...)` is the canonical named-constructor surface. - Struct construction arguments are positional and follow the declared struct field order. -- `this` is an implicit receiver name available only inside struct method bodies. +- `as` is reserved in expressions for explicit contract-view conversion only; it does not denote a general cast surface in v1 core. +- `this` is an implicit receiver name available only inside struct method and `ctor` bodies. - `apply` is right-associative: `f1 apply f2 apply x` parses as `f1 apply (f2 apply x)`. - `f1 apply f2 apply f3 apply params` parses as `f1 apply (f2 apply (f3 apply params))`. - `f()` is exact surface sugar for `f apply ()`. @@ -508,6 +524,7 @@ Rules: - `bind(context, fn_name)` binds only the first parameter of `fn_name`. - The second operand of `bind` is a function identifier, not an arbitrary expression. - Mixing labeled and unlabeled tuple items in the same `TupleExpr` is a syntax error. +- Member selection of a struct or contract method is valid only as an immediate call target; bare method extraction such as `let m = s.compute;` is invalid. ## 11. Deterministic parser requirements @@ -923,7 +940,9 @@ declare struct Struct( ctor createWithSomethingSpecial(x: int, y: int) { let _ = y; - return new Struct(x, "special", 3.0); + this.a = x; + this.b = "special"; + this.c = 3.0; } } diff --git a/docs/specs/pbs/4. Static Semantics Specification.md b/docs/specs/pbs/4. Static Semantics Specification.md index d57d554b..636884c3 100644 --- a/docs/specs/pbs/4. Static Semantics Specification.md +++ b/docs/specs/pbs/4. Static Semantics Specification.md @@ -159,10 +159,14 @@ Rules: - Assigning a struct value copies the reference, not the underlying field storage. - Struct fields are mutable and accessible by default in v1 core. - A struct method declared in a struct body has an implicit receiver binding `this` of type `Self`. -- `this` is valid only inside struct method bodies. +- `this` is valid only inside struct method and `ctor` bodies. - `Self` is valid only in struct method and `ctor` declarations and denotes the enclosing struct type. -- A named `ctor` declared in a struct body is not a method and does not introduce `this`. -- `ctor` bodies return the enclosing struct type and may use explicit `return`. +- The enclosing struct name is in scope inside its own field declarations, enabling self-referential field types. +- A named `ctor` declared in a struct body is not a method, but it does introduce an implicit under-construction `this`. +- A `ctor` has no declared return annotation and is not a `fn`. +- A `ctor` completes by falling off the end of its body after initializing the enclosing struct instance. +- Every field of the enclosing struct must be definitely assigned on every completing `ctor` path. +- `return;` and `return expr;` are both invalid inside `ctor` bodies. - Methods declared in a struct body belong to the direct method namespace of that concrete struct type. - `receiver.method(...)` on a concrete struct receiver resolves only against methods declared directly in that struct body. - `receiver.ctorName(...)` is never valid on a concrete struct value. @@ -173,6 +177,7 @@ Rules: - An `implements` block has no independent visibility; its observability follows the visibility of the struct, and the contract must also be nameable at the use site. - A struct value may be coerced to a contract value when exactly one visible `implements Contract for Struct ...` applies. - Contract coercion may happen by explicit `expr as ContractType` or by contextual typing in assignments, parameter passing, and returns. +- `as` in expression position is reserved for explicit contract coercion only; no other cast semantics exist in v1 core. - A contract value carries the underlying struct reference together with the selected contract implementation for runtime dispatch. - Calling `contractValue.method(...)` uses dynamic dispatch through the contract value. - Calling `structValue.contractMethod(...)` is not valid unless that method is also declared directly on the struct. @@ -191,7 +196,7 @@ declare struct Struct(a: int) { } ctor createWithSomethingSpecial(x: int) { - return new Struct(x); + this.a = x; } } @@ -393,6 +398,7 @@ Rules: - `expr.method` over a concrete struct receiver does not search visible contract implementations. - `TypeName.ctorName` is not a general member access surface; named constructors are entered only through `new TypeName.ctorName(...)`. - `expr.method` is a valid method-call target when the static type of `expr` is a contract value whose contract declares method `method`. +- Bare extraction of a struct or contract method as a value is invalid in v1 core because methods are not first-class. - `expr.name` is valid when the static type of `expr` is a multi-slot named output tuple containing label `name`. - For named output tuples, the projected member type is the type of the corresponding output slot. - Projection is label-based, not position-based. @@ -500,10 +506,12 @@ At minimum, deterministic static diagnostics are required for: - duplicate enum case labels in `declare enum`, - duplicate enum case identifiers in `declare enum`, - invalid mixed implicit/explicit enum case identifiers, -- invalid `this` usage outside struct method body, +- invalid `this` usage outside struct method or `ctor` body, - invalid `Self` type usage outside struct method or `ctor` declarations, - invalid struct method declaration shape, - invalid `ctor` declaration shape, +- invalid `return` inside `ctor`, +- incomplete field initialization on a completing `ctor` path, - duplicate `implements Contract for Struct` pair, - `implements` declared outside the owner module of the struct, - incompatible or missing contract method implementation, @@ -560,6 +568,7 @@ At minimum, deterministic static diagnostics are required for: - member access on a missing struct field, - member access on a missing struct method, - member access on a missing contract method, +- bare method extraction from a struct or contract value, - member projection on a single-slot carrier value, - invalid optional intrinsic member call, - member projection on a missing named output label.