Packages in Object Icon provide two functions :-
A file is declared to be in a package by simply adding a package declaration at the top of the source file, such as the following :-
package my.pack
import io(write)
procedure one()
write("in my.pack.one")
end
This will have the effect of adding the file to the package my.pack
. This information is stored in a file named packages.txt
, stored in the same directory as the ucode file. The format of the file is very simple, and just maintains a list of which files are in which package.
The other effect of the package statement is that the names of the global symbols (procedures, records, classes and global variables) declared in the file are prefixed automatically with the package name. So, the procedure one
in the above file is in fact named my.pack.one
.
A package is used in a program via the import statement. For example :-
import my.pack
procedure main()
one()
end
The import statement causes the linker to search all the packages.txt
located on the linking path for the specified package. When found, all of the files in the package are linked into the program.
Note that the reference to the procedure my.pack.one
is in the shorter form, one
. This is allowed so long as there isn’t another symbol one
which would make the reference ambiguous. In any case, the fully qualified form is also acceptable.
If there are several imports in one file it may become difficult to discern which symbol came from which package. For this reason, the import statement lets you indicate which symbols are being used from a particular package, as follows :-
import my.pack(one, two, three)
This means the three given symbols are being used in the source file and can be resolved to my.pack.one
, my.pack.two
and my.pack.three
respectively. If there were another symbol in my.pack
, say four
, then it would not be resolved by the linker if it were encountered as four
; rather an undeclared identifier error would be raised. If it were encountered as my.pack.four
however, that would not raise an error. Note that this form of the import statement still links all of the files in the package into the program, regardless of which symbols are specified.
It is also possible to specify that certain symbols in a package should be excluded; for example :-
import my.pack -(one, two, three)
This imports all of the symbols in my.pack
except one
, two
and three
. This can be useful if a particular symbol in a package is not being used, but is clashing with a symbol from another package (which is being used).
Sometimes it is necessary to use a fully-qualified symbol; in particular it may be necessary if you have imported two packages which both contain the same symbol. For example, consider the following program which imports two packages each of which contains a symbol named Class
.
import lang, parser, io(write)
procedure main()
write(to_string(Class))
end
Compiling this produces an error message (on linking) :-
/tmp/junk.u:
File junk.icn; Line 4 # Symbol 'Class' resolves to multiple targets in procedure main :-
lang.Class (/opt/objecticon/lib/main/class.icn; Line 7)
parser.Class (/opt/objecticon/lib/parser/tree.icn; Line 723)
1 error
Supposing we meant parser.Class
, we can just change the offending line to :-
write(image(parser.Class))
Note that we still need the import parser
. Otherwise parser
is interpreted as an identifier and Class
as a field, and an “Undeclared identifier” error is produced by the linker.
Another way to resolve the ambiguity would be to use qualified imports. For example, the following program compiles successfully with the use of Class
unambiguously resolving to parser.Class
.
import lang(to_string), parser(Class), io(write)
procedure main()
write(to_string(Class))
end
Yet another way to solve this problem would be to exclude the Class
symbol from the lang
import, as follows :-
import lang-(Class), parser, io(write)
If you use a fully-qualified symbol in a superclass list, or an invocable declaration, then the package must be imported. For example, consider the following file :-
class Abc(xml.Node)
end
Translating this will give the following error :-
File junk.icn; Line 1 # Reference to unimported package: 'xml'
This can be resolved by simply importing the xml
package, either as a qualified or unqualified import. The reasoning behind this error is to avoid library code which translates correctly to a .u
file, but depends on some other file, or the client program, importing (and hence linking) a particular package.
Top-level declarations can be specified as having package scope; for details see here.
Contents