Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Learning Ruby, was a C geek...

Reply
Thread Tools

Learning Ruby, was a C geek...

 
 
Nicholas Paul Johnson
Guest
Posts: n/a
 
      04-02-2004
Hello all,

As I'm learning Ruby, I've decided to write a few programs in Ruby to get
a feel for the language.

I've been a C programmer for a long time. As such, I worry that I'm
thinking too much like a C programmer, and not like a Ruby programmer...

My first attempt has been an emulator for a cs-toy processor called IBCM
(itty-bitty computing machine). Its spec (only 5 pages) is available at:
http://www.cs.virginia.edu/~cs216/notes/ibcm-poo.pdf

I've written it, and it works correctly when compared to my program
written in C, but at its core is a large case-when-end statement.
This is not `sexy.' I was wondering if there was a better way to do
this in Ruby, or if I'm just missing the point.

My code is at: http://manjac.ath.cx/nick/ruby-ibcm.rb

Thanks all,
--
Nicholas Paul Johnson
nickjohnsonSPAM^H^H^H^(E-Mail Removed)
http://manjac.ath.cx/nick
_
( ) ascii ribbon campaign - against html mail
X - against microsoft attachments
/ \ http://www.google.com/search?q=ascii+ribbon
--




 
Reply With Quote
 
 
 
 
Chris Dutton
Guest
Posts: n/a
 
      04-03-2004
A few suggestions, if I may.

I wonder if your option detection might be more efficient as:

trace = true if ARGV.include? "-t"
dump = true if ARGV.include? "-d"
filenames = ARGV.delete_if { |n| n !~ /^[^-]/ }
fn = filenames.empty? ? nil : filenames.first

It would save you from looping through ARGV, just in case it's a mile
long or something.

 
Reply With Quote
 
 
 
 
Asim Jalis
Guest
Posts: n/a
 
      04-03-2004
On Sat, Apr 03, 2004 at 09:19:19AM +0900, Chris Dutton wrote:
> A few suggestions, if I may.
>
> I wonder if your option detection might be more efficient as:
>
> trace = true if ARGV.include? "-t"
> dump = true if ARGV.include? "-d"
> filenames = ARGV.delete_if { |n| n !~ /^[^-]/ }
> fn = filenames.empty? ? nil : filenames.first
>
> It would save you from looping through ARGV, just in case it's
> a mile long or something.


Another suggestion would be to remove the trace statements, which
clutter up the code. Instead use unit tests to ensure correctness.


Asim


 
Reply With Quote
 
Gregory Millam
Guest
Posts: n/a
 
      04-03-2004
Received: Sat, 3 Apr 2004 08:37:54 +0900
And lo, Nicholas wrote:

> I've written it, and it works correctly when compared to my program
> written in C, but at its core is a large case-when-end statement.
> This is not `sexy.' I was wondering if there was a better way to do
> this in Ruby, or if I'm just missing the point.


This is a project similar in scope to an NES emulator I've written in C. When doing so, I tried and benchmarked 2 situations:

switch (opcode) {
case 0x01:
case 0x02 ... (etc, for every opcode)
}

