GNU Java Training Wheels 1.1: J.T.W. Proof of concept #1 A superfor macro

Next: J.T.W. Proof of concept #2 file inclusion, Previous: About GNU Java Training Wheels, Up: Top [Contents][Index]

## 2 J.T.W. Proof of concept #1 A superfor macro

A proof of concept for the J.T.W. preprocessor is the `superfor` macro, which is an enhanced BASIC-style `for` loop. Here is how to invoke the `superfor` macro in your `*.jtw` file:

    beginMain
        superfor (var int i = 0 to 10)
        begin
            System.out.println("i=" + i);
        end
    endMain

The above code results in the following printout:

    i=0
    i=1
    i=2
    i=3
    i=4
    i=5
    i=6
    i=7
    i=8
    i=9
    i=10

The `step` size argument is optional, here is an example with an explicit `step` size announced:

    beginMain
        superfor (var int i = 0 to 10 step 2)
        begin
            System.out.println("i=" + i);
        end
    endMain

The above code results in the following printout:

    i=0
    i=2
    i=4
    i=6
    i=8
    i=10

If the `downto` keyword is given instead of the `to` keyword then the loop will count downwards from the first given number to the second, even if a postive `step` size is given. Here is an example with a negative `step` size:

    beginMain
        superfor (var int i = 10 downto 0 step 2)
        begin
            System.out.println("i=" + i);
        end
    endMain

The above code results in the following printout:

    i=10
    i=8
    i=6
    i=4
    i=2
    i=0

Note that the specification of the `superfor` macro doesn’t need constants for the values of `start`, `stop` and `step-size`. They can be any variable or more generally any Java expression, and those expressions will be evaluated only once, should your code have side effects, i.e. changes the value of a variable in your code. See the following example. The expression `++y` has the side effect of incrementing the value of `y` before returning the value of `y`:

    beginMain
        var int x = 20;
        var int y = 15;
        superfor (var int i = x to (2 * ++y))
        begin
            System.out.println("i=" + i);
        end
    endMain

The above code results in the following printout:

    i=20
    i=21
    i=22
    i=23
    i=24
    i=25
    i=26
    i=27
    i=28
    i=29
    i=30
    i=31
    i=32

### 2.1 Elisp source code for the superfor macro

