csv_plus_plus 0.1.3 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -3
  3. data/docs/CHANGELOG.md +18 -0
  4. data/lib/csv_plus_plus/a1_reference.rb +202 -0
  5. data/lib/csv_plus_plus/benchmarked_compiler.rb +3 -3
  6. data/lib/csv_plus_plus/cell.rb +1 -35
  7. data/lib/csv_plus_plus/cli.rb +43 -80
  8. data/lib/csv_plus_plus/cli_flag.rb +77 -70
  9. data/lib/csv_plus_plus/color.rb +1 -1
  10. data/lib/csv_plus_plus/compiler.rb +31 -21
  11. data/lib/csv_plus_plus/entities/ast_builder.rb +11 -4
  12. data/lib/csv_plus_plus/entities/boolean.rb +16 -9
  13. data/lib/csv_plus_plus/entities/builtins.rb +68 -40
  14. data/lib/csv_plus_plus/entities/date.rb +14 -11
  15. data/lib/csv_plus_plus/entities/entity.rb +11 -29
  16. data/lib/csv_plus_plus/entities/entity_with_arguments.rb +18 -31
  17. data/lib/csv_plus_plus/entities/function.rb +22 -11
  18. data/lib/csv_plus_plus/entities/function_call.rb +35 -11
  19. data/lib/csv_plus_plus/entities/has_identifier.rb +19 -0
  20. data/lib/csv_plus_plus/entities/number.rb +15 -10
  21. data/lib/csv_plus_plus/entities/reference.rb +77 -0
  22. data/lib/csv_plus_plus/entities/runtime_value.rb +36 -23
  23. data/lib/csv_plus_plus/entities/string.rb +13 -10
  24. data/lib/csv_plus_plus/entities.rb +2 -18
  25. data/lib/csv_plus_plus/error/cli_error.rb +17 -0
  26. data/lib/csv_plus_plus/error/compiler_error.rb +17 -0
  27. data/lib/csv_plus_plus/error/error.rb +18 -5
  28. data/lib/csv_plus_plus/error/formula_syntax_error.rb +12 -13
  29. data/lib/csv_plus_plus/error/modifier_syntax_error.rb +10 -36
  30. data/lib/csv_plus_plus/error/modifier_validation_error.rb +6 -32
  31. data/lib/csv_plus_plus/error/positional_error.rb +15 -0
  32. data/lib/csv_plus_plus/error/writer_error.rb +1 -1
  33. data/lib/csv_plus_plus/error.rb +4 -1
  34. data/lib/csv_plus_plus/error_formatter.rb +111 -0
  35. data/lib/csv_plus_plus/google_api_client.rb +18 -8
  36. data/lib/csv_plus_plus/lexer/racc_lexer.rb +144 -0
  37. data/lib/csv_plus_plus/lexer/tokenizer.rb +53 -17
  38. data/lib/csv_plus_plus/lexer.rb +40 -1
  39. data/lib/csv_plus_plus/modifier/data_validation.rb +1 -1
  40. data/lib/csv_plus_plus/modifier/expand.rb +17 -0
  41. data/lib/csv_plus_plus/modifier.rb +6 -1
  42. data/lib/csv_plus_plus/options/file_options.rb +49 -0
  43. data/lib/csv_plus_plus/options/google_sheets_options.rb +42 -0
  44. data/lib/csv_plus_plus/options/options.rb +102 -0
  45. data/lib/csv_plus_plus/options.rb +22 -110
  46. data/lib/csv_plus_plus/parser/cell_value.tab.rb +65 -66
  47. data/lib/csv_plus_plus/parser/code_section.tab.rb +92 -84
  48. data/lib/csv_plus_plus/parser/modifier.tab.rb +40 -30
  49. data/lib/csv_plus_plus/reader/csv.rb +50 -0
  50. data/lib/csv_plus_plus/reader/google_sheets.rb +129 -0
  51. data/lib/csv_plus_plus/reader/reader.rb +27 -0
  52. data/lib/csv_plus_plus/reader/rubyxl.rb +37 -0
  53. data/lib/csv_plus_plus/reader.rb +14 -0
  54. data/lib/csv_plus_plus/runtime/graph.rb +6 -6
  55. data/lib/csv_plus_plus/runtime/{position_tracker.rb → position.rb} +16 -5
  56. data/lib/csv_plus_plus/runtime/references.rb +32 -27
  57. data/lib/csv_plus_plus/runtime/runtime.rb +73 -67
  58. data/lib/csv_plus_plus/runtime/scope.rb +280 -0
  59. data/lib/csv_plus_plus/runtime.rb +9 -9
  60. data/lib/csv_plus_plus/source_code.rb +14 -9
  61. data/lib/csv_plus_plus/template.rb +17 -12
  62. data/lib/csv_plus_plus/version.rb +1 -1
  63. data/lib/csv_plus_plus/writer/csv.rb +32 -5
  64. data/lib/csv_plus_plus/writer/excel.rb +19 -6
  65. data/lib/csv_plus_plus/writer/file_backer_upper.rb +27 -14
  66. data/lib/csv_plus_plus/writer/google_sheets.rb +23 -129
  67. data/lib/csv_plus_plus/writer/{google_sheet_builder.rb → google_sheets_builder.rb} +39 -55
  68. data/lib/csv_plus_plus/writer/merger.rb +56 -0
  69. data/lib/csv_plus_plus/writer/open_document.rb +16 -2
  70. data/lib/csv_plus_plus/writer/rubyxl_builder.rb +68 -43
  71. data/lib/csv_plus_plus/writer/writer.rb +42 -0
  72. data/lib/csv_plus_plus/writer.rb +58 -19
  73. data/lib/csv_plus_plus.rb +26 -14
  74. metadata +43 -18
  75. data/lib/csv_plus_plus/entities/cell_reference.rb +0 -231
  76. data/lib/csv_plus_plus/entities/variable.rb +0 -37
  77. data/lib/csv_plus_plus/error/syntax_error.rb +0 -71
  78. data/lib/csv_plus_plus/google_options.rb +0 -32
  79. data/lib/csv_plus_plus/lexer/lexer.rb +0 -89
  80. data/lib/csv_plus_plus/runtime/can_define_references.rb +0 -87
  81. data/lib/csv_plus_plus/runtime/can_resolve_references.rb +0 -209
  82. data/lib/csv_plus_plus/writer/base_writer.rb +0 -45
