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