template-ruby 0.1.0 → 0.2.0
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.
- checksums.yaml +4 -4
 - data/.editorconfig +9 -0
 - data/.gitignore +1 -0
 - data/.prettierrc +3 -0
 - data/CHANGELOG.md +15 -0
 - data/Gemfile.lock +1 -1
 - data/README.md +10 -0
 - data/bin/template +39 -0
 - data/docs/euler/1.template +14 -0
 - data/docs/euler/2.template +16 -0
 - data/docs/euler/3.template +16 -0
 - data/docs/euler/4.template +11 -0
 - data/docs/euler/5.template +14 -0
 - data/docs/precedence.template +94 -0
 - data/lib/code/error.rb +15 -0
 - data/lib/code/node/base_10_decimal.rb +12 -7
 - data/lib/code/node/base_10_integer.rb +13 -4
 - data/lib/code/node/base_10_number.rb +3 -3
 - data/lib/code/node/base_16_number.rb +2 -2
 - data/lib/code/node/base_2_number.rb +2 -2
 - data/lib/code/node/base_8_number.rb +2 -2
 - data/lib/code/node/block.rb +17 -0
 - data/lib/code/node/boolean.rb +13 -4
 - data/lib/code/node/call.rb +40 -8
 - data/lib/code/node/call_argument.rb +37 -0
 - data/lib/code/node/chained_call.rb +38 -0
 - data/lib/code/node/code.rb +4 -7
 - data/lib/code/node/defined.rb +19 -0
 - data/lib/code/node/dictionnary.rb +11 -7
 - data/lib/code/node/dictionnary_key_value.rb +3 -3
 - data/lib/code/node/equal.rb +36 -0
 - data/lib/code/node/function.rb +17 -0
 - data/lib/code/node/function_argument.rb +45 -0
 - data/lib/code/node/group.rb +13 -0
 - data/lib/code/node/if.rb +55 -0
 - data/lib/code/node/if_modifier.rb +48 -0
 - data/lib/code/node/keyword_call_argument.rb +30 -0
 - data/lib/code/node/keyword_function_argument.rb +33 -0
 - data/lib/code/node/list.rb +10 -4
 - data/lib/code/node/name.rb +37 -4
 - data/lib/code/node/negation.rb +33 -0
 - data/lib/code/node/not_keyword.rb +13 -0
 - data/lib/code/node/nothing.rb +2 -2
 - data/lib/code/node/number.rb +3 -3
 - data/lib/code/node/operation.rb +33 -0
 - data/lib/code/node/or_keyword.rb +34 -0
 - data/lib/code/node/power.rb +16 -0
 - data/lib/code/node/range.rb +31 -0
 - data/lib/code/node/regular_call_argument.rb +34 -0
 - data/lib/code/node/regular_function_argument.rb +36 -0
 - data/lib/code/node/rescue.rb +16 -0
 - data/lib/code/node/statement.rb +53 -3
 - data/lib/code/node/string.rb +2 -2
 - data/lib/code/node/ternary.rb +26 -0
 - data/lib/code/node/unary_minus.rb +22 -0
 - data/lib/code/node/while.rb +42 -0
 - data/lib/code/node.rb +10 -0
 - data/lib/code/object/argument.rb +41 -0
 - data/lib/code/object/boolean.rb +8 -9
 - data/lib/code/object/decimal.rb +32 -9
 - data/lib/code/object/dictionnary.rb +33 -10
 - data/lib/code/object/function.rb +64 -0
 - data/lib/code/object/integer.rb +94 -7
 - data/lib/code/object/list.rb +190 -10
 - data/lib/code/object/nothing.rb +10 -9
 - data/lib/code/object/number.rb +6 -0
 - data/lib/code/object/range.rb +158 -0
 - data/lib/code/object/string.rb +37 -7
 - data/lib/code/object.rb +129 -2
 - data/lib/code/parser/addition.rb +29 -0
 - data/lib/code/parser/and_operator.rb +28 -0
 - data/lib/code/parser/bitwise_and.rb +28 -0
 - data/lib/code/parser/bitwise_or.rb +29 -0
 - data/lib/code/parser/call.rb +77 -3
 - data/lib/code/parser/defined.rb +20 -0
 - data/lib/code/parser/equal.rb +42 -0
 - data/lib/code/parser/equality.rb +36 -0
 - data/lib/code/parser/function.rb +57 -0
 - data/lib/code/parser/greater_than.rb +33 -0
 - data/lib/code/parser/group.rb +17 -0
 - data/lib/code/parser/if.rb +33 -0
 - data/lib/code/parser/if_modifier.rb +28 -0
 - data/lib/code/parser/multiplication.rb +30 -0
 - data/lib/code/parser/name.rb +44 -4
 - data/lib/code/parser/negation.rb +19 -0
 - data/lib/code/parser/not_keyword.rb +21 -0
 - data/lib/code/parser/nothing.rb +2 -2
 - data/lib/code/parser/or_keyword.rb +29 -0
 - data/lib/code/parser/or_operator.rb +28 -0
 - data/lib/code/parser/power.rb +25 -0
 - data/lib/code/parser/range.rb +25 -0
 - data/lib/code/parser/rescue.rb +23 -0
 - data/lib/code/parser/shift.rb +31 -0
 - data/lib/code/parser/statement.rb +1 -4
 - data/lib/code/parser/string.rb +7 -1
 - data/lib/code/parser/ternary.rb +25 -0
 - data/lib/code/parser/unary_minus.rb +13 -0
 - data/lib/code/parser/while.rb +25 -0
 - data/lib/code.rb +5 -7
 - data/lib/template/node/code_part.rb +2 -2
 - data/lib/template/node/part.rb +2 -2
 - data/lib/template/node/template.rb +4 -2
 - data/lib/template/node/text_part.rb +1 -1
 - data/lib/template-ruby.rb +4 -0
 - data/lib/template.rb +9 -4
 - data/spec/call_spec.rb +22 -0
 - data/spec/code/error/type_error_spec.rb +65 -0
 - data/spec/code/parser/boolean_spec.rb +1 -1
 - data/spec/code/parser/call_spec.rb +40 -11
 - data/spec/code/parser/dictionnary_spec.rb +11 -11
 - data/spec/code/parser/function_spec.rb +32 -0
 - data/spec/code/parser/list_spec.rb +5 -5
 - data/spec/code/parser/nothing_spec.rb +1 -1
 - data/spec/code/parser/number_spec.rb +35 -35
 - data/spec/code/parser/string_spec.rb +3 -2
 - data/spec/code_spec.rb +75 -3
 - data/spec/function_spec.rb +26 -0
 - data/spec/spec_helper.rb +2 -0
 - data/spec/template/parser/template_spec.rb +1 -1
 - data/spec/template_spec.rb +6 -6
 - data/template-ruby.gemspec +6 -3
 - metadata +76 -4
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: f42cd4f03c1c1bacdfdcc9e454cdc19411220aa407698bc63024f59311d0a23f
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 59da1aed5e7e8e729c1c4a44c36c62fcaacc47780229e61b8606708e1414e4c4
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 4e56e63c45fce924c3b62571a58be48846be2a0348565713a2e5de6f6a33f07d15ce4e37fc0d48a3ef964ff3d8cb8810bff55ae6f2cc5bba184df2b14182d85c
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 26ba43eea5b6d61a99fd358bdcded3bfcc52e0b0b57910c62f0773380f3777a4b29b8ff355937c0d716cdd5f4e7d29561d17c642de1476a06a32fdd798c3d6ad
         
     | 
    
        data/.editorconfig
    ADDED
    
    
    
        data/.gitignore
    CHANGED
    
    
    
        data/.prettierrc
    ADDED
    
    
    
        data/CHANGELOG.md
    ADDED
    
    | 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Changelog
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            All notable changes to this project will be documented in this file.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
         
     | 
