Contents

Object Icon’s package system

Packages

Packages in Object Icon provide two functions :-

Declaring a package

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.

Using a package

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).

Using fully-qualified symbols

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.

Package scope

Top-level declarations can be specified as having package scope; for details see here.

Contents