Stream < EmptyObject {
Patterns < EmptyObject { Base < Common::Patterns::Base { } End < Base { construct: Constructions::End.new } Item < Base { var checks construct: Constructions::Item.new(checks: checks) } } Constructions < EmptyObject { Base < Common::Constructions::Base { } End < Base { } Item < Base { var checks } } Constructions << { End << { bytecode: |g| { # Just verify the index is NOT within range g.push_subject; g.send(:size, 0) g.push_idx g.send(:">", 1) g.goto_if_true(g.overall_fail) }} Item << { bytecode: |g| { many_checks = checks.size > 1 local_fail = g.overall_fail if(many_checks) { local_fail = g.new_label } # First, verify the index is within range g.push_subject; g.send(:size, 0) g.push_idx g.send(:">", 1) g.goto_if_false(g.overall_fail) checks.empty? || ( # Retrieve the item g.push_subject_at_idx # Try each check on the item until one fails checks.each |method, args, result| { if(many_checks) { g.dup_top } # Run the given method (or other check) with the given args (if applicable) :self.equal?(method) &? ( # Do nothing; let the self pass through to result checking. ) ?? (method.is_a?(Symbol) &? ( args.each |arg| { g.push_literal_or_array(arg) } g.send(method, args.size) ) ?? (method.is_a?(Proc) &? ( code = method.block.compiled_code g.push_literal(code) # TODO: add a move_up instruction and avoid all of these swap_stacks g.swap_stack; g.push_literal(code.name) # name g.swap_stack; g.push_cpath_top; g.find_const(:Myco) # module g.swap_stack # receiver (the item) g.push_literal_array(args) # args g.push_nil # block g.send(:invoke, 5) ) ?? ( raise("Unknown type of check method: "method"") ))) # Compare the result of the check with the given expected result null.equal?(result) &? ( g.goto_if_not_nil(local_fail) ) ?? ((false.equal?(result) || true.equal?(result) || result.is_a?(Symbol) || result.is_a?(Fixnum)) &? ( g.push_literal(result) g.goto_if_not_equal(local_fail) ) ?? ( g.push_literal_or_array(result) g.send(:"==", 1) g.goto_if_false(local_fail) )) } if(many_checks) { local_done = g.new_label g.pop # The dup'd subject_at_idx g.goto(local_done) local_fail.set! g.pop # The dup'd subject_at_idx g.goto(g.overall_fail) local_done.set! } ) g.meta_push_1 g.increment_idx }} }
}