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