Sock: User Manual

Trevor Nash

Melvaig Software Engineering Limited

Table of Contents

1. Introduction
Sock
Objectives
What is it?
What Sock is not
2. Primitive Elements
Overview
Files
Source and Sink
3. User Specified Elements
Purpose
4. Reference
Sock Elements
Commands
5. Manual Production Kit
Framework
Sock Elements
Presentation

Chapter 1. Introduction

Sock

Sock is about patterns. Anything you do in producing text files which is in the least repetitive is a candidate for improvement using Sock. It is a general purpose tool not tied to any particular language or development method. It comes with a basic set of definitions for XSLT and Java: use these as a basis for developing your own flavour of these or any other language.

The fundamental principle is that instead of producing individual text files such as Java source, makefiles, build scripts, user documentation, you write an XML document which contains instructions telling Sock how to write these files for you.

Objectives

Sock has been designed to solve a number of software engineering problems.

  • OO did not fix all of the re-use problem. There are still many things, notably design patterns, that cannot be encapsulated in a class.

  • There is repetition, such as the need to repeat the signature of a method being redefined.

  • Logical vs. physical structure. Compilers and other tools require source code to be physically structured in ways that do not necessarily reflect the logical structure of a system. A typical example is a message file that contains messages from many different parts of the system. This manifests itself most obviously when using change control systems: there are a small number of files which everyone wants to book out, even though they are working on logically separate parts of the system.

  • Loss of design information. Sock provides structures orthogonal to those found in programming languages which help you retain information about why code is written and what implicit links exist between apparently independent bits of code. Programming languages let you give names to variables, which helps you communicate why the variable exists and what it might be used for. Sock lets you name bits of code which do not correspond to named things in the target language: for example, a group of parameters that appear on several related function signatures.

  • Transparency. All of the above aims can be achieved to some degree with existing macro languages. But the implementor has to hold the macro definitions in his head in order to understand the code. Sock lets you 'see through' to the underlying code. So the semantics are always grounded in the language of the target document, not the language of the source document.

  • Painless conditionality. Putting trace and diagnostic code into programs can be a difficult compromise. Lots of tracing gives easy diagnostics, but the underlying structure of the code rapidly becomes obscured and performance may suffer in languages without conditional compilation. The tracing method itself rapidly becomes cast in stone. In Sock the tracing method is encapsulated without run-time overhead.

Future aims:

  • Reversability. All of the above aims can be achieved to some degree with existing macro languages. But the implementor has to hold the macro definitions in his head in order to understand the code. Sock will let you 'see through' to the underlying code. So the semantics are always grounded in the language of the target document, not the language of the source document. And you get one-click access from written program to original specification.

  • Freedom from concrete syntax. A problem with using a multitude of languages, or using a language rarely, is that the precise syntax is easily forgotten or confused. You should be able to view conditionals and loops in the language of your choice, even if that is not the language being written.

  • Filtering. Including diagnostics can obsure the overall structure of code. The existing version of Sock helps by providing an encapsulation mechanism orthogonal to the programming language, but a future version will allow code of various types including diagnostic to be hidden altogether. Filtering of this kind is also known as slicing: slicing systems already exist, but they are based on the program text. Sock has the advantage that it sees the design as well, so can provide slices based on design information, not just program analysis.

What is it?

What Sock is not

  • A macro processor or an editor plug-in. At least, not the kind you are likely to have met before. Sock is based on XML, so it deals with the structure of documents, not text. This makes it possible to do things which are difficult or impossible to do with text-based systems. You can write instructions which sort, optimize, reliably test for the presence of particular constructs elsewhere in the document.

  • A Wizard, or even a framework for creating wizards. It is not magic which is hidden from you, it puts you in the driving seat. The code it writes is like you would have written yourself, not some kind of machine genrated gibberish.

  • A Literate Programming Tool. Though it can be used as one (and we recommend literate programming as a style), the focus is on providing ways of constructing software not just writing it.

Chapter 2. Primitive Elements

Overview

There are three elements which are fundamental to understanding Sock.

  • The first of these is file, which describes a file to be produced. It names the file to be created and provides a skeleton or template for its contents, either directly or by reference to an external document.

  • The second is sink, which identifies somewhere to send output. An obvious place for a sink is inside a file template, but that is not the only place.

  • The last is source, which contains a piece of output and the sink or sinks to which it is to be sent.

Files

This is a simple use of the file element to create a file with fixed content. To build our system we need to compile all the Java classes which we are going to write. A first attempt to produce a shell script which does just this is to write:

