csv_plus_plus 0.1.1 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +18 -63
  3. data/{CHANGELOG.md → docs/CHANGELOG.md} +17 -0
  4. data/lib/csv_plus_plus/benchmarked_compiler.rb +112 -0
  5. data/lib/csv_plus_plus/cell.rb +46 -24
  6. data/lib/csv_plus_plus/cli.rb +44 -17
  7. data/lib/csv_plus_plus/cli_flag.rb +1 -2
  8. data/lib/csv_plus_plus/color.rb +42 -11
  9. data/lib/csv_plus_plus/compiler.rb +178 -0
  10. data/lib/csv_plus_plus/entities/ast_builder.rb +50 -0
  11. data/lib/csv_plus_plus/entities/boolean.rb +40 -0
  12. data/lib/csv_plus_plus/entities/builtins.rb +58 -0
  13. data/lib/csv_plus_plus/entities/cell_reference.rb +231 -0
  14. data/lib/csv_plus_plus/entities/date.rb +63 -0
  15. data/lib/csv_plus_plus/entities/entity.rb +50 -0
  16. data/lib/csv_plus_plus/entities/entity_with_arguments.rb +57 -0
  17. data/lib/csv_plus_plus/entities/function.rb +45 -0
  18. data/lib/csv_plus_plus/entities/function_call.rb +50 -0
  19. data/lib/csv_plus_plus/entities/number.rb +48 -0
  20. data/lib/csv_plus_plus/entities/runtime_value.rb +43 -0
  21. data/lib/csv_plus_plus/entities/string.rb +42 -0
  22. data/lib/csv_plus_plus/entities/variable.rb +37 -0
  23. data/lib/csv_plus_plus/entities.rb +40 -0
  24. data/lib/csv_plus_plus/error/error.rb +20 -0
  25. data/lib/csv_plus_plus/error/formula_syntax_error.rb +37 -0
  26. data/lib/csv_plus_plus/error/modifier_syntax_error.rb +75 -0
  27. data/lib/csv_plus_plus/error/modifier_validation_error.rb +69 -0
  28. data/lib/csv_plus_plus/error/syntax_error.rb +71 -0
  29. data/lib/csv_plus_plus/error/writer_error.rb +17 -0
  30. data/lib/csv_plus_plus/error.rb +10 -2
  31. data/lib/csv_plus_plus/google_api_client.rb +11 -2
  32. data/lib/csv_plus_plus/google_options.rb +23 -18
  33. data/lib/csv_plus_plus/lexer/lexer.rb +17 -6
  34. data/lib/csv_plus_plus/lexer/tokenizer.rb +6 -1
  35. data/lib/csv_plus_plus/lexer.rb +24 -0
  36. data/lib/csv_plus_plus/modifier/conditional_formatting.rb +18 -0
  37. data/lib/csv_plus_plus/modifier/data_validation.rb +138 -0
  38. data/lib/csv_plus_plus/modifier/expand.rb +61 -0
  39. data/lib/csv_plus_plus/modifier/google_sheet_modifier.rb +133 -0
  40. data/lib/csv_plus_plus/modifier/modifier.rb +222 -0
  41. data/lib/csv_plus_plus/modifier/modifier_validator.rb +243 -0
  42. data/lib/csv_plus_plus/modifier/rubyxl_modifier.rb +84 -0
  43. data/lib/csv_plus_plus/modifier.rb +82 -150
  44. data/lib/csv_plus_plus/options.rb +64 -19
  45. data/lib/csv_plus_plus/{language → parser}/cell_value.tab.rb +25 -25
  46. data/lib/csv_plus_plus/{language → parser}/code_section.tab.rb +86 -95
  47. data/lib/csv_plus_plus/parser/modifier.tab.rb +478 -0
  48. data/lib/csv_plus_plus/row.rb +53 -15
  49. data/lib/csv_plus_plus/runtime/can_define_references.rb +87 -0
  50. data/lib/csv_plus_plus/runtime/can_resolve_references.rb +209 -0
  51. data/lib/csv_plus_plus/runtime/graph.rb +68 -0
  52. data/lib/csv_plus_plus/runtime/position_tracker.rb +231 -0
  53. data/lib/csv_plus_plus/runtime/references.rb +110 -0
  54. data/lib/csv_plus_plus/runtime/runtime.rb +126 -0
  55. data/lib/csv_plus_plus/runtime.rb +42 -0
  56. data/lib/csv_plus_plus/source_code.rb +66 -0
  57. data/lib/csv_plus_plus/template.rb +63 -36
  58. data/lib/csv_plus_plus/version.rb +2 -1
  59. data/lib/csv_plus_plus/writer/base_writer.rb +30 -5
  60. data/lib/csv_plus_plus/writer/csv.rb +11 -9
  61. data/lib/csv_plus_plus/writer/excel.rb +9 -2
  62. data/lib/csv_plus_plus/writer/file_backer_upper.rb +7 -4
  63. data/lib/csv_plus_plus/writer/google_sheet_builder.rb +88 -45
  64. data/lib/csv_plus_plus/writer/google_sheets.rb +79 -29
  65. data/lib/csv_plus_plus/writer/open_document.rb +6 -1
  66. data/lib/csv_plus_plus/writer/rubyxl_builder.rb +103 -33
  67. data/lib/csv_plus_plus/writer.rb +39 -9
  68. data/lib/csv_plus_plus.rb +41 -15
  69. metadata +44 -30
  70. data/lib/csv_plus_plus/code_section.rb +0 -101
  71. data/lib/csv_plus_plus/expand.rb +0 -18
  72. data/lib/csv_plus_plus/graph.rb +0 -62
  73. data/lib/csv_plus_plus/language/ast_builder.rb +0 -68
  74. data/lib/csv_plus_plus/language/benchmarked_compiler.rb +0 -65
  75. data/lib/csv_plus_plus/language/builtins.rb +0 -46
  76. data/lib/csv_plus_plus/language/compiler.rb +0 -152
  77. data/lib/csv_plus_plus/language/entities/boolean.rb +0 -33
  78. data/lib/csv_plus_plus/language/entities/cell_reference.rb +0 -33
  79. data/lib/csv_plus_plus/language/entities/entity.rb +0 -86
  80. data/lib/csv_plus_plus/language/entities/function.rb +0 -35
  81. data/lib/csv_plus_plus/language/entities/function_call.rb +0 -37
  82. data/lib/csv_plus_plus/language/entities/number.rb +0 -36
  83. data/lib/csv_plus_plus/language/entities/runtime_value.rb +0 -28
  84. data/lib/csv_plus_plus/language/entities/string.rb +0 -31
  85. data/lib/csv_plus_plus/language/entities/variable.rb +0 -25
  86. data/lib/csv_plus_plus/language/entities.rb +0 -28
  87. data/lib/csv_plus_plus/language/references.rb +0 -70
  88. data/lib/csv_plus_plus/language/runtime.rb +0 -205
  89. data/lib/csv_plus_plus/language/scope.rb +0 -192
  90. data/lib/csv_plus_plus/language/syntax_error.rb +0 -66
  91. data/lib/csv_plus_plus/modifier.tab.rb +0 -907
  92. data/lib/csv_plus_plus/writer/google_sheet_modifier.rb +0 -56
  93. data/lib/csv_plus_plus/writer/rubyxl_modifier.rb +0 -59
