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