summaryrefslogtreecommitdiff
path: root/doc/gf-modules.html
diff options
context:
space:
mode:
authoraarne <aarne@cs.chalmers.se>2008-06-27 11:32:49 +0000
committeraarne <aarne@cs.chalmers.se>2008-06-27 11:32:49 +0000
commit64d2a981a99c8f48f85c4efd0cecd1db1e5ce93a (patch)
tree8ec777785ae6b99e4ade6ab7c97a7653317b82ad /doc/gf-modules.html
parent032531c6a690edbb377ff11ee2a743a30c5bf500 (diff)
more rm in doc
Diffstat (limited to 'doc/gf-modules.html')
-rw-r--r--doc/gf-modules.html1183
1 files changed, 0 insertions, 1183 deletions
diff --git a/doc/gf-modules.html b/doc/gf-modules.html
deleted file mode 100644
index 6292bd855..000000000
--- a/doc/gf-modules.html
+++ /dev/null
@@ -1,1183 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-<HEAD>
-<META NAME="generator" CONTENT="http://txt2tags.sf.net">
-<TITLE>The Module System of GF</TITLE>
-</HEAD><BODY BGCOLOR="white" TEXT="black">
-<P ALIGN="center"><CENTER><H1>The Module System of GF</H1>
-<FONT SIZE="4">
-<I>Aarne Ranta</I><BR>
-8/4/2005 - 5/7/2007
-</FONT></CENTER>
-
-<P></P>
-<HR NOSHADE SIZE=1>
-<P></P>
- <UL>
- <LI><A HREF="#toc1">The principal module types</A>
- <UL>
- <LI><A HREF="#toc2">Abstract syntax</A>
- <UL>
- <LI><A HREF="#toc3">Compilation of abstract syntax</A>
- </UL>
- <LI><A HREF="#toc4">Concrete syntax</A>
- <LI><A HREF="#toc5">Top-level grammar</A>
- <UL>
- <LI><A HREF="#toc6">Compiling top-level grammars</A>
- <LI><A HREF="#toc7">Using top-level grammars</A>
- </UL>
- <LI><A HREF="#toc8">Multilingual grammar</A>
- <UL>
- <LI><A HREF="#toc9">Using multilingual grammars</A>
- </UL>
- <LI><A HREF="#toc10">Resource modules</A>
- <UL>
- <LI><A HREF="#toc11">Compiling resource modules</A>
- <LI><A HREF="#toc12">Using resource modules</A>
- </UL>
- <LI><A HREF="#toc13">Inheritance</A>
- <UL>
- <LI><A HREF="#toc14">Multiple inheritance</A>
- <LI><A HREF="#toc15">Restricted inheritance</A>
- <LI><A HREF="#toc16">Compiling inheritance</A>
- <LI><A HREF="#toc17">Inspecting grammar hierarchies</A>
- </UL>
- <LI><A HREF="#toc18">Reuse of top-level grammars as resources</A>
- </UL>
- <LI><A HREF="#toc19">Additional module types</A>
- <UL>
- <LI><A HREF="#toc20">Interfaces, instances, and incomplete grammars</A>
- <UL>
- <LI><A HREF="#toc21">Using an interface</A>
- <LI><A HREF="#toc22">Instantiating an interface</A>
- <LI><A HREF="#toc23">Compiling interfaces, instances, and parametrized modules</A>
- </UL>
- </UL>
- <LI><A HREF="#toc24">Summary of module syntax and semantics</A>
- <UL>
- <LI><A HREF="#toc25">Abstract syntax modules</A>
- <LI><A HREF="#toc26">Concrete syntax modules</A>
- <LI><A HREF="#toc27">Resource modules</A>
- <LI><A HREF="#toc28">Interface modules</A>
- <LI><A HREF="#toc29">Instance modules</A>
- <LI><A HREF="#toc30">Instantiated concrete syntax modules</A>
- </UL>
- </UL>
-
-<P></P>
-<HR NOSHADE SIZE=1>
-<P></P>
-<P>
-A GF grammar consists of a set of <B>modules</B>, which can be
-combined in different ways to build different grammars.
-There are several different <B>types of modules</B>:
-</P>
-<UL>
-<LI><CODE>abstract</CODE>
-<LI><CODE>concrete</CODE>
-<LI><CODE>resource</CODE>
-<LI><CODE>interface</CODE>
-<LI><CODE>instance</CODE>
-<LI><CODE>incomplete concrete</CODE>
-</UL>
-
-<P>
-We will go through the module types in this order, which is also
-their order of "importance" from the most basic to
-the more advanced ones.
-</P>
-<P>
-This document presupposes knowledge of GF judgements and expressions, which can
-be gained from the <A HREF="tutorial/gf-tutorial2.html">GF tutorial</A>. It aims
-to give a systamatic description of the module system;
-some tutorial information is repeated to make the document
-self-contained.
-</P>
-<A NAME="toc1"></A>
-<H1>The principal module types</H1>
-<A NAME="toc2"></A>
-<H2>Abstract syntax</H2>
-<P>
-Any GF grammar that is used in an application
-will probably contain at least one module
-of the <CODE>abstract</CODE> module type. Here is an example of
-such a module, defining a fragment of propositional logic.
-</P>
-<PRE>
- abstract Logic = {
- cat Prop ;
- fun Conj : Prop -&gt; Prop -&gt; Prop ;
- fun Disj : Prop -&gt; Prop -&gt; Prop ;
- fun Impl : Prop -&gt; Prop -&gt; Prop ;
- fun Falsum : Prop ;
- }
-</PRE>
-<P>
-The <B>name</B> of this module is <CODE>Logic</CODE>.
-</P>
-<P>
-An <CODE>abstract</CODE> module defines an <B>abstract syntax</B>, which
-is a language-independent representation of a fragment of language.
-It consists of two kinds of <B>judgements</B>:
-</P>
-<UL>
-<LI><CODE>cat</CODE> judgements telling what <B>categories</B> there are
- (types of abstract syntax trees)
-<LI><CODE>fun</CODE> judgements telling what <B>functions</B> there are
- (to build abstract syntax trees)
-</UL>
-
-<P>
-There can also be <CODE>def</CODE> and <CODE>data</CODE> judgements in an
-abstract syntax.
-</P>
-<A NAME="toc3"></A>
-<H3>Compilation of abstract syntax</H3>
-<P>
-The GF grammar compiler expects to find the module <CODE>Logic</CODE> in a file named
-<CODE>Logic.gf</CODE>. When the compiler is run, it produces
-another file, named <CODE>Logic.gfc</CODE>. This file is in the
-format called <B>canonical GF</B>, which is the "machine language"
-of GF. Next time that the module <CODE>Logic</CODE> is needed in
-compiling a grammar, it can be read from the compiled (<CODE>gfc</CODE>)
-file instead of the source (<CODE>gf</CODE>) file, unless the source
-has been changed after the compilation.
-</P>
-<A NAME="toc4"></A>
-<H2>Concrete syntax</H2>
-<P>
-In order for a GF grammar to describe a concrete language, the abstract
-syntax must be completed with a <B>concrete syntax</B> of it.
-For this purpose, we use modules of type <CODE>concrete</CODE>: for instance,
-</P>
-<PRE>
- concrete LogicEng of Logic = {
- lincat Prop = {s : Str} ;
- lin Conj a b = {s = a.s ++ "and" ++ b.s} ;
- lin Disj a b = {s = a.s ++ "or" ++ b.s} ;
- lin Impl a b = {s = "if" ++ a.s ++ "then" ++ b.s} ;
- lin Falsum = {s = ["we have a contradiction"]} ;
- }
-</PRE>
-<P>
-The module <CODE>LogicEng</CODE> is a concrete syntax <CODE>of</CODE> the
-abstract syntax <CODE>Logic</CODE>. The GF grammar compiler checks that
-the concrete is valid with respect to the abstract syntax <CODE>of</CODE>
-which it is claimed to be. The validity requires that there has to be
-</P>
-<UL>
-<LI>a <CODE>lincat</CODE> judgement for each <CODE>cat</CODE> judgement, telling what the
- <B>linearization types</B> of categories are
-<LI>a <CODE>lin</CODE> judgement for each <CODE>fun</CODE> judgement, telling what the
- <B>linearization functions</B> corresponding to functions are
-</UL>
-
-<P>
-Validity also requires that the linearization functions defined by
-<CODE>lin</CODE> judgements are type-correct with respect to the
-linearization types of the arguments and value of the function.
-</P>
-<P>
-There can also be <CODE>lindef</CODE> and <CODE>printname</CODE> judgements in a
-concrete syntax.
-</P>
-<A NAME="toc5"></A>
-<H2>Top-level grammar</H2>
-<P>
-When a <CODE>concrete</CODE> module is successfully compiled, a <CODE>gfc</CODE>
-file is produced in the same way as for <CODE>abstract</CODE> modules. The
-pair of an <CODE>abstract</CODE> and a corresponding <CODE>concrete</CODE> module
-is a <B>top-level grammar</B>, which can be used in the GF system to
-perform various tasks. The most fundamental tasks are
-</P>
-<UL>
-<LI><B>linearization</B>: take an abstract syntax tree and find the corresponding string
-<LI><B>parsing</B>: take a string and find the corresponding abstract syntax
- trees (which can be zero, one, or many)
-</UL>
-
-<P>
-In the current grammar, infinitely many trees and strings are recognized, although
-no very interesting ones. For example, the tree
-</P>
-<PRE>
- Impl (Disj Falsum Falsum) Falsum
-</PRE>
-<P>
-has the linearization
-</P>
-<PRE>
- if we have a contradiction or we have a contradiction then we have a contradiction
-</PRE>
-<P>
-which in turn can be parsed uniquely as that tree.
-</P>
-<A NAME="toc6"></A>
-<H3>Compiling top-level grammars</H3>
-<P>
-When GF compiles the module <CODE>LogicEng</CODE> it also has to compile
-all modules that it <B>depends</B> on (in this case, just <CODE>Logic</CODE>).
-The compilation process starts with dependency analysis to find
-all these modules, recursively, starting from the explicitly imported one.
-The compiler then reads either <CODE>gf</CODE> or <CODE>gfc</CODE> files, in
-a dependency order. The decision on which files to read depends on
-time stamps and dependencies in a natural way, so that all and only
-those modules that have to be compiled are compiled. (This behaviour can
-be changed with flags, see below.)
-</P>
-<A NAME="toc7"></A>
-<H3>Using top-level grammars</H3>
-<P>
-To use a top-level grammar in the GF system, one uses the <CODE>import</CODE>
-command (short name <CODE>i</CODE>). For instance,
-</P>
-<PRE>
- i LogicEng.gf
-</PRE>
-<P>
-It is also possible to specify the imported grammar(s) on the command
-line when invoking GF:
-</P>
-<PRE>
- gf LogicEng.gf
-</PRE>
-<P>
-Various <B>compilation flags</B> can be added to both ways of compiling a module:
-</P>
-<UL>
-<LI><CODE>-src</CODE> forces compilation form source files
-<LI><CODE>-v</CODE> gives more verbose information on compilation
-<LI><CODE>-s</CODE> makes compilation silent (except if it fails with an error message)
-</UL>
-
-<P>
-A complete list of flags can be obtained in GF by <CODE>help i</CODE>.
-</P>
-<P>
-Importing a grammar makes it visible in GF's <B>internal state</B>. To see
-what modules are available, use the command <CODE>print_options</CODE> (<CODE>po</CODE>).
-You can empty the state with the command <CODE>empty</CODE> (<CODE>e</CODE>); this is
-needed if you want to read in grammars with a different abstract syntax
-than the current one without exiting GF.
-</P>
-<P>
-Grammar modules can reside in different directories. They can then be found
-by means of a <B>search path</B>, which is a flag such as
-</P>
-<PRE>
- -path=.:api/toplevel:prelude
-</PRE>
-<P>
-given to the <CODE>import</CODE> command or the shell command invoking GF.
-(It can also be defined in the grammar file; see below.) The compiler
-writes every <CODE>gfc</CODE> file in the same directory as the corresponding
-<CODE>gf</CODE> file.
-</P>
-<P>
-The <CODE>path</CODE> is relative to the working directory <CODE>pwd</CODE>, so that
-all directories listed are primarily interpreted as subdirectories of
-<CODE>pwd</CODE>. Secondarily, they are searched relative to the value of the
-environment variable <CODE>GF_LIB_PATH</CODE>, which is by default set to
-<CODE>/usr/local/share/GF</CODE>.
-</P>
-<P>
-Parsing and linearization can be performed with the <CODE>parse</CODE>
-(<CODE>p</CODE>) and <CODE>linearize</CODE> (<CODE>l</CODE>) commands, respectively.
-For instance,
-</P>
-<PRE>
- &gt; l Impl (Disj Falsum Falsum) Falsum
- if we have a contradiction or we have a contradiction then we have a contradiction
-
- &gt; p -cat=Prop "we have a contradiction"
- Falsum
-</PRE>
-<P>
-Notice that the <CODE>parse</CODE> command needs the parsing category
-as a flag. This necessary since a grammar can have several
-possible parsing categories ("entry points").
-</P>
-<A NAME="toc8"></A>
-<H2>Multilingual grammar</H2>
-<P>
-One <CODE>abstract</CODE> syntax can have several <CODE>concrete</CODE> syntaxes.
-Here are two new ones for <CODE>Logic</CODE>:
-</P>
-<PRE>
- concrete LogicFre of Logic = {
- lincat Prop = {s : Str} ;
- lin Conj a b = {s = a.s ++ "et" ++ b.s} ;
- lin Disj a b = {s = a.s ++ "ou" ++ b.s} ;
- lin Impl a b = {s = "si" ++ a.s ++ "alors" ++ b.s} ;
- lin Falsum = {s = ["nous avons une contradiction"]} ;
- }
-
- concrete LogicSymb of Logic = {
- lincat Prop = {s : Str} ;
- lin Conj a b = {s = "(" ++ a.s ++ "&amp;" ++ b.s ++ ")"} ;
- lin Disj a b = {s = "(" ++ a.s ++ "v" ++ b.s ++ ")"} ;
- lin Impl a b = {s = "(" ++ a.s ++ "-&gt;" ++ b.s ++ ")"} ;
- lin Falsum = {s = "_|_"} ;
- }
-</PRE>
-<P>
-The four modules <CODE>Logic</CODE>, <CODE>LogicEng</CODE>, <CODE>LogicFre</CODE>, and
-<CODE>LogicSymb</CODE> together form a <B>multilingual grammar</B>, in which
-it is possible to perform parsing and linearization with respect to any
-of the concrete syntaxes. As a combination of parsing and linearization,
-one can also perform <B>translation</B> from one language to another.
-(By <B>language</B> we mean the set of expressions generated by one
-concrete syntax.)
-</P>
-<A NAME="toc9"></A>
-<H3>Using multilingual grammars</H3>
-<P>
-Any combination of abstract syntax and corresponding concrete syntaxes
-is thus a multilingual grammar. With many languages and other enrichments
-(as described below), a multilingual grammar easily grows to the size of
-tens of modules. The grammar developer, having finished her job, can
-package the result in a <B>multilingual canonical grammar</B>, a file
-with the suffix <CODE>.gfcm</CODE>. For instance, to compile the set of grammars
-described by now, the following sequence of GF commands can be used:
-</P>
-<PRE>
- i LogicEng.gf
- i LogicFre.gf
- i LogicSymb.gf
- pm | wf logic.gfcm
-</PRE>
-<P>
-The "end user" of the grammar only needs the file <CODE>logic.gfcm</CODE> to
-access all the functionality of the multilingual grammar. It can be
-imported in the GF system in the same way as <CODE>.gf</CODE> files. But
-it can also be used in the
-<A HREF="http://www.cs.chalmers.se/~bringert/gf/gf-java.html">Embedded Java Interpreter for GF</A>
-to build Java programs of which the multilingual grammar functionalities
-(linearization, parsing, translation) form a part.
-</P>
-<P>
-In a multilingual grammar, the concrete syntax module names work as
-names of languages that can be selected for linearization and parsing:
-</P>
-<PRE>
- &gt; l -lang=LogicFre Impl Falsum Falsum
- si nous avons une contradiction alors nous avons une contradiction
-
- &gt; l -lang=LogicSymb Impl Falsum Falsum
- ( _|_ -&gt; _|_ )
-
- &gt; p -cat=Prop -lang=LogicSymb "( _|_ &amp; _|_ )"
- Conj Falsum Falsum
-</PRE>
-<P>
-The option <CODE>-multi</CODE> gives linearization to all languages:
-</P>
-<PRE>
- &gt; l -multi Impl Falsum Falsum
- if we have a contradiction then we have a contradiction
- si nous avons une contradiction alors nous avons une contradiction
- ( _|_ -&gt; _|_ )
-</PRE>
-<P>
-Translation can be obtained by using a <B>pipe</B> from a parser
-to a linearizer:
-</P>
-<PRE>
- &gt; p -cat=Prop -lang=LogicSymb "( _|_ &amp; _|_ )" | l -lang=LogicEng
- if we have a contradiction then we have a contradiction
-</PRE>
-<P></P>
-<A NAME="toc10"></A>
-<H2>Resource modules</H2>
-<P>
-The <CODE>concrete</CODE> modules shown above would look much nicer if
-we used the main idea of functional programming: avoid repetitive
-code by using <B>functions</B> that capture repeated patterns of
-expressions. A collection of such functions can be a valuable
-<B>resource</B> for a programmer, reusable in many different
-top-level grammars. Thus we introduce the <CODE>resource</CODE>
-module type, with the first example
-</P>
-<PRE>
- resource Util = {
- oper SS : Type = {s : Str} ;
- oper ss : Str -&gt; SS = \s -&gt; {s = s} ;
- oper paren : Str -&gt; Str = \s -&gt; "(" ++ s ++ ")" ;
- oper infix : Str -&gt; SS -&gt; SS -&gt; SS = \h,x,y -&gt;
- ss (x.s ++ h ++ y.s) ;
- oper infixp : Str -&gt; SS -&gt; SS -&gt; SS = \h,x,y -&gt;
- ss (paren (infix h x y)) ;
- }
-</PRE>
-<P>
-Modules of <CODE>resource</CODE> type have two forms of judgement:
-</P>
-<UL>
-<LI><CODE>oper</CODE> defining auxiliary operations
-<LI><CODE>param</CODE> defining parameter types
-</UL>
-
-<P>
-A <CODE>resource</CODE> can be used in a <CODE>concrete</CODE> (or another
-<CODE>resource</CODE>) by <CODE>open</CODE>ing it. This means that
-all operations (and parameter types) defined in the resource
-module become usable in module that opens it. For instance,
-we can rewrite the module <CODE>LogicSymb</CODE> much more concisely:
-</P>
-<PRE>
- concrete LogicSymb of Logic = open Util in {
- lincat Prop = SS ;
- lin Conj = infixp "&amp;" ;
- lin Disj = infixp "v" ;
- lin Impl = infixp "-&gt;" ;
- lin Falsum = ss "_|_" ;
- }
-</PRE>
-<P>
-What happens when this variant of <CODE>LogicSymb</CODE> is
-compiled is that the <CODE>oper</CODE>-defined constants
-of <CODE>Util</CODE> are <B>inlined</B> in the
-right-hand-sides of the judgements of <CODE>LogicSymb</CODE>,
-and these expressions are <B>partially evaluated</B>, i.e.
-computed as far as possible. The generated <CODE>gfc</CODE> file
-will look just like the file generated for the first version
-of <CODE>LogicSymb</CODE> - at least, it will do the same job.
-</P>
-<P>
-Several <CODE>resource</CODE> modules can be <CODE>open</CODE>ed
-at the same time. If the modules contain same names, the
-conflict can be resolved by <B>qualified</B> opening and
-reference. For instance,
-</P>
-<PRE>
- concrete LogicSymb of Logic = open Util, Prelude in { ...
- } ;
-</PRE>
-<P>
-(where <CODE>Prelude</CODE> is a standard library of GF) brings
-into scope two definitions of the constant <CODE>SS</CODE>.
-To specify which one is used, you can write
-<CODE>Util.SS</CODE> or <CODE>Prelude.SS</CODE> instead of just <CODE>SS</CODE>.
-You can also introduce abbreviations to avoid long qualifiers, e.g.
-</P>
-<PRE>
- concrete LogicSymb of Logic = open (U=Util), (P=Prelude) in { ...
- } ;
-</PRE>
-<P>
-which means that you can write <CODE>U.SS</CODE> and <CODE>P.SS</CODE>.
-</P>
-<P>
-Judgements of <CODE>param</CODE> and <CODE>oper</CODE> forms may also be used
-in <CODE>concrete</CODE> modules, and they are then considered local
-to those modules, i.e. they are not exported.
-</P>
-<A NAME="toc11"></A>
-<H3>Compiling resource modules</H3>
-<P>
-The compilation of a <CODE>resource</CODE> module differs
-from the compilation of <CODE>abstract</CODE> and
-<CODE>concrete</CODE> modules because <CODE>oper</CODE> operations
-do not in general have values in <CODE>gfc</CODE>. A <CODE>gfc</CODE>
-file <I>is</I> generated, but it contains only
-<CODE>param</CODE> judgements (also recall that <CODE>oper</CODE>s
-are inlined in their top-level use sites, so it is not
-necessary to save them in the compiled grammar).
-However, since computing the operations over and over
-again can be time comsuming, and since type checking
-<CODE>resource</CODE> modules also takes time, a third kind
-of file is generated for resource modules: a <CODE>.gfr</CODE>
-file. This file is written in the GF source code notation,
-but it is type checked and type annotated, and <CODE>oper</CODE>s
-are computed as far as possible.
-</P>
-<P>
-If you look at any <CODE>gfc</CODE> or <CODE>gfr</CODE> file generated
-by the GF compiler, you see that all names have been replaced by
-their qualified variants. This is an important first step (after parsing)
-the compiler does. As for the commands in the GF shell, some output
-qualified names and some not. The difference does not always result
-from firm principles.
-</P>
-<A NAME="toc12"></A>
-<H3>Using resource modules</H3>
-<P>
-The typical use is through <CODE>open</CODE> in a
-<CODE>concrete</CODE> module, which means that
-<CODE>resource</CODE> modules are not imported on their own.
-However, in the developing and testing phase of grammars, it
-can be useful to evaluate <CODE>oper</CODE>s with different
-arguments. To prevent them from being thrown away after inlining, the
-<CODE>-retain</CODE> option can be used:
-</P>
-<PRE>
- &gt; i -retain Util.gf
-</PRE>
-<P>
-The command <CODE>compute_concrete</CODE> (<CODE>cc</CODE>)
-can now be used for evaluating expressions that may contain
-operations defined in <CODE>Util</CODE>:
-</P>
-<PRE>
- &gt; cc ss (paren "foo")
- {s = "(" ++ "foo" ++ ")"}
-</PRE>
-<P>
-To find out what <CODE>oper</CODE>s are available for a given type,
-the command <CODE>show_operations</CODE> (<CODE>so</CODE>) can be used:
-</P>
-<PRE>
- &gt; so SS
- Util.ss : Str -&gt; SS ;
- Util.infix : Str -&gt; SS -&gt; SS -&gt; SS ;
- Util.infixp : Str -&gt; SS -&gt; SS -&gt; SS ;
-</PRE>
-<P></P>
-<A NAME="toc13"></A>
-<H2>Inheritance</H2>
-<P>
-The most characteristic modularity of GF lies in the division of
-grammars into <CODE>abstract</CODE>, <CODE>concrete</CODE>, and
-<CODE>resource</CODE> modules. This permits writing multilingual
-grammar and sharing the maximum of code between different
-languages.
-</P>
-<P>
-In addition to this special kind of modularity, GF provides <B>inheritance</B>,
-which is familiar from other programming languages (in particular,
-object-oriented ones). Inheritance means that a module inherits all
-judgements from another module; we also say that it <B>extends</B>
-the other module. Inheritance is useful to divide big grammars into
-smaller units, and also to reuse the same units in different bigger
-grammars.
-</P>
-<P>
-The first example of inheritance is for abstract syntax. Let us
-extend the module <CODE>Logic</CODE> to <CODE>Arithmetic</CODE>:
-</P>
-<PRE>
- abstract Arithmetic = Logic ** {
- cat Nat ;
- fun Even : Nat -&gt; Prop ;
- fun Odd : Nat -&gt; Prop ;
- fun Zero : Nat ;
- fun Succ : Nat -&gt; Nat ;
- }
-</PRE>
-<P>
-In parallel with the extension of the abstract syntax
-<CODE>Logic</CODE> to <CODE>Arithmetic</CODE>, we can extend
-the concrete syntax <CODE>LogicEng</CODE> to <CODE>ArithmeticEng</CODE>:
-</P>
-<PRE>
- concrete ArithmeticEng of Arithmetic = LogicEng ** open Util in {
- lincat Nat = SS ;
- lin Even x = ss (x.s ++ "is" ++ "even") ;
- lin Odd x = ss (x.s ++ "is" ++ "odd") ;
- lin Zero = ss "zero" ;
- lin Succ x = ss ("the" ++ "successor" ++ "of" ++ x.s) ;
- }
-</PRE>
-<P>
-Another extension of <CODE>Logic</CODE> is <CODE>Geometry</CODE>,
-</P>
-<PRE>
- abstract Geometry = Logic ** {
- cat Point ;
- cat Line ;
- fun Incident : Point -&gt; Line -&gt; Prop ;
- }
-</PRE>
-<P>
-The corresponding concrete syntax is left as exercise.
-</P>
-<A NAME="toc14"></A>
-<H3>Multiple inheritance</H3>
-<P>
-Inheritance can be <B>multiple</B>, which means that a module
-may extend many modules at the same time. Suppose, for instance,
-that we want to build a module for mathematics covering both
-arithmetic and geometry, and the underlying logic. We then write
-</P>
-<PRE>
- abstract Mathematics = Arithmetic, Geometry ** {
- } ;
-</PRE>
-<P>
-We could of course add some new judgements in this module, but
-it is not necessary to do so. If no new judgements are added, the
-module body can be omitted:
-</P>
-<PRE>
- abstract Mathematics = Arithmetic, Geometry ;
-</PRE>
-<P></P>
-<P>
-The module <CODE>Mathematics</CODE> shows that it is possibe
-to extend a module already built by extension. The correctness
-criterion for extensions is that the same name
-(<CODE>cat</CODE>, <CODE>fun</CODE>, <CODE>oper</CODE>, or <CODE>param</CODE>)
-may not be defined twice in the resulting union of names.
-That the names defined in <CODE>Logic</CODE> are "inherited twice"
-by <CODE>Mathematics</CODE> (via both <CODE>Arithmetic</CODE> and
-<CODE>Geometry</CODE>) is no violation of this rule; the usual
-problems of multiple inheritance do not arise, since
-the definitions of inherited constants cannot be changed.
-</P>
-<A NAME="toc15"></A>
-<H3>Restricted inheritance</H3>
-<P>
-Inheritance can be <B>restricted</B>, which means that only some of
-the constants are inherited. There are two dual notations for this:
-</P>
-<PRE>
- A [f,g]
-</PRE>
-<P>
-meaning that <I>only</I> <CODE>f</CODE> and <CODE>g</CODE> are inherited from <CODE>A</CODE>, and
-</P>
-<PRE>
- A-[f,g]
-</PRE>
-<P>
-meaning that <I>everything except</I> <CODE>f</CODE> is <CODE>g</CODE> are inherited from <CODE>A</CODE>.
-</P>
-<P>
-Constants that are not inherited may be redefined in the inheriting module.
-</P>
-<A NAME="toc16"></A>
-<H3>Compiling inheritance</H3>
-<P>
-Inherited judgements are not copied into the inheriting modules.
-Instead, an <B>indirection</B> is created for each inherited name,
-as can be seen by looking into the generated <CODE>gfc</CODE> (and
-<CODE>gfr</CODE>) files. Thus for instance the names
-</P>
-<PRE>
- Mathematics.Prop Arithmetic.Prop Geometry.Prop Logic.Prop
-</PRE>
-<P>
-all refer to the same category, declared in the module
-<CODE>Logic</CODE>.
-</P>
-<A NAME="toc17"></A>
-<H3>Inspecting grammar hierarchies</H3>
-<P>
-The command <CODE>visualize_graph</CODE> (<CODE>vg</CODE>) shows the
-dependency graph in the current GF shell state. The graph can
-also be saved in a file and used e.g. in documentation, by the
-command <CODE>print_multi -graph</CODE> (<CODE>pm -graph</CODE>).
-</P>
-<P>
-The <CODE>vg</CODE> command uses the free software packages Graphviz (commad <CODE>dot</CODE>)
-and Ghostscript (command <CODE>gv</CODE>).
-</P>
-<A NAME="toc18"></A>
-<H2>Reuse of top-level grammars as resources</H2>
-<P>
-Top-level grammars have a straightforward translation to
-<CODE>resource</CODE> modules. The translation concerns
-pairs of abstract-concrete judgements:
-</P>
-<PRE>
- cat C ; ===&gt; oper C : Type = T ;
- lincat C = T ;
-
- fun f : A ; ===&gt; oper f : A = t ;
- lin f = t ;
-</PRE>
-<P>
-Due to this translation, a <CODE>concrete</CODE> module
-can be <CODE>open</CODE>ed in the same way as a
-<CODE>resource</CODE> module; the translation is done
-on the fly (it is computationally very cheap).
-</P>
-<P>
-Modular grammar engineering often means that some grammarians
-focus on the semantics of the domain whereas others take care
-of linguistic details. Thus a typical reuse opens a
-linguistically oriented <B>resource grammar</B>,
-</P>
-<PRE>
- abstract Resource = {
- cat S ; NP ; A ;
- fun PredA : NP -&gt; A -&gt; S ;
- }
- concrete ResourceEng of Resource = {
- lincat S = ... ;
- lin PredA = ... ;
- }
-</PRE>
-<P>
-The <B>application grammar</B>, instead of giving linearizations
-explicitly, just reduces them to categories and functions in the
-resource grammar:
-</P>
-<PRE>
- concrete ArithmeticEng of Arithmetic = LogicEng ** open ResourceEng in {
- lincat Nat = NP ;
- lin Even x = PredA x (regA "even") ;
- }
-</PRE>
-<P>
-If the resource grammar is only capable of generating grammatically
-correct expressions, then the grammaticality of the application
-grammar is also guaranteed: the type checker of GF is used as
-grammar checker.
-To guarantee distinctions between categories that have
-the same linearization type, the actual translation used
-in GF adds to every linearization type and linearization
-a <B>lock field</B>,
-</P>
-<PRE>
- cat C ; ===&gt; oper C : Type = T ** {lock_C : {}} ;
- lincat C = T ;
-
- fun f : C_1 ... C_n -&gt; C ; ===&gt; oper f : C_1 ... C_n -&gt; C = \x_1,...,x_n -&gt;
- lin f = t ; t x_1 ... x_n ** {lock_C = &amp;lt;&gt;};
-</PRE>
-<P>
-(Notice that the latter translation is type-correct because of
-record subtyping, which means that <CODE>t</CODE> can ignore the
-lock fields of its arguments.) An application grammarian who
-only uses resource grammar categories and functions never
-needs to write these lock fields herself. Having to do so
-serves as a warning that the grammaticality guarantee given
-by the resource grammar no longer holds.
-</P>
-<P>
-<B>Note</B>. The lock field mechanism is experimental, and may be changed
-to a stronger abstraction mechnism in the future. This may result in
-hand-written lock fields ceasing to work.
-</P>
-<A NAME="toc19"></A>
-<H1>Additional module types</H1>
-<A NAME="toc20"></A>
-<H2>Interfaces, instances, and incomplete grammars</H2>
-<P>
-One difference between top-level grammars and <CODE>resource</CODE>
-modules is that the former systematically separete the
-declarations of categories and functions from their definitions.
-In the reuse translation creating and <CODE>oper</CODE> judgement,
-the declaration coming from the <CODE>abstract</CODE> module is put
-together with the definition coming from the <CODE>concrete</CODE>
-module.
-</P>
-<P>
-However, the separation of declarations and definitions is so
-useful a notion that GF also has specific modules types that
-<CODE>resource</CODE> modules into two parts. In this splitting,
-an <CODE>interface</CODE> module corresponds to an abstract syntax,
-in giving the declarations of operations (and parameter types).
-For instance, a generic markup interface would look as follows:
-</P>
-<PRE>
- interface Markup = open Util in {
- oper Boldface : Str -&gt; Str ;
- oper Heading : Str -&gt; Str ;
- oper markupSS : (Str -&gt; Str) -&gt; SS -&gt; SS = \f,r -&gt;
- ss (f r.s) ;
- }
-</PRE>
-<P>
-The definitions of the constants declared in an <CODE>interface</CODE>
-are given in an <CODE>instance</CODE> module (which is always <CODE>of</CODE>
-an interface, in the same way as a <CODE>concrete</CODE> is always
-<CODE>of</CODE> an abstract). The following <CODE>instance</CODE>s
-define markup in HTML and latex.
-</P>
-<PRE>
- instance MarkupHTML of Markup = open Util in {
- oper Boldface s = "&amp;lt;b&gt;" ++ s ++ "&amp;lt;/b&gt;" ;
- oper Heading s = "&amp;lt;h2&gt;" ++ s ++ "&amp;lt;/h2&gt;" ;
- }
-
- instance MarkupLatex of Markup = open Util in {
- oper Boldface s = "\\textbf{" ++ s ++ "}" ;
- oper Heading s = "\\section{" ++ s ++ "}" ;
- }
-</PRE>
-<P>
-Notice that both <CODE>interface</CODE>s and <CODE>instance</CODE>s may
-<CODE>open</CODE> <CODE>resource</CODE>s (and also reused top-level grammars).
-An <CODE>interface</CODE> may moreover define some of the operations it
-declares; these definitions are inherited by all instances and cannot
-be changed in them. Inheritance by module extension
-is possible, as always, between modules of the same type.
-</P>
-<A NAME="toc21"></A>
-<H3>Using an interface</H3>
-<P>
-An <CODE>interface</CODE> or an <CODE>instance</CODE>
-can be <CODE>open</CODE>ed in
-a <CODE>concrete</CODE> using the same syntax as when opening
-a <CODE>resource</CODE>. For an <CODE>instance</CODE>, the semantics
-is the same as when opening the definitions together with
-the type signatures - one can think of an <CODE>interface</CODE>
-and an <CODE>instance</CODE> of it together forming an ordinary
-<CODE>resource</CODE>. Opening an <CODE>interface</CODE>, however,
-is different: functions that are only declared without
-having a definition cannot be compiled (inlined); neither
-can functions whose definitions depend on undefined functions.
-</P>
-<P>
-A module that <CODE>open</CODE>s an <CODE>interface</CODE> is therefore
-<B>incomplete</B>, and has to be <B>completed</B> with an
-<CODE>instance</CODE> of the interface to become complete. To make
-this situation clear, GF requires any module that opens an
-<CODE>interface</CODE> to be marked as <CODE>incomplete</CODE>. Thus
-the module
-</P>
-<PRE>
- incomplete concrete DocMarkup of Doc = open Markup in {
- ...
- }
-</PRE>
-<P>
-uses the interface <CODE>Markup</CODE> to place markup in
-chosen places in its linearization rules, but the
-implementation of markup - whether in HTML or in LaTeX - is
-left unspecified. This is a powerful way of sharing
-the code of a whole module with just differences in
-the definitions of some constants.
-</P>
-<P>
-Another terminology for <CODE>incomplete</CODE> modules is
-<B>parametrized modules</B> or <B>functors</B>.
-The <CODE>interface</CODE> gives the list of parameters
-that the functor depends on.
-</P>
-<A NAME="toc22"></A>
-<H3>Instantiating an interface</H3>
-<P>
-To complete an <CODE>incomplete</CODE> module, each <CODE>inteface</CODE>
-that it opens has to be provided an <CODE>instance</CODE>. The following
-syntax is used for this:
-</P>
-<PRE>
- concrete DocHTML of Doc = DocMarkup with (Markup = MarkupHTML) ;
-</PRE>
-<P>
-Instantiation of <CODE>Markup</CODE> with <CODE>MarkupLatex</CODE> is
-another one-liner.
-</P>
-<P>
-If more interfaces than one are instantiated, a comma-separated
-list of equations in parentheses is used, e.g.
-</P>
-<PRE>
- concrete MusicIta = MusicI with
- (Syntax = SyntaxIta), (LexMusic = LexMusicIta) ;
-</PRE>
-<P>
-This example shows a common design pattern for building applications:
-the concrete syntax is a functor on the generic resource grammar library
-interface <CODE>Syntax</CODE> and a domain-specific lexicon interface, here
-<CODE>LexMusic</CODE>.
-</P>
-<P>
-All interfaces that are <CODE>open</CODE>ed in the completed model
-must be completed.
-</P>
-<P>
-Notice that the completion of an <CODE>incomplete</CODE> module
-may at the same time extend modules of the same type (which need
-not be completions). It can also add new judgements in a module body,
-and restrict inheritance from the functor.
-</P>
-<PRE>
- concrete MusicIta = MusicI - [f] with
- (Syntax = SyntaxIta), (LexMusic = LexMusicIta) ** {
-
- lin f = ...
-
- } ;
-</PRE>
-<P></P>
-<A NAME="toc23"></A>
-<H3>Compiling interfaces, instances, and parametrized modules</H3>
-<P>
-Interfaces, instances, and parametric modules are purely a
-front-end feature of GF: these module types do not exist in
-the <CODE>gfc</CODE> and <CODE>gfr</CODE> formats. The compiler has
-nevertheless to keep track of their dependencies and modification
-times. Here is a summary of how they are compiled:
-</P>
-<UL>
-<LI>an <CODE>interface</CODE> is compiled into a <CODE>resource</CODE> with an empty body
-<LI>an <CODE>instance</CODE> is compiled into a <CODE>resource</CODE> in union with its
- <CODE>interface</CODE>
-<LI>an <CODE>incomplete</CODE> module (<CODE>concrete</CODE> or <CODE>resource</CODE>) is compiled
- into a module of the same type with an empty body
-<LI>a completion module (<CODE>concrete</CODE> or <CODE>resource</CODE>) is compiled
- into a module of the same type by compiling its functor so that, instead of
- each <CODE>interface</CODE>, its given <CODE>instance</CODE> is used
-</UL>
-
-<P>
-This means that some generated code is duplicated, because those operations that
-do have complete definitions in an <CODE>interface</CODE> are copied to each of
-the <CODE>instances</CODE>.
-</P>
-<A NAME="toc24"></A>
-<H1>Summary of module syntax and semantics</H1>
-<A NAME="toc25"></A>
-<H2>Abstract syntax modules</H2>
-<P>
-Syntax:
-</P>
-<P>
-<CODE>abstract</CODE> A <CODE>=</CODE> (A<sub>1</sub>,...,A<sub>n</sub> <CODE>**</CODE>)?
-<CODE>{</CODE>J<sub>1</sub> <CODE>;</CODE> ... <CODE>;</CODE> J<sub>m</sub> <CODE>; }</CODE>
-</P>
-<P>
-where
-</P>
-<UL>
-<LI>i &gt;= 0
-<LI>each <I>A<sub>i</sub></I> is itself an abstract module,
- possibly with restrictions on inheritance, i.e. <I>A<sub>i</sub></I><CODE>-[</CODE><I>f,..,g</I><CODE>]</CODE>
- or <I>A<sub>i</sub></I><CODE>[</CODE><I>f,..,g</I><CODE>]</CODE>
-<LI>each <I>J<sub>i</sub></I> is a judgement of one of the forms
- <CODE>cat, fun, def, data</CODE>
-</UL>
-
-<P>
-Semantic conditions:
-</P>
-<UL>
-<LI>all inherited names declared in each <I>A<sub>i</sub></I> and <I>A</I> must be distinct
-<LI>names in restriction lists must be defined in the restricted module
-<LI>inherited constants may not depend on names excluded by restriction
-</UL>
-
-<A NAME="toc26"></A>
-<H2>Concrete syntax modules</H2>
-<P>
-Syntax:
-</P>
-<P>
-<CODE>incomplete</CODE>? <CODE>concrete</CODE> C <CODE>of</CODE> A <CODE>=</CODE>
-(C<sub>1</sub>,...,C<sub>n</sub> <CODE>**</CODE>)?
-(<CODE>open</CODE> O<sub>1</sub>,...,O<sub>k</sub> <CODE>in</CODE>)?
-<CODE>{</CODE>J<sub>1</sub> <CODE>;</CODE> ... <CODE>;</CODE> J<sub>m</sub> <CODE>; }</CODE>
-</P>
-<P>
-where
-</P>
-<UL>
-<LI>i &gt;= 0
-<LI><I>A</I> is an abstract module
-<LI>each <I>C<sub>i</sub></I> is a concrete module,
- possibly with restrictions on inheritance, i.e. <I>C<sub>i</sub></I><CODE>-[</CODE><I>f,..,g</I><CODE>]</CODE>
-<LI>each <I>O<sub>i</sub></I> is an open specification, of one of the forms
- <UL>
- <LI><I>R</I>
- <LI><CODE>(</CODE><I>Q</I><CODE>=</CODE><I>R</I><CODE>)</CODE>
- </UL>
-</UL>
-
-<P>
- where <I>R</I> is a resource, instance, or concrete, and <I>Q</I> is any identifier
-</P>
-<UL>
-<LI>each <I>J<sub>i</sub></I> is a judgement of one of the forms
- <CODE>lincat, lin, lindef, printname</CODE>; also the forms <CODE>oper, param</CODE> are
- allowed, but they cannot be inherited.
-</UL>
-
-<P>
-If the modifier <CODE>incomplete</CODE> appears, then any <I>R</I> in
-an open specification may also be an interface or an abstract.
-</P>
-<P>
-Semantic conditions:
-</P>
-<UL>
-<LI>each <CODE>cat</CODE> judgement in <I>A</I>
- must have a corresponding, unique
- <CODE>lincat</CODE> judgement in <I>C</I>
-<LI>each <CODE>fun</CODE> judgement in <I>A</I>
- must have a corresponding, unique
- <CODE>lin</CODE> judgement in <I>C</I>
-<LI>names in restriction lists must be defined in the restricted module
-<LI>inherited constants may not depend on names excluded by restriction
-</UL>
-
-<A NAME="toc27"></A>
-<H2>Resource modules</H2>
-<P>
-Syntax:
-</P>
-<P>
-<CODE>resource</CODE> R <CODE>=</CODE>
-(R<sub>1</sub>,...,R<sub>n</sub> <CODE>**</CODE>)?
-(<CODE>open</CODE> O<sub>1</sub>,...,O<sub>k</sub> <CODE>in</CODE>)?
-<CODE>{</CODE>J<sub>1</sub> <CODE>;</CODE> ... <CODE>;</CODE> J<sub>m</sub> <CODE>; }</CODE>
-</P>
-<P>
-where
-</P>
-<UL>
-<LI>i &gt;= 0
-<LI>each <I>R<sub>i</sub></I> is a resource, instance, or concrete module,
- possibly with restrictions on inheritance, i.e. <I>R<sub>i</sub></I><CODE>-[</CODE><I>f,..,g</I><CODE>]</CODE>
-<LI>each <I>O<sub>i</sub></I> is an open specification, of one of the forms
- <UL>
- <LI><I>P</I>
- <LI><CODE>(</CODE><I>Q</I><CODE>=</CODE><I>R</I><CODE>)</CODE>
- </UL>
-</UL>
-
-<P>
- where <I>P</I> is a resource, instance, or concrete, and <I>Q</I> is any identifier
-</P>
-<UL>
-<LI>each <I>J<sub>i</sub></I> is a judgement of one of the forms <CODE>oper, param</CODE>
-</UL>
-
-<P>
-Semantic conditions:
-</P>
-<UL>
-<LI>all names defined in each <I>R<sub>i</sub></I> and <I>R</I> must be distinct
-<LI>all constants declared must have a definition
-<LI>names in restriction lists must be defined in the restricted module
-<LI>inherited constants may not depend on names excluded by restriction
-</UL>
-
-<A NAME="toc28"></A>
-<H2>Interface modules</H2>
-<P>
-Syntax:
-</P>
-<P>
-<CODE>interface</CODE> R <CODE>=</CODE>
-(R<sub>1</sub>,...,R<sub>n</sub> <CODE>**</CODE>)?
-(<CODE>open</CODE> O<sub>1</sub>,...,O<sub>k</sub> <CODE>in</CODE>)?
-<CODE>{</CODE>J<sub>1</sub> <CODE>;</CODE> ... <CODE>;</CODE> J<sub>m</sub> <CODE>; }</CODE>
-</P>
-<P>
-where
-</P>
-<UL>
-<LI>i &gt;= 0
-<LI>each <I>R<sub>i</sub></I> is an interface or abstract module,
- possibly with restrictions on inheritance, i.e. <I>R<sub>i</sub></I><CODE>-[</CODE><I>f,..,g</I><CODE>]</CODE>
-<LI>each <I>O<sub>i</sub></I> is an open specification, of one of the forms
- <UL>
- <LI><I>P</I>
- <LI><CODE>(</CODE><I>Q</I><CODE>=</CODE><I>R</I><CODE>)</CODE>
- </UL>
-</UL>
-
-<P>
- where <I>P</I> is a resource, instance, or concrete, and <I>Q</I> is any identifier
-</P>
-<UL>
-<LI>each <I>J<sub>i</sub></I> is a judgement of one of the forms <CODE>oper, param</CODE>
-</UL>
-
-<P>
-Semantic conditions:
-</P>
-<UL>
-<LI>all names declared in each <I>R<sub>i</sub></I> and <I>R</I> must be distinct
-<LI>names in restriction lists must be defined in the restricted module
-<LI>inherited constants may not depend on names excluded by restriction
-</UL>
-
-<A NAME="toc29"></A>
-<H2>Instance modules</H2>
-<P>
-Syntax:
-</P>
-<P>
-<CODE>instance</CODE> R <CODE>of</CODE> I <CODE>=</CODE>
-(R<sub>1</sub>,...,R<sub>n</sub> <CODE>**</CODE>)?
-(<CODE>open</CODE> O<sub>1</sub>,...,O<sub>k</sub> <CODE>in</CODE>)?
-<CODE>{</CODE>J<sub>1</sub> <CODE>;</CODE> ... <CODE>;</CODE> J<sub>m</sub> <CODE>; }</CODE>
-</P>
-<P>
-where
-</P>
-<UL>
-<LI>i &gt;= 0
-<LI><I>I</I> is an interface module
-<LI>each <I>R<sub>i</sub></I> is an instance, resource, or concrete module,
- possibly with restrictions on inheritance, i.e. <I>R<sub>i</sub></I><CODE>-[</CODE><I>f,..,g</I><CODE>]</CODE>
-<P></P>
-<LI>each <I>O<sub>i</sub></I> is an open specification, of one of the forms
- <UL>
- <LI><I>P</I>
- <LI><CODE>(</CODE><I>Q</I><CODE>=</CODE><I>R</I><CODE>)</CODE>
- </UL>
-</UL>
-
-<P>
- where <I>P</I> is a resource, instance, or concrete, and <I>Q</I> is any identifier
-</P>
-<UL>
-<LI>each <I>J<sub>i</sub></I> is a judgement of one of the forms
- <CODE>oper, param</CODE>
-</UL>
-
-<P>
-Semantic conditions:
-</P>
-<UL>
-<LI>all names declared in each <I>R<sub>i</sub></I>, <I>I</I>, and <I>R</I> must be distinct
-<LI>all constants declared in <I>I</I> must have a definition either in
- <I>I</I> or <I>R</I>
-<LI>names in restriction lists must be defined in the restricted module
-<LI>inherited constants may not depend on names excluded by restriction
-</UL>
-
-<A NAME="toc30"></A>
-<H2>Instantiated concrete syntax modules</H2>
-<P>
-Syntax:
-</P>
-<P>
-<CODE>concrete</CODE> C <CODE>of</CODE> A <CODE>=</CODE>
-(C<sub>1</sub>,...,C<sub>n</sub> <CODE>**</CODE>)?
-B
-<CODE>with</CODE>
-<CODE>(</CODE>I<sub>1</sub> <CODE>=</CODE>J<sub>1</sub><CODE>),</CODE> ...
-<CODE>, (</CODE>I<sub>p</sub> <CODE>=</CODE>J<sub>p</sub><CODE>)</CODE>
-(<CODE>-</CODE>? <CODE>[</CODE>c<sub>1</sub>,...,c<sub>q</sub> <CODE>]</CODE>)?
-(<CODE>**</CODE>?
-(<CODE>open</CODE> O<sub>1</sub>,...,O<sub>k</sub> <CODE>in</CODE>)?
-<CODE>{</CODE>J<sub>1</sub> <CODE>;</CODE> ... <CODE>;</CODE> J<sub>m</sub> <CODE>; }</CODE>)? <CODE>;</CODE>
-</P>
-<P>
-where
-</P>
-<UL>
-<LI>i &gt;= 0
-<LI><I>A</I> is an abstract module
-<LI>each <I>C<sub>i</sub></I> is a concrete module,
- possibly with restrictions on inheritance, i.e. <I>R<sub>i</sub></I><CODE>-[</CODE><I>f,..,g</I><CODE>]</CODE>
-<LI><I>B</I> is an incomplete concrete syntax of <I>A</I>
-<LI>each <I>I<sub>i</sub></I> is an interface or an abstract
-<LI>each <I>J<sub>i</sub></I> is an instance or a concrete of <I>I<sub>i</sub></I>
-<LI>each <I>O<sub>i</sub></I> is an open specification, of one of the forms
- <UL>
- <LI><I>R</I>
- <LI><CODE>(</CODE><I>Q</I><CODE>=</CODE><I>R</I><CODE>)</CODE>
- </UL>
-</UL>
-
-<P>
- where <I>R</I> is a resource, instance, or concrete, and <I>Q</I> is any identifier
-</P>
-<UL>
-<LI>each <I>J<sub>i</sub></I> is a judgement of one of the forms
- <CODE>lincat, lin, lindef, printname</CODE>; also the forms <CODE>oper, param</CODE> are
- allowed, but they cannot be inherited.
-</UL>
-
-
-<!-- html code generated by txt2tags 2.3 (http://txt2tags.sf.net) -->
-<!-- cmdline: txt2tags -\-toc -thtml gf-modules.txt -->
-</BODY></HTML>