summaryrefslogtreecommitdiffstats
path: root/lib/blink/transportable.rb
blob: afb6f8061b2021f42c440b1a8efc2a81a49312ba (plain)
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/usr/local/bin/ruby -w

# $Id$

# the interpreter
#
# this builds our virtual pinball machine, into which we'll place our host-specific
# information and out of which we'll receive our host-specific configuration

require 'blink'


module Blink
    #------------------------------------------------------------
    class TransObject < Hash
        attr_accessor :type

        @@ohash = {}
        @@oarray = []

        def TransObject.clear
            @@oarray.clear
        end

        def TransObject.list
            return @@oarray
        end

        def initialize(name,type)
            self[:name] = name
            @type = type
            #if @@ohash.include?(name)
            #    raise "%s already exists" % name
            #else
            #    @@ohash[name] = self
            #    @@oarray.push(self)
            #end
            @@oarray.push self
        end

        def name
            return self[:name]
        end

        def to_s
            return "%s(%s) => %s" % [@type,self[:name],super]
        end

        def to_type
            retobj = nil
            if type = Blink::Type.type(self.type)
                namevar = type.namevar
                if namevar != :name
                    self[namevar] = self[:name]
                    self.delete(:name)
                end
                p self
                #begin
                    # this will fail if the type already exists
                    # which may or may not be a good thing...
                    retobj = type.new(self)
                #rescue => detail
                #    Blink.error "Failed to create %s: %s" % [type.name,detail]
                #    puts self.class
                #    puts self.inspect
                #    exit
                #end
            else
                raise "Could not find object type %s" % self.type
            end

            return retobj
        end
    end
    #------------------------------------------------------------

    #------------------------------------------------------------
    class TransSetting
        attr_accessor :type, :name, :args, :evalcount

        def initialize
            @evalcount = 0
        end

        def evaluate
            @evalcount += 0
            if type = Blink::Type.type(self.type)
                # call the settings
                name = self.name
                unless name.is_a?(Symbol)
                    name = name.intern
                end
                if type.allowedmethod(name)
                    type.send(self.name,self.args)
                else
                    Blink.error("%s does not respond to %s" % [self.type,self.name])
                end
            else
                raise "Could not find object type %s" % setting.type
            end
        end
    end
    #------------------------------------------------------------

    #------------------------------------------------------------
    # just a linear container for objects
    class TransBucket < Array
        def to_type
            # this container will contain the equivalent of all objects at
            # this level
            container = Blink::Component.new
            nametable = {}

            self.each { |child|
                # the fact that we descend here means that we are
                # always going to execute depth-first
                # which is _probably_ a good thing, but one never knows...
                if child.is_a?(Blink::TransBucket)
                    # just perform the same operation on any children
                    container.push(child.to_type)
                elsif child.is_a?(Blink::TransSetting)
                    # XXX this is wrong, but for now just evaluate the settings
                    child.evaluate
                elsif child.is_a?(Blink::TransObject)
                    # do a simple little naming hack to see if the object already
                    # exists in our scope
                    # this assumes that type/name combinations are globally
                    # unique
                    name = [child[:name],child.type].join("--")

                    if nametable.include?(name)
                        object = nametable[name]
                        child.each { |var,value|
                            # don't rename; this shouldn't be possible anyway
                            next if var == :name

                            Blink.notice "Adding %s to %s" % [var,name]
                            # override any existing values
                            object[var] = value
                        }
                    else # the object does not exist yet in our scope
                        # now we have the object instantiated, in our scope
                        object = child.to_type
                        nametable[name] = object

                        # this sets the order of the object
                        container.push object
                    end
                else
                    raise "TransBucket#to_type cannot handle objects of type %s" %
                        child.class
                end
            }

            # at this point, no objects at are level are still Transportable
            # objects
            return container
        end

    end
    #------------------------------------------------------------
end