class ZXLib::Basic::Vars

A container class for collecting and inspecting ZX-Spectrum's Basic program variables.

Variables can be created for Basic programs and saved together with them without the need to ever initialize those variables from Basic program itself. Very large strings or arrays can be created this way that would normaly not fit in both program's memory and variable area memory when being used by the program.

Example:

require 'date'
require 'zxlib/basic'

program = Basic.parse_source <<-END
   1 GO SUB 1000
     LOAD ""DATA m$()
     GO SUB 1000
 999 STOP
1000 REM notice m$ is never initialized in the program itself
     INPUT "month number: ", mn
     IF INT mn>=1 AND INT mn<=12 THEN PRINT m$(INT mn): GO TO 1000
     RETURN
END
program.start = 1
# let's create m$ variable containing abbreviated month names and append it to the program
# this is equivalent to basic command DIM m$(12,3) and LET m$(..) = "..."
program.vars << Basic::Variable.new_char_array('m$', [12, 3], Date::ABBR_MONTHNAMES[1..12])
# let's save the program together with the m$ variable
program.save_tap 'askmonth.tap'
# now let's create m$ variable containing full month names
monthnames = Date::MONTHNAMES[1..12]
maxlen = monthnames.max_by(&:length).length
mnames_var = Basic::Variable.new_char_array('m$', [12, maxlen], monthnames)
# we'll save it to a character array TAP file appending it to the file created above
mnames_var.save_tap 'askmonth.tap', append: true, name: 'longmonths'

Attributes

code[RW]

A binary string representing variables as an image of ZX-Spectrum's VARS memory area.

data[RW]

A binary string representing variables as an image of ZX-Spectrum's VARS memory area.

Public Class Methods

new(data='') click to toggle source

Creates an instance of Basic::Vars.

Optionally provide VARS data as a binary string.

# File lib/zxlib/basic.rb, line 1264
def initialize(data='')
        data = data.data if data.is_a?(self.class)
        raise ArgumentError, "data must be a binary string" unless String === data
        @data = data.force_encoding(Encoding::BINARY)
end
program_text_to_string(text) click to toggle source

Converts a UTF-8 text string to a binary string encoded in a form suitable for ZX-Spectrum's Basic variables or other ROM routines that print or otherwise handle strings.

The text string may contain special characters and escape sequences as explained here: Program.to_source. The quotes (“) must be duplicated.

This is the opposite operation of Vars.string_to_program_text.

Example:

Basic::Vars.program_text_to_string('foo""`AT 5,2`©')
=> "foo\"\x16\x05\x02\x7F"
Basic::Vars.program_text_to_string('foo""`AT 5,2``(c)`')
=> "foo\"\x16\x05\x02\x7F"
# File lib/zxlib/basic.rb, line 1351
def Vars.program_text_to_string(text)
        buffer = ''
        tokenizer = Tokenizer.new text
        while token = tokenizer.next_token
                buffer << token.to_chars
                if token.quote?
                        token = tokenizer.next_token
                        break if token.nil?
                        unless token.quote?
                                raise SyntaxError, "quote must be duplicated in a string at: #{token.index}"
                        end
                end
        end
        buffer
end
string_to_program_text(data, ascii_only:false, se:false) click to toggle source

Converts a ZX-Spectrum's string variable data to a source UTF-8 text with special and control characters encoded in a way explained here: Program.to_source.

This is the opposite operation of Vars.program_text_to_string.

Passing :ascii_only as true will render escape sequences instead of non-ascii characters.

Example:

Basic::Vars.string_to_program_text("foo\"\x16\x05\x02\x7F")
=> "foo\"\"`AT 5,2`©"
Basic::Vars.string_to_program_text("foo\"\x16\x05\x02\x7F", ascii_only: true)
=> "foo\"\"`AT 5,2``(c)`"
# File lib/zxlib/basic.rb, line 1334
def Vars.string_to_program_text(data, ascii_only:false, se:false)
        Tokenizer.program_data_to_text(data, true, true, ascii_only, se)
end

Public Instance Methods

<<(var) click to toggle source

Adds a Basic::Variable to self.

# File lib/zxlib/basic.rb, line 1276
def <<(var)
        raise ArgumentError unless var.respond_to?(:data)
        self.data << var.data
end
[](index) click to toggle source

Returns a Basic::Variable at index or an array of variables if Range is given.

# File lib/zxlib/basic.rb, line 1309
def [](index)
        if Integer === index
                each_var.with_index {|v, i| break v if index == i}
        elsif index.respond_to?(:===)
                each_var.with_index.select {|v, i| index === i}
        end
end
clear!() click to toggle source

Clears all variables.

# File lib/zxlib/basic.rb, line 1271
def clear!
        @data = ''
end
each_var(&block) click to toggle source

Returns an Enumerator of every Basic::Variable found in self.

# File lib/zxlib/basic.rb, line 1282
def each_var(&block)
        data = @data
        enu = ::Enumerator.new do |y|
                while !data.empty?
                        v = Variable.from_data data
                        data = data.byteslice(v.bytesize..-1)
                        y << v
                end
        end
        if block_given?
                enu.each(&block)
        else
                enu
        end
end
get(name) click to toggle source

Returns the first Basic::Variable if found by the given name.

# File lib/zxlib/basic.rb, line 1304
def get(name)
        each_var.find{|v| v.name.casecmp(name).zero? }
end
to_a() click to toggle source

Returns an array of every Basic::Variable found in self.

# File lib/zxlib/basic.rb, line 1299
def to_a
        each_var.to_a
end
to_s() click to toggle source

Returns all variables in a BASIC-like text format.

# File lib/zxlib/basic.rb, line 1318
def to_s
        each_var.map(&:to_s).join("\n")
end