Re: Some compiler issues and a request for debugging/design help

Carl Gay <[email protected]> Tue, 18 Jun 2013 12:23:44 -0400
Newsgroups gmane.comp.lang.dylan.gwydion.devel
Message-ID <CALekcH3fqmtMNk87HVL-cMnsxGU7kOXm0jWO_2kP6Y5_YruafA@mail.gmail.com>
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...


On Sun, Jun 16, 2013 at 11:43 AM, Bruce Mitchener <[email protected]
> wrote:

> Wow, this is awesome.
>
> I'm going to need some time to look into the things that you're reporting,
> but it sounds like you've identified some shortcomings and / or compiler
> bugs. :)
>
> For one quick answer, I've used vim with pathogen on OS X. What I did then
> was:
>
> * Put pathogen.vim into ~/.vim/autoload/
> * mkdir ~/.vim/bundle
> * cd ~/.vim/bundle/
> * Cloned git://github.com/dylan-lang/dylan-vim.git
> * Add ":call pathogen#infect()" as the first line in my ~/.vimrc
> * Also added :syntax on and some other stuff to the ~/.vimrc
>
> That'll also make it easy for you to get our updates as bugs get fixed in
> the vim integration.
>
>  - Bruce
>
>
>
> On Sun, Jun 16, 2013 at 9:11 PM, Paul R. Potts <[email protected]>wrote:
>
>> Hello Dylanistas, happy Father's Day!
>>
>> Being unemployed now I'm doing some coding for my own learning/fun
>> recently… blogging about it here:
>>
>> http://praisecurseandrecurse.blogspot.com/2013/06/objective-c-day-5.html
>>
>> Struggling with object-oriented designs, I have in the past found it very
>> useful to implement my ideas in Dylan to get my design thinking
>> straightened, and then port it to a different implementation language,
>> working around missing features. So I've been doing that with my little
>> implementation of the old Mac "Polar" game -- porting it from Objective-C
>> to Dylan as I think about what an ideal, textbook-concise implementation
>> would look like.
>>
>> If you aren't familiar with Polar, the idea is that your avatar is a
>> penguin, walking around on a 4x24 grid of ice. The squares that make up the
>> world can be empty, ice blocks, mountains, trees, hearts, bombs, and
>> houses. They have rules to interact like so:
>>
>> - The penguin can walk on ice and through trees (forested tiles)
>> - ice blocks, hearts, and bombs, if pushed by the penguin onto empty
>> squares, will slide, and continue sliding until they collide with a
>> non-empty square
>> - if an ice block is pushed against some other non-empty square it is
>> crushed and disappears
>> - if a bomb hits a mountain, it blows up the mountain and both bomb and
>> mountain disappear
>> - if a heart hits a house, it disappears, and that gets you closer to
>> your goal of winning the board; when all the hearts have been cleared from
>> the board, the stage is done
>>
>> I've implemented this in Dylan using classes -- empty classes with no
>> slots, just so that I can dispatch on their types, as in a collide method
>> that takes singleton heart and house will do one thing, a collide method
>> that takes singleton mountain and bomb will do something else. I'll attach
>> my source in case you would like to look at it/play with it. Notes on that
>> below.
>>
>> 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.

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.


>
>> 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.


>
>> 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) ?


>
>> 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*);



>
>> 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.


>
>> 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?
* type-union(singleton(foo), singleton(bar)) can be written more concisely
as one-of(foo, bar).

-Carl

_______________________________________________
hackers mailing list
[email protected]
https://lists.opendylan.org/mailman/listinfo/hackers