next up previous contents
Next: Compile-Time Error Messages Up: Compiling ALE Programs Previous: File Management   Contents

Compiling Programs

ALE can compile a program incrementally to some extent. In particular, the compiler is broken down into six primary components for compiling the type hierarchy, functional descriptions, type constraints, the attribute-value logic, the definite clauses and the grammar. Compiling the type hierarchy consists of compiling type subsumption, type unification, appropriateness specifications, and extensionality information. The logic compiler compiles predicates which know how to add a type to a feature structure, how to find a feature value in a type and how to perform feature structure unification, as well as the most general satisfiers of every type, with code attached to enforce cons/2 constraints. Compiling the grammar consists of compiling the lexicon, empty categories, rules and lexical rules, and if compilation for generation is enabled, the semantics/1 directive. Macros are not compiled, but are rather interpreted during compilation.

There is one predicate compile_gram/1 that can be used to compile a whole ALE grammar from one file, as follows:

| ?- compile_gram(GramFile).
where GramFile is the name of the file in which the grammar resides. The compiler will display error messages to the screen when it is compiling. But since ALE uses the Prolog compiler to read the files, Prolog might also complain about syntax errors in specifying the files. In either case, there should be some indication of what the error is and which clause of the file contained it.

ALE's compiler creates code for parsing, generation, or both. As of the present version of ALE, only one grammar can be used, even if code for both modes is to be created. Two files, ale_parse.pl and ale_gen.pl, are included with the distribution, which provide some example glue code to link together two ALE processes running under SICStus Prolog 3.0 or higher in order to parse and generate with two different grammars.

At startup, ALE produces code only for parsing. To produce code for generation only, use the command:

  | ?- generate.
 
  compiler will produce code for generation only
 
  yes
  | ?-
To produce code for both parsing and generation, use parse_and_gen instead. To switch back to producing code for parsing only, use parse. Note that these commands modify the behaviour of the compiler, not the compiled code, so grammars may need to be recompiled after these directives are issued.

The following predicates are available to compile grammars and their component parts. They are listed hierarchically, with each command calling all those listed under it. Each higher-level command is nothing more than the combination of those commands below it.

Command                      Requires            File  Mode  Clause
-------------------------------------------------------------------
compile_gram                 nothing               *   both
  compile_sig                nothing               *   both
    compile_sub_type         nothing               *         sub
    compile_unify_type       compile_sub_type          
    compile_approp           compile_unify_type    *         intro
    compile_extensional      compile_approp        *         ext
  compile_fun                compile_sig           *   both  +++>
  compile_cons               compile_fun           *   both  cons
  compile_logic              compile_sig               both
    compile_mgsat            compile_sig               
    compile_add_to_type      compile_sig               
    compile_featval          compile_add_to_type       
    compile_u                compile_sig               
  compile_subsume            compile_sig            parse/subtest 
  compile_dcs                compile_logic         *   both  if
  compile_grammar            compile_logic         *
    compile_lex_rules        compile_logic         *   parse **>
    compile_lex              compile_logic         *   parse --->
    compile_rules            compile_logic         *   parse ===>,empty
                             compile_logic         *   gen   ===>,empty
                                                             --->,**>
    compile_generate         compile_rules         *   gen   semantics
The table above lists which compilations must have already been compiled before the next stage of compilation can begin. Thus before compile_grammar can be called, compile_logic must be called (or equivalently, the sequence of compile_mgsat, compile_add_to_type, compile_featval, and compile_u). Each command with an asterisk in its clauses column in the above table may be given an optional file argument. The file argument should be an atom which specifies the file in which the relevant clauses can be found. The clauses needed before each stage of compilation can begin are listed to the right of the asterisks. For instance, the if clauses must be loaded before compile_dcs is called. But note that compile_unify_type does not require any clauses to be loaded, as it uses the compiled definition of sub_type rather than the user specification in its operation. Thus changes to the signature in the source file, even if the source file is recompiled, will not be reflected in compile_unify_type if they have not been recompiled by compile_sub_type first. If an attempt is made to compile a part of a program where the relevant clauses have not been asserted, an error will result.

Note that compile_subsume only compiles code if subsumption checking (p. [*]) and parsing have been enabled.

Each of the lowest level commands generates intermediate Prolog source code for that function, which is then compiled further by a Prolog compiler. ALE uses a term-expansion-based compiler in both SICStus and SWI Prologs that avoids the necessity for creating intermediate files. It also improves the speed of intermediate code compilation. Because both SICStus and SWI Prologs require the user to read a file on disk in order to use their compilers, ALE must create a zero-byte file called .alec_throw to throw control to its intermediate code compiler. For that reason, the Prolog process must have write permission in the local directory to create this file, if it does not already exist.

After a grammar is compiled, the system plus grammar code can be saved with the command:

| ?- save_program(File).
This will save the state of the Prolog database in File. SICStus users should normally use this rather than save/1, which creates a larger file by saving other information like the state of Prolog's internal stacks. The SWI Prolog command is qsave_program(File). With either Prolog, the state can be reloaded, by executing the saved file directly.

In general, whenever the ALE source program is changed, it should be recompiled from the point of change. For instance, if the definite clauses are the only thing that have changed since the last compilation, then only compile_dcs(FileSpec) needs to be run. But if in changing the definite clauses, the type hierarchy had to be changed, then everything must be recompiled.

ALE treats lexicon compilation differently than the other stages. Two commands, lex_compile/0 and lex_consult/0, control whether the intermediate code for the lexicon and empty categories is compiled or consulted (a lesser degree of compilation). Lexicon compilation is usually the most time-consuming stage of grammar compilation in ALE, and consulting the code for this stage can result in a substantial compile-time speed-up. The decrease in run-time performance is only significant in grammars with a high degree of lexical ambiguity, i.e., where one string has a very large number of entries in the lexicon. By default, ALE consults the code for the lexicon. In SWI Prolog, only lexicon consulting is available.

When consulting is chosen, the lexicon and empty categories are also consulted dynamically. This means that individual entries can be retracted and added without recompiling the entire lexicon. To retract a lexical entry, use the command:

| ?- retract_lex(LexSpec).
LexSpec can either be a word, or a list of words. The words given to retract_lex/1 are not closed under morph rules -- derived entries with different forms must be retracted explicitly. retract_lex/1 iterates through all of the entries that match the given word(s), asking for each one whether it should be retracted. retractall_lex/1 will remove all of them without asking.

To add lexical entries, use the command:

| ?- update_lex(UpdateFile).
UpdateFile is a file containing new lexical entries and empty categories. New lexical entries are closed under lexical rules, as usual.A.1


next up previous contents
Next: Compile-Time Error Messages Up: Compiling ALE Programs Previous: File Management   Contents
TRALE User's Manual