comfpile-old/lib/comfpile/core.rb
2023-08-12 20:39:22 +02:00

200 lines
No EOL
5.7 KiB
Ruby

require 'digest'
require_relative 'artefact_engine.rb'
require_relative 'context.rb'
module Comfpile
class Core
attr_reader :processing_stack
def initialize(build_dir_path: File.join('/tmp/comfpile/', Digest::MD5.hexdigest(Dir.pwd)))
@build_dir_path = File.expand_path(build_dir_path)
@artefact_engines = []
@artefact_prio_counter = 0
# Artefacts are arranged in a double-hash.
# First query is stage, second filename.
@artefacts = {}
# Stack-style processing queue for item processing
@processing_stack = []
@context_key_provider = ContextKeyProvider.new()
end
def get_context_key(key)
return @context_key_provider.provide_context(key)
end
def find_artefact(stage, file = :none, context = :default)
context = get_context_key(context)
@artefacts.dig(context, stage, file)
end
# Create or find a new artefact.
#
# This will first see if a given artefact matching
# the stage and target descriptions already exists, and
# will return it, if found. Otherwise it will
# consult all given artefact crafting engines to
# see if a new artefact can be created, which will be returned.
#
# If no artefact can be made, nil is returned
#
# @param [Symbol, String] stage State that shall be created (e.g. :parsed, :compiled, etc.)
# @param [String] file File or other target that shall be looked at (e.g. "main.cpp")
#
# @return [Comfpile::Artefact, nil] Found or created artefact, or nil if nothing could be done
#
def craft_artefact(stage, file = :none, context = :default)
context = get_context_key(context)
artefact = find_artefact(stage, file, context)
return artefact unless artefact.nil?
@artefact_engines.each do |engine|
artefact = engine.craft stage, file, context
if artefact
@artefacts[context] ||= {}
@artefacts[context][stage] ||= {}
@artefacts[context][stage][file] = artefact
@processing_stack.push artefact
return artefact
end
end
nil
end
def add_artefact(stage, file = :none, context = :default, engine: nil, artefact_class: Comfpile::Artefact)
context = get_context_key context
return unless find_artefact(stage, file, context).nil?
a = Artefact.new(self, engine, stage, file, context);
@artefacts[context] ||= {}
@artefacts[context][stage] ||= {}
@artefacts[context][stage][file] = a
yield(a) if block_given?
nil
end
# @yieldparam [Comfpile::ArtefactEngine] Engine that was newly created
def add_artefact_engine(engine_class = Comfpile::ArtefactEngine, **options)
new_engine = if(engine_class.is_a? Comfpile::ArtefactEngine)
engine_class
else
engine = engine_class.new(self,
subpriority: @artefact_prio_counter, **options)
@artefact_prio_counter += 1
engine
end
yield(new_engine) if block_given?
@artefact_engines << new_engine
@artefact_engines.sort!
new_engine
end
def processing_stack_prune()
loop do
return if @processing_stack.empty?
if @processing_stack[-1].completed?
@processing_stack.pop
else
break
end
end
nil
end
def processing_stack_find_next()
return nil if @processing_stack.empty?
i = 0
@processing_stack.reverse_each do |a|
i += 1
if a.waiting?
# puts "DBG - Found item after #{i} checks"
return a
end
end
# TODO: Fix up later-on for parallel runner capabilities
raise "Deadlock found, no item was willing to run!"
nil
end
def get_context_build_dir_path(context)
context = context.context if context.is_a? Artefact
File.expand_path(File.join(@build_dir_path, context.to_s))
end
def execute_step
return if @processing_stack.empty?
# puts "Got #{@processing_stack.length} items..."
processing_stack_prune
artefact = processing_stack_find_next
return nil if artefact.nil?
# puts "Processing artefact #{artefact.stage} #{artefact.target}"
build_path = get_context_build_dir_path(artefact)
FileUtils.mkpath build_path
Dir.chdir build_path do
begin
artefact.execute_step
rescue ArtefactExecSkipError
end
end
nil
end
def execute_all
step_count = 0
until @processing_stack.empty?
execute_step()
step_count += 1
end
puts "Done after #{step_count} exec loops..."
end
def craft_and_complete(stage, target)
artefact = craft_artefact(stage, target)
return nil if artefact.nil?
while artefact.in_progress?
execute_step
end
artefact
end
end
end