<sk:file id="cmp" name="compile">
javac *.java
</sk:file>
This causes Sock to write the given text to a file called compile. The file may be referred to elsewhere in the document by the id cmp.

What does this do for us? Not a lot, and you will not see this kind of thing very often. But even just this gives us an easy way to keep the text of a number of small files in one place, so we just have one file to edit and change control.

The next step is to consider how to collect parts of the target file from different places in the design. For that we need the other two basic elements, source and sink.

Source and Sink

We might want to list the classes to be compiled explicitly, rather than rely on finding them by means of a wild card. This could be done by putting the names in the script directly, but that leaves a problem: every time we write a new class we have to remember to update the shell script. This is exactly the kind of thing Sock is designed to solve, and here is how.

Here is a more typical use of the file element, using a sink to collect list items from elsewhere in the specification. We create a shell script with a placeholder for the list of classes to be compiled:

<sk:file id="cmp" name="compile.bat">
javac <sk:sink id="class-list"/>
</sk:file>
This again causes Sock to write the given text to a file called compile, but this time replacing the sink element with the text it finds in any source element with a matching sink and file id. So elsewhere in the design, where we identify the need for a particular class we write:
<sk:source file.id="cmp" sink.id="class-list">foo.java </sk:source>
and perhaps a few pages away
<sk:source file.id="cmp" sink.id="class-list">bar.java </sk:source>
See how the file.id and sink.id match up with the id on the file element and the sink which it contains. The result will be a shell script containing
javac foo.java bar.java 

There is some repetition and room for error in this attempt. We have to put .java every time, and also remember to put a space to separate each entry from the one that may come after it. Both of these can be fixed by allowing the sink element to have a body. This body is instantiated for every matching source, and may contain:

  • text which is to be duplicated for every source

  • body, which will be replaced by the content of the matching source

  • separator, which specifies some text to be inserted only on certain conditions

The example uses a sink element with a body to insert fixed text into each link item. We will start with what we want the source elements to look like: they should contain just the class name.

<sk:source file.id="cmp" sink.id="class-list">foo</sk:source>
<sk:source file.id="cmp" sink.id="class-list">bar</sk:source>

To get this to produce the same script as before, we modify the sink within the file like this:

<sk:file id="cmp" name="compile">
javac <sk:sink id="class-list">
  <sk:copy/>.java<sk:separator test="not last" value=" "/>
</sk:sink>
</sk:file>

The result looks the same:

javac foo.java bar.java
though in fact the trailing space after the last class is gone. The reference section gives options for the separator test attribute.

Chapter 3. User Specified Elements

Table of Contents

Purpose

Purpose

Chapter 4. Reference

Table of Contents

Sock Elements
Commands

Sock Elements

Commands

Table of Contents

m21 - the main user interface to the Software Development Kit system

Name

m21 — the main user interface to the Software Development Kit system

Synopsis

m21 [options] [spec]

Description

m21 is the main user interface to the Software Development Kit system. It performs three kinds of processing on an input specification:

  • Validation, which produces an HTML report describing any problems found with the specification. Once you are familiar with Sock you may choose to omit this step to reduce the processing time on large specifications.

  • Processing, the main purpose of the application: to produce one or more output files described by the specification. (In literate programming systems this is referred to as “tangle”).

  • HTML generation, which produces a nicely formatted version of the input. (In literate programming systems this is referred to as “weave”). This is easier to read than the raw XML input, and can also be used with the graphical interface to select portions of the specification for input.

These processes may be run either in batch mode or through a graphical user interface.

Batch mode is selected by instructing m21 to do something specific with a specification, i.e. to validate it, process it to produce out files, or produce an HTML document from it. In this case the [spec] argument is mandatory.

Otherwise the application runs with a graphical interface. All arguments are optional. In addition to providing an additional way of requesting the processing described above, the graphical interface can interact with most text editors in order to provide a way of selecting parts of a specification to edit.

Table 4.1. Arguments

Short FormLong FormDescription
-v--validate Carry out optional sanity checks on the contents of [spec].
-b--process Process [spec] to produce the specified output files.
-h--html Produces an HTML rendition of the specification, in a file named after the input with extension “html”.
-o dir--output dir place output files relative to [dir], which must already exist. Default: output files are placed relative to the directory containing [spec]
-?--help Prints a short description of the permitted arguments and exits. Other arguments are validated but otherwise ignored.
-z--trace Causes m21 to send tracing information to the console, and write copies of the intermediate XML and XSLT files to the directory containing the input specification. The tracing information is probably only useful for the Sock implementors, but the files may be helpful in debugging problems with user defined objects. The files are:
  • _analyse.xsl: the transform which implements the “replace” parts of user objects.

  • _replaced.xml: the result of applying _analyse.xsl to the input specification.

  • _generate.xsl: the transform which implements the “generate” and “write” parts of user objects.

  • _generated.xml: the result of the “generate” part of _generate.xsl (the result of the “write” part is of course the output files themselves).

  • _options_report.txt: some comments about processing the initialisation file, usually containing just the name of the file accessed. If the options you are setting seem not to be having any effect it may be worth checking this file to ensure that m21 is reading the file you expect it to.

