Skip to content

Commit

Permalink
work on getting @{not} to work with target rule names
Browse files Browse the repository at this point in the history
  • Loading branch information
Andy Newton committed Dec 15, 2017
1 parent 61f49a7 commit d1f32b9
Show file tree
Hide file tree
Showing 10 changed files with 312 additions and 72 deletions.
41 changes: 26 additions & 15 deletions lib/jcr/evaluate_array_rules.rb
Expand Up @@ -45,19 +45,24 @@ def initialize( current_behavior = nil )
end
end

def self.evaluate_array_rule jcr, rule_atom, data, econs, behavior = nil
def self.evaluate_array_rule jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil

push_trace_stack( econs, jcr )
trace( econs, "Evaluating array rule starting at #{slice_to_s(jcr)} against", data )
trace_def( econs, "array", jcr, data )
retval = evaluate_array( jcr, rule_atom, data, econs, behavior )
if behavior
trace( econs, "Evaluating group in array rule starting at #{slice_to_s(jcr)} against", data )
trace_def( econs, "array group", jcr, data )
else
trace( econs, "Evaluating array rule starting at #{slice_to_s(jcr)} against", data )
trace_def( econs, "array", jcr, data )
end
retval = evaluate_array( jcr, rule_atom, data, econs, behavior, target_annotations )
trace_eval( econs, "Array", retval, jcr, data, "array" )
pop_trace_stack( econs )
return retval

end

def self.evaluate_array jcr, rule_atom, data, econs, behavior = nil
def self.evaluate_array jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil

rules, annotations = get_rules_and_annotations( jcr )

Expand All @@ -76,20 +81,24 @@ def self.evaluate_array jcr, rule_atom, data, econs, behavior = nil

# if the data is not an array
return evaluate_not( annotations,
Evaluation.new( false, "#{data} is not an array #{raised_rule(jcr,rule_atom)}"), econs ) unless data.is_a? Array
Evaluation.new( false, "#{data} is not an array #{raised_rule(jcr,rule_atom)}"),
econs, target_annotations ) unless data.is_a? Array

# if the array is zero length and there are zero sub-rules (it is suppose to be empty)
return evaluate_not( annotations,
Evaluation.new( true, nil ), econs ) if rules.empty? && data.empty?
Evaluation.new( true, nil ), econs, target_annotations ) if rules.empty? && data.empty?

# if the array is not empty and there are zero sub-rules (it is suppose to be empty)
return evaluate_not( annotations,
Evaluation.new( false, "Non-empty array for #{raised_rule(jcr,rule_atom)}" ), econs ) if rules.empty? && data.length != 0
Evaluation.new( false, "Non-empty array for #{raised_rule(jcr,rule_atom)}" ),
econs, target_annotations ) if rules.empty? && data.length != 0

if ordered
return evaluate_not( annotations, evaluate_array_rule_ordered( rules, rule_atom, data, econs, behavior ), econs )
return evaluate_not( annotations, evaluate_array_rule_ordered( rules, rule_atom, data, econs, behavior ),
econs, target_annotations )
else
return evaluate_not( annotations, evaluate_array_rule_unordered( rules, rule_atom, data, econs, behavior ), econs )
return evaluate_not( annotations, evaluate_array_rule_unordered( rules, rule_atom, data, econs, behavior ),
econs, target_annotations )
end
end

Expand All @@ -115,7 +124,8 @@ def self.evaluate_array_rule_ordered jcr, rule_atom, data, econs, behavior = nil
# groups require the effects of the evaluation to be discarded if they are false
# groups must also be given the entire array

if (grule = get_group(rule, econs))
grule, target_annotations = get_group( rule, econs )
if grule

if repeat_min == 0
retval = Evaluation.new( true, nil )
Expand All @@ -126,7 +136,7 @@ def self.evaluate_array_rule_ordered jcr, rule_atom, data, econs, behavior = nil
else
group_behavior = ArrayBehavior.new( behavior )
group_behavior.last_index = array_index
retval = evaluate_rule( grule, rule_atom, data, econs, group_behavior )
retval = evaluate_rule( grule, rule_atom, data, econs, group_behavior, target_annotations )
if retval.success
behavior.checked_hash.merge!( group_behavior.checked_hash )
array_index = group_behavior.last_index
Expand All @@ -141,7 +151,7 @@ def self.evaluate_array_rule_ordered jcr, rule_atom, data, econs, behavior = nil
break if array_index == data.length
group_behavior = ArrayBehavior.new( behavior )
group_behavior.last_index = array_index
e = evaluate_rule( grule, rule_atom, data, econs, group_behavior )
e = evaluate_rule( grule, rule_atom, data, econs, group_behavior, target_annotations )
if e.success
behavior.checked_hash.merge!( group_behavior.checked_hash )
array_index = group_behavior.last_index
Expand Down Expand Up @@ -218,14 +228,15 @@ def self.evaluate_array_rule_unordered jcr, rule_atom, data, econs, behavior = n
# groups require the effects of the evaluation to be discarded if they are false
# groups must also be given the entire array

