File: abstract-syntax/core/expression/nary/switch.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_switch / 5 #154
  module: Nary#14
  class: Switch#16
inherits from
  Abstract ( Umu::AbstractSyntax::Core::Expression )
has properties
attribute: source_expr [R] #17
attribute: souce_type_sym [R] #17
attribute: leafs [R] #17
attribute: else_expr [R] #17
method: initialize / 5 #20
method: to_s #35
method: pretty_print / 1 #50
method: __pretty_print_leaf__ / 3 #100
method: __evaluate__ / 2 #109

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  class Switch < Expression::Abstract
  17      attr_reader :source_expr, :souce_type_sym, :leafs, :else_expr
  18 
  19 
  20      def initialize(loc, source_expr, souce_type_sym, leafs, else_expr)
  21          ASSERT.kind_of source_expr,     ASCE::Abstract
  22          ASSERT.kind_of souce_type_sym,  ::Symbol
  23          ASSERT.kind_of leafs,           ::Hash
  24          ASSERT.kind_of else_expr,       ASCE::Abstract
  25 
  26          super(loc)
  27 
  28          @source_expr    = source_expr
  29          @souce_type_sym = souce_type_sym
  30          @leafs          = leafs
  31          @else_expr      = else_expr
  32      end
  33 
  34 
  35      def to_s
  36          format("%%SWITCH %s : %s { %s %%ELSE -> %s}",
  37              self.source_expr.to_s,
  38 
  39              self.souce_type_sym.to_s,
  40 
  41              self.leafs.map { |(head, body)|
  42                  format "%s -> %s", head.to_s, body.to_s
  43              }.join(' | '),
  44 
  45              self.else_expr.to_s
  46          )
  47      end
  48 
  49 
  50      def pretty_print(q)
  51          q.text '%SWITCH '
  52          q.pp self.source_expr
  53          q.text ' : '
  54          q.text self.souce_type_sym.to_s
  55          q.text ' {'
  56 
  57          case self.leafs.size
  58          when 0
  59              # Nothing to do
  60          when 1
  61              q.breakable ''
  62 
  63              head, body = self.leafs.first
  64              __pretty_print_leaf__ q, head, body
  65          else
  66              q.breakable ''
  67 
  68              q.text '| '
  69              fst_head, fst_body = self.leafs.first
  70              __pretty_print_leaf__ q, fst_head, fst_body
  71 
  72              not_fst_leafs = self.leafs.reject { |hd, _| hd.eql? fst_head }
  73              not_fst_leafs.each do |(head, body)|
  74                  q.breakable ''
  75 
  76                  q.text '| '
  77                  PRT.group q do
  78                      __pretty_print_leaf__ q, head, body
  79                  end
  80              end
  81          end
  82 
  83          q.breakable ''
  84 
  85          q.text '%ELSE -> '
  86          PRT.group q do
  87              q.breakable ''
  88 
  89              q.pp self.else_expr
  90          end
  91 
  92          q.breakable ''
  93 
  94          q.text '}'
  95      end
  96 
  97 
  98  private
  99 
 100      def __pretty_print_leaf__(q, head, body)
 101          q.pp head
 102          q.text ' -> '
 103          PRT.group q do
 104              q.pp body
 105          end
 106      end
 107 
 108 
 109      def __evaluate__(env, event)
 110          ASSERT.kind_of env,     E::Entry
 111          ASSERT.kind_of event,   E::Tracer::Event
 112 
 113          new_env = env.enter event
 114 
 115          source_result = self.source_expr.evaluate new_env
 116          ASSERT.kind_of source_result, ASR::Value
 117          source_value = source_result.value
 118 
 119          source_signat = new_env.ty_lookup self.souce_type_sym, self.loc
 120          ASSERT.kind_of source_signat, ECTSC::Base
 121          unless env.ty_kind_of?(source_value, source_signat)
 122              raise X::TypeError.new(
 123                  self.loc,
 124                  env,
 125                  "Type error in case-expression, " +
 126                      "expected a %s, but %s : %s",
 127                  self.souce_type_sym,
 128                  source_value,
 129                  source_value.type_sym
 130              )
 131          end
 132 
 133          opt_leaf_expr = self.leafs[source_value.val]
 134          ASSERT.opt_kind_of opt_leaf_expr, ASCE::Abstract
 135 
 136          result = (
 137              if opt_leaf_expr
 138                  opt_leaf_expr
 139              else
 140                  self.else_expr
 141              end
 142          ).evaluate new_env
 143          ASSERT.kind_of result, ASR::Value
 144 
 145          result.value
 146      end
 147  end
 148 
 149  end # Umu::AbstractSyntax::Core::Expression::Nary
 150 
 151 
 152  module_function
 153 
 154      def make_switch(loc, source_expr, souce_type_sym, leafs, else_expr)
 155          ASSERT.kind_of loc,             LOC::Entry
 156          ASSERT.kind_of source_expr,     ASCE::Abstract
 157          ASSERT.kind_of souce_type_sym,  ::Symbol
 158          ASSERT.kind_of leafs,           ::Hash
 159          ASSERT.kind_of else_expr,       ASCE::Abstract
 160 
 161          Nary::Switch.new(
 162              loc, source_expr, souce_type_sym, leafs, else_expr
 163          ).freeze
 164      end
 165 
 166  end # Umu::AbstractSyntax::Core::Expression
 167 
 168  end # Umu::AbstractSyntax::Core
 169 
 170  end # Umu::AbstractSyntax
 171 
 172  end # Umu