diff options
Diffstat (limited to 'docs/layout-of-source-files.rst')
-rw-r--r-- | docs/layout-of-source-files.rst | 171 |
1 files changed, 128 insertions, 43 deletions
diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst index f9d197b7..9a8bdc3e 100644 --- a/docs/layout-of-source-files.rst +++ b/docs/layout-of-source-files.rst @@ -2,15 +2,29 @@ Layout of a Solidity Source File ******************************** -Source files can contain an arbitrary number of contract definitions, include directives -and pragma directives. +Source files can contain an arbitrary number of +:ref:`contract definitions<contract_structure>`, import_ directives +and :ref:`pragma directives<pragma>`. + +.. index:: ! pragma + +.. _pragma: + +Pragmas +======= + +The ``pragma`` keyword can be used to enable certain compiler features +or checks. A pragma directive is always local to a source file, so +you have to add the pragma to all your files if you want enable it +in all of your project. If you :ref:`import<import>` another file, the pragma +from that file will not automatically apply to the importing file. .. index:: ! pragma, version .. _version_pragma: Version Pragma -============== +-------------- Source files can (and should) be annotated with a so-called version pragma to reject being compiled with future compiler versions that might introduce incompatible @@ -35,6 +49,53 @@ the exact version of the compiler, so that bugfix releases are still possible. It is possible to specify much more complex rules for the compiler version, the expression follows those used by `npm <https://docs.npmjs.com/misc/semver>`_. +.. note:: + Using the version pragma will *not* change the version of the compiler. + It will also *not* enable or disable features of the compiler. It will just + instruct the compiler to check whether its version matches the one + required by the pragma. If it does not match, the compiler will issue + an error. + +.. index:: ! pragma, experimental + +.. _experimental_pragma: + +Experimental Pragma +------------------- + +The second pragma is the experimental pragma. It can be used to enable +features of the compiler or language that are not yet enabled by default. +The following experimental pragmas are currently supported: + + +ABIEncoderV2 +~~~~~~~~~~~~ + +The new ABI encoder is able to encode and decode arbitrarily nested +arrays and structs. It produces less optimal code (the optimizer +for this part of the code is still under development) and has not +received as much testing as the old encoder. You can activate it +using ``pragma experimental ABIEncoderV2;``. + +.. _smt_checker: + +SMTChecker +~~~~~~~~~~ + +This component has to be enabled when the Solidity compiler is built +and therefore it is not available in all Solidity binaries. +The :ref:`build instructions<smt_solvers_build>` explain how to activate this option. +It is activated for the Ubuntu PPA releases in most versions, +but not for solc-js, the Docker images, Windows binaries or the +statically-built Linux binaries. + +If you use +``pragma experimental SMTChecker;``, then you get additional +safety warnings which are obtained by querying an SMT solver. +The component does not yet support all features of the Solidity language +and likely outputs many warnings. In case it reports unsupported +features, the analysis may not be fully sound. + .. index:: source file, ! import .. _import: @@ -56,18 +117,27 @@ At a global level, you can use import statements of the following form: This statement imports all global symbols from "filename" (and symbols imported there) into the current global scope (different than in ES6 but backwards-compatible for Solidity). +This simple form is not recommended for use, because it pollutes the namespace in an +unpredictable way: If you add new top-level items inside "filename", they will automatically +appear in all files that import like this from "filename". It is better to import specific +symbols explicitly. + +The following example creates a new global symbol ``symbolName`` whose members are all +the global symbols from ``"filename"``. :: import * as symbolName from "filename"; -...creates a new global symbol ``symbolName`` whose members are all the global symbols from ``"filename"``. +If there is a naming collision, you can also rename symbols while importing. +This code +creates new global symbols ``alias`` and ``symbol2`` which reference ``symbol1`` and ``symbol2`` from inside ``"filename"``, respectively. :: import {symbol1 as alias, symbol2} from "filename"; -...creates new global symbols ``alias`` and ``symbol2`` which reference ``symbol1`` and ``symbol2`` from ``"filename"``, respectively. + Another syntax is not part of ES6, but probably convenient: @@ -77,6 +147,10 @@ Another syntax is not part of ES6, but probably convenient: which is equivalent to ``import * as symbolName from "filename";``. +.. note:: + If you use `import "filename.sol" as moduleName;`, you access a contract called `C` + from inside `"filename.sol"` as `moduleName.C` and not by using `C` directly. + Paths ----- @@ -93,47 +167,52 @@ It depends on the compiler (see below) how to actually resolve the paths. In general, the directory hierarchy does not need to strictly map onto your local filesystem, it can also map to resources discovered via e.g. ipfs, http or git. +.. note:: + Always use relative imports like ``import "./filename.sol";`` and avoid + using ``..`` in path specifiers. In the latter case, it is probably better to use + global paths and set up remappings as explained below. + Use in Actual Compilers ----------------------- -When the compiler is invoked, it is not only possible to specify how to -discover the first element of a path, but it is possible to specify path prefix -remappings so that e.g. ``github.com/ethereum/dapp-bin/library`` is remapped to -``/usr/local/dapp-bin/library`` and the compiler will read the files from there. -If multiple remappings can be applied, the one with the longest key is tried first. This -allows for a "fallback-remapping" with e.g. ``""`` maps to -``"/usr/local/include/solidity"``. Furthermore, these remappings can -depend on the context, which allows you to configure packages to -import e.g. different versions of a library of the same name. +When invoking the compiler, you can specify how to discover the first element +of a path, and also path prefix remappings. For +example you can setup a remapping so that everything imported from the virtual +directory ``github.com/ethereum/dapp-bin/library`` would actually be read from +your local directory ``/usr/local/dapp-bin/library``. +If multiple remappings apply, the one with the longest key is tried first. +An empty prefix is not allowed. The remappings can depend on a context, +which allows you to configure packages to import e.g., different versions of a +library of the same name. **solc**: -For solc (the commandline compiler), these remappings are provided as +For solc (the commandline compiler), you provide these path remappings as ``context:prefix=target`` arguments, where both the ``context:`` and the -``=target`` parts are optional (where target defaults to prefix in that +``=target`` parts are optional (``target`` defaults to ``prefix`` in this case). All remapping values that are regular files are compiled (including -their dependencies). This mechanism is completely backwards-compatible (as long -as no filename contains = or :) and thus not a breaking change. All imports -in files in or below the directory ``context`` that import a file that -starts with ``prefix`` are redirected by replacing ``prefix`` by ``target``. +their dependencies). + +This mechanism is backwards-compatible (as long +as no filename contains ``=`` or ``:``) and thus not a breaking change. All +files in or below the ``context`` directory that import a file that starts with +``prefix`` are redirected by replacing ``prefix`` by ``target``. -So as an example, if you clone -``github.com/ethereum/dapp-bin/`` locally to ``/usr/local/dapp-bin``, you can use -the following in your source file: +For example, if you clone ``github.com/ethereum/dapp-bin/`` locally to +``/usr/local/dapp-bin``, you can use the following in your source file: :: import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol" as it_mapping; -and then run the compiler as +Then run the compiler: .. code-block:: bash solc github.com/ethereum/dapp-bin/=/usr/local/dapp-bin/ source.sol -As a more complex example, suppose you rely on some module that uses a -very old version of dapp-bin. That old version of dapp-bin is checked -out at ``/usr/local/dapp-bin_old``, then you can use +As a more complex example, suppose you rely on a module that uses an old +version of dapp-bin that you checked out to ``/usr/local/dapp-bin_old``, then you can run: .. code-block:: bash @@ -141,28 +220,29 @@ out at ``/usr/local/dapp-bin_old``, then you can use module2:github.com/ethereum/dapp-bin/=/usr/local/dapp-bin_old/ \ source.sol -so that all imports in ``module2`` point to the old version but imports -in ``module1`` get the new version. +This means that all imports in ``module2`` point to the old version but imports +in ``module1`` point to the new version. -Note that solc only allows you to include files from certain directories: -They have to be in the directory (or subdirectory) of one of the explicitly -specified source files or in the directory (or subdirectory) of a remapping -target. If you want to allow direct absolute includes, just add the -remapping ``=/``. +.. note:: + + ``solc`` only allows you to include files from certain directories. They have + to be in the directory (or subdirectory) of one of the explicitly specified + source files or in the directory (or subdirectory) of a remapping target. If + you want to allow direct absolute includes, add the remapping ``/=/``. If there are multiple remappings that lead to a valid file, the remapping with the longest common prefix is chosen. **Remix**: -`Remix <https://remix.ethereum.org/>`_ -provides an automatic remapping for github and will also automatically retrieve -the file over the network: -You can import the iterable mapping by e.g. -``import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol" as it_mapping;``. +`Remix <https://remix.ethereum.org/>`_ provides an automatic remapping for +GitHub and automatically retrieves the file over the network. You can import +the iterable mapping as above, e.g. -Other source code providers may be added in the future. +:: + import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol" as it_mapping; +Remix may add other source code providers in the future. .. index:: ! comment, natspec @@ -180,6 +260,11 @@ Single-line comments (``//``) and multi-line comments (``/*...*/``) are possible multi-line comment. */ +.. note:: + A single-line comment is terminated by any unicode line terminator + (LF, VF, FF, CR, NEL, LS or PS) in utf8 encoding. The terminator is still part of + the source code after the comment, so if it is not an ascii symbol + (these are NEL, LS and PS), it will lead to a parser error. Additionally, there is another type of comment called a natspec comment, for which the documentation is not yet written. They are written with a @@ -195,17 +280,17 @@ for the two input parameters and two returned values. :: - pragma solidity ^0.4.0; + pragma solidity >=0.4.0 <0.6.0; /** @title Shape calculator. */ - contract shapeCalculator { + contract ShapeCalculator { /** @dev Calculates a rectangle's surface and perimeter. * @param w Width of the rectangle. * @param h Height of the rectangle. * @return s The calculated surface. * @return p The calculated perimeter. */ - function rectangle(uint w, uint h) returns (uint s, uint p) { + function rectangle(uint w, uint h) public pure returns (uint s, uint p) { s = w * h; p = 2 * (w + h); } |