And:
typedef void (*operand)(address);
operand opcodes[0x100]; (You'd use 0x10)
op_0x01(int address) { ... }
opcodes[0x01] = op_0x01.
Then call using: opcodes[0x01](addr);

Ruby caters to the second style rather well, adding in lambda blocks.

ops = []
ops[0x01] = lambda { /* incrememnt accum 1 */ |address| Cpu.accum += 1 }

Either a hash or an array could do the job.

You'd really just need to fetch op[instruction byte 1 >> 4], if I'm reading that specs document correctly.

Hope that helps

- Greg Millam


 
Reply With Quote
 
daz
Guest
Posts: n/a
 
      04-03-2004

Nicholas Paul Johnson wrote:
> Hello all,
>
> As I'm learning Ruby, I've decided to write a few programs in Ruby to get
> a feel for the language.
>
> I've been a C programmer for a long time. As such, I worry that I'm
> thinking too much like a C programmer, and not like a Ruby programmer...
>
> I've written it, and it works correctly when compared to my program
> written in C, but at its core is a large case-when-end statement.
> This is not 'sexy'.
>


Hi Nicholas,

Technically, case isn't as sexy in Ruby as switch is in C, but I think
many Rubyists would use it the way you have done in this example.

The rest of your code suggests to me that you are on the correct path.

Welcome here !


daz




 
Reply With Quote
 
Gregory Millam
Guest
Posts: n/a
 
      04-03-2004
Received: Sat, 3 Apr 2004 15:26:46 +0900
And lo, Nicholas wrote:

> While were on the subject, what is technically the difference between some
> block, such as { |n| 1+n }, and the corresponding lambda { |n| 1+n }, or
> more specifically, how does the interpreter treat them differently? Also,
> could I assign a lambda to a variable as I would in scheme to create a
> function?


They're the same thing. The following two are identical

myproc = lambda { |n| 1+n }
mymethod("5",lambda)

mymethod("5") { |n| 1+n }

You could then call
myproc.call("4") #-> 5

So to continue with the opcode hash example
op[0x05] = lambda { |addr| ... }
op[0x05].call(address)

the 'lambda' is needed to let ruby know it's defining a Proc object.

c = { |n| 1+n } - doesn't really make sense.

'proc' is an alias for lambda, but I believe it's to be phased out because of proc/Proc confusin. and lambda is really just "Proc.new"

c = Proc.new { |n| 1+n }

These blocks, with 'yield,' are among my favorite things about ruby. =).

- Greg


 
Reply With Quote
 
Phil Tomson
Guest
Posts: n/a
 
      04-03-2004
In article <(E-Mail Removed)>,
Nicholas Paul Johnson <(E-Mail Removed)> wrote:
>Hello all,
>
>As I'm learning Ruby, I've decided to write a few programs in Ruby to get
>a feel for the language.
>
>I've been a C programmer for a long time. As such, I worry that I'm
>thinking too much like a C programmer, and not like a Ruby programmer...
>
>My first attempt has been an emulator for a cs-toy processor called IBCM
>(itty-bitty computing machine). Its spec (only 5 pages) is available at:
>http://www.cs.virginia.edu/~cs216/notes/ibcm-poo.pdf
>
>I've written it, and it works correctly when compared to my program
>written in C, but at its core is a large case-when-end statement.
>This is not `sexy.' I was wondering if there was a better way to do
>this in Ruby, or if I'm just missing the point.
>
>My code is at: http://manjac.ath.cx/nick/ruby-ibcm.rb
>


One thing I notice about your code that seems very C-ish is that you use
only integers as options for your case statements. Ruby's case
statements are a lot more flexible than C's switch. (Maybe you need to do
this because you're reading & executing a binary file of IBCM code.) If
you'd rather work at a higher level of abstraction with assembly code you
could perhaps do something like:


case opcode
when :halt
#do halt stuff
when :and
#do and stuff
when ...
end



Or perhaps you could even define a set of opcode classes that each
ecapsulate the bahavior of each opcode. Then instead of a case statement
you could just call a 'execute' (or whatever you want to call it) on each
statement that you read, so it would look something like:

class Machine
include Singleton
attr_accessor :accum
def initialize
@accum = 0
#define registers, states of the machine here
end
end

class Add
def initialize(value)
@value=value
@machine = Machine.instance
end
def execute
@machine.accum += value #scope of accum is an issue here, of course
end
def to_code #so you can convert the mnemonic to a code
5 #this gives you an assembler for free, but I'm not sure

end
end

def Add(value)
Add.new(value)
end

#...main loop

File.foreach("IBCM.program"){ |line| #no more case statement
op = eval(line.strip)
op.execute #or if you want to convert to machine code: op.to_code
}


#contents of IBCM.program:

Load(0x55)
Add(2)
And(0xFF)
Xor(0x0F)
#....


So then your IBCM.program files are actually valid Ruby code.


....but then again, if you've got to read in binary data anyway,
maybe it wouldn't make sense to do it this way.

Phil
 
Reply With Quote
 
Mark Sparshatt
Guest
Posts: n/a
 
      04-03-2004
Nicholas Paul Johnson wrote:

>Hello all,
>
>As I'm learning Ruby, I've decided to write a few programs in Ruby to get
>a feel for the language.
>
>I've been a C programmer for a long time. As such, I worry that I'm
>thinking too much like a C programmer, and not like a Ruby programmer...
>
>My first attempt has been an emulator for a cs-toy processor called IBCM
>(itty-bitty computing machine). Its spec (only 5 pages) is available at:
>http://www.cs.virginia.edu/~cs216/notes/ibcm-poo.pdf
>
>I've written it, and it works correctly when compared to my program
>written in C, but at its core is a large case-when-end statement.
>This is not `sexy.' I was wondering if there was a better way to do
>this in Ruby, or if I'm just missing the point.
>
>My code is at: http://manjac.ath.cx/nick/ruby-ibcm.rb
>
>Thanks all,
>
>

