08 — Grammatik-Skizze: Types, Tags, TypeFns und Refinements¶
Status: Grammatikentwurf, Parser-Kombinator-kompatibel
1. Ziel¶
Diese Grammatik ist absichtlich knapp. Die normative Quelle sollte später die benannte Parser-Kombinator-Grammatik sein. Diese EBNF ist die lesbare Projektion. Zwei Wahrheiten wären schlecht. Eine Wahrheit plus Anzeigeformat ist akzeptabel. Sogar zivilisiert.
2. Top-Level Items¶
Item ::= TypeDecl
| TagDecl
| ProtocolDecl
| ServiceDecl
| TypeFnDecl
| FunctionDecl
| ProvideDecl
| ExternDecl
| ImportDecl
3. Type Declaration¶
TypeDecl ::= "type" MetaPrefix? TypeName TypeParams? ":" TypeBody Refinements?
| "type" TypeName "=" TypeExpr
TypeBody ::= StructBody
| EnumBody
| UnionBody
| AliasBody
StructBody ::= "struct" "{" FieldDecl* "}"
EnumBody ::= "enum" "=" VariantDecl+
UnionBody ::= "union" "=" TypeExpr ("|" TypeExpr)*
Beispiel:
4. Tag Declaration¶
TagDecl ::= "tag" MetaPrefix? TagName TagKind? Refinements?
TagKind ::= ":" "enum" "=" TagVariant+
| ":" TagDomainRef
TagVariant ::= "|" TagName Refinements?
Beispiele:
5. Type Parameters¶
TypeParamList ::= "[" TypeParam ("," TypeParam)* "]"
TypeParam ::= TypeParamQualifier? Name Constraint?
TypeParamQualifier ::= "phantom" | "reified"
Constraint ::= ":" ConstraintExpr
Beispiele:
type ManagedUser[phantom State: UserState] : struct { ... }
def describe[reified T](value: T) -> str = ...
Ungültig:
6. TypeFn Declaration¶
TypeFnDecl ::= "typefn" TypeFnName TypeFnParams? "=" TypeLevelExpr
TypeFnParams ::= "(" TypeFnParam ("," TypeFnParam)* ")"
TypeFnParam ::= Name ":" ConstraintExpr
Beispiel:
TypeFns mit Type-Parametern:
Ob TypeFnParams und TypeParamList syntaktisch getrennt bleiben, ist Parser-Design. Semantisch gilt:
7. Refinements¶
Refinements ::= Refinement+
Refinement ::= ":>" TypeLevelExpr
MetaPrefix ::= "<{" MetaField* "}>"
MetaField ::= Identifier ":" TypeLevelExpr
Beispiele:
8. Type-Level Expressions¶
TypeLevelExpr ::= TagRef
| TypeRef
| TypeFnCall
| MetaRecord
| Literal
| TypeLevelIf
| TypeLevelMatch
MVP kann TypeLevelIf und TypeLevelMatch auf TypeFns beschränken.
9. Name Resolution¶
Die Grammatik erkennt Formen. Die Semantik prüft Symbolarten.
`Local` in Value-Expression:
Fehler, wenn SymbolKind.tag.
`Local` als Argument für Share(policy: SharePolicy):
ok, wenn Local ∈ SharePolicy.
`User` in Value-Type-Position:
ok, wenn SymbolKind.type.
10. Parser-Kombinator-Hinweis¶
Die ausführbare Grammatik sollte in Parser-Kombinator-Syntax geschrieben und daraus als EBNF/Markdown projiziert werden.
Beispiel, konzeptionell:
auto tagDecl = rule("TagDecl",
seq(
tok("tag"),
opt(metaPrefix),
tagName,
opt(tagKind),
many(refinement)
)
);
Die Spec sollte später die benannte Regel TagDecl referenzieren, nicht eine zweite handgepflegte BNF-Wahrheit aufbauen. Niemand braucht zwei auseinanderlaufende Grammatiken. Nicht einmal Menschen, und die sammeln sonst wirklich alles.