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+.



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/HDLRuby/hruby_check.rb', line 258

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.



288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# File 'lib/HDLRuby/hruby_check.rb', line 288

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.



159
160
161
162
163
164
# File 'lib/HDLRuby/hruby_check.rb', line 159

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.



193
194
195
196
197
198
# File 'lib/HDLRuby/hruby_check.rb', line 193

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.



133
134
135
136
137
138
# File 'lib/HDLRuby/hruby_check.rb', line 133

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_require_relatives(code = @code) ⇒ Object

Gets all the require_relative files of +code+.



79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/HDLRuby/hruby_check.rb', line 79

def get_all_require_relatives(code = @code)
    if code.is_a?(Array) then
        require_relatives = (code.select { |sub| is_require_relative?(sub) }).map! do |sub|
            get_require_relative(sub)
        end
        code.each do |sub|
            require_relatives += get_all_require_relatives(sub)
        end
        return require_relatives
    else
        return []
    end
end

#get_all_requires(code = @code) ⇒ Object

Gets all the required files of +code+.



64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/HDLRuby/hruby_check.rb', line 64

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 systems of +code+.



105
106
107
108
109
110
111
# File 'lib/HDLRuby/hruby_check.rb', line 105

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+.



206
207
208
# File 'lib/HDLRuby/hruby_check.rb', line 206

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.



235
236
237
238
239
240
241
242
243
244
245
# File 'lib/HDLRuby/hruby_check.rb', line 235

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+.



153
154
155
# File 'lib/HDLRuby/hruby_check.rb', line 153

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+.



179
180
181
182
183
184
185
186
187
188
189
# File 'lib/HDLRuby/hruby_check.rb', line 179

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+.



127
128
129
# File 'lib/HDLRuby/hruby_check.rb', line 127

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

#get_line(code) ⇒ Object

Gets the line of a code.



248
249
250
# File 'lib/HDLRuby/hruby_check.rb', line 248

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

#get_name(code) ⇒ Object

Gets the variable name of a code.



253
254
255
# File 'lib/HDLRuby/hruby_check.rb', line 253

def get_name(code)
    return code[1]
end

#get_require(code) ⇒ Object Also known as: get_require_relative

Gets the required file from +code+.



57
58
59
60
# File 'lib/HDLRuby/hruby_check.rb', line 57

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+.



100
101
102
# File 'lib/HDLRuby/hruby_check.rb', line 100

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)


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

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)


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

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)


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

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)


114
115
116
117
118
119
120
121
122
123
124
# File 'lib/HDLRuby/hruby_check.rb', line 114

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)


220
221
222
223
# File 'lib/HDLRuby/hruby_check.rb', line 220

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_require_relative?(code) ⇒ Boolean

Tells if +code+ is require_relative description.

Returns:

  • (Boolean)


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

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

#is_signal_declare?(code) ⇒ Boolean

Tells if +code+ is a signal declaration.

Returns:

  • (Boolean)


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

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)


94
95
96
97
# File 'lib/HDLRuby/hruby_check.rb', line 94

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)


201
202
203
# File 'lib/HDLRuby/hruby_check.rb', line 201

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