copied thnad to get a kickstart

This commit is contained in:
Torsten Ruger
2014-04-24 15:43:20 +03:00
parent f97205300f
commit d90ea3dd26
11 changed files with 580 additions and 0 deletions

21
test/test/fake_builder.rb Normal file
View File

@ -0,0 +1,21 @@
class FakeBuilder
attr_reader :result
def initialize
@result = ''
end
def class_builder
'example'
end
def int
'int'
end
def method_missing(name, *args, &block)
@result += ([name] + args.flatten).join(', ').sub(',', '')
@result += "\n"
block.call(self) if name.to_s == 'public_static_method'
end
end

22
test/test/graph_helper.rb Normal file
View File

@ -0,0 +1,22 @@
require 'gritty'
def dump(obj, name)
g = digraph do
graph_attribs << 'bgcolor=black'
node_attribs << 'color=white'
node_attribs << 'penwidth=2'
node_attribs << 'fontcolor=white'
node_attribs << 'labelloc=c'
node_attribs << 'fontname="Courier New"'
node_attribs << 'fontsize=36'
edge_attribs << 'color=white'
edge_attribs << 'penwidth=2'
builder = Gritty::NodeBuilder.new self
builder.build obj, 'root'
save name, 'pdf'
end
end

77
test/test/test_nodes.rb Normal file
View File

@ -0,0 +1,77 @@
$: << File.expand_path(File.dirname(__FILE__) + '/../lib')
$: << File.expand_path(File.dirname(__FILE__))
require 'minitest/autorun'
require 'minitest/spec'
require 'thnad/nodes'
require 'fake_builder'
include Thnad
describe 'Nodes' do
before do
@context = Hash.new
@builder = FakeBuilder.new
end
it 'emits a number' do
input = Thnad::Number.new 42
expected = <<HERE
ldc 42
HERE
input.eval @context, @builder
@builder.result.must_equal expected
end
it 'emits a function call' do
@context[:params] = ['foo']
input = Thnad::Funcall.new 'baz', [Thnad::Number.new(42),
Thnad::Name.new('foo')]
expected = <<HERE
ldc 42
iload 0
invokestatic example, baz, int, int, int
HERE
input.eval @context, @builder
@builder.result.must_equal expected
end
it 'emits a conditional' do
input = Thnad::Conditional.new \
Thnad::Number.new(0),
Thnad::Number.new(42),
Thnad::Number.new(667)
expected = <<HERE
ldc 0
ifeq else
ldc 42
goto endif
label else
ldc 667
label endif
HERE
input.eval @context, @builder
@builder.result.must_equal expected
end
it 'emits a function definition' do
input = Thnad::Function.new \
'foo',
Thnad::Name.new('x'),
Thnad::Number.new(5)
expected = <<HERE
public_static_method foo, int, int
ldc 5
ireturn
HERE
input.eval @context, @builder
@builder.result.must_equal expected
end
end

72
test/test/test_parser.rb Normal file
View File

@ -0,0 +1,72 @@
$: << File.expand_path(File.dirname(__FILE__) + '/../lib')
require 'minitest/autorun'
require 'minitest/spec'
require 'thnad/parser'
include Thnad
describe Parser do
before do
@parser = Thnad::Parser.new
end
it 'reads a number' do
input = '42 '
expected = {:number => '42'}
@parser.number.parse(input).must_equal expected
end
it 'reads a name' do
input = 'foo '
expected = {:name => 'foo'}
@parser.name.parse(input).must_equal expected
end
it 'reads an argument list' do
input = '(42, foo)'
expected = {:args => [{:arg => {:number => '42'}},
{:arg => {:name => 'foo'}}]}
@parser.args.parse(input).must_equal expected
end
it 'reads a function call' do
input = 'baz(42, foo)'
expected = {:funcall => {:name => 'baz' },
:args => [{:arg => {:number => '42'}},
{:arg => {:name => 'foo'}}]}
@parser.funcall.parse(input).must_equal expected
end
it 'reads a conditional' do
input = <<HERE
if (0) {
42
} else {
667
}
HERE
expected = {:cond => {:number => '0'},
:if_true => {:body => {:number => '42'}},
:if_false => {:body => {:number => '667'}}}
@parser.cond.parse(input).must_equal expected
end
it 'reads a function definition' do
input = <<HERE
function foo(x) {
5
}
HERE
expected = {:func => {:name => 'foo'},
:params => {:param => {:name => 'x'}},
:body => {:number => '5'}}
@parser.func.parse(input).must_equal expected
end
end

View File

@ -0,0 +1,78 @@
$: << File.expand_path(File.dirname(__FILE__) + '/../lib')
require 'minitest/autorun'
require 'minitest/spec'
require 'thnad/transform'
include Thnad
describe Transform do
before do
@transform = Thnad::Transform.new
end
it 'transforms a number' do
input = {:number => '42'}
expected = Thnad::Number.new(42)
@transform.apply(input).must_equal expected
end
it 'transforms a name' do
input = {:name => 'foo'}
expected = Thnad::Name.new('foo')
@transform.apply(input).must_equal expected
end
it 'transforms an argument list' do
input = {:args => [{:arg => {:number => '42'}},
{:arg => {:name => 'foo'}}]}
expected = [Thnad::Number.new(42),
Thnad::Name.new('foo')]
@transform.apply(input).must_equal expected
end
it 'transforms a single-argument function call' do
input = {:funcall => {:name => 'foo'},
:args => [{:arg => {:number => '42'}}]}
expected = Thnad::Funcall.new 'foo', [Thnad::Number.new(42)]
@transform.apply(input).must_equal expected
end
it 'transforms a multi-argument function call' do
input = {:funcall => {:name => 'baz'},
:args => [{:arg => {:number => '42'}},
{:arg => {:name => 'foo'}}]}
expected = Thnad::Funcall.new 'baz', [Thnad::Number.new(42),
Thnad::Name.new('foo')]
@transform.apply(input).must_equal expected
end
it 'transforms a conditional' do
input = {:cond => {:number => '0'},
:if_true => {:body => {:number => '42'}},
:if_false => {:body => {:number => '667'}}}
expected = Thnad::Conditional.new \
Thnad::Number.new(0),
Thnad::Number.new(42),
Thnad::Number.new(667)
@transform.apply(input).must_equal expected
end
it 'transforms a function definition' do
input = {:func => {:name => 'foo'},
:params => {:param => {:name => 'x'}},
:body => {:number => '5'}}
expected = Thnad::Function.new \
'foo',
[Thnad::Name.new('x')],
Thnad::Number.new(5)
@transform.apply(input).must_equal expected
end
end