Table of Contents
Occasionally functionality may be desired that is not easily accomplished at the Scheme level. A new first-class type may be desired, or efficient access to a Java library. SISC provides a simple API for such modifications.
        A Scheme value is represented in SISC as a subclass of the
        abstract Java class sisc.data.Value. 
      
          In order to be able to display the value in the Scheme
          system, all Values must implement the
          display method:
        
public void display(sisc.io.ValueWriter writer);Uses the various output methods of sisc.io.ValueWriter to construct an external representation of the given Value suitable for output from the
displayScheme function.
          If the programmer desires the Value to have a different
          representation when written with write,
          the write method must be overridden.  If it
          is not, the output of display is used for
          write as well.
        
public void write(sisc.io.ValueWriter writer);Uses the various output methods of sisc.io.ValueWriter to construct an external representation of the given Value suitable for output from the
writeScheme function. If not implemented, the output constructed the by thedisplaymethod is used as output fromwrite.
          Finally, if the external representation of a new Value is
          likely to be long, the programmer should implement the
          synopsis method, which generates a
          summary representation of the value.
        
public String synopsis(int limit);Returns approximately
limitcharacters from the printable representation of this value as if returned bywrite. This method is used for displaying the value in error messages where the entire representation may be superfluous.
          The sisc.io.ValueWriter type that is passed as an
          argument to both display and
          write contains a number of methods to
          generate the representation.  First there are several methods
          for appending Java Strings, characters, and SISC Values.  In
          each, the called ValueWriter is returned, to
          allow for easy chaining of calls.
        
public sisc.io.ValueWriter append(char c);Appends a single character to the external representation.
public sisc.io.ValueWriter append(String s);Appends the contents of a Java String to the external representation.
public sisc.io.ValueWriter append(sisc.data.Value v);Appends the contents of a Scheme value to the external representation. The value is converted to an external representation using the print style with which the ValueWriter was constructed (for example,
displayorwrite).
          In addition to the above append methods, the
          programmer may wish to force display or
          write rather than use the same method as
          the ValueWriter.  To do this, one can call the
          display or write methods on
          the ValueWriter.
        
If the one wants a Value to be comparable for any more than pointer equality, or for the concept of pointer equality to be less strict than actual pointer equality, one or more of the equality methods must be overridden.
          If the type that is being added will be serialized in a SISC
          heap, and it contains one or more member variables, the Value
          must include a default constructor (a constructor with no
          arguments), and implement the deserialize,
          serialize, and
          visit methods described in the section called “Serialization”.
        
        One can add native bindings to the Scheme environment by 
        implementing a subclass of the abstract class
        sisc.nativefun.NativeLibrary.  Such a
        subclass needs to implement four methods:
        
public String getLibraryName();
Returns the name of this library. The name should also be acceptable for use in filenames.
public float getLibraryVersion();
Returns the version of this library.
public sisc.data.Symbol[] getLibraryBindingNames();
Returns an array of the names of the bindings exported by this library. Each name is a Scheme symbol.
public Value getBindingValue(sisc.data.Symbol name);Returns the value of a given binding exported by this library.
	  It is possible to implement Scheme functions whose behavior
	  is implemented natively in Java code.  Many of SISC's
	  procedures are implemented this way.  Native procedures extend
	  the sisc.nativefun.NativeProcedure
	  abstract class.  Working NativeProcedure subclasses must
	  implement the doApply method, as
          described below.
	
public Value doApply(sisc.interpreter.Interpreter interp);Perform the necessary computations of the NativeProcedure, returning a Value as the result of the procedure call. The arguments to the procedure can be found in the value rib array field,
vlr, of the Interpreter passed as an argument. The number of arguments to the procedure can be found from the length of the array (vlr.length).
 
	  If the native procedure wishes to raise an error, it may do
          so by throwing any Java runtime exception (subclass of
	  java.lang.Runtime).
	  For a more descriptive error, one may raise a SISC error 
	  using any of a number of error
	  forms in sisc.util.Util.  Consult the
	  source of Util or inquire on the sisc-devel mailinglist for
          assistance.
       
Often it is unnecessary to have access to the full Interpreter context to implement a native procedure. If the arguments to the procedure are sufficient and the procedure is purely functional (causes no side effects), it is recommended that the programmer create a fixable native procedure. These native procedures may be inlined into generated code when enabled, allowing much faster execution. In addition, the fixable native procedure interface is simpler to use.
The
         FixableProcedure abstract class consists
         of five methods which may or may not be subclassed.  These
         five methods correspond to the case of calling the
         procedure with no, one, two, three, and more than three
         arguments respectively.  Not overriding one of these methods
         will cause a call to the fixable procedure to throw the
         invalid number of arguments error to the caller.
       