if (grule = get_group(rule, econs))
grule,target_annotations = get_group(rule, econs)
if grule

successes = 0
for i in 0..repeat_max-1
group_behavior = ArrayBehavior.new( behavior )
group_behavior.last_index = highest_index
group_behavior.ordered = false
e = evaluate_rule( grule, rule_atom, data, econs, group_behavior )
e = evaluate_rule( grule, rule_atom, data, econs, group_behavior, target_annotations )
if e.success
highest_index = group_behavior.last_index
behavior.checked_hash.merge!( group_behavior.checked_hash )
Expand Down
12 changes: 6 additions & 6 deletions lib/jcr/evaluate_group_rules.rb
Expand Up @@ -26,34 +26,34 @@

module JCR

def self.evaluate_group_rule jcr, rule_atom, data, econs, behavior = nil
def self.evaluate_group_rule jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil

push_trace_stack( econs, jcr )
trace( econs, "Evaluating group rule against ", data )
trace_def( econs, "group", jcr, data )
retval = evaluate_group( jcr, rule_atom, data, econs, behavior )
retval = evaluate_group( jcr, rule_atom, data, econs, behavior, target_annotations )
trace_eval( econs, "Group", retval, jcr, data, "group" )
pop_trace_stack( econs )
return retval

end

def self.evaluate_group jcr, rule_atom, data, econs, behavior = nil
def self.evaluate_group jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil

rules, annotations = get_rules_and_annotations( jcr )

retval = nil

rules.each do |rule|
if rule[:choice_combiner] && retval && retval.success
return evaluate_not( annotations, retval, econs ) # short circuit
return evaluate_not( annotations, retval, econs, target_annotations ) # short circuit
elsif rule[:sequence_combiner] && retval && !retval.success
return evaluate_not( annotations, retval, econs ) # short circuit
return evaluate_not( annotations, retval, econs, target_annotations ) # short circuit
end
retval = evaluate_rule( rule, rule_atom, data, econs, behavior )
end

return evaluate_not( annotations, retval, econs )
return evaluate_not( annotations, retval, econs, target_annotations )
end

def self.group_to_s( jcr, shallow=true)
Expand Down
13 changes: 7 additions & 6 deletions lib/jcr/evaluate_member_rules.rb
Expand Up @@ -25,19 +25,19 @@

module JCR

def self.evaluate_member_rule jcr, rule_atom, data, econs
def self.evaluate_member_rule jcr, rule_atom, data, econs, behavior, target_annotations

push_trace_stack( econs, jcr )
trace( econs, "Evaluating member rule for key '#{data[0]}' starting at #{slice_to_s(jcr)} against ", data[1])
trace_def( econs, "member", jcr, data )
retval = evaluate_member( jcr, rule_atom, data, econs )
retval = evaluate_member( jcr, rule_atom, data, econs, behavior, target_annotations )
trace_eval( econs, "Member", retval, jcr, data, "member" )
pop_trace_stack( econs )
return retval

end

def self.evaluate_member jcr, rule_atom, data, econs
def self.evaluate_member jcr, rule_atom, data, econs, behavior, target_annotations

# unlike the other evaluate functions, here data is not just the json data.
# it is an array, the first element being the member name or regex and the
Expand Down Expand Up @@ -68,13 +68,14 @@ def self.evaluate_member jcr, rule_atom, data, econs
end

if member_match
e = evaluate_rule( rule, rule_atom, data[ 1 ], econs )
e = evaluate_rule( rule, rule_atom, data[ 1 ], econs, nil, target_annotations )
e.member_found = true
return evaluate_not( annotations, e, econs )
return evaluate_not( annotations, e, econs, target_annotations )
end

return evaluate_not( annotations,
Evaluation.new( false, "#{match_spec} does not match #{data[0]} for #{raised_rule( jcr, rule_atom)}" ), econs )
Evaluation.new( false, "#{match_spec} does not match #{data[0]} for #{raised_rule( jcr, rule_atom)}" ),
econs, target_annotations )

end

Expand Down
42 changes: 25 additions & 17 deletions lib/jcr/evaluate_object_rules.rb
Expand Up @@ -27,33 +27,40 @@ def initialize
end
end

def self.evaluate_object_rule jcr, rule_atom, data, econs, behavior = nil
def self.evaluate_object_rule jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil

push_trace_stack( econs, jcr )
trace( econs, "Evaluating object rule starting at #{slice_to_s(jcr)} against", data )
trace_def( econs, "object", jcr, data )
retval = evaluate_object( jcr, rule_atom, data, econs, behavior )
if behavior
trace( econs, "Evaluating group in object rule starting at #{slice_to_s(jcr)} against", data )
trace_def( econs, "object group", jcr, data )
else
trace( econs, "Evaluating object rule starting at #{slice_to_s(jcr)} against", data )
trace_def( econs, "object", jcr, data )
end
retval = evaluate_object( jcr, rule_atom, data, econs, behavior, target_annotations )
trace_eval( econs, "Object", retval, jcr, data, "object" )
pop_trace_stack( econs )
return retval

