Skip to content

Commit

Permalink
Add clear instruction
Browse files Browse the repository at this point in the history
  • Loading branch information
Josep M. Bach committed Feb 2, 2013
1 parent f2d7a6b commit 5ac64c9
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 95 deletions.
42 changes: 36 additions & 6 deletions compiler/lib/terror/generator.rb
Expand Up @@ -6,7 +6,7 @@ module Terror
class Generator
include Instructions
include Branching
attr_reader :literals, :scope, :ip, :parent
attr_reader :literals, :scope, :ip, :parent, :stack_size
attr_accessor :children

def initialize(parent=nil)
Expand All @@ -21,8 +21,9 @@ def initialize(parent=nil)
@scope = Scope.new
end

@literals = []
@ip = 0
@stack_size = 0
@literals = []
@ip = 0
end

def disassemble
Expand Down Expand Up @@ -50,13 +51,19 @@ def setline(line)
end

def push(value)
inc
@ip += 2
_push literal(value)
end

def pop
@ip += 1
_pop
def pop(count)
@ip += 2
_pop count
end

def clear(count)
@ip += 2
_clear count
end

def pushtrue
Expand All @@ -81,28 +88,33 @@ def jmp(label)
end

def jif(label)
dec
@ip += 2
label.start!
_jif label
end

def jit(label)
dec
@ip += 2
label.start!
_jit label
end

def pushself
inc
@ip += 1
_pushself
end

def pushlobby
inc
@ip += 1
_pushlobby
end

def pushlocal(name)
inc
l = local(name)
if l.depth > 0
@ip += 3
Expand Down Expand Up @@ -130,21 +142,25 @@ def getslot(name)
end

def setslot(name)
dec
@ip += 2
_setslot literal(name)
end

def send_message(msg, argc)
argc.times { dec }
@ip += 3
_send literal(msg), argc
end

def defn(name)
inc
@ip += 2
_defn literal(name)
end

def makevec(count)
(count-1).times { dec }
@ip += 2
_makevec count
end
Expand All @@ -154,8 +170,22 @@ def ret
_ret
end

def clear_stack
extra = @stack_size - 1
@stack_size = 1
clear extra
end

private

def inc
@stack_size += 1
end

def dec
@stack_size -= 1
end

def local name
@scope.search_local(name)
end
Expand Down
3 changes: 2 additions & 1 deletion compiler/lib/terror/instructions.rb
Expand Up @@ -130,9 +130,10 @@ def emit(instruction)
op :getslot, 0x40, 1
op :setslot, 0x41, 1

op :pop, 0x42, 0
op :pop, 0x42, 1
op :defn, 0x43, 1
op :makevec, 0x44, 1
op :clear, 0x45, 1

op :send, 0x80, 2
op :ret, 0x90, 0
Expand Down
1 change: 1 addition & 0 deletions compiler/lib/terror/visitor.rb
Expand Up @@ -229,6 +229,7 @@ def or(node, parent)
end

def finalize(name)
g.clear_stack
out = g.encode(name)
fns = @fns.map { |fn| fn.finalize(fn.name) }
[out, fns].flatten.join("\n")
Expand Down
12 changes: 12 additions & 0 deletions compiler/test/terror/generator_test.rb
Expand Up @@ -136,6 +136,18 @@ module Terror
end
end

describe '#pop' do
it 'pops n elements off the stack' do
@g.pop 3
end
end

describe '#clear' do
it 'clears n elements right below the top of the stack' do
@g.clear 3
end
end

describe '#ret' do
it 'returns from the active call frame' do
@g.ret
Expand Down
4 changes: 2 additions & 2 deletions compiler/test/terror/instructions_test.rb
Expand Up @@ -23,7 +23,7 @@ module Terror
end

describe 'instructions with 1 operand' do
%w(setline push pushlocal setlocal jmp jif jit getslot setslot makevec).each do |instruction|
%w(setline push pushlocal setlocal jmp jif jit getslot pop setslot makevec).each do |instruction|
describe instruction do
it "#{instruction} is encoded correctly" do
inst = @g.__send__ "_#{instruction}", 2
Expand All @@ -37,7 +37,7 @@ module Terror
end

describe 'instructions with no operands' do
%w(noop pushself pushlobby pushtrue pushfalse pushnil pop ret dump).each do |instruction|
%w(noop pushself pushlobby pushtrue pushfalse pushnil ret dump).each do |instruction|
describe instruction do
it "#{instruction} is encoded correctly" do
inst = @g.__send__ :"_#{instruction}"
Expand Down

0 comments on commit 5ac64c9

Please sign in to comment.