| 
      
 6 
     | 
    
         
            +
            and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            ## 0.2.0 / 2022-08-30
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            - Programming language capable of solving the first 5 Project Euler problems
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            ## 0.1.0 / 2022-07-28
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            - Initial version with interpolation
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
    
        data/Gemfile.lock
    CHANGED
    
    
    
        data/README.md
    ADDED
    
    
    
        data/bin/template
    ADDED
    
    | 
         @@ -0,0 +1,39 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "optparse"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_relative "../lib/template-ruby"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            options = {}
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            OptionParser.new do |opts|
         
     | 
| 
      
 9 
     | 
    
         
            +
              opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              opts.on("-i INPUT", "--input=INPUT", "Input in the template language") do |input|
         
     | 
| 
      
 12 
     | 
    
         
            +
                if File.exists?(input)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  input = File.read(input)
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                options[:input] = input
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              opts.on("-c CONTEXT", "--context=CONTEXT", "Context in the code language") do |context|
         
     | 
| 
      
 20 
     | 
    
         
            +
                if File.exists?(context)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  context = File.read(context)
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                options[:context] = context
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              opts.on("-p", "--parse", "Get parser results for input") do |parse|
         
     | 
| 
      
 28 
     | 
    
         
            +
                options[:parse] = parse
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
            end.parse!
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            input = options.fetch(:input, "")
         
     | 
