Resources for Exp

Add resource manager objects to the Exp environment so that values such as button titles, view names, and the debug flag may be set by resources rather than hardcoded. Resource manager objects (rmo's) allow a tool to interact with Centaur's resource database. When defining a tool class (such as the interpreter tool class), it is interesting to define an rmo class alongside. Whereas the tool class defines properties required by the tool to perform its computations, the rmo class defines resource properties required by the tool to access important values.

Once you have defined an rmo class, you may create an rmo instance required for access to the resource database. The object is registered in a tree of rmo instances global to the Centaur system. A path in the tree of rmo instances determines the resource path required to specify a value for a property. More precisely, each rmo instance has an associated query that it uses to interrogate the database. The query's list of instance and class names is formed by the instance and class names of the query's ancestors in the rmo tree.

Rmo instances that share the same parent in the rmo tree must differ in either class or instance name. The rmo object must also be accessible to the tool (either stored in it or visible globally) so that at any moment during a computation, the tool may use it to interrogate the resource data base. For complete information about rmo's, please consult the resource manual. The following Le-Lisp code should also be included in contrib/Exp/environment/interpreter.ll

The first task, therefore, is to define an appropriate rmo class for the interpreter tool with the defrmo function.


   (defrmo Interpreter
           (Debug symbol none)
           (Initial-view-title string "Initial Env")
           (Result-view-title string "Result Env"))

The Interpreter class specifies three properties: Debug, Initial-view-title, and Result-view-title. The allowed value type follows each name, then the default value. Once we have defined the class, we may create instances with the function #:rmo:create. This function takes a class name and an instance name. For example, Centaur creates an rmo instance for each formalism object declared by resources by calling this function with the Formalism rmo class name and as instance name, the formalism name.

What instance name should we choose for our rmo? The answer to this question depends on the resource semantics we require. If we desire that each tool be able to specify different values for the resources, we must provide each rmo with a distinct instance name. For example, we may want to interpret one Exp program in debug mode and another in normal mode. On the other hand, we may not require such individuality, and the same resources could apply to all tool instances. When dealing with formalisms, for example, we definitely need to be able to specify different resources for different formalism instances. In the Exp environment, for example, we probably don't require button titles to vary between interpreter tool instances. In this case, we only require one rmo instance -and therefore one instance name- available to all interpreter tool instances. In this tutorial, no name distinguishes tool instances that we might use as an rmo instance name. We therefore elect the global rmo option. Note that were we to create a distinct rmo instance for each tool instance, we could extend the tool class to allow us to store an rmo in the tool. However, since our rmo instance will be unique and global, we will make it available otherwise.

The next important issue is where to register the rmo instance in the rmo tree. This choice depends on the resource path we want to follow in order to specify interpreter properties. The interpreter depends on the Exp formalism and is implemented in Typol. It makes sense to specify interpreter properties by some path that encompasses that information. For every declared formalism, Centaur creates instances of the predefined Formalism and Semantics rmo classes, and registers these instances in the rmo tree. If we register the interpreter rmo below the Semantics instance, we generate the following query:


< <centaur-name>.Exp.semantics.interpreter | 
  Centaur.Formalism.Semantics.Interpreter>

With this query we may specify interpreter property values, for example, by:


Centaur.Exp.Semantics.interpreter.Debug : t
Centaur.Exp.Semantics.interpreter.Initial-view-title : Initial View
Centaur.Exp.Semantics.interpreter.Result-view-title : Final View

The following code creates and registers an instance of the Interpreter rmo class. If such an rmo has already been created, it is returned.


(de :rmo:find ()
    (let ((semantics-rmo (#:SemanticsManager:semantics-rmo 'Exp)))
    (or (#:rmo:subobject semantics-rmo 'interpreter 'Interpreter)
        (let ((new (#:rmo:create 'interpreter 'Interpreter)))
             (#:rmo:register-object semantics-rmo new)
             new))))

This function may be called by the interpreter tool wherever it needs to access the database. For example, to determine debug mode:


(de :callback:interpret (stnode port)
  (lets ((tool (st-object stnode))
         (root (:tool:get-source tool))
         (env  (:tool:get-initial-env tool))
         (debug 
           (neq 'none (#:properties:get-property (:rmo:find) 'Debug)))
         )
    ;;If no environment tree memorized by tool,
    ;;call appropriate Typol predicate.
    (if env
        (ty-run tool '#:eval_exp:full_eval_exp debug root env)
        (ty-run tool '#:eval_exp:init_eval_exp debug root)
        )))

The generic function #:properties:get-property takes an rmo and a property name and returns the value stored in the resource database. N.B. We may not specify nil as a property value, so instead we specify none which we then interpret to mean nil.

Two issues remain: Where do we store interpreter resources? And how do we load them automatically into the resource database with the Exp environment? We suggest specifying interpreter resources in a file named: contrib/Exp/semantics/interpreter/interpreter.rdb

The resources provided by an environment must be general enough to allow users to override them, and specific enough to not be subsumed by other system resources. For the Exp environment, it makes sense to use the asterisk up to the formalism name, and classes everywhere else.


*Exp.Semantics.Interpreter.Debug : none
*Exp.Semantics.Interpreter.Initial-view-title : Initial View
*Exp.Semantics.Interpreter.Result-view-title : Final View

We would like to load resources from this file when necessary, i.e., at the first request for an interpreter property value. To do so, we create an instance of the predefined Database rmo class which simply describes the location of a database file. We will register this rmo instance under the Interpreter instance, so it should be created at the same time:


(de :rmo:find ()
    (let ((semantics-rmo (#:SemanticsManager:semantics-rmo 'Exp)))
    (or (#:rmo:subobject semantics-rmo 'interpreter 'Interpreter)
        (let ((new (#:rmo:create 'interpreter 'Interpreter)))
             (#:rmo:register-object semantics-rmo new)
             ;;Create Database rmo and load database.
             (#:databaseMan:load (#:databaseMan:database new))
             new))))

The previous function will load the database file automatically provided some specification identifies the database location when the function is called. Therefore, the following resource should be included in the formalism resource file Exp.rdb:


*Exp.Semantics.Interpreter.Database.Location : \resbs
contrib/Exp/semantics/interpreter/interpreter.rdb

If you modify these resources dynamically, don't forget to reset the database!


                  



Tutorial