class Bolt::PAL::YamlPlan::Loader

def self.create(loader, typed_name, source_ref, yaml_string)

def self.create(loader, typed_name, source_ref, yaml_string)
  plan_definition = from_string(typed_name.name, yaml_string, source_ref)
  created = create_function_class(plan_definition)
  closure_scope = nil
  created.new(closure_scope, loader.private_loader)
end

def self.create_function_class(plan_definition)

def self.create_function_class(plan_definition)
  Puppet::Functions.create_function(plan_definition.name, Puppet::Functions::PuppetFunction) do
    closure = Puppet::Pops::Evaluator::Closure::Named.new(plan_definition.name,
                                                          YamlPlan::Evaluator.new,
                                                          plan_definition)
    init_dispatch(closure)
  end
end

def self.from_string(name, yaml_string, source_ref)

def self.from_string(name, yaml_string, source_ref)
  result = parse_plan(yaml_string, source_ref)
  unless result.is_a?(Hash)
    type = result.class.name
    raise ArgumentError, "The data loaded from #{source_ref} does not contain an object - its type is #{type}"
  end
  begin
    YamlPlan.new(name, result).freeze
  rescue Bolt::Error => e
    raise Puppet::ParseError.new(e.message, source_ref)
  end
end

def self.parse_plan(yaml_string, source_ref)

def self.parse_plan(yaml_string, source_ref)
  # This passes the filename as the second arg for compatibility with Psych used with ruby < 2.6
  # This can be removed when we remove support for ruby 2.5
  parse_tree = if Psych.method(:parse).parameters.rassoc(:filename) == %i[key filename]
                 Psych.parse(yaml_string, filename: source_ref)
               else
                 Psych.parse(yaml_string, source_ref)
               end
  PuppetVisitor.create_visitor(source_ref).accept(parse_tree)
end