| 
      
 33 
     | 
    
         
            +
            context = options.fetch(:context, "")
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            if options[:parse]
         
     | 
| 
      
 36 
     | 
    
         
            +
              pp ::Template::Parser::Template.new.parse(input)
         
     | 
| 
      
 37 
     | 
    
         
            +
            else
         
     | 
| 
      
 38 
     | 
    
         
            +
              Template.render(input, context, io: $stdout)
         
     | 
| 
      
 39 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,94 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            - Code
         
     | 
| 
      
 2 
     | 
    
         
            +
              - {a = "Go" a += "od" a}
         
     | 
| 
      
 3 
     | 
    
         
            +
            - Statement
         
     | 
| 
      
 4 
     | 
    
         
            +
              - {a = "Good"}
         
     | 
| 
      
 5 
     | 
    
         
            +
              - {
         
     | 
| 
      
 6 
     | 
    
         
            +
                 a = 0
         
     | 
| 
      
 7 
     | 
    
         
            +
                 while a < 10
         
     | 
| 
      
 8 
     | 
    
         
            +
                   a += 1
         
     | 
| 
      
 9 
     | 
    
         
            +
                   "Good"
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
                }
         
     | 
| 
      
 12 
     | 
    
         
            +
            - While
         
     | 
| 
      
 13 
     | 
    
         
            +
              - {
         
     | 
| 
      
 14 
     | 
    
         
            +
                 a = 0
         
     | 
| 
      
 15 
     | 
    
         
            +
                 until a > 10
         
     | 
| 
      
 16 
     | 
    
         
            +
                   a += 1
         
     | 
| 
      
 17 
     | 
    
         
            +
                   "Good"
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
                }
         
     | 
| 
      
 20 
     | 
    
         
            +
              - {
         
     | 
| 
      
 21 
     | 
    
         
            +
                a = 0
         
     | 
| 
      
 22 
     | 
    
         
            +
                while
         
     | 
| 
      
 23 
     | 
    
         
            +
                  if a > 10
         
     | 
| 
      
 24 
     | 
    
         
            +
                    false
         
     | 
| 
      
 25 
     | 
    
         
            +
                  else
         
     | 
| 
      
 26 
     | 
    
         
            +
                    true
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                  a += 1
         
     | 
| 
      
 29 
     | 
    
         
            +
                  "Good"
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
                }
         
     | 
| 
      
 32 
     | 
    
         
            +
            - If
         
     | 
| 
      
 33 
     | 
    
         
            +
              - {if true "Good" end}
         
     | 
| 
      
 34 
     | 
    
         
            +
              - {if true if false "Bad" else "Good" end}
         
     | 
| 
      
 35 
     | 
    
         
            +
            - IfModifier
         
     | 
| 
      
 36 
     | 
    
         
            +
              - {"Good" if true}
         
     | 
| 
      
 37 
     | 
    
         
            +
            - OrKeyword
         
     | 
| 
      
 38 
     | 
    
         
            +
              - {false or "Good"}
         
     | 
| 
      
 39 
     | 
    
         
            +
            - NotKeyword
         
     | 
| 
      
 40 
     | 
    
         
            +
              - {not false and "Good"}
         
     | 
| 
      
 41 
     | 
    
         
            +
            - Defined
         
     | 
| 
      
 42 
     | 
    
         
            +
              - {a = 1 "Good" if defined?(a)}
         
     | 
| 
      
 43 
     | 
    
         
            +
            - Equal
         
     | 
| 
      
 44 
     | 
    
         
            +
              - {a = "Good"}
         
     | 
| 
      
 45 
     | 
    
         
            +
            - Rescue
         
     | 
| 
      
 46 
     | 
    
         
            +
              - {0 > "String" rescue "Good"}
         
     | 
| 
      
 47 
     | 
    
         
            +
            - Ternary
         
     | 
| 
      
 48 
     | 
    
         
            +
              - {nothing ? "Bad" : "Good"}
         
     | 
| 
      
 49 
     | 
    
         
            +
            - Range
         
     | 
| 
      
 50 
     | 
    
         
            +
              - {("Good".."Bad").first}
         
     | 
