Skip to content

Commit c809977

Browse files
authored
document actor class import (#1998)
document actor class import
1 parent c76016c commit c809977

File tree

1 file changed

+89
-25
lines changed

1 file changed

+89
-25
lines changed

doc/modules/language-guide/pages/language-manual.adoc

Lines changed: 89 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -382,18 +382,29 @@ An import introduces a resource named '<id>?' referring to a local source module
382382
The syntax of a _library_ (that can be referenced in an import) is as follows:
383383

384384
```bnf
385-
<lib> ::= library
386-
<imp>;* module <id>? =? { <dec-field>;* }
385+
<lib> ::= library
386+
<imp>;* module <id>? <obj-body> module
387+
<imp>;* <shared-pat>? actor class <id> <typ-params>? <pat> (: <typ>)? <class-body> actor class
387388
```
388389

389-
A library `<lib>` is a sequence of imports `<imp>;*` followed by a named or anonymous (module) declaration `module <id>? =? { <dec-field>;* }`.
390+
A library `<lib>` is a sequence of imports `<imp>;*` followed by:
390391

391-
Libraries stored in {ext} files may be referenced by `import`s.
392+
* a named or anonymous (module) declaration; or
393+
* a named actor class declaration.
392394

393-
The name `<id>?` is only significant within the library and does not determine the name of the library when imported.
395+
Libraries stored in {ext} files may be referenced by `import` declarations.
396+
397+
In a module library, the optional name `<id>?` is only significant within the library and does not determine the name of the library when imported.
394398
Instead, the imported name of a library is determined by the `import` declaration, giving clients of the library the freedom to
395399
choose library names (e.g. to avoid clashes).
396400

401+
An actor class library, because it defines both a type constructor and a function with name `<id>`, is imported as a module defining both a type and a function named `<id>`.
402+
The name `<id>` is mandatory and cannot be omitted.
403+
The imported actor class constructor is asynchronous, with return type `async T`. Here `T` is the inferred or supplied type of the class body.
404+
Because actor construction is asynchronous, an instance of an imported actor class can only be created in an asynchronous context
405+
(i.e. in the body of a (non-`query`) `shared` function or `async` expression).
406+
407+
397408
[[syntax-decls]]
398409
=== Declaration syntax
399410

@@ -405,10 +416,17 @@ The syntax of a _declaration_ is as follows:
405416
ignore <exp> ignore
406417
let <pat> = <exp> immutable
407418
var <id> (: <typ>)? = <exp> mutable
408-
<sort> <id>? =? { <dec-field>;* } object
419+
<sort> <id>? =? <obj-body> object
409420
<shared-pat>? func <id>? <typ-params>? <pat> (: <typ>)? =? <exp> function
410421
type <id> <typ-params>? = <typ> type
411-
<shared-pat>? <sort>? class <id> <typ-params>? <pat> (: <typ>)? =? { <exp-field>;* } class
422+
<shared-pat>? <sort>? class <id>? <typ-params>? <pat> (: <typ>)? <class-body> class
423+
424+
<obj-body> ::= object body
425+
{ <dec-field>;* } field declarations
426+
427+
<class-body> ::= class body
428+
= <id>? <obj-body> object body, optionally binding <id> to _this_ instance
429+
<obj-body> object body
412430
```
413431

414432
The syntax of a shared function qualifier with call-context pattern is as follows:
@@ -496,7 +514,7 @@ The syntax of an _expression_ is as follows:
496514
try <exp> catch <pat> <exp> catch an error (only in async)
497515
assert <exp> assertion
498516
<exp> : <typ> type annotation
499-
dec declaration
517+
<dec> declaration
500518
debug <exp> debug expression
501519
actor <canister-id-exp> actor reference
502520
( <exp> ) parentheses
@@ -931,7 +949,7 @@ A type `T` is well-formed only if (recursively) its constituent types are well-f
931949
* if `T` is `async U` then `U` is shared, and
932950
* if `T` is `shared query? U -> V`, `U` is shared and
933951
`V == ()` or `V == async W'` with `W` shared, and
934-
* if `T` is `C<T0, ..., TN>` where:
952+
* if `T` is `C<T0, ..., Tn>` where:
935953
** a declaration `type C<X0 <: U0, Xn <: Un> = ...` is in scope, and
936954
** `Ti <: Ui[ T0/X0, ..., Tn/Xn ]`, for each `0 \<= i \<= n`.
937955
* if `T` is `actor { ... }` then all fields in `...` are immutable and have `shared` function type.
@@ -985,15 +1003,15 @@ Two types `T`, `U` are related by subtyping, written `T <: U`, whenever, one of
9851003
`U` is a function type `<shared>? <X0 <: W0, ..., Xn <: Wn> U1 -> U2` and
9861004
** `T` and `U` are either both equivalently `<shared>?`, and
9871005
** assuming constraints `X0 <: W0, ..., Xn <: Wn` then
988-
*** for all `i`, `Wi <: Vi`, and
1006+
*** for all `i`, `Wi == Vi`, and
9891007
*** `U1 <: T1`, and
9901008
*** `T2 <: U2`.
9911009
+
9921010
(That is, function type `T` is a subtype of function type `U` if they have same `<shared>?` qualification, they have the same type parameters (modulo renaming) and assuming the bounds in `U`,
9931011
every bound in `T` supertypes the corresponding parameter bound in `U` (contra-variance), the domain of `T` supertypes the domain of `U` (contra-variance) and the range of `T` subtypes
9941012
the range of `U` (co-variance).)
9951013
+
996-
* `T` (respectively `U`) is a constructed type `C<V0,...VN>` that is equal, by definition of type constructor `C`, to `W`, and `W <: U` (respectively `U <: W`).
1014+
* `T` (respectively `U`) is a constructed type `C<V0, ..., Vn>` that is equal, by definition of type constructor `C`, to `W`, and `W <: U` (respectively `U <: W`).
9971015

9981016
* For some type `V`, `T <: V` and `V <: U` (_transitivity_).
9991017

@@ -1061,18 +1079,59 @@ A program evaluates by (transitively) evaluating the imports, binding their valu
10611079
[[libraries]]
10621080
=== Libraries
10631081

1064-
A library `<imp>;* module <id>? =? { <dec-field>;* }` is a sequence of imports `<import>;*` followed by a single module declaration.
1082+
Restrictions on the syntactic form of modules means that libraries can have no side-effects.
1083+
1084+
The imports of a library are local and not re-exported in its interface.
1085+
1086+
Multiple imports of the same library can be safely deduplicated without loss of side-effects.
1087+
1088+
==== Module libraries
1089+
1090+
A library `<imp>;* module <id>? <obj-body>` is a sequence of imports `<import>;*` followed by a single module declaration.
10651091

10661092
A library has module type `T` provided
10671093

1068-
* `module <id>? =? { <dec-field>;* }` has (module) type `T` under the static environment induced by the imports in `<import>;*`.
1094+
* `module <id>? <obj-body>` has (module) type `T` under the static environment induced by the imports in `<import>;*`.
10691095

1070-
The imports of a library are local and not re-exported in its interface.
1096+
A module library evaluates by (transitively) evaluating its imports, binding their values to the identifiers in `<imp>;*` and then evaluating `module <id>? <obj-body>`.
10711097

1072-
A library evaluates by (transitively) evaluating its imports, binding their values to the identifiers in `<imp>;*` and then evaluating the sequence of declarations in `<dec>;*`.
1098+
==== Actor class libraries
10731099

1074-
Restrictions on the syntactic form of modules means that libraries can have no side-effects.
1075-
Multiple imports of the same library can be safely deduplicated without loss of side-effects.
1100+
////
1101+
This ugly asyncification of actor class imports below will go away once we change actor class definitions to be asynchronous. This is a temporary kludge.
1102+
////
1103+
1104+
The actor class library `<imp>;* <dec>` where `<dec>` is of the form `<shared-pat>? actor class <id> <typ-params>? <pat> (: <typ>)? <class-body>` has type:
1105+
1106+
```
1107+
module {
1108+
type <id> = T;
1109+
<id> : (U1,...,Un) -> async T // asynchronous!
1110+
}
1111+
```
1112+
1113+
provided that:
1114+
1115+
* the actor class declaration `<dec>` has function type `(U1, ..., Un) -> T` under the static environment induced by the imports in `<import>;*`.
1116+
1117+
Notice that the imported type of the function `<id>` is the *asynchronous* version of its declared type.
1118+
1119+
An actor class library evaluates by (transitively) evaluating its imports, binding their values to the identifiers in `<imp>;*`, and evaluating the (derived) module:
1120+
1121+
```
1122+
module {
1123+
public type <id> = T;
1124+
public func <id>(a1 : U1, ..., an : Un) : async T { // asynchronous!
1125+
(<dec>)(a1, ..., an)
1126+
}
1127+
}
1128+
```
1129+
1130+
The imported module contains an asynchronous implementation of function `<id>`.
1131+
1132+
On the Internet Computer, calling `await <id>(<exp1>, ..., <expn>)`, installs a fresh instance of the actor class as an isolated IC canister, passing the values of `<exp1>`, ..., `<expn>`
1133+
as installation arguments, and returns a reference to a (remote) actor of type `T`.
1134+
Installation is (necessarily) asynchronous.
10761135

10771136
[[imports]]
10781137
=== Imports and Urls
@@ -1163,7 +1222,7 @@ During an upgrade, a trap occuring in the implicit call to `preupgrade()` or `po
11631222
[[decl-seq]]
11641223
=== Sequence of declarations
11651224

1166-
A sequence of declarations `<dec>;*` occurring in a block, a program or the `exp-field;*` sequence of an object declaration has type `T`
1225+
A sequence of declarations `<dec>;*` occurring in a block, a program or embedded in the `<dec-field>;*` sequence of an object body has type `T`
11671226
provided:
11681227

11691228
* `<dec>;*` is empty and `T == ()`; or
@@ -1345,13 +1404,13 @@ In scope of the declaration `type C < X0<:T0>, ..., Xn <: Tn > = U`, any well-
13451404
[[decl-obj]]
13461405
=== Object declaration
13471406

1348-
Declaration `<sort> <id>? =? { <exp-field>;* }` declares an object with optional identifier `<id>` and zero or more fields `<exp-field>;*`.
1407+
Declaration `<sort> <id>? <obj-body>`, where `<obj_body>` is of the form `=? { <dec-field>;* }`, declares an object with optional identifier `<id>` and zero or more fields `<dec-field>;*`.
13491408
Fields can be declared with `public` or `private` visibility; if the visibility is omitted, it defaults to `private`.
13501409

13511410
The qualifier `<sort>` (one of `actor`, `module` or `object`) specifies the *sort* of the object's type. The sort imposes restrictions on the types of the public object fields.
13521411

13531412
Let `T = sort { [var0] id0 : T0, ... , [varn] idn : T0 }` denote the type of the object.
1354-
Let `<dec>;*` be the sequence of declarations in `<exp_field>;*`.
1413+
Let `<dec>;*` be the sequence of declarations embedded in `<dec-field>;*`.
13551414
The object declaration has type `T` provided that:
13561415

13571416
1. type `T` is well-formed for sort `sort`, and
@@ -1395,20 +1454,25 @@ Named function definitions are recursive.
13951454
[[decl-class]]
13961455
=== Class declaration
13971456

1398-
The declaration `<shared-pat>? <sort>? class <id> <typ-params>? <pat> (: <typ>)? =? <id_this>? { <exp-field>;* }` is sugar for pair of a type and function declaration:
1457+
////
1458+
TODO: revise once actor class declaration async
1459+
////
1460+
1461+
The _class_ declaration `<shared-pat>? <sort>? class <id>? <typ-params>? <pat> (: <typ>)? <class-body>` is sugar for pair of a type and function declaration:
13991462

14001463
```bnf
1401-
<shared-pat>? <sort>? class <id> <typ-params>? <pat> (: <typ>)? =? <id_this>? { <dec-field>;* } :=
1464+
<shared-pat>? <sort>? class <id> <typ-params>? <pat> (: <typ>)? <class-body> :=
14021465
type <id> <typ-params> = <sort> { <typ-field>;* };
1403-
<shared-pat>? func <id> <typ-params>? <pat> : <id> <typ-args> = <sort> <id_this>? { <dec-field>;* }
1466+
<shared-pat>? func <id> <typ-params>? <pat> : <id> <typ-args> = <sort> <id_this>? <obj-body>
14041467
```
14051468

14061469
where:
14071470

14081471
* `<shared-pat>?`, when present, requires `<sort>` == `actor`, and provides access to the `caller` of an `actor` constructor, and
14091472
* `<typ-args>?` is the sequence of type identifiers bound by `<typ-params>?` (if any), and
14101473
* `<typ-field>;*` is the set of public field types inferred from `<dec-field>;*`.
1411-
* `<id_this>?` is the optional `this` parameter of the object instance.
1474+
* `<obj-body>` is the object body of `<class-body>`.
1475+
* `<id_this>?` is the optional _this_ (a.k.a _self_), parameter of `<class-body>`.
14121476

14131477
Note `<shared-pat>?` must not be of the form `shared query <pat>?`: a constructor, unlike a function, cannot be a query.
14141478

@@ -1481,7 +1545,7 @@ For equality and inequality, the meaning of `v1 <relop> v2` depends on the compi
14811545
=== Tuples
14821546

14831547
Tuple expression `(<exp1>, ..., <expn>)` has tuple type `(T1, ..., Tn)`, provided
1484-
`<exp1>`, ..., `<expN>` have types `T1`, ..., `Tn`.
1548+
`<exp1>`, ..., `<expn>` have types `T1`, ..., `Tn`.
14851549

14861550
The tuple expression `(<exp1>, ..., <expn>)` evaluates the expressions `exp1` ... `expn` in order, trapping as soon as some expression `<expi>` traps. If no evaluation traps and `exp1`, ..., `<expn>` evaluate to values `v1`,...,`vn` then the tuple expression returns the tuple value `(v1, ... , vn)`.
14871551

0 commit comments

Comments
 (0)