Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

motherfucking debugger

  • Loading branch information...
commit 84c720c08c177d07804e3996ecdd8818ded8634d 1 parent 806c92d
@txus authored
Showing with 981 additions and 433 deletions.
  1. +6 −0 bin/tvm.c
  2. +2 −3 compiler/kernel/beta.rb
  3. +3 −1 compiler/lib/terror.rb
  4. +13 −1 compiler/lib/terror/generator.rb
  5. +1 −0  compiler/lib/terror/instructions.rb
  6. +36 −1 compiler/lib/terror/visitor.rb
  7. +6 −0 compiler/test/terror/generator_test.rb
  8. +1 −1  compiler/test/terror/instructions_test.rb
  9. +2 −0  compiler/test/terror/visitor_test.rb
  10. +28 −13 examples/functions.tvm
  11. +28 −17 examples/hello_world.tvm
  12. +13 −8 examples/maps.tvm
  13. +15 −12 examples/numbers.tvm
  14. +52 −25 examples/objects.tvm
  15. +43 −24 examples/vectors.tvm
  16. +243 −194 kernel/alpha.tvm
  17. +53 −49 kernel/beta.tvm
  18. +15 −0 src/terror/bootstrap.c
  19. +11 −0 src/terror/call_frame.c
  20. +2 −0  src/terror/call_frame.h
  21. +158 −0 src/terror/debugger.c
  22. +45 −0 src/terror/debugger.h
  23. +61 −0 src/terror/file_utils.c
  24. +16 −0 src/terror/file_utils.h
  25. +13 −5 src/terror/function.c
  26. +5 −3 src/terror/function.h
  27. +20 −52 src/terror/input_reader.c
  28. +1 −0  src/terror/input_reader.h
  29. +1 −0  src/terror/opcode.h
  30. +4 −4 src/terror/primitives.c
  31. +1 −0  src/terror/state.c
  32. +3 −0  src/terror/state.h
  33. +1 −2  src/terror/value.c
  34. +41 −13 src/terror/vm.c
  35. +2 −0  src/terror/vm.h
  36. +28 −0 tests/file_utils_tests.c
  37. +2 −2 tests/input_reader_tests.c
  38. +3 −2 tests/testfile.tvm
  39. +1 −1  tests/value_tests.c
  40. +2 −0  tests/vm_tests.c
