Implement loading namespaces with the using keyword (#338)

* Add using namespace as to scanner and parser

* Change the alias from id() to con()

* Add using namespace to AST type inference

* Allow using namespace to appear in the top level

* Allow using namespace to appear inside functions

* Add a compiler test for using namespace

* Handle name collisions

* Implement mk_error for ambiguous_name

* Add failing test for ambiguous names

* Limit the scope of the used namespaces

* Add test for wrong scope of using namespace

* Use a single using declaration

* Split long line

* Forbid using undefined namespaces

* Add a test for using undefined namespaces

* Change the type of used_namespaces

* Add using namespace parts to scanner and parser

* Add using namespace parts to ast type inference

* Add tests for using namespace parts

* Update CHANGELOG.md

* Code cleaning

* Update the docs

* Update the docs about the same alias for multiple namespaces
This commit is contained in:
Gaith Hallak
2021-09-07 17:45:28 +03:00
committed by GitHub
parent 262452fb70
commit a7b7aafced
13 changed files with 310 additions and 18 deletions
+60
View File
@@ -248,6 +248,66 @@ Functions in namespaces have access to the same environment (including the
with the exception of `state`, `put` and `Chain.event` since these are
dependent on the specific state and event types of the contract.
To avoid mentioning the namespace every time it is used, Sophia allows
including the namespace in the current scope with the `using` keyword:
```
include "Pair.aes"
using Pair
contract C =
type state = int
entrypoint init() =
let p = (1, 2)
fst(p) // this is the same as Pair.fst(p)
```
It is also possible to make an alias for the namespace with the `as` keyword:
```
include "Pair.aes"
contract C =
using Pair as P
type state = int
entrypoint init() =
let p = (1, 2)
P.fst(p) // this is the same as Pair.fst(p)
```
Having the same alias for multiple namespaces is possible and it allows
referening functions that are defined in different namespaces and have
different names with the same alias:
```
namespace Xa = function f() = 1
namespace Xb = function g() = 2
contract Cntr =
using Xa as A
using Xb as A
type state = int
entrypoint init() = A.f() + A.g()
```
Note that using functions with the same name would result in an ambiguous name
error:
```
namespace Xa = function f() = 1
namespace Xb = function f() = 2
contract Cntr =
using Xa as A
using Xb as A
type state = int
// the next line has an error because f is defined in both Xa and Xb
entrypoint init() = A.f()
```
Importing specific parts of a namespace or hiding these parts can also be
done like this:
```
using Pair for [fst, snd] // this will only import fst and snd
using Triple hiding [fst, snd] // this will import everything except for fst and snd
```
Note that it is possible to use a namespace in the top level of the file, in the
contract level, namespace level, or in the function level.
## Splitting code over multiple files
Code from another file can be included in a contract using an `include`