@@ -7,50 +7,37 @@ module CSVPlusPlus
7
7
  # are function calls and function definitions
8
8
  #
9
9
  # @attr_reader arguments [Array<Entity>] The arguments supplied to this entity.
10
- class EntityWithArguments < Entity
10
+ class EntityWithArguments < ::CSVPlusPlus::Entities::Entity
11
11
  extend ::T::Sig
12
+ extend ::T::Helpers
13
+ extend ::T::Generic
12
14
 
13
15
  abstract!
14
16
 
15
- sig { returns(::T::Array[::CSVPlusPlus::Entities::Entity]) }
17
+ ArgumentsType = type_member
18
+ public_constant :ArgumentsType
19
+
20
+ sig { returns(::T::Array[::CSVPlusPlus::Entities::EntityWithArguments::ArgumentsType]) }
16
21
  attr_reader :arguments
17
22
 
18
- sig do
19
- params(
20
- type: ::CSVPlusPlus::Entities::Type,
21
- id: ::T.nilable(::Symbol),
22
- arguments: ::T::Array[::CSVPlusPlus::Entities::Entity]
23
- ).void
24
- end
25
- # @param type [Entities::Type]
26
- # @param id [::String]
27
- # @param arguments [Array<Entity>]
28
- def initialize(type, id: nil, arguments: [])
29
- super(type, id:)
23
+ sig { params(arguments: ::T::Array[::CSVPlusPlus::Entities::EntityWithArguments::ArgumentsType]).void }
24
+ # @param arguments [Array<ArgumentsType>]
25
+ def initialize(arguments: [])
26
+ super()
30
27
  @arguments = arguments
