Class: SlowBlink::Schema

Inherits:
Object
  • Object
show all
Defined in:
lib/slow_blink/schema.rb

Overview

Location string formatted as: [ FILENAME, ':' ], LINE_NUMBER, ':', COLUMN_NUMBER

Returns:

  • (String)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*buffer) ⇒ Schema

Create a Schema from one or more Blink Protocol schemas

Parameters:



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
# File 'lib/slow_blink/schema.rb', line 71

def initialize(*buffer)

    # This array keeps references to the various objects
    # created in the C extension parser
    @crefs = []
    
    namespace = []

    if buffer.size > 0
        buffer.each do |b|
            if b.kind_of? String
                namespace << parse_file_buffer(b, nil)
            else
                namespace << parse_file_buffer(b.buffer, b.filename)
            end
        end
    else
        raise ArgumentError.new "at least one buffer required"
    end

    # we safely have all our c references rooted at namespace so this can go away
    @crefs = nil

    @defs = {}

    # create groups and definitions
    namespace.each do |ns|    
        ns[:defs].select{|d|d[:class] != :IncrementalAnnotation}.each do |d|
            key = d[:name][:name].dup
            if ns[:name]
                key.prepend "#{ns[:name]}::"
            end
            if @defs[key]
                raise ParseError.new "#{d[:loc]}: duplicate definition: '#{key}' first defined at '#{@defs[key].location}'"
            else
                @defs[key] = SlowBlink.const_get(d[:class]).new(d.merge({:ns=>ns[:name], :table=>@defs}))
            end
        end                
    end

    # test that reference definitions resolve and detect circular references
    @defs.values.each do |d|
        if d.is_a? Definition and d.type.is_a? REF
            ptr = d.type.resolve
            if ptr        
                stack = [d]
                while ptr and ptr.is_a? Definition and ptr.type.is_a? REF do
                    if stack.include? ptr
                        raise ParseError.new "#{d.type.location}: '#{d.name}' resolves to a circular reference"
                    else
                        ptr = ptr.type.resolve
                    end
                end
            else
                raise ParseError.new "#{d.type.location}: '#{d.name}' does not resolve"
            end
        end
    end

    # test that groups resolve and meet constraints
    tagged = {}
    @defs.values.each do |d|                
        if d.is_a? Group
            d.superGroup
            d.fields
            if d.id and tagged[d.id]
                raise ParseError.new "#{d.type.location}: duplicate tag"
            else
                tagged[d.id] = d
            end                    
        end
    end

end

Class Method Details

.read(*filename) ⇒ Schema

Create a Schema from one or more Blink Schema files that are evaluated in the order they appear.

Parameters:

  • filename (Array<String>)

Returns:



38
39
40
41
42
43
44
45
46
47
48
# File 'lib/slow_blink/schema.rb', line 38

def self.read(*filename)
    input = []
    if filename.size > 0
        filename.each do |f|
            input << SchemaBuffer.new(File.read(f), f)
        end
        self.new(*input)
    else
        raise ArgumentError.new "at least one file required"                
    end
end

Instance Method Details

#definitionsArray<Definition,Group>

Returns definitions.

Returns:



62
63
64
# File 'lib/slow_blink/schema.rb', line 62

def definitions
    @defs.values
end

#groupsArray<Group>

Returns groups.

Returns:

  • (Array<Group>)

    groups



53
54
55
56
57
# File 'lib/slow_blink/schema.rb', line 53

def groups
    @defs.values.select do |d|
        d.is_a? Group
    end
end