Wednesday 25 May 2011

XMF and XModeler

Both XMF and XModeler are now available from my home page. Click on the links to the left to get instructions for download and for documentation. XMF is a language for developing Domain Specific Languages and for Language Oriented Programming. XModeler is an IDE for Model Driven Engineering and for developing XMF programs.

The download of XMF includes the source code. Since XMF is written in itself (on a small VM written in Java), this is an excellent place to start to see what you can do with the language. XMF supports both functional and object-oriented programming. Classes in XMF have optional grammars that can be used to create syntax-classes that extend the base language. XMF includes features for pattern matching, processing XML, writing prolog-style rules over object structures, threads, daemons, quasi-quotes for processing syntax. Virtually all aspects of the language are open for extension and reflection.

The download of XModeler includes the source code (the actual sources will follow later) so you can browse through the implementation using the various editors. XModeler is written in XMF.

Tuesday 10 May 2011

XPL: A Functional Language for Language Oriented Programming

XPL is a functional language that has been developed to experiment with Domain Specific Languages and Language Oriented Programming.  It is written in Java. The source code for XPL v 0.1 can be downloaded here. The language has first-class grammars that can be combined and has access to its own abstract syntax. Grammars use quasi-quotes to build new syntax structures that can be inserted into the XPL execution stream. This is like macros in Scheme (in that language features can be defined with a limited scope). However unlike Scheme XPL can define the syntax of each new language feature.

Here is a simple language feature inspired by an example from Martin Fowler. Suppose that we get a stream of character codes as input. The stream contains information about customers and we need to chop up the input to produce data records. If there are a large number of different types of input data and they change regularly then it makes sense to define a declarative language construct that defines each type. The following XPL code defines a language construct for recovering structure from an input stream:
export test1,test2

// We need syntax constructors for Record and Field:

import 'src/xpl/exp.xpl'

// We need list operations:
//   take([1,2,3],2) = [1,2]
//   drop([1,2,3],2) = [3]
//   foldr(f,g,b,[1,2,3]) = g(f(1),g(f(2),g(f(3),b)))

import 'src/xpl/lists.xpl'

// Define some functions to be used as args to foldr:

combine(left,right) = [| fun(l) ${left}(l,fun(r,l) r + ${right}(l)) |]
   id(x) = x
   empty = [| fun(l) {} |]

// Define a function that constructs *the syntax* of a field extractor:
//   extractor('name',5) = [| fun(l,k) k({name=asString(take(l,5))},drop(l,5)) |]

extractor(n,i) = 
  let record = Record([Field(n,[| asString(take(l,${i})) |])]) 
  in [| fun(l,k) k(${record},drop(l,${i})) |]

// Define the grammar to consists of a sequence of fields.
// Each field builds an extractor. All extractors are combined
// into a mapping from a sequence of character codes to a record:

grammar = {
  fields -> fs=field* { foldr(id,combine,empty,fs) };
  field -> n=name whitespace ':' i=int { extractor(n,i) };
  int -> whitespace n=numeric+ { Int(asInt(n)) };
  whitespace -> (32 | 10 | 9 | 13)*;  
  name -> whitespace l=alpha ls=alpha* { asString(l:ls) }; 
  alpha -> ['a','z'];
  numeric -> ['0','9']
}

// Here is a use of the language: a customer is a name (5 chars) followed
// by an address (15 chars), followed by an account number (3 chars):

customer = 
  intern grammar {
    customer:5
    address:15
    account:3
  }

// The customer map is used by applying it to a stream of char codes:

input = [102,114,101,100,32,49,48,32,77,97,105,110,32,82,111,97,100,32,32,32,53,48,49]
 
test1() = customer(input)

// Just to show everything is first-class:

test2() = map(customer,repeat(input,10))
To use XPL you download the ZIP file (link above). It is developed as an Eclipse project, but can also be run stand-alone. The interpreter is in the xpl package in the source folder. If you run the Interpreter as a Java application in Eclipse then the console becomes an XPL top-level loop that you can type XPL commands to. Here is a transcript of the example given above (user input after a '>' followed by XPL output):
[src/xpl/xpl.xpl 2353 ms,136]
> import 'src/xpl/split.xpl';
[src/xpl/split.xpl 179 ms,262]
[src/xpl/exp.xpl 26 ms,404]
[src/xpl/lists.xpl 108 ms,164]
> test1();
{customer=fred ;address=10 Main Road   ;account=501}
> test2();
[{customer=fred ;address=10 Main Road   ;account=501},
 {customer=fred ;address=10 Main Road   ;account=501},
 {customer=fred ;address=10 Main Road   ;account=501},
 {customer=fred ;address=10 Main Road   ;account=501},
 {customer=fred ;address=10 Main Road   ;account=501},
 {customer=fred ;address=10 Main Road   ;account=501},
 {customer=fred ;address=10 Main Road   ;account=501},
 {customer=fred ;address=10 Main Road   ;account=501},
 {customer=fred ;address=10 Main Road   ;account=501},
 {customer=fred ;address=10 Main Road   ;account=501}]
> 
There is currently no user documentation (contact me if you are interested in this). But there are some technical articles: language modules in XPL, modular interpreters in XPL, and parsing infix operators using XPL. In addition the source code contains a number of examples in the xpl folder.