31
28
  end
32
29
 
33
- sig { override.params(other: ::CSVPlusPlus::Entities::Entity).returns(::T::Boolean) }
30
+ sig { override.params(other: ::BasicObject).returns(::T::Boolean) }
34
31
  # @param other [Entity]
35
32
  #
36
33
  # @return [boolean]
37
34
  def ==(other)
38
- return false unless other.is_a?(self.class)
39
-
40
- @arguments == other.arguments && super
41
- end
42
-
43
- protected
44
-
45
- sig do
46
- params(arguments: ::T::Array[::CSVPlusPlus::Entities::Entity])
47
- .returns(::T::Array[::CSVPlusPlus::Entities::Entity])
48
- end
49
- attr_writer :arguments
50
-
51
- sig { params(runtime: ::CSVPlusPlus::Runtime::Runtime).returns(::T::Array[::String]) }
52
- def evaluate_arguments(runtime)
53
- @arguments.map { |arg| arg.evaluate(runtime) }
35
+ case other
36
+ when self.class
37
+ @arguments == other.arguments
38
+ else
39
+ false
40
+ end
54
41
  end
55
42
  end
56
43
  end
@@ -7,8 +7,15 @@ module CSVPlusPlus
7
7
  #
8
8
  # @attr_reader body [Entity] The body of the function. +body+ can contain variable references
9
9
  # from +@arguments+
10
- class Function < EntityWithArguments
10
+ class Function < ::CSVPlusPlus::Entities::EntityWithArguments
11
11
  extend ::T::Sig
12
+ include ::CSVPlusPlus::Entities::HasIdentifier
13
+
14
+ ArgumentsType = type_member { { fixed: ::Symbol } }
15
+ public_constant :ArgumentsType
16
+
17
+ sig { returns(::Symbol) }
18
+ attr_reader :id
12
19
 
13
20
  sig { returns(::CSVPlusPlus::Entities::Entity) }
14
21
  attr_reader :body
@@ -18,27 +25,31 @@ module CSVPlusPlus
18
25
  # @param arguments [Array<Symbol>]
19
26
  # @param body [Entity]
20
27
  def initialize(id, arguments, body)
21
- super(::CSVPlusPlus::Entities::Type::Function, id:, arguments: arguments.map(&:to_sym))
28
+ super(arguments: arguments.map(&:to_sym))
22
29
 
23
30
  @body = ::T.let(body, ::CSVPlusPlus::Entities::Entity)
31
+ @id = ::T.let(identifier(id), ::Symbol)
24
32
  end
25
33
 
26
- sig { override.params(runtime: ::CSVPlusPlus::Runtime::Runtime).returns(::String) }
27
- # @param runtime [Runtime]
34
+ sig { override.params(position: ::CSVPlusPlus::Runtime::Position).returns(::String) }
35
+ # @param position [Position]
28
36
  #
29
- # @return [::String]
30
- def evaluate(runtime)
31
- "def #{@id.to_s.upcase}(#{arguments.map(&:to_s).join(', ')}) #{@body.evaluate(runtime)}"
37
+ # @return [String]
38
+ def evaluate(position)
39
+ "def #{@id.to_s.upcase}(#{arguments.map(&:to_s).join(', ')}) #{@body.evaluate(position)}"
32
40
  end
33
41
 
34
- sig { override.params(other: ::CSVPlusPlus::Entities::Entity).returns(::T::Boolean) }
42
+ sig { override.params(other: ::BasicObject).returns(::T::Boolean) }
35
43
  # @param other [Entity]
36
44
  #
37
45
  # @return [::T::Boolean]
38
46
  def ==(other)
39
- return false unless super
40
-
41
- other.is_a?(self.class) && @body == other.body
47
+ case other
48
+ when self.class
49
+ @body == other.body && super
50
+ else
51
+ false
52
+ end
42
53
  end
