5 Application Programmer's Interface

The compiler is available to Mozart applications through the module Compiler. This chapter describes the functionality provided by that module and its classes.

First, a number of additional secondary type names used in this description is introduced in Section 5.1, then the Compiler module is described in Section 5.2. The material in that section should prove sufficient for most cases. The remainder of the chapter is intended for advanced uses.

An arbitrary number of compilers may be instantiated, each with its own internal state, and used concurrently. We distinguish between compiler engines, described in Section 5.3, which store the state of a compiler and perform the compilation proper, and compiler interfaces, described in Section 5.4, which allow to observe the activities of compiler engines and to react to them. Both of these use the narrator/listener mechanism described in Appendix B; familiarity with this is assumed.

Finally, serving the purpose of examples, the provided abstractions are explained in terms of compiler engines and interfaces in Section 5.5.

5.1 Additional Secondary Types

This section describes additional secondary types used in the descriptions in this chapter. The conventions defined in Section 2.3 of ``The Oz Base Environment'' will be respected.

Coord

stands for information about source coordinates. This is either unit if no information is known or a tuple pos(FileName Line Column), where FileName is represented as an atom ('' meaning `unknown') and Line and Column are integers. Line numbering begins at 1 and column numbering at 0; a column number of ~1 means `unknown'.

SwitchName

is an atom which must be a valid switch name (see Appendix A).

PrintName

is an atom which must be a valid variable print name.

Env

represents an environment, represented as a record whose features are valid print names.

5.2 The Compiler Module

evalExpression

{Compiler.evalExpression +V +Env ?KillP X}

evaluates an expression, given as a virtual string V, in a base environment enriched by the bindings given by Env, either returning the result X of the evaluation or raising an exception. Furthermore, the variable KillP is bound to a nullary procedure which, when applied, interrupts compilation.

virtualStringToValue

{Compiler.virtualStringToValue +V X}

is a replacement for System.virtualStringToValue, which was available in Mozart's predecessor DFKI Oz.

Note that you are discouraged from using this for large data structures: Because it is much more powerful than System.virtualStringToValue, it can also be much less efficient. Rather, you should use pickling and unpickling of data structures ``System Modules''.

engine

Compiler.engine

is the final class from which compiler engines can be instantiated. This is described in detail in Section 5.3.

interface

Compiler.interface

is a class providing a simple mechanism to create compiler interfaces. It is described in detail in Section 5.4.

parseOzFile

{Compiler.parseOzFile +V +O +P +Dictionary ?T}

parseOzVirtualString

{Compiler.parseOzVirtualString +V +O +P +Dictionary ?T}

assemble

{Compiler.assemble +Ts +Xs +SwitchR ?P}

5.3 Compiler Engines

Instances of the Compiler.engine class are active objects called compiler engines. Each object's thread processes all queries inside its query queue sequentially.

The final class Compiler.engine inherits from Narrator.'class', described in Appendix B.

5.3.1 Methods of the Compiler.engine Class

enqueue

enqueue(+T ?I <= _)

enqueue(+Ts ?Is <= _)

appends a new query T to the query queue. If T is an unknown query, an exception is raised immediately. All of the query's input arguments (the subtrees of T) are type-checked before it is enqueued.

Internally, each enqueued query is assigned a unique identification number I. This may be used later to remove the query from the queue (unless its execution has already begun or terminated).

The argument to enqueue may also be a list of queries: These are guaranteed to be executed in sequence without other queries interleaving. The second argument then returns a list of identification numbers.

dequeue

dequeue(+I)

dequeues the query with identification number I, if that query is still waiting in the query queue for execution, else does nothing.

interrupt

interrupt()

interrupts execution of the current query. Does not affect the remaining queue.

clearQueue

clearQueue()

flushes the whole remaining queue. Does not affect the currently processed query (if any).

5.3.2 Queries

This chapter documents the queries understood by the Mozart Compiler.

Some queries request state information from the compiler engine. The following description annotates the corresponding output variables with a question mark, although they only become bound when the query is actually executed. If binding an output variable raises an exception, an error is reported through the registered listeners (see Appendix B).

Macro Definitions

macroDefine(+V)

Add V to the set of defined macro names.

macroUndef(+V)

Remove V from the set of defined macro names.

getDefines(?PrintNames)

Return all currently defined macro names as a list, in no particular order.

Compiler Switches

setSwitch(+SwitchName +B)

Set the state of the given switch to either `on', if B == true, or to `off', if B == false.

getSwitch(+SwitchName ?B)

Return the state of the given switch.

pushSwitches()

Save the current settings of all switches onto the internal switch state stack.

popSwitches()

Restore all switch settings from the topmost element of the internal switch state stack, provided it is not empty, else do nothing.

Compiler Options

setMaxNumberOfErrors(+I)

Set the maximal number of errors to report for any one compilation before aborting it to I. A negative value means never to abort.

getMaxNumberOfErrors(?I)

Return the maximal number of errors to report for any one compilation before aborting it.

setBaseURL(+VU)

Set the base URL relative to which the require clause of computed functors is resolved. A value of unit means to resolve the imports relative to the location of the file in which the functor keyword appeared.

getBaseURL(?AU)

Return the base URL relative to which the require clause of computed functors is resolved.

The Environment

addToEnv(+PrintName X)

Add a binding for a variable with the given print name, and bound to X, to the environment.

lookupInEnv(+PrintName X)

Look up the binding for the variable with the given print name in the environment and bind X to its value. If it does not exist, report an error.

removeFromEnv(+PrintName)

Remove the binding for the variable with the given print name from the environment if it exists.

putEnv(+Env)

Replace the current environment by the one given by Env.

mergeEnv(+Env)

Adjoin Env to the current environment, overwriting already existing bindings.

getEnv(?Env)

Return the current environment.

Feeding Source Text

feedVirtualString(+V)

Evaluate the Oz source code given by the virtual string V.

feedVirtualString(+V +R)

Evaluate the Oz source code given by the virtual string V, returning the resulting value in R.result (if the \switch +expression switch is set and R has the feature result).

feedFile(+V)

Evaluate the Oz source code contained in the file with name V.

feedFile(+V +R)

Evaluate the Oz source code contained in the file with name V, returning the resulting value in R.result (if the \switch +expression switch is set and R has the feature result).

Synchronization

ping(?U)

Bind the variable U to unit on execution of this query. This allows to synchronize on the work of the compiler, e. g., to be informed when a compilation is finished.

ping(?U X)

Works like the ping(_) query, except gives a value which will reappear in the response notification sent to interfaces. This allows to identify the ping query with its pong notification.

Custom Front-Ends

setFrontEnd(+P1 +P2)

5.4 Compiler Interfaces

As said above, compiler engines are narrators. The term ``compiler interface'' simply denotes a standard listener attached to a compiler engine. This section presents what is required to implement a compiler interface.

First the notifications sent by compiler engines are documented. These include normal compiler output and information about compiler state changes. Then a specific compiler interface is described that makes many compilation tasks easy to control.

5.4.1 Sent Notifications

Query Queue

newQuery(I T)

A new query T with identification I has been enqueued.

runQuery(I T)

The query T with identification I is now being executed.

removeQuery(I)

The query with identification I has been removed from the query queue, either because it finished executing or because it was dequeued by a user program.

Compiler Activity

busy()

The compiler is currently busy (i. e., executing a query).

idle()

The compiler is currently idle (i. e., waiting for a query to be enqueued).

State Change

switch(SwitchName B)

The given switch has been set to B.

switches(R)

The settings of all switches is transmitted as a record mapping each switch name to its setting.

maxNumberOfErrors(I)

The maximum number of errors after which to abort compilation has been set to I.

baseURL(AU)

The base URL relative to which the require clause of computed functors is resolved has been set to AU.

env(Env)

The environment has been set to Env.

Output

info(V)

An information message V is to be printed out.

info(V Coord)

An information message V, related to the source coordinates Coord, is to be printed out.

message(R Coord)

An error or warning message R, related to the source coordinates Coord, is to be printed out. R has the standard error message format, described in mozart/share/lib/sp/Error.oz.

insert(V Coord)

During parsing, the file named V has been read. The corresponding \insert directive (if any) was at source coordinates Coord.

displaySource(TitleV ExtV V)

A source text V with title TitleV is to be displayed; its format is the one for which the file extension ExtV is typically used (such as oz or ozm).

attention()

The error output buffer should be raised with the cursor at the current output coordinates (an error message should follow).

Synchronization

pong(X)

This is sent in response to a ping(_) or ping(_ X) query (see Section 5.3). In the first case, unit is returned in X.

5.4.2 The Compiler.interface Class

init(+EngineO +L <= false)

reset()

sync()

getInsertedFiles(?Vs)

getSource(?V)

5.5 A Look into the Provided Abstractions

proc {Compiler.evalExpression VS Env ?Kill ?Result} E I S in 
   E = {New Compiler.engine init()}
   I = {New Compiler.interface init(E)}
   {E enqueue(mergeEnv(Env))}
   {E enqueue(setSwitch(expression true))}
   {E enqueue(setSwitch(threadedqueries false))}
   {E enqueue(feedVirtualString(VS return(result: ?Result)))}
   thread T in 
      T = {Thread.this}
      proc {Kill}
         {E clearQueue()}
         {E interrupt()}
         try 
            {Thread.terminate T}
            S = killed
         catch _ then skip   % already dead
         end 
      end 
      {I sync()}
      if {I hasErrors($)} then Ms in 
         {I getMessages(?Ms)}
         S = error(compiler(evalExpression VS Ms))
      else 
         S = success
      end 
   end 
   case S of error(M) then 
      {Exception.raiseError M}
   [] success then skip 
   [] killed then skip 
   end 
end 

fun {Compiler.virtualStringToValue VS}
   {Compiler.evalExpression VS env() _}
end 


Leif Kornstaedt
Version 1.1.0 (20000207)