File: abstract-syntax/core/expression/nary/if.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_rule / 3 #176
function: make_if / 3 #185
  module: Nary#14
  module: If#16
  class: Rule#18
inherits from
  Model ( Umu::Abstraction )
has properties
attribute: head_expr [R] #19
attribute: body_expr [R] #19
method: initialize / 3 #22
method: to_s #33
method: pretty_print / 1 #38
  class: Entry#53
inherits from
  Abstract ( Umu::AbstractSyntax::Core::Expression )
has properties
attribute: rules [R] #54
attribute: else_expr [R] #54
method: initialize / 3 #57
method: to_s #68
method: pretty_print / 1 #93
method: __evaluate__ / 2 #133

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 Nary
  15 
  16  module If
  17 
  18  class Rule < Abstraction::Model
  19      attr_reader :head_expr, :body_expr
  20 
  21 
  22      def initialize(loc, head_expr, body_expr)
  23          ASSERT.kind_of head_expr,   ASCE::Abstract
  24          ASSERT.kind_of body_expr,   ASCE::Abstract
  25 
  26          super(loc)
  27 
  28          @head_expr  = head_expr
  29          @body_expr  = body_expr
  30      end
  31 
  32 
  33      def to_s
  34          format "%s %%THEN %s", self.head_expr, self.body_expr
  35      end
  36 
  37 
  38      def pretty_print(q)
  39          q.pp self.head_expr
  40 
  41          q.breakable ' '
  42 
  43          q.text '%THEN'
  44 
  45          q.breakable ' '
  46 
  47          q.pp self.body_expr
  48      end
  49  end
  50 
  51 
  52 
  53  class Entry < Expression::Abstract
  54      attr_reader :rules, :else_expr
  55 
  56 
  57      def initialize(loc, rules, else_expr)
  58          ASSERT.kind_of rules,       ::Array
  59          ASSERT.kind_of else_expr,   ASCE::Abstract
  60 
  61          super(loc)
  62 
  63          @rules      = rules
  64          @else_expr  = else_expr
  65      end
  66 
  67 
  68      def to_s
  69          rules_string = case self.rules.size
  70                          when 0
  71                              ''
  72                          when 1
  73                              self.rules[0].to_s + ' '
  74                          else
  75                              head_rule, *tail_rules = self.rules
  76 
  77                              format("%s %s ",
  78                                  head_rule.to_s,
  79 
  80                                  tail_rules.map { |rule|
  81                                      '%ELSIF ' + rule.to_s
  82                                  }.join(' ')
  83                              )
  84                          end
  85 
  86          format("(%%IF %s%%ELSE %s)",
  87              rules_string,
  88              self.else_expr.to_s
  89          )
  90      end
  91 
  92 
  93      def pretty_print(q)
  94          q.text '('
  95          PRT.group q do
  96              q.breakable ''
  97 
  98              case self.rules.size
  99              when 0
 100                  q.text '%IF'
 101              when 1
 102                  PRT.group q, bb:'%IF ' do
 103                      q.pp self.rules[0]
 104                  end
 105              else
 106                  hd_rule, *tl_rules = self.rules
 107 
 108                  PRT.group q, bb:'%IF ' do
 109                      q.pp hd_rule
 110                  end
 111 
 112                  tl_rules.each do |rule|
 113                      q.breakable
 114 
 115                      PRT.group q, bb:'%ELSIF ' do
 116                          q.pp rule
 117                      end
 118                  end
 119              end
 120 
 121              q.breakable
 122 
 123              PRT.group q, bb:'%ELSE ' do
 124                  q.pp self.else_expr
 125              end
 126          end
 127          q.text ')'
 128      end
 129 
 130 
 131  private
 132 
 133      def __evaluate__(env, event)
 134          ASSERT.kind_of env,     E::Entry
 135          ASSERT.kind_of event,   E::Tracer::Event
 136 
 137          new_env = env.enter event
 138 
 139          result = self.rules.inject(self.else_expr) { |expr, rule|
 140              ASSERT.kind_of expr,    ASCE::Abstract
 141              ASSERT.kind_of rule,    Rule
 142 
 143              head_result = rule.head_expr.evaluate new_env
 144              ASSERT.kind_of head_result, ASR::Value
 145 
 146              head_value = head_result.value
 147              unless head_value.kind_of? VCA::Bool
 148                  raise X::TypeError.new(
 149                      rule.loc,
 150                      env,
 151                      "Expected a Bool, but %s : %s",
 152                          head_value.to_s,
 153                          head_value.type_sym.to_s
 154                  )
 155              end
 156 
 157              if head_value.true?
 158                  break rule.body_expr
 159              end
 160 
 161              expr
 162          }.evaluate new_env
 163          ASSERT.kind_of result, ASR::Value
 164 
 165          result.value
 166      end
 167  end
 168 
 169  end # Umu::AbstractSyntax::Core::Expression::Nary::If
 170 
 171  end # Umu::AbstractSyntax::Core::Expression::Nary
 172 
 173 
 174  module_function
 175 
 176      def make_rule(loc, head_expr, body_expr)
 177          ASSERT.kind_of loc,         LOC::Entry
 178          ASSERT.kind_of head_expr,   ASCE::Abstract
 179          ASSERT.kind_of body_expr,   ASCE::Abstract
 180 
 181          Nary::If::Rule.new(loc, head_expr, body_expr).freeze
 182      end
 183 
 184 
 185      def make_if(loc, rules, else_expr)
 186          ASSERT.kind_of loc,         LOC::Entry
 187          ASSERT.kind_of rules,       ::Array
 188          ASSERT.kind_of else_expr,   ASCE::Abstract
 189 
 190          Nary::If::Entry.new(loc, rules, else_expr).freeze
 191      end
 192 
 193  end # Umu::AbstractSyntax::Core::Expression
 194 
 195  end # Umu::AbstractSyntax::Core
 196 
 197  end # Umu::AbstractSyntax
 198 
 199  end # Umu