43
54
  end
44
55
  end
@@ -8,26 +8,40 @@ module CSVPlusPlus
8
8
  # @attr_reader infix [boolean] Whether or not this function call is infix (X * Y, A + B, etc)
9
9
  class FunctionCall < EntityWithArguments
10
10
  extend ::T::Sig
11
+ include ::CSVPlusPlus::Entities::HasIdentifier
12
+
13
+ ArgumentsType = type_member { { fixed: ::CSVPlusPlus::Entities::Entity } }
14
+ public_constant :ArgumentsType
11
15
 
12
16
  sig { returns(::T::Boolean) }
13
17
  attr_reader :infix
14
18
 
15
- sig { params(id: ::Symbol, arguments: ::T::Array[::CSVPlusPlus::Entities::Entity], infix: ::T::Boolean).void }
19
+ sig { returns(::Symbol) }
20
+ attr_reader :id
21
+
22
+ sig do
23
+ params(
24
+ id: ::Symbol,
25
+ arguments: ::T::Array[::CSVPlusPlus::Entities::FunctionCall::ArgumentsType],
26
+ infix: ::T::Boolean
27
+ ).void
28
+ end
16
29
  # @param id [::String] The name of the function
17
30
  # @param arguments [Array<Entity>] The arguments to the function
18
31
  # @param infix [T::Boolean] Whether the function is infix
19
32
  def initialize(id, arguments, infix: false)
20
- super(::CSVPlusPlus::Entities::Type::FunctionCall, id:, arguments:)
33
+ super(arguments:)
21
34
 
35
+ @id = ::T.let(identifier(id), ::Symbol)
22
36
  @infix = infix
23
37
  end
24
38
 
25
- sig { override.params(runtime: ::CSVPlusPlus::Runtime::Runtime).returns(::String) }
26
- # @param runtime [Runtime]
39
+ sig { override.params(position: ::CSVPlusPlus::Runtime::Position).returns(::String) }
40
+ # @param position [Position]
27
41
  #
28
42
  # @return [::String]
29
- def evaluate(runtime)
30
- evaluated_arguments = evaluate_arguments(runtime)
43
+ def evaluate(position)
44
+ evaluated_arguments = evaluate_arguments(position)
31
45
 
32
46
  if @infix
33
47
  "(#{evaluated_arguments.join(" #{@id} ")})"
@@ -36,14 +50,24 @@ module CSVPlusPlus
36
50
  end
37
51
  end
38
52
 
39
- sig { override.params(other: ::CSVPlusPlus::Entities::Entity).returns(::T::Boolean) }
40
- # @param other [Entity]
53
+ sig { override.params(other: ::BasicObject).returns(::T::Boolean) }
54
+ # @param other [BasicObject]
41
55
  #
42
- # @return [boolean]
56
+ # @return [Boolean]
43
57
  def ==(other)
44
- return false unless super
58
+ case other
59
+ when self.class
60
+ @id == other.id && @infix == other.infix
61
+ else
62
+ false
63
+ end
64
+ end
65
+
66
+ private
45
67
 
46
- other.is_a?(self.class) && @id == other.id && @infix == other.infix
68
+ sig { params(position: ::CSVPlusPlus::Runtime::Position).returns(::T::Array[::String]) }
69
+ def evaluate_arguments(position)
70
+ @arguments.map { |arg| arg.evaluate(position) }
47
71
  end
48
72
  end
49
73
  end
@@ -0,0 +1,19 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module CSVPlusPlus
5
+ module Entities
6
+ # Can be included on any class that has a comparable id
7
+ module HasIdentifier
8
+ extend ::T::Sig
9
+
10
+ sig { params(symbol: ::Symbol).returns(::Symbol) }
11
+ # Variables and functions are case insensitive. I hate it but it's how excel is
12
+ #
13
+ # @param symbol [Symbol]
14
+ def identifier(symbol)
15
+ symbol.downcase
16
+ end
17
+ end
18
+ end
19
+ end
@@ -6,14 +6,16 @@ module CSVPlusPlus
6
6
  # A number value
