Example of an Oberon-2 compilation for Java

Canterbury Oberon-2 for Java can be easily called from a simple command prompt. For example, the compiler package has a click animation sample program as follows:

Slides.obn
MODULE Slides;

(* A simple Web page click animation entirely done       *)
(* in Canterbury Oberon-2 for Java.                      *)
(* Last update: Sep 14, 1998                             *)
(*                                                       *)
(* (c) 1998 by Mill Hill & Canterbury Corporation, Ltd.  *)

(*$XF+ Extended function designator usage  *)

IMPORT
  SYSTEM,
  java_applet_Applet,
  java_lang_Runnable,
  java_lang_Thread,
  java_awt_Image,
  java_awt_Graphics,
  java_awt_Event,
  java_lang_String,
  java_lang_Exception;

TYPE

  (* ClickAnimation extends Java class java.applet.Applet
     and implements Java interface java.lang.Runnable
  *)
  ClickAnimation* = RECORD
    ( java_applet_Applet.Applet, java_lang_Runnable.Runnable )
    animationThread : java_lang_Thread.POINTER_TO_Thread;
    cur : INTEGER;
    frame : ARRAY 4 OF java_awt_Image.POINTER_TO_Image;
    mouseClick : BOOLEAN;
  END;



(* Oberon-2 always regards constructors as type-bound
   procedures, but Java needs to know that it is a
   constructor, hence the need for using the
   JAVA CONSTRUCTOR directive.
*)

(*$JAVA CONSTRUCTOR *)
PROCEDURE( VAR Self : ClickAnimation) construct*();
BEGIN
  Self._init_^(); (* call superclass constructor *)
END construct;



(* The type-bound procedure "init" overrides the
   one inherited from Java class java.applet.Applet.
   This procedure always gets called first in
   a Java applet and is responsible for intializing
   all the fields
*)

PROCEDURE( VAR Self : ClickAnimation) init*();
  VAR
    i          : INTEGER;
    gifName    : ARRAY 9 OF CHAR;

  PROCEDURE JavaString
  ( s : ARRAY OF CHAR ) : java_lang_String.POINTER_TO_String;
    VAR Result : java_lang_String.POINTER_TO_String;
    VAR i : LONGINT;
  BEGIN
    (* convert an ARRAY OF CHAR to a java.lang.String object *)
    NEW( Result, SYSTEM.ADR(s) );
    i := Result.indexOf( 0 );
    IF i >= 0 THEN
      Result := Result.substring( 0, i );
    END;
    RETURN Result;
  END JavaString;

BEGIN
  (* set display size for applet *)
  Self.resize(300,300);

  (* get the GIF-formatted images *)
  FOR i := 0 TO 3 DO
    CASE i OF
    | 0 :        gifName := 'col1.gif';
    | 1 :        gifName := 'col2.gif';
    | 2 :        gifName := 'col3.gif';
    ELSE         gifName := 'col4.gif';
    END;
    Self.frame[i] := Self.getImage
    ( Self.getDocumentBase(), JavaString(gifName) );
  END;

  (* no mouse click yet *)
  Self.mouseClick := FALSE;
END init;



(* The type-bound procedure "start" overrides java.applet.Applet.start.
   It is called by the browser or applet viewer to inform this applet
   that it should start its execution.
   It is called after the init method and
   each time the applet is revisited in a Web page.
*)

PROCEDURE( VAR Self : ClickAnimation) start*();
BEGIN
  (* Create a new thread for class ClickAnimation.
     Canterbury uses an extended standard procedure
     NEW, with an optional second parameter for
     a constrcutor call
  *)
  NEW( Self.animationThread, SYSTEM.ADR(Self) );

  (* The start() method spawns the animation thread in order
     for the animation to run the first time
  *)
  Self.animationThread.start();

  (* Once the animation thread is started, it calls
     the run() method.
  *)
END start;



(* The type-bound procedure "stop" overrides java.applet.Applet.stop.
   It is called by the browser or applet viewer to inform this applet
   that it should stop its execution.
   It is called when the Web page that contains this applet has been
   replaced by another page, and also just before the applet is to be
   destroyed.
*)

