Class: RubyLabs::MARSLab::Warrior

Inherits:
Object
  • Object
show all
Defined in:
lib/marslab.rb

Overview

Warrior

A Warrior is a core warrior – an object of this class is a simple struct that has the program name, assembled code, the starting location, and the symbol table.

A static method (Warrior.load) will load an assembled Warrior into memory, making sure the max number of programs is not exceeded. The addr attribute is set to the starting location of the program when it is loaded.

Constant Summary collapse

@@in_use =
Array.new

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename) ⇒ Warrior

Create a new Warrior by reading and assembling the instructions in filename. The code array is empty if there are any assembly errors.



359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/marslab.rb', line 359

def initialize(filename)
  if filename.class == Symbol
    filename = File.join(@@marsDirectory, filename.to_s + ".txt")
  end

  if ! File.exists?(filename)
    raise "Can't find file: #{filename}"
  end

  @name, @code, @symbols, @errors = MARS.assemble( File.open(filename).readlines )

  if @errors.length > 0
    puts "Syntax errors in #{filename}:"
    puts errors
    @code.clear
  end
end

Instance Attribute Details

#codeObject (readonly)

Returns the value of attribute code.



354
355
356
# File 'lib/marslab.rb', line 354

def code
  @code
end

#errorsObject (readonly)

Returns the value of attribute errors.



354
355
356
# File 'lib/marslab.rb', line 354

def errors
  @errors
end

#nameObject (readonly)

Returns the value of attribute name.



354
355
356
# File 'lib/marslab.rb', line 354

def name
  @name
end

#symbolsObject (readonly)

Returns the value of attribute symbols.



354
355
356
# File 'lib/marslab.rb', line 354

def symbols
  @symbols
end

Class Method Details

.load(app, addr = :random) ⇒ Object

Load the code for the Warrior object reference by app into the MARS main memory. If an address is specified, load that code starting at that location, otherwise choose a random location. The memory addresses used by the program are recorded so programs aren’t accidentally loaded on top of each other.



390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
# File 'lib/marslab.rb', line 390

def Warrior.load(app, addr = :random)
  if app.class != Warrior
    puts "Argument must be a Warrior object, not a #{app.class}"
    return nil
  end
 
  if @@entries.length == @@maxEntries
    puts "Maximum #{@@maxEntries} programs can be loaded at one time"
    return nil
  end
  
  if addr == :random
    loop do
      addr = rand(@@mem.size)
      break if Warrior.check_loc(addr, addr + app.code.length - 1)
    end
  else
    if ! Warrior.check_loc(addr, addr + app.code.length - 1)
      puts "Address #{addr} too close to another program; #{app.name} not loaded"
      return nil
    end
  end
  
  loc = addr
  app.code.each do |x|
    @@mem.store(loc, x)
    loc = (loc + 1) % @@mem.size
  end

  id = @@entries.length
  @@pcs << PC.new(id, addr + app.symbols[:start])
  @@entries << app
  
  # save the range of memory locations reserved by this app
  
  lb = addr - @@params[:buffer]
  ub = addr + app.code.length + @@params[:buffer] - 1
  if lb < 0
    @@in_use << ( 0 .. (addr+app.code.length-1) )
    @@in_use << ( (@@params[:memSize] + lb) .. (@@params[:memSize]-1) )
  elsif ub > @@params[:memSize]
    @@in_use << ( addr .. (@@params[:memSize]-1) )
    @@in_use << ( 0 .. (ub - @@params[:memSize]) )
  else
    @@in_use << (lb..ub)
  end
  
  return addr
end

.resetObject

Clear the data structure that records which memory locations are in use, allowing new programs to be loaded into any location.



445
446
447
# File 'lib/marslab.rb', line 445

def Warrior.reset
  @@in_use = Array.new
end

Instance Method Details

#inspectObject Also known as: to_s

Create a string with essential information about this object.



379
380
381
# File 'lib/marslab.rb', line 379

def inspect
  sprintf "Name: #{@name} Code: #{@code.inspect}"
end