7
7
  #
8
8
  # @attr_reader value [Numeric] The parsed number value
9
- class Number < Entity
9
+ class Number < ::CSVPlusPlus::Entities::Entity
10
+ extend ::T::Sig
11
+
10
12
  sig { returns(::Numeric) }
11
13
  attr_reader :value
12
14
 
13
15
  sig { params(value: ::T.any(::String, ::Numeric)).void }
14
16
  # @param value [String, Numeric] Either a +String+ that looks like a number, or an already parsed Numeric
15
17
  def initialize(value)
16
- super(::CSVPlusPlus::Entities::Type::Number)
18
+ super()
17
19
 
18
20
  @value =
19
21
  ::T.let(
@@ -26,22 +28,25 @@ module CSVPlusPlus
26
28
  )
27
29
  end
28
30
 
29
- sig { override.params(_runtime: ::CSVPlusPlus::Runtime::Runtime).returns(::String) }
30
- # @param _runtime [Runtime]
31
+ sig { override.params(_position: ::CSVPlusPlus::Runtime::Position).returns(::String) }
32
+ # @param _position [Position]
31
33
  #
32
34
  # @return [::String]
33
- def evaluate(_runtime)
35
+ def evaluate(_position)
34
36
  @value.to_s
35
37
  end
36
38
 
37
- sig { override.params(other: ::CSVPlusPlus::Entities::Entity).returns(::T::Boolean) }
38
- # @param other [Entity]
39
+ sig { override.params(other: ::BasicObject).returns(::T::Boolean) }
40
+ # @param other [BasicObject]
39
41
  #
40
42
  # @return [::T::Boolean]
41
43
  def ==(other)
42
- return false unless super
43
-
44
- other.is_a?(self.class) && @value == other.value
44
+ case other
45
+ when self.class
46
+ @value == other.value
47
+ else
48
+ false
49
+ end
45
50
  end
46
51
  end
47
52
  end
@@ -0,0 +1,77 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module CSVPlusPlus
5
+ module Entities
6
+ # A reference to something - this is typically either a cell reference (handled by +A1Reference+) or a reference
7
+ # to a variable.
8
+ #
9
+ # One sticking point with the design of this class is that we don't know if a reference is a variable reference
10
+ # unless we look at currently defined variables and see if there is one by that name. Since all cell references
11
+ # can be a valid variable name, we can't be sure which is which. So we delegate that decision as late as possible
12
+ # - in #evaluate
13
+ #
14
+ # @attr_reader scoped_to_expand [Expand, nil] If set, the expand in which this variable is scoped to. It cannot be
15
+ # resolved outside of the given expand.
16
+ class Reference < ::CSVPlusPlus::Entities::Entity
17
+ extend ::T::Sig
18
+ include ::CSVPlusPlus::Entities::HasIdentifier
19
+
20
+ sig { returns(::T.nilable(::String)) }
21
+ attr_reader :ref
22
+
23
+ # sig { returns(::T.nilable(::CSVPlusPlus::A1Reference)) }
24
+ # attr_reader :a1_ref
25
+
26
+ sig { params(ref: ::T.nilable(::String), a1_ref: ::T.nilable(::CSVPlusPlus::A1Reference)).void }
27
+ # Either +ref+, +cell_index+ or +row_index+ must be specified.
28
+ #
29
+ # @param ref [Integer, nil] An A1-style cell reference (that will be parsed into it's row/cell indexes).
30
+ # @param a1_ref [Integer, nil] An A1-style cell reference (that will be parsed into it's row/cell indexes).
31
+ def initialize(ref: nil, a1_ref: nil)
32
+ super()
33
+
34
+ raise(::ArgumentError, 'Must specify :ref or :a1_ref') unless ref || a1_ref
35
+
36
+ @ref = ref
37
+ @a1_ref = a1_ref
38
+ end
39
+
40
+ sig { override.params(other: ::BasicObject).returns(::T::Boolean) }
41
+ # @param other [BasicObject]
42
+ #
43
+ # @return [boolean]
44
+ def ==(other)
45
+ case other
46
+ when self.class
47
+ a1_ref == other.a1_ref
48
+ else
49
+ false
50
+ end
51
+ end
52
+
53
+ sig { returns(::CSVPlusPlus::A1Reference) }
54
+ # @return [A1Reference]
55
+ def a1_ref
56
+ @a1_ref ||= ::CSVPlusPlus::A1Reference.new(ref: ::T.must(ref))
57
+ end
58
+
59
+ sig { override.params(position: ::CSVPlusPlus::Runtime::Position).returns(::String) }
60
+ # Get the A1-style cell reference
61
+ #
62
+ # @param position [Position] The current position
63
+ #
64
+ # @return [::String] An A1-style reference
65
+ def evaluate(position)
66
+ # TODO: ugh make to_a1_ref not return a nil
67
+ ref || a1_ref.to_a1_ref(position) || ''
68
+ end
69
+
70
+ sig { returns(::T.nilable(::Symbol)) }
71
+ # @return [Symbol]
72
+ def id
73
+ ref && identifier(::T.must(ref).to_sym)
74
+ end
75
+ end
76
+ end
77
+ end
@@ -1,41 +1,54 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require_relative './entity'
5
+
4
6
  module CSVPlusPlus
