class TestML::Runtime
Attributes
base[RW]
bridge[RW]
compiler[RW]
error[RW]
function[RW]
global[RW]
library[RW]
skip[RW]
testml[RW]
Public Class Methods
new(attributes={})
click to toggle source
# File lib/testml/runtime.rb, line 15 def initialize(attributes={}) attributes.each { |k,v| self.send "#{k}=", v } $TestMLRuntimeSingleton = self @base ||= 'test' end
Public Instance Methods
apply_signature(function, args)
click to toggle source
# File lib/testml/runtime.rb, line 45 def apply_signature(function, args) signature = function.signature || [] fail "Function received #{args.size} args but expected #{signature.size}" \ if ! signature.empty? and args.size != signature.size @function.setvar('Self', function) signature.each_with_index do |sig_elem, i| arg = args[i] arg = run_expression(arg) \ if arg.kind_of? TestML::Expression function.setvar(sig_elem, arg) end end
compile_testml()
click to toggle source
# File lib/testml/runtime.rb, line 198 def compile_testml fail "'testml' document required but not found" \ unless @testml if @testml !~ /\n/ @testml =~ /(.*)\/(.*)/ or fail testml = $2 @base = @base + '/' + $1 @testml = read_testml_file testml end @function = @compiler.new.compile(@testml) end
get_label()
click to toggle source
# File lib/testml/runtime.rb, line 231 def get_label label = @function.getvar('Label') or return label = label.value label.gsub(/\$(\w+)/) {|m| replace_label($1)} end
get_point(name)
click to toggle source
# File lib/testml/runtime.rb, line 173 def get_point(name) value = @function.getvar('Block').points[name] or return if value.sub!(/\n+\z/, "\n") and value == "\n" value = '' end return TestML::Str.new(value) end
initialize_runtime()
click to toggle source
# File lib/testml/runtime.rb, line 210 def initialize_runtime @global = @function.outer @global.setvar('Block', TestML::Block.new) @global.setvar('Label', TestML::Str.new('$BlockLabel')) @global.setvar('True', TestML::Constant::True) @global.setvar('False', TestML::Constant::False) @global.setvar('None', TestML::Constant::None) @global.setvar('TestNumber', TestML::Num.new(0)) @global.setvar('Library', TestML::List.new) library = @function.getvar('Library') [@bridge, @library].each do |lib| if lib.kind_of? Array lib.each {|l| library.push(l.new)} else library.push(lib.new) end end end
lookup_callable(name)
click to toggle source
# File lib/testml/runtime.rb, line 159 def lookup_callable(name) @function.getvar('Library').value.each do |library| if library.respond_to?(name) function = lambda do |*args| library.method(name).call(*args) end callable = TestML::Callable.new(function) @function.setvar(name, callable) return callable end end return nil end
read_testml_file(file)
click to toggle source
# File lib/testml/runtime.rb, line 249 def read_testml_file file path = @base + '/' + file File.read(path) end
replace_label(var)
click to toggle source
# File lib/testml/runtime.rb, line 237 def replace_label(var) block = @function.getvar('Block') if var == 'BlockLabel' block.label elsif v = block.points[var] v.sub!(/\n.*/m, '') v.strip elsif v = function.getvar(var) v.value end end
run()
click to toggle source
# File lib/testml/runtime.rb, line 21 def run compile_testml initialize_runtime run_function(@function, []) end
run_assertion(left, assert)
click to toggle source
# File lib/testml/runtime.rb, line 79 def run_assertion left, assert method_ = method(('assert_' + assert.name).to_sym) @function.getvar('TestNumber').value += 1 if assert.expr method_.call(left, run_expression(assert.expr)) else method_.call(left) end end
run_assignment(assignment)
click to toggle source
# File lib/testml/runtime.rb, line 72 def run_assignment(assignment) @function.setvar( assignment.name, run_expression(assignment.expr) ) end
run_call(call, context=nil)
click to toggle source
# File lib/testml/runtime.rb, line 115 def run_call call, context=nil if call.kind_of? TestML::Object return call end if call.kind_of? TestML::Function return call end if call.kind_of? TestML::Point return get_point(call.name) end if call.kind_of? TestML::Call name = call.name callable = @function.getvar(name) || get_point(name) || lookup_callable(name) || fail("Can't locate '#{name}' callable") if callable.kind_of? TestML::Object return callable end return callable unless call.args or !context.nil? call.args ||= [] args = call.args.map{|arg| run_expression(arg)} args.unshift context if !context.nil? if callable.kind_of? TestML::Callable begin value = callable.value.call(*args) rescue @error = $!.message # @error = "#{$!.class}: #{$!.message}\n at #{$!.backtrace[0]}" return TestML::Error.new(@error) end fail "'#{name}' did not return a TestML::Object object" \ unless value.kind_of? TestML::Object return value end if callable.kind_of? TestML::Function return run_function(callable, args) end fail end fail end
run_expression(expr)
click to toggle source
# File lib/testml/runtime.rb, line 91 def run_expression(expr) context = nil @error = nil if expr.kind_of? TestML::Expression calls = expr.calls.clone fail if calls.size <= 1 context = run_call(calls.shift) calls.each do |call| if @error next unless call.kind_of?(TestML::Call) and call.name == 'Catch' end context = run_call(call, context) end else context = run_call(expr) end if @error fail @error end return context end
run_function(function, args)
click to toggle source
# File lib/testml/runtime.rb, line 27 def run_function(function, args) signature = apply_signature(function, args) parent = @function @function = function function.statements.each do |statement| if statement.kind_of? TestML::Assignment run_assignment(statement) else run_statement(statement) end end @function = parent return end
run_statement(statement)
click to toggle source
# File lib/testml/runtime.rb, line 60 def run_statement(statement) blocks = select_blocks(statement.points || []) blocks.each do |block| @function.setvar('Block', block) if block != 1 result = run_expression(statement.expr) if assertion = statement.assert run_assertion(result, assertion) end end end
select_blocks(wanted)
click to toggle source
# File lib/testml/runtime.rb, line 181 def select_blocks(wanted) return [1] if wanted.empty? selected = [] @function.data.each do |block| points = block.points next if points.key?('SKIP') next unless wanted.all?{|point| points.key?(point)} if points.key?('ONLY') selected = [block] break end selected << block break if points.key?('LAST') end return selected end