This is the mail archive of the kawa@sources.redhat.com mailing list for the Kawa project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Kawa now has define-class and define-simple-class


I've checked in the new syntax forms define-class and define-simple-class.
These are similar to the syntax of Guile and Stk, and also the syntax
for the existing (object ...) form.  While not everything works as it
should and there are things I've haven't implemented, at this point
it should be usable.  I also checked in some documentation; for
convenience, I've included it below.

Defining new classes
====================

   Kawa provides various mechanisms for defining new classes.  The
`define-class' and `define-simple-class' forms will usually be the
preferred mechanisms.  They have basically the same syntax, but have a
couple of differences.  `define-class' allows multiple inheritance as
well as true nested (first-class) class objects.  However, the
implementation is more complex: code using it is slightly slower, and
the mapping to Java classes is a little less obvious.   (Each Schcme
class is implemented as a pair of an interface and an implementation
class.)  A class defined by `define-simple-class' is slightly more
efficient, and it is easier to access it from Java code.

   The features of `define-class' are mostly compatible with those of
the Guile and Stk dialects of Scheme.

 - Syntax: define-class name (supers ...) field-or-method-decl ...
 - Syntax: define-simple-class name (supers ...) field-or-method-decl
          ...
          FIELD-OR-METHOD = FIELD-DECL | METHOD-DECL
          FIELD-DECL = (FNAME [:: FTYPE] [OPTION-KEYWORD OPTION-VALUE]*)
          METHOD-DECL = ((METHOD-NAME FORMAL-ARGUMENTS) [[::] RTYPE] BODY)
     Defines a new class named NAME.  If `define-simple-class' is used,
     creates a normal Java class named NAME in the current package.
     (If NAME has the form `<xyx>' the Java implementation type is
     named `xyz'..)  If `define-class' the implementation is
     unspecified.  In most cases, the compiler creates a class pair,
     consisting of a Java interface and a Java implementation class.

     The class inherits from the classes and interfaces listed in
     SUPERS.  This is a list of names of classes that are in scope
     (perhaps imported using `require'), or names for existing classes
     or interfaces surrounded by `<>', such as `<gnu.lists.Sequence>'.
     If `define-simple-class' is used, at most one of these may be the
     name of a normal Java class or classes defined using
     `define-simple-class'; the rest must be interfaces or classes
     defined using `define-class'.  If `define-class' is used, _all_ of
     the classes listed in SUPERS should be interfaces or classes
     defined using `define-class'.

     Each FIELD-DECL declares a public instance "slot" (field) with the
     given FNAME.  If FTYPE is specified it is the type of the slot.
     The following OPTION-KEYWORDs are implemented:
    `type:' FTYPE
          Specifies thatFTYPE is the type of (the values of) the field.
          Equivalent to `:: FTYPE'.

    `allocation:' `class:'
          Specifies that there should be a single slot shared between
          all instances of the class (and its sub-classes).  Not yet
          implemented for `define-class', only for
          `define-simple-class'.  In Java terms this is a `static'
          field.

    `allocation:' `instance:'
          Specifies that each instance has a separate value "slot", and
          they are not shared. In Java terms, this is a non-`static'
          field.  This is the default.

    `init-form:' EXPR
          An expression used to initialize the slot.  The lexical
          environment of the EXPR is that of the `defien-class' or
          `define-simple-class'.  (This is not quite true in the current
          implementation, as the names of fields and methods of this
          class are visible.)

    `init-value:' VALUE
          A value expression used to initialize the slot.  For now this
          is synonymous with INIT-FORM:, but that may change (depending
          on what other implementation do), so to be safe only use
          `init-value:' with a literal.

    `init-keyword:' `NAME:'
          A keyword that that can be used to initialize instance in
          `make' calls.  For now, this is ignored, and NAME should be
          the same as the field's FNAME.  `static' field.

     Each METHOD-DECL declares a public non-static method, whose name
     is METHOD-NAME.  (If METHOD-NAME is not a valid Java method name,
     it is mapped to something reasonable.  For example `foo-bar?' is
     mapped to `isFooBar'.)  The types of the method arguments can be
     specified in the FORMAL-ARGUMENTS.  The return type can be
     specified by RTYPE, or is otherwise the type of the BODY.
     Currently, the FORMAL-ARGUMENTS cannot contain optional, rest, or
     keyword parameters.  (The plan is to allow optional parameters,
     implemented using multiple overloaded methods.)

     The scope of the BODY of a method includes the FIELD-DECLs of the
     object.  It does include the surrounding lexical scope.  It
     sort-of also includes the declared methods, but this is not
     working yet.

   A simple example:
     (define-simple-class <2d-vector> ()
       (x type: <double> init-value: 0.0 init-keyword: x:)
       (y type: <double> init-value: 0.0 init-keyword: y:)
       ((add (other :: <2d-vector>)) :: <2d-vector>
        ;; Kawa compiles this using primitive Java types!
        (make <2d-vector>
          x: (+ x (slot-ref other 'x))
          y: (+ y (slot-ref other 'y))))
       ((scale (factor :: <double>)) :: <2d-vector>
        ;; Unfortunately, multiply is not yet optimized as addition is.
        (make <2d-vector> x: (* factor x) y: (* factor y))))
     
     (define-simple-class <3d-vector> (<2d-vector>)
       (z type: <double> init-value: 0.0 init-keyword: z:)
       ((scale (factor :: <double>)) :: <2d-vector>
        ;; Note we cannot override the return type to <3d-vector>
        ;; because Java does not allow that.  Should fix that.
        (make <3d-vector>
          ;; Unfortunately, slot names of inherited classes are not visible.
          ;; Until this is fixed, use slot-ref.
          x: (* factor (slot-ref (this) 'x))
          y: (* factor (slot-ref (this) 'y))
          z: (* factor z))))

-- 
	--Per Bothner
per@bothner.com   http://www.bothner.com/per/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]