| 
      
 51 
     | 
    
         
            +
            - OrOperator
         
     | 
| 
      
 52 
     | 
    
         
            +
              - {false || "Good"}
         
     | 
| 
      
 53 
     | 
    
         
            +
            - AndOperator
         
     | 
| 
      
 54 
     | 
    
         
            +
              - {"Bad" && "Good"}
         
     | 
| 
      
 55 
     | 
    
         
            +
            - Equality
         
     | 
| 
      
 56 
     | 
    
         
            +
              - {1 == 1 ? "Good"}
         
     | 
| 
      
 57 
     | 
    
         
            +
            - GreaterThan
         
     | 
| 
      
 58 
     | 
    
         
            +
              - {2 > 1 ? "Good"}
         
     | 
| 
      
 59 
     | 
    
         
            +
            - BitwiseOr
         
     | 
| 
      
 60 
     | 
    
         
            +
              - {2 | 1 == 3 ? "Good"}
         
     | 
| 
      
 61 
     | 
    
         
            +
            - BitwiseAnd
         
     | 
| 
      
 62 
     | 
    
         
            +
              - {2 & 1 == 0 ? "Good"}
         
     | 
| 
      
 63 
     | 
    
         
            +
            - Shift
         
     | 
| 
      
 64 
     | 
    
         
            +
              - {1 << 1 == 2 ? "Good"}
         
     | 
| 
      
 65 
     | 
    
         
            +
            - Addition
         
     | 
| 
      
 66 
     | 
    
         
            +
              - {1 + 1 == 2 ? "Good"}
         
     | 
| 
      
 67 
     | 
    
         
            +
            - Multiplication
         
     | 
| 
      
 68 
     | 
    
         
            +
              - {1 * 2 == 2 ? "Good"}
         
     | 
| 
      
 69 
     | 
    
         
            +
            - UnaryMinus
         
     | 
| 
      
 70 
     | 
    
         
            +
              - {-1 == 1 - 2 ? "Good"}
         
     | 
| 
      
 71 
     | 
    
         
            +
            - Power
         
     | 
| 
      
 72 
     | 
    
         
            +
              - {2 ** 2 == 4 ? "Good"}
         
     | 
| 
      
 73 
     | 
    
         
            +
            - Negation
         
     | 
| 
      
 74 
     | 
    
         
            +
              - {!false ? "Good"}
         
     | 
| 
      
 75 
     | 
    
         
            +
            - Function
         
     | 
| 
      
 76 
     | 
    
         
            +
              - {good = () => { "Good" } good}
         
     | 
| 
      
 77 
     | 
    
         
            +
            - Call
         
     | 
| 
      
 78 
     | 
    
         
            +
              - {["Good"].first}
         
     | 
| 
      
 79 
     | 
    
         
            +
            - Dictionnary
         
     | 
| 
      
 80 
     | 
    
         
            +
              - {{a: "Good"}.a}
         
     | 
| 
      
 81 
     | 
    
         
            +
            - List
         
     | 
| 
      
 82 
     | 
    
         
            +
              - {["Good", "Bad"].first}
         
     | 
| 
      
 83 
     | 
    
         
            +
            - String
         
     | 
| 
      
 84 
     | 
    
         
            +
              - {"Good"}
         
     | 
| 
      
 85 
     | 
    
         
            +
            - Number
         
     | 
| 
      
 86 
     | 
    
         
            +
              - {1 == 1 ? "Good"}
         
     | 
| 
      
 87 
     | 
    
         
            +
            - Boolean
         
     | 
| 
      
 88 
     | 
    
         
            +
              - {true ? "Good"}
         
     | 
| 
      
 89 
     | 
    
         
            +
            - Nothing
         
     | 
| 
      
 90 
     | 
    
         
            +
              - {nothing ? "Bad" : "Good"}
         
     | 
| 
      
 91 
     | 
    
         
            +
            - Group
         
     | 
| 
      
 92 
     | 
    
         
            +
              - {(a = 0 a += 1 a) == 1 ? "Good"}
         
     | 
| 
      
 93 
     | 
    
         
            +
            - Name
         
     | 
| 
      
 94 
     | 
    
         
            +
              - {a = "Good" a}
         
     | 
    
        data/lib/code/error.rb
    ADDED
    
    
| 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            class Code
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Node
         
     | 
| 
       3 
     | 
    
         
            -
                class Base10Decimal
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Base10Decimal < Node
         
     | 