View
6 bin/tvm.c
@@ -1,12 +1,18 @@
#include <stdio.h>
#include <terror/dbg.h>
#include <terror/bstrlib.h>
+#include <terror/debugger.h>
#include <terror/vm.h>
+int Debug;
+
int
main(int argc, char *argv[])
{
bstring filename = bfromcstr(argv[1]);
+ if(argc > 2 && strcmp(argv[2], "-d") == 0) {
+ Debug = 1;
+ }
VM_start(filename);
return 0;
}
View
5 compiler/kernel/beta.rb
@@ -1,5 +1,4 @@
-# Vector#map
-VM.types[:vector].map = -> fn {
+Vector.map = -> fn {
new = []
each(-> element {
new.push fn.apply(element)
@@ -7,7 +6,7 @@
new
}
-VM.types[:vector].length = -> fn {
+Vector.length = -> fn {
len = 0
each(-> element { len += 1 })
len
View
4 compiler/lib/terror.rb
@@ -1,6 +1,7 @@
require "terror/version"
require "terror/core_ext/node"
require "terror/visitor"
+require 'pathname'
module Terror
def self.parse_file(file, verbose=false)
@@ -10,6 +11,7 @@ def self.parse_file(file, verbose=false)
puts visitor.generator.disassemble if verbose
# Always return nil at the end of a script
visitor.generator.pushnil
- puts visitor.finalize(:main)
+ puts Pathname.new(file).expand_path
+ puts visitor.finalize('0_main')
end
end
View
14 compiler/lib/terror/generator.rb
@@ -10,6 +10,7 @@ class Generator
attr_accessor :children
def initialize(parent=nil)
+ @current_line = -1
@children = []
@parent = parent
@@ -40,6 +41,14 @@ def encode(name)
output
end
+ def setline(line)
+ if @current_line != line
+ @ip += 2
+ _setline line
+ @current_line = line
+ end
+ end
+
def push(value)
@ip += 2
_push literal(value)
@@ -152,12 +161,15 @@ def local name
end
def literal value
+ inspect = value.is_a?(Symbol) ? value.to_s.inspect : value.inspect
val = value.is_a?(Numeric) ? value : "\"#{value}"
- @literals.index(val) or begin
+ idx = @literals.index(val) || begin
@literals.push val
@literals.index(val)
end
+
+ "#{idx} #{inspect}"
end
end
end
View
1  compiler/lib/terror/instructions.rb
@@ -109,6 +109,7 @@ def emit(instruction)
# op :opcode, value, arity
op :noop, 0x00, 0
+ op :setline, 0x01, 1
op :pushself, 0x10, 0
op :push, 0x11, 1
View
37 compiler/lib/terror/visitor.rb
@@ -5,57 +5,70 @@ module Terror
class Visitor
attr_reader :generator
+ attr_accessor :linenum
+
def initialize(parent=nil)
@generator = Generator.new(parent)
+ @linenum = 0
@slots = {}
@fns = []
end
alias_method :g, :generator
def name
- @name ||= "block_#{SecureRandom.hex}"
+ @name ||= "#{linenum}_block_#{SecureRandom.hex}"
end
def fixnum_literal(node, parent)
+ setline(node)
g.push node.value
end
def float_literal(node, parent)
+ setline(node)
g.push node.value
end
def local_variable_assignment(node, parent)
+ setline(node)
node.value.lazy_visit self, node
g.setlocal node.name
end
def local_variable_access(node, parent)
+ setline(node)
g.pushlocal node.name
end
def block(node, parent)
+ setline(node)
node.array.each do |expression|
expression.lazy_visit self, node
end
end
def nil_literal(node, parent)
+ setline(node)
g.pushnil
end
def true_literal(node, parent)
+ setline(node)
g.pushtrue
end
def false_literal(node, parent)
+ setline(node)
g.pushfalse
end
def string_literal(node, parent)
+ setline(node)
g.push node.string
end
def send(node, parent)
+ setline(node)
if node.receiver.respond_to?(:name) && @slots[node.receiver.name] && @slots[node.receiver.name].include?(node.name)
return slot_retrieval(node, parent)
end
@@ -69,7 +82,9 @@ def send(node, parent)
end
def defn(block)
+ setline(block)
visitor = Visitor.new(g)
+ visitor.linenum = block.line
block.arguments.names.each do |arg|
# vivify arguments as locals
visitor.g.scope.new_local(arg)
@@ -80,6 +95,7 @@ def defn(block)
end
def send_with_arguments(node, parent)
+ setline(node)
node.receiver.lazy_visit self, node
argc = node.arguments.array.count
node.arguments.lazy_visit self
@@ -88,16 +104,19 @@ def send_with_arguments(node, parent)
end
def actual_arguments(node, parent)
+ setline(node)
node.array.each do |argument|
argument.lazy_visit(self, parent)
end
end
def self(node, parent)
+ setline(node)
g.pushself
end
def if(node, parent)
+ setline(node)
node.condition.lazy_visit(self, parent)
body_val = else_val = nil
@@ -118,11 +137,13 @@ def if(node, parent)
end
def slot_retrieval(node, parent)
+ setline(node)
node.receiver.lazy_visit self
g.getslot node.name
end
def attribute_assignment(node, parent)
+ setline(node)
receiver_name = if node.receiver.is_a?(Rubinius::AST::Self)
:self
else
@@ -138,6 +159,7 @@ def attribute_assignment(node, parent)
end
def constant_assignment(node, parent)
+ setline(node)
receiver_name = :lobby
attribute_name = node.constant.name.to_sym
@slots[receiver_name] ||= []
@@ -149,6 +171,7 @@ def constant_assignment(node, parent)
end
def element_assignment(node, parent)
+ setline(node)
receiver_name = if node.receiver.is_a?(Rubinius::AST::Self)
:self
else
@@ -164,6 +187,7 @@ def element_assignment(node, parent)
end
def array_literal(node, parent)
+ setline(node)
node.body.reverse.each do |element|
element.lazy_visit self
end
@@ -171,10 +195,12 @@ def array_literal(node, parent)
end
def empty_array(node, parent)
+ setline(node)
g.makevec 0
end
def hash_literal(node, parent)
+ setline(node)
node.array.reverse.each do |element|
element.lazy_visit self
end
@@ -184,15 +210,18 @@ def hash_literal(node, parent)
end
def symbol_literal(node, parent)
+ setline(node)
g.push node.value
end
def constant_access(node, parent)
+ setline(node)
g.pushlobby
g.getslot node.name
end
def or(node, parent)
+ setline(node)
node.left.lazy_visit self
node.right.lazy_visit self
g.send_message :or, 1
@@ -203,6 +232,12 @@ def finalize(name)
fns = @fns.map { |fn| fn.finalize(fn.name) }
[out, fns].flatten.join("\n")
end
+
+ private
+
+ def setline(node)
+ g.setline(node.line)
+ end
end
end
View
6 compiler/test/terror/generator_test.rb
@@ -22,6 +22,12 @@ module Terror
end
end
+ describe '#setline' do
+ it 'sets the current file line' do
+ @g.setline(3)
+ end
+ end
+
describe '#push' do
it 'pushes an integer literal to the stack' do
@g.push(3)
View
2  compiler/test/terror/instructions_test.rb
@@ -23,7 +23,7 @@ module Terror
end
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
it "#{instruction} is encoded correctly" do
inst = @g.__send__ "_#{instruction}", 2
View
2  compiler/test/terror/visitor_test.rb
@@ -15,12 +15,14 @@ def visit(code)
def compiles(code, &block)
g = Generator.new
+ g.setline 1
g.instance_eval(&block)
visit(code).instructions.must_equal g.instructions
end
def compiles_block(code, &block)
g = Generator.new
+ g.setline 1
g.instance_eval(&block)
visit(code).children.first.instructions.must_equal g.instructions
end
View
41 examples/functions.tvm
@@ -1,45 +1,60 @@
-_main
-:5:25
+/Users/txus/Code/terrorvm/compiler/examples/functions.rb
+_0_main
+:5:37
123
-"block_9f8765f64c42ec0b2c499597d199b177
+"3_block_bf084d8f8eaa49a9bbfc20e2bc845fd0
"fn
2
"puts
+1 SETLINE
+1
17 PUSH
-0
+0 123
33 SETLOCAL
0
+1 SETLINE
+2
17 PUSH
-0
+0 123
33 SETLOCAL
1
+1 SETLINE
+3
+1 SETLINE
+7
16 PUSHSELF
+1 SETLINE
+3
67 DEFN
-1
+1 "3_block_bf084d8f8eaa49a9bbfc20e2bc845fd0"
65 SETSLOT
-2
+2 "fn"
+1 SETLINE
+7
16 PUSHSELF
16 PUSHSELF
17 PUSH
-3
+3 2
128 SEND
-2
+2 "fn"
1
128 SEND
-4
+4 "puts"
1
20 PUSHNIL
144 RET
-_block_9f8765f64c42ec0b2c499597d199b177
-:1:9
+_3_block_bf084d8f8eaa49a9bbfc20e2bc845fd0
+:1:11
"+
+1 SETLINE
+5
34 PUSHLOCALDEPTH
1
0
32 PUSHLOCAL
0
128 SEND
-0
+0 "+"
1
144 RET
View
45 examples/hello_world.tvm
@@ -1,63 +1,74 @@
-_main
-:5:26
+/Users/txus/Code/terrorvm/compiler/examples/hello_world.rb
+_0_main
+:5:34
"hello
"to_map
-"block_20915b4a4c9dabb4c467b5361606dfb9
+"3_block_8536122f47329b1115b21d7d42c847e5
"greet
"world
+1 SETLINE
+1
17 PUSH
-0
+0 "hello"
33 SETLOCAL
0
+1 SETLINE
+2
68 MAKEVEC
0
128 SEND
-1
+1 "to_map"
0
33 SETLOCAL
1
+1 SETLINE
+3
32 PUSHLOCAL
1
67 DEFN
-2
+2 "3_block_8536122f47329b1115b21d7d42c847e5"
65 SETSLOT
-3
+3 "greet"
+1 SETLINE
+6
32 PUSHLOCAL
1
17 PUSH
-4
+4 "world"
128 SEND
-3
+3 "greet"
1
20 PUSHNIL
144 RET
-_block_20915b4a4c9dabb4c467b5361606dfb9
-:4:23
+_3_block_8536122f47329b1115b21d7d42c847e5
+:4:25
"
"+
"!
"puts
+1 SETLINE
+4
16 PUSHSELF
34 PUSHLOCALDEPTH
1
0
17 PUSH
-0
+0 " "
128 SEND
-1
+1 "+"
1
32 PUSHLOCAL
0
128 SEND
-1
+1 "+"
1
17 PUSH
-2
+2 "!"
128 SEND
-1
+1 "+"
1
128 SEND
-3
+3 "puts"
1
144 RET
View
21 examples/maps.tvm
@@ -1,31 +1,36 @@
-_main
-:5:24
+/Users/txus/Code/terrorvm/compiler/examples/maps.rb
+_0_main
+:5:28
"hello world
"foo
"to_map
"[]
"puts
+1 SETLINE
+1
17 PUSH
-0
+0 "hello world"
17 PUSH
-1
+1 "foo"
68 MAKEVEC
2
128 SEND
-2
+2 "to_map"
0
33 SETLOCAL
0
+1 SETLINE
+2
16 PUSHSELF
32 PUSHLOCAL
0
17 PUSH
-1
+1 "foo"
128 SEND
-3
+3 "[]"
1
128 SEND
-4
+4 "puts"
1
20 PUSHNIL
144 RET
View
27 examples/numbers.tvm
@@ -1,5 +1,6 @@
-_main
-:9:28
+/Users/txus/Code/terrorvm/compiler/examples/numbers.rb
+_0_main
+:9:30
3
1
"-
@@ -9,31 +10,33 @@ _main
"*
"+
"puts
+1 SETLINE
+1
16 PUSHSELF
17 PUSH
-0
+0 3
17 PUSH
-1
+1 1
128 SEND
-2
+2 "-"
1
17 PUSH
-0
+0 3
17 PUSH
-3
+3 9.0
17 PUSH
-4
+4 3.2
128 SEND
-5
+5 "/"
1
128 SEND
-6
+6 "*"
1
128 SEND
-7
+7 "+"
1
128 SEND
-8
+8 "puts"
1
20 PUSHNIL
144 RET
View
77 examples/objects.tvm
@@ -1,5 +1,6 @@
-_main
-:13:91
+/Users/txus/Code/terrorvm/compiler/examples/objects.rb
+_0_main
+:13:117
"to_map
50
"age
@@ -13,94 +14,120 @@ _main
"Parent money:
"Child age:
"Child money:
+1 SETLINE
+1
68 MAKEVEC
0
128 SEND
-0
+0 "to_map"
0
33 SETLOCAL
0
+1 SETLINE
+2
32 PUSHLOCAL
0
17 PUSH
-1
+1 50
65 SETSLOT
-2
+2 "age"
+1 SETLINE
+3
32 PUSHLOCAL
0
17 PUSH
-3
+3 1000
65 SETSLOT
+4 "money"
+1 SETLINE
4
32 PUSHLOCAL
0
128 SEND
-5
+5 "clone"
0
33 SETLOCAL
1
+1 SETLINE
+5
32 PUSHLOCAL
1
17 PUSH
-6
+6 25
65 SETSLOT
-2
+2 "age"
+1 SETLINE
+7
16 PUSHSELF
17 PUSH
-7
+7 "Parent age:"
128 SEND
-8
+8 "print"
1
+1 SETLINE
+8
16 PUSHSELF
32 PUSHLOCAL
0
64 GETSLOT
-2
+2 "age"
128 SEND
-9
+9 "puts"
1
+1 SETLINE
+9
16 PUSHSELF
17 PUSH
-10
+10 "Parent money:"
128 SEND
-8
+8 "print"
1
+1 SETLINE
+10
16 PUSHSELF
32 PUSHLOCAL
0
64 GETSLOT
-4
+4 "money"
128 SEND
-9
+9 "puts"
1
+1 SETLINE
+12
16 PUSHSELF
17 PUSH
-11
+11 "Child age:"
128 SEND
-8
+8 "print"
1
+1 SETLINE
+13
16 PUSHSELF
32 PUSHLOCAL
1
64 GETSLOT
-2
+2 "age"
128 SEND
-9
+9 "puts"
1
+1 SETLINE
+14
16 PUSHSELF
17 PUSH
-12
+12 "Child money:"
128 SEND
-8
+8 "print"
1
+1 SETLINE
+15
16 PUSHSELF
32 PUSHLOCAL
1
128 SEND
-4
+4 "money"
0
128 SEND
-9
+9 "puts"
1
20 PUSHNIL
144 RET
View
67 examples/vectors.tvm
@@ -1,66 +1,83 @@
-_main
-:11:46
+/Users/txus/Code/terrorvm/compiler/examples/vectors.rb
+_0_main
+:11:60
"*
"everyone!
"to
"world
"hello
-"block_a0329904e2f682e96effd52e95980a17
+"3_block_68a56f63dd748cfa15d0a25639c38b2d
"each
"done!
"puts
-"block_ca644b6f9b6e500926cd95aa60554dfc
+"9_block_af301809d6ab3b20182bedec552860ca
"map
+1 SETLINE
+1
17 PUSH
-0
+0 "* "
33 SETLOCAL
0
+1 SETLINE
+2
17 PUSH
-1
+1 "everyone!"
17 PUSH
-2
+2 "to"
17 PUSH
-3
+3 "world"
17 PUSH
-4
+4 "hello"
68 MAKEVEC
4
33 SETLOCAL
1
+1 SETLINE
+3
67 DEFN
-5
+5 "3_block_68a56f63dd748cfa15d0a25639c38b2d"
33 SETLOCAL
2
+1 SETLINE
+6
32 PUSHLOCAL
1
32 PUSHLOCAL
2
128 SEND
-6
+6 "each"
1
+1 SETLINE
+7
16 PUSHSELF
17 PUSH
-7
+7 "done!"
128 SEND
-8
+8 "puts"
1
+1 SETLINE
+11
16 PUSHSELF
+1 SETLINE
+9
32 PUSHLOCAL
1
67 DEFN
-9
+9 "9_block_af301809d6ab3b20182bedec552860ca"
128 SEND
-10
+10 "map"
1
128 SEND
-8
+8 "puts"
1
20 PUSHNIL
144 RET
-_block_a0329904e2f682e96effd52e95980a17
-:2:13
+_3_block_68a56f63dd748cfa15d0a25639c38b2d
+:2:15
"+
"puts
+1 SETLINE
+4
16 PUSHSELF
34 PUSHLOCALDEPTH
1
@@ -68,22 +85,24 @@ _block_a0329904e2f682e96effd52e95980a17
32 PUSHLOCAL
0
128 SEND
-0
+0 "+"
1
128 SEND
-1
+1 "puts"
1
144 RET
-_block_ca644b6f9b6e500926cd95aa60554dfc
-:2:8
+_9_block_af301809d6ab3b20182bedec552860ca
+:2:10
"!!!!
"+
+1 SETLINE
+10
32 PUSHLOCAL
0
17 PUSH
-0
+0 "!!!!"
128 SEND
-1
+1 "+"
1
144 RET
View
437 kernel/alpha.tvm
@@ -1,5 +1,6 @@
-_main
-:44:518
+/Users/txus/Code/terrorvm/compiler/kernel/alpha.rb
+_0_main
+:44:566
"VM
"types
"object
@@ -44,522 +45,570 @@ _main
"closure
"Closure
"Map
+1 SETLINE
+3
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-2
+2 "object"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-5
+5 "prototype"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-5
+5 "prototype"
+1 SETLINE
+4
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-2
+2 "object"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-6
+6 "or"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-6
+6 "or"
+1 SETLINE
+5
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-2
+2 "object"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-7
+7 "equals"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-8
+8 "=="
+1 SETLINE
+6
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-2
+2 "object"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-9
+9 "is"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-10
+10 "==="
+1 SETLINE
+7
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-2
+2 "object"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-11
+11 "clone"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-11
+11 "clone"
+1 SETLINE
+8
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-2
+2 "object"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-12
+12 "print"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-12
+12 "print"
+1 SETLINE
+9
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-2
+2 "object"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-13
+13 "puts"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-13
+13 "puts"
+1 SETLINE
+11
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-14
+14 "number"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-15
+15 "number_+"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-16
+16 "+"
+1 SETLINE
+12
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-14
+14 "number"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-17
+17 "number_-"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-18
+18 "-"
+1 SETLINE
+13
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-14
+14 "number"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-19
+19 "number_/"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-20
+20 "/"
+1 SETLINE
+14
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-14
+14 "number"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-21
+21 "number_*"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-22
+22 "*"
+1 SETLINE
+16
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-23
+23 "string"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-24
+24 "string_+"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-16
+16 "+"
+1 SETLINE
+18
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-25
+25 "vector"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-26
+26 "vector_[]"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-3
+3 "[]"
+1 SETLINE
+19
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-25
+25 "vector"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-27
+27 "vector_push"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-28
+28 "push"
+1 SETLINE
+20
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-25
+25 "vector"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-29
+29 "vector_to_map"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-30
+30 "to_map"
+1 SETLINE
+21
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-25
+25 "vector"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-31
+31 "vector_each"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-32
+32 "each"
+1 SETLINE
+22
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-25
+25 "vector"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-33
+33 "vector_each_with_index"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-34
+34 "each_with_index"
+1 SETLINE
+24
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-35
+35 "map"
128 SEND
-3
+3 "[]"
1
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-4
+4 "primitives"
0
17 PUSH
-36
+36 "map_each"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-32
+32 "each"
+1 SETLINE
+26
21 PUSHLOBBY
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-2
+2 "object"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-37
+37 "Object"
+1 SETLINE
+27
21 PUSHLOBBY
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-14
+14 "number"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-38
+38 "Number"
+1 SETLINE
+28
21 PUSHLOBBY
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-23
+23 "string"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-39
+39 "String"
+1 SETLINE
+29
21 PUSHLOBBY
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-25
+25 "vector"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-40
+40 "Vector"
+1 SETLINE
+30
21 PUSHLOBBY
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-41
+41 "closure"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-42
+42 "Closure"
+1 SETLINE
+31
21 PUSHLOBBY
21 PUSHLOBBY
64 GETSLOT
-0
+0 "VM"
128 SEND
-1
+1 "types"
0
17 PUSH
-35
+35 "map"
128 SEND
-3
+3 "[]"
1
65 SETSLOT
-43
+43 "Map"
20 PUSHNIL
144 RET
View
102 kernel/beta.tvm
@@ -1,68 +1,64 @@
-_main
-:8:32
-"VM
-"types
-"vector
-"[]
-"block_732d1c0d0ac63cf57ee71487df62b266
+/Users/txus/Code/terrorvm/compiler/kernel/beta.rb
+_0_main
+:5:20
+"Vector
+"1_block_24f06bd53e4344e3176be470e94f0ad1
"map
-"block_3668c081fb5429e52577c04a918fd681
+"9_block_19cbfb1f488176aa34bdaba622a347c3
"length
+1 SETLINE
+1
21 PUSHLOBBY
64 GETSLOT
-0
-128 SEND
-1
-0
-17 PUSH
-2
-128 SEND
-3
-1
+0 "Vector"
67 DEFN
-4
+1 "1_block_24f06bd53e4344e3176be470e94f0ad1"
65 SETSLOT
-5
+2 "map"
+1 SETLINE
+9
21 PUSHLOBBY
64 GETSLOT
-0
-128 SEND
-1
-0
-17 PUSH
-2
-128 SEND
-3
-1
+0 "Vector"
67 DEFN
-6
+3 "9_block_19cbfb1f488176aa34bdaba622a347c3"
65 SETSLOT
-7
+4 "length"
20 PUSHNIL
144 RET
-_block_732d1c0d0ac63cf57ee71487df62b266
-:2:15
-"block_5f0562b981cc7414703389cd5b533b1e
+_1_block_24f06bd53e4344e3176be470e94f0ad1
+:2:23
+"3_block_93e17b3867bbd34ee955f2f04d1c20e8
"each
+1 SETLINE
+2
68 MAKEVEC
0
35 SETLOCALDEPTH
1
0
+1 SETLINE
+5
16 PUSHSELF
+1 SETLINE
+3
67 DEFN
-0
+0 "3_block_93e17b3867bbd34ee955f2f04d1c20e8"
128 SEND
+1 "each"
1
-1
+1 SETLINE
+6
34 PUSHLOCALDEPTH
1
0
144 RET
-_block_5f0562b981cc7414703389cd5b533b1e
-:2:15
+_3_block_93e17b3867bbd34ee955f2f04d1c20e8
+:2:17
"apply
"push
+1 SETLINE
+4
34 PUSHLOCALDEPTH
2
0
@@ -72,43 +68,51 @@ _block_5f0562b981cc7414703389cd5b533b1e
32 PUSHLOCAL
0
128 SEND
-0
+0 "apply"
1
128 SEND
-1
+1 "push"
1
144 RET
-_block_3668c081fb5429e52577c04a918fd681
-:3:15
+_9_block_19cbfb1f488176aa34bdaba622a347c3
+:3:21
0
-"block_6b594ab5d15beab416cf57ef5369c2d4
+"11_block_42099631ba6b6e0c915a00b2b36aefca
"each
+1 SETLINE
+10
17 PUSH
-0
+0 0
35 SETLOCALDEPTH
1
1
+1 SETLINE
+11
16 PUSHSELF
67 DEFN
-1
+1 "11_block_42099631ba6b6e0c915a00b2b36aefca"
128 SEND
-2
+2 "each"
1
+1 SETLINE
+12
34 PUSHLOCALDEPTH
1
1
144 RET
-_block_6b594ab5d15beab416cf57ef5369c2d4
-:2:12
+_11_block_42099631ba6b6e0c915a00b2b36aefca
+:2:14
1
"+
+1 SETLINE
+11
34 PUSHLOCALDEPTH
2
1
17 PUSH
-0
+0 1
128 SEND
-1
+1 "+"
1
35 SETLOCALDEPTH
2
View
15 src/terror/bootstrap.c
@@ -3,6 +3,7 @@
#include <terror/bstrlib.h>
#include <terror/runtime.h>
#include <terror/primitives.h>
+#include <terror/debugger.h>
#include <dirent.h>
VALUE Number_bp;
@@ -10,6 +11,7 @@ VALUE String_bp;
VALUE Vector_bp;
VALUE Map_bp;
VALUE Closure_bp;
+int Debug;
static inline DArray*
kernel_files()
@@ -44,6 +46,7 @@ expose_VM(VALUE lobby)
// Object
DEFPRIM(primitives, "prototype", Primitive_prototype);
DEFPRIM(primitives, "or", Primitive_or);
+
DEFPRIM(primitives, "equals", Primitive_equals);
DEFPRIM(primitives, "is", Primitive_is);
DEFPRIM(primitives, "print", Primitive_print);
@@ -94,6 +97,14 @@ State_bootstrap(STATE)
// Expose toplevel constants
expose_VM(state->lobby);
+ int reenable_debugger = 0;
+
+ // Disable debugger while loading kernel files
+ if(Debug) {
+ reenable_debugger = 1;
+ Debug = 0;
+ }
+
// Load all files.
for(int i=0; i < count; i++) {
bstring filename = (bstring)DArray_at(filenames, i);
@@ -102,5 +113,9 @@ State_bootstrap(STATE)
debug("[BOOTSTRAP] Loading %s...", bdata(path));
Primitive_require(state, String_new(bdata(path)), NULL, NULL);
}
+
+ // Reenable debugger if needed
+ if(reenable_debugger) Debug = 1;
+
debug("[BOOTSTRAP] Done!");
}
View
11 src/terror/call_frame.c
@@ -11,6 +11,7 @@ CallFrame_new(VALUE self, Function *fn, int *ret)
CallFrame* cf = calloc(1, sizeof(CallFrame));
cf->self = self;
cf->fn = fn;
+ cf->name = NULL;
cf->ret = ret;
cf->locals = DArray_create(sizeof(VALUE), 10);
cf->parent = NULL;
@@ -54,3 +55,13 @@ CallFrame_setlocaldepth(CallFrame *frame, int depth, int idx, VALUE value)
error:
debug("Error.");
}
+
+void
+CallFrame_print(CallFrame *frame)
+{
+ printf("%s:%i", frame->fn->filename, frame->fn->line);
+ if(frame->name) {
+ printf(" (%s)", frame->name);
+ }
+ printf("\n");
+}
View
2  src/terror/call_frame.h
@@ -8,6 +8,7 @@ struct val_s;
struct call_frame_s {
struct val_s *self;
+ char *name;
DArray *locals;
Function *fn;
int *ret;
@@ -22,5 +23,6 @@ struct val_s* CallFrame_getlocal(CallFrame *frame, int idx);
void CallFrame_setlocal(CallFrame *frame, int idx, struct val_s* value);
struct val_s* CallFrame_getlocaldepth(CallFrame *frame, int depth, int idx);
void CallFrame_setlocaldepth(CallFrame *frame, int depth, int idx, struct val_s* value);
+void CallFrame_print(CallFrame *frame);
#endif
View
158 src/terror/debugger.c
@@ -0,0 +1,158 @@
+#include <terror/state.h>
+#include <terror/debugger.h>
+#include <terror/file_utils.h>
+#include <terror/vm.h>
+#include "stdlib.h"
+#include "stdio.h"
+
+Debugger*
+Debugger_new()
+{
+ Debugger *debugger = calloc(1, sizeof(Debugger));
+ debugger->line_changed = 0;
+ debugger->step = STEP_LINE;
+ debugger->current_line = -1;
+ debugger->current_file = NULL;
+ return debugger;
+}
+
+void
+Debugger_load_current_file(STATE)
+{
+ if(DEBUGGER->current_file) {
+ bstrListDestroy(DEBUGGER->current_file);
+ }
+
+ bstring current_filename = bfromcstr(CURR_FRAME->fn->filename);
+
+ bstring buf = readfile(current_filename);
+
+ struct bstrList *lines = bsplit(buf, '\n');
+
+ if(lines) {
+ // Insert line counts
+ bstring *l = lines->entry;
+
+ for(int i=1; i <= lines->qty; i++) {
+ char linenum[8];
+ sprintf(linenum, "%-7i", i);
+
+ binsert(*l, 0, bfromcstr(linenum), ' ');
+ l++;
+ }
+
+ DEBUGGER->current_file = lines;
+ };
+}
+
+void
+Debugger_stop(STATE)
+{
+ switch(DEBUGGER->step) {
+ case STEP_INS: {
+ break;
+ }
+ case STEP_LINE: {
+ break;
+ }
+ }
+ Debugger_prompt(state);
+}
+
+void
+Debugger_prompt(STATE)
+{
+ int cont = 0;
+ while(!cont) {
+ Debugger_print_context(state);
+
+ printf("> ");
+
+ switch(getchar()) {
+ case 'h':
+ printf("\nCommands");
+ printf("\n--------");
+ printf("\nh: show this help");
+ printf("\ns: step to the next bytecode instruction");
+ printf("\nn: step to the next line of code");
+ printf("\nc: continue execution");
+ printf("\nd: show the stack");
+ printf("\nl: show locals");
+ printf("\nt: show backtrace");
+ printf("\n\n");
+ break;
+ case 's':
+ DEBUGGER->step = STEP_INS;
+ cont = 1;
+ break;
+ case 't': {
+ printf("\nBacktrace");
+ printf("\n---------\n");
+ CallFrame *p = CURR_FRAME;
+ while(p) {
+ CallFrame_print(p);
+ p = p->parent;
+ }
+ printf("\n");
+ break;
+ }
+ case 'l': {
+ printf("\nLocals");
+ printf("\n------");
+ for(int i=0; i < DArray_count(CURR_FRAME->locals); i++) {
+ printf("\n%i. ", i);
+ Value_print((VALUE)DArray_at(CURR_FRAME->locals, i));
+ printf("\n");
+ }
+ break;
+ }
+ case 'd':
+ Stack_print(STACK);
+ cont = 1;
+ break;
+ case 'n':
+ DEBUGGER->step = STEP_LINE;
+ cont = 1;
+ break;
+ case 'c':
+ DEBUGGER->step = STEP_NONE;
+ cont = 1;
+ break;
+ case EOF:
+ DEBUGGER->step = STEP_NONE;
+ cont = 1;
+ break;
+ default:
+ printf("I don't understand.\n");
+ break;
+ }
+ getchar();
+ }
+}
+
+void
+Debugger_print_context(STATE)
+{
+ int ctx = 3;
+ int ctx_start = DEBUGGER->current_line - ctx;
+ int ctx_end = DEBUGGER->current_line + ctx;
+
+ bstring current_filename = bfromcstr(CURR_FRAME->fn->filename);
+ printf("\n%s\n", bdata(current_filename));
+
+ DArray *lines = getlines(DEBUGGER->current_file, ctx_start, ctx_end);
+
+ int middle_idx = ((DArray_count(lines) - 1) / 2);
+
+ for(int i=0; i < DArray_count(lines); i++) {
+ bstring curr_line = (bstring)DArray_at(lines, i);
+ if(i+1 == middle_idx) { // current line
+ curr_line = bstrcpy((bstring)DArray_at(lines, i));
+
+ breplace(curr_line, 5, 1, bfromcstr(">"), ' ');
+ }
+ printf("%s\n", bdata(curr_line));
+ }
+ printf("\n");
+}
+
View
45 src/terror/debugger.h
@@ -0,0 +1,45 @@
+#ifndef _tvm_debugger_h_
+#define _tvm_debugger_h_
+
+extern int Debug;
+
+struct state_s;
+
+typedef enum {
+ STEP_NONE,
+ STEP_INS,
+ STEP_LINE
+} DebuggerStep;
+
+struct debugger_s {
+ int line_changed;
+ int current_line;
+ int step;
+ struct bstrList* current_file;
+};
+
+typedef struct debugger_s Debugger;
+
+Debugger* Debugger_new();
+void Debugger_stop(struct state_s* state);
+void Debugger_prompt(struct state_s* state);
+void Debugger_load_current_file(struct state_s* state);
+void Debugger_print_context(struct state_s* state);
+
+#define Debugger_setline(S, L) \
+ if(Debug) { \
+ (S)->dbg->current_line = (L); \
+ (S)->dbg->line_changed = 1; \
+ }
+
+#define Debugger_evaluate(S) \
+ if(Debug) { \
+ if((S)->dbg->step == STEP_INS) { \
+ Debugger_stop((S)); \
+ } else if ((S)->dbg->step == STEP_LINE && (S)->dbg->line_changed) { \
+ Debugger_stop((S)); \
+ } \
+ (S)->dbg->line_changed = 0; \
+ }
+
+#endif
View
61 src/terror/file_utils.c
@@ -0,0 +1,61 @@
+#include <terror/dbg.h>
+#include <terror/file_utils.h>
+
+/*
+ * Return the filesize of `filename` or -1.
+ */
+
+static inline off_t
+file_size(bstring filename) {
+ struct stat s;
+ int rc = stat(bdata(filename), &s);
+
+ if (rc < 0) return -1;
+ return s.st_size;
+}
+
+/*
+ * Read the contents of `filename` or return NULL.
+ */
+
+bstring
+readfile(bstring filename) {
+ off_t len = file_size(filename);
+ check(len >= 0, "Invalid file length.");
+
+ char *buf = malloc(len + 1);
+ check_mem(buf);
+
+ int fd = open(bdata(filename), O_RDONLY);
+ check(fd >= 0, "Error opening file.");
+
+ ssize_t size = read(fd, buf, len);
+ check(size == len, "Read length is invalid");
+
+ bstring retval = bfromcstr(buf);
+ free(buf);
+ return retval;
+
+error:
+ return NULL;
+}
+
+DArray*
+getlines(struct bstrList *file, int start, int end)
+{
+ if (start < 0) start = 1;
+ if (end > file->qty) end = file->qty;
+
+ int count = end - start + 1;
+ DArray *lines = DArray_create(sizeof(bstring), count);
+
+ bstring *line = file->entry;
+
+ while(--start > 0) line++; // advance to the start
+ while(count--) {
+ DArray_push(lines, *line);
+ line++;
+ }
+
+ return lines;
+}
View
16 src/terror/file_utils.h
@@ -0,0 +1,16 @@
+#ifndef _tvm_file_utils_h_
+#define _tvm_file_utils_h_
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <terror/bstrlib.h>
+#include <terror/darray.h>
+
+bstring readfile(bstring filename);
+DArray *getlines(struct bstrList *file, int start, int end);
+
+#endif
+
View
18 src/terror/function.c
@@ -6,10 +6,12 @@
#include <terror/vm.h>
Function*
-Function_new(int *code, DArray *literals)
+Function_new(char *filename, int *code, DArray *literals)
{
Function *fn = calloc(1, sizeof(Function));
+ fn->filename = filename;
fn->code = code;
+ fn->line = 0;
fn->literals = literals;
fn->scope = NULL;
fn->c_fn = NULL;
@@ -20,6 +22,7 @@ Function*
Function_native_new(native_fn c_fn)
{
Function *fn = calloc(1, sizeof(Function));
+ fn->filename = "(native)";
fn->code = NULL;
fn->literals = NULL;
fn->scope = NULL;
@@ -43,7 +46,8 @@ Function_call(
STATE, // the State
Function *fn, // the Function we're calling
VALUE receiver, // the Receiver value
- DArray *locals) // the arguments to the function call
+ DArray *locals, // the arguments to the function call
+ char *name) // optional name for the backtrace
{
int *ret = state->ret;
if(!receiver) receiver = CURR_FRAME->self;
@@ -58,6 +62,7 @@ Function_call(
// Normal dispatch
CallFrame *new_frame = CallFrame_new(receiver, fn, ret);
new_frame->locals = locals;
+ new_frame->name = name;
// If it is a closure, we nest the call frames.
if(fn->scope) {
@@ -66,13 +71,16 @@ Function_call(
Stack_push(FRAMES, new_frame);
- return new_frame->fn->code;
+ ret = new_frame->fn->code;
+ ret--;
+
+ return ret;
}
VALUE
-Closure_invoke(STATE, VALUE closure, VALUE receiver, DArray *args)
+Closure_invoke(STATE, VALUE closure, VALUE receiver, DArray *args, char *name)
{
state->ret = NULL; // don't return anywhere
- Function_call(state, VAL2FN(closure), receiver, args);
+ Function_call(state, VAL2FN(closure), receiver, args, name);
return VM_run(state);
}
View
8 src/terror/function.h
@@ -10,6 +10,8 @@ struct call_frame_s;
typedef struct val_s* (*native_fn)(struct state_s*, void*, void*, void*);
struct function_s {
+ char *filename;
+ int line;
int *code;
DArray *literals;
struct call_frame_s *scope;
@@ -17,11 +19,11 @@ struct function_s {
};
typedef struct function_s Function;
-Function* Function_new(int*, DArray*);
+Function* Function_new(char*, int*, DArray*);
Function* Function_native_new(native_fn);
struct val_s* Function_native_call(struct state_s*, Function*, struct val_s*, DArray*);
-int* Function_call(struct state_s*, Function*, struct val_s*, DArray*);
+int* Function_call(struct state_s*, Function*, struct val_s*, DArray*, char* name);
-struct val_s* Closure_invoke(struct state_s*, struct val_s* closure, struct val_s* receiver, DArray *args);
+struct val_s* Closure_invoke(struct state_s*, struct val_s* closure, struct val_s* receiver, DArray *args, char *name);
#endif
View
72 src/terror/input_reader.c
@@ -1,52 +1,7 @@
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <terror/dbg.h>
-#include <terror/bstrlib.h>
+#include <terror/file_utils.h>
#include <terror/input_reader.h>
#include <terror/value.h>
-/*
- * Return the filesize of `filename` or -1.
- */
-
-static inline off_t
-file_size(bstring filename) {
- struct stat s;
- int rc = stat(bdata(filename), &s);
-
- if (rc < 0) return -1;
- return s.st_size;
-}
-
-/*
- * Read the contents of `filename` or return NULL.
- */
-
-static inline bstring
-file_read(bstring filename) {
- off_t len = file_size(filename);
- check(len >= 0, "Invalid file length.");
-
- char *buf = malloc(len + 1);
- check_mem(buf);
-
- int fd = open(bdata(filename), O_RDONLY);
- check(fd >= 0, "Error opening file.");
-
- ssize_t size = read(fd, buf, len);
- check(size == len, "Read length is invalid");
-
- bstring retval = bfromcstr(buf);
- free(buf);
- return retval;
-
-error:
- return NULL;
-}
-
static inline void
parse_string(bstring buf, BytecodeFile *file)
{
@@ -56,12 +11,23 @@ parse_string(bstring buf, BytecodeFile *file)
bstring *line = lines->entry;
+ // Get filename
+ file->filename = bstrcpy(*line);
+ line++; cnt++;
+
while(1) {
// eof
if (bstrcmp(bmidstr(*line, 0, 1), bfromcstr("_")) != 0) break;
// Get method name
- int num_literals, num_instructions;
+ int num_literals, num_instructions, linenum;
+ {
+ struct bstrList *fn_params = bsplit(*line, '_');
+ bstring *fnptr = fn_params->entry;
+ fnptr++; // linenum
+ linenum = atoi(bdata(*fnptr));