File: concrete-syntax/core/expression/nary/lambda.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: Umu#6
  module: ConcreteSyntax#8
  module: Core#10
  module: Expression#12
has properties
function: make_lambda / 4 #271
function: make_named_lambda / 5 #282
  module: Nary#14
  module: Lambda#16
  class: Abstract#18
inherits from
  Abstract ( Umu::ConcreteSyntax::Core::Expression )
has properties
attribute: pats [R] #19
attribute: expr [R] #19
attribute: decls [R] #19
method: initialize / 4 #22
method: to_s #35
method: __name_sym__ #42
method: __desugar__ / 2 #47
  class: Named#158
inherits from
  Abstract ( Umu::ConcreteSyntax::Core::Expression::Nary::Lambda )
has properties
attribute: sym [R] #159
method: initialize / 5 #162
method: to_s #174
method: pretty_print / 1 #189
method: __name_sym__ #215
  class: Anonymous#222
inherits from
  Abstract ( Umu::ConcreteSyntax::Core::Expression::Nary::Lambda )
has properties
method: to_s #224
method: pretty_print / 1 #237
method: __name_sym__ #259

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 Expression
  13 
  14  module Nary
  15 
  16  module Lambda
  17 
  18  class Abstract < Expression::Abstract
  19      attr_reader :pats, :expr, :decls
  20 
  21 
  22      def initialize(loc, pats, expr, decls)
  23          ASSERT.kind_of pats,    ::Array
  24          ASSERT.kind_of expr,    CSCE::Abstract
  25          ASSERT.kind_of decls,   CSCD::SeqOfDeclaration
  26 
  27          super(loc)
  28 
  29          @pats   = pats
  30          @expr   = expr
  31          @decls  = decls
  32      end
  33 
  34 
  35      def to_s
  36          format "%s -> %s", self.pats.map(&:to_s).join(' '), self.expr.to_s
  37      end
  38 
  39 
  40  private
  41 
  42      def __name_sym__
  43          raise X::InternalSubclassResponsibility
  44      end
  45 
  46 
  47      def __desugar__(env, event)
  48          new_env = env.enter event
  49 
  50          lamb_params, lamb_decls = self.pats.each_with_index.inject(
  51               [[],       []]
  52          ) {
  53              |(params,   decls),         (pat, index)|
  54              ASSERT.kind_of params,  ::Array
  55              ASSERT.kind_of decls,   ::Array
  56              ASSERT.kind_of pat,     CSCP::Abstract
  57              ASSERT.kind_of index,   ::Integer
  58 
  59              seq_num = index + 1
  60 
  61              opt_result = pat.desugar_lambda seq_num, new_env
  62              ASSERT.opt_kind_of opt_result, CSCP::Result
  63              if opt_result
  64                  result = opt_result
  65 
  66                  param = ASCE.make_parameter(
  67                              result.ident.loc,
  68                              result.ident,
  69                              result.opt_type_sym
  70                      )
  71 
  72 
  73                  [
  74                      params + [param],
  75                      decls  + result.decls
  76                  ]
  77              else
  78                  ident_sym = format("%%x_%d", seq_num).to_sym
  79 
  80                  param = ASCE.make_parameter(
  81                          pat.loc,
  82                          ASCE.make_identifier(loc, ident_sym)
  83                      )
  84 
  85                  decl = ASCD.make_value(
  86                          pat.loc,
  87 
  88                          WILDCARD,
  89 
  90                          ASCE.make_if(
  91                              pat.loc,
  92 
  93                              [
  94                                  ASCE.make_rule(
  95                                      pat.loc,
  96 
  97                                      ASCE.make_send(
  98                                          pat.loc,
  99 
 100                                          ASCE.make_identifier(
 101                                              pat.loc,
 102                                              ident_sym
 103                                          ),
 104 
 105                                          ASCE.make_message(
 106                                              pat.loc,
 107                                              :'empty?'
 108                                          )
 109                                      ),
 110 
 111                                      ASCE.make_unit(pat.loc)
 112                                  )
 113                              ],
 114 
 115                              ASCE.make_raise(
 116                                  pat.loc,
 117 
 118                                  X::EmptyError,
 119 
 120                                  ASCE.make_string(
 121                                      pat.loc,
 122                                      "Empty morph cannot be destructible"
 123                                  )
 124                              )
 125                          )
 126                      )
 127 
 128                  [
 129                      params + [param],
 130                      decls  + [decl]
 131                  ]
 132              end
 133          }
 134 
 135          local_decls = lamb_decls + self.decls.desugar(new_env).to_a
 136          body_expr   = self.expr.desugar new_env
 137          lamb_expr   = if local_decls.empty?
 138                              body_expr
 139                          else
 140                              ASCE.make_let(
 141                                  self.loc,
 142 
 143                                  ASCD.make_seq_of_declaration(
 144                                      self.loc,
 145                                      local_decls
 146                                  ),
 147 
 148                                  body_expr
 149                              )
 150                          end
 151 
 152          ASCE.make_lambda self.loc, lamb_params, lamb_expr, __name_sym__
 153      end
 154  end
 155 
 156 
 157 
 158  class Named < Abstract
 159      attr_reader :sym
 160 
 161 
 162      def initialize(loc, pats, expr, decls, sym)
 163          ASSERT.kind_of pats,    ::Array
 164          ASSERT.kind_of expr,    CSCE::Abstract
 165          ASSERT.kind_of decls,   CSCD::SeqOfDeclaration
 166          ASSERT.kind_of sym,     ::Symbol
 167 
 168          super(loc, pats, expr, decls)
 169 
 170          @sym = sym
 171      end
 172 
 173 
 174      def to_s
 175          format("%s = %s%s",
 176                  self.sym.to_s,
 177 
 178                  super,
 179 
 180                  if self.decls.empty?
 181                      ''
 182                  else
 183                      format " %%WHERE {%s}", self.decls.to_s
 184                  end
 185          )
 186      end
 187 
 188 
 189      def pretty_print(q)
 190          PRT.group_for_enum(
 191              q,
 192              self.pats,
 193              bb: format("%s = ", self.sym.to_s),
 194              join: ' '
 195          )
 196 
 197          q.breakable
 198 
 199          PRT.group q, bb:'-> ' do
 200              q.pp self.expr
 201          end
 202 
 203          unless self.decls.empty?
 204              q.breakable
 205 
 206              PRT.group_for_enum(
 207                  q, self.decls, bb:'%WHERE {', eb:'}', sep:' '
 208              )
 209          end
 210      end
 211 
 212 
 213  private
 214 
 215      def __name_sym__
 216          self.sym
 217      end
 218  end
 219 
 220 
 221 
 222  class Anonymous < Abstract
 223 
 224      def to_s
 225          format("{%s%s}",
 226                  super,
 227 
 228                  if self.decls.empty?
 229                      ''
 230                  else
 231                      format " %%WHERE %s", self.decls.to_s
 232                  end
 233          )
 234      end
 235 
 236 
 237      def pretty_print(q)
 238          PRT.group_for_enum q, self.pats, bb:'{', sep:' '
 239 
 240          q.breakable
 241 
 242          PRT.group q, bb:'-> ' do
 243              q.pp self.expr
 244          end
 245 
 246          unless self.decls.empty?
 247              q.breakable
 248 
 249              PRT.group_for_enum q, self.decls, bb:'%WHERE', sep:' '
 250          end
 251 
 252          q.breakable
 253 
 254          q.text '}'
 255      end
 256 
 257  private
 258 
 259      def __name_sym__
 260          nil
 261      end
 262  end
 263 
 264  end # Umu::ConcreteSyntax::Core::Expression::Nary::Lambda
 265 
 266  end # Umu::ConcreteSyntax::Core::Expression::Nary
 267 
 268 
 269  module_function
 270 
 271      def make_lambda(loc, pats, expr, opt_decls = nil)
 272          ASSERT.kind_of     loc,         LOC::Entry
 273          ASSERT.kind_of     pats,        ::Array
 274          ASSERT.kind_of     expr,        CSCE::Abstract
 275          ASSERT.opt_kind_of opt_decls,   CSCD::SeqOfDeclaration
 276 
 277          decls = opt_decls ? opt_decls : CSCD.make_empty_seq_of_declaration
 278          Nary::Lambda::Anonymous.new(loc, pats, expr, decls.freeze).freeze
 279      end
 280 
 281 
 282      def make_named_lambda(loc, pats, expr, decls, sym)
 283          ASSERT.kind_of loc,     LOC::Entry
 284          ASSERT.kind_of pats,    ::Array
 285          ASSERT.kind_of expr,    CSCE::Abstract
 286          ASSERT.kind_of decls,   CSCD::SeqOfDeclaration
 287          ASSERT.kind_of sym,     ::Symbol
 288 
 289          Nary::Lambda::Named.new(loc, pats, expr, decls.freeze, sym).freeze
 290      end
 291 
 292  end # Umu::ConcreteSyntax::Core::Expression
 293 
 294  end # Umu::ConcreteSyntax::Core
 295 
 296  end # Umu::ConcreteSyntax
 297 
 298  end # Umu