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 # N-ary, where N >= 3
15
16 class Let < Expression::Abstract
17 attr_reader :decls, :expr
18
19
20 def initialize(loc, decls, expr)
21 ASSERT.kind_of decls, ASCD::SeqOfDeclaration
22 ASSERT.kind_of expr, ASCE::Abstract
23
24 super(loc)
25
26 @decls = decls
27 @expr = expr
28 end
29
30
31 def to_s
32 format(
33 "%%LET { %s %%IN %s }",
34 self.decls.map(&:to_s).join(' '),
35 self.expr
36 )
37 end
38
39
40 def pretty_print(q)
41 PRT.group_for_enum q, self.decls, bb:'%LET {', sep:' '
42
43 q.breakable
44
45 PRT.group q, bb:'%IN', eb:'}', sep:' ' do
46 q.pp self.expr
47 end
48 end
49
50
51 private
52
53 def __evaluate__(init_env, event)
54 ASSERT.kind_of init_env, E::Entry
55 ASSERT.kind_of event, E::Tracer::Event
56
57 new_env = self.decls.inject(init_env.enter(event)) { |env, decl|
58 ASSERT.kind_of env, E::Entry
59 ASSERT.kind_of decl, ASCD::Abstract
60
61 result = decl.evaluate env
62 ASSERT.kind_of result, ASR::Environment
63
64 result.env
65 }
66
67 final_result = self.expr.evaluate new_env
68 ASSERT.kind_of final_result, ASR::Value
69
70 final_result.value
71 end
72 end
73
74 end # Umu::AbstractSyntax::Core::Expression::Nary
75
76
77 module_function
78
79 def make_let(loc, decls, expr)
80 ASSERT.kind_of loc, LOC::Entry
81 ASSERT.kind_of decls, ASCD::SeqOfDeclaration
82 ASSERT.kind_of expr, ASCE::Abstract
83
84 Nary::Let.new(loc, decls.freeze, expr).freeze
85 end
86
87 end # Umu::AbstractSyntax::Core::Expression
88
89 end # Umu::AbstractSyntax::Core
90
91 end # Umu::AbstractSyntax
92
93 end # Umu