[http://pysch.sourceforge.net/] [index.html] [user.html] [developer.html] [ast.html]

Pysch: developer's guide

Embedding Pysch

In order to execute a Scheme program:

The file pysch/vm/eval.py contains a sample code:

if __name__ == "__main__":
  s = sys.stdin.read()    # Read a program text in the XML format
  c = xmltosexp.parse(s)  # Load the program
  r = evaluate(c)         # Execute the program
  print str(r)            # Print result

Execution model

Pysch uses the heap-based model as desribed in the “Three Implementation Models for Scheme”[pdf]. Access to variables is optimized, lookup uses a precalculated position in the environment instead of the variable's name. Out-of-the-3imp.pdf improvement is usage of an associative array for the globals.

Evaluation of a program consists of two steps:

The file pysch/vm/eval.py contains a sample code:

def evaluate(sexp, globals = None):
  """ Compile and interpret S-expression """
  env = environment.rib(null.null(), globals)
  c = compiler.compile(sexp, env, pair.pair(symbol.symbol('halt'), null.null()))
  r = interpreter.vm(null.null(), c, env, null.null(), null.null())
  return r

Consult the referred pdf for the exact meaning of parameters to the functions compile and vm. The variable globals is a map of variables' names and theirs values.

Realization of the core Scheme functions like map and for-each also uses the function vm. See the file pysch/func/func.py for details.


Each Scheme type is represented by a some Python class. These Python classes are located in the folder pysch/types. The class pysch.types.base is the base class for all types.

Use the function “obj.value()” to get a value wrapped by the Python object obj.

You can't get the type of a value, but you can ask a value if it is of some type. Use the function “obj.typeq('type?')” to do it. Direct access to a type is forbidden to ensure code safety. I plan to make subclassing, and some subclasses will have different low-level types but the same type for Scheme.

Values can be serialized to strings:


The package pysch.util.xmltosexp provides the function parse. This function parses the XML representation of a s-expression.

The package pysch.util.strutil contains functions to escape special characters (escapeXmlChar, escapeXmlString and escapeWriteString) and class strflags to support serialization of values.

The Pysch code uses the Logging package. Initialization of the logging system and configuration of the loggers are performed in the module pysch.util.log.

The Pysch code often converts the Python lists into the Scheme lists. This conversion is simplified by the function list in the package pysch.util.list. Sample usage:

$ cat x.py
from pysch.util.list import list
from pysch.types.symbol import symbol
l = [symbol('a1'), symbol('a2'), symbol('a3')]
print list(symbol('b1'), symbol('b2'), symbol('b3'))
print list(*l)
print list(symbol('b1'), symbol('b2'), symbol('b3'), dot=1)
print list(dot=1, *l)
$ python x.py
(b1 b2 b3)
(a1 a2 a3)
(b1 b2 . b3)
(a1 a2 . a3)

The core functions

An implementation of the library of the core Scheme functions is located in the folder pysch/func/. The main file is func.py. It contains a mapping from Scheme function names to Python implementations of these functions. The implementations are located in the several files, the files group functions from the same sections of the Scheme specification.

A Python function accepts two input parameters, args and env, and must return some Scheme type (including pysch.types.unspecified). The parameter args is a Scheme list of the arguments to a Scheme function. So args.car() gives the first argument, args.cdr().car() gives the second argument, etc. The parameter env is the function environment. It is used only by functions like map and for-each.

Author: Oleg Paraschenko
Hosted by:
SourceForge.net Logo