PROCEDURE( VAR Self : ClickAnimation) stop*();
BEGIN
  (* stop the animation thread *)
  Self.animationThread.stop();
END stop;



(* The type-bound procedure "run" implements the one from the
   Java interface java.lang.Runnable.
   Starting the thread causes the objects "run" method to be
   called in that separately executing thread.
*)

PROCEDURE( VAR Self : ClickAnimation) run*();
BEGIN
  (* If there was no mouse click repaint the first frame,
     else repaint the next one.
  *)
  IF (~Self.mouseClick) THEN
    Self.cur := 0;
    Self.repaint();
  ELSE
    Self.mouseClick := FALSE;
    Self.cur := Self.cur + 1;
    IF (Self.cur > 3) THEN
      Self.cur := 0;
    END;
    Self.repaint();
  END;
END run;




(* The type-bound procedure "paint" overrides an inherited one.
   It is responsible for painting the applets display area.
*)

PROCEDURE( VAR Self : ClickAnimation) paint*
( g : java_awt_Graphics.POINTER_TO_Graphics );
BEGIN
  g.drawImage( Self.frame[Self.cur], 0, 0, SYSTEM.ADR(Self) );
END paint;



(* Method "mouseDown" overrides an inherited one.
   Always called in case of a mouse button being pressed
   while its cursor is on the applet.
*)

PROCEDURE( VAR Self : ClickAnimation) mouseDown*
(
  e : java_awt_Event.POINTER_TO_Event;
  x : LONGINT;
  y : LONGINT
)   : BOOLEAN;
BEGIN
  Self.mouseClick := TRUE;
  NEW( Self.animationThread, SYSTEM.ADR(Self) );
  Self.animationThread.start();
  RETURN TRUE;
END mouseDown;

END Slides.

                      

In order to compile and execute the Slides.obn sample on a Windows system, just open a DOS-prompt and enter the following commands (shown here in bold font):

C:\com.mhccorp\mhc\obn\samples\slides>java mhc.obn Slides -m -r
Oberon-2 2.5.xx (c) 1998-2006 J.Neuhoff (www.mhccorp.com)
Compiling: C:\com.mhccorp\mhc\runtime\obn\SYSTEM.obn
Importing Java class: java.applet.Applet
Importing Java class: java.lang.Runnable
Importing Java class: java.lang.Thread
Importing Java class: java.awt.Image
Importing Java class: java.awt.Graphics
Importing Java class: java.awt.Event
Importing Java class: java.lang.String
Importing Java class: java.lang.Exception
Compiling: Slides.obn
Compilation done: Slides.obn
C:\com.mhccorp\mhc\obn\samples\slides>javac *.java -nowarn

C:\com.mhccorp\mhc\obn\samples\slides>appletviewer Slides.html
C:\com.mhccorp\mhc\obn\samples\slides>
                      

As can be seen, the command

java mhc.obn Slides -m -r

causes the file Slides.obn to be compiled into various *.java files:

Slides.java
Slides_ClickAnimation_init_Frame.java
Slides_ClickAnimation.java
SYSTEM.java
SYSTEM_*.java

The -m switch tells the compiler also to recompile other imported Oberon-2 files if they are updated. This is like a Make-utility for Oberon-2 files integrated into the Oberon-2 compiler. The -r switch causes the compiler to write the compiled runtime classes into the current working directory.

The command

javac *.java -nowarn

gets the *.java files translated into the final byte code:

Slides.class
Slides_ClickAnimation_init_Frame.class
Slides_ClickAnimation.class
SYSTEM.class
SYSTEM_*.class

Module Slides.obn has an Oberon-2 class type called ClickAnimation extending the imported class java.applet.Applet. It also declares some type-bound procedures resulting in an override of some inherited methods. In order to run ClickAnimation, an applet-tag has to be declared in an HTML-document. In this case, file Slides.html has an applet-tag as follows:

Slides.html
<html>
<head>
<title>A simple click animation applet</title>
</head>
<body>
<p />
<applet code="Slides_ClickAnimation.class"
    codebase="."
    name="A simple click animation applet"
    width="170" height="170">
</applet>
</body>
</html>

Calling this file using the JDK appletviewer utility:

appletviewer Slides.html

will launch the Slides_ClickAnimation.class.