Closed ta0kira closed 2 years ago
A few problems:
#self
or explicit expansion) will cause infinite recursion during TypeInstance
creation. (Affects both approaches, unless we use lazy init.)(Now that I think about it, I explicitly decided against type aliases for similar reasons back when this project was just a type system.)
I implemented the first approach (pragma and lazy init, didn't commit the changes), but it only improved performance of the bulk-write test below by about ~1%, caching HashNode<#k,#v>
in HashRoot
.
concrete HashTest {
@type run () -> ()
}
define HashTest {
run () {
HashedMap<Int,Int> map <- HashedMap<Int,Int>.new()
traverse (`Counter.zeroIndexed` 1000000 -> Int i) {
\ map.set(i,i)
}
}
}
The poor improvement is probably because the cached type is only needed when allocating new objects. It might provide more improvement for @type
calls that don't involve any dynamic allocation, including multiple returns.
HashedMap
is the only place where this feature would be useful, so I don't think it's worth the added complexity.
For example,
HashRoot<#k,#v>
currently constructsHashNode<#k,#v>
every time a new entry is added.Caching the
TypeInstance
can currently be faked with an extra param#n requires HashNode<#k,#v>
toHashRoot
, but that's quite messy.The two options seem to be:
$CacheTypes[HashNode<#k,#v>]$
, fabricate a C++ param name (e.g.,Param_1
, since#1
is an invalid in Zeolite param), then do a reverse substitution when expanding types in@value
and@type
calls.alias #n <- HashNode<#k,#v>
, then give it implicitallows
/requires
filters so that type checking works.Both will look roughly the same in C++. The main differences are in the syntax and whether or not the compiler automatically uses the alias.