Skip to content

Commit

Permalink
motherfucking debugger
Browse files Browse the repository at this point in the history
  • Loading branch information
Josep M. Bach committed Jan 12, 2013
1 parent 806c92d commit 84c720c
Show file tree
Hide file tree
Showing 40 changed files with 981 additions and 433 deletions.
6 changes: 6 additions & 0 deletions bin/tvm.c
Original file line number Original file line Diff line number Diff line change
@@ -1,12 +1,18 @@
#include <stdio.h> #include <stdio.h>
#include <terror/dbg.h> #include <terror/dbg.h>
#include <terror/bstrlib.h> #include <terror/bstrlib.h>
#include <terror/debugger.h>
#include <terror/vm.h> #include <terror/vm.h>


int Debug;

int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
bstring filename = bfromcstr(argv[1]); bstring filename = bfromcstr(argv[1]);
if(argc > 2 && strcmp(argv[2], "-d") == 0) {
Debug = 1;
}
VM_start(filename); VM_start(filename);
return 0; return 0;
} }
5 changes: 2 additions & 3 deletions compiler/kernel/beta.rb
Original file line number Original file line Diff line number Diff line change
@@ -1,13 +1,12 @@
# Vector#map Vector.map = -> fn {
VM.types[:vector].map = -> fn {
new = [] new = []
each(-> element { each(-> element {
new.push fn.apply(element) new.push fn.apply(element)
}) })
new new
} }


