Yes, there is a EBNF for Cadence.
The runtime Interface
functions ExecuteTransaction
and ExecuteScript
require a Context
argument.
The context has an Environment
field, in which stdlib.StandardLibraryValue
s can be declared.
Cadence's parser is implemented as a hand-written recursive descent parser which uses operator precedence parsing. The recursive decent parsing technique allows for greater control, e.g. when implementing whitespace sensitivity, ambiguities, etc. The handwritten parser also allows for better / great custom error reporting and recovery.
The operator precedence parsing technique avoids constructing a CST and the associated overhead, where each grammar rule is translated to a CST node. For example, a simple integer literal would be "boxed" in several outer grammar rule nodes.
Arrays and dictionaries are implemented as trees. This means that lookup operations do not run in constant time. In certain cases, a mutation operation may cause a rebalancing of the tree.
To analyze Cadence code, you can use the Go package github.com/onflow/cadence/analysis
.
It is similar to the Go package golang.org/x/tools/go/analysis
, which allows analyzing Go code.
The blog post at https://eli.thegreenplace.net/2020/writing-multi-package-analysis-tools-for-go/ can be followed to learn more about how to write an analyzer.
The API of the analysis package for Cadence programs is fairly similar to the package for Go programs, but not identical.
To run the analyzer pass, the Cadence linter tool can be used. For example, it allows running the pass over all contracts of a network.
There are several options to run the analyzer pass with the linter tool:
- The analysis pass can be written directly in the linter tool. See the existing passes in the linter tool for examples.
- The analysis pass can be written in a separate package in Cadence, and the linter tool can use it.
The go.mod
replace
statement can be used to point to a locally modified Cadence working directory. - The linter supports Go plugins (see e.g. https://eli.thegreenplace.net/2021/plugins-in-go/) https://github.com/onflow/cadence-tools/blob/83eb7d4d19ddf2dd7ad3fdcc6aa6451a6bc126ff/lint/cmd/lint/main.go#L48.
The analyzer pass can be written in a separate module, built as a plugin, and loaded in the linter using the
-plugin
command line option.
To analyze Cadence values (interpreter.Value
), you can use the function interpreter.InspectValue
.
To find static types in Cadence values (e.g. in type values, containers, capabilities), you can see which values contain static types in the Cadence 1.0 static type migration code.
To load values from a state snapshot you can use the flow-go util
commad to convert a state snapshot in trie format to a file which just contains the payloads.
To get a runtime.Storage
instance from it, use util.ReadPayloadFile
, util.NewPayloadSnapshot
, state.NewTransactionState
, environment.NewAccounts
, util.NewAccountsAtreeLedger
, and finally runtime.NewStorage
.