5
7
  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
8
+ # A runtime value. These are values which can be materialized at any point via the +resolve_fn+ which
9
+ # will provide a value depending on the +Runtime+'s current state.
10
+ class RuntimeValue < ::CSVPlusPlus::Entities::Entity
11
11
  extend ::T::Sig
12
12
 
13
- sig { returns(::T::Array[::T.untyped]) }
14
- attr_reader :arguments
15
-
16
- sig { returns(::T.proc.params(arg0: ::CSVPlusPlus::Runtime::Runtime).returns(::CSVPlusPlus::Entities::Entity)) }
17
- attr_reader :resolve_fn
13
+ ResolveFn =
14
+ ::T.type_alias do
15
+ ::T.proc.params(
16
+ position: ::CSVPlusPlus::Runtime::Position,
17
+ arguments: ::T::Enumerable[::CSVPlusPlus::Entities::Entity]
18
+ ).returns(::CSVPlusPlus::Entities::Entity)
19
+ end
20
+ public_constant :ResolveFn
18
21
 
19
22
  sig do
20
- params(
21
- resolve_fn: ::T.proc.params(arg0: ::CSVPlusPlus::Runtime::Runtime).returns(::CSVPlusPlus::Entities::Entity),
22
- arguments: ::T::Array[::T.untyped]
23
- ).void
23
+ params(resolve_fn: ::CSVPlusPlus::Entities::RuntimeValue::ResolveFn).void
24
24
  end
25
25
  # @param resolve_fn [lambda] A lambda that is called when the runtime value is resolved
26
- # @param arguments [Any] Arguments to the runtime value call
27
- def initialize(resolve_fn, arguments: [])
28
- super(::CSVPlusPlus::Entities::Type::RuntimeValue)
29
-
30
- @arguments = arguments
26
+ def initialize(resolve_fn)
31
27
  @resolve_fn = resolve_fn
28
+ super()
29
+ end
30
+
31
+ sig do
32
+ params(
33
+ position: ::CSVPlusPlus::Runtime::Position,
34
+ arguments: ::T::Enumerable[::CSVPlusPlus::Entities::Entity]
35
+ ).returns(::CSVPlusPlus::Entities::Entity)
36
+ end
37
+ # Using the +@resolve_fn+, evaluate this runtime value into an +Entity+ that can be later evaluated
38
+ def call(position, arguments)
39
+ @resolve_fn.call(position, arguments)
32
40
  end
33
41
 
