File: abstract-syntax/core/expression/binary/product.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: Umu#6
  module: AbstractSyntax#8
  module: Core#10
  module: Expression#12
has properties
function: make_number_selector / 2 #299
function: make_label_selector / 2 #307
function: make_modifier / 2 #315
function: make_product / 5 #323
  module: Binary#14
  module: Product#16
  module: Operator#18
  module: Abstraction#20
  class: Abstract#22
inherits from
  Model ( Umu::Abstraction )
has properties
method: apply / 3 #23
  class: Selector#30
inherits from
  Abstract ( Umu::AbstractSyntax::Core::Expression::Binary::Product::Operator::Abstraction )
has properties
attribute: sel [R] #31
method: initialize / 2 #34
  class: ByNumber#47
inherits from
  Selector ( Umu::AbstractSyntax::Core::Expression::Binary::Product::Operator::Abstraction )
has properties
alias: sel_num sel #48
method: initialize / 2 #51
method: to_s #58
method: pretty_print / 1 #63
method: apply / 3 #68
  class: ByLabel#89
inherits from
  Selector ( Umu::AbstractSyntax::Core::Expression::Binary::Product::Operator::Abstraction )
has properties
alias: sel_sym sel #90
method: initialize / 2 #92
method: to_s #99
method: pretty_print / 1 #104
method: apply / 3 #109
  class: Modifier#130
inherits from
  Selector ( Umu::AbstractSyntax::Core::Expression::Binary::Product::Operator::Abstraction )
has properties
alias: expr_by_label sel #131
method: initialize / 2 #133
method: to_s #140
method: pretty_print / 1 #149
method: apply / 3 #160
  class: Entry#197
inherits from
  Abstract ( Umu::AbstractSyntax::Core::Expression::Binary )
has properties
alias: rhs_head_operator rhs #198
attribute: rhs_tail_operators [R] #199
attribute: opt_operand_type_sym [R] #200
method: initialize / 5 #203
method: rhs_operators #221
method: to_s #226
method: pretty_print / 1 #241
method: __evaluate__ / 2 #255

