Class: HDLRuby::Checker

Inherits:
Object
  • Object
show all
Defined in:
lib/HDLRuby/hruby_check.rb

Overview

Describes a HDLRuby code checker.

Instance Method Summary collapse

Constructor Details

#initialize(code, filename = nil) ⇒ Checker

Create a new checker on code string, from filename file. Returns a list of error and the related object and method.



19
20
21
22
23
24
# File 'lib/HDLRuby/hruby_check.rb', line 19

def initialize(code,filename = nil)
    @code = Ripper.sexp(code.to_s,filename ? filename : "-", 1)
    @code ||= [] # In case the parse failed
    @filename = filename
    # puts "@code=#{@code}"
end

Instance Method Details

#assign_check(code = @code) ⇒ Object

Check for invalid assignments in code.



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/HDLRuby/hruby_check.rb', line 234

def assign_check(code = @code)
    system_check = false # Flag telling if the internal of a system
                         # is reached.
    hdr_names = []       # The existing HDLRuby names, they cannot be
                         # used as Ruby variables.
    code.each do |subcode|
        if system_check then
            # Internal of a system, do a specific check.
            assign_check_in_system(subcode,hdr_names.clone)
            system_check = false
        elsif subcode.is_a?(Array) then
            if (self.is_hdr_declare?(code,hdr_names)) then
                # New HDLRuby name, add them to the hdr names.
                hdr_names.concat(self.get_hdr_declares(code))
            end
            if self.is_system?(subcode) then
                # The current subcode is a system, the next one will
                # be its internal.
                system_check = true
            else
                # Go on cheking recursively.
                self.assign_check(subcode)
            end
        end
    end
end

#assign_check_in_system(code, hdr_names) ⇒ Object

Check for invalid assignments in code assuming being within a system. For that purpose assigned names are look for in hdr_names that includes the current HDLRuby names.



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/HDLRuby/hruby_check.rb', line 264

def assign_check_in_system(code, hdr_names)
    # puts "hdr_names=#{hdr_names}"
    if (self.is_hdr_declare?(code,hdr_names)) then
        # New HDLRuby names, add them to the hdr names.
        hdr_names.concat(self.get_hdr_declares(code))
    elsif (self.is_variable_assign?(code)) then
        var = self.get_assign_variable(code)
        # puts "var=#{var} and hdr_names=#{hdr_names}"
        if hdr_names.include?(var[1]) then
            # An HDLRuby name is overwritten.
            if @filename then
                warn("*WARNING* In file '#{@filename}': ")
            else
                warn("*WARNING*")
            end
            warn("Potential invalid assignment for '#{self.get_name(var)}' at line #{self.get_line(var)}")
        end
    else
        # Go on checking recursively.
        code.each do |subcode|
            if subcode.is_a?(Array) then
                self.assign_check_in_system(subcode,hdr_names)
            end
        end
    end
end

#get_all_includes(systems, code = @code) ⇒ Object

Get all the include in code of systems. NOTE: return the sub code describing the include.



135
136
137
138
139
140
# File 'lib/HDLRuby/hruby_check.rb', line 135

def get_all_includes(systems,code = @code)
    return [] unless code.is_a?(Array)
    return code.reduce([]) do |ar,sub|
        ar + get_all_includes(systems,sub)
    end + (code.select { |sub| is_include?(sub,systems) }).to_a
end

#get_all_inherits(systems, code = @code) ⇒ Object

Get all the inherited system in code of systems. NOTE: return the sub code describing the include.



169
170
171
172
173
174
# File 'lib/HDLRuby/hruby_check.rb', line 169

def get_all_inherits(systems,code = @code)
    return [] unless code.is_a?(Array)
    return code.reduce([]) do |ar,sub|
        ar + get_all_inherits(systems,sub)
    end + (code.select { |sub| is_inherit?(sub,systems) }).to_a
end

#get_all_instances(systems, code = @code) ⇒ Object

Get all the instances in code of systems. NOTE: return the sub code describing the instantiation.



109
110
111
112
113
114
# File 'lib/HDLRuby/hruby_check.rb', line 109

