You are not logged in Log in Join
You are here: Home » Members » Phillip J. Eby's Zope Center » My Wikis » ZPatterns Wiki » SkinScriptSyntax

Log in
Name

Password

 
 

History for SkinScriptSyntax

??changed:
-
The !SkinScript Language Reference


 Preface

  This document describes the syntax for !SkinScript as defined in
  !ZPatterns 0.4.3, which is not yet publically available.  If you are
  using an earlier version of !ZPatterns, the following features are
  not available:

   * The 'QUERY' keyword and the 'OTHERWISE LET' clause on 'WITH/COMPUTE' declarations

   * The 'INITIALIZE OBJECT WITH' declaration

   * The 'DEPENDENT ON' clause of 'WITH/COMPUTE' declarations

  It is also recommended that you read about HowTriggersWork before
  trying to define complex rules with !SkinScript.



 Basic Concepts and Syntax

  If you're familiar with ZPatterns, you know that DataSkins get their
  attributes and behavior from AttributeProviders and RuleAgents,
  respectively.  Providers and Agents (known as DataPlugIns) can be
  written directly in Python, but it is much easier to write them in
  !SkinScript.  !SkinScript lets you define an individual attribute
  provider or rule agent in a single declarative statement, using
  standard Zope tools such as SQL Methods, DTML Methods, Python
  Methods, and so on to do the actual data retrieval or storage.  In
  effect, !SkinScript is a "glue language" which lets you define the
  linkages between a !DataSkin and the methods you want to implement
  its "skeleton" of data storage and triggered behavior.

  In most languages, the order that statements appear in makes a
  difference to the results you get, and !SkinScript is no exception.
  Although each !SkinScript statement defines a seperate and
  independent data plug-in, the ordering makes a difference in how
  they will be used by DataSkins.  When a !DataSkin needs to perform
  an operation (such as retrieving an attribute), it asks its
  !DataManager for a list of suitable DataPlugIns.  This list is
  ordered according to the original order of plug-ins as listed on the
  Data Plug-ins tab of the [Racks] or [Customizers] involved.  And the
  declarations of a !SkinScript Method are treated as though they were
  individual plug-ins appearing in place of the !SkinScript Method in
  that list.

  In other words, !SkinScript is literally a language for defining
  data plug-ins.  A !SkinScript *script* consists of a series of
  *declarations*, seperated by whitespace.  Each declaration is
  compiled into a single data plug-in.  !SkinScript is a
  keyword-driven language, is case-sensitive, and is not whitespace
  sensitive, even for Python expressions contained within
  declarations.  All whitespace which occurs outside of quoted strings
  is treated as though it were a single space.  (Incidentally, this
  means that the usual Python rules about where you can put linebreaks
  in expressions do not apply.  You can write the expression '1+2'
  split across three lines, if you so desire.)  Comments are marked as
  in Python, using a '#' symbol to mean that the rest of the current
  line is a comment.  Comments are treated as simple whitespace.



 Declarations

  Declarations are the basic building block of !SkinScript.
  Declarations are compiled into AttributeProviders or RuleAgents, one
  per declaration.  Some declarations provide attribute values:

   - 'INITIALIZE OBJECT WITH' *assignmentlist*

   - 'WITH ![QUERY]' *expression* 'COMPUTE' *nameorassignlist* ![OTHERWISE LET assignmentlist] ![DEPENDENT ON dependencies]

   - 'WITH SELF COMPUTE' *assignmentlist*

  Some handle attribute storage:

   - ![WHEN eventspec] 'STORE' *attributelist* 'USING' *expression* ![SAVING mementolist]

   - 'STORE' *attributelist* 'IN SELF'


  And others can call an expression upon transaction commit:

   - 'WHEN' *eventspec* 'CALL' *expression* ![SAVING mementolist]


  Each declaration has its own parameters, but there are certain
  conventions which are followed across most kinds of declarations.


 Declaration Parameters

  *expression* -- A DTML-style Python expression.  As with DTML, the
  "_" object is available for access to Python built-ins and library
  functions.  Please see the section below on "Variables and Functions
  Available in Expressions" for details on how names other than "_"
  are looked up in !SkinScript expressions.

  *assignmentlist* -- A comma-seperated list of assignments in the
  form *attributename* = *expression*, similar to passing keyword
  arguments to a function or method.

  *nameorassignlist* -- Similar to *assignmentlist*, but with a
  special shorthand for the case where *attributename* and
  *expression* are the same (e.g. 'foo=foo').  To make such an
  assignment, you can replace *attributename* '=' *expression* with
  just *attributename*.  So 'foo=bar,baz=baz,bada=bing' can be
  simplified to 'foo=bar,baz,bada=bing' if a clause's syntax allows a
  *nameorassignmentlist*.

  *mementolist* -- A *mementolist* is syntactically identical to a
  *nameorassignlist*, but has a different context and purpose.  A
  *mementolist* is used to save old values of expressions for later
  comparison purposes when a (sub)transaction commits, and appears
  only in 'SAVING' clauses.  Expression variables are looked up in the
  context of the !DataSkin whose snapshot is being taken.  So in the
  clause 'SAVING bar,foo=baz' the DataSkin's 'bar' attribute will be
  saved as OLD!['bar'], and its 'baz' attribute will be saved as
  OLD!['foo'].

   A *mementolist* is computed only once per (sub)transaction for a
   given !DataSkin.  The first time the !DataSkin is changed in a
   (sub)transaction, the 'SAVING' clause is executed for all
   declarations that have one, even if the declaration never ends up
   firing.

  *eventspec* -- A clause of the form 'OBJECT ADDED, CHANGED,
  DELETED', where the 'ADDED', 'CHANGED' and 'DELETED' keywords may be
  used in any combination.  For example, 'OBJECT ADDED,DELETED' and
  'OBJECT CHANGED' are both valid *eventspec* clauses.  Please see
  HowTriggersWork for details on how !ZPatterns events are interpreted
  by !SkinScript.
  
  *attributelist* -- A comma-seperated list of attribute names, to
  which the declaration will be applied.  An asterisk ("*") may be
  used as a wildcard attribute name, meaning that the declaration will
  be applicable for any attribute name.  Remember, however, that
  declarations associated with specific names will take precedence
  over wildcard declarations, even if the wildcard declaration comes
  before the specific declaration and would match the name being
  looked up.

  *dependencies* -- A comma-seperated list of attribute names which,
  when changed, will cause the dependent attributes to be recalculated
  on their next access.  Wildcards cannot be used, only actual
  attribute names.



 Variables and Functions Available in Expressions

  Names used in an expression are usually looked up from the
  attributes of individual !SkinScript statement and its acquisition
  parents (e.g. the Rack or Customizer which it's contained in, and so
  on up the line).  One exception to this rule is in the 'COMPUTE'
  clause of a WITH/COMPUTE declaration, where names are first looked
  up in the 'RESULT' object returned by the 'WITH' clause.  The other
  exception is in 'SAVING' clauses, where names are looked up in the
  context of the !DataSkin whose snapshot is being taken.

  The following variable names and functions are provided by
  !SkinScript for use in expressions.

  * Generally available:

   'self' -- The !DataSkin instance which the declaration is being
   applied to at the time the expression is being called.

   'NOT_FOUND' -- A special value which causes an attribute to be
   non-existent, if this is the value provided.  In a WITH/COMPUTE
   declaration, if the 'WITH' expression returns 'NOT_FOUND', the
   'COMPUTE' clause is ignored, and the 'OTHERWISE LET' clause is
   activated if one exists.

  * Available for WITH/COMPUTE declarations:

   'RESULT' -- The result of the 'WITH' expression in a WITH/COMPUTE
   declaration.  Available only from expressions in the 'COMPUTE'
   clause.  This variable is placed atop the DTML namespace stack
   during execution of the 'COMPUTE' clause, so just referring to a
   name in a 'COMPUTE' expression will look up that name in the
   'RESULT' object first.  Only if it is not found there, will the
   search continue to the declaration and its acquisition context.

   'ATTRIBUTE_NAME' -- A string containing the name of the attribute
   which the !DataSkin is currently trying to retrieve.  Available in
   both the 'WITH' and 'COMPUTE' clauses.

  * Available for WHEN/STORE and WHEN/CALL declarations:

   'TRIGGER_EVENT' -- A string, either "ADD", "CHANGE", or "DELETE",
   denoting the type of event which caused the expression to be
   executed.

   'OLD!["name"]' -- 'OLD' is a mapping object containing the values
   saved by the "SAVING mementolist" clause of a WHEN/STORE or
   WHEN/CALL declaration.
[499 more lines...]