diff options
| author | aarne <aarne@cs.chalmers.se> | 2008-06-27 11:32:49 +0000 |
|---|---|---|
| committer | aarne <aarne@cs.chalmers.se> | 2008-06-27 11:32:49 +0000 |
| commit | 64d2a981a99c8f48f85c4efd0cecd1db1e5ce93a (patch) | |
| tree | 8ec777785ae6b99e4ade6ab7c97a7653317b82ad /doc/gf-modules.txt | |
| parent | 032531c6a690edbb377ff11ee2a743a30c5bf500 (diff) | |
more rm in doc
Diffstat (limited to 'doc/gf-modules.txt')
| -rw-r--r-- | doc/gf-modules.txt | 994 |
1 files changed, 0 insertions, 994 deletions
diff --git a/doc/gf-modules.txt b/doc/gf-modules.txt deleted file mode 100644 index 1a4067b40..000000000 --- a/doc/gf-modules.txt +++ /dev/null @@ -1,994 +0,0 @@ -The Module System of GF -Aarne Ranta -8/4/2005 - 5/7/2007 - -%!postproc(html): #SUB1 <sub>1</sub> -%!postproc(html): #SUBk <sub>k</sub> -%!postproc(html): #SUBi <sub>i</sub> -%!postproc(html): #SUBm <sub>m</sub> -%!postproc(html): #SUBn <sub>n</sub> -%!postproc(html): #SUBp <sub>p</sub> -%!postproc(html): #SUBq <sub>q</sub> - - -% to compile: txt2tags --toc -thtml modulesystem.txt - - -A GF grammar consists of a set of **modules**, which can be -combined in different ways to build different grammars. -There are several different **types of modules**: -- ``abstract`` -- ``concrete`` -- ``resource`` -- ``interface`` -- ``instance`` -- ``incomplete concrete`` - - -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. - -This document presupposes knowledge of GF judgements and expressions, which can -be gained from the [GF tutorial tutorial/gf-tutorial2.html]. It aims -to give a systamatic description of the module system; -some tutorial information is repeated to make the document -self-contained. - - - - -=The principal module types= - -==Abstract syntax== - -Any GF grammar that is used in an application -will probably contain at least one module -of the ``abstract`` module type. Here is an example of -such a module, defining a fragment of propositional logic. -``` - abstract Logic = { - cat Prop ; - fun Conj : Prop -> Prop -> Prop ; - fun Disj : Prop -> Prop -> Prop ; - fun Impl : Prop -> Prop -> Prop ; - fun Falsum : Prop ; - } -``` -The **name** of this module is ``Logic``. - - - -An ``abstract`` module defines an **abstract syntax**, which -is a language-independent representation of a fragment of language. -It consists of two kinds of **judgements**: -- ``cat`` judgements telling what **categories** there are - (types of abstract syntax trees) -- ``fun`` judgements telling what **functions** there are - (to build abstract syntax trees) - - -There can also be ``def`` and ``data`` judgements in an -abstract syntax. - - -===Compilation of abstract syntax=== - -The GF grammar compiler expects to find the module ``Logic`` in a file named -``Logic.gf``. When the compiler is run, it produces -another file, named ``Logic.gfc``. This file is in the -format called **canonical GF**, which is the "machine language" -of GF. Next time that the module ``Logic`` is needed in -compiling a grammar, it can be read from the compiled (``gfc``) -file instead of the source (``gf``) file, unless the source -has been changed after the compilation. - - -==Concrete syntax== - -In order for a GF grammar to describe a concrete language, the abstract -syntax must be completed with a **concrete syntax** of it. -For this purpose, we use modules of type ``concrete``: for instance, -``` - 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"]} ; - } -``` -The module ``LogicEng`` is a concrete syntax ``of`` the -abstract syntax ``Logic``. The GF grammar compiler checks that -the concrete is valid with respect to the abstract syntax ``of`` -which it is claimed to be. The validity requires that there has to be -- a ``lincat`` judgement for each ``cat`` judgement, telling what the - **linearization types** of categories are -- a ``lin`` judgement for each ``fun`` judgement, telling what the - **linearization functions** corresponding to functions are - - -Validity also requires that the linearization functions defined by -``lin`` judgements are type-correct with respect to the -linearization types of the arguments and value of the function. - - - -There can also be ``lindef`` and ``printname`` judgements in a -concrete syntax. - - -==Top-level grammar== - -When a ``concrete`` module is successfully compiled, a ``gfc`` -file is produced in the same way as for ``abstract`` modules. The -pair of an ``abstract`` and a corresponding ``concrete`` module -is a **top-level grammar**, which can be used in the GF system to -perform various tasks. The most fundamental tasks are -- **linearization**: take an abstract syntax tree and find the corresponding string -- **parsing**: take a string and find the corresponding abstract syntax - trees (which can be zero, one, or many) - - -In the current grammar, infinitely many trees and strings are recognized, although -no very interesting ones. For example, the tree -``` - Impl (Disj Falsum Falsum) Falsum -``` -has the linearization -``` - if we have a contradiction or we have a contradiction then we have a contradiction -``` -which in turn can be parsed uniquely as that tree. - - -===Compiling top-level grammars=== - -When GF compiles the module ``LogicEng`` it also has to compile -all modules that it **depends** on (in this case, just ``Logic``). -The compilation process starts with dependency analysis to find -all these modules, recursively, starting from the explicitly imported one. -The compiler then reads either ``gf`` or ``gfc`` 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.) - - -===Using top-level grammars=== - -To use a top-level grammar in the GF system, one uses the ``import`` -command (short name ``i``). For instance, -``` - i LogicEng.gf -``` -It is also possible to specify the imported grammar(s) on the command -line when invoking GF: -``` - gf LogicEng.gf -``` -Various **compilation flags** can be added to both ways of compiling a module: -- ``-src`` forces compilation form source files -- ``-v`` gives more verbose information on compilation -- ``-s`` makes compilation silent (except if it fails with an error message) - - -A complete list of flags can be obtained in GF by ``help i``. - -Importing a grammar makes it visible in GF's **internal state**. To see -what modules are available, use the command ``print_options`` (``po``). -You can empty the state with the command ``empty`` (``e``); this is -needed if you want to read in grammars with a different abstract syntax -than the current one without exiting GF. - - - -Grammar modules can reside in different directories. They can then be found -by means of a **search path**, which is a flag such as -``` - -path=.:api/toplevel:prelude -``` -given to the ``import`` command or the shell command invoking GF. -(It can also be defined in the grammar file; see below.) The compiler -writes every ``gfc`` file in the same directory as the corresponding -``gf`` file. - -The ``path`` is relative to the working directory ``pwd``, so that -all directories listed are primarily interpreted as subdirectories of -``pwd``. Secondarily, they are searched relative to the value of the -environment variable ``GF_LIB_PATH``, which is by default set to -``/usr/local/share/GF``. - -Parsing and linearization can be performed with the ``parse`` -(``p``) and ``linearize`` (``l``) commands, respectively. -For instance, -``` - > l Impl (Disj Falsum Falsum) Falsum - if we have a contradiction or we have a contradiction then we have a contradiction - - > p -cat=Prop "we have a contradiction" - Falsum -``` -Notice that the ``parse`` command needs the parsing category -as a flag. This necessary since a grammar can have several -possible parsing categories ("entry points"). - - - -==Multilingual grammar== - -One ``abstract`` syntax can have several ``concrete`` syntaxes. -Here are two new ones for ``Logic``: -``` - 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 ++ "&" ++ b.s ++ ")"} ; - lin Disj a b = {s = "(" ++ a.s ++ "v" ++ b.s ++ ")"} ; - lin Impl a b = {s = "(" ++ a.s ++ "->" ++ b.s ++ ")"} ; - lin Falsum = {s = "_|_"} ; - } -``` -The four modules ``Logic``, ``LogicEng``, ``LogicFre``, and -``LogicSymb`` together form a **multilingual grammar**, 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 **translation** from one language to another. -(By **language** we mean the set of expressions generated by one -concrete syntax.) - - -===Using multilingual grammars=== - -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 **multilingual canonical grammar**, a file -with the suffix ``.gfcm``. For instance, to compile the set of grammars -described by now, the following sequence of GF commands can be used: -``` - i LogicEng.gf - i LogicFre.gf - i LogicSymb.gf - pm | wf logic.gfcm -``` -The "end user" of the grammar only needs the file ``logic.gfcm`` to -access all the functionality of the multilingual grammar. It can be -imported in the GF system in the same way as ``.gf`` files. But -it can also be used in the -[Embedded Java Interpreter for GF http://www.cs.chalmers.se/~bringert/gf/gf-java.html] -to build Java programs of which the multilingual grammar functionalities -(linearization, parsing, translation) form a part. - -In a multilingual grammar, the concrete syntax module names work as -names of languages that can be selected for linearization and parsing: -``` - > l -lang=LogicFre Impl Falsum Falsum - si nous avons une contradiction alors nous avons une contradiction - - > l -lang=LogicSymb Impl Falsum Falsum - ( _|_ -> _|_ ) - - > p -cat=Prop -lang=LogicSymb "( _|_ & _|_ )" - Conj Falsum Falsum -``` -The option ``-multi`` gives linearization to all languages: -``` - > 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 - ( _|_ -> _|_ ) -``` -Translation can be obtained by using a **pipe** from a parser -to a linearizer: -``` - > p -cat=Prop -lang=LogicSymb "( _|_ & _|_ )" | l -lang=LogicEng - if we have a contradiction then we have a contradiction -``` - - - -==Resource modules== - -The ``concrete`` modules shown above would look much nicer if -we used the main idea of functional programming: avoid repetitive -code by using **functions** that capture repeated patterns of -expressions. A collection of such functions can be a valuable -**resource** for a programmer, reusable in many different -top-level grammars. Thus we introduce the ``resource`` -module type, with the first example -``` - resource Util = { - oper SS : Type = {s : Str} ; - oper ss : Str -> SS = \s -> {s = s} ; - oper paren : Str -> Str = \s -> "(" ++ s ++ ")" ; - oper infix : Str -> SS -> SS -> SS = \h,x,y -> - ss (x.s ++ h ++ y.s) ; - oper infixp : Str -> SS -> SS -> SS = \h,x,y -> - ss (paren (infix h x y)) ; - } -``` -Modules of ``resource`` type have two forms of judgement: - -- ``oper`` defining auxiliary operations -- ``param`` defining parameter types - - -A ``resource`` can be used in a ``concrete`` (or another -``resource``) by ``open``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 ``LogicSymb`` much more concisely: -``` - concrete LogicSymb of Logic = open Util in { - lincat Prop = SS ; - lin Conj = infixp "&" ; - lin Disj = infixp "v" ; - lin Impl = infixp "->" ; - lin Falsum = ss "_|_" ; - } -``` -What happens when this variant of ``LogicSymb`` is -compiled is that the ``oper``-defined constants -of ``Util`` are **inlined** in the -right-hand-sides of the judgements of ``LogicSymb``, -and these expressions are **partially evaluated**, i.e. -computed as far as possible. The generated ``gfc`` file -will look just like the file generated for the first version -of ``LogicSymb`` - at least, it will do the same job. - - -Several ``resource`` modules can be ``open``ed -at the same time. If the modules contain same names, the -conflict can be resolved by **qualified** opening and -reference. For instance, -``` - concrete LogicSymb of Logic = open Util, Prelude in { ... - } ; -``` -(where ``Prelude`` is a standard library of GF) brings -into scope two definitions of the constant ``SS``. -To specify which one is used, you can write -``Util.SS`` or ``Prelude.SS`` instead of just ``SS``. -You can also introduce abbreviations to avoid long qualifiers, e.g. -``` - concrete LogicSymb of Logic = open (U=Util), (P=Prelude) in { ... - } ; -``` -which means that you can write ``U.SS`` and ``P.SS``. - -Judgements of ``param`` and ``oper`` forms may also be used -in ``concrete`` modules, and they are then considered local -to those modules, i.e. they are not exported. - - - -===Compiling resource modules=== - -The compilation of a ``resource`` module differs -from the compilation of ``abstract`` and -``concrete`` modules because ``oper`` operations -do not in general have values in ``gfc``. A ``gfc`` -file //is// generated, but it contains only -``param`` judgements (also recall that ``oper``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 -``resource`` modules also takes time, a third kind -of file is generated for resource modules: a ``.gfr`` -file. This file is written in the GF source code notation, -but it is type checked and type annotated, and ``oper``s -are computed as far as possible. - - - -If you look at any ``gfc`` or ``gfr`` 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. - - -===Using resource modules=== - -The typical use is through ``open`` in a -``concrete`` module, which means that -``resource`` modules are not imported on their own. -However, in the developing and testing phase of grammars, it -can be useful to evaluate ``oper``s with different -arguments. To prevent them from being thrown away after inlining, the -``-retain`` option can be used: -``` - > i -retain Util.gf -``` -The command ``compute_concrete`` (``cc``) -can now be used for evaluating expressions that may contain -operations defined in ``Util``: -``` - > cc ss (paren "foo") - {s = "(" ++ "foo" ++ ")"} -``` -To find out what ``oper``s are available for a given type, -the command ``show_operations`` (``so``) can be used: -``` - > so SS - Util.ss : Str -> SS ; - Util.infix : Str -> SS -> SS -> SS ; - Util.infixp : Str -> SS -> SS -> SS ; -``` - - - - -==Inheritance== - -The most characteristic modularity of GF lies in the division of -grammars into ``abstract``, ``concrete``, and -``resource`` modules. This permits writing multilingual -grammar and sharing the maximum of code between different -languages. - - -In addition to this special kind of modularity, GF provides **inheritance**, -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 **extends** -the other module. Inheritance is useful to divide big grammars into -smaller units, and also to reuse the same units in different bigger -grammars. - - - -The first example of inheritance is for abstract syntax. Let us -extend the module ``Logic`` to ``Arithmetic``: -``` - abstract Arithmetic = Logic ** { - cat Nat ; - fun Even : Nat -> Prop ; - fun Odd : Nat -> Prop ; - fun Zero : Nat ; - fun Succ : Nat -> Nat ; - } -``` -In parallel with the extension of the abstract syntax -``Logic`` to ``Arithmetic``, we can extend -the concrete syntax ``LogicEng`` to ``ArithmeticEng``: -``` - 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) ; - } -``` -Another extension of ``Logic`` is ``Geometry``, -``` - abstract Geometry = Logic ** { - cat Point ; - cat Line ; - fun Incident : Point -> Line -> Prop ; - } -``` -The corresponding concrete syntax is left as exercise. - - -===Multiple inheritance=== - - -Inheritance can be **multiple**, 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 -``` - abstract Mathematics = Arithmetic, Geometry ** { - } ; -``` -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: -``` - abstract Mathematics = Arithmetic, Geometry ; -``` - -The module ``Mathematics`` shows that it is possibe -to extend a module already built by extension. The correctness -criterion for extensions is that the same name -(``cat``, ``fun``, ``oper``, or ``param``) -may not be defined twice in the resulting union of names. -That the names defined in ``Logic`` are "inherited twice" -by ``Mathematics`` (via both ``Arithmetic`` and -``Geometry``) is no violation of this rule; the usual -problems of multiple inheritance do not arise, since -the definitions of inherited constants cannot be changed. - - - -===Restricted inheritance=== - -Inheritance can be **restricted**, which means that only some of -the constants are inherited. There are two dual notations for this: -``` - A [f,g] -``` -meaning that //only// ``f`` and ``g`` are inherited from ``A``, and -``` - A-[f,g] -``` -meaning that //everything except// ``f`` is ``g`` are inherited from ``A``. - -Constants that are not inherited may be redefined in the inheriting module. - - - - -===Compiling inheritance=== - -Inherited judgements are not copied into the inheriting modules. -Instead, an **indirection** is created for each inherited name, -as can be seen by looking into the generated ``gfc`` (and -``gfr``) files. Thus for instance the names -``` - Mathematics.Prop Arithmetic.Prop Geometry.Prop Logic.Prop -``` -all refer to the same category, declared in the module -``Logic``. - - - -===Inspecting grammar hierarchies=== - -The command ``visualize_graph`` (``vg``) 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 ``print_multi -graph`` (``pm -graph``). - -The ``vg`` command uses the free software packages Graphviz (commad ``dot``) -and Ghostscript (command ``gv``). - - - -==Reuse of top-level grammars as resources== - -Top-level grammars have a straightforward translation to -``resource`` modules. The translation concerns -pairs of abstract-concrete judgements: -``` - cat C ; ===> oper C : Type = T ; - lincat C = T ; - - fun f : A ; ===> oper f : A = t ; - lin f = t ; -``` -Due to this translation, a ``concrete`` module -can be ``open``ed in the same way as a -``resource`` module; the translation is done -on the fly (it is computationally very cheap). - -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 **resource grammar**, -``` - abstract Resource = { - cat S ; NP ; A ; - fun PredA : NP -> A -> S ; - } - concrete ResourceEng of Resource = { - lincat S = ... ; - lin PredA = ... ; - } -``` -The **application grammar**, instead of giving linearizations -explicitly, just reduces them to categories and functions in the -resource grammar: -``` - concrete ArithmeticEng of Arithmetic = LogicEng ** open ResourceEng in { - lincat Nat = NP ; - lin Even x = PredA x (regA "even") ; - } -``` -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 **lock field**, -``` - cat C ; ===> oper C : Type = T ** {lock_C : {}} ; - lincat C = T ; - - fun f : C_1 ... C_n -> C ; ===> oper f : C_1 ... C_n -> C = \x_1,...,x_n -> - lin f = t ; t x_1 ... x_n ** {lock_C = <>}; -``` -(Notice that the latter translation is type-correct because of -record subtyping, which means that ``t`` 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. - -**Note**. 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. - - -=Additional module types= - -==Interfaces, instances, and incomplete grammars== - -One difference between top-level grammars and ``resource`` -modules is that the former systematically separete the -declarations of categories and functions from their definitions. -In the reuse translation creating and ``oper`` judgement, -the declaration coming from the ``abstract`` module is put -together with the definition coming from the ``concrete`` -module. - - - -However, the separation of declarations and definitions is so -useful a notion that GF also has specific modules types that -``resource`` modules into two parts. In this splitting, -an ``interface`` 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: -``` - interface Markup = open Util in { - oper Boldface : Str -> Str ; - oper Heading : Str -> Str ; - oper markupSS : (Str -> Str) -> SS -> SS = \f,r -> - ss (f r.s) ; - } -``` -The definitions of the constants declared in an ``interface`` -are given in an ``instance`` module (which is always ``of`` -an interface, in the same way as a ``concrete`` is always -``of`` an abstract). The following ``instance``s -define markup in HTML and latex. -``` - instance MarkupHTML of Markup = open Util in { - oper Boldface s = "<b>" ++ s ++ "</b>" ; - oper Heading s = "<h2>" ++ s ++ "</h2>" ; - } - - instance MarkupLatex of Markup = open Util in { - oper Boldface s = "\\textbf{" ++ s ++ "}" ; - oper Heading s = "\\section{" ++ s ++ "}" ; - } -``` -Notice that both ``interface``s and ``instance``s may -``open`` ``resource``s (and also reused top-level grammars). -An ``interface`` 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. - - -===Using an interface=== - -An ``interface`` or an ``instance`` -can be ``open``ed in -a ``concrete`` using the same syntax as when opening -a ``resource``. For an ``instance``, the semantics -is the same as when opening the definitions together with -the type signatures - one can think of an ``interface`` -and an ``instance`` of it together forming an ordinary -``resource``. Opening an ``interface``, 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. - - - -A module that ``open``s an ``interface`` is therefore -**incomplete**, and has to be **completed** with an -``instance`` of the interface to become complete. To make -this situation clear, GF requires any module that opens an -``interface`` to be marked as ``incomplete``. Thus -the module -``` - incomplete concrete DocMarkup of Doc = open Markup in { - ... - } -``` -uses the interface ``Markup`` 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. - - - -Another terminology for ``incomplete`` modules is -**parametrized modules** or **functors**. -The ``interface`` gives the list of parameters -that the functor depends on. - - -===Instantiating an interface=== - -To complete an ``incomplete`` module, each ``inteface`` -that it opens has to be provided an ``instance``. The following -syntax is used for this: -``` - concrete DocHTML of Doc = DocMarkup with (Markup = MarkupHTML) ; -``` -Instantiation of ``Markup`` with ``MarkupLatex`` is -another one-liner. - -If more interfaces than one are instantiated, a comma-separated -list of equations in parentheses is used, e.g. -``` - concrete MusicIta = MusicI with - (Syntax = SyntaxIta), (LexMusic = LexMusicIta) ; -``` -This example shows a common design pattern for building applications: -the concrete syntax is a functor on the generic resource grammar library -interface ``Syntax`` and a domain-specific lexicon interface, here -``LexMusic``. - -All interfaces that are ``open``ed in the completed model -must be completed. - -Notice that the completion of an ``incomplete`` 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. -``` - concrete MusicIta = MusicI - [f] with - (Syntax = SyntaxIta), (LexMusic = LexMusicIta) ** { - - lin f = ... - - } ; -``` - - -===Compiling interfaces, instances, and parametrized modules=== - -Interfaces, instances, and parametric modules are purely a -front-end feature of GF: these module types do not exist in -the ``gfc`` and ``gfr`` formats. The compiler has -nevertheless to keep track of their dependencies and modification -times. Here is a summary of how they are compiled: -- an ``interface`` is compiled into a ``resource`` with an empty body -- an ``instance`` is compiled into a ``resource`` in union with its - ``interface`` -- an ``incomplete`` module (``concrete`` or ``resource``) is compiled - into a module of the same type with an empty body -- a completion module (``concrete`` or ``resource``) is compiled - into a module of the same type by compiling its functor so that, instead of - each ``interface``, its given ``instance`` is used - - -This means that some generated code is duplicated, because those operations that -do have complete definitions in an ``interface`` are copied to each of -the ``instances``. - - -=Summary of module syntax and semantics= - - -==Abstract syntax modules== - -Syntax: - -``abstract`` A ``=`` (A#SUB1,...,A#SUBn ``**``)? -``{``J#SUB1 ``;`` ... ``;`` J#SUBm ``; }`` - - - -where -- i >= 0 -- each //A#SUBi// is itself an abstract module, - possibly with restrictions on inheritance, i.e. //A#SUBi//``-[``//f,..,g//``]`` - or //A#SUBi//``[``//f,..,g//``]`` -- each //J#SUBi// is a judgement of one of the forms - ``cat, fun, def, data`` - - -Semantic conditions: -- all inherited names declared in each //A#SUBi// and //A// must be distinct -- names in restriction lists must be defined in the restricted module -- inherited constants may not depend on names excluded by restriction - - - -==Concrete syntax modules== - -Syntax: - -``incomplete``? ``concrete`` C ``of`` A ``=`` -(C#SUB1,...,C#SUBn ``**``)? -(``open`` O#SUB1,...,O#SUBk ``in``)? -``{``J#SUB1 ``;`` ... ``;`` J#SUBm ``; }`` - - - -where -- i >= 0 -- //A// is an abstract module -- each //C#SUBi// is a concrete module, - possibly with restrictions on inheritance, i.e. //C#SUBi//``-[``//f,..,g//``]`` -- each //O#SUBi// is an open specification, of one of the forms - - //R// - - ``(``//Q//``=``//R//``)`` - - - where //R// is a resource, instance, or concrete, and //Q// is any identifier -- each //J#SUBi// is a judgement of one of the forms - ``lincat, lin, lindef, printname``; also the forms ``oper, param`` are - allowed, but they cannot be inherited. - - - -If the modifier ``incomplete`` appears, then any //R// in -an open specification may also be an interface or an abstract. - - -Semantic conditions: -- each ``cat`` judgement in //A// - must have a corresponding, unique - ``lincat`` judgement in //C// -- each ``fun`` judgement in //A// - must have a corresponding, unique - ``lin`` judgement in //C// -- names in restriction lists must be defined in the restricted module -- inherited constants may not depend on names excluded by restriction - - - -==Resource modules== - -Syntax: - -``resource`` R ``=`` -(R#SUB1,...,R#SUBn ``**``)? -(``open`` O#SUB1,...,O#SUBk ``in``)? -``{``J#SUB1 ``;`` ... ``;`` J#SUBm ``; }`` - - -where -- i >= 0 -- each //R#SUBi// is a resource, instance, or concrete module, - possibly with restrictions on inheritance, i.e. //R#SUBi//``-[``//f,..,g//``]`` -- each //O#SUBi// is an open specification, of one of the forms - - //P// - - ``(``//Q//``=``//R//``)`` - - - where //P// is a resource, instance, or concrete, and //Q// is any identifier -- each //J#SUBi// is a judgement of one of the forms ``oper, param`` - - - - -Semantic conditions: -- all names defined in each //R#SUBi// and //R// must be distinct -- all constants declared must have a definition -- names in restriction lists must be defined in the restricted module -- inherited constants may not depend on names excluded by restriction - - - -==Interface modules== - -Syntax: - -``interface`` R ``=`` -(R#SUB1,...,R#SUBn ``**``)? -(``open`` O#SUB1,...,O#SUBk ``in``)? -``{``J#SUB1 ``;`` ... ``;`` J#SUBm ``; }`` - - -where -- i >= 0 -- each //R#SUBi// is an interface or abstract module, - possibly with restrictions on inheritance, i.e. //R#SUBi//``-[``//f,..,g//``]`` -- each //O#SUBi// is an open specification, of one of the forms - - //P// - - ``(``//Q//``=``//R//``)`` - - - where //P// is a resource, instance, or concrete, and //Q// is any identifier -- each //J#SUBi// is a judgement of one of the forms ``oper, param`` - - - - -Semantic conditions: -- all names declared in each //R#SUBi// and //R// must be distinct -- names in restriction lists must be defined in the restricted module -- inherited constants may not depend on names excluded by restriction - - - - -==Instance modules== - -Syntax: - -``instance`` R ``of`` I ``=`` -(R#SUB1,...,R#SUBn ``**``)? -(``open`` O#SUB1,...,O#SUBk ``in``)? -``{``J#SUB1 ``;`` ... ``;`` J#SUBm ``; }`` - - -where -- i >= 0 -- //I// is an interface module -- each //R#SUBi// is an instance, resource, or concrete module, - possibly with restrictions on inheritance, i.e. //R#SUBi//``-[``//f,..,g//``]`` - -- each //O#SUBi// is an open specification, of one of the forms - - //P// - - ``(``//Q//``=``//R//``)`` - - - where //P// is a resource, instance, or concrete, and //Q// is any identifier -- each //J#SUBi// is a judgement of one of the forms - ``oper, param`` - - - - -Semantic conditions: -- all names declared in each //R#SUBi//, //I//, and //R// must be distinct -- all constants declared in //I// must have a definition either in - //I// or //R// -- names in restriction lists must be defined in the restricted module -- inherited constants may not depend on names excluded by restriction - - - -==Instantiated concrete syntax modules== - -Syntax: - -``concrete`` C ``of`` A ``=`` -(C#SUB1,...,C#SUBn ``**``)? -B -``with`` -``(``I#SUB1 ``=``J#SUB1``),`` ... -``, (``I#SUBp ``=``J#SUBp``)`` -(``-``? ``[``c#SUB1,...,c#SUBq ``]``)? -(``**``? -(``open`` O#SUB1,...,O#SUBk ``in``)? -``{``J#SUB1 ``;`` ... ``;`` J#SUBm ``; }``)? ``;`` - -where -- i >= 0 -- //A// is an abstract module -- each //C#SUBi// is a concrete module, - possibly with restrictions on inheritance, i.e. //R#SUBi//``-[``//f,..,g//``]`` -- //B// is an incomplete concrete syntax of //A// -- each //I#SUBi// is an interface or an abstract -- each //J#SUBi// is an instance or a concrete of //I#SUBi// -- each //O#SUBi// is an open specification, of one of the forms - - //R// - - ``(``//Q//``=``//R//``)`` - - - where //R// is a resource, instance, or concrete, and //Q// is any identifier -- each //J#SUBi// is a judgement of one of the forms - ``lincat, lin, lindef, printname``; also the forms ``oper, param`` are - allowed, but they cannot be inherited. - - - - |