def get_all_instances(systems,code = @code)
    return [] unless code.is_a?(Array)
    return code.reduce([]) do |ar,sub|
        ar + get_all_instances(systems,sub)
    end + (code.select { |sub| is_instance?(sub,systems) }).to_a
end

#get_all_requires(code = @code) ⇒ Object

Gets all the required files of code.



55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/HDLRuby/hruby_check.rb', line 55

def get_all_requires(code = @code)
    if code.is_a?(Array) then
        requires = (code.select { |sub| is_require?(sub) }).map! do |sub|
            get_require(sub)
        end
        code.each do |sub|
            requires += get_all_requires(sub)
        end
        return requires
    else
        return []
    end
end

#get_all_systems(code = @code) ⇒ Object

Gets all the required files of code.



81
82
83
84
85
86
87
# File 'lib/HDLRuby/hruby_check.rb', line 81

def get_all_systems(code = @code)
    return [] unless code.is_a?(Array)
    return code.reduce([]) {|ar,sub| ar + get_all_systems(sub) } +
        (code.select { |sub| is_system?(sub) }).map! do |sub|
            get_system(sub)
        end
end

#get_assign_variable(code) ⇒ Object

Gets the assigned variable in code.



182
183
184
# File 'lib/HDLRuby/hruby_check.rb', line 182

def get_assign_variable(code)
    return code[1][1]
end

#get_hdr_declares(code) ⇒ Object

Gets the HDLRuby names declared from code.

Note: assumes code is indeed a declaration.



211
212
213
214
215
216
217
218
219
220
221
# File 'lib/HDLRuby/hruby_check.rb', line 211

def get_hdr_declares(code)
    if code.is_a?(Array) then
        if code[0] == :@ident then
            return [ code[1] ]
        else
            return code.map {|elem| get_hdr_declares(elem) }.flatten
        end
    else
        return []
    end
end

#get_include_system(code) ⇒ Object

Get the system of an include in code.



129
130
131
# File 'lib/HDLRuby/hruby_check.rb', line 129

def get_include_system(code)
    return code[2][1][1]
end

#get_inherit_systems(code) ⇒ Object

Get the inherted systems of an inheritance in code.



155
156
157
158
159
160
161
162
163
164
165
# File 'lib/HDLRuby/hruby_check.rb', line 155

def get_inherit_systems(code)
    res = []
    code[2][1][1..-1].each do |field|
        if (field[0] == :command) then
            res << field[1][1]
        elsif (field[0] == :method_add_arg) then
            res << field[1][1][1]
        end
    end
    return res
end

#get_instance_system(code) ⇒ Object

Get the system of an instance in code.



103
104
105
# File 'lib/HDLRuby/hruby_check.rb', line 103

def get_instance_system(code)
    return code[1][1]
end

#get_line(code) ⇒ Object

Gets the line of a code.



224
225
226
# File 'lib/HDLRuby/hruby_check.rb', line 224

def get_line(code)
    return code[2][0]
end

#get_name(code) ⇒ Object

Gets the variable name of a code.



229
230
231
# File 'lib/HDLRuby/hruby_check.rb', line 229

def get_name(code)
    return code[1]
end

#get_require(code) ⇒ Object

Gets the required file from code.



49
50
51
52
# File 'lib/HDLRuby/hruby_check.rb', line 49

def get_require(code)
    # return (code[0][2][1][0][1][1][1])
    return (code[2][1][0][1][1][1])
end

#get_system(code) ⇒ Object

Gets the system name in code.



76
77
78
# File 'lib/HDLRuby/hruby_check.rb', line 76

def get_system(code)
    return code[2][1][0][1][1][1]
end

#has_name_deep?(code, name) ⇒ Boolean

Tells if name is included in one of the field or subfield of code.

Returns:

  • (Boolean)


33
34
35
36
37
38
# File 'lib/HDLRuby/hruby_check.rb', line 33

def has_name_deep?(code, name)
    # Checks recursively.
    return code.find do |field|
        field.is_a?(Array) ? has_name_deep?(field,name) : field == name
    end
end

#is_hdr_declare?(code, systems) ⇒ Boolean

Tells if code is an HDLRuby declaration of a signal or an instance of one of systems.

