From 990b4726ba9a3fc5fd6ead935660f31af66f3251 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Fri, 2 May 2014 08:02:25 +0300 Subject: [PATCH] more random code --- lib/crystal.rb | 2 +- lib/vm/context.rb | 53 ++++++++++++++++++++++++++++++++++++ lib/vm/instruction.rb | 6 +++++ lib/vm/kernel.rb | 7 +++++ lib/vm/machine.rb | 26 +++++++++++++++--- lib/vm/values.rb | 63 +++++++++++++++++++++++++++++++++++++++---- test/runners/foo.rb | 4 ++- test/test_runner.rb | 7 ++--- 8 files changed, 155 insertions(+), 13 deletions(-) create mode 100644 lib/vm/context.rb create mode 100644 lib/vm/instruction.rb create mode 100644 lib/vm/kernel.rb diff --git a/lib/crystal.rb b/lib/crystal.rb index e1d5af56..d7ea5cf3 100644 --- a/lib/crystal.rb +++ b/lib/crystal.rb @@ -4,4 +4,4 @@ require "asm/program" require "elf/object_writer" require 'parser/composed' require 'parser/transform' - +require "vm/context" diff --git a/lib/vm/context.rb b/lib/vm/context.rb new file mode 100644 index 00000000..9d0ec2b2 --- /dev/null +++ b/lib/vm/context.rb @@ -0,0 +1,53 @@ +require_relative "kernel" + +module Vm + class Context + def initialize + @locals = {} + end + def get name + @locals[name] + end + end +end + +# ast classes +module Parser + Expression.class_eval do + def compile builder , context + raise "abstract #{self.inspect}" + end + end + + IntegerExpression.class_eval do + end + + NameExpression.class_eval do + end + + StringExpression.class_eval do + def compile builder , context + return string + end + end + + FuncallExpression.class_eval do + def compile builder , context + arguments = args.collect{|arg| arg.compile(builder , context) } + function = context.get(name) + unless function + function = Vm::Kernel.send(name) + context.add_function( name , function ) + end + + end + end + + ConditionalExpression.class_eval do + end + + AssignmentExpression.class_eval do + end + FunctionExpression.class_eval do + end +end diff --git a/lib/vm/instruction.rb b/lib/vm/instruction.rb new file mode 100644 index 00000000..c9a46b61 --- /dev/null +++ b/lib/vm/instruction.rb @@ -0,0 +1,6 @@ + +module Vm + class Instruction + end + +end diff --git a/lib/vm/kernel.rb b/lib/vm/kernel.rb new file mode 100644 index 00000000..fa07409c --- /dev/null +++ b/lib/vm/kernel.rb @@ -0,0 +1,7 @@ +module Vm + module Kernel + def self.puts + "me" + end + end +end \ No newline at end of file diff --git a/lib/vm/machine.rb b/lib/vm/machine.rb index 4eebd8f6..185a2cb1 100644 --- a/lib/vm/machine.rb +++ b/lib/vm/machine.rb @@ -1,7 +1,27 @@ module Vm - # the vm machine is what does things. The only one that does things - # all things must go through the machine to actually happen + + # Our virtual machine has a number of registers of a given size and uses a stack + # So much so standard + # But our machine is oo, meaning that the register contents is typed. + # Off course current hardware does not have that (a perceived issue), but for our machine we pretend. + # So internally we have at least 8 word registers, one of which is used to keep track of types* + # and any number of scratch registers + # but externally it's all Values (see there) + + # * Note that register content is typed externally. Not as in mri, where int's are tagged. Floats can's + # be tagged and lambda should be it's own type, so tagging does not work + + # Note: subclasses should/will be used once we have the basic architecture clear and working + class Machine - + + attr_reader :registers + attr_reader :scratch + attr_reader :pc + attr_reader :stack + # is often a pseudo register (ie doesn't support move or other operations). + # Still, using if to express tests makes sense, not just for + # consistency in this code, but also because that is what is actually done + attr_reader :status end end diff --git a/lib/vm/values.rb b/lib/vm/values.rb index 4b23341f..15d56ff0 100644 --- a/lib/vm/values.rb +++ b/lib/vm/values.rb @@ -1,17 +1,70 @@ module Vm + + # Values represent the information as it is processed. Different subclasses for different types, + # each type with different operations. + # The oprerations on values is what makes a machine do things. + # For compilation, values are mopped to the machines registers and the functions (on values) map + # to machine instructions + + # Values are immutable! (that's why they are called values) + # Operations on values _always_ produce new values (conceptionally) + + # Values are a way to reason about (create/validate) instructions. The final executable is mostly + # instrucions. + + # Word Values are what fits in a register. Derived classes + # Float, Reference , Integer(s) must fit the same registers + class Value + def bit_size + 8 * byte_size + end + + def byte_size + raise "abstract method called #{self.inspect}" + end + attr :register + + def initialize reg = nil + @register = nil + end end - - + class Word < Value end - class Reference < Value + class Unsigned < Word + + def + unsigned + unless unsigned.is_a? Unsigned + unsigned = Conversion.new( unsigned , Unsigned ) + end + UnsignedAdd.new( self , unsigned ) + end + end + + class Signed < Word + def + signed + unless signed.is_a? Signed + signed = Conversion.new( signed , Signed ) + end + SignedAdd.new( self , signed ) + end + end + + class Float < Word + end + + class Reference < Word end class MemoryReference < Reference end - + class ObjectReference < Reference end -end \ No newline at end of file + + class Byte < Value + end + +end diff --git a/test/runners/foo.rb b/test/runners/foo.rb index 94170287..483a7950 100644 --- a/test/runners/foo.rb +++ b/test/runners/foo.rb @@ -1,3 +1,5 @@ def foo(x) a = 5 -end \ No newline at end of file +end + +foo( 3 ) \ No newline at end of file diff --git a/test/test_runner.rb b/test/test_runner.rb index 74babb01..1bf4f887 100644 --- a/test/test_runner.rb +++ b/test/test_runner.rb @@ -25,9 +25,10 @@ class TestRunner < MiniTest::Test #link # execute # check result ? - puts string - puts " " - puts tree.inspect + context = Vm::Context.new + builder = Asm::Program.new + compiled = tree.compile( builder , context ) + puts compiled.inspect end end \ No newline at end of file