VM.types[:vector].length = -> fn { Vector.length = -> fn {
len = 0 len = 0
each(-> element { len += 1 }) each(-> element { len += 1 })
len len
Expand Down
4 changes: 3 additions & 1 deletion compiler/lib/terror.rb
Original file line number Original file line Diff line number Diff line change
@@ -1,6 +1,7 @@
require "terror/version" require "terror/version"
require "terror/core_ext/node" require "terror/core_ext/node"
require "terror/visitor" require "terror/visitor"
require 'pathname'


module Terror module Terror
def self.parse_file(file, verbose=false) def self.parse_file(file, verbose=false)
Expand All @@ -10,6 +11,7 @@ def self.parse_file(file, verbose=false)
puts visitor.generator.disassemble if verbose puts visitor.generator.disassemble if verbose
# Always return nil at the end of a script # Always return nil at the end of a script
visitor.generator.pushnil visitor.generator.pushnil
puts visitor.finalize(:main) puts Pathname.new(file).expand_path
puts visitor.finalize('0_main')
end end
end end
14 changes: 13 additions & 1 deletion compiler/lib/terror/generator.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class Generator
attr_accessor :children attr_accessor :children


def initialize(parent=nil) def initialize(parent=nil)
@current_line = -1
@children = [] @children = []
@parent = parent @parent = parent


Expand Down Expand Up @@ -40,6 +41,14 @@ def encode(name)
output output
end end


def setline(line)
if @current_line != line
@ip += 2
_setline line
@current_line = line
end
end

def push(value) def push(value)
@ip += 2 @ip += 2
_push literal(value) _push literal(value)
Expand Down Expand Up @@ -152,12 +161,15 @@ def local name
end end


def literal value def literal value
inspect = value.is_a?(Symbol) ? value.to_s.inspect : value.inspect
val = value.is_a?(Numeric) ? value : "\"#{value}" val = value.is_a?(Numeric) ? value : "\"#{value}"


@literals.index(val) or begin idx = @literals.index(val) || begin
@literals.push val @literals.push val
@literals.index(val) @literals.index(val)
end end

"#{idx} #{inspect}"
end end
end end
end end
1 change: 1 addition & 0 deletions compiler/lib/terror/instructions.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ def emit(instruction)


# op :opcode, value, arity # op :opcode, value, arity
op :noop, 0x00, 0 op :noop, 0x00, 0
op :setline, 0x01, 1


op :pushself, 0x10, 0 op :pushself, 0x10, 0
op :push, 0x11, 1 op :push, 0x11, 1
Expand Down
37 changes: 36 additions & 1 deletion compiler/lib/terror/visitor.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -5,57 +5,70 @@ module Terror
class Visitor class Visitor
attr_reader :generator attr_reader :generator


attr_accessor :linenum

def initialize(parent=nil) def initialize(parent=nil)
@generator = Generator.new(parent) @generator = Generator.new(parent)
@linenum = 0
@slots = {} @slots = {}
@fns = [] @fns = []
end end
alias_method :g, :generator alias_method :g, :generator


def name def name
@name ||= "block_#{SecureRandom.hex}" @name ||= "#{linenum}_block_#{SecureRandom.hex}"
end end


def fixnum_literal(node, parent) def fixnum_literal(node, parent)
setline(node)
g.push node.value g.push node.value
end end


def float_literal(node, parent) def float_literal(node, parent)
setline(node)
g.push node.value g.push node.value
end end


def local_variable_assignment(node, parent) def local_variable_assignment(node, parent)
setline(node)
node.value.lazy_visit self, node node.value.lazy_visit self, node
g.setlocal node.name g.setlocal node.name
end end


def local_variable_access(node, parent) def local_variable_access(node, parent)
setline(node)
g.pushlocal node.name g.pushlocal node.name
end end


def block(node, parent) def block(node, parent)
setline(node)
node.array.each do |expression| node.array.each do |expression|
expression.lazy_visit self, node expression.lazy_visit self, node
end end
end end


def nil_literal(node, parent) def nil_literal(node, parent)
setline(node)
g.pushnil g.pushnil
end end


def true_literal(node, parent) def true_literal(node, parent)
setline(node)
g.pushtrue g.pushtrue
end end


def false_literal(node, parent) def false_literal(node, parent)
setline(node)
g.pushfalse g.pushfalse
end end


def string_literal(node, parent) def string_literal(node, parent)
setline(node)
g.push node.string g.push node.string
end end


def send(node, parent) def send(node, parent)
setline(node)
if node.receiver.respond_to?(:name) && @slots[node.receiver.name] && @slots[node.receiver.name].include?(node.name) if node.receiver.respond_to?(:name) && @slots[node.receiver.name] && @slots[node.receiver.name].include?(node.name)
return slot_retrieval(node, parent) return slot_retrieval(node, parent)
end end
Expand All @@ -69,7 +82,9 @@ def send(node, parent)
end end


def defn(block) def defn(block)
setline(block)
visitor = Visitor.new(g) visitor = Visitor.new(g)
visitor.linenum = block.line
block.arguments.names.each do |arg| block.arguments.names.each do |arg|
# vivify arguments as locals # vivify arguments as locals
visitor.g.scope.new_local(arg) visitor.g.scope.new_local(arg)
Expand All @@ -80,6 +95,7 @@ def defn(block)
end end


def send_with_arguments(node, parent) def send_with_arguments(node, parent)
setline(node)
node.receiver.lazy_visit self, node node.receiver.lazy_visit self, node
argc = node.arguments.array.count argc = node.arguments.array.count
node.arguments.lazy_visit self node.arguments.lazy_visit self
Expand All @@ -88,16 +104,19 @@ def send_with_arguments(node, parent)
end end


def actual_arguments(node, parent) def actual_arguments(node, parent)
setline(node)
node.array.each do |argument| node.array.each do |argument|
argument.lazy_visit(self, parent) argument.lazy_visit(self, parent)
end end
end end


def self(node, parent) def self(node, parent)
setline(node)
g.pushself g.pushself
end end


def if(node, parent) def if(node, parent)
setline(node)
node.condition.lazy_visit(self, parent) node.condition.lazy_visit(self, parent)


body_val = else_val = nil body_val = else_val = nil
Expand All @@ -118,11 +137,13 @@ def if(node, parent)
end end


def slot_retrieval(node, parent) def slot_retrieval(node, parent)
setline(node)
node.receiver.lazy_visit self node.receiver.lazy_visit self
g.getslot node.name g.getslot node.name
end end


def attribute_assignment(node, parent) def attribute_assignment(node, parent)
setline(node)
receiver_name = if node.receiver.is_a?(Rubinius::AST::Self) receiver_name = if node.receiver.is_a?(Rubinius::AST::Self)
:self :self
else else
Expand All @@ -138,6 +159,7 @@ def attribute_assignment(node, parent)
end end


def constant_assignment(node, parent) def constant_assignment(node, parent)
setline(node)
receiver_name = :lobby receiver_name = :lobby
attribute_name = node.constant.name.to_sym attribute_name = node.constant.name.to_sym
@slots[receiver_name] ||= [] @slots[receiver_name] ||= []
Expand All @@ -149,6 +171,7 @@ def constant_assignment(node, parent)
end end


def element_assignment(node, parent) def element_assignment(node, parent)
setline(node)
receiver_name = if node.receiver.is_a?(Rubinius::AST::Self) receiver_name = if node.receiver.is_a?(Rubinius::AST::Self)
:self :self
else else
Expand All @@ -164,17 +187,20 @@ def element_assignment(node, parent)
end end


def array_literal(node, parent) def array_literal(node, parent)
setline(node)
node.body.reverse.each do |element| node.body.reverse.each do |element|
element.lazy_visit self element.lazy_visit self
end end
g.makevec node.body.count g.makevec node.body.count
end end


def empty_array(node, parent) def empty_array(node, parent)
setline(node)
g.makevec 0 g.makevec 0
end end


def hash_literal(node, parent) def hash_literal(node, parent)
setline(node)
node.array.reverse.each do |element| node.array.reverse.each do |element|
element.lazy_visit self element.lazy_visit self
end end
Expand All @@ -184,15 +210,18 @@ def hash_literal(node, parent)
end end


def symbol_literal(node, parent) def symbol_literal(node, parent)
setline(node)
g.push node.value g.push node.value
end end


def constant_access(node, parent) def constant_access(node, parent)
setline(node)
g.pushlobby g.pushlobby
g.getslot node.name g.getslot node.name
end end


def or(node, parent) def or(node, parent)
setline(node)
node.left.lazy_visit self node.left.lazy_visit self
node.right.lazy_visit self node.right.lazy_visit self
g.send_message :or, 1 g.send_message :or, 1
Expand All @@ -203,6 +232,12 @@ def finalize(name)
fns = @fns.map { |fn| fn.finalize(fn.name) } fns = @fns.map { |fn| fn.finalize(fn.name) }
[out, fns].flatten.join("\n") [out, fns].flatten.join("\n")
end end

private

def setline(node)
g.setline(node.line)
end
end end
end end


6 changes: 6 additions & 0 deletions compiler/test/terror/generator_test.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ module Terror
end end
end end


describe '#setline' do
it 'sets the current file line' do
@g.setline(3)
end
end

describe '#push' do describe '#push' do
it 'pushes an integer literal to the stack' do it 'pushes an integer literal to the stack' do
@g.push(3) @g.push(3)
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/terror/instructions_test.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ module Terror
end end


describe 'instructions with 1 operand' do describe 'instructions with 1 operand' do
%w(push pushlocal setlocal jmp jif jit getslot setslot makevec).each do |instruction| %w(setline push pushlocal setlocal jmp jif jit getslot setslot makevec).each do |instruction|
describe instruction do describe instruction do
it "#{instruction} is encoded correctly" do it "#{instruction} is encoded correctly" do
inst = @g.__send__ "_#{instruction}", 2 inst = @g.__send__ "_#{instruction}", 2
Expand Down
2 changes: 2 additions & 0 deletions compiler/test/terror/visitor_test.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ def visit(code)


def compiles(code, &block) def compiles(code, &block)
g = Generator.new g = Generator.new
g.setline 1
g.instance_eval(&block) g.instance_eval(&block)
visit(code).instructions.must_equal g.instructions visit(code).instructions.must_equal g.instructions
end end


def compiles_block(code, &block) def compiles_block(code, &block)
g = Generator.new g = Generator.new
g.setline 1
g.instance_eval(&block) g.instance_eval(&block)
visit(code).children.first.instructions.must_equal g.instructions visit(code).children.first.instructions.must_equal g.instructions
end end
Expand Down
Loading

0 comments on commit 84c720c

Please sign in to comment.