File: concrete-syntax/core/pattern/container/morph/abstract.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: Umu#6
  module: ConcreteSyntax#8
  module: Core#10
  module: Pattern#12
  module: Container#14
  module: Morph#16
  class: Abstract#18
inherits from
  Abstract ( Umu::ConcreteSyntax::Core::Pattern::Container )
has properties
alias: pats array #19
attribute: opt_last_pat [R] #20
method: initialize / 3 #22
method: to_s #51
method: pretty_print / 1 #68
method: exported_vars #83
method: __bb__ #96
method: __eb__ #101
method: __desugar_value__ / 3 #106
method: __desugar_lambda__ / 3 #121
method: __desugar__ / 2 #147
method: __desugar_value_nil__ / 2 #252
method: __desugar_lambda_nil__ / 1 #259
method: __gen_pair_sym__ / 1 #268
method: __make_send_dest__ / 2 #275
method: __make_select_by_number__ / 3 #291
method: __make_select_head__ / 2 #304
method: __make_select_tail__ / 2 #312
method: __opt_type_sym_of_morph__ #320
alias: __opt_type_sym_of_nil__ __opt_type_sym_of_morph__ #324
alias: __opt_type_sym_of_cons__ __opt_type_sym_of_morph__ #325

Code

   1  # coding: utf-8
   2  # frozen_string_literal: true
   3 
   4 
   5 
   6  module Umu
   7 
   8  module ConcreteSyntax
   9 
  10  module Core
  11 
  12  module Pattern
  13 
  14  module Container
  15 
  16  module Morph
  17 
  18  class Abstract < Container::Abstract
  19      alias       pats array
  20      attr_reader :opt_last_pat
  21 
  22      def initialize(loc, pats, opt_last_pat)
  23          ASSERT.kind_of      pats,           ::Array
  24          ASSERT.opt_kind_of  opt_last_pat,   ElementOfContainer::Variable
  25          ASSERT.assert (if pats.empty? then opt_last_pat.nil? else true end)
  26 
  27          init_hash = if self.opt_last_pat
  28                          {self.opt_last_pat.var_sym => true}
  29                      else
  30                          {}
  31                      end
  32 
  33          pats.reject(&:wildcard?).inject(init_hash) do |hash, vpat|
  34              ASSERT.kind_of vpat,    ElementOfContainer::Variable
  35              ASSERT.kind_of hash,    ::Hash
  36 
  37              hash.merge(vpat.var_sym => true) {
  38                  raise X::SyntaxError.new(
  39                      vpat.loc,
  40                      "Duplicated pattern variable: '%s'", vpat.to_s
  41                  )
  42              }
  43          end
  44 
  45          super(loc, pats)
  46 
  47          @opt_last_pat = opt_last_pat
  48      end
  49 
  50 
  51      def to_s
  52          [
  53              __bb__,
  54 
  55              self.map(&:to_s).join(', '),
  56 
  57              if self.opt_last_pat
  58                  '|' + self.opt_last_pat.to_s
  59              else
  60                  ''
  61              end,
  62 
  63              __eb__
  64          ].join
  65      end
  66 
  67 
  68      def pretty_print(q)
  69          if self.opt_last_pat
  70              last_pat = self.opt_last_pat
  71 
  72              PRT.group_for_enum q, self, bb:__bb__, join:', '
  73 
  74              PRT.group q, bb:'|', eb:__eb__ do
  75                  q.pp last_pat
  76              end
  77          else
  78              PRT.group_for_enum q, self, bb:__bb__, eb:__eb__, join:', '
  79          end
  80      end
  81 
  82 
  83      def exported_vars
  84          (self.pats + [self.opt_last_pat]).reject(&:wildcard?).inject([]) {
  85              |array, vpat|
  86              ASSERT.kind_of array,   ::Array
  87              ASSERT.kind_of vpat,    ElementOfContainer::Variable
  88 
  89              array + vpat.exported_vars
  90          }.freeze
  91      end
  92 
  93 
  94  private
  95 
  96      def __bb__
  97          raise X::InternalSubclassResponsibility
  98      end
  99 
 100 
 101      def __eb__
 102          raise X::InternalSubclassResponsibility
 103      end
 104 
 105 
 106      def __desugar_value__(expr, env, _event)
 107          ASSERT.kind_of expr, ASCE::Abstract
 108 
 109          decl = if self.pats.empty?
 110                  __desugar_value_nil__(self.loc, expr)
 111              else
 112                  ASCD.make_seq_of_declaration(
 113                      self.loc, __desugar__(expr, env)
 114                  )
 115              end
 116 
 117          ASSERT.kind_of decl, ASCD::Abstract
 118      end
 119 
 120 
 121      def __desugar_lambda__(seq_num, env, _event)
 122          ASSERT.kind_of seq_num, ::Integer
 123 
 124          var_sym = __gen_sym__ seq_num
 125 
 126          opt_result = (
 127              if self.pats.empty?
 128                  __desugar_lambda_nil__(self.loc)
 129              else
 130                  CSCP.make_result(
 131                      ASCE.make_identifier(self.loc, var_sym),
 132 
 133                      __desugar__(
 134                          ASCE.make_identifier(self.loc, var_sym),
 135                          env
 136                      ),
 137 
 138                      __opt_type_sym_of_cons__
 139                  )
 140              end
 141          )
 142 
 143          ASSERT.opt_kind_of opt_result, CSCP::Result
 144      end
 145 
 146 
 147      def __desugar__(expr, _env)
 148          ASSERT.kind_of expr, ASCE::Abstract
 149 
 150          head_vpat, *tail_pats = self.pats
 151          ASSERT.kind_of head_vpat, ElementOfContainer::Variable
 152 
 153          init_loc = head_vpat.loc
 154 
 155          init_seq_num = 1
 156 
 157          init_pair_sym = __gen_pair_sym__ init_seq_num
 158 
 159          init_decls = [
 160              ASCD.make_value(
 161                  init_loc,
 162                  init_pair_sym,
 163                  __make_send_dest__(init_loc, expr)
 164              ),
 165 
 166              ASCD.make_value(
 167                  init_loc,
 168                  head_vpat.var_sym,
 169                  __make_select_head__(init_loc, init_pair_sym),
 170                  head_vpat.opt_type_sym
 171              )
 172          ]
 173 
 174          _final_seq_num, final_pair_sym, final_decls = tail_pats.inject(
 175               [init_seq_num, init_pair_sym, init_decls]
 176          ) {
 177              |(seq_num,      pair_sym,      decls     ), vpat|
 178              ASSERT.kind_of seq_num,     ::Integer
 179              ASSERT.kind_of pair_sym,    ::Symbol
 180              ASSERT.kind_of decls,       ::Array
 181              ASSERT.kind_of vpat,        ElementOfContainer::Variable
 182 
 183              loc             = vpat.loc
 184              next_seq_num    = seq_num + 1
 185              next_pair_sym   = __gen_pair_sym__ next_seq_num
 186              tail_list_expr  = __make_select_tail__ loc, pair_sym
 187 
 188              next_decls = (
 189                      decls
 190                  ) + (
 191                      if vpat.wildcard?
 192                          [
 193                              ASCD.make_value(
 194                                  loc,
 195                                  next_pair_sym,
 196                                  ASCE.make_product(
 197                                      loc,
 198                                      __make_send_dest__(loc, tail_list_expr),
 199                                      ASCE.make_number_selector(loc, 2)
 200                                  ),
 201                                  vpat.opt_type_sym
 202                              )
 203                          ]
 204                      else
 205                          [
 206                              ASCD.make_value(
 207                                  loc,
 208                                  next_pair_sym,
 209                                  __make_send_dest__(loc, tail_list_expr)
 210                              ),
 211 
 212                              ASCD.make_value(
 213                                  loc,
 214                                  vpat.var_sym,
 215                                  __make_select_head__(loc, next_pair_sym),
 216                                  vpat.opt_type_sym
 217                              )
 218 
 219                          ]
 220                      end
 221                  )
 222 
 223              [next_seq_num, next_pair_sym, next_decls]
 224          }
 225 
 226          (
 227              final_decls
 228          ) + (
 229              if self.opt_last_pat
 230                  last_pat = self.opt_last_pat
 231 
 232                  [
 233                      ASCD.make_value(
 234                          last_pat.loc,
 235                          last_pat.var_sym,
 236                          __make_select_tail__(last_pat.loc, final_pair_sym),
 237                          last_pat.opt_type_sym
 238                      )
 239                  ]
 240              else
 241                  [
 242                      __desugar_value_nil__(
 243                          loc,
 244                          __make_select_tail__(loc, final_pair_sym)
 245                      )
 246                  ]
 247              end
 248          )
 249      end
 250 
 251 
 252      def __desugar_value_nil__(loc, expr)
 253          ASCD.make_value(
 254              loc, WILDCARD, expr, __opt_type_sym_of_nil__
 255          )
 256      end
 257 
 258 
 259      def __desugar_lambda_nil__(loc)
 260          CSCP.make_result(
 261              ASCE.make_identifier(loc, WILDCARD),
 262              [],
 263              __opt_type_sym_of_nil__
 264          )
 265      end
 266 
 267 
 268      def __gen_pair_sym__(num)
 269          ASSERT.kind_of num, ::Integer
 270 
 271          format("%%p%d", num).to_sym
 272      end
 273 
 274 
 275      def __make_send_dest__(loc, expr)
 276          ASSERT.kind_of loc,  LOC::Entry
 277          ASSERT.kind_of expr, ASCE::Abstract
 278 
 279          opt_type_sym = if self.opt_last_pat
 280                              self.opt_last_pat.opt_type_sym
 281                          else
 282                              __opt_type_sym_of_morph__
 283                          end
 284 
 285          ASCE.make_send(
 286              loc, expr, ASCE.make_message(loc, :dest!), [], opt_type_sym
 287          )
 288      end
 289 
 290 
 291      def __make_select_by_number__(loc, var_sym, sel_num)
 292          ASSERT.kind_of loc,     LOC::Entry
 293          ASSERT.kind_of var_sym, ::Symbol
 294          ASSERT.kind_of sel_num, ::Integer
 295 
 296          ASCE.make_product(
 297              loc,
 298              ASCE.make_identifier(loc, var_sym),
 299              ASCE.make_number_selector(loc, sel_num)
 300          )
 301      end
 302 
 303 
 304      def __make_select_head__(loc, var_sym)
 305          ASSERT.kind_of loc,     LOC::Entry
 306          ASSERT.kind_of var_sym, ::Symbol
 307 
 308          __make_select_by_number__ loc, var_sym, 1
 309      end
 310 
 311 
 312      def __make_select_tail__(loc, var_sym)
 313          ASSERT.kind_of loc,     LOC::Entry
 314          ASSERT.kind_of var_sym, ::Symbol
 315 
 316          __make_select_by_number__ loc, var_sym, 2
 317      end
 318 
 319 
 320      def __opt_type_sym_of_morph__
 321          raise X::InternalSubclassResponsibility
 322      end
 323 
 324      alias __opt_type_sym_of_nil__   __opt_type_sym_of_morph__
 325      alias __opt_type_sym_of_cons__  __opt_type_sym_of_morph__
 326  end
 327 
 328  end # Umu::ConcreteSyntax::Core::Pattern::Container::Morph
 329 
 330  end # Umu::ConcreteSyntax::Core::Pattern::Container
 331 
 332  end # Umu::ConcreteSyntax::Core::Pattern
 333 
 334  end # Umu::ConcreteSyntax::Core
 335 
 336  end # Umu::ConcreteSyntax
 337 
 338  end # Umu