34
- sig { override.params(_runtime: ::CSVPlusPlus::Runtime::Runtime).returns(::String) }
35
- # @param _runtime [Runtime]
42
+ sig { override.params(_position: ::CSVPlusPlus::Runtime::Position).returns(::String) }
43
+ # Given the current runtime, call +@resolve_fn+ to produce a value
44
+ #
45
+ # @param _position [Position]
36
46
  #
37
- # @return [String]
38
- def evaluate(_runtime)
47
+ # @return [Entities::Entity]
48
+ def evaluate(_position)
49
+ # TODO: we can do a check on arguments here and make sure that the RuntimeValue is being called
50
+ # with the number of arguments it requires
51
+ # @resolve_fn.call(position, ::T.must(arguments)).evaluate(position)
39
52
  '(runtime value)'
40
53
  end
41
54
  end
@@ -6,7 +6,7 @@ module CSVPlusPlus
6
6
  # A string value
7
7
  #
8
8
  # @attr_reader value [String]
9
- class String < Entity
9
+ class String < ::CSVPlusPlus::Entities::Entity
10
10
  extend ::T::Sig
11
11
 
12
12
  sig { returns(::String) }
@@ -15,27 +15,30 @@ module CSVPlusPlus
15
15
  sig { params(value: ::String).void }
16
16
  # @param value [String] The string that has been parsed out of the template
17
17
  def initialize(value)
18
- super(::CSVPlusPlus::Entities::Type::String)
18
+ super()
19
19
 
20
20
  @value = ::T.let(value.gsub(/^"|"$/, ''), ::String)
21
21
  end
22
22
 
23
- sig { override.params(_runtime: ::CSVPlusPlus::Runtime::Runtime).returns(::String) }
24
- # @param _runtime [Runtime]
23
+ sig { override.params(_position: ::CSVPlusPlus::Runtime::Position).returns(::String) }
24
+ # @param _position [Position]
25
25
  #
26
26
  # @return [::String]
27
- def evaluate(_runtime)
27
+ def evaluate(_position)
28
28
  "\"#{@value}\""
29
29
  end
30
30
 
31
- sig { override.params(other: ::CSVPlusPlus::Entities::Entity).returns(::T::Boolean) }
32
- # @param other [Entity]
31
+ sig { override.params(other: ::BasicObject).returns(::T::Boolean) }
32
+ # @param other [BasicObject]
33
33
  #
34
34
  # @return [T::Boolean]
35
35
  def ==(other)
36
- return false unless super
37
-
38
- other.is_a?(self.class) && @value == other.value
36
+ case other
37
+ when self.class
38
+ @value == other.value
39
+ else
40
+ false
41
+ end
39
42
  end
40
43
  end
41
44
  end
@@ -3,36 +3,20 @@
3
3
 
4
4
  require_relative 'entities/entity'
5
5
  require_relative 'entities/entity_with_arguments'
6
+ require_relative 'entities/has_identifier'
6
7
 
7
8
  require_relative 'entities/boolean'
8
- require_relative 'entities/cell_reference'
9
9
  require_relative 'entities/date'
10
10
  require_relative 'entities/function'
11
11
  require_relative 'entities/function_call'
12
12
  require_relative 'entities/number'
13
+ require_relative 'entities/reference'
13
14
  require_relative 'entities/runtime_value'
14
15
  require_relative 'entities/string'
15
- require_relative 'entities/variable'
16
16
 
17
17
  module CSVPlusPlus
18
18
  # The entities that form abstract syntax trees which make up the language
19
19
  module Entities
20
- extend ::T::Sig
21
-
22
- # A primitive type. These all correspond to an implementation of the same name in the CSVPlusPlus::Entities module.
23
- class Type < ::T::Enum
24
- enums do
25
- Boolean = new
26
- CellReference = new
27
- Date = new
28
- Function = new
29
- FunctionCall = new
30
- Number = new
31
- RuntimeValue = new
32
- String = new
33
- Variable = new
34
- end
35
- end
36
20
  end
37
21
  end
38
22
 