@@ -1,152 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'csv'
4
-
5
- require_relative 'benchmarked_compiler'
6
- require_relative 'code_section.tab'
7
- require_relative 'entities'
8
- require_relative 'runtime'
9
- require_relative 'scope'
10
-
11
- module CSVPlusPlus
12
- module Language
13
- # Encapsulates the parsing and building of objects (+Template+ -> +Row+ -> +Cell+). Variable resolution is delegated
14
- # to the +Scope+
15
- #
16
- # @attr_reader options [Options] The +Options+ to compile with
17
- # @attr_reader runtime [Runtime] The runtime execution
18
- # @attr_reader scope [Scope] +Scope+ for variable resolution
19
- class Compiler
20
- attr_reader :timings, :benchmark, :options, :runtime, :scope
21
-
22
- # Create a compiler and make sure it gets cleaned up
23
- #
24
- # @param runtime [Runtime] The initial +Runtime+ for the compiler
25
- # @param options [Options]
26
- def self.with_compiler(runtime:, options:, &block)
27
- compiler = new(options:, runtime:)
28
- if options.verbose
29
- ::CSVPlusPlus::Language::BenchmarkedCompiler.with_benchmarks(compiler) do |c|
30
- block.call(c)
31
- end
32
- else
33
- yield(compiler)
34
- end
35
- ensure
36
- runtime.cleanup!
37
- end
38
-
39
- # @param runtime [Runtime]
40
- # @param options [Options]
41
- # @param scope [Scope, nil]
42
- def initialize(runtime:, options:, scope: nil)
43
- @options = options
44
- @runtime = runtime
45
- @scope = scope || ::CSVPlusPlus::Language::Scope.new(runtime:)
46
- end
47
-
48
- # Write the compiled results
49
- def outputting!
50
- @runtime.start_at_csv!
51
- yield
52
- end
53
-
54
- # Compile a template and return a +::CSVPlusPlus::Template+ instance ready to be written with a +Writer+
55
- #
56
- # @return [Template]
57
- def compile_template
58
- parse_code_section!
59
- rows = parse_csv_section!
60
-
61
- ::CSVPlusPlus::Template.new(rows:, code_section: scope.code_section).tap do |t|
62
- t.validate_infinite_expands(@runtime)
63
- expanding { t.expand_rows! }
64
- resolve_all_cells!(t)
65
- end
66
- end
67
-
68
- # @return [String]
69
- def to_s
70
- "Compiler(options: #{@options}, runtime: #{@runtime}, scope: #{@scope})"
71
- end
72
-
73
- protected
74
-
75
- # Parses the input file and returns a +CodeSection+
76
- #
77
- # @return [CodeSection]
78
- def parse_code_section!
79
- @runtime.start!
80
- parsing_code_section do |input|
81
- code_section, csv_section = ::CSVPlusPlus::Language::CodeSectionParser.new.parse(input, @runtime)
82
- # TODO: infer a type
83
- # allow user-supplied key/values to override anything global or from the code section
84
- code_section.def_variables(
85
- options.key_values.transform_values { |v| ::CSVPlusPlus::Language::Entities::String.new(v.to_s) }
86
- )
87
- @scope.code_section = code_section
88
-
89
- # return the csv_section to the caller because they're gonna re-write input with it
90
- next csv_section
91
- end
92
- @scope.code_section
93
- end
94
-
95
- # Parse the CSV section and return an array of +Row+s
96
- #
97
- # @return [Array<Row>]
98
- def parse_csv_section!
99
- @runtime.start_at_csv!
100
- @runtime.map_rows(::CSV.new(runtime.input)) do |csv_row|
101
- parse_row(csv_row)
102
- end
103
- ensure
104
- # we're done with the file and everything is in memory
105
- @runtime.cleanup!
106
- end
107
-
108
- # Iterates through each cell of each row and resolves it's variable and function references.
109
- #
110
- # @param template [Template]
111
- # @return [Array<Entity>]
112
- def resolve_all_cells!(template)
113
- @runtime.start_at_csv!
114
- @runtime.map_rows(template.rows, cells_too: true) do |cell|
115
- cell.ast = @scope.resolve_cell_value if cell.ast
116
- end
117
- end
118
-
119
- # Expanding rows
120
- def expanding
121
- @runtime.start_at_csv!
122
- yield
123
- end
124
-
125
- private
126
-
127
- def parsing_code_section
128
- csv_section = yield(@runtime.input.read)
129
- @runtime.rewrite_input!(csv_section)
130
- end
131
-
132
- # Using the current +@runtime+ and the given +csv_row+ parse it into a +Row+ of +Cell+s
133
- # +csv_row+ should have already been run through a CSV parser and is an array of strings
134
- #
135
- # @param csv_row [Array<Array<String>>]
136
- # @return [Row]
137
- def parse_row(csv_row)
138
- row_modifier = ::CSVPlusPlus::Modifier.new(row_level: true)
139
-
140
- cells =
141
- @runtime.map_row(csv_row) do |value, _cell_index|
142
- cell_modifier = ::CSVPlusPlus::Modifier.new
143
- parsed_value = ::CSVPlusPlus::ModifierParser.new(row_modifier:, cell_modifier:).parse(value, @runtime)
144
-
145
- ::CSVPlusPlus::Cell.parse(parsed_value, runtime:, modifier: cell_modifier)
146
- end
147
-
148
- ::CSVPlusPlus::Row.new(@runtime.row_index, cells, row_modifier)
149
- end
150
- end
151
- end
152
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './entity'
4
-
5
- module CSVPlusPlus
6
- module Language
7
- module Entities
8
- # A boolean value
9
- #
10
- # @attr_reader value [true, false]
11
- class Boolean < Entity
12
- attr_reader :value
13
-
14
- # @param value [String, Boolean]
15
- def initialize(value)
16
- super(:boolean)
17
- # TODO: probably can do a lot better in general on type validation
18
- @value = value.is_a?(::String) ? (value.downcase == 'true') : value
19
- end
20
-
21
- # @return [String]
22
- def to_s
23
- @value.to_s.upcase
24
- end
25
-
26
- # @return [boolean]
27
- def ==(other)
28
- super && value == other.value
29
- end
30
- end
31
- end
32
- end
33
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './entity'
4
-
5
- module CSVPlusPlus
6
- module Language
7
- module Entities
8
- # A reference to a cell
9
- #
10
- # @attr_reader cell_reference [String] The cell reference in A1 format
11
- class CellReference < Entity
12
- attr_reader :cell_reference
13
-
14
- # @param cell_reference [String] The cell reference in A1 format
15
- def initialize(cell_reference)
16
- super(:cell_reference)
17
-
18
- @cell_reference = cell_reference
19
- end
20
-
21
- # @return [String]
22
- def to_s
23
- @cell_reference
24
- end
25
-
26
- # @return [Boolean]
27
- def ==(other)
28
- super && @cell_reference == other.cell_reference
29
- end
30
- end
31
- end
32
- end
33
- end
@@ -1,86 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../entities'
4
-
5
- module CSVPlusPlus
6
- module Language
7
- module Entities
8
- # A basic building block of the abstract syntax tree (AST)
9
- #
10
- # @attr_reader id [Symbol] The identifier of the entity. For functions this is the function name,
11
- # for variables it's the variable name
12
- # @attr_reader type [Symbol] The type of the entity. Valid values are defined in +::CSVPlusPlus::Language::Types+
13
- class Entity
14
- attr_reader :id, :type
15
-
16
- # @param type [::String, Symbol]
17
- # @param id [::String, nil]
18
- def initialize(type, id: nil)
19
- @type = type.to_sym
20
- @id = id.downcase.to_sym if id
21
- end
22
-
23
- # @return [boolean]
24
- def ==(other)
25
- self.class == other.class && @type == other.type && @id == other.id
26
- end
27
-
28
- # Respond to predicates that correspond to types like #boolean?, #string?, etc
29
- #
30
- # @param method_name [Symbol] The +method_name+ to respond to
31
- def method_missing(method_name, *_arguments)
32
- if method_name =~ /^(\w+)\?$/
33
- t = ::Regexp.last_match(1)
34
- a_type?(t) && @type == t.to_sym
35
- else
36
- super
37
- end
38
- end
39
-
40
- # Respond to predicates by type (entity.boolean?, entity.string?, etc)
41
- #
42
- # @param method_name [Symbol] The +method_name+ to respond to
43
- #
44
- # @return [boolean]
45
- def respond_to_missing?(method_name, *_arguments)
46
- (method_name =~ /^(\w+)\?$/ && a_type?(::Regexp.last_match(1))) || super
47
- end
48
-
49
- private
50
-
51
- def a_type?(str)
52
- ::CSVPlusPlus::Language::TYPES.include?(str.to_sym)
53
- end
54
- end
55
-
56
- # An entity that can take other entities as arguments. Current use cases for this
57
- # are function calls and function definitions
58
- #
59
- # @attr_reader arguments [Array<Entity>] The arguments supplied to this entity.
60
- class EntityWithArguments < Entity
61
- attr_reader :arguments
62
-
63
- # @param type [::String, Symbol]
64
- # @param id [::String]
65
- # @param arguments [Array<Entity>]
66
- def initialize(type, id: nil, arguments: [])
67
- super(type, id:)
68
- @arguments = arguments
69
- end
70
-
71
- # @return [boolean]
72
- def ==(other)
73
- super && @arguments == other.arguments
74
- end
75
-
76
- protected
77
-
78
- attr_writer :arguments
79
-
80
- def arguments_to_s
81
- @arguments.join(', ')
82
- end
83
- end
84
- end
85
- end
86
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './entity'
4
-
5
- module CSVPlusPlus
6
- module Language
7
- module Entities
8
- # A function definition
9
- #
10
- # @attr_reader body [Entity] The body of the function. +body+ can contain variable references
11
- # from +@arguments+
12
- class Function < EntityWithArguments
13
- attr_reader :body
14
-
15
- # @param id [Symbool, String] the name of the function - what it will be callable by
16
- # @param arguments [Array<Symbol>]
17
- # @param body [Entity]
18
- def initialize(id, arguments, body)
19
- super(:function, id:, arguments: arguments.map(&:to_sym))
20
- @body = body
21
- end
22
-
23
- # @return [String]
24
- def to_s
25
- "def #{@id.to_s.upcase}(#{arguments_to_s}) #{@body}"
26
- end
27
-
28
- # @return [boolean]
29
- def ==(other)
30
- super && @body == other.body
31
- end
32
- end
33
- end
34
- end
35
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CSVPlusPlus
4
- module Language
5
- module Entities
6
- # A function call
7
- #
8
- # @attr_reader infix [boolean] Whether or not this function call is infix (X * Y, A + B, etc)
9
- class FunctionCall < EntityWithArguments
10
- attr_reader :infix
11
-
12
- # @param id [String] The name of the function
13
- # @param arguments [Array<Entity>] The arguments to the function
14
- # @param infix [boolean] Whether the function is infix
15
- def initialize(id, arguments, infix: false)
16
- super(:function_call, id:, arguments:)
17
-
18
- @infix = infix
19
- end
20
-
21
- # @return [String]
22
- def to_s
23
- if @infix
24
- "(#{arguments.join(" #{@id} ")})"
25
- else
26
- "#{@id.to_s.upcase}(#{arguments_to_s})"
27
- end
28
- end
29
-
30
- # @return [boolean]
31
- def ==(other)
32
- super && @id == other.id
33
- end
34
- end
35
- end
36
- end
37
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CSVPlusPlus
4
- module Language
5
- module Entities
6
- # A number value
7
- #
8
- # @attr_reader value [Numeric] The parsed number value
9
- class Number < Entity
10
- attr_reader :value
11
-
12
- # @param value [String, Numeric] Either a +String+ that looks like a number, or an already parsed Numeric
13
- def initialize(value)
14
- super(:number)
15
-
16
- @value =
17
- if value.instance_of?(::String)
18
- value.include?('.') ? Float(value) : Integer(value, 10)
19
- else
20
- value
21
- end
22
- end
23
-
24
- # @return [String]
25
- def to_s
26
- @value.to_s
27
- end
28
-
29
- # @return [boolean]
30
- def ==(other)
31
- super && value == other.value
32
- end
33
- end
34
- end
35
- end
36
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CSVPlusPlus
4
- module Language
5
- module Entities
6
- # A runtime value. These are values which can be materialized at any point via the +resolve_fn+
7
- # which takes an ExecutionContext as a param
8
- #
9
- # @attr_reader resolve_fn [lambda] A lambda that is called when the runtime value is resolved
10
- class RuntimeValue < Entity
11
- attr_reader :arguments, :resolve_fn
12
-
13
- # @param resolve_fn [lambda] A lambda that is called when the runtime value is resolved
14
- def initialize(resolve_fn, arguments: nil)
15
- super(:runtime_value)
16
-
17
- @arguments = arguments
18
- @resolve_fn = resolve_fn
19
- end
20
-
21
- # @return [String]
22
- def to_s
23
- '(runtime_value)'
24
- end
25
- end
26
- end
27
- end
28
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CSVPlusPlus
4
- module Language
5
- module Entities
6
- # A string value
7
- #
8
- # @attr_reader value [String]
9
- class String < Entity
10
- attr_reader :value
11
-
12
- # @param value [String] The string that has been parsed out of the template
13
- def initialize(value)
14
- super(:string)
15
-
16
- @value = value.gsub(/^"|"$/, '')
17
- end
18
-
19
- # @return [String]
20
- def to_s
21
- "\"#{@value}\""
22
- end
23
-
24
- # @return [boolean]
25
- def ==(other)
26
- super && value == other.value
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CSVPlusPlus
4
- module Language
5
- module Entities
6
- # A reference to a variable
7
- class Variable < Entity
8
- # initialize
9
- def initialize(id)
10
- super(:variable, id:)
11
- end
12
-
13
- # to_s
14
- def to_s
15
- "$$#{@id}"
16
- end
17
-
18
- # ==
19
- def ==(other)
20
- super && id == other.id
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'entities/boolean'
4
- require_relative 'entities/cell_reference'
5
- require_relative 'entities/entity'
6
- require_relative 'entities/function'
7
- require_relative 'entities/function_call'
8
- require_relative 'entities/number'
9
- require_relative 'entities/runtime_value'
10
- require_relative 'entities/string'
11
- require_relative 'entities/variable'
12
-
13
- module CSVPlusPlus
14
- module Language
15
- TYPES = {
16
- boolean: ::CSVPlusPlus::Language::Entities::Boolean,
17
- cell_reference: ::CSVPlusPlus::Language::Entities::CellReference,
18
- function: ::CSVPlusPlus::Language::Entities::Function,
19
- function_call: ::CSVPlusPlus::Language::Entities::FunctionCall,
20
- number: ::CSVPlusPlus::Language::Entities::Number,
21
- runtime_value: ::CSVPlusPlus::Language::Entities::RuntimeValue,
22
- string: ::CSVPlusPlus::Language::Entities::String,
23
- variable: ::CSVPlusPlus::Language::Entities::Variable
24
- }.freeze
25
-
26
- public_constant :TYPES
27
- end
28
- end
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../graph'
4
- require_relative './scope'
5
-
6
- module CSVPlusPlus
7
- module Language
8
- # References in an AST that need to be resolved
9
- #
10
- # @attr functions [Array<Entities::Function>] Functions references
11
- # @attr variables [Array<Entities::Variable>] Variable references
12
- class References
13
- attr_accessor :functions, :variables
14
-
15
- # Extract references from an AST and return them in a new +References+ object
16
- #
17
- # @param ast [Entity] An +Entity+ to do a depth first search on for references. Entities can be
18
- # infinitely deep because they can contain other function calls as params to a function call
19
- # @param code_section [CodeSection] The +CodeSection+ containing all currently defined functions
20
- #
21
- # @return [References]
22
- def self.extract(ast, code_section)
23
- new.tap do |refs|
24
- ::CSVPlusPlus::Graph.depth_first_search(ast) do |node|
25
- next unless node.function_call? || node.variable?
26
-
27
- refs.functions << node if function_reference?(node, code_section)
28
- refs.variables << node if node.variable?
29
- end
30
- end
31
- end
32
-
33
- # Is the node a resolvable reference?
34
- #
35
- # @param node [Entity] The node to check if it's resolvable
36
- #
37
- # @return [boolean]
38
- # TODO: move this into the Entity subclasses
39
- def self.function_reference?(node, code_section)
40
- node.function_call? && (code_section.defined_function?(node.id) \
41
- || ::CSVPlusPlus::Language::Builtins::FUNCTIONS.key?(node.id))
42
- end
43
-
44
- private_class_method :function_reference?
45
-
46
- # Create an object with empty references. The caller will build them up as it depth-first-searches
47
- def initialize
48
- @functions = []
49
- @variables = []
50
- end
51
-
52
- # Are there any references to be resolved?
53
- #
54
- # @return [boolean]
55
- def empty?
56
- @functions.empty? && @variables.empty?
57
- end
58
-
59
- # @return [String]
60
- def to_s
61
- "References(functions: #{@functions}, variables: #{@variables})"
62
- end
63
-
64
- # @return [boolean]
65
- def ==(other)
66
- @functions == other.functions && @variables == other.variables
67
- end
68
- end
69
- end
70
- end