Code

   1  # coding: utf-8
   2  # frozen_string_literal: true
   3 
   4 
   5 
   6  module Umu
   7 
   8  module AbstractSyntax
   9 
  10  module Core
  11 
  12  module Expression
  13 
  14  module Binary
  15 
  16  module Product
  17 
  18  module Operator
  19 
  20  module Abstraction
  21 
  22  class Abstract < Umu::Abstraction::Model
  23      def apply(_value, _env, _event)
  24          raise X::InternalSubclassResponsibility
  25      end
  26  end
  27 
  28 
  29 
  30  class Selector < Abstract
  31      attr_reader :sel
  32 
  33 
  34      def initialize(loc, sel)
  35          ASSERT.kind_of sel, ::Object        # Polymopic
  36 
  37          super(loc)
  38 
  39          @sel = sel
  40      end
  41  end
  42 
  43  end # Umu::AbstractSyntax::Core::Expression::Binary::Product::Operator::Abstraction
  44 
  45 
  46 
  47  class ByNumber < Abstraction::Selector
  48      alias sel_num sel
  49 
  50 
  51      def initialize(loc, sel_num)
  52          ASSERT.kind_of sel_num, ::Integer
  53 
  54          super
  55      end
  56 
  57 
  58      def to_s
  59          '$' + self.sel_num.to_s
  60      end
  61 
  62 
  63      def pretty_print(q)
  64          q.text format("$%d", self.sel_num)
  65      end
  66 
  67 
  68      def apply(value, env, _event)
  69          ASSERT.kind_of value,   VC::Top
  70          ASSERT.kind_of env,     E::Entry
  71 
  72          unless value.kind_of? VCP::Abstract
  73              raise X::TypeError.new(
  74                  self.loc,
  75                  env,
  76                  "Selection operator '$' require a Product, but %s : %s",
  77                      value.to_s,
  78                      value.type_sym.to_s
  79              )
  80          end
  81 
  82          result = value.select_by_number self.sel_num, self.loc, env
  83          ASSERT.kind_of result, VC::Top
  84      end
  85  end
  86 
  87 
  88 
  89  class ByLabel < Abstraction::Selector
  90      alias sel_sym sel
  91 
  92      def initialize(loc, sel_sym)
  93          ASSERT.kind_of sel_sym, ::Symbol
  94 
  95          super
  96      end
  97 
  98 
  99      def to_s
 100          '$' + self.sel_sym.to_s
 101      end
 102 
 103 
 104      def pretty_print(q)
 105          q.text format("$%s", self.sel_sym.to_s)
 106      end
 107 
 108 
 109      def apply(value, env, _event)
 110          ASSERT.kind_of value,   VC::Top
 111          ASSERT.kind_of env,         E::Entry
 112 
 113          unless value.kind_of? VCP::Named
 114              raise X::TypeError.new(
 115                  self.loc,
 116                  env,
 117                  "Selection operator '$' require a Named, but %s : %s",
 118                      value.to_s,
 119                      value.type_sym.to_s
 120              )
 121          end
 122 
 123          result = value.select_by_label self.sel_sym, self.loc, env
 124          ASSERT.kind_of result, VC::Top
 125      end
 126  end
 127 
 128 
 129 
 130  class Modifier < Abstraction::Selector
 131      alias expr_by_label sel
 132 
 133      def initialize(loc, expr_by_label)
 134          ASSERT.kind_of expr_by_label, ::Hash
 135 
 136          super
 137      end
 138 
 139 
 140      def to_s
 141          format("$(%s)",
 142              self.expr_by_label.map { |label, expr|
 143                  format "%s %s", label.to_s, expr.to_s
 144              }.join(', ')
 145          )
 146      end
 147 
 148 
 149      def pretty_print(q)
 150          PRT.group_for_enum(
 151               q, self.expr_by_label, bb:'$(', eb:')', join:' '
 152          ) do |label, expr|
 153 
 154              q.text label.to_s
 155              q.pp expr
 156          end
 157      end
 158 
 159 
 160      def apply(value, env, event)
 161          ASSERT.kind_of value, VC::Top
 162 
 163          unless value.kind_of? VCP::Named
 164              raise X::TypeError.new(
 165                  self.loc,
 166                  env,
 167                  "Modifier operator '$(..)' require a Named, but %s : %s",
 168                      value.to_s,
 169                      value.type_sym.to_s
 170              )
 171          end
 172 
 173          new_env = env.enter event
 174          value_by_label = self.expr_by_label.inject({}) {
 175              |hash, (label, expr)|
 176              ASSERT.kind_of hash,    ::Hash
 177              ASSERT.kind_of label,   ASCEU::Container::Named::Label
 178              ASSERT.kind_of expr,    ASCE::Abstract
 179 
 180              result = expr.evaluate new_env
 181              ASSERT.kind_of result, ASR::Value
 182 
 183              hash.merge(label.sym => result.value) { |lab, _, _|
 184                  ASSERT.abort "No case - label: $s", lab.to_s
 185              }
 186          }
 187 
 188          result = value.modify value_by_label, self.loc, env
 189          ASSERT.kind_of result, VC::Top
 190      end
 191  end
 192 
 193  end # Umu::AbstractSyntax::Core::Expression::Binary::Product::Operator
 194 
 195 
 196 
 197  class Entry < Binary::Abstract
 198      alias       rhs_head_operator rhs
 199      attr_reader :rhs_tail_operators
 200      attr_reader :opt_operand_type_sym
 201 
 202 
 203      def initialize(
 204          loc, lhs_expr,
 205          rhs_head_operator, rhs_tail_operators,
 206          opt_operand_type_sym
 207      )
 208          ASSERT.kind_of      lhs_expr,               ASCE::Abstract
 209          ASSERT.kind_of      rhs_head_operator,
 210                          Binary::Product::Operator::Abstraction::Abstract
 211          ASSERT.kind_of      rhs_tail_operators,     ::Array
 212          ASSERT.opt_kind_of  opt_operand_type_sym,   ::Symbol
 213 
 214          super(loc, lhs_expr, rhs_head_operator)
 215 
 216          @rhs_tail_operators     = rhs_tail_operators
 217          @opt_operand_type_sym   = opt_operand_type_sym
 218      end
 219 
 220 
 221      def rhs_operators
 222          [self.rhs_head_operator] + self.rhs_tail_operators
 223      end
 224 
 225 
 226      def to_s
 227          format("(%s%s)%s",
 228              self.lhs_expr.to_s,
 229 
 230              if self.opt_operand_type_sym
 231                  format " : %s", self.opt_operand_type_sym.to_s
 232              else
 233                  ''
 234              end,
 235 
 236              self.rhs_operators.map(&:to_s).join
 237          )
 238      end
 239 
 240 
 241      def pretty_print(q)
 242          PRT.group q, bb:'(', eb:')' do
 243              q.pp lhs_expr
 244              if self.opt_operand_type_sym
 245                  q.text format(" : %s", self.opt_operand_type_sym.to_s)
 246              end
 247          end
 248 
 249          PRT.group_for_enum q, self.rhs_operators
 250      end
 251 
 252 
 253  private
 254 
 255      def __evaluate__(env, event)
 256          ASSERT.kind_of env,     E::Entry
 257          ASSERT.kind_of event,   E::Tracer::Event
 258 
 259          new_env = env.enter event
 260 
 261          lhs_result = self.lhs_expr.evaluate new_env
 262          ASSERT.kind_of lhs_result, ASR::Value
 263          init_operand = lhs_result.value
 264 
 265          if self.opt_operand_type_sym
 266              operand_type_sym = opt_operand_type_sym
 267 
 268              operand_signat = new_env.ty_lookup operand_type_sym, self.loc
 269              ASSERT.kind_of operand_signat, ECTSC::Base
 270              unless env.ty_kind_of?(init_operand, operand_signat)
 271                  raise X::TypeError.new(
 272                      self.loc,
 273                      env,
 274                      "Expected a %s, but %s : %s",
 275                      operand_type_sym,
 276                      init_operand,
 277                      init_operand.type_sym
 278                  )
 279              end
 280          end
 281 
 282          final_operand = self.rhs_operators.inject(init_operand) {
 283              |operand, operator|
 284              ASSERT.kind_of operand,     VC::Top
 285              ASSERT.kind_of operator,    Operator::Abstraction::Abstract
 286 
 287              operator.apply operand, new_env, event
 288          }
 289          ASSERT.kind_of final_operand, VC::Top
 290      end
 291  end
 292 
 293  end # Umu::AbstractSyntax::Core::Expression::Binary::Product
 294 
 295  end # Umu::AbstractSyntax::Core::Expression::Binary
 296 
 297 
 298  module_function
 299      def make_number_selector(loc, sel_num)
 300          ASSERT.kind_of loc,     LOC::Entry
 301          ASSERT.kind_of sel_num, ::Integer
 302 
 303          Binary::Product::Operator::ByNumber.new(loc, sel_num).freeze
 304      end
 305 
 306 
 307      def make_label_selector(loc, sel_sym)
 308          ASSERT.kind_of loc,     LOC::Entry
 309          ASSERT.kind_of sel_sym, ::Symbol
 310 
 311          Binary::Product::Operator::ByLabel.new(loc, sel_sym).freeze
 312      end
 313 
 314 
 315      def make_modifier(loc, expr_by_label)
 316          ASSERT.kind_of loc,             LOC::Entry
 317          ASSERT.kind_of expr_by_label,   ::Hash
 318 
 319          Binary::Product::Operator::Modifier.new(loc, expr_by_label).freeze
 320      end
 321 
 322 
 323      def make_product(
 324          loc, lhs_expr,
 325          rhs_head_operator, rhs_tail_operators = [],
 326          opt_operand_type_sym = nil
 327      )
 328          ASSERT.kind_of      loc,                    LOC::Entry
 329          ASSERT.kind_of      lhs_expr,               ASCE::Abstract
 330          ASSERT.kind_of      rhs_head_operator,
 331                          Binary::Product::Operator::Abstraction::Abstract
 332          ASSERT.kind_of      rhs_tail_operators,     ::Array
 333          ASSERT.opt_kind_of  opt_operand_type_sym,   ::Symbol
 334 
 335          Binary::Product::Entry.new(
 336              loc, lhs_expr, rhs_head_operator, rhs_tail_operators.freeze,
 337              opt_operand_type_sym
 338          ).freeze
 339      end
 340 
 341  end # Umu::AbstractSyntax::Core::Expression
 342 
 343  end # Umu::AbstractSyntax::Core
 344 
 345  end # Umu::AbstractSyntax
 346 
 347  end # Umu