From bf019714d4ee6df5e6cc0e93555fd2a286dd63d2 Mon Sep 17 00:00:00 2001 From: Luke Gareth Ribchester Date: Wed, 7 Feb 2024 20:31:27 +0100 Subject: [PATCH 1/4] docs(core): reformat `Semantics.md` This document reformats `Semantics.md` without changing its content. Signed-off-by: Luke Gareth Ribchester --- pact/Pact/Core/Semantics.md | 242 ++++++++++++++++++++++++++++++------ 1 file changed, 207 insertions(+), 35 deletions(-) diff --git a/pact/Pact/Core/Semantics.md b/pact/Pact/Core/Semantics.md index 584c6fb4e..ff267617c 100644 --- a/pact/Pact/Core/Semantics.md +++ b/pact/Pact/Core/Semantics.md @@ -1,6 +1,7 @@ # Pact Semantics document -This document should serve as a record of known pact semantics, covering as much of the language as possible, including corner cases, and semantic divergences between core and prod pact. +This document should serve as a record of known pact semantics, covering as much of the language as possible, including +corner cases, and semantic divergences between core and prod pact. Bullet points that are not filled are potential tasks @@ -9,18 +10,17 @@ Bullet points that are not filled are potential tasks EBNF of Pact, Roughly speaking ### Legend -| Usage | Notation | Meaning | -| ------------- | :--------: | ------- | -| concatenation | | One token immediately follows another -| alternation | \| | One or the order -| optional | \[ ... \] | none or once -| repetition | \{ ... \} | none or many -| grouping | \( ... \) | Groups tokens to match +| Usage | Notation | Meaning | +|---------------|:---------:|---------------------------------------| +| concatenation | | One token immediately follows another +| alternation | \| | One or the order +| optional | \[ ... \] | none or once +| repetition | \{ ... \} | none or many +| grouping | \( ... \) | Groups tokens to match ### Lexical Syntax - ``` lower ::= 'a' | ... | 'z' (Ascii only, no unicode lower case) upper ::= 'A' | ... | 'Z' (Ascii only, no unicode lower case) @@ -45,23 +45,25 @@ TICKSTRING ::= '\'' alpha {alpha | digit | '-' | '_'} ### Keywords -| | | | -| :--------: | :--------: | :--------: | -| let | let* | if | -| defun | defcap | defconst | -| defschema | deftable | defpact | -| defproperty | property | invariant | -| interface | module | bless | -| implements | use | true | -| false | lambda | and | -| or | load | @doc | -| @model | @event | @managed | -| step | step-with-rollback | enforce | -| enforce-one | with-capability | create-user-guard | -| try | error | progn | +| | | | +|:-----------:|:------------------:|:-----------------:| +| let | let* | if | +| defun | defcap | defconst | +| defschema | deftable | defpact | +| defproperty | property | invariant | +| interface | module | bless | +| implements | use | true | +| false | lambda | and | +| or | load | @doc | +| @model | @event | @managed | +| step | step-with-rollback | enforce | +| enforce-one | with-capability | create-user-guard | +| try | error | progn | #### Productions + TODO: fill + ``` ::= { } @@ -73,10 +75,10 @@ TODO: fill ``` - ## Modules ### Module Lexing and Parsing Implementation + - [x] `module` keyword - [x] Governance forms: keyed governance (via Keyset name string) or cap governance bare name resolution - [x] use, bless and implements forms @@ -85,6 +87,7 @@ TODO: fill - [x] defpacts ### Module name resolution + - [x] Defuns - [x] DefConsts - [x] DefCaps @@ -94,13 +97,15 @@ TODO: fill - [x] Internal defs produce the right dependency tree (Needs test) ### Module evaluation semantics + - [x] Module governance eval (Note: the way we do this via interpretation is still not concrete) - - [x] Cap governance - - [x] Keyset Governance + - [x] Cap governance + - [x] Keyset Governance ## Top level forms ### Defuns + - [x] Defun name resolution - [x] Defconst name resolution - [x] Defcap name resolution @@ -111,6 +116,7 @@ TODO: fill ## Environment ### EvalEnv + - [x] Message signatures - [x] Pactdb in env - [x] Tx hash @@ -125,6 +131,7 @@ TODO: fill - [x] Purity (now in pactdb) ### EvalState + - [x] Loaded names (called `Loaded` currently instead of `RefStore` and `RefState`) - [x] Call stack - [x] Capabilities environment @@ -133,217 +140,266 @@ TODO: fill - [x] Defpact environment `PactExec` ### Environment semantic changes -- RefStore no longer in `EvalEnv`. We do not resolve natives that way, but we potentially could for repl natives in modules. It is TBD -- `InRepl` flag is not necessary currently. This may change, but it serves as a way to fork on-chain errors in prod-pact. + +- RefStore no longer in `EvalEnv`. We do not resolve natives that way, but we potentially could for repl natives in + modules. It is TBD +- `InRepl` flag is not necessary currently. This may change, but it serves as a way to fork on-chain errors in + prod-pact. ## Intepreter + - [X] Stable interpreter API - [ ] EvalResult and EvalInput-type API ## Base Builtins ### at + - [x] Object case implemented - [x] List case implemented - [ ] Gas ### base64-decode + - [x] implemented - [ ] Gas ### base64-encode + - [x] implemented - [ ] Gas ### bind + - [x] implemented - [ ] Gas ### chain-data + - [x] implemented - [ ] Gas ### compose + - [x] implemented - [ ] Gas ### concat + - [x] implemented - [ ] Gas ### constantly + - [x] implemented - [ ] Gas ### contains + - [x] String case implemented - [x] List case implemented - [x] Object case implemented - [ ] Gas ### define-namespace + - [x] implemented - [x] repl test - [ ] Gas ### distinct + - [x] implemented - [ ] Gas ### enforce + - [x] implemented - [ ] Gas - ### enforce-one + - [x] implemented - [ ] Gas - ### enforce-pact-version + TODO: Do we want this still??? ### enumerate + - [x] implemented 2-arg overload - [x] implemented 3-arg overload - [ ] Gas ### filter + - [x] implemented - [ ] Gas - ### fold + - [x] implemented - [ ] Gas ### format + - [x] implemented - [ ] Gas ### hash + - [x] implemented - [ ] Gas ### identity + - [x] implemented - [ ] Gas ### if + - [x] implemented - [ ] Gas ### int-to-str + - [x] implemented - [ ] Gas - ### is-charset + - [x] implemented - [ ] Gas ### length + - [x] object case implemented - [x] string case implemented - [x] list case implemented - [ ] Gas ### list + DELETED FROM EXISTENCE ### list-modules + TODO: (potentially) DELETED FROM EXISTENCE ### make-list + - [x] implemented - [ ] Gas ### map + - [x] implemented - [ ] Gas ### pact-id + - [x] implemented - [ ] Gas ### pact-version + TODO: (potentially) DELETED FROM EXISTENCE ### public-chain-data + - Todo: provide in base loaded ### read-decimal + - [x] implemented - [ ] Gas ### read-integer + - [x] implemented - [ ] Gas ### read-msg + - [x] implemented both overloads - [ ] Gas ### read-string + - [x] implemented - [ ] Gas ### remove + - [x] implemented - [ ] Gas ### resume + - [x] implemented - [ ] Gas ### reverse + - [x] implemented - [ ] Gas ### reverse + - [x] list case implemented - [x] object case implemented - [ ] Gas ### str-to-int + - [x] list case implemented - [x] object case implemented - [ ] Gas ### str-to-list + - [x] implemented - [ ] Gas ### take + - [x] string case implemented - [x] list case implemented - [ ] Gas ### try + - [x] implemented - [ ] Gas ### tx-hash + - [x] implemented - [ ] Gas ### typeof + - [x] implemented - [ ] Gas ### where + - [x] implemented - [ ] Gas ### yield + - [x] implemented both overloads (yield and yield to chain) - [ ] Gas ### zip + - [x] implemented both overloads (yield and yield to chain) - [ ] Gas ### create-table + - [x] Local Bypass Check (NOTBYPASSED) - [x] Enforcing blessed hashes - [x] Guarded db access (Module admin or calledByModule) @@ -353,6 +409,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### describe-keyset + - [x] Enforced top level only - [x] Mock PactDb implementation - [ ] ChainwebPactDb implementation @@ -360,6 +417,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### describe-module + - [x] Local only - [x] Enforced top level only - [x] Mock PactDb implementation @@ -368,6 +426,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### fold-db + - [x] Local Bypass Check (BYPASS) - [x] Enforcing blessed hashes - [x] Guarded db access (Module admin or calledByModule) @@ -377,6 +436,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### insert + - [x] Local Bypass Check (NOTBYPASSED) - [x] Enforcing blessed hashes - [x] Guarded db access (Module admin or calledByModule) @@ -386,6 +446,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### keylog + - [x] Local only - [x] Local Bypass Check (BYPASS) - [x] Enforcing blessed hashes @@ -396,6 +457,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### keys + - [x] Local Bypass Check (BYPASS) - [x] Enforcing blessed hashes - [x] Guarded db access (Module admin or calledByModule) @@ -405,6 +467,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### read + - [x] Local Bypass Check (BYPASS) - [x] Enforcing blessed hashes - [x] Guarded db access (Module admin or calledByModule) @@ -414,6 +477,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### select + - [x] Local Bypass Check (BYPASS) - [x] Enforcing blessed hashes - [x] Guarded db access (Module admin or calledByModule) @@ -423,6 +487,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### txids + - [x] Local only - [x] Local Bypass Check (BYPASS) - [x] Enforcing blessed hashes @@ -433,6 +498,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### txlog + - [x] Local only - [x] Local Bypass Check (BYPASS) - [x] Enforcing blessed hashes @@ -443,6 +509,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### update + - [x] Local Bypass Check (NOTBYPASSED) - [x] Enforcing blessed hashes - [x] Guarded db access (Module admin or calledByModule) @@ -452,6 +519,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### with-default-read + - [x] Local Bypass Check (BYPASS) - [x] Enforcing blessed hashes - [x] Guarded db access (Module admin or calledByModule) @@ -461,6 +529,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### with-read + - [x] Local Bypass Check (BYPASS) - [x] Enforcing blessed hashes - [x] Guarded db access (Module admin or calledByModule) @@ -470,6 +539,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### write + - [x] Local Bypass Check (NOTBYPASSED) - [x] Enforcing blessed hashes - [x] Guarded db access (Module admin or calledByModule) @@ -481,54 +551,65 @@ TODO: (potentially) DELETED FROM EXISTENCE ## Time Builtins ### add-time + - [x] implemented both overloads - [ ] Gas ### days + - [x] implemented both overloads - [ ] Gas ### diff-time + - [x] implemented both overloads - [ ] Gas ### format-time + - [x] implemented - [ ] Gas ### hours + - [x] implemented both overloads - [ ] Gas ### minutes + - [x] implemented both overloads - [ ] Gas ### parse-time + - [x] implemented - [ ] Gas ### time + - [x] implemented - [ ] Gas - ## Operator Builtins ### != + - [x] implemented - [ ] Gas ### & + - [x] implemented - [ ] Gas ### * + - [x] implemented integer case - [x] implemented decimal case - [ ] Gas ### + + - [x] implemented integer case - [x] implemented decimal case - [x] implemented string case (concatenation) @@ -536,6 +617,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### - + - [x] implement - as negate (1-arg) for integer - [x] implement - as negate (1-arg) for decimal - [x] implement - as subtract (2-arg) for integer @@ -544,6 +626,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### < + - [x] implemented integer case - [x] implemented decimal case - [x] implemented string case @@ -551,6 +634,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### <= + - [x] implemented integer case - [x] implemented decimal case - [x] implemented string case @@ -558,6 +642,7 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### = + - [x] implemented integer case - [x] implemented decimal case - [x] implemented string case @@ -570,13 +655,15 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### > + - [x] implemented integer case - [x] implemented decimal case - [x] implemented string case - [x] implemented time case - [ ] Gas -### >= +### > = + - [x] implemented integer case - [x] implemented decimal case - [x] implemented string case @@ -584,106 +671,128 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### ^ + - [x] implemented integer case - [x] implemented decimal case - [x] Musl - [ ] Gas ### abs + - [x] implemented integer case - [x] implemented decimal case - [ ] Gas ### and + - [x] implemented with lazy eval - [ ] Gas ### and? + - [x] implemented with lazy eval - [ ] Gas ### ceiling + - [x] implemented base case - [x] implemented specific precision case - [ ] Gas ### dec + - [x] implemented - [ ] Gas ### exp + - [x] implemented integer case - [x] implemented decimal case - [x] Musl - [ ] Gas ### floor + - [x] implemented base case - [x] implemented specific precision case - [ ] Gas ### ln + - [x] implemented integer case - [x] implemented decimal case - [x] Musl - [ ] Gas ### log + - [x] implemented integer case - [x] implemented decimal case - [x] Musl - [ ] Gas ### mod + - [x] implemented integer case - [ ] Gas ### not + - [x] implemented - [ ] Gas ### not? + - [x] implemented - [ ] Gas ### or + - [x] implemented with lazy eval - [ ] Gas ### or? + - [x] implemented with lazy eval - [ ] Gas ### round + - [x] implemented base case - [x] implemented specific precision case - [ ] Gas ### shift + - [x] implemented - [ ] Gas ### sqrt + - [x] implemented integer case - [x] implemented decimal case - [x] Musl - [ ] Gas ### xor + - [x] implemented - [ ] Gas ### | (bitwise or) + - [x] implemented - [ ] Gas ### | (bitwise not) + - [x] implemented - [ ] Gas ## Keyset builtins ### define-keyset + - [x] Enforced top level only - [x] implemented 2-arg case - [x] implemented 1-arg case @@ -691,19 +800,23 @@ TODO: (potentially) DELETED FROM EXISTENCE - [ ] Gas ### enforce-keyset + - [x] implemented guard case - [x] implemented keyset name case - [ ] Gas ### enforce-keyset + - [x] implemented guard case - [x] implemented keyset name case - [ ] Gas ### keys-2, keys-all, keys-any + TODO: do we need this as a native? ### read-keyset + - [x] implemented guard case - [x] implemented keyset name case - [ ] Gas @@ -711,98 +824,122 @@ TODO: do we need this as a native? ## Capability Builtins ### compose-capability + - [x] implemented - [ ] Gas ### emit-event + - [x] implemented - [ ] Gas ### enforce-guard + - [x] implemented (Same as enforce-keyset, basically they're an alias) - [ ] Gas ### install-capability + - [x] implemented - [ ] Gas ### require-capability + - [x] implemented - [ ] Gas ### with-capability + - [x] implemented - [ ] Gas ## SPV Builtins ### verify-spv + - [ ] implemented - [ ] Gas ## Commitment builtins ### decrypt-cc20p1305 + TODO: do we want this in core? Can we delete? + - [ ] implemented - [ ] gas ### validate-keypair + TODO: do we want this in core? Can we delete? + - [ ] implemented - [ ] gas ## Guard Builtins + ### create-capability-guard + - [x] implemented - [ ] Gas ### create-module-guard + - [x] implemented - [ ] Gas ### create-pact-guard + - [x] implemented - [ ] Gas ### create-principal + - [x] implemented - [ ] Gas ### create-user-guard + - [x] implemented - [x] executed as sys only - [ ] Gas ## is-principal + - [x] implemented - [ ] Gas ## keyset-ref-guard + - [x] implemented - [ ] Gas ## typeof-principal + - [x] implemented - [ ] Gas ## validate-principal + - [x] implemented - [ ] Gas ## Zk Builtins ## pairing-check + - [x] implemented - [x] ensure points that are tested are on the curve - [ ] Gas ## point-add + - [x] implemented - [x] ensure points that are tested are on the curve - [ ] Gas ## scalar-mult + - [x] implemented - [x] ensure points that are tested are on the curve - [ ] Gas @@ -810,110 +947,145 @@ TODO: do we want this in core? Can we delete? ## REPL-only Builtins ### begin-tx + - [x] implemented ### bench + - [ ] implemented ### commit-tx + - [x] implemented ### continue=-pact + - [x] implemented all 4 overloads ### env-data + - [ ] TODO: string case? Do we want to parse json still??? what is the use case vs just an object? - [x] implemented object case ### env-dynref + TODO: may not be necessary with new fv + - [ ] implemented ### env-enable-repl-natives + - [ ] implemented ### env-entity + To be removed ### env-events + - [x] implemented ### env-exec-config + - [x] implemented ### env-gas + - [ ] implemented ### env-gaslimit + - [ ] implemented ### env-gaslog + - [ ] implemented ### env-gasmodel + - [ ] implemented ### env-gasprice + - [ ] implemented ### env-gasrate + - [ ] implemented ### env-hash + - [x] implemented ### env-keys + - [x] implemented ### env-namespace-policy + - [x] implemented ### env-sigs -- [x] implemented +- [x] implemented ### env-simulate-onchain + - [ ] This is a specific one related to error forking in pact. Likely we will implement it at a later date. ### expect + - [x] implemented ### expect-failure + - [x] implemented ### expect-that + - [x] implemented ### format-address + TODO: what are we doing about this? ### load + - [x] implemented ### mock-spv + - [ ] implemented ### pact-state + - [x] implemented 1-arg - [x] implemented 2-arg ### print + - [x] implemented ### rollback-tx + - [x] implemented ### sig-keyset + - [x] implemented ### test-capability + - [x] implemented ### typecheck + - [ ] TODO: implement using new typed core ### verify + - [ ] implemented ### with-applied-env + DELETED. Unnecessary with core's arch. From 189b2084fdad7c851a10d3a2a6cc4e69b9024803 Mon Sep 17 00:00:00 2001 From: Luke Gareth Ribchester Date: Wed, 7 Feb 2024 20:40:31 +0100 Subject: [PATCH 2/4] docs(core): update `Semantics.md` intro and legend table Signed-off-by: Luke Gareth Ribchester --- pact/Pact/Core/Semantics.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/pact/Pact/Core/Semantics.md b/pact/Pact/Core/Semantics.md index ff267617c..2fa6fbe83 100644 --- a/pact/Pact/Core/Semantics.md +++ b/pact/Pact/Core/Semantics.md @@ -1,23 +1,24 @@ # Pact Semantics document -This document should serve as a record of known pact semantics, covering as much of the language as possible, including -corner cases, and semantic divergences between core and prod pact. +This document should serve as a record of known Pact semantics, covering as much of the language as possible, including +corner cases, and semantic divergences between core and prod Pact. -Bullet points that are not filled are potential tasks +Bullet points that are not filled are potential tasks. ## Pact Syntax -EBNF of Pact, Roughly speaking +Approximate (in-progress) grammar definition of Pact +in [Extended Backus-Naur form (EBNF)](https://en.wikipedia.org/wiki/Extended_Backus–Naur_form). ### Legend | Usage | Notation | Meaning | |---------------|:---------:|---------------------------------------| -| concatenation | | One token immediately follows another -| alternation | \| | One or the order -| optional | \[ ... \] | none or once -| repetition | \{ ... \} | none or many -| grouping | \( ... \) | Groups tokens to match +| concatenation | | One token immediately follows another | +| alternation | \| | One or the other | +| optional | \[ ... \] | none or once | +| repetition | \{ ... \} | none or many | +| grouping | \( ... \) | Groups tokens to match | ### Lexical Syntax From 00c0529bb2f7a58eeb9fe66e1cd3449c74fb44f7 Mon Sep 17 00:00:00 2001 From: Luke Gareth Ribchester Date: Wed, 7 Feb 2024 21:05:54 +0100 Subject: [PATCH 3/4] docs(core): add approximate grammar definition Signed-off-by: Luke Gareth Ribchester --- pact/Pact/Core/Semantics.md | 285 +++++++++++++++++++++++++++++++++++- 1 file changed, 278 insertions(+), 7 deletions(-) diff --git a/pact/Pact/Core/Semantics.md b/pact/Pact/Core/Semantics.md index 2fa6fbe83..d4cee205b 100644 --- a/pact/Pact/Core/Semantics.md +++ b/pact/Pact/Core/Semantics.md @@ -23,8 +23,8 @@ in [Extended Backus-Naur form (EBNF)](https://en.wikipedia.org/wiki/Extended_Bac ### Lexical Syntax ``` -lower ::= 'a' | ... | 'z' (Ascii only, no unicode lower case) -upper ::= 'A' | ... | 'Z' (Ascii only, no unicode lower case) +lower ::= 'a' | ... | 'z' // Ascii only, no unicode lower case +upper ::= 'A' | ... | 'Z' // Ascii only, no unicode lower case special-symbol ::= '%' | '#' | '+' | '-' | '_' | '&' | '$' | '@' | '<' | '>' | '=' | '^' | '?' | '*' | '!' | '|' | '/' | '~' @@ -63,17 +63,288 @@ TICKSTRING ::= '\'' alpha {alpha | digit | '-' | '_'} #### Productions -TODO: fill +##### Verified +```bnf +// ::= { } +// +// ::= | | | +// +// ::= '(' module IDENT ')' +// +// ::= '(' interface IDENT ')' ``` - ::= { } - ::= | | | +##### In Progress - ::= '(' module IDENT ')' +```bnf +Program ::= ProgramList | ReplProgramList - ::= '(' interface IDENT ')' +ProgramList ::= TopLevel+ +ReplProgramList ::= ReplTopLevel+ + +TopLevel ::= Module + | Interface + | Expr + | Use + +ReplTopLevel ::= TopLevel + | "(" Defun ")" + | "(" DefConst ")" + | "(" ReplSpecial ")" + +ReplSpecial ::= "load" STR BOOLEAN + | "load" STR + +Governance ::= StringRaw + | IDENT + +StringRaw ::= STR + | TICK + +Module ::= "(" "module" IDENT Governance [MDocOrModel] ExtOrDefs ")" + +Interface ::= "(" "interface" IDENT [MDocOrModel] ImportOrIfDef ")" + +Ext ::= Use + | "(" "implements" ModQual ")" + | "(" "bless" StringRaw ")" + +Use ::= "(" "import" ModQual ImportList ")" + | "(" "import" ModQual STR ImportList ")" + +ExtOrDefs ::= (Def | Ext)+ + +Def ::= Defun + | DefConst + | Defcap + | Defschema + | Deftable + | DefPact + +ImportOrIfDef ::= (IfDef | Use)+ + +IfDef ::= IfDefun + | DefConst + | IfDefCap + | Defschema + | IfDefPact + +IfDefun ::= "(" "defun" IDENT [MTypeAnn] "(" MArgs ")" [MDocOrModel] ")" +IfDefCap ::= "(" "defcap" IDENT [MTypeAnn] "(" MArgs ")" [MDocOrModel] [MDCapMeta] ")" +IfDefPact ::= "(" "defpact" IDENT [MTypeAnn] "(" MArgs ")" [MDocOrModel] ")" + +ImportList ::= "[" ImportNames "]" + +ImportNames ::= IDENT+ + +Defun ::= "(" "defun" IDENT [MTypeAnn] "(" [MArgs] ")" [MDocOrModel] Block ")" +Defcap ::= "(" "defcap" IDENT [MTypeAnn] "(" [MArgs] ")" [MDocOrModel] [MDCapMeta] Block ")" +DefPact ::= "(" "defpact" IDENT [MTypeAnn] "(" MArgs ")" [MDocOrModel] Steps ")" +DefConst ::= "(" "defconst" IDENT [MTypeAnn] Expr [MDoc] ")" +Defschema ::= "(" "defschema" IDENT [MDocOrModel] SchemaArgList ")" +Deftable ::= "(" "deftable" IDENT ":" "{" ParsedName "}" [MDoc] ")" + +Steps ::= Step+ + +Step ::= "(" "step" Expr [MModel] ")" + | "(" "step" Expr Expr [MModel] ")" + | "(" "step-with-rollback" Expr Expr [MModel] ")" + | "(" "step-with-rollback" Expr Expr Expr [MModel] ")" + +MDCapMeta ::= Managed + | Event + +Managed ::= "@managed" (IDENT ParsedName)* + +Event ::= "@event" + +MArgs ::= MArg* + +MArg ::= IDENT ":" Type + | IDENT + +SchemaArgList ::= SchemaArg (SchemaArg) * + +SchemaArg ::= IDENT (":" Type)? + +Type ::= "[" Type "]" + | "module" "{" ModuleNames "}" + | IDENT "{" ParsedTyName "}" + | IDENT + +ModuleNames ::= ModQual ("," ModQual) * + +DocAnn ::= "@doc" STR + +DocStr ::= STR + +MModel ::= ModelAnn + +ModelAnn ::= "@model" "[" PactFVModels "]" + +MDocOrModel ::= DocAnn ModelAnn + | ModelAnn DocAnn + | DocAnn + | ModelAnn + | DocStr + +MDoc ::= DocAnn + | DocStr + +MTypeAnn ::= ":" Type + +Block ::= BlockBody + +BlockBody ::= Expr+ + +Expr ::= "(" SExpr ")" + | Atom + +SExpr ::= LamExpr + | LetExpr + | IfExpr + | TryExpr + | ProgNExpr + | GenAppExpr + | SuspendExpr + | CapExpr + +List ::= "[" [ListExprs] "]" + +ListExprs ::= Expr MCommaExpr? + +MCommaExpr ::= "," ExprCommaSep + | AppList + +ExprCommaSep ::= Expr ("," Expr) * + +LamExpr ::= "lambda" "(" LamArgs ")" Block + +IfExpr ::= "if" Expr Expr Expr + +TryExpr ::= "try" Expr Expr + +SuspendExpr ::= "suspend" Expr + +CapExpr ::= CapForm + +CapForm ::= "with-capability" Expr Block + | "create-user-guard" "(" ParsedName AppList ")" + +LamArgs ::= LamArg (LamArg)* +LamArg ::= IDENT (":" Type)? + + +LetExpr ::= LET_KEYWORD "(" Binders ")" Block + +Binders ::= ("(" IDENT MTypeAnn Expr ")")+ // Type annotation fault + +GenAppExpr ::= Expr AppBindList // Check * ? + +ProgNExpr ::= "progn" BlockBody + +AppList ::= Expr* // Was + + +AppBindList ::= (Expr | BindingForm)* + +BindingForm ::= "{" BindPairs "}" + +BindPair ::= STR ":=" MArg + | TICK ":=" MArg + +BindPairs ::= BindPair ("," BindPair)* + +Atom ::= Var + | Number + | String + | List + | Bool + | Operator + | Object + | "(" ")" + +Operator ::= "and" + | "or" + | "enforce" + | "enforce-one" + +Bool ::= "true" + | "false" + +Var ::= IDENT "." ModQual + | IDENT + | IDENT "::" IDENT + +ParsedName ::= IDENT "." ModQual + | IDENT + | IDENT "::" IDENT + +ParsedTyName ::= IDENT "." ModQual + | IDENT + +ModQual ::= IDENT "." IDENT + | IDENT + +Number ::= ["+" | "-"] NUM+ ["." NUM+] + +String ::= STR + | TICK + +Object ::= "{" ObjectBody "}" + +ObjectBody ::= FieldPairs + +FieldPair ::= STR ":" Expr + | TICK ":" Expr + +FieldPairs ::= FieldPair ("," FieldPair)* + +PactFVModels ::= PropExprList + +PropExprList ::= PropExpr* // Verify * + +PropExpr ::= PropAtom + | "(" PropExprList ")" + | "[" PropExprList "]" + +PropAtom ::= FVVar + | FVNumber + | FVString + | FVKeyword + | FVDelim + | FVBool + +FVKeyword ::= "let" + | "lambda" + | "if" + | "progn" + | "suspend" + | "try" + | "enforce" + | "enforce-one" + | "and" + | "or" + | "create-user-guard" + | "with-capability" + +FVDelim ::= "{" + | "}" + | ":" + | "," + +FVBool ::= "true" + | "false" + +FVNumber ::= ["+" | "-"] NUM+ ["." NUM+] + +FVString ::= STR + | TICK + +FVVar ::= IDENT "." ModQual + | IDENT + | IDENT "::" IDENT ``` ## Modules From 29a8fd876abc028466f868de6b93afcb8deb8cf6 Mon Sep 17 00:00:00 2001 From: Luke Gareth Ribchester Date: Fri, 3 May 2024 00:44:10 +0200 Subject: [PATCH 4/4] docs(core): refine grammar definition Signed-off-by: Luke Gareth Ribchester --- pact/Pact/Core/Semantics.md | 504 +++++++++++++++++++++++------------- 1 file changed, 328 insertions(+), 176 deletions(-) diff --git a/pact/Pact/Core/Semantics.md b/pact/Pact/Core/Semantics.md index d4cee205b..8e7d19caa 100644 --- a/pact/Pact/Core/Semantics.md +++ b/pact/Pact/Core/Semantics.md @@ -61,260 +61,424 @@ TICKSTRING ::= '\'' alpha {alpha | digit | '-' | '_'} | enforce-one | with-capability | create-user-guard | | try | error | progn | -#### Productions - -##### Verified +##### In Progress -```bnf -// ::= { } -// -// ::= | | | -// -// ::= '(' module IDENT ')' -// -// ::= '(' interface IDENT ')' +```javascript +/* Whitespace */ +CRLF="regexp:\R" +WHITE_SPACE="regexp:[ \n\t\f]" + +/* Comments */ +COMMENT="regexp:(;.*\n*)" + +/* Keywords */ +KEYWORD_BLESS="bless" +KEYWORD_ENFORCE="enforce" +KEYWORD_ENFORCE_ONE="enforce-one" +KEYWORD_IF="if" +KEYWORD_IMPLEMENTS="implements" +KEYWORD_INTERFACE="interface" +KEYWORD_LAMBDA="lambda" +KEYWORD_LET="regexp:(let\*?)" +KEYWORD_MODULE="module" +KEYWORD_BLOCK_INTRO="progn" +KEYWORD_STEP="step" +KEYWORD_STEP_WITH_ROLLBACK="step-with-rollback" +KEYWORD_SUSPEND="suspend" +KEYWORD_TRY="try" +KEYWORD_IMPORT="use" + +/* Keywords (Capabilities) */ +KEYWORD_CREATE_USER_GUARD="create-user-guard" +KEYWORD_WITH_CAPABILITY="with-capability" + +/* Keywords (Definitions) */ +KEYWORD_DEF_CAP="defcap" +KEYWORD_DEF_CONST="defconst" +KEYWORD_DEF_PACT="defpact" +KEYWORD_DEF_SCHEMA="defschema" +KEYWORD_DEF_TABLE="deftable" +KEYWORD_DEFUN="defun" + +/* Keywords (REPL) */ +KEYWORD_LOAD="load" + +/* Annotations */ +KEYWORD_DOC_ANNOTATION="@doc" +KEYWORD_EVENT_ANNOTATION="@event" +KEYWORD_MANAGED_ANNOTATION="@managed" +KEYWORD_MODEL_ANNOTATION="@model" + +/* Literals */ +STR="regexp:(\"([^\"\\]|\\\"|\\)*\")" +INTEGER="regexp:([+-]?[0-9]+)" +FLOATING_POINT="regexp:([+-]?([0-9]+\.[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?)" +TRUE="true" +FALSE="false" + +/* Identifiers */ +TICK="regexp:'[a-zA-Z][a-zA-Z0-9\-_]*" +IDENTIFIER="regexp:[a-zA-Z_][a-zA-Z0-9\-_]*" + +/* Operators (Arithmetic) */ +PLUS="+" +MINUS="-" +MULTIPLY="*" +DIVIDE="/" +POW="^" +ABS="abs" +CEILING="ceiling" +FLOOR="floor" +LOG="log" +LN="ln" +DECIMAL="dec" +EXP="exp" +MOD="mod" +ROUND="round" +SQRT="sqrt" + +/* Operators (Assignment) */ +BIND_ASSIGN=":=" + +/* Operators (Bitwise) */ +BITWISE_AND="&" +BITWISE_OR="|" +BITWISE_REVERSE="~" +BITWISE_SHIFT="shift" +BITWISE_XOR="xor" + +/* Operators (Logical) */ +AND="and" +AND_SHORT_CIRCUIT="and?" +NOT="not" +NOT_SHORT_CIRCUIT="not?" +OR="or" +OR_SHORT_CIRCUIT="or?" + +/* Operators (Relational) */ +EQUAL="=" +NOT_EQUAL="!=" +LESS_THAN="<" +LESS_THAN_OR_EQUAL="<=" +GREATER_THAN=">" +GREATER_THAN_OR_EQUAL=">=" + +/* Delimiters */ +PAREN_OPEN="(" +PAREN_CLOSE=")" +BRACE_OPEN="{" +BRACE_CLOSE="}" +BRACKET_OPEN="[" +BRACKET_CLOSE="]" +COLON=":" +COMMA="," +DOT="." +DYN_ACC="::" ``` -##### In Progress +#### Productions ```bnf -Program ::= ProgramList | ReplProgramList +Program ::= ReplProgramList + | ProgramList -ProgramList ::= TopLevel+ +/* Top Level */ -ReplProgramList ::= ReplTopLevel+ +ProgramList ::= TopLevel+ TopLevel ::= Module | Interface - | Expr | Use + | Expression -ReplTopLevel ::= TopLevel - | "(" Defun ")" - | "(" DefConst ")" - | "(" ReplSpecial ")" +/* Top Level (REPL) */ -ReplSpecial ::= "load" STR BOOLEAN - | "load" STR +ReplProgramList ::= ReplTopLevel+ -Governance ::= StringRaw - | IDENT +ReplTopLevel ::= ReplSpecial + | Defun + | DefConst + | TopLevel -StringRaw ::= STR - | TICK +ReplSpecial ::= "(" KEYWORD_LOAD STR Boolean? ")" -Module ::= "(" "module" IDENT Governance [MDocOrModel] ExtOrDefs ")" +/* Annotations & Documentation */ -Interface ::= "(" "interface" IDENT [MDocOrModel] ImportOrIfDef ")" +MDocOrModel ::= DocumentationAnnotation ModelAnnotation + | ModelAnnotation DocumentationAnnotation + | DocumentationAnnotation + | ModelAnnotation + | DocumentationString -Ext ::= Use - | "(" "implements" ModQual ")" - | "(" "bless" StringRaw ")" +MDCapMeta ::= ManagedAnnotation + | EventAnnotation -Use ::= "(" "import" ModQual ImportList ")" - | "(" "import" ModQual STR ImportList ")" +MModel ::= ModelAnnotation -ExtOrDefs ::= (Def | Ext)+ +MDoc ::= DocumentationAnnotation + | DocumentationString -Def ::= Defun - | DefConst - | Defcap - | Defschema - | Deftable - | DefPact +DocumentationAnnotation ::= KEYWORD_DOC_ANNOTATION STR -ImportOrIfDef ::= (IfDef | Use)+ +DocumentationString ::= STR -IfDef ::= IfDefun - | DefConst - | IfDefCap - | Defschema - | IfDefPact +EventAnnotation ::= KEYWORD_EVENT_ANNOTATION -IfDefun ::= "(" "defun" IDENT [MTypeAnn] "(" MArgs ")" [MDocOrModel] ")" -IfDefCap ::= "(" "defcap" IDENT [MTypeAnn] "(" MArgs ")" [MDocOrModel] [MDCapMeta] ")" -IfDefPact ::= "(" "defpact" IDENT [MTypeAnn] "(" MArgs ")" [MDocOrModel] ")" +ManagedAnnotation ::= KEYWORD_MANAGED_ANNOTATION (IDENTIFIER ParsedName)* -ImportList ::= "[" ImportNames "]" +ModelAnnotation ::= KEYWORD_MODEL_ANNOTATION "[" PactFVModels "]" -ImportNames ::= IDENT+ +/* Module */ -Defun ::= "(" "defun" IDENT [MTypeAnn] "(" [MArgs] ")" [MDocOrModel] Block ")" -Defcap ::= "(" "defcap" IDENT [MTypeAnn] "(" [MArgs] ")" [MDocOrModel] [MDCapMeta] Block ")" -DefPact ::= "(" "defpact" IDENT [MTypeAnn] "(" MArgs ")" [MDocOrModel] Steps ")" -DefConst ::= "(" "defconst" IDENT [MTypeAnn] Expr [MDoc] ")" -Defschema ::= "(" "defschema" IDENT [MDocOrModel] SchemaArgList ")" -Deftable ::= "(" "deftable" IDENT ":" "{" ParsedName "}" [MDoc] ")" +Module ::= "(" KEYWORD_MODULE IDENTIFIER Governance [MDocOrModel] (Definition | Extension)+ ")" -Steps ::= Step+ +ModuleNames ::= ModuleQualifier ("," ModuleQualifier)* -Step ::= "(" "step" Expr [MModel] ")" - | "(" "step" Expr Expr [MModel] ")" - | "(" "step-with-rollback" Expr Expr [MModel] ")" - | "(" "step-with-rollback" Expr Expr Expr [MModel] ")" +Governance ::= String + | IDENTIFIER -MDCapMeta ::= Managed - | Event +Interface ::= "(" KEYWORD_INTERFACE IDENTIFIER [MDocOrModel] (InterfaceDefinition | Use)+ ")" -Managed ::= "@managed" (IDENT ParsedName)* +/* Extensions */ -Event ::= "@event" +Extension ::= Use + | "(" KEYWORD_IMPLEMENTS ModuleQualifier ")" + | "(" KEYWORD_BLESS String ")" -MArgs ::= MArg* +Use ::= "(" KEYWORD_IMPORT ModuleQualifier STR? ImportList? ")" -MArg ::= IDENT ":" Type - | IDENT +ImportList ::= "[" [IDENTIFIER+] "]" -SchemaArgList ::= SchemaArg (SchemaArg) * +/* Definitions */ -SchemaArg ::= IDENT (":" Type)? +Definition ::= DefCap + | DefConst + | DefPact + | DefSchema + | DefTable + | Defun -Type ::= "[" Type "]" - | "module" "{" ModuleNames "}" - | IDENT "{" ParsedTyName "}" - | IDENT +DefCap ::= "(" KEYWORD_DEF_CAP IDENTIFIER [MTypeAnn] "(" [MArgs] ")" [MDocOrModel] [MDCapMeta] Block ")" +DefConst ::= "(" KEYWORD_DEF_CONST IDENTIFIER [MTypeAnn] Expression [MDoc] ")" +DefPact ::= "(" KEYWORD_DEF_PACT IDENTIFIER [MTypeAnn] "(" MArgs ")" [MDocOrModel] Steps ")" +DefSchema ::= "(" KEYWORD_DEF_SCHEMA IDENTIFIER [MDocOrModel] SchemaArgumentList ")" +DefTable ::= "(" KEYWORD_DEF_TABLE IDENTIFIER ":" "{" ParsedName "}" [MDoc] ")" +Defun ::= "(" KEYWORD_DEFUN IDENTIFIER [MTypeAnn] "(" [MArgs] ")" [MDocOrModel] Block ")" + +MArgs ::= MArg* -ModuleNames ::= ModQual ("," ModQual) * +MArg ::= IDENTIFIER ":" TypeDeclaration + | IDENTIFIER -DocAnn ::= "@doc" STR +MTypeAnn ::= ":" TypeDeclaration -DocStr ::= STR +SchemaArgumentList ::= SchemaArgument (SchemaArgument)* -MModel ::= ModelAnn +SchemaArgument ::= IDENTIFIER (":" TypeDeclaration)? -ModelAnn ::= "@model" "[" PactFVModels "]" +/* Definitions (Interface) */ -MDocOrModel ::= DocAnn ModelAnn - | ModelAnn DocAnn - | DocAnn - | ModelAnn - | DocStr +InterfaceDefinition ::= IfDefCap + | DefConst + | IfDefPact + | DefSchema + | IfDefun -MDoc ::= DocAnn - | DocStr +IfDefCap ::= "(" KEYWORD_DEF_CAP IDENTIFIER [MTypeAnn] "(" MArgs ")" [MDocOrModel] [MDCapMeta] ")" +IfDefPact ::= "(" KEYWORD_DEF_PACT IDENTIFIER [MTypeAnn] "(" MArgs ")" [MDocOrModel] ")" +IfDefun ::= "(" KEYWORD_DEFUN IDENTIFIER [MTypeAnn] "(" MArgs ")" [MDocOrModel] ")" -MTypeAnn ::= ":" Type +/* Expressions */ Block ::= BlockBody -BlockBody ::= Expr+ +BlockBody ::= Expression+ -Expr ::= "(" SExpr ")" - | Atom +Expression ::= "(" SymbolicExpression ")" + | Variable + | DataType + | Operator -SExpr ::= LamExpr - | LetExpr - | IfExpr - | TryExpr - | ProgNExpr - | GenAppExpr - | SuspendExpr - | CapExpr +SymbolicExpression ::= LambdaExpression + | LetExpression + | IfExpression + | TryExpression + | SuspendExpression + | ProgNExpression + | CapabilityExpression + | GenericExpression -List ::= "[" [ListExprs] "]" +LambdaExpression ::= KEYWORD_LAMBDA "(" LambdaArguments ")" Block -ListExprs ::= Expr MCommaExpr? +LambdaArguments ::= LambdaArgument (LambdaArgument)* -MCommaExpr ::= "," ExprCommaSep - | AppList +LambdaArgument ::= IDENTIFIER (":" TypeDeclaration)? -ExprCommaSep ::= Expr ("," Expr) * +LetExpression ::= KEYWORD_LET "(" Binders ")" Block -LamExpr ::= "lambda" "(" LamArgs ")" Block +Binders ::= ("(" IDENTIFIER [MTypeAnn] Expression ")")+ -IfExpr ::= "if" Expr Expr Expr +IfExpression ::= KEYWORD_IF Expression Expression Expression -TryExpr ::= "try" Expr Expr +TryExpression ::= KEYWORD_TRY Expression Expression -SuspendExpr ::= "suspend" Expr +SuspendExpression ::= KEYWORD_SUSPEND Expression -CapExpr ::= CapForm +ProgNExpression ::= KEYWORD_BLOCK_INTRO BlockBody -CapForm ::= "with-capability" Expr Block - | "create-user-guard" "(" ParsedName AppList ")" +CapabilityExpression ::= CapabilityForm -LamArgs ::= LamArg (LamArg)* -LamArg ::= IDENT (":" Type)? +CapabilityForm ::= KEYWORD_WITH_CAPABILITY Expression Block + | KEYWORD_CREATE_USER_GUARD "(" ParsedName AppList ")" +AppList ::= Expression* -LetExpr ::= LET_KEYWORD "(" Binders ")" Block +GenericExpression ::= Expression AppBindList -Binders ::= ("(" IDENT MTypeAnn Expr ")")+ // Type annotation fault +AppBindList ::= (Expression | BindingForm)* -GenAppExpr ::= Expr AppBindList // Check * ? +BindingForm ::= "{" BindPairs "}" -ProgNExpr ::= "progn" BlockBody +BindPairs ::= BindPair ("," BindPair)* -AppList ::= Expr* // Was + +BindPair ::= STR ":=" MArg + | TICK ":=" MArg -AppBindList ::= (Expr | BindingForm)* +/* Steps */ -BindingForm ::= "{" BindPairs "}" +Steps ::= Step+ -BindPair ::= STR ":=" MArg - | TICK ":=" MArg +Step ::= "(" KEYWORD_STEP Expression [MModel] ")" + | "(" KEYWORD_STEP Expression Expression [MModel] ")" + | "(" KEYWORD_STEP_WITH_ROLLBACK Expression Expression [MModel] ")" + | "(" KEYWORD_STEP_WITH_ROLLBACK Expression Expression Expression [MModel] ")" -BindPairs ::= BindPair ("," BindPair)* +/* Variables & Names */ -Atom ::= Var - | Number - | String - | List - | Bool - | Operator - | Object - | "(" ")" +Variable ::= IDENTIFIER "." ModuleQualifier + | IDENTIFIER "::" IDENTIFIER + | IDENTIFIER -Operator ::= "and" - | "or" - | "enforce" - | "enforce-one" +ParsedName ::= IDENTIFIER "." ModuleQualifier + | IDENTIFIER "::" IDENTIFIER + | IDENTIFIER -Bool ::= "true" - | "false" +ParsedTypeName ::= IDENTIFIER "." ModuleQualifier + | IDENTIFIER -Var ::= IDENT "." ModQual - | IDENT - | IDENT "::" IDENT +ModuleQualifier ::= IDENTIFIER "." IDENTIFIER + | IDENTIFIER -ParsedName ::= IDENT "." ModQual - | IDENT - | IDENT "::" IDENT +/* Data Types */ -ParsedTyName ::= IDENT "." ModQual - | IDENT +TypeDeclaration ::= "[" TypeDeclaration "]" + | "module" "{" ModuleNames "}" + | IDENTIFIER "{" ParsedTypeName "}" + | IDENTIFIER -ModQual ::= IDENT "." IDENT - | IDENT +DataType ::= CompositeDataType + | AtomicDataType + | "(" ")" -Number ::= ["+" | "-"] NUM+ ["." NUM+] +CompositeDataType ::= List + | Object -String ::= STR - | TICK +AtomicDataType ::= Number + | String + | Boolean + +/* Data Types (Composite) */ + +List ::= "[" [ListExpression] "]" -Object ::= "{" ObjectBody "}" +ListExpression ::= Expression MCommaExpression? -ObjectBody ::= FieldPairs +MCommaExpression ::= "," ExpressionCommaSep + | AppList -FieldPair ::= STR ":" Expr - | TICK ":" Expr +ExpressionCommaSep ::= Expression ("," Expression)* -FieldPairs ::= FieldPair ("," FieldPair)* +Object ::= "{" ObjectBody? "}" -PactFVModels ::= PropExprList +ObjectBody ::= FieldPair ("," FieldPair)* -PropExprList ::= PropExpr* // Verify * +FieldPair ::= STR ":" Expression + | TICK ":" Expression -PropExpr ::= PropAtom - | "(" PropExprList ")" - | "[" PropExprList "]" +/* Data Types (Atomic) */ -PropAtom ::= FVVar - | FVNumber - | FVString +Number ::= FLOATING_POINT + | INTEGER + +String ::= STR + | TICK + +Boolean ::= TRUE + | FALSE + +/* Operators */ + +Operator ::= ArithmeticOperator + | AssignmentOperator + | LogicalOperator + | RelationalOperator + | BitwiseOperator + | KEYWORD_ENFORCE + | KEYWORD_ENFORCE_ONE + +ArithmeticOperator ::= PLUS + | MINUS + | MULTIPLY + | DIVIDE + | POW + | ABS + | CEILING + | FLOOR + | LOG + | LN + | DECIMAL + | EXP + | MOD + | ROUND + | SQRT + +AssignmentOperator ::= BIND_ASSIGN + +BitwiseOperator ::= BITWISE_AND + | BITWISE_OR + | BITWISE_REVERSE + | BITWISE_SHIFT + | BITWISE_XOR + +LogicalOperator ::= AND + | AND_SHORT_CIRCUIT + | NOT + | NOT_SHORT_CIRCUIT + | OR + | OR_SHORT_CIRCUIT + +RelationalOperator ::= EQUAL + | NOT_EQUAL + | LESS_THAN + | LESS_THAN_OR_EQUAL + | GREATER_THAN + | GREATER_THAN_OR_EQUAL + +PactFVModels ::= PropExpressionList + +PropExpressionList ::= PropExpression* + +PropExpression ::= PropAtom + | "(" PropExpressionList ")" + | "[" PropExpressionList "]" + +PropAtom ::= Variable + | Number + | String | FVKeyword | FVDelim - | FVBool + | Boolean + | Operator FVKeyword ::= "let" | "lambda" @@ -333,18 +497,6 @@ FVDelim ::= "{" | "}" | ":" | "," - -FVBool ::= "true" - | "false" - -FVNumber ::= ["+" | "-"] NUM+ ["." NUM+] - -FVString ::= STR - | TICK - -FVVar ::= IDENT "." ModQual - | IDENT - | IDENT "::" IDENT ``` ## Modules