csv_plus_plus 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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