2014-05-21 20:13:12 +02:00
|
|
|
require_relative '../helper'
|
2014-05-21 20:37:04 +02:00
|
|
|
require 'parslet/convenience'
|
2014-05-21 20:13:12 +02:00
|
|
|
|
|
|
|
#test the generation of code fragments.
|
|
|
|
# ie parse assumes @string_input
|
|
|
|
# compile
|
|
|
|
# assemble/write assume a @should array with the bytes in it
|
|
|
|
|
2014-05-21 20:37:04 +02:00
|
|
|
# since the bytes are store, the test can be run on any machine.
|
|
|
|
|
|
|
|
# but to get the bytes, one needs to link and run the object file to confirm correctness (to be automated)
|
|
|
|
|
2014-05-21 20:13:12 +02:00
|
|
|
module Fragments
|
|
|
|
# need a code generator, for arm
|
|
|
|
def setup
|
2014-05-31 11:52:29 +02:00
|
|
|
@object_space = Vm::BootSpace.new "Arm"
|
2014-05-21 20:13:12 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
def parse
|
|
|
|
parser = Parser::Crystal.new
|
|
|
|
syntax = parser.parse_with_debug(@string_input)
|
|
|
|
parts = Parser::Transform.new.apply(syntax)
|
|
|
|
# file is a list of expressions, all but the last must be a function
|
|
|
|
# and the last is wrapped as a main
|
|
|
|
parts.each_with_index do |part,index|
|
|
|
|
if index == (parts.length - 1)
|
2014-05-31 11:52:29 +02:00
|
|
|
expr = part.compile( @object_space.context , @object_space.main )
|
2014-05-21 20:13:12 +02:00
|
|
|
else
|
2014-05-31 11:52:29 +02:00
|
|
|
expr = part.compile( @object_space.context , nil )
|
2014-06-02 12:45:08 +02:00
|
|
|
raise "should be function definition for now, not #{part.inspect}#{expr.inspect}" unless expr.is_a? Vm::Function
|
2014-05-21 20:13:12 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# helper to write the file
|
|
|
|
def write name
|
2014-05-31 11:52:29 +02:00
|
|
|
writer = Elf::ObjectWriter.new(@object_space , Elf::Constants::TARGET_ARM)
|
2014-05-21 20:13:12 +02:00
|
|
|
assembly = writer.text
|
2014-06-05 12:02:36 +02:00
|
|
|
writer.save("#{name}.o")
|
|
|
|
function = @object_space.classes[@target[0]]
|
|
|
|
assert function
|
|
|
|
function = function.get_function(@target[1])
|
|
|
|
assert function
|
|
|
|
io = StringIO.new
|
|
|
|
function.assemble io
|
|
|
|
assembly = io.string
|
2014-05-21 20:13:12 +02:00
|
|
|
# use this for getting the bytes to compare to :
|
2014-06-05 12:02:36 +02:00
|
|
|
#puts bytes(assembly)
|
|
|
|
assembly.bytes.each_with_index do |byte , index|
|
2014-05-21 20:13:12 +02:00
|
|
|
is = @should[index]
|
|
|
|
assert_equal Fixnum , is.class , "@#{index.to_s(16)} = #{is}"
|
|
|
|
assert_equal byte , is , "@#{index.to_s(16)} #{byte.to_s(16)} != #{is.to_s(16)}"
|
|
|
|
end
|
2014-05-28 13:55:13 +02:00
|
|
|
if( RbConfig::CONFIG["build_cpu"] == "arm")
|
|
|
|
system "ld -N #{name}.o"
|
|
|
|
result = %x[./a.out]
|
|
|
|
assert_equal @output , result
|
|
|
|
end
|
2014-05-21 20:13:12 +02:00
|
|
|
end
|
2014-06-05 12:02:36 +02:00
|
|
|
def bytes string
|
|
|
|
"[" + string.bytes.collect{|b| "0x"+ b.to_s(16)}.join(",") + "]"
|
|
|
|
end
|
|
|
|
|
2014-05-21 20:13:12 +02:00
|
|
|
end
|