@@ -0,0 +1,17 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module CSVPlusPlus
5
+ module Error
6
+ # An error that represents an invalid CLI option or state
7
+ class CLIError < ::CSVPlusPlus::Error::Error
8
+ extend ::T::Sig
9
+
10
+ sig { override.returns(::String) }
11
+ # @return [String]
12
+ def error_message
13
+ message
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module CSVPlusPlus
5
+ module Error
6
+ # An error that represents an invalid state during compilation.
7
+ class CompilerError < ::CSVPlusPlus::Error::Error
8
+ extend ::T::Sig
9
+
10
+ sig { override.returns(::String) }
11
+ # @return [String]
12
+ def error_message
13
+ message
14
+ end
15
+ end
16
+ end
17
+ end
@@ -4,17 +4,30 @@
4
4
  module CSVPlusPlus
5
5
  module Error
6
6
  # An error thrown by our code (generally to be handled at the top level bin/ command)
7
- class Error < StandardError
7
+ class Error < ::StandardError
8
8
  extend ::T::Sig
9
9
  extend ::T::Helpers
10
10
 
11
- sig { returns(::String) }
11
+ abstract!
12
+
13
+ sig { returns(::T.nilable(::StandardError)) }
14
+ attr_reader :wrapped_error
15
+
16
+ sig { params(message: ::String, wrapped_error: ::T.nilable(::StandardError)).void }
17
+ # @param wrapped_error [StandardError] The underlying error that caused the syntax error. For example a
18
+ # Racc::ParseError that was thrown
19
+ def initialize(message, wrapped_error: nil)
20
+ super(message)
21
+
22
+ @message = message
23
+ @wrapped_error = wrapped_error
24
+ end
25
+
26
+ sig { abstract.returns(::String) }
12
27
  # Return an error message for display to a command-line user.
13
28
  #
14
29
  # @return [::String]
15
- def error_message
16
- message
17
- end
30
+ def error_message; end
18
31
  end
19
32
  end
20
33
  end
@@ -1,36 +1,35 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- require_relative './syntax_error'
5
-
6
4
  module CSVPlusPlus
7
5
  module Error
8
6
  # An error that can be thrown when there is an error parsing a modifier
9
7
  #
10
8
  # @attr_reader message [::String] A helpful error message
11
9
  # @attr_reader bad_input [String] The offending input that caused the error to be thrown
12
- class FormulaSyntaxError < ::CSVPlusPlus::Error::SyntaxError
13
- attr_reader :message, :bad_input
10
+ class FormulaSyntaxError < ::CSVPlusPlus::Error::Error
11
+ extend ::T::Sig
12
+ include ::CSVPlusPlus::Error::PositionalError
14
13
 
15
- # You must supply either a +choices+ or +message+
16
- #
14
+ sig { returns(::String) }
15
+ attr_reader :bad_input
16
+
17
+ sig { params(message: ::String, bad_input: ::String, wrapped_error: ::T.nilable(::StandardError)).void }
17
18
  # @param message [String] A relevant message to show
18
19
  # @param bad_input [String] The offending input that caused the error to be thrown
19
- # @param runtime [Runtime] The current runtime
20
20
  # @param wrapped_error [StandardError] The underlying error that caused the syntax error. For example a
21
21
  # Racc::ParseError that was thrown
22
- def initialize(message, bad_input, runtime, wrapped_error: nil)
22
+ def initialize(message, bad_input:, wrapped_error: nil)
23
+ super(message, wrapped_error:)
23
24
  @bad_input = bad_input
24
- @message = message
25
-
26
- super(runtime, wrapped_error:)
27
25
  end
28
26
 
27
+ sig { override.returns(::String) }
29
28
  # Create a relevant error message given +@bad_input+ and +@message+.
30
29
  #
31
30
  # @return [::String]
32
31
  def error_message
33
- "#{@message}: \"#{@bad_input}\""
32
+ "#{message}: \"#{bad_input}\""
34
33
  end
35
34
  end
36
35
  end