class Pione::PNML::ConstituentRuleBuilder

ConstituentRuleBuilder builds constituent rule definitions.

Public Class Methods

new(net, net_name, env) click to toggle source

@param net [PNML::Net]

net

@param net_name [String]

name of the net

@param env [Lang::Environment]

language environment
# File lib/pione/pnml/compiler.rb, line 98
def initialize(net, net_name, env)
  @net = net
  @net_name = net_name
  @env = env
end

Public Instance Methods

build() click to toggle source

Build a consituent rule definitions by transitions in the net.

@return [Array(Array<RuleDefinition>,Array)]

# File lib/pione/pnml/compiler.rb, line 107
def build
  definition = build_rule_definition_table()

  # save all inner rules
  rules = definition.values.compact
  flow_elements = definition.values.compact

  # conditional branch
  @net.transitions.each do |transition|
    inputs = @net.find_all_places_by_target_id(transition.id).select do |place|
      Perspective.data_place?(@env, place)
    end.map {|input| InputData.new(input)}

    if Perspective.if_transition?(@env, transition)
      flow_elements << create_if_branch(transition, definition, inputs, flow_elements)
    elsif Perspective.case_transition?(@env, transition)
      flow_elements << create_case_branch(transition, definition, inputs, flow_elements)
    end
  end

  return [rules, flow_elements]
end

Private Instance Methods

build_rule_definition_table() click to toggle source

Build rule definition table.

@return [Hash{String=>RuleDefinition}]

relatioin table between transition ID and rule definition
# File lib/pione/pnml/compiler.rb, line 136
def build_rule_definition_table
  return @net.transitions.each_with_object({}) do |transition, table|
    if Perspective.rule_transition?(@env, transition)
      type = :action
      rule_name = LabelExtractor.extract_rule_expr(transition.name)
      is_external = Perspective.external_rule_transition?(@env, transition)
      rule = RuleDefinition.new(rule_name, type, is_external, @net_name, table.size)

      # setup rule conditions
      rule.inputs = find_inputs(transition)
      rule.outputs = find_outputs(transition)
      rule.params = find_params(transition)
      rule.constraints = find_constraints(transition)
      rule.source_tickets = find_source_tickets(transition)
      rule.target_tickets = find_target_tickets(transition)
      rule.features = find_features(transition)

      table[transition.id] = rule
    end
  end
end
create_case_branch(transition, definition, inputs, flow_elements) click to toggle source

Create a case-branch from the transiton.

@param transition [PNML::Transition]

base transition

@return [ConditionalBranch]

conditional branch
# File lib/pione/pnml/compiler.rb, line 333
def create_case_branch(transition, definition, inputs, flow_elements)
  expr = @net.find_place_by_source_id(transition.id)

  nodes = @net.find_all_transitions_by_source_id(expr.id)
  keys_when = nodes.select{|node| Perspective.when_transition?(@env, node)}
  key_else = nodes.find{|node| Perspective.else_transition?(@env, node)}

  branch = ConditionalBranch.new(:case, expr.name)

  keys_when.each do |key|
    find_next_rules(key).each do |transition|
      rule = definition[transition.id]
      rule.inputs += inputs
      flow_elements.delete(rule)
      conditional_value_place = @net.find_place_by_source_id(key.id)
      branch.table[conditional_value_place.name] << rule
    end
  end

  if key_else
    find_next_rules(key_else).each do |transition|
      rule = definition[transition.id]
      rule.inputs += inputs
      flow_elements.delete(rule)
      branch.table[:else] << rule
    end
  end

  return branch
end
create_if_branch(transition, definition, inputs, flow_elements) click to toggle source

Create a if-branch from the transiton.

@param transition [PNML::Transition]

base transition

@return [ConditionalBranch]

conditional branch
# File lib/pione/pnml/compiler.rb, line 299
def create_if_branch(transition, definition, inputs, flow_elements)
  condition = @net.find_place_by_source_id(transition.id)

  nodes = @net.find_all_transitions_by_source_id(condition.id)
  key_then = nodes.find{|node| Perspective.then_transition?(@env, node)}
  key_else = nodes.find{|node| Perspective.else_transition?(@env, node)}

  branch = ConditionalBranch.new(:if, condition.name)

  find_next_rules(key_then).each do |transition|
    rule = definition[transition.id]
    rule.inputs += inputs
    flow_elements.delete(rule)
    branch.table[:then] << rule
  end

  if key_else
    find_next_rules(key_else).each do |transition|
      rule = definition[transition.id]
      rule.inputs += inputs
      flow_elements.delete(rule)
      branch.table[:else] << rule
    end
  end

  return branch
end
find_constraints(transition) click to toggle source

Find constraints from net.

