Adenine Tutorial

Introduction

The Semantic Web stands to revolutionize the way in which Internet applications are written. By standardizing the language for encoding knowledge representations and transferring information over the network, the Semantic Web enables computer agents to automate many information-driven activities in our daily lives, such as appointment scheduling, comparison shopping, and Web searches. However, to enable the next generation of Internet applications to take advantage of the Semantic Web’s knowledge representational facilities, programming tools must be made available that make common Semantic Web activities convenient to implement.

Why Adenine?

The motivation for creating Adenine is twofold. First, introducing the RDF data model into a standard object oriented language is fairly straightforward, since object oriented languages were designed specifically to be extensible in this fashion. Normally, one creates a class library to support the required objects. However, more advanced manipulation paradigms specific to an object model begin to tax the syntax of the language. In languages such as C++, C#, and Python, operator overloading allows programmers to reuse built-in operators for manipulating objects. However, one is restricted to the existing syntax of the language; one cannot easily construct new syntactic structures. In Java, operator overloading is not supported, and this results in verbose APIs being created for any object oriented system. Arguably, this verbosity can be said to improve the readability of code.

On the other hand, lack of syntactic support for a specific object model can be a hindrance to rapid development. Programs can end up being three times as long as necessary because of the verbose syntactic structures used. This is the reason behind the popularity of domain-specific programming languages. Adenine is such a language. It includes native support for RDF data types and makes it easy to interact with RDF containers and services.

The other key feature of Adenine is its ability to be compiled into RDF. The benefits of this capability can be classified as portability and extensibility. Since 1996, p-code virtual machine execution models have resurged as a result of Java’s popularity. Their key benefit has been portability, enabling interpretation of software written for these platforms on vastly different computing environments. In essence, p-code is a set of instructions written to a portable, predetermined, and byte-encoded ontology.

Adenine takes the p-code concept one step further by making the ontology explicit and extensible and by replacing bytecodes with RDF. Instead of dealing with the syntactic issue of introducing bytecodes for new instructions and semantics, Adenine takes advantage of RDF’s ability to extend the directed “object code” graph with new predicate types. The idea of having metadata-extensible languages has become popular lately with the introduction of Microsoft’s Common Language Runtime (CLR). In a language such as C#, developer-defined attributes can be placed on methods, classes, and fields to declare metadata ranging from thread safety to serializability. Compare this to Java, where serializability was introduced only through the creation of a new keyword called transient. The keyword approach requires knowledge of these extensions by the compiler; the attributes approach delegates this knowledge to the runtime and makes the language truly extensible. In Adenine, RDF assertions can be applied to any statement.

Conventions

In this document, code snippets are presented in the following style:

add { <urn:xxx>
   rdf:type hs:Person ;
   dc:title "Dennis Quan"

}


Variable names, function names, and other code entities that appear inline with regular text are shown in monospace typeface.

Adenine prefixes, such as rdf:, dc:, and hs: shown above, are defined in Appendix A where not explicitly specified.

Defining Ontologies

We introduce Adenine and use it for the purpose for which it was designed: to express sets of RDF statements concisely and succinctly. Many of the basic concepts of RDF, including resources, literals, lists, prefixes, and ontologies, have convenient syntax in Adenine.

The Structure of an Adenine Source File

Adenine source files hold Adenine source code and serve as the unit of compilation. The Adenine compiler takes Adenine source code and produces a collection of RDF statements. An example source file is given below.

# An example Adenine source file
#@base <http://example.org/sample>

@prefix dc: <http://purl.org/dc/elements/1.1/>
@prefix sample: <http://example.org/sample#>

add { ^
    rdf:type daml:Ontology ;
    dc:title "Sample Ontology"
}

add { sample:age
    rdf:type daml:DatatypeProperty ;
    rdfs:isDefinedBy ^ ;
    rdfs:label "Age" ;
    rdfs:range xsd:int
}