| 
       4 
4 
     | 
    
         
             
                  def initialize(number)
         
     | 
| 
       5 
5 
     | 
    
         
             
                    @sign = number[:sign]
         
     | 
| 
       6 
6 
     | 
    
         
             
                    @whole = number.fetch(:whole)
         
     | 
| 
         @@ -11,12 +11,17 @@ class Code 
     | 
|
| 
       11 
11 
     | 
    
         
             
                    end
         
     | 
| 
       12 
12 
     | 
    
         
             
                  end
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                  def evaluate( 
     | 
| 
       15 
     | 
    
         
            -
                     
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
                       
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def evaluate(**args)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    if @exponent
         
     | 
| 
      
 16 
     | 
    
         
            +
                      exponent = @exponent.evaluate(**args)
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                      ::Code::Object::Decimal.new(
         
     | 
| 
      
 19 
     | 
    
         
            +
                        "#{sign}#{whole}.#{decimal}",
         
     | 
| 
      
 20 
     | 
    
         
            +
                        exponent: exponent,
         
     | 
| 
      
 21 
     | 
    
         
            +
                      )
         
     | 
| 
      
 22 
     | 
    
         
            +
                    else
         
     | 
| 
      
 23 
     | 
    
         
            +
                      ::Code::Object::Decimal.new("#{sign}#{whole}.#{decimal}")
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
       20 
25 
     | 
    
         
             
                  end
         
     | 
| 
       21 
26 
     | 
    
         | 
| 
       22 
27 
     | 
    
         
             
                  private
         
     | 
| 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            class Code
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Node
         
     | 
| 
       3 
     | 
    
         
            -
                class Base10Integer
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Base10Integer < Node
         
     | 
| 
       4 
4 
     | 
    
         
             
                  def initialize(number)
         
     | 
| 
       5 
5 
     | 
    
         
             
                    @sign = number[:sign]
         
     | 
| 
       6 
6 
     | 
    
         
             
                    @whole = number.fetch(:whole)
         
     | 
| 
         @@ -10,9 +10,18 @@ class Code 
     | 
|
| 
       10 
10 
     | 
    
         
             
                    end
         
     | 
| 
       11 
11 
     | 
    
         
             
                  end
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
                  def evaluate( 
     | 
| 
       14 
     | 
    
         
            -
                     
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def evaluate(**args)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    if @exponent
         
     | 
| 
      
 15 
     | 
    
         
            +
                      exponent = @exponent.evaluate(**args)
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                      if exponent.is_a?(::Code::Object::Decimal)
         
     | 
| 
      
 18 
     | 
    
         
            +
                        ::Code::Object::Decimal.new("#{sign}#{whole}", exponent: exponent)
         
     | 
| 
      
 19 
     | 
    
         
            +
                      else
         
     | 
| 
      
 20 
     | 
    
         
            +
                        ::Code::Object::Integer.new("#{sign}#{whole}", exponent: exponent)
         
     | 
| 
      
 21 
     | 
    
         
            +
                      end
         
     | 
| 
      
 22 
     | 
    
         
            +
                    else
         
     | 
| 
      
 23 
     | 
    
         
            +
                      ::Code::Object::Integer.new("#{sign}#{whole}")
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
       16 
25 
     | 
    
         
             
                  end
         
     | 
| 
       17 
26 
     | 
    
         | 
| 
       18 
27 
     | 
    
         
             
                  private
         
     | 
| 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            class Code
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Node
         
     | 
| 
       3 
     | 
    
         
            -
                class Base10Number
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Base10Number < Node
         
     | 
| 
       4 
4 
     | 
    
         
             
                  def initialize(number)
         
     | 
| 
       5 
5 
     | 
    
         
             
                    if number.key?(:integer)
         
     | 
| 
       6 
6 
     | 
    
         
             
                      @number = ::Code::Node::Base10Integer.new(number[:integer])
         
     | 
| 
         @@ -11,8 +11,8 @@ class Code 
     | 
|
| 
       11 
11 
     | 
    
         
             
                    end
         
     | 
| 
       12 
12 
     | 
    
         
             
                  end
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                  def evaluate( 
     | 
| 
       15 
     | 
    
         
            -
                    @number.evaluate( 
     | 
| 
      
 14 
     | 
    
         
            +
                  def evaluate(**args)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @number.evaluate(**args)
         
     | 
| 
       16 
16 
     | 
    
         
             
                  end
         
     | 
| 
       17 
17 
     | 
    
         
             
                end
         
     | 
| 
       18 
18 
     | 
    
         
             
              end
         
     | 
| 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Code
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Node
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Block < Node
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def initialize(block)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    @body = ::Code::Node::Code.new(block.fetch(:body))
         
     | 
| 
      
 6 
     | 
    
         
            +
                    @arguments = block.fetch(:arguments, [])
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @arguments.map! do |argument|
         
     | 
| 
      
 8 
     | 
    
         
            +
                      ::Code::Node::FunctionArgument.new(argument)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    end
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def evaluate(**args)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    ::Code::Object::Function.new(arguments: @arguments, body: @body)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/code/node/boolean.rb
    CHANGED
    
    | 
         @@ -1,12 +1,21 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            class Code
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Node
         
     | 
| 
       3 
     | 
    
         
            -
                class Boolean
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Boolean < Node
         
     | 
| 
      
 4 
     | 
    
         
            +
                  TRUE = "true"
         
     | 
| 
      
 5 
     | 
    
         
            +
                  FALSE = "false"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
       4 
7 
     | 
    
         
             
                  def initialize(boolean)
         
     | 
| 
       5 
     | 
    
         
            -
                    @boolean = boolean 
     | 
| 
      
 8 
     | 
    
         
            +
                    @boolean = boolean
         
     | 
| 
       6 
9 
     | 
    
         
             
                  end
         
     | 
| 
       7 
10 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
                  def evaluate( 
     | 
| 
       9 
     | 
    
         
            -
                     
     | 
| 
      
 11 
     | 
    
         
            +
                  def evaluate(**args)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    if @boolean == TRUE
         
     | 
| 
      
 13 
     | 
    
         
            +
                      ::Code::Object::Boolean.new(true)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    elsif @boolean == FALSE
         
     | 
| 
      
 15 
     | 
    
         
            +
                      ::Code::Object::Boolean.new(false)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    else
         
     | 
| 
      
 17 
     | 
    
         
            +
                      raise NotImplementedError, @boolean.inspect
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
       10 
19 
     | 
    
         
             
                  end
         
     | 
| 
       11 
20 
     | 
    
         
             
                end
         
     | 
| 
       12 
21 
     | 
    
         
             
              end
         
     | 
    
        data/lib/code/node/call.rb
    CHANGED
    
    | 
         @@ -1,19 +1,51 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            class Code
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Node
         
     | 
| 
       3 
     | 
    
         
            -
                class Call
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Call < Node
         
     | 
| 
       4 
4 
     | 
    
         
             
                  def initialize(call)
         
     | 
| 
       5 
5 
     | 
    
         
             
                    @left = ::Code::Node::Statement.new(call.fetch(:left))
         
     | 
| 
       6 
     | 
    
         
            -
                    @right = ::Code::Node::Statement.new(call.fetch(:right))
         
     | 
| 
       7 
     | 
    
         
            -
                  end
         
     | 
| 
       8 
6 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
                     
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
      
 7 
     | 
    
         
            +
                    @arguments = call.fetch(:arguments, [])
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @arguments.map! { |argument| ::Code::Node::CallArgument.new(argument) }
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    if call.key?(:right)
         
     | 
| 
      
 11 
     | 
    
         
            +
                      @right = call.fetch(:right).map do |right|
         
     | 
| 
      
 12 
     | 
    
         
            +
                        ::Code::Node::ChainedCall.new(right)
         
     | 
| 
      
 13 
     | 
    
         
            +
                      end
         
     | 
| 
      
 14 
     | 
    
         
            +
                    end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    if call.key?(:block)
         
     | 
| 
      
 17 
     | 
    
         
            +
                      @block = ::Code::Node::Block.new(call.fetch(:block))
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
       12 
19 
     | 
    
         
             
                  end
         
     | 
| 
       13 
20 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                   
     | 
| 
      
 21 
     | 
    
         
            +
                  def evaluate(**args)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    if @right
         
     | 
| 
      
 23 
     | 
    
         
            +
                      left = @left.evaluate(**args)
         
     | 
| 
      
 24 
     | 
    
         
            +
                      @right.reduce(left) do |acc, element|
         
     | 
| 
      
 25 
     | 
    
         
            +
                        element.evaluate(**args.merge(object: acc))
         
     | 
| 
      
 26 
     | 
    
         
            +
                      end
         
     | 
| 
      
 27 
     | 
    
         
            +
                    else
         
     | 
| 
      
 28 
     | 
    
         
            +
                      arguments =
         
     | 
| 
      
 29 
     | 
    
         
            +
                        @arguments.map do |argument|
         
     | 
| 
      
 30 
     | 
    
         
            +
                          ::Code::Object::Argument.new(
         
     | 
| 
      
 31 
     | 
    
         
            +
                            argument.evaluate(**args),
         
     | 
| 
      
 32 
     | 
    
         
            +
                            name: argument.name,
         
     | 
| 
      
 33 
     | 
    
         
            +
                            splat: argument.splat?,
         
     | 
| 
      
 34 
     | 
    
         
            +
                            keyword_splat: argument.keyword_splat?,
         
     | 
| 
      
 35 
     | 
    
         
            +
                            block: argument.block?,
         
     | 
| 
      
 36 
     | 
    
         
            +
                          )
         
     | 
| 
      
 37 
     | 
    
         
            +
                        end
         
     | 
| 
       15 
38 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
      
 39 
     | 
    
         
            +
                      if @block
         
     | 
| 
      
 40 
     | 
    
         
            +
                        arguments << ::Code::Object::Argument.new(
         
     | 
| 
      
 41 
     | 
    
         
            +
                          @block.evaluate(**args),
         
     | 
| 
      
 42 
     | 
    
         
            +
                          block: true,
         
     | 
| 
      
 43 
     | 
    
         
            +
                        )
         
     | 
| 
      
 44 
     | 
    
         
            +
                      end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                      @left.evaluate(**args.merge(arguments: arguments))
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
       17 
49 
     | 
    
         
             
                end
         
     | 
| 
       18 
50 
     | 
    
         
             
              end
         
     | 
| 
       19 
51 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Code
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Node
         
     | 
| 
      
 3 
     | 
    
         
            +
                class CallArgument < Node
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def initialize(argument)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    if argument.key?(:regular)
         
     | 
| 
      
 6 
     | 
    
         
            +
                      @argument =
         
     | 
| 
      
 7 
     | 
    
         
            +
                        ::Code::Node::RegularCallArgument.new(argument.fetch(:regular))
         
     | 
| 
      
 8 
     | 
    
         
            +
                    elsif argument.key?(:keyword)
         
     | 
| 
      
 9 
     | 
    
         
            +
                      @argument =
         
     | 
| 
      
 10 
     | 
    
         
            +
                        ::Code::Node::KeywordCallArgument.new(argument.fetch(:keyword))
         
     | 
| 
      
 11 
     | 
    
         
            +
                    else
         
     | 
| 
      
 12 
     | 
    
         
            +
                      raise NotImplementedError.new(argument.inspect)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    end
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def evaluate(**args)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    @argument.evaluate(**args)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def name
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @argument.name
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  def block?
         
     | 
| 
      
 25 
     | 
    
         
            +
                    @argument.block?
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  def splat?
         
     | 
| 
      
 29 
     | 
    
         
            +
                    @argument.splat?
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  def keyword_splat?
         
     | 
| 
      
 33 
     | 
    
         
            +
                    @argument.keyword_splat?
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Code
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Node
         
     | 
| 
      
 3 
     | 
    
         
            +
                class ChainedCall < Node
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def initialize(chained_call)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    @name = ::Code::Node::Name.new(chained_call.fetch(:name))
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                    @arguments = chained_call.fetch(:arguments, [])
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @arguments.map! { |argument| ::Code::Node::CallArgument.new(argument) }
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    if chained_call.key?(:block)
         
     | 
| 
      
 11 
     | 
    
         
            +
                      @block = ::Code::Node::Block.new(chained_call.fetch(:block))
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def evaluate(**args)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    arguments =
         
     | 
| 
      
 17 
     | 
    
         
            +
                      @arguments.map do |argument|
         
     | 
| 
      
 18 
     | 
    
         
            +
                        ::Code::Object::Argument.new(
         
     | 
| 
      
 19 
     | 
    
         
            +
                          argument.evaluate(**args.merge(object: nil)),
         
     | 
| 
      
 20 
     | 
    
         
            +
                          name: argument.name,
         
     | 
| 
      
 21 
     | 
    
         
            +
                          splat: argument.splat?,
         
     | 
| 
      
 22 
     | 
    
         
            +
                          keyword_splat: argument.keyword_splat?,
         
     | 
| 
      
 23 
     | 
    
         
            +
                          block: argument.block?,
         
     | 
| 
      
 24 
     | 
    
         
            +
                        )
         
     | 
| 
      
 25 
     | 
    
         
            +
                      end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    if @block
         
     | 
| 
      
 28 
     | 
    
         
            +
                      arguments << ::Code::Object::Argument.new(
         
     | 
| 
      
 29 
     | 
    
         
            +
                        @block.evaluate(**args.merge(object: nil)),
         
     | 
| 
      
 30 
     | 
    
         
            +
                        block: true,
         
     | 
| 
      
 31 
     | 
    
         
            +
                      )
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    @name.evaluate(**args.merge(arguments: arguments))
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/code/node/code.rb
    CHANGED
    
    | 
         @@ -1,18 +1,15 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require "active_support"
         
     | 
| 
       2 
     | 
    
         
            -
            require "active_support/core_ext/object/blank"
         
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
1 
     | 
    
         
             
            class Code
         
     | 
| 
       5 
2 
     | 
    
         
             
              class Node
         
     | 
| 
       6 
     | 
    
         
            -
                class Code
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Code < Node
         
     | 
| 
       7 
4 
     | 
    
         
             
                  def initialize(statements)
         
     | 
| 
       8 
     | 
    
         
            -
                    statements = [] if statements.blank?
         
     | 
| 
      
 5 
     | 
    
         
            +
                    statements = [] if statements.to_s.blank?
         
     | 
| 
       9 
6 
     | 
    
         | 
| 
       10 
7 
     | 
    
         
             
                    @statements =
         
     | 
| 
       11 
8 
     | 
    
         
             
                      statements.map { |statement| ::Code::Node::Statement.new(statement) }
         
     | 
| 
       12 
9 
     | 
    
         
             
                  end
         
     | 
| 
       13 
10 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                  def evaluate( 
     | 
| 
       15 
     | 
    
         
            -
                    @statements.map { |statement| statement.evaluate( 
     | 
| 
      
 11 
     | 
    
         
            +
                  def evaluate(**args)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @statements.map { |statement| statement.evaluate(**args) }.last
         
     | 
| 
       16 
13 
     | 
    
         
             
                  end
         
     | 
| 
       17 
14 
     | 
    
         
             
                end
         
     | 
| 
       18 
15 
     | 
    
         
             
              end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Code
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Node
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Defined < Node
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def initialize(defined)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    @name = defined.fetch(:name)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def evaluate(**args)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    ::Code::Object::Boolean.new(args.fetch(:context).key?(name))
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  private
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def name
         
     | 
| 
      
 15 
     | 
    
         
            +
                    ::Code::Object::String.new(@name.to_s)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,16 +1,20 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            class Code
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Node
         
     | 
| 
       3 
     | 
    
         
            -
                class Dictionnary
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Dictionnary < Node
         
     | 
| 
       4 
4 
     | 
    
         
             
                  def initialize(key_values)
         
     | 
| 
       5 
     | 
    
         
            -
                     
     | 
| 
       6 
     | 
    
         
            -
                      key_values 
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
                       
     | 
| 
      
 5 
     | 
    
         
            +
                    if key_values.blank?
         
     | 
| 
      
 6 
     | 
    
         
            +
                      @key_values = []
         
     | 
| 
      
 7 
     | 
    
         
            +
                    else
         
     | 
| 
      
 8 
     | 
    
         
            +
                      @key_values =
         
     | 
| 
      
 9 
     | 
    
         
            +
                        key_values.map do |key_value|
         
     | 
| 
      
 10 
     | 
    
         
            +
                          ::Code::Node::DictionnaryKeyValue.new(key_value)
         
     | 
| 
      
 11 
     | 
    
         
            +
                        end
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
       9 
13 
     | 
    
         
             
                  end
         
     | 
| 
       10 
14 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
                  def evaluate( 
     | 
| 
      
 15 
     | 
    
         
            +
                  def evaluate(**args)
         
     | 
| 
       12 
16 
     | 
    
         
             
                    ::Code::Object::Dictionnary.new(
         
     | 
| 
       13 
     | 
    
         
            -
                      @key_values.map { |key_value| key_value.evaluate( 
     | 
| 
      
 17 
     | 
    
         
            +
                      @key_values.map { |key_value| key_value.evaluate(**args) }.to_h,
         
     | 
| 
       14 
18 
     | 
    
         
             
                    )
         
     | 
| 
       15 
19 
     | 
    
         
             
                  end
         
     | 
| 
       16 
20 
     | 
    
         
             
                end
         
     |