I haven't got any advice over what everyone else has suggested for the
layout of your program but I have spotted a couple of bugs.

Firstly the read word instruction doesn't work. It either doesn't take
any input or if you run the program with the trace option it gives an
error no such file or directory - -t

changing the line
accum = gets.to_i

to

accum = $stdin.gets.to_i

fixes this

The other problem is the JUMPL instruction jumps even if the acummalator
isn't less than 0. The problem is in this line

progcount = off if accum & 0x8000

since 0 is a true value in Ruby the part accum & 0x8000 is always true.
You need to change it to

progcount = off if (accum & ox8000 != 0)

--
Mark Sparshatt





 
Reply With Quote
 
Kent S.
Guest
Posts: n/a
 
      04-03-2004
lambda is almost the same thing as Proc.new. Consider this:

irb(main):001:0> l = lambda{ break }
=> #<Proc:0x00372bf4@(irb):1>
irb(main):002:0> l.call
=> nil
irb(main):003:0> p = Proc.new { break }
=> #<Proc:0x00366cdc@(irb):3>
irb(main):004:0> p.call
LocalJumpError: break from proc-closure
from (irb):3:in `call'
from (irb):4

Cheers,
Kent

On Apr 3, 2004, at 2:43 AM, Gregory Millam wrote:
>
> 'proc' is an alias for lambda, but I believe it's to be phased out
> because of proc/Proc confusin. and lambda is really just "Proc.new"
>
> c = Proc.new { |n| 1+n }
>
> These blocks, with 'yield,' are among my favorite things about ruby.
> =).
>
> - Greg
>



Cheers,
Kent.



 
Reply With Quote
 
Ara.T.Howard
Guest
Posts: n/a
 
      04-03-2004
On Sun, 4 Apr 2004, Kent S. wrote:

> lambda is almost the same thing as Proc.new. Consider this:


can you elaborate for those of us who are seeing double after a really long
week?

-a
--
================================================== =============================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| URL :: http://www.ngdc.noaa.gov/stp/
| TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done
================================================== =============================

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[I'm learning C]: Learning to use ucontext Andrey Popp C Programming 5 01-31-2012 01:05 AM
Learning C and Learning Make/Configure/Building/Linking Hal Vaughan C Programming 7 03-21-2006 05:07 PM
e-learning, (collaborative learning environment) collinm Java 1 09-08-2005 09:52 PM
Learning about SMS technology... VM Wireless Networking 2 07-02-2004 02:36 PM
learning VHDL Vilvox VHDL 5 07-20-2003 08:59 AM



Advertisments