end

def self.evaluate_object jcr, rule_atom, data, econs, behavior = nil
def self.evaluate_object jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil

rules, annotations = get_rules_and_annotations( jcr )

# if the data is not an object (Hash)
return evaluate_not( annotations,
Evaluation.new( false, "#{data} is not an object for #{raised_rule(jcr,rule_atom)}"), econs ) unless data.is_a? Hash
Evaluation.new( false, "#{data} is not an object for #{raised_rule(jcr,rule_atom)}"),
econs, target_annotations ) unless data.is_a? Hash

# if the object has no members and there are zero sub-rules (it is suppose to be empty)
return evaluate_not( annotations,
Evaluation.new( true, nil ), econs ) if rules.empty? && data.length == 0
Evaluation.new( true, nil ), econs, target_annotations ) if rules.empty? && data.length == 0

# if the object has members and there are zero sub-rules (it is suppose to be empty)
return evaluate_not( annotations,
Evaluation.new( false, "Non-empty object for #{raised_rule(jcr,rule_atom)}" ), econs ) if rules.empty? && data.length != 0
Evaluation.new( false, "Non-empty object for #{raised_rule(jcr,rule_atom)}" ),
econs, target_annotations ) if rules.empty? && data.length != 0

retval = nil
behavior = ObjectBehavior.new unless behavior
Expand All @@ -64,7 +71,7 @@ def self.evaluate_object jcr, rule_atom, data, econs, behavior = nil
if rule[:choice_combiner] && retval && retval.success
next
elsif rule[:sequence_combiner] && retval && !retval.success
return evaluate_not( annotations, retval, econs ) # short circuit
return evaluate_not( annotations, retval, econs, target_annotations ) # short circuit
end

repeat_min, repeat_max, repeat_step = get_repetitions( rule, econs )
Expand All @@ -76,13 +83,14 @@ def self.evaluate_object jcr, rule_atom, data, econs, behavior = nil
# Also, groups must be handed the entire object, not key/values
# as member rules use.

if (grule = get_group(rule, econs))
grule,gtarget_annotations = get_group(rule, econs)
if grule

successes = 0
for i in 0..repeat_max-1
group_behavior = ObjectBehavior.new
group_behavior.checked_hash.merge!( behavior.checked_hash )
e = evaluate_rule( grule, rule_atom, data, econs, group_behavior )
e = evaluate_rule( grule, rule_atom, data, econs, group_behavior, gtarget_annotations )
if e.success
behavior.checked_hash.merge!( group_behavior.checked_hash )
successes = successes + 1
Expand All @@ -109,7 +117,7 @@ def self.evaluate_object jcr, rule_atom, data, econs, behavior = nil
# if defined by a name, and not a regex, just pluck it from the object
# and short-circuit the enumeration

lookahead = get_leaf_rule( rule, econs )
lookahead, ltarget_annotations = get_leaf_rule( rule, econs )
lrules, lannotations = get_rules_and_annotations( lookahead[:member_rule] )
if lrules[0][:member_name]

Expand All @@ -118,13 +126,13 @@ def self.evaluate_object jcr, rule_atom, data, econs, behavior = nil
v = data[k]
if v
unless behavior.checked_hash[k]
e = evaluate_rule(rule, rule_atom, [k, v], econs, nil)
e = evaluate_rule(rule, rule_atom, [k, v], econs, nil, nil)
behavior.checked_hash[k] = e.success
repeat_results[ k ] = v if e.success
end
else
trace( econs, "No member '#{k}' found in object.")
e = evaluate_rule(rule, rule_atom, [nil, nil], econs, nil)
e = evaluate_rule(rule, rule_atom, [nil, nil], econs, nil, nil)
repeat_results[ nil ] = nil if e.success
end

Expand All @@ -137,7 +145,7 @@ def self.evaluate_object jcr, rule_atom, data, econs, behavior = nil
repeat_results = data.select do |k,v|
unless behavior.checked_hash[k]
if i < repeat_max
e = evaluate_rule(rule, rule_atom, [k, v], econs, nil)
e = evaluate_rule(rule, rule_atom, [k, v], econs, nil, nil)
behavior.checked_hash[k] = e.success
i = i + 1 if e.success
found = true if e.member_found
Expand All @@ -147,7 +155,7 @@ def self.evaluate_object jcr, rule_atom, data, econs, behavior = nil
end
unless found
trace( econs, "No member matching #{regex} found in object.")
e = evaluate_rule(rule, rule_atom, [nil, nil], econs, nil)
e = evaluate_rule(rule, rule_atom, [nil, nil], econs, nil, nil)
repeat_results[ nil ] = nil if e.success
end

Expand All @@ -169,7 +177,7 @@ def self.evaluate_object jcr, rule_atom, data, econs, behavior = nil

end # end if grule else

return evaluate_not( annotations, retval, econs )
return evaluate_not( annotations, retval, econs, target_annotations )
end

def self.object_to_s( jcr, shallow=true )
Expand Down

0 comments on commit d1f32b9

Please sign in to comment.