Runtime error in JS calling private constructor
Closed this issue · 3 comments
jvasileff commented
The code below (and also version 2 of this gist fails with:
error undefined — Runtime error:
error undefined — --- ReferenceError: Can't find variable: Trie$c_$doiss5$gac
It works if the constructor is made shared
(as was done in the gist).
// **NOTE** doesn't work on JS backend!
shared void run() {
variable value t = Trie<Integer>();
value count = 256;
// create a list of ints
for (i in 0:count) {
t = t.withTrailing(i);
}
// update the values
for (i in 0:count) {
t = t.withValue(i, -i);
}
printAll(t);
}
alias StorageArray<out Element>
=> Array<out Chunk<Element>?>;
class Chunk<out Element>(data, children) {
shared Element data;
shared StorageArray<Element>? children;
}
shared class Trie<out Element> satisfies List<Element> {
StorageArray<Element>? contents;
shared actual Integer size;
shared new () {
size = 0;
contents = null;
}
new create(Integer size, StorageArray<Element> contents) {
this.size = size;
this.contents = contents;
}
Element unsafeGet(Integer index) {
assert (0 <= index < size);
assert (exists contents);
if (index < 32) {
assert (exists chunk = contents.get(index));
return chunk.data;
}
variable value c = contents;
variable value p = path(index);
for (i in p.exceptLast) {
assert (exists cc = c.get(i)?.children);
c = cc;
}
assert (exists chunk = c.get(index.and(31)));
return chunk.data;
}
"Return an efficient copy of this [[Trie]] with the given [[item]] appended."
shared Trie<Element | Other> withTrailing<Other>(Other item)
=> withValue(size, item);
"Return an efficient copy of this [[Trie]], replacing the value at the given
[[index]] with [[item]]. [[index]] must be no greater than [[lastIndex + 1]]."
shared Trie<Element | Other> withValue<Other>(Integer index, Other item) {
assert (0 <= index <= size); // allow appending
value path = this.path(index);
assert (exists firstIndex = path.first);
value newContents = copyArray<Chunk<Element | Other>?>(
contents, null, firstIndex + 1);
variable value arrayToUpdate = newContents;
for ([curIdx, nextIdx] in path.paired) {
assert (exists vectorToReplace = arrayToUpdate.get(curIdx));
value children = vectorToReplace.children;
value newArray = copyArray(children, null, nextIdx+1);
value newVector = Chunk(vectorToReplace.data, newArray);
arrayToUpdate.set(curIdx, newVector);
arrayToUpdate = newArray;
}
assert (exists idx = path.last);
value oldVector = arrayToUpdate.get(idx);
arrayToUpdate.set(idx, Chunk(item, oldVector?.children));
return Trie.create(Integer.largest(size, index + 1), newContents);
}
getFromFirst(Integer index) => if (index < size) then unsafeGet(index) else null;
lastIndex => size > 0 then size - 1;
iterator() => object satisfies Iterator<Element> {
// TODO optimize?
variable value i = 0;
next() => if (i == size) then finished else unsafeGet(i++);
};
hash => (super of List<Element>).hash;
equals(Object other) => (super of List<Element>).equals(other);
"Basically, [[index]] in base-32"
[Integer*] path(Integer index)
=> loop(index)((i)
=> if (i.rightLogicalShift(5).zero)
then finished
else i.rightLogicalShift(5))
.collect((i) => i.and(31))
.reversed;
"Return a copy of [[source]] at least as large as [[minSize]]"
Array<Element> copyArray<Element>(
Array<out Element>? source,
Element fillItem,
Integer minSize) {
if (!exists source) {
return Array<Element>.ofSize(minSize, fillItem);
} else if (minSize <= source.size) {
return Array<Element>(source);
} else {
value result = Array<Element>.ofSize(minSize, fillItem);
source.copyTo(result);
return result;
}
}
}
gavinking commented
@chochos would you please take a look at this one. I would love to have this fixed for 1.3.3.
chochos commented
OK it seems the invocation uses the private name but the constructor is defined as if it was shared (naming is different). I guess the correct thing is to generate it with the private name.
A much simpler way to reproduce this:
shared class SevenOneTwoTwo {
shared Integer x;
shared new() {
x = 0;
}
new withInt(Integer i) {
x = i;
}
shared SevenOneTwoTwo add(Integer i) {
return SevenOneTwoTwo.withInt(x + i);
}
string = "Value:``x``";
}
shared void run() {
print(SevenOneTwoTwo().add(5));
}
chochos commented
I'm close to solving this