@param transition [Transition]

base transition

@return [Array<Constraint>]

rule constraints
# File lib/pione/pnml/compiler.rb, line 224
def find_constraints(transition)
  @net.find_all_places_by_target_id(transition.id).each_with_object([]) do |place, constraints|
    prev_transitions = @net.find_all_transitions_by_target_id(place.id)
    constraint_transitions = prev_transitions.select{|t| Perspective.constraint_transition?(@env, t)}

    case constraint_transitions.size
    when 0
      # ignore
    when 1
      if Perspective.expr_place?(@env, place)
        constraints << Constraint.new(place.name)
      else
        # the place should be constraint expression
        raise CompilerError.should_be_constraint_expr(place)
      end
    else
      # multiple constraint keywords found
      raise CompilerError.multiple_constraint_keywords(transition.name)
    end
  end
end
find_features(transition) click to toggle source

Find features from net.

@param transition [Transition]

base transition

@return [Array<Feature>]

features
# File lib/pione/pnml/compiler.rb, line 280
def find_features(transition)
  @net.find_all_places_by_target_id(transition.id).each_with_object([]) do |place, features|
    if Perspective.feature_place?(@env, place)
      keyword_transitions = @net.find_all_transitions_by_target_id(place.id).select do |t|
        Perspective.keyword_transition?(@env, t)
      end
      if keyword_transitions.empty?
        features << Feature.new(place.name)
      end
    end
  end
end
find_inputs(transition) click to toggle source

Find inputs from net.

@param transition [Transition]

base transition

@return [Array<InputData>]

rule inputs
# File lib/pione/pnml/compiler.rb, line 164
def find_inputs(transition)
  @net.find_all_places_by_target_id(transition.id).each_with_object([]) do |place, inputs|
    begin
      # consideration for constraint nodes
      prev_transition = @net.find_transition_by_target_id(place.id)
      if Perspective.constraint_transition?(@env, prev_transition)
        @net.find_all_places_by_target_id(prev_transition.id).each do |_place|
          if Perspective.data_place?(@env, _place)
            inputs << InputData.new(_place)
          end
        end
      else
        if Perspective.data_place?(@env, place)
          inputs << InputData.new(place)
        end
      end
    rescue AmbiguousNetQueryResult
      # ignore
    end
  end
end
find_next_rules(base_rule) click to toggle source

Find next rules.

@param base_rule [PNML::Transition]

base transition
# File lib/pione/pnml/compiler.rb, line 368
def find_next_rules(base_rule)
  @net.find_all_places_by_source_id(base_rule.id).each_with_object([]) do |place, res|
    @net.find_all_transitions_by_source_id(place.id).each do |transition|
      if Perspective.rule_transition?(@env, transition)
        res << transition
      else
        find_next_rules(transition)
      end
    end
  end
end
find_outputs(transition) click to toggle source

Find outputs from net.

@param transition [Transition]

base transition

@return [Array]

rule outputs
# File lib/pione/pnml/compiler.rb, line 192
def find_outputs(transition)
  @net.find_all_places_by_source_id(transition.id).each_with_object([]) do |place, outputs|
    if Perspective.data_place?(@env, place)
      outputs << OutputData.new(place)
    end
  end
end
find_params(transition) click to toggle source

Find parameters from net.

@param transition [Transition]

base transition

@return [Array<Param>]

rule parameters
# File lib/pione/pnml/compiler.rb, line 206
def find_params(transition)
  @net.find_all_places_by_target_id(transition.id).each_with_object([]) do |place, params|
    if Perspective.param_place?(@env, place)
      prev_transitions = @net.find_all_transitions_by_target_id(place.id)
      keyword_transitions = prev_transitions.select{|t| Perspective.keyword_transition?(@env, t)}
      if keyword_transitions.empty?
        params << Param.set_of(place)
      end
    end
  end
end
find_source_tickets(transition) click to toggle source

Find source tickets from net.

@param transition [Transition]

base transition

@return [Array<Ticket>]

tickets
# File lib/pione/pnml/compiler.rb, line 252
def find_source_tickets(transition)
  @net.find_all_places_by_target_id(transition.id).each_with_object([]) do |place, tickets|
    if Perspective.ticket_place?(@env, place)
      tickets << Ticket.new(place.name)
    end
  end
end
find_target_tickets(transition) click to toggle source

Find target tickets from net.

@param transition [Transition]

base transition

@return [Array<Ticket>]

tickets
# File lib/pione/pnml/compiler.rb, line 266
def find_target_tickets(transition)
  @net.find_all_places_by_source_id(transition.id).each_with_object([]) do |place, tickets|
    if Perspective.ticket_place?(@env, place)
      tickets << Ticket.new(place.name)
    end
  end
end