summaryrefslogtreecommitdiff
path: root/miralib/manual/27/3
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2022-03-04 12:32:20 -0500
committerJakob Kaivo <jkk@ung.org>2022-03-04 12:32:20 -0500
commit55f277e77428d7423ae906a8e1f1324d35b07a7d (patch)
tree5c1c04703dff89c46b349025d2d3ec88ea9b3819 /miralib/manual/27/3
import Miranda 2.066 from upstream
Diffstat (limited to 'miralib/manual/27/3')
-rw-r--r--miralib/manual/27/3286
1 files changed, 286 insertions, 0 deletions
diff --git a/miralib/manual/27/3 b/miralib/manual/27/3
new file mode 100644
index 0000000..5891ed2
--- /dev/null
+++ b/miralib/manual/27/3
@@ -0,0 +1,286 @@
+_E_x_p_l_a_n_a_t_i_o_n_ _o_f_ _l_i_b_r_a_r_y_ _d_i_r_e_c_t_i_v_e_s
+
+The three directives %_i_n_c_l_u_d_e %_e_x_p_o_r_t %_f_r_e_e constitute the Miranda
+library mechanism, which controls the sharing of identifiers between
+separately compiled scripts. The %_f_r_e_e directive is covered in a
+separate manual entry and will not be discussed further here.
+------------------------------------------------------------------------
+
+%_i_n_c_l_u_d_e "file"
+
+The presence of this directive, anywhere in a Miranda script, causes all
+the identifiers exported from the Miranda script "file" to be in scope
+in the containing script. Note that "file" should be the name of a
+Miranda source file (by convention these all have names ending in `.m').
+
+The following conventions apply to all filenames in library directives:
+ 1) A fileid can be an arbitrary UNIX pathname
+ 2) If the fileid given does not end in `.m' this is added.
+ 3) If the fileid is surrounded by angle brackets instead of string
+quotes it is assumed to be a pathname relative to the `miralib'
+directory, otherwise it is taken to be relative to the directory of the
+script in which the directive occurs. (Examples, "pig" means "pig.m",
+<stdenv> means "/usr/lib/miralib/stdenv.m")
+
+In addition (if you are using Berkeley UNIX or a derivative) the `~'
+convention of the cshell may be used to abbreviate home directories.
+That is `~' abbreviates your own home directory, and ~jack abbreviates
+jack's home directory, at the front of any pathname.
+
+The file mentioned in a %_i_n_c_l_u_d_e directive must contain a CORRECT,
+CLOSED Miranda script. (That is it must have no syntax or type errors,
+and no undefined names.) An attempt to %_i_n_c_l_u_d_e a file which violates
+these conditions will be rejected by the compiler as a syntax error in
+the script containing the %_i_n_c_l_u_d_e statement.
+
+It is also illegal to %_i_n_c_l_u_d_e a script which causes nameclashes, either
+against top-level identifiers of the including script or those of other
+%_i_n_c_l_u_d_e directives in the script.
+
+The effect of an %_i_n_c_l_u_d_e directive can be modified by following it with
+one or more aliases (which are used to remove nameclashes between
+identifiers exported from the included script and those of the current
+script or of other %_i_n_c_l_u_d_e files). There are two forms of alias,
+`new/old' which renames and `-old' which suppresses an identifier
+altogether.
+
+For example suppose we wish to include the file "mike" but it contains
+two identifiers, f and g say, which clash with top-level bindings of
+these identifiers in the current script. We wish to use the "mike"
+definition of `f', but his `g' is of no interest. The following
+directive could be used.
+
+%_i_n_c_l_u_d_e "mike" -g mike_f/f
+
+Any other identifiers exported from "mike", not specifically mentioned
+in the aliases, will be accepted unchanged.
+
+It is permitted to alias typenames, and constructors (say `NEW/OLD') but
+typenames and constructors cannot be suppressed by a `-name' alias.
+Note that if you alias one or more of the constructors of an algebraic
+data type the behaviour of `_s_h_o_w' on objects of that type will be
+modified in the appropriate way.
+
+A file which has been %included may itself contain %_i_n_c_l_u_d_e directives,
+and so on, to any reasonable depth. A (directly or indirectly) cyclic
+%_i_n_c_l_u_d_e is not permitted, however.
+
+The `?identifier' command can be used to find the ultimate place of
+definition of an imported identifier. When aliasing has taken place the
+`?identifier' command will give both the current and the original name
+of an aliased identifier. If your installed editor is `vi' the
+`??identifier' command will open the appropriate source file at the
+definition of the identifier. (There is also a command `/find
+identifier' which is like `?identifier' but will recognise an alias
+under its original name.)
+
+Every script behaves as though it contained the directive
+ %_i_n_c_l_u_d_e <stdenv>
+
+It is therefore illegal to %_i_n_c_l_u_d_e the standard environment explicitly,
+as this will lead to huge number of name clashes (because it is now
+present twice). As a consequence there is currently no way of aliasing
+or suppressing the names in the standard environment. (This will be
+fixed in the future by providing a directive for suppressing the
+implicit inclusion of <stdenv>.)
+------------------------------------------------------------------------
+
+%_e_x_p_o_r_t parts
+
+Any (correct, closed) Miranda script can be %included in another script
+(there is no notion of a "module" as something with a different syntax
+from an ordinary script). By default the names exported from a script
+are all those defined in it, at top level, but none of those acquired by
+a %_i_n_c_l_u_d_e of another file. This behaviour can be modified (either to
+export more or to export less than the default) by placing a %_e_x_p_o_r_t
+directive in the script, specifying a list of `parts' to be exported to
+an including file.
+
+The presence of a %_e_x_p_o_r_t directive in a script has no effect on its
+behaviour when it is the current script of a Miranda session - it is
+effective only when the script is %included in another. A script may
+contain at most one %_e_x_p_o_r_t directive. This can be anywhere in the
+script, but to avoid nasty surprises it is advisable to place it near
+the top.
+
+Each `part' listed in the export directive must be one of the following:
+ identifier (variable or typename)
+ fileid (in quotes, conventions as described above)
+ the symbol `+'
+ -identifier
+
+Notice that constructors need not (and cannot) be listed explicitly in
+an %_e_x_p_o_r_t directive - if you export an algebraic typename, its
+constructors are AUTOMATICALLY exported along with it. The consequence
+of this is that you cannot use %_e_x_p_o_r_t to create an abstract data type,
+by "hiding information" about how an algebraic type was formed. If you
+want to create an abstract data type you must use the _a_b_s_t_y_p_e mechanism
+- see separate manual entry.
+
+If a fileid is present in the export list, this must be the name of a
+file which is %included in the exporting script, and the effect is that
+all the bindings acquired by that %_i_n_c_l_u_d_e statement (as modified by
+aliases if present) are re-exported. Allowing fileid's in the export
+list is merely a piece of shorthand, which can be used to avoid writing
+out long lists of names.
+
+The symbol `+' is allowed in an export list as an abbreviation for all
+the top-level identifiers defined in the current script.
+
+The default %_e_x_p_o_r_t directive (i.e. that which is assumed if no %_e_x_p_o_r_t
+statement is present) is therefore
+ %_e_x_p_o_r_t +
+This will export all the top-level identifiers of the current script,
+but not those acquired by %_i_n_c_l_u_d_e directives.
+
+Finally, the notation `-identifier' is allowed in an export list to
+indicate that this identifier NOT to be exported. This is useful if you
+have used a fileid or the symbol `+' to abbreviate a list of names, and
+wish to subtract some of these names from the final export list.
+
+An example - the following export statement exports all the top-level
+identifiers of the current script, except `flooby'.
+ %_e_x_p_o_r_t + -flooby
+
+The order of appearance of the items in an export list is of no
+significance, and repetitions are ignored. A negative occurrence of an
+identifier overrides any number of positive occurrences.
+
+It is possible to find out what names are exported from a given Miranda
+script (or scripts) by calling, from UNIX, the command
+ `mira -exports files' (the extension `.m' will be added to each file
+name if missing). This will list (to stdout) for each file the exported
+names together with their types.
+------------------------------------------------------------------------
+
+_S_o_m_e_ _e_x_a_m_p_l_e_s
+
+(i) There are two scripts, called "liba.m" and "libb.m" say, containing
+useful definitions. For convenience we wish to combine them into a
+single larger library called say, "libc.m". The following text inside
+the file "libc.m" will accomplish this.
+
+ %_e_x_p_o_r_t "liba" "libb"
+ %_i_n_c_l_u_d_e "liba"
+ %_i_n_c_l_u_d_e "libb"
+
+You will notice that when "libc.m" is compiled, this does NOT cause
+recompilation of "liba.m" and "libb.m" (see section on separate
+compilation - the compiler is able to create an object code file for
+"libc.m", called "libc.x", by combining "liba.x" and "libb.x" in an
+appropriate way). This economy in recompilation effort is one reason
+why %_i_n_c_l_u_d_e is a better mechanism than the simpler textual directive
+%_i_n_s_e_r_t (see section on compiler directives).
+
+We could if we wished add some definitions to "libc.m" - if the
+corresponding names are added to the %_e_x_p_o_r_t statement these bindings
+will then be exported along with those of the two sublibraries. Of
+course if we don't add the names of the locally defined objects to the
+%_e_x_p_o_r_t directive they will be `private definitions' of "libc.m", not
+visible to includors.
+
+Recall that if no %_e_x_p_o_r_t is directive is present, then ONLY the
+immediate definitions (if any) of "libc.m" will be exported. So a
+script which contains only %_i_n_c_l_u_d_e directives and no %_e_x_p_o_r_t cannot be
+usefully %included in another script (it is however perfectly acceptable
+as a current script).
+
+(ii) [More technical - omit on first reading]
+ Our second group of examples is chosen to bring out some issues which
+arise when exporting types between scripts. Suppose we have the
+following script, called "trees.m"
+
+ tree * ::= NILT | NODE * (tree *) (tree *)
+ reflect :: tree *->tree *
+ reflect NILT = NILT
+ reflect (NODE a x y) = NODE a(reflect y)(reflect x)
+
+(a) If in another script we write `%_i_n_c_l_u_d_e "trees"', the following
+bindings will be imported - tree NILT NODE reflect. Now suppose we
+modify the "trees.m" by placing in it the following directive - `%_e_x_p_o_r_t
+reflect'. When the modified "trees.m" script is included in another, we
+will get the following error message from the compilation of the
+including script:
+
+ MISSING TYPENAME
+ the following type is needed but has no name in this scope:
+ 'tree' of file "trees.m", needed by: reflect;
+ typecheck cannot proceed - compilation abandoned
+
+Explanation - it is illegal to export an identifier to a place where its
+type, or any part of its type, is unknown. In this situation we call
+reflect a `type-orphan' - it has lost one of its parents!
+
+(b) Readoption of a type-orphan (a more subtle example). Assuming the
+"trees.m" script in its original form as above, we construct the
+following file "treelib.m"
+
+ %_e_x_p_o_r_t size
+ %_i_n_c_l_u_d_e "trees"
+ size :: tree *->num
+ size NILT = 0
+ size (NODE a x y) = 1+size x+size y
+
+If we %_i_n_c_l_u_d_e the above script in another as it stands, we will of
+course get a missing typename diagnostic for `size' - consider however
+the following script
+
+ %_i_n_c_l_u_d_e "treelib"
+ %_i_n_c_l_u_d_e "trees"
+ ... (etc)
+
+Everything is now ok, because a name for size's missing parent is
+imported through another route (the second %_i_n_c_l_u_d_e statement). The
+Miranda compiler recognises the `tree' type imported by the second
+%_i_n_c_l_u_d_e as being the same one as that referred to inside "treelib.m",
+because it originates (albeit via different routes) from the SAME
+SOURCEFILE. A `tree' type imported from a different original
+sourcefile, even if it had the same constructor names with the same
+field types, would be recognised as a different type.
+
+[Note: the Miranda compiler is always able to recognise when the same
+source file is inherited via different routes, including in cases
+involving files with multiple pathnames due to the presence of (hard or
+symblic) links.]
+
+[Further note: the lexical directive %_i_n_s_e_r_t (see compiler directives)
+should be regarded as making a _t_e_x_t_u_a_l_ _c_o_p_y of the material from the
+inserted file into the file containing the %_i_n_s_e_r_t directive - if the
+text of a type definition (in ::= or abstype) is copied in this way, the
+compiler will regard the %_i_n_s_e_r_t as having created a new type in each
+such case, not identical with that in the inserted file.]
+
+(c) Last example (typeclash). Finally note that that it is illegal for
+the same original type to be imported twice into the same scope even
+under different names. Consider the following script
+
+ %_i_n_c_l_u_d_e "trees" shrub/tree Leaf/NILT Fork/NODE -reflect
+ %_i_n_c_l_u_d_e "trees"
+ ... (etc)
+
+The first %_i_n_c_l_u_d_e taken on its own is perfectly ok - we have imported
+the `tree' type, and renamed everything in it by using aliases. However
+we have also inherited the `tree' type under its original name, via the
+second %_i_n_c_l_u_d_e. The compiler will reject the script with the following
+message:
+
+ TYPECLASH - the following type is multiply named:
+ 'tree' of file "trees.m", as: shrub,tree;
+ typecheck cannot proceed - compilation abandoned
+
+The rule that a type can have at most one name in a given scope applies
+to both algebraic types and abstract types (it does not apply to synonym
+types, because these are not `real' types but mere macro's - you can
+have any number of synonyms for `tree' in scope at the same time - as
+long as the underlying `real' type has a unique name).
+
+Typeclashes are illegal in Miranda in order to preserve the following
+two principles. (i) In any given scope, each possible type must have a
+unique canonical form (obtained by expanding out synonyms, and renaming
+generic type variables in a standard way). (ii) Each object of a
+`printable type' must have, in any given scope, a unique external
+representation (ruling out multiply named constructors). The first
+principle is necessary to the functioning of the typechecker, the second
+is demanded by the requirement that the function `_s_h_o_w' be referentially
+transparent.
+