-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactoring and yak shaving. #13687
refactoring and yak shaving. #13687
Conversation
… into remove-compiles-from-compiler
I don't think recursing inside ptr/ref is desirable example1# D20200319T034809:here
type Foo = ref object
bar: Foo
x: int
var foo = Foo(x: 12)
foo.bar = foo
echo foo
example2# D20200319T035242:here
type Bar = ref object
s: string
type Foo = ref object
bar1: Bar
bar2: Bar
x: int
var bar = Bar(s: "some long string that gets duplicated")
var foo = Foo(x: 12, bar1: bar, bar2: bar)
echo foo =>
this is a common case (eg graphs, edges etc) Not only do you duplicate but you also can't tell whether bar1, bar2 have same address or not. proposalinstead, you can print the hex-formatted address of ref/ptr/pointer that are not at top-level
or, you could maintain a hashtable of what's been already expanded and only use address if it's already been printed:
|
if arg == nil: | ||
"nil" | ||
else: | ||
$arg[] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be some difference between echo somePtrToInt
and echo someInt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For ptr someType
maybe print the address and the object it points to
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you mean you would like to have an indirection sign like "-> 1"
instead of "1"
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, my github was slow I didn't see your second message. I actually thought about printing the address, but honestly most of the time you really do not care about an address. Addresses are long and rarely what you really care about. That is why I omitted it. I also didn't indicate that the object is a pointer, because for me being a pointer is part of the type, and types aren't printed in string representation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because for me being a pointer is part of the type, and types aren't printed in string representation.
I agree on this point
I actually thought about printing the address, but honestly most of the time you really do not care about an address.
i disagree on this point, with reference types the address is what matters most since equality (and hence identity) is base on address instead of its dereferenced content. Eg if you want to know whether 2 nodes are equal in a graph. This relates to my point in #13687 (comment)
so for top-level types you'd print:
type Foo = ref object
x: int
f2: Foo
doAssert $Foo(x: 2) == 0xdeadbeef->(x: 2, f2: 0xdead0000)
analog to how repr
does
Furthermore, this natually extends to pointer
(where the only thing we can do is print address)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well for pointer
I agree, the address is what should be printed and that is also what I do print here in this PR. But for everything else, pointer addresses are just visual noise, nothing else. And if you do care about an address you can still do: $cast[pointer](x)
on it.
|
as of your latest commit bd9694e, you've introduced already 7 regressions that I found, affecting many of the modules you've changed, who knows how many other ones there are. regression 1when true:
import sequtils
var s = newSeq[int](3)
proc fun() =
let s2 = toSeq(s)
s[0] = 10
doAssert s2 == @[0,0,0]
fun() before PR: this works regression 2when true:
import sequtils
import times
let n = 10_000_000
let s = newSeq[int](n)
proc fun(a: openArray[int]) =
let s = toSeq(a)
doAssert s[^1] != -1
let t = cpuTime()
for i in 0..<100: fun(s)
echo cpuTime()-t (with -d:danger) regression 3when true:
type Foo = object
age: int
s: string
internal: seq[ptr Foo]
var foo = Foo(age: 20, s: "bob")
foo.internal = @[foo.addr]
echo foo before PR: (age: 20, s: "bob", internal: ...) regression 4when true:
type Foo = object
age: int
s: string
internal: seq[ptr int]
var foo = Foo(age: 20, s: "bob")
let px = foo.age.addr
foo.internal = @[px, cast[ptr int](cast[int](px) + 1*sizeof(int))]
echo foo
foo.internal.add cast[ptr int](cast[int](px) + (int.high div 10)*sizeof(int))
echo foo before PR: after PR: regression 5when true:
import tables
var t: OrderedTable[int, int]
t[0] = 0
clear(t)
doAssert 0 notin t before PR: works regression 6when true:
import sharedtables
import tables
var t: SharedTable[int, int]
var t0: Table[int, int]
t0[0] = 0
t[0] = 0 before PR: works regression 7nim c --gc:arc main when true:
type Foo = ref object
id: int
a: seq[Foo]
var x = Foo()
echo $x[] before PR: (id: 0, a: ...) regression 8related to regression 4 when true:
import tables
import hashes
type Foo = object
id: int
internal: ptr Foo
proc hash(a: Foo): Hash = a.id
var t: Table[Foo, int]
proc main()=
var f {.noinit.}: Foo
f.id = 10
try:
echo t[f]
except Exception as e:
echo "caught"
main() before PR: caught overall commentAuto dereferencing |
@timotheecour thanks a lot for your last review and extensive tests. They are really valuable.
This looks like a compiler bug to me. After all
Thanks a lot. Easy fix.
Good catch.
You are trying to print invalid pointers am I right? Well it does crash. But shouldn't it be ok to crash? after all these pointers are invalid pointers. After all you can crash ref equally, and you can even crash string printing if you force it to have invalid data: var myString = "abc"
cast[ptr tuple[len,cap: int]](myString).len = -10
echo myString
I really din't think I would have changed anything on how tables work. How did you catch that one? Thanks a lot of finding it. |
|
0388b6a
to
b83dea3
Compare
@timotheecour regarding regression 6 you posted. I am a bit puzzled by it. The code is clearly written in a way, so that shared tables can only be used after they are initialized.
when true:
import sharedtables
import tables
var t: SharedTable[int, int]
var t0: Table[int, int]
t0[0] = 0
t[0] = 0 # this is supposed to raise an exception. |
good observation. i found the root cause:
So indeed, |
This pull request has been automatically marked as stale because it has not had recent activity. If you think it is still a valid PR, please rebase it on the latest devel; otherwise it will be closed. Thank you for your contributions. |
sequtils.evalOnceAs
andtables.ctAnd
dispensable and removed it.astalgo.debug
on builtin core types less verbose.sequtils.toSeq
to be simpler (and probably faster).$
operator for every type, including distinct and ptr, ref and proc. Even though$
on proc isn't particularly informative, it won't reject to compile.CyclicSeq = seq[ref CyclicSeq]
This should make future code simpler to write as you won't need to check anymore if a type supports a
$
operator, when it is available for everything.