Project Structure¶
Coco code can be organised in a number of different ways:
- A module is a Coco source file, written
filename.coco
, which defines a namespace and groups together declarations within it. - Modules can be organised into packages, where a package contains a collection of Coco modules, together with a configuration file that describes various settings about the package. Packages can depend on other packages to facilitate code reuse.
- Packages can be organised into workspaces. A workspace contains a collection of Coco packages, and a configuration file specifying the packages within it, together with default settings that apply to them.
Modules¶
A module defines a namespace and groups together a number of declarations within it. Each source file automatically creates a module in Coco.
A module can be labelled with attributes to make them applicable across the whole module. To achieve this, the
keyword module
has to be explicitly included, and then labelled with the corresponding attributes.
The visibility
of a module can also be set. For example:
private module
specifies that the module is not visible from outside the package within which it is defined.
A module can refer to definitions in another module, in which case one module depends on the other. However, there must not be any cyclic dependencies between modules. Including modules with cyclic dependencies is a static error.
Declarations¶
A module may contain the following:
Import
declarations, which allows the use of declarations from other modules.- Constant
variable
declarations. Enum
,struct
, andtype alias
declarations.Function
declaration.- Trait and trait instance declarations.
Port
andcomponent
declarations, which are used for defining the system and its behaviour.- External component,
external function
,external type
, andexternal constant
declarations, which are used to describe parts of the system not modelled in Coco.
All declarations are lexically scoped: they are visible with the context in which they occur and any of its nested declarations.
Namespaces and Imports¶
Each module has its own namespace, so a single name may be used in several different modules, with a distinct meaning in each. In order to use a name declared in another module, the module must be imported.
-
declaration
Import
¶ import [unqualified] «module name» [as «new module name»]
In its simplest form, import X
, all names declared in X
may then be used as
X.«name»
. It is not possible to import only some of the names in a module.
As in Java, the module M
must be stored in the file M.coco
. A dot (.
) in the module name
will be converted into a directory separator, so import M.N
looks for the file M/N.coco
.
Modules can also be imported with a different name using the as
keyword followed by a new module name. For example:
import X as Y
In this case, names declared in the imported module X
may be used as Y.«name»
.
Names declared in the current module may not be used qualified (prefixed with the name of the current module).
Alternatively, modules may be imported unqualified, using the keyword unqualified
. For example:
import unqualified X
In this case, names declared in the imported module X
may be used unqualified in the current module.
It is a static error to use an unqualified name in the current module if it is ambiguous; i.e. if it could refer to two different declarations. An unqualified import of a module that contains declarations of names that are also used in the current module is likely to lead to ambiguous references and thus static errors.
Note
The use of unqualified
imports is generally not recommended.
However, the standard library is imported unqualified by default into every module.
Packages and Workspaces¶
Coco modules can be organised into packages, where a package contains a collection of Coco modules, together with a configuration file called “Coco.toml” that describes various settings about the package. Packages can depend on other packages to facilitate code reuse.
Packages can be organised into workspaces. A workspace contains a collection of Coco packages, and a “Coco.toml” configuration file that contains references to packages, together with default settings for that workspace.
The remainder of this section provides a brief introduction to the TOML format used in the configuration files, together with a summary of the tables and key/value pairs supported by Coco. Further configuration settings relating to code generation can be found in Code Generation Options.
TOML format¶
Coco.toml
files are written in TOML, which is a format for specifying
configuration files. It is intended to be easy to write and understand, and
its syntax primarily consists of key/value pairs, tables, and comments. TOML files are organised by grouping together
common configuration settings in tables, where a table is a collection of key/value pairs.
Key/value pairs are written as:
key = value
where value
is the configuration value assigned to the key
.
In Coco.toml
files, values will either be of type Int
, Bool
, String
, or an Array
of String
elements.
A table is a collection of key/value pairs, written as:
[table]
Comments are written as:
# This is a comment.
For example:
[package]
# Package name
name = "lift_system"
# Location of Coco source files belonging to this package
sources = "src"
[generator.cpp]
# C++ standard generated by the code generator
standard = "C++17"
[verification]
# Remote verification cannot be used for files belonging to this package
allowRemote = false
Inline tables are also supported in Coco.toml
files to provide a more compact syntax, where tables can be expressed
on one line. An inline table is specified as a comma-separated list of zero or more key/value pairs within curly braces:
table = { key = value, ... }
For example, the package table above can be written inline as follows:
package = { name = "lift_system", sources = "src" }
Coco also supports multi-line basic strings to allow long strings to be written across multiple lines, as illustrated in the following example:
description = """
This is how you can break up a
long string over multiple lines
"""
A multi-line basic string is enclosed by three quotation marks denoting the start and end of the string. The string can include newlines, which are preserved, apart from a newline immediately after the opening three quotation marks that is trimmed.
Package¶
This section gives an overview of the settings that are exclusively used for packages only.
-
package setting
package
¶ Type: Table
This table specifies the package name, the location of the Coco source files that belong to it, and any of the other settings listed below as required.
-
package setting
package.name
¶ Type: String Identifier representing the package name.
For example:
[package]
name = "lift_system"
-
package setting
package.sources
¶ Type: Array(String) Comma-separated list of directories relative to the
Coco.toml
file that contain the Coco source files belonging to the package.
For example:
[package]
name = "lift_system"
sources = ["src"]
This means that the package called lift_system
applies to the Coco source files in the directory src
.
-
package setting
package.testSources
¶ Type: Array(String) Comma-separated list of directories relative to the
Coco.toml
file that contain .coco files that should be considered as test sources.
Test sources are treated like regular sources (i.e. like package.sources
), but have some
special features:
- When generating code, they are output into a separate directory (e.g.
generator.cpp.testOutputDirectory
) alongside other Coco-generated source files that are relevant to testing, such as mocks; - They can depend on files in
package.sources
, but not the other way around.
This permits .coco files related to testing to be kept as part of the main package, but ensures they are kept separate when generating code.
-
package setting
package.exportConfig
¶ Type: Boolean Exports configuration settings from a package to other packages that depend on it.
If a setting is specified in both a package P
and a package Q
that depends on P
, then the setting
in Q
takes precedence. Not all of the configuration settings are exported. For example, the package name and
its dependencies are not exported, whereas the the option settings for the code generation are.
-
package setting
package.workspace
¶ Type: String A reference to the directory (relative to this package’s
Coco.toml
file) containing the Coco workspace that this package belongs to.
For example:
[package]
name = "lift_system"
sources = ["src"]
workspace = "../bridge_system"
This specifies that the package called lift_system
belongs to the workspace in the directory specified.
Workspace¶
This section gives an overview of the settings that are exclusively used for workspaces only.
-
package setting
workspace
¶ Type: Table
This table specifies the location of the packages that belong to this workspace, and any default settings that apply to them.
-
package setting
workspace.members
¶ Type: Array(String) Comma-separated list of references to directories (relative to the
Coco.toml
file) that contain the Coco packages belonging to the workspace.
For example:
[workspace]
members = [
"lift_system",
"light_network",
]
This means that the packages in the directories lift_system
and light_network
belong to this workspace.
A workspace can define default configuration settings for all of the packages that belong to it. For example:
[workspace]
members = [
"lift_system",
"light_network",
]
[language]
standard = "1"
In this example, the language
settings will be applied as the default to all of the packages that belong to this
workspace, namely those in the directories lift_system
and light_network
. Any configuration settings defined in the
Coco.toml
file of the packages themselves will override the default ones set by the workspace they belong to.
For example, if the Coco.toml
file for the package lift_system
is defined as follows:
[package]
name = "lift_system"
sources = ["src"]
[language]
standard = "1.1"
then the language standard applied for the Coco modules in this package will be version 1.1
and not the default setting
of 1
specified in the workspace it belongs to.
Note
It is recommended that packages are organised in sub-directories of the workspace directory
to which they belong. However, a workspace can also include packages that are located elsewhere, for example, the
workspace member could be listed as "../bridge_control"
. In cases where the packages are located elsewhere, then
Coco.toml
files for those packages must also include a reference to the directory of the workspace they belong to.
See package.workspace
for further details.
Dependencies¶
This table captures dependencies between packages, and can be used in packages or workspaces. If a package has
many dependencies on other packages in the same workspace, then it is recommended to specify these dependencies in
the Coco.toml
file of the workspace.
-
package setting
dependencies
¶ Type: Table
Short form dependencies are specified as key-value pairs of the form:
[dependencies]
package_name = "*"
where package_name
is the name of the package that this one depends on. This means that there must exist a
Coco.toml
file whose package.name
property is equal to package_name
. The string refers to which version of the
package should be depended on. Currently, the only supported constraint is *
, which means any version, as written above.
Dependencies can also be specified in a longer form, for example, the short form dependency above is equivalent to:
[dependency.package_name]
version = "*"
Language¶
This table consists of all of the configuration settings related to the Coco language, which can be used in packages or workspaces.
-
package setting
language
¶ Type: Table
-
package setting
language.disabledWarnings
¶ Type: Array(String) Value: The string name of any enum case from Warning
(e.g."IncompleteMatch"
).
-
package setting
language.profiles
¶ Type: Array(String)
Values: - "C" – Restricts Coco to features that are supported by the C generator.
- "C++" – Restricts Coco to features that are supported by the C++ generator.
- "C#" – Restricts Coco to features that are supported by the C# generator.
Default value: “[]”
The Coco Platform supports the generation of multiple target languages, but not all Coco features are supported by all of them. To avoid unsupported features being diagnosed late during code generation, Coco uses profiles to define additional rules that Coco source files must adhere to. This means that diagnostics can be provided to users as early as possible during type checking of their Coco source files.
For example, the following setting:
[language]
profiles = ["C++"]
means that the profile for C++ applies to the Coco source files belonging to the package. As an example of an additional rule this introduces, when this profile is applied to the following valid Coco port declaration:
port Conflict {
struct Conflict {}
}
a static error will be raised during type checking stating that types cannot have the same name as their parent port when the C++ profile is enabled. C++ does not support a class and nested class having the same identifier, and would therefore lead to a compilation error of the generated C++. Rather than discovering this problem during compilation, the Coco profiles help users catch these errors earlier in Coco, which is much more efficient.
-
package setting
language.standard
¶ Type: String
Values: Sets the language standard to be used by the Coco source files belonging to this package.
For example, the following setting:
[language]
standard = "1"
will set the Coco language to version 1
.
See also
Language Standards for descriptions of Coco language versions.
Format¶
This table consists of all of the configuration settings related to the formatting of the Coco source files. These settings can be used in packages or workspaces.
-
package setting
format
¶ Type: Table
-
package setting
format.allowShortBlocksOnASingleLine
¶ Type: Boolean Default value: false
-
package setting
format.allowShortCaseLabelsOnASingleLine
¶ Type: Boolean Default value: false
-
package setting
format.allowShortFunctionsOnASingleLine
¶ Type: String
Values: - "All" – All functions that are short can be placed onto a single line.
- "Empty" – Only empty functions can be placed onto a single line.
- "None" – No functions can be placed onto a single line.
Default value: “All”
-
package setting
format.allowShortIfStatementsOnASingleLine
¶ Type: Boolean Default value: true If true, then all short if statements can be placed onto a single line.
-
package setting
format.allowShortLoopsOnASingleLine
¶ Type: Boolean Default value: false If true, then all short loops can be placed onto a single line.
-
package setting
format.columnLimit
¶ Type: Int Default value: 120 Sets the column width limit to the specified length.
-
package setting
format.sortImports
¶ Type: Boolean Default value: true
-
package setting
format.indentWidth
¶ Type: Int Default value: 2 Sets the indent width to the specified length.
-
package setting
format.tabWidth
¶ Type: Int Default value: 8 Sets the tab width to the specified length.
-
package setting
format.useTabs
¶ Type: String
Values: - "Always" – Always use tabs.
- "ContinuationAndIndentation" – Only use tabs for continuation and indentation.
- "Indentation" – Only use tabs for indentation.
- "Never" – Never use tabs.
Default value: “Never”
Generator¶
This table consists of all of the configuration settings related to the generation of code from Coco. These settings can be used in packages or workspaces.
-
package setting
generator
¶ Type: Table
-
package setting
generator.defaultLanguage
¶ Sets the language that will be generated by default when pressing Generate Code in one of the Coco GUI tools (e.g. Eclipse).
Type: String
Values: - "C" –
- "C++" –
Default value: “C++”
-
package setting
generator.cpp
¶ Sets the settings used when generating C++. See Code Generation Options for further information.
Type: Table:
Tool¶
-
package setting
tool
¶ Type: Table
This table consists of all of the configuration settings related to the tool itself.
-
package setting
tool.requiredVersion
¶ Type: String Specifies the version of the Coco Platform that is required by this package. This must be a version constraint of the form
>= version
or> version
, whereversion
is a partial semantic version; i.e. it is a string of the formx.y.z-p
wherex
,y
andz
are integers, andp
is a string. Any suffix of this may be omitted. For example:>= 1
,>= 1.0
,>= 1.0.0
are all equivalent. Pre-releases can also be included, such as>= 1.0.0-beta.3
.
-
package setting
tool.selectedVersion
¶ type: String Specifies the preferred version of the Coco Platform as a string of the form
x.y.z
. Tools that can automatically download the Coco Platform on-demand will use this version.Note that you should not attempt to parse this value using your own scripts, as the values supported here might change over time. Instead use
coco metadata --selected-tool-version
to extract the value.
Verification¶
This table consists of all of the configuration settings related to the verification. These settings can be used in packages or workspaces.
-
package setting
verification
¶ Type: Table
-
package setting
verification.allowRemote
¶ Type: Boolean Default value: true Sets the access rights to the remote verification service.
For example, the following setting:
[verification]
allowRemote = false
will prohibit the Coco source files that belong to this package from using the remote verification service.