rus3 0.1.2 → 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/CHANGELOG.md +9 -1
- data/Gemfile.lock +1 -1
- data/README.md +14 -6
- data/exe/rus3 +26 -2
- data/lib/rus3.rb +3 -0
- data/lib/rus3/ast.rb +70 -0
- data/lib/rus3/ast/branch_node.rb +412 -0
- data/lib/rus3/ast/error.rb +8 -0
- data/lib/rus3/ast/leaf_node.rb +55 -0
- data/lib/rus3/error.rb +15 -1
- data/lib/rus3/evaluator.rb +38 -54
- data/lib/rus3/evaluator/environment.rb +25 -0
- data/lib/rus3/evaluator/scheme_evaluator.rb +79 -0
- data/lib/rus3/evaluator/translator.rb +337 -0
- data/lib/rus3/{parser/lexer.rb → lexer.rb} +22 -52
- data/lib/rus3/parser.rb +39 -23
- data/lib/rus3/parser/scheme_parser.rb +595 -306
- data/lib/rus3/procedure/char.rb +21 -17
- data/lib/rus3/procedure/control.rb +28 -24
- data/lib/rus3/procedure/list.rb +210 -207
- data/lib/rus3/procedure/predicate.rb +267 -264
- data/lib/rus3/procedure/utils.rb +20 -16
- data/lib/rus3/procedure/vector.rb +68 -65
- data/lib/rus3/procedure/write.rb +107 -103
- data/lib/rus3/repl.rb +57 -47
- data/lib/rus3/token.rb +35 -0
- data/lib/rus3/version.rb +2 -2
- metadata +11 -3
    
        data/lib/rus3/repl.rb
    CHANGED
    
    | @@ -21,13 +21,13 @@ module Rus3 | |
| 21 21 | 
             
              class Repl
         | 
| 22 22 |  | 
| 23 23 | 
             
                # Indicates the version of the Repl class.
         | 
| 24 | 
            -
                 | 
| 24 | 
            +
                REPL_VERSION = "0.2.0"
         | 
| 25 25 |  | 
| 26 26 | 
             
                class << self
         | 
| 27 27 |  | 
| 28 28 | 
             
                  # Starts REPL.
         | 
| 29 | 
            -
                  def start(verbose: false)
         | 
| 30 | 
            -
                    repl = Repl.new(verbose: verbose)
         | 
| 29 | 
            +
                  def start(parser: nil, evaluator: nil, verbose: false)
         | 
| 30 | 
            +
                    repl = Repl.new(parser: parser, evaluator: evaluator, verbose: verbose)
         | 
| 31 31 | 
             
                    repl.loop
         | 
| 32 32 | 
             
                  end
         | 
| 33 33 |  | 
| @@ -35,9 +35,9 @@ module Rus3 | |
| 35 35 |  | 
| 36 36 | 
             
                # Hods major component names of the REPL.
         | 
| 37 37 | 
             
                COMPONENTS = {
         | 
| 38 | 
            -
                  :parser | 
| 39 | 
            -
                  :evaluator => Evaluator,
         | 
| 40 | 
            -
                  :printer | 
| 38 | 
            +
                  :parser    => Parser::DEFAULT_PARSER,
         | 
| 39 | 
            +
                  :evaluator => Evaluator::DEFAULT_EVALUATOR,
         | 
| 40 | 
            +
                  :printer   => nil,
         | 
| 41 41 | 
             
                }
         | 
| 42 42 |  | 
| 43 43 | 
             
                # Prompt for input.
         | 
| @@ -49,14 +49,20 @@ module Rus3 | |
| 49 49 | 
             
                @@value_history = []        # :nodoc:
         | 
| 50 50 |  | 
| 51 51 | 
             
                attr_accessor :verbose      # :nodoc:
         | 
| 52 | 
            +
                attr_accessor :prompt       # :nodoc:
         | 
| 52 53 |  | 
| 53 | 
            -
                def initialize(verbose: false)
         | 
| 54 | 
            -
                  COMPONENTS. | 
| 54 | 
            +
                def initialize(parser: nil, evaluator: nil, verbose: false)
         | 
| 55 | 
            +
                  comps = COMPONENTS.dup
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  comps[:parser] = Parser.const_get("#{parser.capitalize}Parser") if parser
         | 
| 58 | 
            +
                  comps[:evaluator] = Evaluator.const_get("#{evaluator.capitalize}Evaluator") if evaluator
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                  comps.each { |name, klass|
         | 
| 55 61 | 
             
                    instance_variable_set("@#{name}", klass.nil? ? self : klass.new)
         | 
| 56 62 | 
             
                  }
         | 