Perform the necessary computations of the FixableNativeProcedure, returning a Value as the result of the procedure call. No argument variant.
Perform the necessary computations of the FixableNativeProcedure, returning a Value as the result of the procedure call. One argument variant.
public Value apply(Value v1,
Value v2);Perform the necessary computations of the FixableNativeProcedure, returning a Value as the result of the procedure call. Two argument variant.
public Value apply(Value v1,
Value v2,
Value v3);Perform the necessary computations of the FixableNativeProcedure, returning a Value as the result of the procedure call. Three argument variant.
public Value apply(Value[] v);Perform the necessary computations of the FixableNativeProcedure, returning a Value as the result of the procedure call. More than three argument variant.
        In the most common case, a Library is created to define several
        bindings, including procedures whose implementations are in Java
        code.  For this common case, a skeleton subclass of
	NativeLibrary,
	sisc.nativefun.IndexedLibraryAdapter
	is provided.  The IndexedLibraryAdapter class provides
	implementations for all four required NativeLibrary methods, and
	introduces a new abstract method which must be implemented, called
	construct.  In addition, the method
	define is provided.
       
        In an indexed native library, each binding is associated with
        a Java int unique to that binding within
	the library.  The IndexedLibraryAdapter subclass should in its
	constructor call define for each
	binding provided by the library, according to the
	contract of the method:
	
public void define(String name,
int id);Register the native binding with the given name, and assign it the given library-unique id.
        In implementing the
	getBindingValue method of the 
	NativeLibrary class, an
	IndexedLibraryAdapter will call the
	abstract method construct 
	required by the its subclasses:
	
        Most frequently, the bindings created in an indexed library
	are native procedures.  In such a case, a second class is
        created which subclasses
	sisc.nativefun.IndexedProcedure.
	IndexedProcedure is subclass of
	NativeProcedure.
	An IndexedProcedure subclass' constructor must call the
	superconstructor with an int, the unique id
	for that binding.  That int is stored in
	the id field of
	IndexedProcedure.  A subclass can 
	then use the id instance variable to
	dispatch to many native procedures in the body of the
	doApply method required by native 
	procedures.
      
        So, typically, an IndexedNativeLibrary subclass is created
	whose construct method creates 
	instances of IndexedProcedure subclasses.  The
	IndexedNativeLibrary subclass its itself nested in the
	IndexedProcedure class which it is constructing.  See the
	various indexed libraries in
	sisc.modules
	for concrete examples.
      
SISC provides an API for serializing the state of a running Interpreter. The SISC heap is a dump of the state of an Interpreter with the necessary code to implement R5RS Scheme, for example. In order to facilitate this serialization, SISC Expressions and Values can implement helper methods to define the serialization of the object. If the Expression or Value contains no internal state that need be serialized, the serialization methods may be ignored. If not, the Expression or Value must contain a default (no argument) constructor, and implement the following three methods:
public void serialize(sisc.ser.Serializer serializer)
throws java.io.IOException;Serializes the contents of the Expression to the given Serialization context.
public void deserialize(sisc.ser.Deserializer deserializer)
throws java.io.IOException;Sets the state of the Expression to the serialized data read from
deserializer.
public boolean visit(sisc.util.ExpressionVisitor visitor);When called, the Expression should call
visitor.visit(n)on any nested Expressions.
        The Serializer and
        Deserializer objects implement Java's
        java.io.DataOutput and
        java.io.DataInput interfaces,
        respectively.  This means that you can use any of the
        write/read functions in those interfaces to serialize the
        state of your Expression or Value.  In addition, a
        number of methods are provided that are helpful for this
        domain.
      
        The ExpressionVisitor passed to visit contains
        only one method, visit, which bears the
        same contract as the visit above.  When
        called, an Expression would then call the
        ExpressionVisitor's visit method once for
        each nested Expression.  This method is used during
        serialization and during printing to detect cycles in data
        and code structures.
      
public BigInteger readBigInteger()
throws java.io.IOException;Reads a BigInteger from the stream.
public BigDecimal readBigDecimal()
throws java.io.IOException;Reads a BigDecimal from the stream.
public Class readClass()
throws java.io.IOException;Reads a Java Class object from the stream.
public Expression readExpression()
throws java.io.IOException;Reads a SISC Expression from the stream.
public Expression readInitializedExpression()
throws java.io.IOException;Reads a SISC Expression from the stream, fully initialized. This method should only be used if fields internal to the Expression returned must be available during deserialization.
public sisc.data.Expression[] readExpressionArray()
throws java.io.IOException;Reads an array of
Expressions from the stream.
public sisc.data.Value[] readValueArray()
throws java.io.IOException;Reads an array of
Values from the stream.
public SymbolicEnvironment readSymbolicEnvironment()
throws java.io.IOException;Reads a SISC Symbolic Environment from the stream.
public void writeBigInteger(BigInteger bigint)
throws java.io.IOException;Writes a BigInteger to the stream.
public void writeBigDecimal(BigDecimal bigdecim)
throws java.io.IOException;Writes a BigDecimal to the stream.
public void writeClass(Class clazz)
throws java.io.IOException;Writes a Java Class object to the stream.
public void writeExpression(Expression expr)
throws java.io.IOException;Writes a SISC Expression to the stream.
public void writeInitializedExpression(Expression expr)
throws java.io.IOException;Writes a SISC Expression to the stream. This method should only be used if fields internal to the Expression returned must be available during deserialization.
public void writeExpressionArray(sisc.data.Expression[] ary)
throws java.io.IOException;Writes an array of
Expressions to the stream.
public void writeValueArray(sisc.data.Value[] ary)
throws java.io.IOException;Writes an array of
Values to the stream.
public void writeSymbolicEnvironment(SymbolicEnvironment e)
throws java.io.IOException;Writes a SISC Symbolic Environment to the stream.