2. Source Code
Most, but not all, of the Teyjus source code is separated by
functionality into source file pairs, where the header (`.h') file
defines the public interface and the source (`.c') file defines the
implementation. When this separation is particularly clear, we refer to
this pair of files as a module. All identifiers relating to a
particular module are prefixed by the name of the module in capital
letters. Thus the module foo would contain functions such as
FOO_Foo()
and data types such as FOO_Bar
.
Do not confuse the use of the term modules in the context of the
Teyjus implementation with the use of the term in the context of Lambda
Prolog program structure.
The Teyjus source code is divided into a number of directories. We
divide the source-code documentation in the same manner:
2.1 Compiler
The `compiler/' directory contains the code implementing the
compiler. The parser used in compiling is also used in reading terms
at runtime.
2.1.1 Abstract Syntax
2.1.2 Clause Generation
2.1.3 Clauses
2.1.4 Code Generation
2.1.5 Compile
2.1.6 Compiler Error
2.1.7 Compiler Init
2.1.8 Compiler Instr
2.1.9 Compiler Types
2.1.10 Error Message
2.1.11 LP Grammar
2.1.12 LP Lexical Specification
2.1.13 Parse
2.1.14 Parse Module
2.1.15 Parse Signature
2.1.16 Parse Terms
2.1.17 Parse Variables
2.1.18 Show
2.1.19 Spit Code
2.1.20 Symbol Init
2.1.21 Symbol
2.1.22 Table
2.2 Disassembler
The disassembler is a class hierarchy implemented in C. We assume in
this section that the reader has some familiarity with object oriented
terminology. The data type DIS_context
is the abstract base
class, and has as its public member functions the functions defined in
the Disassembly module. The Disassembly Context module declares the
data type and implements a few default methods which are inherited by
the subclasses.
Currently Teyjus contains only one subclass of DIS_context
,
DIS_bc_context
. The Disassembler Bytecode module implements this
subclass. The intention is to support disassembly of loaded modules, as
well as debugging (run-time) disassembly.
The Disassembler Output module takes care of formatting instructions
into columns, including support for multi-line instructions.
2.2.1 Disassembler Bytecode
The Disassembler Bytecode file implements a subclass of
DIS_context
intended to disassemble compiled bytecode files
(`.lp' files). Because of the inheritance structure used in the
disassembler, the module's functionality is mostly available through the
Disassembly module (see Disassembly).
In brief, this module opens and parses the bytecode file when the
constructor (DIS_context_from_bytecode
) is called, storing all
code and tables in the returned DIS_context
. The source file for
this module implements the functions needed in a DIS_context
object (see Disassembler Context), as well as an array of
functions used to load the bytecode from disk (see Load Clauses),
and a long series of functions to parse and later print the many data
structures contained in a bytecode file.
-
-
DIS_context DIS_context_from_bytecode(char *inFilename);
This function is the "constructor" for the bytecode subclass of
DIS_context
. The argument is the full pathname of a compiled
bytecode file.
2.2.2 Disassembler Context
The Disassembler Context module declares the structure of a
DIS_context
object, and implements several default functions
which can be inherited by subclasses.
-
-
typedef struct DIS_vtable **DIS_context;
There are no variables in a generic DIS_context
object, so
DIS_context
is declared simply as a pointer to a pointer to a
vtable. Thus any subclass of DIS_context
should have as the
first member of its structure a pointer to a vtable.
-
typedef void (*DIS_destroy_fn)(DIS_context);
This is the type of the function used to destroy a DIS_context
.
-
typedef char *(*DIS_get_name_fn)(DIS_context);
This is the type of the function used to get the name of the code
represented by a DIS_context
.
-
typedef CSPACE_PTR_TY (*DIS_get_code_fn)(DIS_context);
This is the type of the function used to find the address of the first
byte of abstract machine code in the DIS_context
.
-
typedef int (*DIS_get_code_length_fn)(DIS_context);
This is the type of the function used to find the number of bytes of
abstract machine code in the DIS_context
.
-
typedef char *(*DIS_offset_to_label_fn)(int, DIS_context);
This is the type of the function used to translate offsets into the
DIS_context
's code into labels. The function returns a pointer
to the name for the offset, or NULL if the offset has no appropriate
name.
-
typedef void (*DIS_output_operand_fn)(INSTR_operand_type, int, DIS_context);
This is the type of the functions used to output operands to
instructions in the abstract machine code. The functions are given the
operand's value in the integer argument, as well as the operand type and
a reference to the DIS_context
. Because these functions use the
Disassembler Output module, no FILE argument is necessary.
-
typedef void (*DIS_headfoot_fn)(FILE *, DIS_context);
This is the type of the functions used to print the header and footer
information to the given FILE.
-
char *DIS_default_offset_to_label_fn(int, DIS_context);
This default translation function simply returns NULL regardless of its
input.
-
void DIS_default_output_operand_fn(INSTR_operand_type, int, DIS_context);
This default operand function is actually quite functional. For
operand types R, E, CE, N, I1, I2, this function will simply print
the value. For other operand types, it prints a tag containing the
given value, but is unable to do any translation back to the names used
in the source code.
-
void DIS_default_headfoot_fn(FILE *, DIS_context);
This default header and footer function prints nothing.
The Disassembler Context's vtable has the following fields:
-
DIS_destroy_fn destroy;
This function should destroy the DIS_context
, freeing all
associated resources.
-
DIS_get_name_fn get_name;
This function should return some identifying name for the code
represented by the DIS_context
.
-
DIS_get_code_fn get_code;
This function should return the address of the abstract machine code
represented by the DIS_context
.
-
DIS_get_code_length_fn get_code_length;
This function should return the length of the abstract machine code
represented by the DIS_context
.
-
DIS_offset_to_label_fn offset_to_label;
This function should translate offsets into the DIS_context
's
code into labels. The function returns a pointer to the name for the
offset, or NULL if the offset has no appropriate name.
-
DIS_output_operand_fn output_operand[INSTR_X];
This is an array of functions used to output the several types of
operands to instructions.
-
DIS_headfoot_fn print_header_info;
-
DIS_headfoot_fn print_footer_info;
These functions should print the header and footer for the
DIS_context
, respectively.
2.2.3 Disassembler Output
The Disassembler Output module handles the formatting of instructions
into three columns. It correctly handles the possibility of the data in
any of these columns overflowing onto the next line. The module
maintains a notion of position within each column, so that successive
strings output to the same column will be concatenated.
In brief, the implementation uses a statically allocated array of
DIS_MAX_LINES
lines, and implements functions to clear this
array, to write a string into each field, and to print the array.
-
-
void DIS_output_label(char *inLabel);
Insert inLabel
into the label column (the first column).
-
void DIS_output_instruction(char *inInstruction);
Insert inInstruction
into the instruction column (the second
column).
-
void DIS_output_operand(char *inOperand);
Insert inOperand
into the operand column (the third column).
-
void DIS_output(FILE *inFile);
Output the current set of lines to inFile
.
-
void DIS_output_reset(void);
Clear the current set of lines, in anticipation of a new instruction.
2.2.4 Disassembly
The Disassembly module is contained in the files
`disassembly.{c,h}'. This file implements the high-level
interface to the disassembly system. All of the functions operate on
objects of type DIS_context
. These objects should be obtained
from a module defining a specific implementation of DIS_context
,
such as Disassembler Bytecode.
-
-
void DIS_dispose_context(DIS_context inContext);
This function is the "destructor" for DIS_context
objects.
-
void DIS_output_header(FILE *inFile, DIS_context inContext);
Thus function causes the DIS_context
object to print its header
information to the given FILE. This will contain some sort of summary
information, such as source filename or memory address.
-
void DIS_output_all(FILE *inFile, DIS_context inContext);
This function causes the DIS_context
to print all of its bytecode
to the given FILE.
-
void DIS_output_footer(FILE *inFile, DIS_context inContext);
This function causes the DIS_context
to print its footer
information to the given FILE. This will contain further information
about the disassembly, such as tables relevant to the bytecode.
-
void DIS_output_line(FILE *inFile, DIS_context inContext, int inOffset);
This function will disassemble and print one instruction to the given
FILE, given the offset from the beginning of the DIS_context
's
code to the beginning of the desired instruction.
2.3 Front
The `front/' directory contains source code implementing the
frontends to each of the four Teyjus executables.
2.3.1 Compiler Front
2.3.2 Disassembler Front
2.3.3 Environ
2.3.4 Front File
The Front module itself is contained in the files front.{c,h}. The
following functions and variable are defined:
-
-
void FRONT_Init();
Initialize the frontends.
-
void FRONT_PrintIntro();
Print the "Welcome" message.
-
void FRONT_Interact(FRONT_Module inModule);
Interactively query against the given module.
-
int FRONT_Quiet;
A boolean value; if TRUE
, the front ends will suppress normal
frontend output. This output currently includes only the welcome
message.
2.3.5 Getopt
2.3.6 Module
2.3.7 Query
2.3.8 Simulator Front
2.3.9 System Front
2.3.10 System Interact
2.3.11 Version
The Version module is a very tiny piece of code contained in
`front.{c,h}'. It is small because it is rewritten during the
release process to contain the current release version. It has only one
function:
-
-
void FRONT_Version();
This function prints the current Teyjus version.
2.4 Loader
2.4.1 Bytecode
2.4.2 Const
2.4.3 Hash
2.4.4 Kind
This module is responsible for loading kinds, also known as sorts, from
module files.
-
-
INDEX_TY KIND_GetIndex(BYTE, TWO_BYTES);
Given a mark (GLOBAL, LOCAL, or PERVASIVE) and an index from
the bytecode file, this function will produce the corresponding runtime
kind index. Because of the dynamic combination of modules, these
indices must be generated dynamically, and cannot be known at bytecode
compile-time.
-
void KIND_LoadGlobalKinds(int num);
Load all of the global kinds from a module, assigning an index to each
one by matching it to some already existing global kind. This global
kind may have been renamed in the chain of imports, or may be named in
the top-level module. In either case, the pre-existing index is reused.
-
void KIND_LoadTopLevelGlobKinds(int num);
Perform the same actions as KIND_LoadGlobalKinds, but for each kind
insert it into the parser tables so that it may be used in parsing
terms, and update the runtime data structure (the kind table) to include
the new kind.
-
void KIND_LoadLocalKinds(int num);
Allocate the given number of indices to anonymous, local kinds, and
update the runtime data structure (the kind table) to include the new kinds.
-
void KIND_ExtendRenamingFunction();
Load a renaming function from the bytecode file for a module. This
renaming function sends kinds exported globally from a module to indices
of local kinds.
-
void int KIND_GlobalListSearch(S_symbol sy);
Search the list of global kinds in the current top-level module for the
given symbol, returning its index if found, and KIND_NOTINTABLE if
it is not.
-
void int KIND_RenamingFnSearch(S_symbol sy);
If the given symbol is renamed by the current kind renaming function,
then return the index of the original kind. Otherwise return
KIND_NOTINTABLE.
2.4.5 Load Clauses
2.4.6 Loader Data Structures
2.4.7 Loader Error
2.4.8 Loader Init
2.4.9 Loader Types
2.4.10 Loader Utils
2.4.11 Loader File
2.4.12 ModTable
2.4.13 SearchFns
2.4.14 SearchTables
2.4.15 Snl
2.4.16 Search Table Struct
2.4.17 Unload
2.5 Simulator
2.5.1 Abstract Machine
2.5.2 Builtins
2.5.2.1 Builtins File
2.5.2.2 Comparison Expressions
2.5.2.3 Evaluation Expressions
2.5.2.4 IO
2.5.2.5 Meta-Level
2.5.2.6 Read Term
2.5.3 Data Formats
The files `dataformats.{c,h}' do not constitute a module, but
are described here nonetheless. The files define the primitive data
types used in the simulator, and some operations upone those elements.
2.5.4 Error Constants
2.5.5 Head Normalization
2.5.6 Heap
2.5.7 Higher-Order Unification
2.5.8 IO Data Structures
2.5.9 Machine Types
2.5.10 Pervasive Table Init
2.5.11 Print Term
2.5.12 Print Type
2.5.13 Simulator Local
2.5.14 Simulator Init
2.5.15 Simulator Types
2.5.16 Simulator File
2.5.17 Trail
2.5.18 WAM String
2.6 System
2.6.1 Error
2.6.2 Float Make
2.6.3 Operators
2.6.4 Stream
2.6.5 Teyjus Signals
2.6.6 Toplevel
2.7 Tables
2.7.1 CI To PI Table
2.7.2 Instructions
2.7.3 Pervasive Names
2.7.4 Pervasives
2.8 Utils
2.8.1 IntSet
The IntSet module is found in the files `utils/intset.{c,h}'. It
implements a set of integers, and is used as a utility by other
modules. It contains the data type INTSET_Set
, which is a
structure that is manipulated by the following functions:
-
-
void INTSET_Init(INTSET_Set *outSet);
Initialize a new set of integers to empty. The structure is passed by
reference (pointer).
-
void INTSET_Free(INTSET_Set *inSet);
Free a set of integers; used when the set is no longer needed.
-
void INTSET_Insert(INTSET_Set *ioSet, int inInteger);
Insert an integer into a set.
-
bool INTSET_Test(INTSET_Set *inSet, int inInteger);
Return TRUE
iff the specified integer is in the set.
-
int INTSET_GetLength(INTSET_Set *inSet);
Return the number of integers in a set.
-
int *INTSET_GetVector(INTSET_Set *inSet);
Return an array containing the integers in a set.
2.8.2 IOUtils
The IOUtils module contains several functions which are useful to parts
of the system dealing with the bytecode files. It is contained in the
file `utils/ioutils.{c,h}'. The following are its functions:
-
-
void IOUTILS_fix_bb4(BYTE_PTR lptr);
Fixes the byte-backwards problem. It is passed a pointer to a sequence
of 4 bytes read in from a file as bytes. It then converts those bytes
to represent a number. This code works for any machine, and makes the
byte-code machine independent.
-
void IOUTILS_fix_bb2(BYTE_PTR lptr);
Fixes the byte-backwards problem. It is passed a pointer to a sequence
of 2 bytes read in from a file as bytes. It then converts those bytes
to represent a number. This code works for any machine, and makes the
byte-code machine independent.
-
void IOUTILS_num2bytes(FILE *file, unsigned int num, int bytes);
Write out a quantity as a sequence of bytes.
2.8.3 ITSM
The ITSM module implements a simple Integer To String Mapping. It is
implemented in the files `utils/itsm.{c,h}'. Currently this
mapping is implemented as a linked list, although this may change if the
module is used in a place where efficiency is important. It contains
the data type ITSM_element
, pointed to by ITSM_Map
, which
is manipulated by the following functions:
-
-
void ITSM_Init(ITSM_Map *outMap);
Initialize a new map.
-
void ITSM_Free(ITSM_Map *inMap);
Free the memory occupied by an existing map, including all strings in
the map.
-
void ITSM_Insert(ITSM_Map *ioMap, int inInteger, char *inString);
Insert a mapping of inInteger
to inString
into the map.
Note that the string inString
is duplicated into storage private
to the map, so the original string's space may be reclaimed immediately.
-
char *ITSM_Lookup(ITSM_Map *inMap, int inInteger);
Lookup the string to which the integer inInteger
is mapped.
Returns NULL
if there is no such mapping.
2.8.4 Paths
The Paths module contains functions to manipulate pathnames by their
component parts, and to manipulate the global list of paths which is
used to find modules. It resides in the files
`utils/paths.{c,h}'. It defines one data type,
PATHS_Pathname
, which is a "black box" representing a
pathname. The following functions are defined:
-
-
void PATHS_Init();
Initialize the Paths module. Should be called before any other Paths
functions are called.
-
void PATHS_AddPathHead(string pname);
Add the path specified by pname
to the head of the list of paths
to search. pname
is checked to be sure it is a valid directory
specification, and an error exception is raised if it is not.
-
void PATHS_AddPathTail(string pname);
Add the path specified by pname
to the tail of the list of paths
to search. pname
is checked to be sure it is a valid directory
specification, and an error exception is raised if it is not.
-
void PATHS_RemovePath(string pname);
Remove the path specified by pname
from the list of paths to
search. If the path is not found, an error exception is raised.
-
void PATHS_ShowPaths(void);
Print a representation of the current list of search paths to the
console.
-
void PATHS_SetDefaultDirectory(char *inDefaultDir);
Set the default directory for files. Unqualified pathnames are assumed
to indicate this directory, and it is the first directory searched.
-
PATHS_Pathname *PATHS_MakePathname(char *inPathname);
Create a Pathname object for the input pathname.
-
PATHS_Pathname *PATHS_MakePathnameFromBasename(char *inBasename);
Create a Pathname object for the input pathname, given a filename. If
the input filename has a directory component, this function returns
NULL
.
-
PATHS_Pathname *PATHS_Duplicate(PATHS_Pathname *inPN);
Duplicate a Pathname object for a pathname. The returned object must be
freed separately from the input object.
-
void PATHS_Free(PATHS_Pathname *inPN);
Free a Pathname object, returning its memory to the common pool. This
should be called for every object created with
PATHS_MakePathname
, PATHS_MakePathnameFromBasename
, or
PATHS_Duplicate
.
-
void PATHS_SetExtension(PATHS_Pathname *inPN, char *inNewExt);
Set the extension (the portion following the fullstop) of a Pathname
object. Specify the extension with the preceding fullstop
(e.g. ".mod"
).
-
void PATHS_SetBasename(PATHS_Pathname *inPN, char *inNewBasename);
Set the basename (the portion of a pathname not including directory
specifications and not including the extension) of a Pathname object.
-
void PATHS_SetDirectory(PATHS_Pathname *inPN, char *inNewDirectory);
Set the directory portion of a Pathname object.
-
bool PATHS_Search(PATHS_Pathname *inPN);
Fully qualify a Pathname object using the list of search paths. If
the input pathname contains directory information, no searching is
done. Returns TRUE
if the file exists, otherwise FALSE
.
-
char *PATHS_GetDirectory(PATHS_Pathname *inPN);
Get the directory portion of a Pathname object.
-
char *PATHS_GetBasename(PATHS_Pathname *inPN);
Get the basename portion of a Pathname object
-
char *PATHS_GetExtension(PATHS_Pathname *inPN);
Get the extension of a Pathname object.
-
char *PATHS_GetFilename(PATHS_Pathname *inPN);
Get the filename portion of a Pathname object. The filename portion is
the basename and extension, without any directory information.
-
char *PATHS_GetFullname(PATHS_Pathname *inPN);
Get the full name of a Pathname object. The full name is the fully
qualified pathname for the object.
2.8.5 Util
The Util module was extracted from the compiler some time ago and still
contains routines used by the compiler. It has not been rewritten in
the style of the other modules in Teyjus.
This document was generated by Gopalan Nadathur on October, 20 2007 using texi2html 1.76.