class Z80::Alloc
Alloc
class is used internally by relocation mechanizm and lazy evaluation of labels' values. See Label
instead.
Public Class Methods
include?(alloc, label)
click to toggle source
Return true if label
takes part in an alloc
expression.
# File lib/z80/labels.rb, line 1120 def Alloc.include?(alloc, label) return true if alloc == label return false unless alloc.is_a?(Alloc) alloc.instance_exec do Alloc.include?(@lhs, label) || Alloc.include?(@rhs, label) end end
new(lhs, oper=nil, rhs=nil, index=[])
click to toggle source
# File lib/z80/labels.rb, line 1164 def initialize(lhs, oper=nil, rhs=nil, index=[]) raise Syntax, "lhs is not a Label or an Alloc" unless lhs.is_a?(Label) or lhs.is_a?(Alloc) rhs = rhs.to_alloc if rhs.is_a?(Label) raise Syntax, "rhs is not an Alloc or an integer" unless rhs.nil? or Integer === rhs or rhs.is_a?(Alloc) raise Syntax, "lhs nor rhs must not be a pointer" if lhs.pointer? or (rhs.respond_to?(:pointer?) and rhs.pointer?) raise Syntax, "invalid operator" unless oper.nil? or [:+,:-,:+@,:-@,:>>,:<<,:/,:%,:*,:^,:&,:|,:~,:alias].include?(oper) raise Syntax, "invalid operator's rhs" unless (rhs.nil? and (oper.nil? or [:+@,:-@,:~,:alias].include?(oper))) or (!oper.nil? and !rhs.nil?) xalias = if oper == :alias oper = nil true else false end raise Syntax, "invalid index" unless Array === index and index.all?{|m| Integer === m || String === m || m.is_a?(Alloc) } raise Syntax, "index-op is only allowed on labels" unless index.empty? or oper.nil? unless oper.nil? raise Syntax, "invalid operator's lhs" unless lhs.is_a?(Alloc) end @lhs = lhs @oper = oper @rhs = rhs @index = index @pointer = false @alias = xalias @name = nil end
Public Instance Methods
%(other)
click to toggle source
# File lib/z80/labels.rb, line 1253 def %(other) Alloc.new(self, :%, other) end
&(other)
click to toggle source
# File lib/z80/labels.rb, line 1281 def &(other) Alloc.new(self, :&, other) end
*(other)
click to toggle source
# File lib/z80/labels.rb, line 1245 def *(other) Alloc.new(self, :*, other) end
**(m)
click to toggle source
# File lib/z80/labels.rb, line 1219 def **(m) label = self begin if label.sublabel_access_expression? label.instance_eval do label = @lhs @index.each do |idx| label = label ** idx end end else raise Syntax, "** #{m} not allowed on an expression: #{label.inspect}" if label.expression? label = label.instance_variable_get('@lhs') end end until label.is_a?(Label) label.**(m) end
+(other)
click to toggle source
# File lib/z80/labels.rb, line 1237 def +(other) Alloc.new(self, :+, other) end
+@()
click to toggle source
# File lib/z80/labels.rb, line 1265 def +@ Alloc.new(self, :+@) end
-(other)
click to toggle source
# File lib/z80/labels.rb, line 1241 def -(other) Alloc.new(self, :-, other) end
-@()
click to toggle source
# File lib/z80/labels.rb, line 1269 def -@ Alloc.new(self, :-@) end
/(other)
click to toggle source
# File lib/z80/labels.rb, line 1249 def /(other) Alloc.new(self, :/, other) end
<<(other)
click to toggle source
# File lib/z80/labels.rb, line 1261 def <<(other) Alloc.new(self, :<<, other) end
==(other)
click to toggle source
# File lib/z80/labels.rb, line 1192 def ==(other) case other when Label !expression? && @lhs == other when Alloc %w[@lhs @oper @rhs @index @pointer].all? do |n| self.instance_variable_get(n) == other.instance_variable_get(n) end else false end end
>>(other)
click to toggle source
# File lib/z80/labels.rb, line 1257 def >>(other) Alloc.new(self, :>>, other) end
[](index = nil)
click to toggle source
# File lib/z80/labels.rb, line 1484 def [](index = nil) if index.nil? if @pointer dup else raise Syntax, "pointer not allowed from a sizeof" if @oper == :+@ Alloc.new(self).tap { |l| l.instance_variable_set('@pointer', true) } end else raise Syntax, "indexing is only allowed on a label" unless indexable? if @index.empty? Alloc.new(self) else dup end.tap do |l| lix = l.instance_variable_get('@index') case index when String, Symbol lix << index.to_s when Label, Alloc lix << index.to_alloc when Integer if Integer === lix.last lix[-1]+= index else lix << index end else raise Syntax, "invalid index" end end end end
^(other)
click to toggle source
# File lib/z80/labels.rb, line 1273 def ^(other) Alloc.new(self, :^, other) end
alias?()
click to toggle source
This label can be the only dummy sublabel of another label and as such may exist in both members and dummies.
# File lib/z80/labels.rb, line 1207 def alias?; @alias; end
dummy?()
click to toggle source
# File lib/z80/labels.rb, line 1289 def dummy? @lhs.dummy? || (@rhs.respond_to?(:dummy?) && @rhs.dummy?) end
dup()
click to toggle source
Calls superclass method
# File lib/z80/labels.rb, line 1157 def dup super.tap do |l| l.instance_variable_set('@index', @index.dup) l.instance_variable_set('@name', nil) end end
expression?()
click to toggle source
# File lib/z80/labels.rb, line 1211 def expression? @pointer || !@oper.nil? || !@index.empty? end
immediate?()
click to toggle source
# File lib/z80/labels.rb, line 1293 def immediate? if @index.empty? @lhs.immediate? && (@rhs.respond_to?(:immediate?) ? @rhs.immediate? : true) else label = @lhs return false if label.dummy? @index.all? do |idx| case idx when String label = label ** idx label ? label.immediate? : false when Alloc idx.immediate? else label.immediate? end end # all? end end
indexable?()
click to toggle source
# File lib/z80/labels.rb, line 1476 def indexable? if @alias @lhs.indexable? else !@pointer and @oper.nil? and (@lhs.is_a?(Label) or !@index.empty?) end end
method_missing(m)
click to toggle source
Calls superclass method
# File lib/z80/labels.rb, line 1522 def method_missing(m) if m == :to_ary || m == :to_a || m == :to_hash || m == :to_h super else self.[](m) end end
name=(value)
click to toggle source
# File lib/z80/labels.rb, line 1464 def name=(value) value = value.to_s raise Syntax, "Invalid label name: #{value.inspect}" if value.empty? raise Syntax, "Can't rename already named label: #{@name} != #{value}" if @name and @name != value @name = value end
pointer?()
click to toggle source
# File lib/z80/labels.rb, line 1209 def pointer?; @pointer; end
reinitialize(address, type = 1, reloc = nil, members = nil)
click to toggle source
# File lib/z80/labels.rb, line 1317 def reinitialize(address, type = 1, reloc = nil, members = nil) return self if address == self raise Syntax, "Can't re-initialize" unless @oper.nil? && @index.empty? && @lhs.is_a?(Label) && @lhs.dummy? && !@pointer if address.is_a?(Label) || Integer === address @lhs.reinitialize(address, type, reloc, members) elsif address.is_a?(self.class) lhs, oper, rhs, index, pointer, xalias = %w[@lhs @oper @rhs @index @pointer @alias]. map {|n| address.instance_variable_get(n) } if lhs.is_a?(Label) @lhs.reinitialize(lhs, type, reloc, members) else @lhs = lhs end @oper = oper @rhs = rhs @index = index @pointer = pointer @alias = xalias else raise Syntax, "invalid re-initialize address" end name = if address.respond_to?(:to_name) address.to_name elsif @lhs.to_name end if name and @name and @name != name and @alias name = nil end self.name = name unless name.nil? self end
respond_to_missing?(m, include_private=false)
click to toggle source
# File lib/z80/labels.rb, line 1518 def respond_to_missing?(m, include_private=false) m != :to_ary && m != :to_a && m != :to_hash && m != :to_h end
sublabel?()
click to toggle source
# File lib/z80/labels.rb, line 1313 def sublabel? false end
sublabel_access_expression?()
click to toggle source
# File lib/z80/labels.rb, line 1215 def sublabel_access_expression? !@pointer && @oper.nil? && !@index.empty? && @index.all? {|s| String === s } end
to_aliased_name(start)
click to toggle source
# File lib/z80/labels.rb, line 1354 def to_aliased_name(start) raise CompileError, "not an alias" unless alias? if @lhs.alias? or @lhs.is_a?(Label) @lhs.to_aliased_name(start) else @lhs.to_str end end
to_alloc()
click to toggle source
# File lib/z80/labels.rb, line 1350 def to_alloc; self; end
to_i(start = 0, rel_to = nil, override:nil, prefix:''.freeze, size_of:false)
click to toggle source
rel_to: an absolute address or :self used by ix/iy offset addressing
# File lib/z80/labels.rb, line 1387 def to_i(start = 0, rel_to = nil, override:nil, prefix:''.freeze, size_of:false) rel_to_label = rel_to == :self ? :self : nil arg_to_i = ->(arg, rel_to) do case arg when Integer arg.to_i when Alloc, Label arg.to_alloc.to_i(start, rel_to, override:override) else raise CompileError, "Invalid argument: #{arg.inspect}" end end if !size_of and @name and rel_to_label.nil? if (override_value = override && override[prefix + @name]) return override_value - rel_to.to_i end end val = if @oper.nil? label = @lhs raise CompileError, "can't calculate an address of a directly addressed sublabel: #{label}" if label.sublabel? addr = label.to_i(start, rel_to_label, override:override, prefix:prefix) # allow overrides of simple nested sublabels that only exist when overridden if !size_of and rel_to_label.nil? and !@index.empty? and label.to_name and @index.all?{|idx| idx.is_a?(String)} and (override_value = override && override[prefix + label.to_name + '.'.freeze + @index.join('.'.freeze)]) override_value - rel_to.to_i else @index.each do |idx| case idx when String raise CompileError, "Unknown member: #{idx} of label #{label}." unless sublabel = label ** idx subprefix = prefix + label.to_name + '.'.freeze # a member of struct if sublabel.sublabel? addr += sublabel.to_i elsif label.sublabel? raise CompileError, "Non struct member as a member of a struct label: #{subprefix}#{sublabel.to_name}" # a label else if label.immediate? and !sublabel.immediate? raise CompileError, "Relative member #{subprefix}#{sublabel.to_name} of an absolute label #{label}!" end addr = sublabel.to_i(start, rel_to_label, override:override, prefix:subprefix) end prefix = subprefix label = sublabel else addr+= arg_to_i.call(idx, nil) * label.to_i(size_of:true) end end if size_of label.to_i(size_of:true) else addr end end else raise CompileError, "Can't get a size from an expression: #{self.inspect}" if size_of case @oper when :+@ then return @lhs.to_i(start, rel_to, override:override, size_of:true) when :-@ then -arg_to_i.call(@lhs, rel_to_label) when :~ then ~arg_to_i.call(@lhs, rel_to_label) else arg_to_i[@lhs, rel_to_label].send(@oper, arg_to_i[@rhs, rel_to_label]) end end if Integer === rel_to val - rel_to else val end end
to_label(_)
click to toggle source
# File lib/z80/labels.rb, line 1352 def to_label(_); self; end
to_name(info=false)
click to toggle source
# File lib/z80/labels.rb, line 1471 def to_name(info=false) return @name if @name return @lhs.to_name(info) if !expression? end
to_str()
click to toggle source
# File lib/z80/labels.rb, line 1363 def to_str return @name if @name return @lhs.to_str if @pointer case @oper when nil @lhs.to_name(true).to_s + @index.map {|idx| case idx when String '.' + idx else "[#{idx}]" end }.join when :+@ "(+#{@lhs})" when :~, :-@ "#{@oper.to_s[0]}(#{@lhs})" else "(#{@lhs}#{@oper}#{@rhs})" end end
Also aliased as: to_s
|(other)
click to toggle source
# File lib/z80/labels.rb, line 1277 def |(other) Alloc.new(self, :|, other) end
~()
click to toggle source
# File lib/z80/labels.rb, line 1285 def ~ Alloc.new(self, :~) end