| 57 63 |  | 
| 58 64 | 
             
                  @prompt = PROMPT
         | 
| 59 | 
            -
                  @parser.prompt = PROMPT | 
| 65 | 
            +
                  @parser.prompt = PROMPT
         | 
| 60 66 |  | 
| 61 67 | 
             
                  @verbose = verbose
         | 
| 62 68 | 
             
                  @evaluator.verbose = verbose
         | 
| @@ -73,15 +79,15 @@ module Rus3 | |
| 73 79 | 
             
                def loop
         | 
| 74 80 | 
             
                  msg = Kernel.loop {               # LOOP
         | 
| 75 81 | 
             
                    begin
         | 
| 76 | 
            -
                       | 
| 82 | 
            +
                      ast = @parser.read(STDIN)     # READ
         | 
| 77 83 | 
             
                    rescue SchemeSyntaxError => e
         | 
| 78 84 | 
             
                      puts "ERROR" + (@verbose ? "(READ)" : "")  + ": %s" % e
         | 
| 79 85 | 
             
                      next
         | 
| 80 86 | 
             
                    end
         | 
| 81 | 
            -
                    break FAREWELL_MESSAGE if  | 
| 87 | 
            +
                    break FAREWELL_MESSAGE if ast.nil?
         | 
| 82 88 |  | 
| 83 89 | 
             
                    begin
         | 
| 84 | 
            -
                      value = @evaluator.eval( | 
| 90 | 
            +
                      value = @evaluator.eval(ast)  # EVAL
         | 
| 85 91 | 
             
                    rescue SyntaxError, StandardError => e
         | 
| 86 92 | 
             
                      puts "ERROR" + (@verbose ? "(EVAL)" : "")  + ": %s" % e
         | 
| 87 93 | 
             
                      next
         | 
| @@ -96,15 +102,20 @@ module Rus3 | |
| 96 102 |  | 
| 97 103 | 
             
                # Shows the greeting message.
         | 
| 98 104 | 
             
                def greeting
         | 
| 99 | 
            -
                  puts "A simple REPL  | 
| 100 | 
            -
                  puts "- Rus3 version: #{Rus3::VERSION} (#{Rus3::RELEASE})"
         | 
| 105 | 
            +
                  puts "A simple REPL to run Rus3:"
         | 
| 101 106 | 
             
                  return unless @verbose
         | 
| 102 107 |  | 
| 103 | 
            -
                   | 
| 108 | 
            +
                  vmsg =  "(rus3 :version #{Rus3::VERSION} :release #{Rus3::RELEASE}\n"
         | 
| 109 | 
            +
                  vmsg += "  (repl :version #{REPL_VERSION}\n"
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                  comp_vmsgs = []
         | 
| 104 112 | 
             
                  COMPONENTS.keys.each { |comp_name|
         | 
| 105 | 
            -
                     | 
| 106 | 
            -
                    print_version(comp_name)
         | 
| 113 | 
            +
                    comp_vmsgs << "    (#{version_message(comp_name)})"
         | 
| 107 114 | 
             
                  }
         | 
| 115 | 
            +
                  vmsg += comp_vmsgs.join("\n")
         | 
| 116 | 
            +
                  vmsg += "))"
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                  puts vmsg
         | 
| 108 119 | 
             
                end
         | 
| 109 120 |  | 
| 110 121 | 
             
                # :stopdoc:
         | 
| @@ -117,8 +128,8 @@ module Rus3 | |
| 117 128 | 
             
                  Readline::readline(@prompt, true)
         | 
| 118 129 | 
             
                end
         | 
| 119 130 |  | 
| 120 | 
            -
                def eval( | 
| 121 | 
            -
                   | 
| 131 | 
            +
                def eval(ast)
         | 
| 132 | 
            +
                  ast
         | 
| 122 133 | 
             
                end
         | 
| 123 134 |  | 
| 124 135 | 
             
                def print(obj)
         | 
| @@ -130,12 +141,21 @@ module Rus3 | |
| 130 141 |  | 
| 131 142 | 
             
                private
         | 
| 132 143 |  | 
| 144 | 
            +
                def version_message(comp_name)
         | 
| 145 | 
            +
                  vmsg = nil
         | 
| 146 | 
            +
                  component = instance_variable_get("@#{comp_name}")
         | 
| 147 | 
            +
                  if component.nil? or component == self
         | 
| 148 | 
            +
                    vmsg = ":using :built-in :#{comp_name}"
         | 
| 149 | 
            +
                  else
         | 
| 150 | 
            +
                    vmsg = "#{component.version}"
         | 
| 151 | 
            +
                  end
         | 
| 152 | 
            +
                  vmsg
         | 
| 153 | 
            +
                end
         | 
| 154 | 
            +
             | 
| 133 155 | 
             
                def define_constants        # :nodoc:
         | 
| 134 156 | 
             
                  return if @evaluator.nil?
         | 
| 135 157 |  | 
| 136 | 
            -
                   | 
| 137 | 
            -
             | 
| 138 | 
            -
                  r.instance_eval {
         | 
| 158 | 
            +
                  @evaluator.instance_eval {
         | 
| 139 159 | 
             
                    self.class.const_set(:RUS3_VERSION, "#{VERSION}")
         | 
| 140 160 | 
             
                  }
         | 
| 141 161 | 
             
                end
         | 
| @@ -143,9 +163,7 @@ module Rus3 | |
| 143 163 | 
             
                def define_help_feature     # :nodoc:
         | 
| 144 164 | 
             
                  return if @evaluator.nil?
         | 
| 145 165 |  | 
| 146 | 
            -
                   | 
| 147 | 
            -
             | 
| 148 | 
            -
                  r.instance_eval {
         | 
| 166 | 
            +
                  @evaluator.instance_eval {
         | 
| 149 167 | 
             
                    def _help
         | 
| 150 168 | 
             
                      puts <<HELP
         | 
| 151 169 | 
             
            A simple REPL for Rus3.
         | 
| @@ -167,10 +185,8 @@ HELP | |
| 167 185 | 
             
                def define_history_feature  # :nodoc:
         | 
| 168 186 | 
             
                  return if @evaluator.nil?
         | 
| 169 187 |  | 
| 170 | 
            -
                   | 
| 171 | 
            -
             | 
| 172 | 
            -
                  r.instance_variable_set(:@value_history, @@value_history)
         | 
| 173 | 
            -
                  r.instance_eval {
         | 
| 188 | 
            +
                  @evaluator.instance_variable_set(:@value_history, @@value_history)
         | 
| 189 | 
            +
                  @evaluator.instance_eval {
         | 
| 174 190 |  | 
| 175 191 | 
             
                    def _last_value
         | 
| 176 192 | 
             
                      @value_history[-1]
         | 
| @@ -201,30 +217,24 @@ HELP | |
| 201 217 | 
             
                def define_load_feature
         | 
| 202 218 | 
             
                  return if @evaluator.nil?
         | 
| 203 219 |  | 
| 204 | 
            -
                   | 
| 205 | 
            -
             | 
| 206 | 
            -
                   | 
| 207 | 
            -
                  r.instance_eval {
         | 
| 220 | 
            +
                  @evaluator.instance_variable_set(:@scm_parser, @parser)
         | 
| 221 | 
            +
                  @evaluator.instance_variable_set(:@scm_evaluator, @evaluator)
         | 
| 222 | 
            +
                  @evaluator.instance_eval {
         | 
| 208 223 | 
             
                    def load_scm(path)
         | 
| 209 224 | 
             
                      raise Rus3::CannotFindFileError, path unless FileTest.exist?(path)
         | 
| 210 | 
            -
                       | 
| 211 | 
            -
                       | 
| 212 | 
            -
                       | 
| 213 | 
            -
             | 
| 214 | 
            -
                       | 
| 225 | 
            +
                      scheme_source = File.readlines(path, chomp: true).join(" ")
         | 
| 226 | 
            +
                      result = ast = nil
         | 
| 227 | 
            +
                      if @scm_parser.respond_to?(:parse)
         | 
| 228 | 
            +
                        ast = @scm_parser.parse(scheme_source)
         | 
| 229 | 
            +
                      end
         | 
| 230 | 
            +
                      if @scm_evaluator.respond_to?(:eval)
         | 
| 231 | 
            +
                        result = @scm_evaluator.eval(ast)
         | 
| 232 | 
            +
                      end
         | 
| 233 | 
            +
                      pp result
         | 
| 215 234 | 
             
                    end
         | 
| 216 235 | 
             
                  }
         | 
| 217 236 | 
             
                end
         | 
| 218 237 |  | 
| 219 | 
            -
                def print_version(comp_name)
         | 
| 220 | 
            -
                  component = instance_variable_get("@#{comp_name}")
         | 
| 221 | 
            -
                  if component.nil? or component == self
         | 
| 222 | 
            -
                    puts "using built-in #{comp_name.upcase}"
         | 
| 223 | 
            -
                  else
         | 
| 224 | 
            -
                    puts "#{component.version}"
         | 
| 225 | 
            -
                  end
         | 
| 226 | 
            -
                end
         | 
| 227 | 
            -
             | 
| 228 238 | 
             
                def history_push(value)
         | 
| 229 239 | 
             
                  prev_value = @@value_history[-1]
         | 
| 230 240 | 
             
                  if prev_value != value and UNDEF != value
         | 
    
        data/lib/rus3/token.rb
    ADDED
    
    | @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Rus3
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              TOKEN_TYPES = [             # :nodoc:
         | 
| 6 | 
            +
                # delimiters
         | 
| 7 | 
            +
                :lparen,                  # `(`
         | 
| 8 | 
            +
                :rparen,                  # `)`
         | 
| 9 | 
            +
                :vec_lparen,              # `#(`
         | 
| 10 | 
            +
                :bytevec_lparen,          # `#u8(`
         | 
| 11 | 
            +
                :quotation,               # `'`
         | 
| 12 | 
            +
                :backquote,               # "`" (aka quasiquote)
         | 
| 13 | 
            +
                :comma,                   # `,`
         | 
| 14 | 
            +
                :comma_at,                # `,@`
         | 
| 15 | 
            +
                :dot,                     # `.`
         | 
| 16 | 
            +
                :semicolon,               # `;`
         | 
| 17 | 
            +
                :comment_lparen,          # `#|`
         | 
| 18 | 
            +
                :comment_rparen,          # `|#`
         | 
| 19 | 
            +
                # value types
         | 
| 20 | 
            +
                :identifier,              # `foo`
         | 
| 21 | 
            +
                :boolean,                 # `#f` or `#t` (`#false` or `#true`)
         | 
| 22 | 
            +
                :number,                  # `123`, `456.789`, `1/2`, `3+4i`
         | 
| 23 | 
            +
                :character,               # `#\a`
         | 
| 24 | 
            +
                :string,                  # `"hoge"`
         | 
| 25 | 
            +
                # operators
         | 
| 26 | 
            +
                :op_proc,                 # `+`, `-`, ...
         | 
| 27 | 
            +
                # control
         | 
| 28 | 
            +
                :illegal,
         | 
| 29 | 
            +
              ]
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              Token = Struct.new(:type, :literal) {
         | 
| 32 | 
            +
                alias :to_s :literal
         | 
| 33 | 
            +
              }
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            end
         | 
    
        data/lib/rus3/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: rus3
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.2.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - mnbi
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2021- | 
| 11 | 
            +
            date: 2021-05-03 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies: []
         | 
| 13 13 | 
             
            description: Ruby with Syntax Sugar of Scheme
         | 
| 14 14 | 
             
            email:
         | 
| @@ -33,12 +33,19 @@ files: | |
| 33 33 | 
             
            - examples/iota.scm
         | 
| 34 34 | 
             
            - exe/rus3
         | 
| 35 35 | 
             
            - lib/rus3.rb
         | 
| 36 | 
            +
            - lib/rus3/ast.rb
         | 
| 37 | 
            +
            - lib/rus3/ast/branch_node.rb
         | 
| 38 | 
            +
            - lib/rus3/ast/error.rb
         | 
| 39 | 
            +
            - lib/rus3/ast/leaf_node.rb
         | 
| 36 40 | 
             
            - lib/rus3/char.rb
         | 
| 37 41 | 
             
            - lib/rus3/error.rb
         | 
| 38 42 | 
             
            - lib/rus3/evaluator.rb
         | 
| 43 | 
            +
            - lib/rus3/evaluator/environment.rb
         | 
| 44 | 
            +
            - lib/rus3/evaluator/scheme_evaluator.rb
         | 
| 45 | 
            +
            - lib/rus3/evaluator/translator.rb
         | 
| 46 | 
            +
            - lib/rus3/lexer.rb
         | 
| 39 47 | 
             
            - lib/rus3/pair.rb
         | 
| 40 48 | 
             
            - lib/rus3/parser.rb
         | 
| 41 | 
            -
            - lib/rus3/parser/lexer.rb
         | 
| 42 49 | 
             
            - lib/rus3/parser/scheme_parser.rb
         | 
| 43 50 | 
             
            - lib/rus3/port.rb
         | 
| 44 51 | 
             
            - lib/rus3/printer.rb
         | 
| @@ -50,6 +57,7 @@ files: | |
| 50 57 | 
             
            - lib/rus3/procedure/vector.rb
         | 
| 51 58 | 
             
            - lib/rus3/procedure/write.rb
         | 
| 52 59 | 
             
            - lib/rus3/repl.rb
         | 
| 60 | 
            +
            - lib/rus3/token.rb
         | 
| 53 61 | 
             
            - lib/rus3/vector.rb
         | 
| 54 62 | 
             
            - lib/rus3/version.rb
         | 
| 55 63 | 
             
            - rus3.gemspec
         |