Re: Some compiler issues and a request for debugging/design help
"Paul R. Potts" <[email protected]> Tue, 18 Jun 2013 20:59:25 -0400
| Newsgroups | gmane.comp.lang.dylan.gwydion.devel |
|---|---|
| Message-ID | <[email protected]> |
On Jun 18, 2013, at 12:23 PM, Carl Gay <[email protected]> wrote: > Hi Paul, good to see you trying Dylan again. I can add a few little bits > of info, but you'll have to wait for Bruce or others on the compiler > issues… Thanks for your comments/suggestions, Carl! >>> I've been playing with the 2012.1 compiler and have come across a few >>> things. Maybe these are all well known, maybe they are actually not bugs >>> and I just misunderstand, or maybe there are workarounds. I would be happy >>> to take a crack at fixing some if I can, although it seems that maybe >>> people far smarter than me have tried and failed -- what is the state of >>> the art as it were in getting the compiler or run-time up under some kind >>> of debugging environment? The way runtime errors just terminate, without >>> giving line numbers, I find less than helpful. >>> >> > For the best debugging experience you need to use the IDE on Windows. > You'll generally get a real debugger with the ability to browse the stack, > jump to the code, etc. You'll experience some serious bugs in the IDE > though, which can be frustrating. I've come to know what sorts of things > it can and can't do without blowing up in my face. It is possible to be > quite productive with it. Yeah… I have used it before, using the old Visual C++ 6 (IIRC) linker, but I had not tried installing it recently. I have a Windows 7 laptop -- maybe I'll see if I can get it going. > On the Linux/OS X side I think gdb is the best you can do right now. > You'll have to do some mental gymnastics to read the stack trace. Bruce > (I think) did some work recently to improve the ability to print Dylan > objects in gdb, but I haven't tried it yet. I've never gotten very good with gdb so I guess I'll try the IDE route first. >>> It looks like there are still a lot of issues with making collection >>> types. For example, I want to make a type-union of singletons and use it as >>> the basis of a collection, where my constants like $the-bomb are instances >>> of simple classes defined at the module level: >>> >>> define constant <tile-or-false> = type-union( >>> singleton( $the-bomb ), singleton( $the-empty ), >>> singleton( $the-heart ), singleton( $the-house ), >>> singleton( $the-ice-block ), singleton( $the-mountain ), >>> singleton( $the-tree ) ); >>> >>> If I instantiate an array at the top level: >>> >>> define constant <board-type> = limited( <vector>, of: <tile-or-false>, >>> init-value: $the-empty, size: 96 ); >>> >>> The compiler accepts this fine but at run-time I get a crash like so: >>> >>> #f is not of type {<union>: {<union>: {<union>: {<union>: {<union>: >>> {<union>: {<bomb>}, {<empty>}}, {<heart>}}, {<house>}}, {<ice-block>}}, >>> {<mountain>}}, {<tree>}} >>> #f is not of type {<union> 0x476ed0} >>> Breaking into debugger. >>> Trace/BPT trap: 5 >>> >>> It seems that including the singleton( #f ) is absolutely necessary to >>> even create the limited type. I'm guessing that internally it is >>> constructed containing #f before the init-value is actually applied, but it >>> seems to me that this is a leaking implementation details? >>> >> > IIRC this was a hot/unsolved issue just before Harlequin shut down. It > seems to me the compiler needs magic to come up with an "uninitialized" > type for each limited collection element type. But I'm not a compiler guy. It's not a big deal -- I don't actually need this program to be highly optimized. It just seemed odd. >>> Next, it looks like some work has been done on collections recently but >>> some of them still seem pretty broken. If I define a limited 2-D array like >>> so: >>> >>> define constant <board-type-2D> = limited( <array>, of: <tile-or-false>, >>> init-value: $the-empty, dimensions: #( 4, 24 ) ); >>> >>> If I instantiate one, it always comes out as a simple object vector with >>> actual size zero, and trying to set any element crashes. >>> >>> ELEMENT outside of range: 0 >>> ELEMENT outside of range: 0 >>> Breaking into debugger. >>> Trace/BPT trap: 5 >>> >>> Also, it appears that if I have a constant like >>> >>> define constant $board-dim-y = 4; >>> >>> I can't use it as something to pass in the dimensions: parameter. >>> >> > That's strange. I have to ask whether you were perhaps doing > #($board-dim-y, $board-dim-x) when you should have been doing > list($board-dim-y, $board-dim-x) ? Hmmm, it looks like list() works here. Maybe this is a dumb question, but shouldn't they be equivalent? With the exception that the #() is built at compile time and immutable? So anyway, using list() works, but creating the limited 2-D array doesn't. I have tried to pin down exactly what fails. Given: define class <model> (<object>) slot board :: <array>; slot board-2d :: <array>; slot penguin-pos :: <pos>; slot penguin-dir :: <dir>; slot heart-count :: <integer>; end; define constant <board-type> = limited( <vector>, of: <tile-or-false>, init-value: $the-empty, size: 96 ); define constant <board-type-2d> = limited( <array>, of: <tile-or-false>, init-value: $the-empty, dimensions: list( $board-dim-y, $board-dim-x ) ); this: let board-2d-limited-type = make( <board-type-2d> ); format-out( "Made locally bound limited array (2-D) %S\n", board-2d-limited-type ); force-output( *standard-output* ); works, but writing to the array using [0, 0] fails with: Invalid number of indices for {<simple-element-type-vector>: size 0}. Expected 1, got 2 this: let board-2d-untyped = make( <array>, dimensions: list( $board-dim-y, $board-dim-x ) ); format-out( "Made locally bound unlimited array (2-D) %S\n", board-2d-untyped ); force-output( *standard-output* ); works, and writing at all the elements using [y, x] works this: model.board-2d := make( <board-type-2d> ); format-out( "Made limited array (2-D) bound to <array> slot %S\n", model.board-2d ); force-output( *standard-output* ); fails with: The board slot is unbound in {<model>}. without ever printing (Ummm… I'm not even sure where that is coming from… that is very strange...) and this: model.board-2d := make( <array>, dimensions: list( $board-dim-y, $board-dim-x ) ); format-out( "Made unlimited array (2-D) bound to <array> slot %S\n", model.board-2d ); force-output( *standard-output* ); fails the same way (I'll have to look into that some more -- my brain is fading for the day. >>> So I'm still having to fake a 2-D array with my own indexing calculations >>> (which works OK). >>> >>> Let's say I then have my fake 2-D array type: >>> >>> define constant <board-type> = limited( <vector>, of: <tile-or-false>, >>> init-value: $the-empty, size: 96 ); >>> >>> I want to use that type as a slot type: >>> >>> define class <model> (<object>) >>> slot board :: <board-type>; >>> slot penguin-pos :: <pos>; >>> slot penguin-dir :: <dir>; >>> slot heart-count :: <integer>; >>> end; >>> >>> that also fails in a not-very-helpful manner. (I think that's a failure >>> on my part -- <board-type> is actually not an instantiable class type, so >>> my bad). I've wound up using plain old <array> for slot board and that >>> seems to work. >>> >>> Let's see, various other less-than-helpful crashes… oh, if I accidentally >>> use a constant instance of a class instead of a type in a method definition >>> like so: >>> >>> define method collide( model :: <model>, dir :: <dir>, >>> slider-pos :: <pos>, slider-tile :: <pushable-tile>, >>> next-pos :: <pos>, next-tile :: $the-empty ) >>> end; >>> >>> That produces a crash at program start-up even if I never call that >>> method… ugh (it should read "next-tile == $the-empty -- my bad again, but >>> ugh). >>> >>> Let's see, what else… oh, if I have a crash I get _no_ output from >>> format-out, even if I have printed hundreds of lines before the crash; I >>> was not easily able to locate any kind of equivalent of flush()? >>> >> > I wish this were more straight-forward, but: > > define library my-library > ... > use io; > end; > > define module my-module > ... > use streams; > use standard-io; > end; > > // Before exiting your program, > force-output(*standard-output*); Thanks! Helpful... >>> So I've made some progress but I still have a crashing bug -- line 252. >>> If I un-comment that line, I get a crash in setTileAtXYDebug() in what >>> looks to me like the kind of array element setter call that the program >>> makes hundreds of times. In this case it is driven specifically by the >>> collide method at line 153, the collision between bombs and mountains. In >>> fact it really should just call setTileAtPos, but I was so confused by why >>> this particular set of calls were always crashing that I made a separate >>> method just to try to figure out what was different here. >>> >>> Maybe my somewhat muddled design will become clear. The goal was to try, >>> basically, to use the dispatch mechanism entirely for the penguin push and >>> collide methods. I've had some difficulty here. I was getting errors about >>> dispatch being determined by "arbitrary and capricious --?" rules. I think >>> the current compiler is up to this if I can avoid colliding with certain >>> mis-features. >>> >> > You'll normally get at least one such warning from building the dylan > library itself, which happens on first build of any user library. Not sure > if you're saying it was due to your code. It was in my code. It is not occurring in the code as it stands right now. I've been tweaking it a lot. Some combination of dispatch on types/singletons caused it, but currently I'm dispatching entirely on singletons. >>> Basically, the bigger design issue is that I want to use classes to >>> represent the tile behaviors, and so I can dispatch on singletons -- I >>> don't care about instances as the tiles have no state. But given that >>> interactions take place on a board and can cross the entire board, class >>> methods have to be able to access the board and look up and alter arbitrary >>> tiles. So I'm kind of torn. I've played with giving tiles their own >>> coordinates, with using actual instances for tiles and replacing them as >>> they changed, but that also seems silly. I'd be curious as to whether any >>> of you see a cleaner, simpler design in here struggling to get out. Note >>> also how I'm passing both positions and types to the collide and push >>> methods. That seems really sub-optimal but I wasn't sure if I could ask the >>> compiler to dispatch on wrapped-up objects that contained both positions >>> and singleton instances… but maybe that would be cleaner? >>> >>> Thanks for any conversation… it's keeping my mind off the realities of my >>> job search while I wait to here results back from various >>> interviews/applications. >>> >>> Paul >>> >>> p.s. the color syntax highlighting in vim on Ubuntu for .dylan files is >>> very nice -- anyone figured out how to get that working on MacOS X? >>> >> > I haven't looked carefully at your code yet, so I can't comment on the > design issue above, but here are a couple things I noticed: > > * Why are <pushables>, <walkables>, etc. necessary? Just dispatch on > <pushable-tile>, <walkable-tile>, etc. instead? Yeah -- I was experimenting with dispatching on all the singleton-based type-unions instead of classes, because some combinations of dispatching on classes here, singletons there was leading to those messages about "arbitrary and capricious rules" _and_ the code was crashing such that I could not determine why. If I can get rid of the one remaining crashing bug, I'll try dispatching on classes again. I think that would be the clearest, really. > * type-union(singleton(foo), singleton(bar)) can be written more concisely > as one-of(foo, bar). Oh, nice! That shortens & clarifies a little! Thanks! > > -Carl > _______________________________________________ > hackers mailing list > [email protected] > https://lists.opendylan.org/mailman/listinfo/hackers _______________________________________________ hackers mailing list [email protected] https://lists.opendylan.org/mailman/listinfo/hackers