module Yadriggy::Assert

Power assert by Yadriggy

Public Class Methods

assert(&block) click to toggle source

Checks the given assertion is correct and prints the result if the assertion fails.

@param [Proc] block the assertion.

# File lib/yadriggy/assert.rb, line 13
def self.assert(&block)
  reason = Reason.new
  begin
    res = assertion(reason, block)
    puts_reason(reason) unless res
    return res
  rescue AssertFailure => evar
    puts_reason(evar.reason, evar)
    raise evar.cause
  end
end
assertion(reason, block) click to toggle source

Checks the given assertion is correct.

@param [Reason] reason the object where the reason that the assertion

fails will be stored.

@param [Proc] block the assertion. @return [Object] the result of executing the given block.

# File lib/yadriggy/assert.rb, line 41
def self.assertion(reason, block)
  return if block.nil?
  ast = Yadriggy::reify(block)
  begin
    results = {}
    reason.setup(ast.tree.body, results)
    run_ast(ast.tree.body, block.binding, results)[1]
  rescue => evar
    raise AssertFailure.new(reason, evar.message, evar)
  end
end
eval_by_ruby(ast, blk_binding) click to toggle source

@api private Eval the AST by the RubyVM @return [Pair<String,Object>] an array. The first element is the source code

and the second element is the resulting value.
# File lib/yadriggy/assert.rb, line 217
def self.eval_by_ruby(ast, blk_binding)
  src = PrettyPrinter.ast_to_s(ast)
  loc = ast.source_location
  [src, eval(src, blk_binding, loc[0], loc[1])]
end
puts_reason(reason, evar=nil) click to toggle source

@api private

# File lib/yadriggy/assert.rb, line 26
def self.puts_reason(reason, evar=nil)
  puts '--- Yadriggy::Assert ---'
  print evar.cause.class.name, ': ' if evar&.cause
  puts evar.message if evar&.message
  puts(reason.ast.source_location_string)
  puts(reason.show)
  puts '------------------------'
end
run_ast(ast, blk_binding, results) click to toggle source

@api private Executes the given AST and records the result. @param [ASTnode] ast the given AST. @param [Binding] blk_binding the binding for executing the AST. @param [Hash<ASTnode,Pair<String,Object>>] results a map from ASTs

to their source and values.

@return [Pair<String,Object>] the result of the execution of the given AST.

It is also recorded in `results`.
The first element is the source code and the second one is the resulting value.
# File lib/yadriggy/assert.rb, line 179
def self.run_ast(ast, blk_binding, results)
  if ast.is_a?(Paren)
    res = run_ast(ast.expression, blk_binding, results)
    src = "(#{res[0]})"
    results[ast] = [src, res[1]]
  elsif ast.is_a?(Call) && ast.block_arg.nil? && ast.block.nil?
    if ast.receiver.nil?
      receiver = ['self', blk_binding.eval('self')]
    else
      receiver = run_ast(ast.receiver, blk_binding, results)
    end
    args = ast.args.map {|e| run_ast(e, blk_binding, results) }
    arg_values = args.map {|e| e[1] }
    res = receiver[1].send(ast.name.name, *arg_values)
    arg_src = args.each_with_object('') do |e, code|
      code << ', ' if code.size > 0
      code << e[0]
    end
    src = "#{receiver[0]}.#{ast.name.name.to_s}(#{arg_src.to_s})"
    results[ast] = [src, res]
  elsif ast.is_a?(Binary)
    left_value = run_ast(ast.left, blk_binding, results)
    right_value = run_ast(ast.right, blk_binding, results)
    res = left_value[1].send(ast.op, right_value[1])
    results[ast] = ["#{left_value[0]} #{ast.op.to_s} #{right_value[0]}", res]
  elsif ast.is_a?(Unary)
    value = run_ast(ast.operand, blk_binding, results)
    res = value[1].send(ast.op)
    results[ast] = ["#{ast.real_operator.to_s}#{value[0]}", res]
  else
    results[ast] = eval_by_ruby(ast, blk_binding)
  end
end