Returns:

  • (Boolean)


203
204
205
206
# File 'lib/HDLRuby/hruby_check.rb', line 203

def is_hdr_declare?(code, systems)
    return is_system?(code) || is_signal_declare?(code) ||
        is_instance_declare?(code, systems)
end

#is_include?(code, systems) ⇒ Boolean

Tells is code is an include of one of systems.

Returns:

  • (Boolean)


117
118
119
120
121
122
123
124
125
126
# File 'lib/HDLRuby/hruby_check.rb', line 117

def is_include?(code,systems)
    # Ensures systems is an array.
    systems = [*systems]
    # Check for each system.
    return systems.any? do |system|
        code.is_a?(Array) && (code[0] == :command) &&
                             (code[1][1] == "include") &&
                             (code[2][1][1] == system)
    end
end

#is_inherit?(code, systems) ⇒ Boolean

Tells is code is an inheritance of one of systems.

Returns:

  • (Boolean)


143
144
145
146
147
148
149
150
151
152
# File 'lib/HDLRuby/hruby_check.rb', line 143

def is_inherit?(code,systems)
    # Ensures systems is an array.
    systems = [*systems]
    # Check for each system.
    return systems.any? do |system|
        code.is_a?(Array) && (code[0] == :command) &&
                             (code[1][1] == "system") &&
                             (has_name_deep?(code[2][1][1..-1],system))
    end
end

#is_instance?(code, systems) ⇒ Boolean

Tells is code is an instance of one of systems.

Returns:

  • (Boolean)


90
91
92
93
94
95
96
97
98
99
100
# File 'lib/HDLRuby/hruby_check.rb', line 90

def is_instance?(code,systems)
    # puts "is_instance? with #{code}"
    # Ensures systems is an array.
    systems = [*systems]
    # Check for each system.
    return systems.any? do |system|
        code.is_a?(Array) && 
            ( (code[0] == :command) || (code[0] == :fcall) ) &&
            (code[1][1] == system)
    end
end

#is_instance_declare?(code, systems) ⇒ Boolean

Tells if code is an instance declaration of one of systems.

Returns:

  • (Boolean)


196
197
198
199
# File 'lib/HDLRuby/hruby_check.rb', line 196

def is_instance_declare?(code,systems)
    return code[0] == :command &&
        systems.find {|sys| has_name_deep?(code,sys) }
end

#is_require?(code) ⇒ Boolean

Tells if code is a require description.

Returns:

  • (Boolean)


41
42
43
44
45
46
# File 'lib/HDLRuby/hruby_check.rb', line 41

def is_require?(code)
    # return code[0] && (code[0][0] == :command) &&
    #        (code[0][1][1] == "require")
    return code && (code[0] == :command) &&
           (code[1][1] == "require")
end

#is_signal_declare?(code) ⇒ Boolean

Tells if code is a signal declaration.

Returns:

  • (Boolean)


187
188
189
190
191
192
193
# File 'lib/HDLRuby/hruby_check.rb', line 187

def is_signal_declare?(code)
    return [:command,:command_call].include?(code[0]) &&
        ( has_name_deep?(code,"input") ||
          has_name_deep?(code,"output") ||
          has_name_deep?(code,"inout") ||
          has_name_deep?(code,"inner") )
end

#is_system?(code) ⇒ Boolean

Tells if code is a system description.

Returns:

  • (Boolean)


70
71
72
73
# File 'lib/HDLRuby/hruby_check.rb', line 70

def is_system?(code)
    return code.is_a?(Array) && (code[0] == :command) &&
                                (code[1][1] == "system")
end

#is_variable_assign?(code) ⇒ Boolean

Tells if code is a variable assignment.

Returns:

  • (Boolean)


177
178
179
# File 'lib/HDLRuby/hruby_check.rb', line 177

def is_variable_assign?(code)
    return (code[0] == :assign) && (code[1][1][0] == :@ident)
end

#show(output = $stout) ⇒ Object

Displays the full syntax tree.



27
28
29
# File 'lib/HDLRuby/hruby_check.rb', line 27

def show(output = $stout)
    pp(@code,output)
end