February 1999 Draft
Thursday, February 18, 1999
A package P typically starts with
import statements that import other packages used by package
P. A package that is meant to be used by other packages typically has one or more
declarations that declare versions available for export.
When a package is loaded, all of its statements are evaluated in order, which may cause other packages to be loaded along
the way when
import statements are encountered. A package's symbols are available for export to other packages
only after the package's body has been successfully evaluated. Unlike in Java, circularities are not allowed in the graph
of package imports.
To create packages A and B that access each others' symbols, we need to instead define a hidden package C that consists of all of the code that would have gone into A and B. Package C should define versions verA and verB and tag the symbols it exports with either verA or verB to indicate whether these symbols belong in package A or B. Package A should then be empty except for a directive (or several directives if there are multiple versions of A and verA) that reexports C's symbols tagged with verA. Similarly, package B should reexport C's symbols tagged with verB. To make this work we need a reexport directive. Is this really necessary? Also, do we want a mechanism for hiding package C from general view so that users can only use it through A or B?
We can export a symbol in a package by giving it
To import symbols from a package we use the
=] NonAssignmentExpression [
The first form of the
import statement (without a Block) imports symbols into
the current lexical scope. The second and third forms import symbols into the lexical scope of the Block.
If the imports are unsuccessful, the first two forms of the
import statement throw an exception, while the last
form executes the CodeStatement after the
import statement can import one or more packages separated by commas. Each ImportItem
specifies one package to be imported. The NonAssignmentExpression should evaluate to a string
that contains a URI where the package may be found. If present, Version indicates the version
of the package's exports to be imported; if not present, Version defaults to version 1.
An ImportItem can introduce a name for the imported package if the NonAssignmentExpression
is preceded by Identifier
becomes bound (either in the current lexical scope or in the Block's scope) to the imported package
as a whole. Individual symbols can be extracted from the package by using Identifier with the
:: operator. For example, if package at URI P has
b, then after the statement
P's symbols can be referenced as either
If an ImportItem contains the keyword
the imported symbols can only be accessed using the
:: operator. If we were to import
package P using
import protected x=P
then we'd have to access P's symbols using either
If two imports in the same scope import packages with clashing symbols, then neither symbol is accessible unless qualified
:: operator. If an imported symbol clashes with a symbol declared in the same
scope, then the declared symbol shadows the imported symbol. Scope rules 3 and
4 apply here as well, so the following code is illegal because
a is referenced and then redefined:
; References P's
var y=a; //
const a=17; //
a in same scope
Version names cannot be imported.
Last modified Thursday, February 18, 1999