[go: up one dir, main page]

Menu

[e5459b]: / lib / finita / problem.rb  Maximize  Restore  History

Download this file

100 lines (94 with data), 2.7 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
require "set"
require "autoc"
require "finita/symbolic"
require "finita/system"
require "finita/generator"
module Finita
class Problem
@@current = nil
@@problems = []
def self.current
raise "problem context is not set" if @@current.nil?
@@current
end
def self.current=(problem)
raise "nested problem contexts are not allowed" if @@current.nil? == problem.nil?
@@current = problem
end
def self.problems
@@problems
end
attr_reader :name, :systems, :instances
def initialize(name, &block)
@name = name.to_s # TODO validate
@instances = Set.new
@systems = []
Problem.problems << self
if block_given?
begin
Problem.current = self
block.call(self)
ensure
Problem.current = nil
end
end
end
def <<(entity)
instances << entity
end
def process!
@systems = systems.collect {|s| s.process!(self)}
new_module(code).generate!
self
end
def code
self.class::Code.new(self)
end
class Code < Finita::Code
def initialize(problem)
@problem = Finita.check_type(problem, Problem)
@initializer_codes = Set.new
@finalizer_codes = Set.new
@bound_codes = {}
super(problem.name)
@system_codes = @problem.systems.collect {|s| s.code(self)}
@instance_codes = @problem.instances.collect {|i| i.code(self)}
end
attr_reader :initializer_codes
attr_reader :finalizer_codes
def entities
super.concat(@bound_codes.values + @system_codes + @instance_codes + (initializer_codes | finalizer_codes).to_a)
end
def hash
@problem.hash # TODO
end
def ==(other)
equal?(other) || self.class == other.class && @problem == other.instance_variable_get(:@problem)
end
alias :eql? :==
def bind!(owner, &ctor)
@bound_codes.include?(owner) ? @bound_codes[owner] : @bound_codes[owner] = yield(self)
end
def write_intf(stream)
stream << %$
#{extern} void #{setup}(int, char**);
#{extern} void #{cleanup}(void);
$
end
def write_defs(stream)
stream << %$
FINITA_ARGSUSED
void #{setup}(int argc, char** argv) {FINITA_ENTER;$
AutoC.priority_sort(initializer_codes, false).each {|e| e.write_initializer(stream)}
stream << "FINITA_LEAVE;}"
stream << %$void #{cleanup}(void) {FINITA_ENTER;$
AutoC.priority_sort(finalizer_codes, true).each {|e| e.write_finalizer(stream)}
stream << "FINITA_LEAVE;}"
end
end # Code
private
def new_module(root_code)
AutoC::Module.new(name) << root_code
end
end # Problem
end # Finita