Up to Main Index                         Up to Journal for September, 2023

                   JOURNAL FOR SATURDAY 9TH SEPTEMBER, 2023
______________________________________________________________________________

SUBJECT: Type declarations and inference sorted out
   DATE: Sat  9 Sep 17:15:52 BST 2023

I’ve been continuing my experiments to make Mere strongly typed. I can now
write code such as:


    call display 3

    display: func limit:int
      for x := 1; x <= limit; x++
        print " " x
      next
      for x := limit; x-- > 0;
        print " " x
      next
      println
    endfunc


When run the code produces “ 1 2 3 2 1”. Yes, I have sorted out the issues
with colons being used as non-tokens for label terminators and colons used as
tokens for variable type declarations and type inference ;) This makes the new
type declaration operator ‘:’ and type inference ‘:=’ as originally intended.

One thing is still bothering me, range-next loops over maps and the fact that
the loop value needs to change its type. For example:


    >cat range.mr
    range ; v; [string] "i" 1, "f" 2.2, "s" "c"
      println v " " type v
    next
    >mere range.mr
    2.2 float
    1 int
    c string
    >


Should this bother me? We can use the type built-in if we need to work with
the specific type of value:


    >cat type.mr
    range ; v; [string] "i" 1, "f" 2.2, "s" "c"
      t := type v
      if t == "int"
        i := int v
        println i " is int"
      elif t == "float"
        f := float v
        println f " is float"
      elif t == "string"
        s := string v
        println s " is string"
      fi
    next
    >mere type.mr
    2.2 is float
    1 is int
    c is string
    >


I tried to think of a program that makes a lot of use of knowing what a type
is. The best I could come up with is a pretty printer that displays a nice
indented structure of nested maps and arrays:


    >cat pretty.mr

    call pretty [string](
      "a" [int](
        2 [string](
          "c" [string]("i" 1, "u" 2u, "f" 3.3, "s" "IV", "b" true),
          "d" [int](1 1, 2 2u, 3 3.3, 4 "four", 5 true),
          "e" []int(3 5 7),
        )
      )
    )

    pretty: func sm:[string]
      println type sm, "("
      call _pretty [string]("data" sm)
      println ")"
    endfunc

    _pretty: func  sm:[string], depth:int
      indent:string, dt:string >< " "*2*depth++, type sm["data"]
      dt := type sm["data"]

      range k; v; sm["data"]
        vt := type v
        if vt[0] == "["
          printf "%s%s %s(\n", indent, literal k, vt
          call _pretty [string]("data" v), depth
          printf "%s),\n", indent
        elif dt[1] == "]"
          printf "%s%s,\n", indent, literal v
        else
          printf "%s%s %s,\n", indent, literal k, literal v
        fi
      next
    endfunc

    >mere pretty.mr
    [string](
      "a" [int](
        2 [string](
          "c" [string](
            "b" true,
            "f" 3.3,
            "i" 1,
            "s" "IV",
            "u" 2u,
          ),
          "d" [int](
            1 1,
            2 2u,
            3 3.3,
            4 "four",
            5 true,
          ),
          "e" []int(
            3,
            5,
            7,
          ),
        ),
      ),
    )
    >


Maybe that’s not too bad? The main _print function, doing all the work, is
called recursively. The trick here is to always wrap the data in a [string]
stub. The code works and is quite readable. I very was happy when the multiple
assignment with variable type declarations just worked without any changes :)

Carefully looking over the code I think I can type check nearly all of it at
compile time. Performance seems to be holding up looking at the benchmarks:


                            Old          New
          counter           0:00:16.978  0:00:17.085  +0.107s +0.63%
          loop_counter      0:00:18.663  0:00:18.552  -0.111s -0.59%
          fastloop_counter  0:00:15.629  0:00:15.692  +0.063s +0.40%


The differences there seem to be chatter from a not so quiet machine.

This does mean I now need to go and update all of my example code and tests.
At the moment the tests won’t run at all and just error all over the place.
I’ve updated some of my examples and they seem to be working well. After that
I think I may be able to push everything out for others to have a play with.

--
Diddymus


  Up to Main Index                         Up to Journal for September, 2023