From 82ab8ac4d35ca3b8e8be5271cf145b7e5af98985 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Sun, 25 Mar 2018 18:22:02 +0300 Subject: [PATCH] add data objects marker class (may change) to be able to check access --- lib/parfait.rb | 3 +- lib/parfait/binary_code.rb | 39 +++++++++++++++++++---- lib/parfait/data_object.rb | 63 ++++++++++++++++++++++++++++++++++++++ lib/parfait/integer.rb | 2 +- lib/parfait/word.rb | 23 +++----------- lib/risc/boot.rb | 8 +++-- 6 files changed, 110 insertions(+), 28 deletions(-) create mode 100644 lib/parfait/data_object.rb diff --git a/lib/parfait.rb b/lib/parfait.rb index 16ce1375..ee04101d 100644 --- a/lib/parfait.rb +++ b/lib/parfait.rb @@ -2,8 +2,9 @@ module Parfait end -require_relative "parfait/integer" require_relative "parfait/object" +require_relative "parfait/data_object" +require_relative "parfait/integer" require_relative "parfait/behaviour" require_relative "parfait/class" require_relative "parfait/list" diff --git a/lib/parfait/binary_code.rb b/lib/parfait/binary_code.rb index 04736c2a..c2a7ed3a 100644 --- a/lib/parfait/binary_code.rb +++ b/lib/parfait/binary_code.rb @@ -5,13 +5,40 @@ # module Parfait - # obviously not a "Word" but a ByteArray , but no such class yet - # As our String (Word) on the other hand has no encoding (yet) it is close enough - class BinaryCode < Word - def to_s - "BinaryCode #{self.char_length}" + class BinaryCode < Data16 + attr_accessor :next + + def initialize(total_size) + super() + if total_size > self.data_length + @next = BinaryCode.new(total_size - data_length) + end + #puts "Init with #{total_size} for #{object_id}" + end + def to_s + "BinaryCode #{}" + end + def data_length + 14 + end + def char_length + 4*data_length + end + def set_char(c , index) + if index >= char_length + puts "Pass it on #{index} for #{object_id}" + return @next.set_char( c , index - char_length) + end + word_index = (index - 1) / 4 + 2 + old = get_internal_word( word_index ) + old = old && c << ((index-1)%4) + set_internal_word(word_index , c) + end + def total_byte_length(start = 0 ) + start += 4*14 + return start unless self.next + self.next.total_byte_length(start) end - end end diff --git a/lib/parfait/data_object.rb b/lib/parfait/data_object.rb new file mode 100644 index 00000000..e0d5e38b --- /dev/null +++ b/lib/parfait/data_object.rb @@ -0,0 +1,63 @@ +# +# +# In rubyx everything truely is an object. (most smalltalk/ruby systems use a union +# for integers/pointers that are called objects, but are really very different) +# +# Objects have type as their first member. No exception. +# +# So where is the data? In DataObjects. DataObjects are opague carriers of data. +# Opague to rubyx that is. There is no way to get at it or pass the data around. +# +# To use Data, Risc instructions have to be used. Luckily there is not soo much one +# actually wants to do with data, moving it between DataObject , comparing and +# logical and math operation that are bundled into the OperatorInstruction. +# +# For safe access the access code needs to know the length of the data, which is +# encoded in the class/type name. Ie An Integer derives from Data2, which is 2 long +# (minus one for the type, so exactly the one word for the integer) +# +# DataObjects still have a type, and so can have objects before the data starts +# +# A marker class +module Parfait + class DataObject < Object + def initialize + @memory = [] + end + def data_length + raise "called #{self}" + end + def data_start + return type.length + end + + # 1 -based index + def get_internal_word(index) + @memory[index] + end + + # 1 -based index + def set_internal_word(index , value) + raise "Word[#{index}] = nil" if( value.nil? ) + @memory[index] = value + value + end + end + + class Data2 < DataObject + def data_length + 1 + end + end + + class Data8 < DataObject + def data_length + 7 + end + end + class Data16 < DataObject + def data_length + 15 + end + end +end diff --git a/lib/parfait/integer.rb b/lib/parfait/integer.rb index d32aa43f..05165791 100644 --- a/lib/parfait/integer.rb +++ b/lib/parfait/integer.rb @@ -7,7 +7,7 @@ # Ie it would be possible to change the value, we just don't support that) module Parfait - class Integer + class Integer < Data2 # :integer?, :odd?, :even?, :upto, :downto, :times, :succ, :next, :pred, :chr, :ord, :to_i, :to_int, :floor, # :ceil, :truncate, :round, :gcd, :lcm, :gcdlcm, :numerator, :denominator, :to_r, :rationalize, diff --git a/lib/parfait/word.rb b/lib/parfait/word.rb index 687798cc..9603aa55 100644 --- a/lib/parfait/word.rb +++ b/lib/parfait/word.rb @@ -12,14 +12,14 @@ module Parfait # So all indexes are offset by one in the implementation # Object length is measured in non-type cells though - class Word < Object + class Word < Data8 attr_reader :char_length #semi "indexed" methods for interpreter def self.get_length_index 2 # 2 is the amount of attributes, type and char_length. the offset after which chars start end - def self.get_indexed i + def self.get_indexed( i ) i + get_length_index * 4 end # initialize with length. For now we try to keep all non-parfait (including String) out @@ -28,25 +28,12 @@ module Parfait def initialize len super() @char_length = 0 - @memory = [] raise "Must init with int, not #{len.class}" unless len.kind_of? Fixnum raise "Must init with positive, not #{len}" if len < 0 set_length( len , 32 ) unless len == 0 #32 beeing ascii space #puts "type #{self.get_type} #{self.object_id.to_s(16)}" end - # 1 -based index - def get_internal_word(index) - @memory[index] - end - - # 1 -based index - def set_internal_word(index , value) - raise "Word[#{index}] = nil" if( value.nil? ) - @memory[index] = value - value - end - # return a copy of self def copy @@ -100,13 +87,13 @@ module Parfait # character must be an integer, as is the index # the index starts at one, but may be negative to count from the end # indexes out of range will raise an error - def set_char at , char + def set_char( at , char ) raise "char not fixnum #{char.class}" unless char.kind_of? Fixnum index = range_correct_index(at) set_internal_byte( index , char) end - def set_internal_byte index , char + def set_internal_byte( index , char ) word_index = (index) / 4 rest = ((index) % 4) shifted = char << (rest * 8) @@ -128,7 +115,7 @@ module Parfait # the index starts at one, but may be negative to count from the end # indexes out of range will raise an error #the return "character" is an integer - def get_char at + def get_char( at ) index = range_correct_index(at) get_internal_byte(index) end diff --git a/lib/risc/boot.rb b/lib/risc/boot.rb index a4165bce..62c7c3b4 100644 --- a/lib/risc/boot.rb +++ b/lib/risc/boot.rb @@ -116,7 +116,8 @@ module Risc # superclasses other than default object def super_class_names - { Object: :Kernel , Kernel: :Value , Integer: :Value , BinaryCode: :Word } + { Object: :Kernel , Kernel: :Value , BinaryCode: :Word , + Data2: :DataObject ,Data8: :DataObject , Integer: :Data2, Word: :Data8} end # the function really just returns a constant (just avoiding the constant) @@ -129,12 +130,15 @@ module Risc return_address: :Integer, return_value: :Integer, caller: :Message , name: :Word , arguments: :NamedList }, Integer: {}, + DataObject: {}, + Data2: {}, + Data8: {}, TrueClass: {}, FalseClass: {}, NilClass: {}, Object: {}, Kernel: {}, #fix, kernel is a class, but should be a module - BinaryCode: {char_length: :Integer} , + BinaryCode: {next: :BinaryCode} , Space: {classes: :Dictionary , types: :Dictionary , first_message: :Message , single_true: :TrueClass, single_false: :FalseClass , single_nil: :NilClass},