Posts Tagged ‘ruby’

just the lexer, ma’am

Thursday, October 29th, 2009

So in my compilers class I’m supposed to write a recursive descent parser for the WAE grammar. To remind you, this grammar looks like this:

WAEStart ::= WAE SEMI
WAE ::= num | {+ WAE WAE} | {- WAE WAE} | {with {id WAE} WAE} | id

I’ve created this in python, using the PLY parser. That code has scoping issues, and is available on google code. I’ve also built this using treetop, with some modifications on the unary minus (a new rule, WAE::= -WAE , and that’s available from google code, bitbucket, and github.

But I also wanted to try to build both a recursive descent parser and possibly a packrat parser by hand, and maybe using a combinator, so I’m working on another version of this grammar using rparsec. I chose rparsec because I needed a lexer with simple, easy to understand, useful output. Possibly, there are a dozen rubygems that solve this problem, but rparsec is the one in “Practical Ruby Programming”, so that’s the one I used.

I also wanted to test out the pygments tool, which is a syntax highlighter that converts code for display in various formats. So, using pygments, my lexer looks like this:

require 'rubygems'

require 'rparsec'

module WAEParser
  include RParsec
  extend RParsec::Parsers

  Id = regexp(/[a-z]/)
  Num = number.token(:number)

  Reserved = Keywords.case_sensitive(%w{with exit})
  Ops = Operators.new(%w{+ - \{ \} ;})

  Lexer = longer(Id.token(:id) , Reserved.lexer) | Num |  Ops.lexer

  Lexeme = Lexer.lexeme << eof
end

The method Lexeme.parse(string) produces the array of tokens.

testing, testing, testing

Monday, April 6th, 2009

So the latest problem that came up is that a given node cannot transmit and receive simultaneously. You would think that this would be easy to solve in a discrete event simulation of a wireless ad hoc network. For example, you might do this:

  1. Find all the packets you will simulate this round
  2. Find all the senders of those packets
  3. Set some flag to forbid them from recieving

And yeah, you can do that. The problem is, there are at least three kinds of packets. Virtual packets are symbolic, and have no meaning outside of reporting/administrative functions. They aren’t simulations of something, they are part of the simulation. But because the event queue needs packets, they exist. Actually, the event queue doesn’t need packets, now that I think about it. The event queue needs objects, and doesn’t care if those objects are packets or pachyderms. But I have to handle pachyderms, in that case.

The second kind of packet is an internal message from one part of a node to another. But you know, now that I think about it, I’m looking at this wrong. Only packets create sender conflicts. The other things aren’t packets, and they don’t need to be packets. Definitely food for thought.

Hmm… if I put my other classes in with the “Packet” class, that is, in the same file, then that file really becomes the events file, that is, the file where we define what types of messages get put on the event queue…

For some reason, I get the awful feeling that I’m programming in Ruby, but I’m actually still programming in AppleScript, or worse, in Java. Like I’m just not grokking what I could be doing here.

easy

Saturday, April 4th, 2009

Wow. It’s easy to get behind in the blogging.

The bathroom project really sucked a lot out of me, to be honest. I was up at about 3 am on sunday, having put in fifteen or so hours building, moving… and I totally screwed up the toilet drain. Meaning that I’m either going to have to add about an inch of flooring in that section, or get incredibly creative with a fix.

This is not a good thing. Once PVC is set, it is set. And it occurs to me that I may not want to do the refinance anyway.

Anyway, the latest has been creating an output file and doing some fairly major refactoring in simpleHoc. My notes from a few days ago for changeset 12 say

serious refactoring. Altered the receieve packet method, it now takes a packet and then places a packed directly to the event queue, rather than back to the run_sim method in the queue. Added an output function in the Hocnode Factory class for reporting purposes.

I’m not sure about this. This is a side effect, and I try to avoid side effects. On the other hand, this makes some sense. The packet queue object calls the receive packet method, the receive packet method returns a packet to the packet queue. So it both is a side effect, in that the function that I’m calling does not return a value, but instead does something to a data structure belonging to another object. On the other hand, it isn’t a side effect, because from an object standpoint, one object sends an object and gets an object back.

Overthinking the aesthetics of your software is a productivity killer. So its ugly… does it work? Then its pretty enough, learn your lessons and move on.

hashes

Saturday, March 28th, 2009

This weekend, I have to install a sink and a toilet and a tub in my upstairs bathroom… that project needs to move forward ASAP. At the moment, I’m sick, which I just realized. Not surprisingly, I seem to have a cold of some kind.

Which is bad, I need to be at reasonable capacity this week.

Today, I rewrote the packet_queue to behave a little better and I think to use better ruby style. The new code looks like this


def run_sim(endTime)
   until @pheap.empty? || @pheap.first.timestamp > endTime
     @moment = @pheap.first.timestamp
     @packetlist = []
     until @pheap.empty? || (@moment != @pheap.first.timestamp)
       @packetlist.push(@pheap.shift)
     end
     @neighborhoods = Hash.new
     @packetlist.each {|x| puts x.sender}
     @packetlist.each {|x| @neighborhoods[x] = x.sender.get_neighbor_nodes(x.sigma)}
     collision_detect(@neighborhoods, @packetlist)
     @tlist = Hash.new
     until @packetlist.empty?
       @pak = @packetlist.shift
       @tlist[@pak] = []
       @neighborhoods[@pak].each {|x| @tlist[@pak] = @tlist[@pak] + x.translist}
     end
     @tlist.each_key{|key| @tlist[key].each{|x| @packetlist.push(x.receive_packet(Packet.new(key.timestamp, key.sender, key.sigma)))}}
     @packetlist.each{|x| put_packet(x)}
   end
end

The obvious tactic of using Hashes makes collision detection more sure footed, and the mapping helps to condense the code.

The only problem I have with this is that I would like to simplify this code further, and abstract it further so that it isn't associated with my algorithm. This core should be able to work with several algorithms simply and effectively, that's the goal.

This code is from revision ten, available at: http://simhoc.hg.sourceforge.net:8000/hgroot/simhoc

Even More Code!

Friday, March 27th, 2009

Bit of a tough chunk of coding last night, mostly because I misdiagnosed a problem and ended up spending more time trying to insure that I was passing arrays than I needed to.

So the event queue needs to detect collisions. Not in a PDES sort of way, but in the simulator itself. Two nights ago, I realized that packets don’t have an explicit receiver, so my strategy for detecting collision was going to have to be rewritten. Last night, I rewrote it.

So in the final product, two packets only collide if they are using the same channel. So far, I haven’t implemented channelization, I’m just building a basic simulation framework, so the method collides_with in is a one liner:
def collides_with(pak) return true; end. The code in the Packet Queue is a little more complex. The Problem is this: The queue goes through the following steps

  1. Get the first packet from the queue, and all following packets with the same time stamp
  2. For every packet, get the neighborhood of the sender
  3. Compare packets
  4. If two packets collide, remove any common nodes from the neighborhood associated with that packet
  5. Send the packets to the remaining nodes

And that collision detection part is tricky.

Right now, my code looks something like this:

def collision_detect(hoods, moments)
   colliders = []
   for k in 0..moments.size-2
     for i in k+1..moments.size-1
       if moments[k].will_collide(moments[i])
         colliders.push(hoods[k] & hoods[i])
         hoods[i] = hoods[i] - hoods[k]
       end
     end
     if !colliders.empty?
       colliders.flatten!
       colliders.uniq!
     end
     hoods[k] = hoods[k] - colliders
     colliders = []
   end
end

But I don’t think that is working the way I want it to, because my tests are coming back with no calls to any transceivers. This is a frustrating piece of code to test… partially because it doesn’t belong in this class, but mostly because I’m not sure when Ruby is going to return an empty array and when it is going to return nil. And this matters.

Something I noticed about that algorithm versus that code, though. So much of the algorithm is “Get some list, and do something to every item on the list” and yet the code contains no Array.map calls. So obviously I’m doing this wrong. And LISP might be a better language for event simulation than Ruby, because it might be easier to treat anything at all as an event, since all LISP code has the same syntax.

rewrite

Thursday, March 26th, 2009

Well, it was inevitable. First major conceptual mistake in SimpleHoc discovered last night.

For some reason, I was giving packets explicit receivers. This is wrong. Packets should have explicit senders, and, later, explicit destinations, but the immediate receiver is handled by the underlying channel selection event queue algorithm. Anyway, as a result of this, I was finding the neighborhood of local nodes, and then putting a packet in the event queue to be sent to all of those nodes.

This is a problem. It’s mostly a problem because the neighborhood of a node might change between the time the event is queued and the time that the event occurs. Unlikely with my sim, because it’s single threaded, but possible if I want to take this code over to the cluster and run a distributed/parallel version. Of course, I probably don’t want to write that in Ruby anyway…

Actually, I might. Maybe this is a rails app waiting to happen. That would be cool, and very appropriate for HiPC.

Anyway, I ended up realizing that what I want is to put a single packet on the queue, then let the queue choose who gets the packet when the packet is sent. I’m only partway through that rewrite. I hate running out of steam in the middle of a function. You just know you’ve lost an hour at least rebooting the brain, but as your body slows down, you hit this point of diminishing returns. Oy.

Anyway, I also added 200 lines of case statements, but I’ll spare you a look at the StateMachine module. There has to be a better way to do that.

mercurial repos: http://simhoc.hg.sourceforge.net:8000/hgroot/simhoc