@@ -6,10 +6,16 @@ use strict;
6
6
use warnings;
7
7
8
8
use Language::Bel::Core qw(
9
+ is_nil
9
10
is_pair
10
11
is_symbol
12
+ is_symbol_of_name
11
13
make_pair
12
14
make_symbol
15
+ symbol_name
16
+ ) ;
17
+ use Language::Bel::Printer qw(
18
+ _print
13
19
) ;
14
20
use Language::Bel::Compiler::Gensym qw(
15
21
is_gensym
@@ -42,6 +48,21 @@ sub substitute_registers {
42
48
}
43
49
}
44
50
51
+ sub starts_with {
52
+ my ($string , $prefix ) = @_ ;
53
+
54
+ return substr ($string , 0, length ($prefix )) eq $prefix ;
55
+ }
56
+
57
+ my $REGISTER_PREFIX = " %" ;
58
+
59
+ sub is_register {
60
+ my ($expr ) = @_ ;
61
+
62
+ return is_symbol($expr )
63
+ && starts_with(symbol_name($expr ), $REGISTER_PREFIX );
64
+ }
65
+
45
66
# @override
46
67
sub check_precondition {
47
68
# no checks
@@ -65,4 +86,102 @@ sub do_translate {
65
86
);
66
87
}
67
88
89
+ # @override
90
+ sub check_postcondition {
91
+ my ($self , $ast ) = @_ ;
92
+
93
+ my $body = cdr(cdr($ast ));
94
+
95
+ while (!is_nil($body )) {
96
+ die " body not a pair"
97
+ unless is_pair($body );
98
+
99
+ my $operation = car($body );
100
+
101
+ my @operands ;
102
+ while (!is_nil($operation )) {
103
+ die " operation is not a pair"
104
+ unless is_pair($operation );
105
+ push @operands , car($operation );
106
+ $operation = cdr($operation );
107
+ }
108
+
109
+ my $op_name = shift (@operands );
110
+
111
+ if (is_symbol_of_name($op_name , " return" )) {
112
+ die " expected gensym as only operand to 'return'"
113
+ unless scalar (@operands ) == 1 && is_register($operands [0]);
114
+ }
115
+ elsif (is_register($op_name )) {
116
+ die " expected two operands"
117
+ unless scalar (@operands ) == 2;
118
+ die " expected := immediately after gensym"
119
+ unless is_pair($operands [0])
120
+ && is_symbol_of_name(car($operands [0]), " compose" )
121
+ && is_symbol_of_name(car(cdr($operands [0])), " =" );
122
+
123
+ my $rhs = $operands [1];
124
+ my @rhs_operands ;
125
+ while (!is_nil($rhs )) {
126
+ die " rhs operation is not a pair"
127
+ unless is_pair($rhs );
128
+ push @rhs_operands , car($rhs );
129
+ $rhs = cdr($rhs );
130
+ }
131
+
132
+ my $rhs_op = shift (@rhs_operands );
133
+
134
+ if (is_pair($rhs_op )
135
+ && is_symbol_of_name(car($rhs_op ), " prim" )
136
+ && is_pair(car(cdr($rhs_op )))
137
+ && is_symbol_of_name(car(car(cdr($rhs_op ))), " quote" )
138
+ && is_symbol(car(cdr(car(cdr($rhs_op )))))) {
139
+
140
+ my $primop_name = symbol_name(car(cdr(car(cdr($rhs_op )))));
141
+
142
+ die " expected primop to be id or type"
143
+ unless $primop_name eq " id" || $primop_name eq " type" ;
144
+
145
+ if ($primop_name eq " id" ) {
146
+ die " expected prim!id to have 2 operands"
147
+ unless scalar (@rhs_operands ) == 2;
148
+
149
+ die " expected first prim!id operand to be a register"
150
+ unless is_register($rhs_operands [0]);
151
+
152
+ die " expected second prim!id operand to be a quoted symbol"
153
+ unless is_pair($rhs_operands [1])
154
+ && is_symbol_of_name(car($rhs_operands [1]), " quote" )
155
+ && is_symbol(car(cdr($rhs_operands [1])));
156
+ }
157
+ elsif ($primop_name eq " type" ) {
158
+ die " expected prim!type to have 1 operand"
159
+ unless scalar (@rhs_operands ) == 1;
160
+
161
+ die " expected prim!type operand to be a register"
162
+ unless is_register($rhs_operands [0]);
163
+ }
164
+ else {
165
+ die " unexpected type of primop: $primop_name " ;
166
+ }
167
+ }
168
+ elsif (is_symbol_of_name($rhs_op , " quote" )) {
169
+ die " expected quote to have 1 operand"
170
+ unless scalar (@rhs_operands ) == 1;
171
+
172
+ die " expected quote operand to be a symbol"
173
+ unless is_symbol($rhs_operands [0]);
174
+ }
175
+ else {
176
+ die " unexpected rhs" ;
177
+ }
178
+ }
179
+ else {
180
+ die " unrecognized operation: " , _print(car($body ));
181
+ }
182
+
183
+ $body = cdr($body );
184
+ }
185
+ }
186
+
68
187
1;
0 commit comments