The following code belongs in the file `~/jtw-tutorials/jtw-cpp.el` which in itself is too large for inclusion in this manual. You can find this code by visiting J.T.W. tarball. Alternatively, you can study this fragment of the file `~/jtw-tutorials/jtw-cpp.el` which deals with the `superfor` macro. In the listing that follows, `*pp-namespace*` stores a string containing a long arbitrary name to prevent accidental aliasing of the `include` directives with rest of the comments code.

    (let (p1 p2 str form type variable T var start stop step-size step-size-2
             this_start this_stop this_step this_step_size file line p-prior
             beg0 end0)
      ;;(checkpoint "2")
      (save-excursion
        ;;(setq parse-sexp-ignore-comments t)
        (goto-char (point-min))
        (setq *superfor* 0)
        (while (re-search-forward "\\<superfor\\>" nil t)
          (setq beg0 (match-beginning 0))
          (setq end0 (match-end 0))
          ;;(checkpoint "sitting for 1 seconds...")
          (font-lock-fontify-buffer)
          ;;(sit-for 1)
          (when (save-excursion
                  (save-match-data
                    (re-search-forward "(" (point-at-eol) t)
                    (forward-char -1)
                    (re-search-forward "\\<var\\>" nil t)
                    (not (warn--inside-comment-or-string))))
            ;;(error "Smelly cat")
            (setq *current-buffer* (current-buffer))
            ;;(switch-to-buffer *current-buffer*)
            (setq p1 beg0)
            (assert (save-match-data
                      (looking-at " \t\r\n*(")))
            (setq p2 (save-excursion
                       (forward-sexp 1)
                       (point)))
            (setq str (buffer-substring-no-properties end0 p2))
            ;;(checkpoint "str=%s" str)
            (setq form (read-str str))
            ;;(checkpoint "form=%s" form)
            ;;(debug "form")
            (assert (consp form))
            ;;(error "Rolling Stones plays Cuba")
            (delete-region p1 p2)
            (incf *superfor*)
            (setq this (format "superfor_%d_" *superfor*))
            (when (not (eq (nth 0 form) 'var))
              (warn--log-message "Error 35: Keyword var missing")
              (when (and (not (eq (nth 0 form) 'char))
                         (not (eq (nth 0 form) 'short))
                         (not (eq (nth 0 form) 'int))
                         (not (eq (nth 0 form) 'long))
                         (not (eq (nth 0 form) 'float))
                         (not (eq (nth 0 form) 'double)))
                (warn--log-message (concat
                                    "Error 37:#1 argument type to superfor macro must be"
                                    " one of char/short/int/long/float/double"))))
            (when (eq (nth 0 form) 'var)
              (if (and (not (eq (nth 1 form) 'char))
                       (not (eq (nth 1 form) 'short))
                       (not (eq (nth 1 form) 'int))
                       (not (eq (nth 1 form) 'long))
                       (not (eq (nth 1 form) 'float))
                       (not (eq (nth 1 form) 'double)))
                  (warn--log-message (concat
                                      "Error 37:#2 argument type to superfor macro must be"
                                      " one of char/short/int/long/float/double")))
              (progn
                (setq type (nth 1 form))
                (setq T (prin1-to-string type))
                (setq variable (nth 2 form))
                (setq variable-equals (prin1-to-string (nth 2 form)))
                (if (string-match "=" variable-equals)
                    (progn
                      (setq variable (read-str (substring variable-equals 0 (match-beginning 0))))
                      (setq start    (read-str (substring variable-equals (match-end 0))))
                      (if (eq (nth 3 form) 'to)
                          (setq to 'to)
                        (if (eq (nth 3 form) 'downto)
                            (setq to 'downto)
                          (assert "The Bug")))
                      (setq stop     (nth 4 form))
                      (if (eq (nth 5 form) 'step)
                          (setq step-size (nth 6 form))
                        ;;(setq step-size 1)
                        ))
                  (assert (or (eq (nth 3 form) '=)))
                  ;;(debug "Joaquin Rodrigo")
                  (setq start (nth 4 form))
                  (if (eq (nth 5 form) 'to)
                      (setq to 'to)
                    (if (eq (nth 5 form) 'downto)
                        (setq to 'downto)
                      (assert "Planet of New Orleans")))
                  (setq stop (nth 6 form))
                  (if (eq (nth 7 form) 'step)
                      (progn
                        (setq step-size (nth 8 form))
                        ;;(assert (numberp (nth 8 form)))
                        )
                    ;;(setq step-size 1)
                    )
                  ))
              (d-quote
               (debug "Rocket Queen")
               (setq type "")
               (setq T "double")
               (setq variable (nth 0 form))
               (assert (eq (nth 1 form) '=))
               (setq start (nth 2 form))
               (if (eq (nth 3 form) 'to)
                   (setq to 'to)
                 (if (eq (nth 3 form) 'downto)
                     (setq to 'downto)
                   (debug "My Michelle")))
               (setq stop (nth 4 form))
               (if (eq (nth 5 form) 'step)
                   (setq step-size (nth 6 form))))
              (setq var         (prin1-to-string variable))
              (setq start       (prin1-to-string start))
              (setq stop        (prin1-to-string stop))
              (setq step-size-2 (prin1-to-string step-size))
              (setq start       (warn--splat-quest start))
              (setq stop        (warn--splat-quest stop))
              (setq step-size-2 (warn--splat-quest step-size-2))
               -----------------------------------------------------
              (setq this_start     (concat this "start"))
              (setq this_stop      (concat this "stop"))
              (setq this_step      (concat this "step"))
              (setq this_step_size (concat this "step_size"))
              ;;(debug "My Parties")
              (insert (concat (concat "var " T " " this_start " = " start ";")
                              (concat "var " T " " this_stop  " = " stop  ";")
                              (if step-size
                                  (concat "var " T " " this_step " = " step-size-2 ";"
                                          "var " T " " this_step_size " = "
                                          (if (eq to 'to) (concat "Math.abs(" this_step ")") (if (eq to 'downto) (concat "-Math.abs(" this_step ")") (debug "Heavy Fuel"))) ";\n")
                                (concat "var " T " " this_step_size " = " (if (eq to 'to) "1" (if (eq to 'downto) "-1" (debug "Ticket to Heaven"))))) ";\n"))
              (setq line 0)
              (setq p-prior
                    (save-excursion
                      (beginning-of-line)
                      (setq str (concat "^ \t*//+ " *pp-namespace* " #location0-9"
                                        " (\\(" *drive-spec* "-a-zA-Z0-9_./+\\):\\(0-9+\\))"))
                      (if (or (looking-at str) (re-search-backward str nil t))
                          (progn
                            ;;(debug "Antonio Vivaldi")
                            (setq file (buffer-substring-no-properties           (match-beginning 1)
                                                                                 (match-end 1)))
                            (assert (stringp file))
                            (setq line (read-str (buffer-substring-no-properties (match-beginning 3)
                                                                                 (match-end 3))))
                            (assert (integerp line))
                            (point)
                            )
                        (setq file (concat default-directory *stump* ".jtw"))
                        (setq line 1)
                        (goto-char (point-min))
                        (forward-line 2)
                        (point)
                        )))
              (setq line (+ line (count-lines p-prior (point))))
              (decf line)
              (decf line)
              (insert (format "// %s (setq file-stack '%s)\n" *list-namespace* (prin1-to-string file-stack)))
              (insert (format "// %s #location3 (%s:%d)\n" *pp-namespace* file line))
              (insert (concat "for (var " T " " var " = " this_start ";"
                              " ((" this_step_size " > 0) ? " var " <= "
                              this_stop " : " var " >= " this_stop "); "
                              var " += " this_step_size ")"))
              ;;(debug "Yehudi Menuhin")
              )))))
    )

### 2.2 A bug in J.T.W. superfor

The question mark operator `a ? b : c` which expands to

    Type result;
    if (a) then
    begin
        result = b;
    end
    else
    begin
        result = c;
    end

where type can be any Java type is not directly supported by the arguments to the `superfor` macro in J.T.W. Elsewhere the question mark is supported. Instead in the `superfor` macro you have to write the following code to get a question mark operator online:

``class` SuperFor
`begin`
`beginMain`
foo(1,2);
`endMain`
`function` void foo(int x, int y)
`begin`
`superfor` (`var` int i=0 to (x < y `QUEST` 10 : 20))
`begin`
System.out.print(" " + i);
`end`
System.out.println();
`end`
`end`
`

where the symbol `QUEST` compiles into a question mark: `?`. When built, the program prints out the following:

    i=0
    i=1
    i=2
    i=3
    i=4
    i=5
    i=6
    i=7
    i=8
    i=9
    i=10

Next: J.T.W. Proof of concept #2 file inclusion, Previous: About GNU Java Training Wheels, Up: Top [Contents][Index]