The first line of the file demonstrates how comments are expressed in Adenine: with a hash mark (#) as the first non-space character on a line. The comment area extends to the end of the line.

The second line of the file gives an @base declaration. This directive specifies the URI of the Adenine source file, much like the <base> tag does in HTML.

Following the @base declaration is a series of @prefix specifications. They instruct the compiler to define prefixes such as dc:, whose URI is prepended to the text following the colon in identifiers such as dc:title. By default, the following prefixes are also defined:

Prefix

URI

Use

rdf:

<http://www.w3.org/1999/02/22-rdf-syntax-ns#>

RDF standard ontology

rdfs:

<http://www.w3.org/2000/01/rdf-schema#>

RDF Schema ontology

daml:

<http://www.daml.org/2001/03/daml+oil#>

DAML+OIL ontology

xsd:

<http://www.w3.org/2001/XMLSchema#>

XML Schema Datatypes

adenine:

<http://haystack.lcs.mit.edu/schemata/adenine#>

Adenine ontology

random:

A random URI generated each time the file is compiled

Varies

:

The @base URI plus a colon (:), or a random URI distinct from the one assigned to random: if @base is not specified

Local definitions

While @base and @prefix declarations can appear anywhere in the file, they only affect the text following the declarations and are best made at the top of the file.

Defining RDF Statements

The remainder of the file consists of a series of add {} blocks. In Adenine curly braces ({}) are used to enclose RDF statements. The elements within the curly braces come three elements at a time: subject, then predicate, then object, in that order. No delimiter is used between statements.

Certain special symbols are permitted within statement blocks. The caret (^) refers to the URI of the file given by an @base declaration. In the example, the source file is declared to have type daml:Ontology. A semicolon (;) may be used in the subject field to refer to the previously used subject.

Additionally, Adenine supports the notion of existential nodes, declared by the ${} syntax. Existential nodes are resources whose properties are known but whose URI is not known or relevant. They can be used anywhere a resource is needed. For example:

add { :john
    :hasChild ${
        rdf:type :Person ;
        dc:title “Joe”
    }
}


Here, :john is asserted to have a child whose name is “Joe” and who is a :Person, but the URI of this child is randomly generated at compile time. Like normal curly braces, existential node expressions can have RDF statements embedded within them, except that the subject is never specified as it is implied to be the existential node; furthermore, semicolons must be used to separate property/object pairs.

Finally, Adenine supports a convenient syntax for specifying DAML+OIL lists: @(). For example:

add { :john
    :favoriteColorsInOrder @( "blue" "black" "green" "red" )
}


@() can contain any combination of resources, literals, existential nodes, or even other lists. While @() can be used anywhere resources can, it does not allow you to specify the name of the daml:List resource, much like ${}. In fact, the preceding sample is identical to the following:

add { :john
    :favoriteColorsInOrder ${
        rdf:type daml:List ;
        daml:first "blue" ;
        daml:rest ${
            rdf:type daml:List ;
            daml:first "black" ;
            daml:rest ${
                rdf:type daml:List ;
                daml:first "green" ;
                daml:rest ${
                    rdf:type daml:List ;
                    daml:first "red" ;
                    daml:rest daml:nil
                }
            }
        }
    }
}


The Adenine Runtime Environment

We have now seen how Adenine can be used to conveniently define ontologies and state information using RDF. In this chapter we focus on another aspect of Adenine—the programming language. Adenine includes an interpreted, dynamically typed language that shares many features with modern programming languages such as JavaScript, Scheme, and Python. We discuss the syntax and semantics of Adenine code and demonstrate the building blocks of the language with numerous examples. In Chapter 5 we will learn how Adenine’s programming language and data definition language are connected.

Basic Expressions

Like certain languages such as Scheme, JavaScript, Perl, and Python, Adenine can be used interactively. The Adenine Console is provided to allow interactive use of the Adenine interpreter. Using the Adenine Console is perhaps the easiest way to get started learning the language. You can find the Adenine Console under the Development tools collection under Starting Points. The design of the Adenine Console is extremely simple: the console prompts you for a block of code to evaluate, and after you press Enter the Adenine interpreter evaluates the code and displays the result; this cycle then repeats itself indefinitely.

The following example using IFCX Wings embedded in this document demonstrates how to form some basic Adenine expressions:

+ 1 2

3

+ (* 3 4.5) 5 6

24.5

print '4 divided by 2 is' (/ 4 2)

4 divided by 2 is 2


The first example is an example of a simple function call. The + function is being invoked with the integer parameters 1 and 2. (What are sometimes operators in other languages are implemented as functions in Adenine.) Function calls are expressed in prefix notation, i.e., the function being called is given first, followed by the parameters to the function. All of the standard arithmetic operators are available: + (addition), - (subtraction or negation when only one parameter is given), * (multiplication), and / (division).

The second example demonstrates a more complex function call in which one of the parameters is the result of another function call. Function calls that appear within other expressions are enclosed within parentheses. Operationally, the parameters (and possibly the function itself) are evaluated in some unspecified order before the function call takes place. Furthermore, 4.5 is interpreted as a double precision number. The arithmetic operators know to promote integers when needed to retain the precision of the result.

The third example demonstrates the print function, which can take any number of parameters and prints out their string representations, separated by spaces. Another data type, the string, is used in this example. Strings in Adenine are enclosed in single quotes ('').

Variables

One can bind values to variables in Adenine using the assignment (=) command.

= x 10

10

+ x (* x 2)

30

= x 'hi'

hi

print x

hi


The assignment command can also be used to change the value of a variable. Note that commands such as = are not functions, so they cannot be nested within expressions.

Boolean Expressions

Adenine supports a Boolean data type and the keywords true and false, which evaluate to the Boolean values of true and false, respectively. Unlike some languages, true and false are distinct from the integer values 1 and 0 with which they are often associated. Additionally, several common Boolean operators are available:

·          Equality function (==): tests for equality among its parameters.

·          Inequality function (!=): tests for inequality among its parameters.

·          Greater than function (gt): returns true when the first parameter is greater than the second parameter; otherwise false.

·          Less than function (lt): returns true when the first parameter is less than the second parameter; otherwise false.

·          Boolean And function (and): returns true when all of its parameters evaluate to true; otherwise false.

·          Boolean Or function (or): returns true when any of its parameters evaluate to true; otherwise false.

·          Boolean Not function (!): returns the opposite value of its parameter.

Note that unlike many languages, Adenine’s and and or functions do not short circuit; all parameters are evaluated before the function call is evaluated.

while

A number of basic control structures are available in Adenine. The simplest of these is the while command, which repeatedly executes a block of code while the given expression evaluates to a non-false value. Try the following in the Adenine Console; note that in order to go to the next line before you have entered the entire expression, you must press Control+Enter:

= x 1
= sum 0
while (!= x 10)
    = sum (+ sum x)
    = x (+ 1 x)
print x

10


As in the data definition language, lines that begin with a hash mark (#) are comments.

Perhaps the most important aspect of this example is that it demonstrates Adenine’s use of indentation to delineate block structure. Commands that require a body, such as a while loop, incorporate a block, which is a series of statements that have been indented at the same level. The end of the block is signified by a return to a previous indentation level.

Like Java, C++, Python, and JavaScript, Adenine supports the break and continue commands for exiting a while loop and for rechecking the loop condition and returning to the beginning of the loop, respectively.

Static scoping

Variables are said to be in scope when they can be referred to and evaluated. A variable is clearly not in scope until after it has been defined for the first time with the assignment command. However, there are other rules governing the scoping of variables. Adenine is a statically-scoped language, meaning that the scope of a variable is defined to be the block in which the variable is defined and all sub-blocks thereof. (Exceptions to this rule will be introduced in the next chapter.) In other words, a variable cannot be referred to in code outside of the block it was defined in. For example:

= x 0
while (!= x 1)
    # y is defined in this block
    = y 2

    # x can be used in this block because it was defined in a parent block
    = x (+ 1 x)

# At this point, y is no longer in scope!
print y

edu.mit.lcs.haystack.adenine.interpreter.UnboundIdentifierException: Unbound identifier: y
        identifier evaluation instruction at line 10
        Function call at line 10

To avoid this problem, a variable must either be assigned a value in a parent block or they can be declared with the var command:

= x 0

# Declare y in this block
var y

while (!= x 1)
    # y is defined in this block
    = y 2

    # x can be used in this block because it was defined in a parent block
    = x (+ 1 x)

# The value of y is retained now
print y

2


if/else

The if command executes its body if the supplied condition evaluates to a non-false value:

if (== 4 (* 2 2))
    print '2 times 2 is 4'

2 times 2 is 4


An if command can also incorporate an optional else clause:

if (== 4 (* 2 2))
    print '2 times 2 is 4'
else
    print 'Something is wrong!'

2 times 2 is 4


Unlike in other languages, there is no ambiguity when nesting if/else commands because of the indentation structure:

if (== 4 (* 2 2))
    print '2 times 2 is 4'
    if (== 8 (* 3 3))
        print '3 times 3 is 8'
    else
        print "But 3 times 3 isn’t 8!"

2 times 2 is 4
"But 3 times 3 isn't 8!"


Collections and for…in

Adenine supports a number of different collection data types, such as lists and sets. Collections can contain objects of any type and can be mutated by calling member functions such as add and remove. The following code snippet demonstrates these features:

# Make a list of the primary colors
= colors @('red' 'blue' 'green')

# Add cyan, violet, and yellow
= otherColors (Set 'cyan' 'violet' 'yellow')
colors.addAll otherColors

# Add black and remove red
colors.add 'black'
colors.remove 'red'

# Print out the colors
for x in colors
    print x

blue
green
cyan
yellow
violet
black


As is the case in the data definition language, @() can be used to construct a list object. Alternatively, the List function can also be used. Sets are created using the Set function.

Objects in Adenine sometimes have member functions, which may be accessed by means of the dereferencement operator (.). You can easily learn about what members are available for any expression by passing it to the help function in the Adenine Console.

The for…in statement executes the body once for each item in the given collection. On each iteration the given variable name is bound to the element in the collection being processed. For collections that support a notion of order, such as lists, the elements are iterated in order. The body of a for…in statement can also incorporate the break and continue commands.

Ordered collections also support the use of the index operator ([]) for referring to the nth element in a collection (indices are 0-based):

= x @( 1 2 3 4 )
print x[0]

1


Defining functions

Custom functions can be defined in Adenine by using the function command. Take the example of the factorial function:

function factorial x
    if (== 1 x)
        return 1
    else
        return (* x (factorial (- x 1)))

edu.mit.lcs.haystack.adenine.interpreter.Closure@24f60c

factorial 5

120

The first line of a function definition states the name of the function as well as the names of the variables to which parameters will be bound when the function is called (called formal variables). Functions in Adenine are first class, i.e., they are values that can be bound to variables like integers and strings. In fact, the function command binds the defined function to a variable much as the assignment instruction does. The resulting variable is then subject to the same rules of static scoping as other variables.

The function name as well as the declared formal variables are in scope within the body of the function. Variables defined in parent blocks of the function definition are also in the scope of the function.

The return command returns the given value to the caller.

Manipulating RDF

Using the language primitives set forth in the previous chapters, we are now ready to talk about how Adenine facilitates the manipulation of RDF data. In this chapter we introduce the basic RDF manipulation functions and objects built into Adenine as well as the relationship between the data definition language and the programming language.

RDF Data Types

The Adenine programming language supports a special data type called the RDF container. RDF containers store sets of RDF statements and allow statements to be added, removed, or queried for. An RDF container can be created and initialized with a series of RDF statements by using curly braces ({}):

= x { :john rdf:type :Person ; dc:title "John" }

class edu.mit.lcs.haystack.rdf.LocalRDFContainer - 2 statements

The same notation that was introduced in Chapter 3can be used with {}in code. In other words, resources can be named with angle brackets (<>), literals with double quotes (""), and existential nodes and lists with ${}and @(), respectively. In fact, these objects can even be used outside of {}:

= person1 ${
    rdf:type :Person ;
    dc:title "Mary"
}
= person2 <urn:sample:john>
= person3 :joe
= myNameAsALiteral "Dennis"

"Dennis"

In other words, resources and literals are built-in Adenine data types that can be used anywhere in Adenine. Furthermore, variables and expressions can be used in {}, and the values to which they evaluate will be used in constructing statements:

= peopleInformation { :dennis
    :knows @(
        person1
        person2
        person3
    ) ;
    dc:title myNameAsALiteral ;
    :idNumber (+ 45 50)
}

class edu.mit.lcs.haystack.rdf.LocalRDFContainer - 12 statements

When an expression that appears in {} does not evaluate to a resource or a literal, a literal is constructed consisting of the expression’s string representation. In the preceding example, the :idNumber property is set to be the literal "90". Also, the block indentation rules do not apply within {} or ${}; you are free to add whitespace to the expression as needed.

Resources and literals can also be constructed directly via the Resource and Literal functions:

# The following two expressions will evaluate to true
== <urn:test> (Resource 'urn:test')
== "Test" (Literal 'Test')

true

Dynamic Variables

In Chapter 4 we introduced the concept of static scoping in Adenine. Adenine also supports variables that are dynamically scoped. That is, the value of a dynamic variable is determined based on whatever value was last assigned to it, regardless of block structure. Dynamic variables are assigned using the with command and retain their value for the body of the with command, as well as for whatever functions are called within. For example, the following code prints out the number 25:

# __x__ is not defined at this point
function addToX y
    return (+ __x__ y)

with __x__ 10
    # __x__ is defined for the duration of this block,
    # as well as for whatever functions that are called within
    print (addToX 15)

# __x__ is now no longer defined

25


By convention, dynamic variables are prefixed and suffixed with two underscore characters to distinguish them from statically-scoped variables.

Manipulating RDF Containers

We now introduce two standard dynamic variables that are always defined in an Adenine program: __source__ and __target__. These variables refer to RDF containers and are used by the functions add, remove, query, extract, contains, and others.

The add function adds a set of statements into __target__. Consider the example below:

add { :john
    :hasChild ${
        rdf:type :Person ;
        dc:title "Joe"
    }
}


This example was in fact taken from Chapter 3. The syntax of the add function was designed to duplicate the syntax used in the data definition language, except that Adenine expressions can also be incorporated into {}.

The contains function checks for the existence of a statement in __source__:

contains :john rdf:type :Person

false

This expression would evaluate to trueif the statement :john rdf:type :Personexists in the store; otherwise it would evaluate to false.

The remaining functions support the use of existential variables, which serve as placeholders or wildcards. Existential variables are composed of a question mark (?) and any sequence of alphanumeric characters. For example, the removefunction deletes statements of the form given by the three parameters to remove from __target__, treating any existential variables as wildcards:

# Remove all information about :john
remove :john ?x ?y


The extractfunction, like the containsand removefunctions, takes three parameters, a subject-predicate-object triple. However, one of these three parameters must be an existential variable, and extractfinds some statement that satisfies this pattern and returns a resource or literal that fills that position. For example:

= database { :john :nickname "Johnny" ; :nickname "Jonathan" }
with __source__ database
    print 'John likes to be called' (extract :john :nickname ?x)

John likes to be called "Jonathan"


This example, when run, would print either "Johnny"or "Jonathan". Notice the use of with for overriding the dynamic variable __source__ for use with the extract function.

RDF Queries

The query function allows you to express complex queries against the __source__ RDF container. query takes up to three parameters, but the last two are optional. The first parameter is a set of RDF statements that incorporate a series of existential variables. query returns a set of arrays that correspond to assignments of existential variables. When these assignments are substituted into the query specification, statements are formed that match statements in __source__. The second parameter allows you to specify which and in what order the existential variable matches will appear in the result set arrays.

The following code snippet shows some example queries. Note that the Adenine Console has a built-in RDF container that is attached to both __source__ and __target__. Also, the printset command is used to print out the Set returned by query.

#@prefix : <urn:sample:>
add { :bob :age "30" ; :hasSister :mary ; :hasSister :jane }
add { :mary :age "30" }
add { :jane :age "25" }


Ask for all ?x whose :age property is "30".

printset (query { ?x :age "30" })

<urn:06MhHv72cPUrUe2:mary>
<urn:06MhHv72cPUrUe2:bob>


A bit more complex: search the __source__ for all pairs ?x and ?y that satisfy the relationship ?x :hasSister :y and asks that the rows in the result set be ordered ?x then ?y.

printset (query { ?x :hasSister ?y } @(?x ?y))

<urn:06MhHv72cPUrUe2:bob> <urn:06MhHv72cPUrUe2:mary>
<urn:06MhHv72cPUrUe2:bob> <urn:06MhHv72cPUrUe2:jane>


More complex yet; here, a list of resources and their sisters’ ages is requested.

printset (query { ?x :hasSister ?y ?y :age ?z } @(?x ?z))

<urn:06MhHv72cPUrUe2:bob> "25"
<urn:06MhHv72cPUrUe2:bob> "30"


Methods

Up to this point our discussion of the Adenine programming language has been in the context of interacting with the Adenine interpreter directly via the Adenine Console. Adenine code can also be incorporated into source files. Recall that an Adenine source file compiles into a set of RDF statements. The Adenine compiler supports the notion of an Adenine method, which like a function, can take parameters and evaluate expressions. However, a method is compiled into a series of RDF statements that describe the object code of the method according to the Adenine ontology. This allows code and data to be defined in the same source file and to share a common output representation, namely RDF statements. Also, unlike functions, only methods can be called from a program that has embedded the Adenine interpreter. In this sense, methods serve as entry points into the Adenine runtime environment.

Defining a method looks a lot like defining a function, with a few exceptions. The most significant of the differences is that Adenine methods are resources and are named by URI. The following is an example Adenine source file with some method declarations:

#@base <urn:sample:sampleCode>

@prefix dc: <http://purl.org/dc/elements/1.1/>

add { :Person
    rdf:type rdfs:Class ;
    rdf:isDefinedBy ^ ;
    rdfs:label "Person"
}

add { :fullName
    rdf:type rdf:Property ;
    rdf:isDefinedBy ^ ;
    rdfs:label "Full name" ;
    rdfs:domain :Person ;
}

method :getFullName x
    if (:isAPerson x)
        return (extract x :fullName ?x)

method :isAPerson x
    return (contains x rdf:type :Person)

<urn:06MhHv72cPUrUe2:isAPerson>

add { :jim
   rdf:type :Person ;
   :fullName "James Paul White"
}


:getFullName :jim

"James Paul White"

for p in (query { ?x rdf:type :Person } )
   print (:getFullName p)

edu.mit.lcs.haystack.adenine.AdenineException: Unknown exception: [Ledu.mit.lcs.haystack.rdf.RDFNode;
        Function call at line 23
        return instruction at line 23
        in method <urn:06MhHv72cPUrUe2:isAPerson>
        Function call at line 19
        if instruction at line 19
        in method <urn:06MhHv72cPUrUe2:getFullName>
        Function call at line 2
        Function call at line 2
        for in instruction at line 1

As can be seen from the :getFullName definition, methods can be invoked using the URI naming the method or any expression that evaluates to the method resource.

Interfacing with Java

The reference implementation of Adenine is written in Java, a language in which a lot of useful functionality has been written. Commands are available in Adenine to allow interfacing with Java objects and classes. Adenine code can invoke Java methods, construct Java objects, and access fields.

importjava

The importjava command introduces Java classes into the current scope. Variables are created that share names with the classes they represent and are bound to the java.lang.Class objects themselves. Class objects can be treated as functions, which when invoked, construct an instance of the class by calling the constructor that best matches the parameters passed in. Static members are directly available from class objects.

The following snippet illustrates the use of importjava:

importjava "java.lang" System Runtime StringBuffer
= x (Runtime.getRuntime)
help x

Methods:
void exit(int)
void runFinalizersOnExit(boolean)
void loadLibrary(java.lang.String)
void load(java.lang.String)
void gc()
void runFinalization()
java.lang.Runtime getRuntime()
long freeMemory()
long maxMemory()
void addShutdownHook(java.lang.Thread)
boolean removeShutdownHook(java.lang.Thread)
void halt(int)
java.lang.Process exec(java.lang.String, [Ljava.lang.String;)
java.lang.Process exec([Ljava.lang.String;, [Ljava.lang.String;)
java.lang.Process exec([Ljava.lang.String;, [Ljava.lang.String;, java.io.File)
java.lang.Process exec(java.lang.String, [Ljava.lang.String;, java.io.File)
java.lang.Process exec([Ljava.lang.String;)
java.lang.Process exec(java.lang.String)
int availableProcessors()
long totalMemory()
void traceInstructions(boolean)
void traceMethodCalls(boolean)
java.io.InputStream getLocalizedInputStream(java.io.InputStream)
java.io.OutputStream getLocalizedOutputStream(java.io.OutputStream)


print (x.maxMemory)

266403840


System.getProperty 'os.name'

Mac OS X

= y (StringBuffer)
y.append 'hello'

hello

y.append ' world'

hello world

y.toString

hello world

Trying to load some Hayloft stuff

@prefix config: <http://haystack.lcs.mit.edu/schemata/config#>
@prefix content: <http://haystack.lcs.mit.edu/schemata/content#>
@prefix dc: <http://purl.org/dc/elements/1.1/>
@prefix : <http://haystack.lcs.mit.edu/bootstrap/packages#>

########################################################################
# Functionality Groups

add { <http://haystack.lcs.mit.edu/bootstrap/base>
        rdf:type config:OntologyPackage ;
        dc:description "Base Ontologies" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/bootstrap/base.ad"
}

add { <http://haystack.lcs.mit.edu/bootstrap/haystackBase>
        rdf:type config:OntologyPackage ;
        dc:description "Haystack Base Ontologies" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/bootstrap/haystackBase.ad"
}

add { <http://haystack.lcs.mit.edu/bootstrap/uiBase>
        rdf:type config:OntologyPackage ;
        dc:description "Base User Interface" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/bootstrap/uiBase.ad"
}

add { <http://haystack.lcs.mit.edu/bootstrap/ui>
        rdf:type config:OntologyPackage ;
        dc:description "User Interface" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/bootstrap/ui.ad"
}

add { <http://haystack.lcs.mit.edu/bootstrap/navigation>
        rdf:type config:OntologyPackage ;
        dc:description "Navigation" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/bootstrap/navigation.ad"
}

add { <http://haystack.lcs.mit.edu/bootstrap/operationTaskBase>
        rdf:type config:OntologyPackage ;
        dc:description "Base Operation and Task Support" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/bootstrap/operationTaskBase.ad"
}

add { <http://haystack.lcs.mit.edu/bootstrap/utilities>
        rdf:type config:OntologyPackage ;
        dc:description "Utilities" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/bootstrap/utilities.ad"
}

########################################################################
# Agents


add { <http://haystack.lcs.mit.edu/agents/text>
        rdf:type config:OntologyPackage ;
        dc:description "Text Agents" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/agents/text.ad"
}

add { <http://haystack.lcs.mit.edu/agents/lucene>
        rdf:type config:OntologyPackage ;
        dc:description "Lucene Agent" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/agents/lucene.ad"
}

add { <http://haystack.lcs.mit.edu/agents/content>
        rdf:type config:OntologyPackage ;
        dc:description "Content Agents" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/agents/content.ad"
}

add { <http://haystack.lcs.mit.edu/agents/rdfstore>
        rdf:type config:OntologyPackage ;
        dc:description "RDF Store" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/agents/rdfstore.ad"
}

add { <http://haystack.lcs.mit.edu/agents/information>
        rdf:type config:OntologyPackage ;
        dc:description "Information Agent" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/agents/information.ad"
}

add { <http://haystack.lcs.mit.edu/agents/xml>
        rdf:type config:OntologyPackage ;
        dc:description "XML Recognition Agent" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/agents/xml.ad"
}

add { <http://haystack.lcs.mit.edu/agents/melatonin>
        rdf:type config:OntologyPackage ;
        dc:description "Melatonin Agent" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/agents/melatonin.ad"
}

add { <http://haystack.lcs.mit.edu/agents/mercury>
        rdf:type config:OntologyPackage ;
        dc:description "Mercury Agent" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/agents/mercury.ad"
}

add { <http://haystack.lcs.mit.edu/agents/scheduler>
        rdf:type config:OntologyPackage ;
        dc:description "Scheduler Agent" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/agents/scheduler.ad"
}

add { <http://haystack.lcs.mit.edu/bootstrap/baseAgents>
        rdf:type config:OntologyPackage ;
        dc:description "Base Agents" ;
        rdf:type content:NullContent ;
        config:includes <http://haystack.lcs.mit.edu/agents/content> ;
        config:includes <http://haystack.lcs.mit.edu/agents/rdfstore>
}

########################################################################
# Miscellaneous Packages

add { <http://haystack.lcs.mit.edu/ui/setup>
        rdf:type config:OntologyPackage ;
        dc:description "Setup UI" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/ui/setup.ad"
}

add { <http://haystack.lcs.mit.edu/ui/standalone>
        rdf:type config:OntologyPackage ;
        dc:description "Standalone adenine console support" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/ui/standalone.ad"
}


add { <http://haystack.lcs.mit.edu/schemata/thing>
        rdf:type config:OntologyPackage ;
        dc:title "Base ontology for daml:Thing";
        rdf:type content:JavaClasspathContent ;
        content:path "/schemata/thing.ad"
}

add { <http://haystack.lcs.mit.edu/schemata/picture>
        rdf:type config:OntologyPackage ;
        dc:description "Haystack Picture Ontology" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/schemata/picture.ad"
}

add { <http://haystack.lcs.mit.edu/ui/picture>
        rdf:type config:OntologyPackage ;
        dc:description "Picture UI" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/ui/picture.ad"
}

add { <http://haystack.lcs.mit.edu/schemata/help>
        rdf:type config:OntologyPackage ;
        dc:description "Help Ontology" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/schemata/help.ad"
}

add { <http://haystack.lcs.mit.edu/ui/helpView>
        rdf:type config:OntologyPackage ;
        dc:description "Help View" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/ui/helpView.ad"
}

add { <http://haystack.lcs.mit.edu/data/helpData>
        rdf:type config:OntologyPackage ;
        dc:description "Example help file" ;
        rdf:type content:JavaClasspathContent ;
        content:path "/data/helpData.ad"
}

########################################################################
# Common Configurations

add { <http://haystack.lcs.mit.edu/bootstrap/console>
        rdf:type config:OntologyPackage ;
        dc:description "Console-only Package" ;
        rdf:type content:NullContent ;
        adenine:precompile "true" ;

        config:includes <http://haystack.lcs.mit.edu/bootstrap/base> ;
        config:includes <http://haystack.lcs.mit.edu/bootstrap/haystackBase> ;
        config:includes <http://haystack.lcs.mit.edu/bootstrap/utilities> ;
        config:includes <http://haystack.lcs.mit.edu/bootstrap/baseAgents> ;
}

library <http://haystack.lcs.mit.edu/bootstrap/console>

edu.mit.lcs.haystack.adenine.interpreter.UnboundIdentifierException: Unbound identifier: library
        identifier evaluation instruction at line 208
        Function call at line 208

(<http://haystack.lcs.mit.edu/bootstrap/utilities#beep>)

edu.mit.lcs.haystack.adenine.AdenineException: Method <http://haystack.lcs.mit.edu/bootstrap/utilities#beep> missing entry point.
        Function call at line 1
        Function call at line 1

Some Adenine Implementation

printset (query { ?x rdfs:subClassOf adenine:Method })


printset (query { ?x rdfs:subClassOf ?z})

<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#Identifier>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#Call>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#Index>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#FunctionCall>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#Break>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#Dereferencement>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#Query>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#CallReturn>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#Model>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#BNode>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#Var>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#Return>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#Literal>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#If>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#MethodDef>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#Import>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#With>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#ForIn>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#Assignment>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#LibraryDef>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#Continue>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#RDFNode>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#Function>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#While>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#String>
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> <http://haystack.lcs.mit.edu/schemata/adenine#Parameter>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#ImportJava>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#MethodDef2>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction> <http://haystack.lcs.mit.edu/schemata/adenine#Resource>


printset (query { ?x rdf:type rdfs:Class })

<http://haystack.lcs.mit.edu/schemata/adenine#ConditionSet>
<http://haystack.lcs.mit.edu/schemata/adenine#Method>
<http://haystack.lcs.mit.edu/schemata/adenine#ResourceConverter>
<http://haystack.lcs.mit.edu/schemata/adenine#InstructionHandler>
<http://haystack.lcs.mit.edu/schemata/adenine#ConditionHandler>
<http://haystack.lcs.mit.edu/schemata/adenine#Parameter>
<http://haystack.lcs.mit.edu/schemata/adenine#Instruction>



Afterword

This IFCX Wings document is adapted from the Adenine Tutorial that used to be located at http://haystack.csail.mit.edu/developers/adenine.html, but that page is no longer there. The copy used was obtained from The Internet Archive here http://web.archive.org/web/20060831131559/http://haystack.csail.mit.edu/developers/adenine.html.