Chapter 5. Manual Production Kit

Framework

This is a set of objects for writing a user manual with examples, specifically for Sock.

The first requirement is for two modes of processing: one to produce a version with editing tags for development purposes, and another to produce the final manual.

For Object k:development replacement:
<sk:replace>
   <sk:declare>
       <xsl:param name="k:development" select="true()"/>
   </sk:declare>
</sk:replace>
For Object k:development generate:
<sk:generate>
   <sk:declare>
       <xsl:param name="k:development" select="true()"/>
   </sk:declare>
</sk:generate>
For Object k:development presentation:
<sk:presentation>
   <sk:declare>
       <xsl:param name="k:development" select="true()"/>
   </sk:declare>
   <xsl:if test="$k:development">
      <sk:instantiate/>
   </xsl:if>
</sk:presentation>

For Object k:example-summary replacement:
<sk:replace>
   <xsl:variable name="this" select="."/>
   <sk:file id="{$this/@name}-readme" name="examples/{$this/@name}/ReadMe.txt">
   <sk:text-file>
<sk:sink id="description"/>
</sk:text-file>
</sk:file>
   <xsl:for-each select="k:description">
      <sk:source file.id="{$this/@name}-readme" sink.id="description">
         <xsl:value-of select="."/>
      </sk:source>
   </xsl:for-each>
   <xsl:for-each select="k:file">
      <sk:file id="{$this/@name}-{@id}" name="examples/{$this/@name}/{@name}">
         <sk:instantiate/>
      </sk:file>
      <sk:source file.id="{$this/@name}-{@id}" sink.id="sk-namespace">
         <sk:namespace prefix="sk"/>
      </sk:source>
   </xsl:for-each>
</sk:replace>
For Object k:example-summary presentation:
<sk:presentation>
   <sk:instantiate select="k:description/node()"/>
</sk:presentation>

For Object k:example replacement:
<sk:replace>
   <sk:source file.id="{@name}-{@file.id}" sink.id="{@sink.id}">
      <sk:instantiate/>
   </sk:source>
</sk:replace>
For Object k:example presentation:
<sk:presentation>
   <xsl:choose>
      <xsl:when test="$k:development">
         <sk:listing/>
      </xsl:when>
      <xsl:otherwise>
         <db:programlisting>
            <sk:instantiate/>
         </db:programlisting>
      </xsl:otherwise>
   </xsl:choose>
</sk:presentation>

Sock Elements

In examples Sock elements are written with the k prefix, and converted to the proper namespace when they are written to the example files and the user manual.

For Object e:* write:
<sk:write>
   <xsl:element name="{concat('sk:', local-name())}">
      <xsl:copy-of select="@*[namespace-uri()='']"/>
      <sk:instantiate/>
   </xsl:element>
</sk:write>
For Object e:* presentation:
<sk:presentation>
   <!-- Borrowed from weave, changed to substitute the right namespace
        prefix -->
   <xsl:text/><sk:<xsl:value-of select="local-name()"/>
   <xsl:apply-templates select="@*" mode="source"/>
   <xsl:choose>
      <xsl:when test="node()">
         <!-- non-empty element: do the content and a full end tag -->
         <xsl:text>></xsl:text>
         <xsl:apply-templates select="node()" mode="source"/>
         <xsl:text/></sk:<xsl:value-of select="local-name()"/>><xsl:text/>
      </xsl:when>
      <xsl:otherwise>
         <!-- empty element: do a short end tag -->
         <xsl:text>/></xsl:text>
      </xsl:otherwise>
   </xsl:choose>
</sk:presentation>

Presentation

Add an edit icon to each section heading.

For Object db:section presentation:
<sk:presentation>
   <section>
      <xsl:if test="$k:development">
         <xsl:variable name="file" select="substring-after (saxon:systemId(), '/')"/>
         <sk:xref file="{$file}" line="{saxon:lineNumber()}"/>
      </xsl:if>
      <sk:instantiate/>
   </section>
</sk:presentation>