line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!/usr/bin/perl |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package Language::Farnsworth::Evaluate; |
4
|
|
|
|
|
|
|
|
5
|
1
|
|
|
1
|
|
10
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
30
|
|
6
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
22
|
|
7
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
1214
|
use Data::Dumper; |
|
1
|
|
|
|
|
17882
|
|
|
1
|
|
|
|
|
93
|
|
9
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
691
|
use Language::Farnsworth::FunctionDispatch; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
use Language::Farnsworth::Variables; |
12
|
|
|
|
|
|
|
use Language::Farnsworth::Units; |
13
|
|
|
|
|
|
|
use Language::Farnsworth::Parser; |
14
|
|
|
|
|
|
|
use Language::Farnsworth::Value::Types; |
15
|
|
|
|
|
|
|
use Language::Farnsworth::Value::Pari; |
16
|
|
|
|
|
|
|
use Language::Farnsworth::Value::Date; |
17
|
|
|
|
|
|
|
use Language::Farnsworth::Value::String; |
18
|
|
|
|
|
|
|
use Language::Farnsworth::Value::Undef; |
19
|
|
|
|
|
|
|
use Language::Farnsworth::Value::Lambda; |
20
|
|
|
|
|
|
|
use Language::Farnsworth::Value::Array; |
21
|
|
|
|
|
|
|
use Language::Farnsworth::Value::Boolean; |
22
|
|
|
|
|
|
|
use Language::Farnsworth::Output; |
23
|
|
|
|
|
|
|
use Language::Farnsworth::Error; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
use Math::Pari;# ':hex'; #why not? because it fucks up so fucking badly that fuck isn't a strong enough word |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
sub new |
28
|
|
|
|
|
|
|
{ |
29
|
|
|
|
|
|
|
my $class = shift; |
30
|
|
|
|
|
|
|
my $self = {}; |
31
|
|
|
|
|
|
|
bless $self; |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
my %opts = (@_); |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
if (ref($opts{funcs}) eq "Language::Farnsworth::FunctionDispatch") |
36
|
|
|
|
|
|
|
{ |
37
|
|
|
|
|
|
|
$self->{funcs} = $opts{funcs}; |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
else |
40
|
|
|
|
|
|
|
{ |
41
|
|
|
|
|
|
|
$self->{funcs} = new Language::Farnsworth::FunctionDispatch(); |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
if (ref($opts{vars}) eq "Language::Farnsworth::Variables") |
45
|
|
|
|
|
|
|
{ |
46
|
|
|
|
|
|
|
$self->{vars} = $opts{vars}; |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
else |
49
|
|
|
|
|
|
|
{ |
50
|
|
|
|
|
|
|
$self->{vars} = new Language::Farnsworth::Variables(); |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
if (ref($opts{units}) eq "Language::Farnsworth::Units") |
54
|
|
|
|
|
|
|
{ |
55
|
|
|
|
|
|
|
$self->{units} = $opts{units}; |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
else |
58
|
|
|
|
|
|
|
{ |
59
|
|
|
|
|
|
|
$self->{units} = new Language::Farnsworth::Units(); |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
if (ref($opts{parser}) eq "Language::Farnsworth::Parser") |
63
|
|
|
|
|
|
|
{ |
64
|
|
|
|
|
|
|
$self->{parser} = $opts{parser}; |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
else |
67
|
|
|
|
|
|
|
{ |
68
|
|
|
|
|
|
|
$self->{parser} = new Language::Farnsworth::Parser(); |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
$self->{dumpbranches} = 0; |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
return $self; |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
sub DESTROY |
77
|
|
|
|
|
|
|
{ |
78
|
|
|
|
|
|
|
debug 2,"SCOPE DIE: $_[0]"; |
79
|
|
|
|
|
|
|
} |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
sub eval |
82
|
|
|
|
|
|
|
{ |
83
|
|
|
|
|
|
|
my $self = shift; |
84
|
|
|
|
|
|
|
my $code = shift; #i should probably take an array, so i can use arrays of things, but that'll be later |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
$code =~ s/^\s*//; |
87
|
|
|
|
|
|
|
$code =~ s/\s*$//; |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
my $tree = $self->{parser}->parse($code); #should i catch the exceptions here? dunno |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
debug 3, Dumper($tree); |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
my $ret = eval{$self->evalbranch($tree)}; |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
#capture return[] at minimum level |
96
|
|
|
|
|
|
|
if ($@ && $@->isa("Language::Farnsworth::Error")&&$@->isreturn()) |
97
|
|
|
|
|
|
|
{ |
98
|
|
|
|
|
|
|
return $@->getmsg(); |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
elsif ($@ && $@->isa("Language::Farnsworth::Error")) |
101
|
|
|
|
|
|
|
{ |
102
|
|
|
|
|
|
|
return $@; |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
elsif ($@) |
105
|
|
|
|
|
|
|
{ |
106
|
|
|
|
|
|
|
error EPERL, $@; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
else |
109
|
|
|
|
|
|
|
{ |
110
|
|
|
|
|
|
|
return $ret; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
#evaluate a single branch |
115
|
|
|
|
|
|
|
sub evalbranch |
116
|
|
|
|
|
|
|
{ |
117
|
|
|
|
|
|
|
my $self = shift; |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
my $branch = shift; |
120
|
|
|
|
|
|
|
my $type = ref($branch); #this'll grab what kind from the bless on the tree |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
my $return; #to make things simpler later on |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
#print Data::Dumper->Dump([$branch],["BRANCH"]); |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
if ($type eq "Add") |
127
|
|
|
|
|
|
|
{ |
128
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
129
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
130
|
|
|
|
|
|
|
$return = $a + $b; |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
elsif ($type eq "Sub") |
133
|
|
|
|
|
|
|
{ |
134
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
135
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
136
|
|
|
|
|
|
|
$return = $a - $b; |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
elsif ($type eq "Mul") |
139
|
|
|
|
|
|
|
{ |
140
|
|
|
|
|
|
|
if ((ref($branch->[0]) eq "Fetch") && (ref($branch->[1]) eq "Array") && ($branch->[2] eq "imp")) |
141
|
|
|
|
|
|
|
{ |
142
|
|
|
|
|
|
|
#we've got a new style function call! |
143
|
|
|
|
|
|
|
my $a = $branch->[0][0]; #grab the function name |
144
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
# print STDERR "----------------FUNCCALL! $a\n"; |
147
|
|
|
|
|
|
|
# print STDERR "$self"; |
148
|
|
|
|
|
|
|
# print Dumper($a, $b); |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
if ($self->{funcs}->isfunc($a)) #check if there is a func $a |
151
|
|
|
|
|
|
|
{ #$return = $self->{funcs}->callfunc($self, $name, $args, $branch); |
152
|
|
|
|
|
|
|
$return = $self->{funcs}->callfunc($self, $a, $b, $branch); |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
else #otherwise we try to |
155
|
|
|
|
|
|
|
{ |
156
|
|
|
|
|
|
|
$a = $self->makevalue($branch->[0]); #evaluate it, since it wasn't a function |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
$return = $a * $b; #do the multiplication |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
else |
162
|
|
|
|
|
|
|
{ |
163
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
164
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
#print "-----------SUBMULT!\n"; |
167
|
|
|
|
|
|
|
#print Dumper($a,$b); |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
$return = $a * $b; |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
elsif ($type eq "Div") |
173
|
|
|
|
|
|
|
{ |
174
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
175
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
176
|
|
|
|
|
|
|
#print Dumper($a, $b); |
177
|
|
|
|
|
|
|
$return = $a / $b; |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
elsif ($type eq "Conforms") |
180
|
|
|
|
|
|
|
{ |
181
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
182
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
183
|
|
|
|
|
|
|
$return = new Language::Farnsworth::Value::Boolean($a->conforms($b)); |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
elsif ($type eq "Mod") |
186
|
|
|
|
|
|
|
{ |
187
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
188
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
189
|
|
|
|
|
|
|
$return = $a % $b; |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
elsif ($type eq "Pow") |
192
|
|
|
|
|
|
|
{ |
193
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
194
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
195
|
|
|
|
|
|
|
$return = $a ** $b; |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
elsif ($type eq "And") |
198
|
|
|
|
|
|
|
{ |
199
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
if ($a->bool()) |
202
|
|
|
|
|
|
|
{ |
203
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
204
|
|
|
|
|
|
|
$return = $a && $b ? 1 : 0; |
205
|
|
|
|
|
|
|
$return = Language::Farnsworth::Value::Boolean->new($return); #make sure its the right type |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
else |
208
|
|
|
|
|
|
|
{ |
209
|
|
|
|
|
|
|
$return = Language::Farnsworth::Value::Boolean->new(0); #make sure its the right type |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
elsif ($type eq "Or") |
213
|
|
|
|
|
|
|
{ |
214
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
if ($a->bool()) |
217
|
|
|
|
|
|
|
{ |
218
|
|
|
|
|
|
|
$return = Language::Farnsworth::Value::Boolean->new(1); #make sure its the right type |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
else |
221
|
|
|
|
|
|
|
{ |
222
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
223
|
|
|
|
|
|
|
$return = $a || $b ? 1 : 0; |
224
|
|
|
|
|
|
|
$return = Language::Farnsworth::Value::Boolean->new($return); #make sure its the right type |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
elsif ($type eq "Xor") |
228
|
|
|
|
|
|
|
{ |
229
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
230
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
231
|
|
|
|
|
|
|
$return = $a->bool() ^ $b->bool() ? 1 : 0; |
232
|
|
|
|
|
|
|
$return = Language::Farnsworth::Value::Boolean->new($return); #make sure its the right type |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
elsif ($type eq "Not") |
235
|
|
|
|
|
|
|
{ |
236
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
237
|
|
|
|
|
|
|
$return = $a->bool() ? 0 : 1; |
238
|
|
|
|
|
|
|
$return = Language::Farnsworth::Value::Boolean->new($return); #make sure its the right type |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
elsif ($type eq "Gt") |
241
|
|
|
|
|
|
|
{ |
242
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
243
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
244
|
|
|
|
|
|
|
$return = ($a > $b) ? 1 : 0; |
245
|
|
|
|
|
|
|
$return = Language::Farnsworth::Value::Boolean->new($return); #make sure its the right type |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
elsif ($type eq "Lt") |
248
|
|
|
|
|
|
|
{ |
249
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
250
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
251
|
|
|
|
|
|
|
$return = $a < $b ? 1 : 0; |
252
|
|
|
|
|
|
|
$return = Language::Farnsworth::Value::Boolean->new($return); #make sure its the right type |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
elsif ($type eq "Ge") |
255
|
|
|
|
|
|
|
{ |
256
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
257
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
258
|
|
|
|
|
|
|
$return = $a >= $b ? 1 : 0; |
259
|
|
|
|
|
|
|
$return = Language::Farnsworth::Value::Boolean->new($return); #make sure its the right type |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
elsif ($type eq "Le") |
262
|
|
|
|
|
|
|
{ |
263
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
264
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
265
|
|
|
|
|
|
|
$return = $a <= $b ? 1 : 0; |
266
|
|
|
|
|
|
|
$return = Language::Farnsworth::Value::Boolean->new($return); #make sure its the right type |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
elsif ($type eq "Compare") |
269
|
|
|
|
|
|
|
{ |
270
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
271
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
272
|
|
|
|
|
|
|
$return = $a <=> $b; |
273
|
|
|
|
|
|
|
$return = Language::Farnsworth::Value::Pari->new($return); #make sure its the right type |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
elsif ($type eq "Eq") |
276
|
|
|
|
|
|
|
{ |
277
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
278
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
279
|
|
|
|
|
|
|
$return = $a == $b ? 1 : 0; |
280
|
|
|
|
|
|
|
$return = Language::Farnsworth::Value::Boolean->new($return); #make sure its the right type |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
elsif ($type eq "Ne") |
283
|
|
|
|
|
|
|
{ |
284
|
|
|
|
|
|
|
my $a = $self->makevalue($branch->[0]); |
285
|
|
|
|
|
|
|
my $b = $self->makevalue($branch->[1]); |
286
|
|
|
|
|
|
|
$return = $a != $b ? 1 : 0; |
287
|
|
|
|
|
|
|
$return = Language::Farnsworth::Value::Boolean->new($return); #make sure its the right type |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
elsif ($type eq "Ternary") |
290
|
|
|
|
|
|
|
{ |
291
|
|
|
|
|
|
|
#turing completeness FTW |
292
|
|
|
|
|
|
|
my $left = $self->makevalue($branch->[0]); |
293
|
|
|
|
|
|
|
#$left = $left->bool() != new Language::Farnsworth::Value::Pari(0, $left->{dimen}); #shouldn't need it anymore, since i got ->bool working |
294
|
|
|
|
|
|
|
$return = $left ? $self->makevalue($branch->[1]) : $self->makevalue($branch->[2]); |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
elsif ($type eq "If") |
297
|
|
|
|
|
|
|
{ |
298
|
|
|
|
|
|
|
#turing completeness FTW |
299
|
|
|
|
|
|
|
my $left = $self->makevalue($branch->[0]); |
300
|
|
|
|
|
|
|
#$left = $left != new Language::Farnsworth::Value(0, $left->{dimen}); |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
if ($left) |
303
|
|
|
|
|
|
|
{ |
304
|
|
|
|
|
|
|
$return = $self->makevalue($branch->[1]); |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
else |
307
|
|
|
|
|
|
|
{ |
308
|
|
|
|
|
|
|
$return = $self->makevalue($branch->[2]); |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
elsif ($type eq "Store") |
312
|
|
|
|
|
|
|
{ |
313
|
|
|
|
|
|
|
my $value = $self->makevalue($branch->[1]); |
314
|
|
|
|
|
|
|
my $lvalue = $self->makevalue($branch->[0]); |
315
|
|
|
|
|
|
|
$return = $value; #make stores evaluate to the value on the right |
316
|
|
|
|
|
|
|
#$self->{vars}->setvar($name, $value); |
317
|
|
|
|
|
|
|
$lvalue->{stored}++; #testing |
318
|
|
|
|
|
|
|
my $cloned = $value->clone(); |
319
|
|
|
|
|
|
|
#warn "SETTING VALUES"; |
320
|
|
|
|
|
|
|
#warn Data::Dumper->Dump([$lvalue, $lvalue->getref(), $value, $cloned], [qw($lvalue \$ref $value $cloned)]); |
321
|
|
|
|
|
|
|
$cloned->setref(\$cloned); |
322
|
|
|
|
|
|
|
debug 6, "---STORE---\n",Data::Dumper->Dump([$lvalue, $value, $cloned, $lvalue->getref()],[qw(lvalue value cloned lvalref)]); |
323
|
|
|
|
|
|
|
${$lvalue->{_ref}} = $cloned; |
324
|
|
|
|
|
|
|
debug 6, "---STORE---\n",Data::Dumper->Dump([$lvalue, $value, $cloned, $lvalue->getref()],[qw(lvalue value cloned lvalref)]); |
325
|
|
|
|
|
|
|
# eval { |
326
|
|
|
|
|
|
|
# my $rrval = $self->makevalue($branch->[0]); |
327
|
|
|
|
|
|
|
# debug 2, Data::Dumper->Dump([$rrval, $lvalue, $cloned], [qw(rrval lvalue cloned)]); |
328
|
|
|
|
|
|
|
# }; #keep it from killing things ahead of time |
329
|
|
|
|
|
|
|
# undef $@; |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
elsif ($type eq "StoreAdd") |
332
|
|
|
|
|
|
|
{ |
333
|
|
|
|
|
|
|
my $value = $self->makevalue($branch->[1]); |
334
|
|
|
|
|
|
|
my $lvalue = $self->makevalue($branch->[0]); |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
my $cloned = $value->clone(); |
337
|
|
|
|
|
|
|
$return = (${$lvalue->getref()} = $lvalue + $cloned); |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
elsif ($type eq "StoreSub") |
340
|
|
|
|
|
|
|
{ |
341
|
|
|
|
|
|
|
my $value = $self->makevalue($branch->[1]); |
342
|
|
|
|
|
|
|
my $lvalue = $self->makevalue($branch->[0]); |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
my $cloned = $value->clone(); |
345
|
|
|
|
|
|
|
$return = (${$lvalue->getref()} = $lvalue - $cloned); |
346
|
|
|
|
|
|
|
} |
347
|
|
|
|
|
|
|
elsif ($type eq "StoreDiv") |
348
|
|
|
|
|
|
|
{ |
349
|
|
|
|
|
|
|
my $value = $self->makevalue($branch->[1]); |
350
|
|
|
|
|
|
|
my $lvalue = $self->makevalue($branch->[0]); |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
my $cloned = $value->clone(); |
353
|
|
|
|
|
|
|
$return = (${$lvalue->getref()} = $lvalue / $cloned); |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
elsif ($type eq "StoreMul") |
356
|
|
|
|
|
|
|
{ |
357
|
|
|
|
|
|
|
my $value = $self->makevalue($branch->[1]); |
358
|
|
|
|
|
|
|
my $lvalue = $self->makevalue($branch->[0]); |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
my $cloned = $value->clone(); |
361
|
|
|
|
|
|
|
$return = (${$lvalue->getref()} = $lvalue * $cloned); |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
elsif ($type eq "StoreMod") |
364
|
|
|
|
|
|
|
{ |
365
|
|
|
|
|
|
|
my $value = $self->makevalue($branch->[1]); |
366
|
|
|
|
|
|
|
my $lvalue = $self->makevalue($branch->[0]); |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
my $cloned = $value->clone(); |
369
|
|
|
|
|
|
|
$return = (${$lvalue->getref()} = $lvalue % $cloned); |
370
|
|
|
|
|
|
|
} |
371
|
|
|
|
|
|
|
elsif ($type eq "StorePow") |
372
|
|
|
|
|
|
|
{ |
373
|
|
|
|
|
|
|
my $value = $self->makevalue($branch->[1]); |
374
|
|
|
|
|
|
|
my $lvalue = $self->makevalue($branch->[0]); |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
my $cloned = $value->clone(); |
377
|
|
|
|
|
|
|
$return = (${$lvalue->getref()} = $lvalue ** $cloned); |
378
|
|
|
|
|
|
|
} |
379
|
|
|
|
|
|
|
elsif ($type eq "PreInc") |
380
|
|
|
|
|
|
|
{ |
381
|
|
|
|
|
|
|
my $lvalue = $self->makevalue($branch->[0]); |
382
|
|
|
|
|
|
|
$return = (${$lvalue->getref()} = $lvalue+VALUE_ONE()); |
383
|
|
|
|
|
|
|
} |
384
|
|
|
|
|
|
|
elsif ($type eq "PostInc") |
385
|
|
|
|
|
|
|
{ |
386
|
|
|
|
|
|
|
my $lvalue = $self->makevalue($branch->[0]); |
387
|
|
|
|
|
|
|
my $val = $lvalue->clone(); |
388
|
|
|
|
|
|
|
${$lvalue->getref()} = $val+VALUE_ONE(); |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
$return = $val; |
391
|
|
|
|
|
|
|
} |
392
|
|
|
|
|
|
|
elsif ($type eq "PreDec") |
393
|
|
|
|
|
|
|
{ |
394
|
|
|
|
|
|
|
my $lvalue = $self->makevalue($branch->[0]); |
395
|
|
|
|
|
|
|
$return = (${$lvalue->getref()} = $lvalue-VALUE_ONE()); |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
elsif ($type eq "PostDec") |
398
|
|
|
|
|
|
|
{ |
399
|
|
|
|
|
|
|
my $lvalue = $self->makevalue($branch->[0]); |
400
|
|
|
|
|
|
|
my $val = $lvalue->clone(); |
401
|
|
|
|
|
|
|
${$lvalue->getref()} = $val-VALUE_ONE(); |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
$return = $val; |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
elsif ($type eq "DeclareVar") |
406
|
|
|
|
|
|
|
{ |
407
|
|
|
|
|
|
|
my $name = $branch->[0]; |
408
|
|
|
|
|
|
|
my $value; |
409
|
|
|
|
|
|
|
#print "\n\n DECLARING $name\n"; |
410
|
|
|
|
|
|
|
#print Dumper($branch); |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
if (defined($branch->[1])) |
413
|
|
|
|
|
|
|
{ |
414
|
|
|
|
|
|
|
$value = $self->makevalue($branch->[1]); |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
else |
417
|
|
|
|
|
|
|
{ |
418
|
|
|
|
|
|
|
$value = $self->makevalue(bless [0], 'Num'); |
419
|
|
|
|
|
|
|
} |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
$return = $value; #make stores evaluate to the value on the right |
422
|
|
|
|
|
|
|
$self->{vars}->declare($name, $value); |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
elsif ($type eq "DeclareFunc") |
425
|
|
|
|
|
|
|
{ |
426
|
|
|
|
|
|
|
#print Dumper($branch); |
427
|
|
|
|
|
|
|
my $name = $branch->[0]; |
428
|
|
|
|
|
|
|
my $lambda = $self->makevalue($branch->[1]); |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
#should i allow constants? if i do i'll have to handle them differently, for now it'll be an error |
431
|
|
|
|
|
|
|
error "Right side of function declaration for '$name' did not evaluate to a lambda" unless ($lambda->istype("Lambda")); |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
$self->{funcs}->addfunclamb($name, $lambda); |
434
|
|
|
|
|
|
|
$return = $lambda; |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
elsif ($type eq "FuncDef") |
437
|
|
|
|
|
|
|
{ |
438
|
|
|
|
|
|
|
#print Dumper($branch); |
439
|
|
|
|
|
|
|
my $name = $branch->[0]; |
440
|
|
|
|
|
|
|
my $args = $branch->[1]; |
441
|
|
|
|
|
|
|
my $value = $branch->[2]; #not really a value, but in fact the tree to run for the function |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
my $nvars = new Language::Farnsworth::Variables($self->{vars}); #lamdbas get their own vars |
444
|
|
|
|
|
|
|
my %nopts = (vars => $nvars, funcs => $self->{funcs}, units => $self->{units}, parser => $self->{parser}); |
445
|
|
|
|
|
|
|
my $scope = $self->new(%nopts); |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
my $vargs; |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
for my $arg (@$args) |
450
|
|
|
|
|
|
|
{ |
451
|
|
|
|
|
|
|
my $reference = $arg->[3]; |
452
|
|
|
|
|
|
|
my $constraint = $arg->[2]; |
453
|
|
|
|
|
|
|
my $default = $arg->[1]; |
454
|
|
|
|
|
|
|
my $name = $arg->[0]; #name |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
if (defined($default)) |
457
|
|
|
|
|
|
|
{ |
458
|
|
|
|
|
|
|
$default = $self->makevalue($default); #should be right |
459
|
|
|
|
|
|
|
} |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
if (defined($constraint)) |
462
|
|
|
|
|
|
|
{ |
463
|
|
|
|
|
|
|
#print Dumper($constraint); |
464
|
|
|
|
|
|
|
$constraint = $self->makevalue($constraint); #should be right |
465
|
|
|
|
|
|
|
#print Dumper($constraint); |
466
|
|
|
|
|
|
|
} |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
push @$vargs, [$name, $default, $constraint, $reference]; |
469
|
|
|
|
|
|
|
} |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
$self->{funcs}->addfunc($name, $vargs, $value, $scope); |
472
|
|
|
|
|
|
|
$return = undef; #cause an error should someone manage to make it parse other than the way i think it should be |
473
|
|
|
|
|
|
|
} |
474
|
|
|
|
|
|
|
elsif ($type eq "Lambda") |
475
|
|
|
|
|
|
|
{ |
476
|
|
|
|
|
|
|
my $args = $branch->[0]; |
477
|
|
|
|
|
|
|
my $code = $branch->[1]; |
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
#print "==========LAMBDA==========\n"; |
480
|
|
|
|
|
|
|
#print Data::Dumper->Dump([$args,$code], ["args", "code"]); |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
my $nvars = new Language::Farnsworth::Variables($self->{vars}); #lamdbas get their own vars |
483
|
|
|
|
|
|
|
my %nopts = (vars => $nvars, funcs => $self->{funcs}, units => $self->{units}, parser => $self->{parser}); |
484
|
|
|
|
|
|
|
my $scope = $self->new(%nopts); |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
#this should probably get a function in Language::Farnsworth::FunctionDispatch |
487
|
|
|
|
|
|
|
my $vargs; |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
for my $arg (@$args) |
490
|
|
|
|
|
|
|
{ |
491
|
|
|
|
|
|
|
my $reference = $arg->[3]; |
492
|
|
|
|
|
|
|
my $constraint = $arg->[2]; |
493
|
|
|
|
|
|
|
my $default = $arg->[1]; |
494
|
|
|
|
|
|
|
my $name = $arg->[0]; #name |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
# if ($reference) |
497
|
|
|
|
|
|
|
# { |
498
|
|
|
|
|
|
|
# #we've got a reference for lambdas! |
499
|
|
|
|
|
|
|
# error "Passing arguments by reference for lambdas is unsupported at this time"; |
500
|
|
|
|
|
|
|
# } |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
if (defined($default)) |
503
|
|
|
|
|
|
|
{ |
504
|
|
|
|
|
|
|
$default = $self->makevalue($default); #should be right |
505
|
|
|
|
|
|
|
} |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
if (defined($constraint)) |
508
|
|
|
|
|
|
|
{ |
509
|
|
|
|
|
|
|
#print Dumper($constraint); |
510
|
|
|
|
|
|
|
$constraint = $self->makevalue($constraint); #should be right |
511
|
|
|
|
|
|
|
#print Dumper($constraint); |
512
|
|
|
|
|
|
|
} |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
push @$vargs, [$name, $default, $constraint, $reference]; |
515
|
|
|
|
|
|
|
} |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
$return = new Language::Farnsworth::Value::Lambda($scope, $vargs, $code, $branch); |
518
|
|
|
|
|
|
|
} |
519
|
|
|
|
|
|
|
elsif ($type eq "LambdaCall") #still used in ONE place, sort[] in Standard.pm, i need to get the code to use mult but that's being a pita and i'm done trying to do it at the moment |
520
|
|
|
|
|
|
|
{ |
521
|
|
|
|
|
|
|
my $left = $self->makevalue($branch->[0]); |
522
|
|
|
|
|
|
|
my $right = $self->makevalue($branch->[1]); |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
error "Right side of lamdbda call must evaluate to a Lambda\n" unless $right->istype("Lambda"); |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
#need $args to be an array |
527
|
|
|
|
|
|
|
my $args = $left->istype("Array") ? $left : new Language::Farnsworth::Value::Array([$left]); |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
$return = $self->{funcs}->calllambda($right, $args); #needs to be updated |
530
|
|
|
|
|
|
|
} |
531
|
|
|
|
|
|
|
elsif (($type eq "Array") || ($type eq "SubArray")) |
532
|
|
|
|
|
|
|
{ |
533
|
|
|
|
|
|
|
my $array = []; #fixes bug with empty arrays |
534
|
|
|
|
|
|
|
for my $bs (@$branch) #iterate over all the elements |
535
|
|
|
|
|
|
|
{ |
536
|
|
|
|
|
|
|
my $type = ref($bs); #find out what kind of thing we are |
537
|
|
|
|
|
|
|
my $value = $self->makevalue($bs); |
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
#print "ARRAY FILL -- $type\n"; |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
# if ($value->istype("Array")) |
542
|
|
|
|
|
|
|
# { |
543
|
|
|
|
|
|
|
#since we have an array, but its not in a SUBarray, we dereference it before the push |
544
|
|
|
|
|
|
|
#push @$array, $value->getarray() unless ($type eq "SubArray"); |
545
|
|
|
|
|
|
|
#push @$array, $value;# if ($type eq "SubArray"); |
546
|
|
|
|
|
|
|
#} |
547
|
|
|
|
|
|
|
#else |
548
|
|
|
|
|
|
|
{ |
549
|
|
|
|
|
|
|
#print "ARRAY VALUE --- ".Dumper($value); |
550
|
|
|
|
|
|
|
#its not an array or anything so we push it on |
551
|
|
|
|
|
|
|
push @$array, $value; #we return an array ref! i need more error checking around for this later |
552
|
|
|
|
|
|
|
} |
553
|
|
|
|
|
|
|
} |
554
|
|
|
|
|
|
|
$return = new Language::Farnsworth::Value::Array($array); |
555
|
|
|
|
|
|
|
} |
556
|
|
|
|
|
|
|
elsif ($type eq "ArgArray") |
557
|
|
|
|
|
|
|
{ |
558
|
|
|
|
|
|
|
my $array = []; #autovivification wasn't working? |
559
|
|
|
|
|
|
|
for my $bs (@$branch) #iterate over all the elements |
560
|
|
|
|
|
|
|
{ |
561
|
|
|
|
|
|
|
my $type = ref($bs); #find out what kind of thing we are |
562
|
|
|
|
|
|
|
my $value = $self->makevalue($bs); |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
#even if it is an array we don't want to deref it here, because thats the wrong behavior, this will make things like push[a, 1,2,3] work properly |
565
|
|
|
|
|
|
|
push @$array, $value; #we return an array ref! i need more error checking around for this later |
566
|
|
|
|
|
|
|
} |
567
|
|
|
|
|
|
|
$return = new Language::Farnsworth::Value::Array($array); |
568
|
|
|
|
|
|
|
} |
569
|
|
|
|
|
|
|
elsif ($type eq "ArrayFetch") |
570
|
|
|
|
|
|
|
{ |
571
|
|
|
|
|
|
|
#print "\n\nAFETCH\n"; |
572
|
|
|
|
|
|
|
my $var = $self->makevalue($branch->[0]); #need to check if this is an array, and die if not |
573
|
|
|
|
|
|
|
my $listval = $self->makevalue($branch->[1]); |
574
|
|
|
|
|
|
|
my @rval; |
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
#print Data::Dumper->Dump([$branch, $var, $listval], ["branch","var","listval"]); |
577
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
for ($listval->getarray()) |
579
|
|
|
|
|
|
|
{ |
580
|
|
|
|
|
|
|
my $index = $_->getpari()*1.0; |
581
|
|
|
|
|
|
|
#print STDERR "ARFET: ".$_->toperl()."\n"; |
582
|
|
|
|
|
|
|
#ok this line FOR WHATEVER REASON, makes Math::Pari.xs die in isnull(), WHY i don't know, there's something wrong here somewhere |
583
|
|
|
|
|
|
|
#my $float = $_ * (Language::Farnsworth::Value::Pari->new(1.0)); #makes rationals work right |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
my $input = $var->getarrayref()->[$index]; |
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
#error "Array out of bounds\n" #old message, check is down below now; |
588
|
|
|
|
|
|
|
$var->getarrayref()->[$index] = TYPE_UNDEF unless defined $input; |
589
|
|
|
|
|
|
|
$input = $var->getarrayref()->[$index] unless defined $input; #reset the value if needed, this code should be redone but i don't feel like it right now XXX |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
$input->setref(\$var->getarrayref()->[$index]); |
592
|
|
|
|
|
|
|
push @rval, $input; |
593
|
|
|
|
|
|
|
} |
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
#print Dumper(\@rval); |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
if (@rval > 1) |
598
|
|
|
|
|
|
|
{ |
599
|
|
|
|
|
|
|
my $pr = new Language::Farnsworth::Value::Array([@rval]); |
600
|
|
|
|
|
|
|
$return = $pr; |
601
|
|
|
|
|
|
|
$return->setref(\$return); #i think this should work fine |
602
|
|
|
|
|
|
|
} |
603
|
|
|
|
|
|
|
else |
604
|
|
|
|
|
|
|
{ |
605
|
|
|
|
|
|
|
$return = $rval[0]; |
606
|
|
|
|
|
|
|
} |
607
|
|
|
|
|
|
|
} |
608
|
|
|
|
|
|
|
elsif ($type eq "ArrayStore") |
609
|
|
|
|
|
|
|
{ |
610
|
|
|
|
|
|
|
my $var = $self->makevalue(bless [$branch->[0]], 'Fetch'); #need to check if this is an array, and die if not |
611
|
|
|
|
|
|
|
my $listval = $self->makevalue($branch->[1]); |
612
|
|
|
|
|
|
|
my $rval = $self->makevalue($branch->[2]); |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
#print Dumper($branch, $var, $listval); |
615
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
if ($listval->getarray() > 1) |
617
|
|
|
|
|
|
|
{ |
618
|
|
|
|
|
|
|
error "Assigning to slices not implemented yet\n"; |
619
|
|
|
|
|
|
|
} |
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
error "Only numerics may be given as array indexes!" unless ($listval->getarrayref()->[0]->istype("Pari")); |
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
my $num = $listval->getarrayref()->[0]->getpari() + 0; #the +0 makes sure its coerced into a number |
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
$var->getarrayref()->[$num] = $rval; |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
for my $value ($var->getarray()) |
628
|
|
|
|
|
|
|
{ |
629
|
|
|
|
|
|
|
$value = $self->makevalue(bless [0], 'Num') if !defined($value); |
630
|
|
|
|
|
|
|
} |
631
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
$return = $rval; |
633
|
|
|
|
|
|
|
} |
634
|
|
|
|
|
|
|
elsif ($type eq "While") |
635
|
|
|
|
|
|
|
{ |
636
|
|
|
|
|
|
|
my $cond = $branch->[0]; #what to check each time |
637
|
|
|
|
|
|
|
my $stmts = $branch->[1]; #what to run each time |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
my $condval = $self->makevalue($cond); |
640
|
|
|
|
|
|
|
while ($condval) |
641
|
|
|
|
|
|
|
{ |
642
|
|
|
|
|
|
|
my $v = $self->makevalue($stmts); |
643
|
|
|
|
|
|
|
$condval = $self->makevalue($cond); |
644
|
|
|
|
|
|
|
} |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
$return = undef; #cause errors |
647
|
|
|
|
|
|
|
} |
648
|
|
|
|
|
|
|
elsif ($type eq "Stmt") |
649
|
|
|
|
|
|
|
{ |
650
|
|
|
|
|
|
|
for my $bs (@$branch) #iterate over all the statements |
651
|
|
|
|
|
|
|
{ |
652
|
|
|
|
|
|
|
if (defined($bs)) |
653
|
|
|
|
|
|
|
{ |
654
|
|
|
|
|
|
|
my $r = $self->makevalue($bs); |
655
|
|
|
|
|
|
|
$return = $r if defined $r; #this has interesting semantics! |
656
|
|
|
|
|
|
|
} |
657
|
|
|
|
|
|
|
} |
658
|
|
|
|
|
|
|
} |
659
|
|
|
|
|
|
|
elsif ($type eq "Paren") |
660
|
|
|
|
|
|
|
{ |
661
|
|
|
|
|
|
|
$return = $self->makevalue($branch->[0]); |
662
|
|
|
|
|
|
|
} |
663
|
|
|
|
|
|
|
elsif ($type eq "SetDisplay") |
664
|
|
|
|
|
|
|
{ |
665
|
|
|
|
|
|
|
#TODO make error checking |
666
|
|
|
|
|
|
|
print Dumper($branch); |
667
|
|
|
|
|
|
|
my $combo = $branch->[0][0]; #is a string? |
668
|
|
|
|
|
|
|
my $right = $self->makevalue($branch->[1]); |
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
Language::Farnsworth::Output->setdisplay($combo, $right); |
671
|
|
|
|
|
|
|
} |
672
|
|
|
|
|
|
|
elsif ($type eq "UnitDef") |
673
|
|
|
|
|
|
|
{ |
674
|
|
|
|
|
|
|
my $unitsize = $self->makevalue($branch->[1]); |
675
|
|
|
|
|
|
|
my $name = $branch->[0]; |
676
|
|
|
|
|
|
|
$self->{units}->addunit($name, $unitsize); |
677
|
|
|
|
|
|
|
$return = $unitsize; |
678
|
|
|
|
|
|
|
} |
679
|
|
|
|
|
|
|
elsif ($type eq "DefineDimen") |
680
|
|
|
|
|
|
|
{ |
681
|
|
|
|
|
|
|
my $unit = $branch->[1]; |
682
|
|
|
|
|
|
|
my $dimen = $branch->[0]; |
683
|
|
|
|
|
|
|
$self->{units}->adddimen($dimen, $unit); |
684
|
|
|
|
|
|
|
} |
685
|
|
|
|
|
|
|
elsif ($type eq "DefineCombo") |
686
|
|
|
|
|
|
|
{ |
687
|
|
|
|
|
|
|
my $combo = $branch->[1]; #should get me a string! |
688
|
|
|
|
|
|
|
my $value = $self->makevalue($branch->[0]); |
689
|
|
|
|
|
|
|
Language::Farnsworth::Output::addcombo($combo, $value); |
690
|
|
|
|
|
|
|
} |
691
|
|
|
|
|
|
|
elsif (($type eq "SetPrefix") || ($type eq "SetPrefixAbrv")) |
692
|
|
|
|
|
|
|
{ |
693
|
|
|
|
|
|
|
my $name = $branch->[0]; |
694
|
|
|
|
|
|
|
my $value = $self->makevalue($branch->[1]); |
695
|
|
|
|
|
|
|
#carp "SETTING PREFIX0: $name : $value : ".Dumper($branch->[1]) if ($name eq "m"); |
696
|
|
|
|
|
|
|
$self->{units}->setprefix($name, $value); |
697
|
|
|
|
|
|
|
} |
698
|
|
|
|
|
|
|
elsif ($type eq "Trans") |
699
|
|
|
|
|
|
|
{ |
700
|
|
|
|
|
|
|
my $left = $self->makevalue($branch->[0]); |
701
|
|
|
|
|
|
|
my $rights = eval {$self->makevalue($branch->[1])}; |
702
|
|
|
|
|
|
|
print "TRANS: right side eval\n"; |
703
|
|
|
|
|
|
|
#print Dumper($@); |
704
|
|
|
|
|
|
|
my $right = $rights; |
705
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
if (!$@ && defined($rights) && $rights->istype("String")) #if its a string we do some fun stuff |
707
|
|
|
|
|
|
|
{ |
708
|
|
|
|
|
|
|
print "STRINGED\n"; |
709
|
|
|
|
|
|
|
$right = $self->eval($rights->getstring()); #we need to set $right to the evaluation $rights |
710
|
|
|
|
|
|
|
#print Dumper($rights, $right); |
711
|
|
|
|
|
|
|
print "ERRORED: ".Dumper($@); |
712
|
|
|
|
|
|
|
} |
713
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
if (!$@) |
715
|
|
|
|
|
|
|
{ |
716
|
|
|
|
|
|
|
debug 1,"\n\nLEFT\n"; |
717
|
|
|
|
|
|
|
debug 1,ref($left); |
718
|
|
|
|
|
|
|
debug 1,"RIGHT\n"; |
719
|
|
|
|
|
|
|
debug 1,ref($right); |
720
|
|
|
|
|
|
|
|
721
|
|
|
|
|
|
|
if ($left->conforms($right)) #only do this if they are the same |
722
|
|
|
|
|
|
|
{ |
723
|
|
|
|
|
|
|
print "Got Conformity\n"; |
724
|
|
|
|
|
|
|
my $dispval = ($left / $right); |
725
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
#$return = $left; |
727
|
|
|
|
|
|
|
%$return = %$left; #ok this makes NO SENSE as to WHY it would behave like it was... |
728
|
|
|
|
|
|
|
bless $return, ref($left); |
729
|
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
if ($rights->istype("String")) |
731
|
|
|
|
|
|
|
{ |
732
|
|
|
|
|
|
|
#right side was a string, use it |
733
|
|
|
|
|
|
|
$return->{outmagic} = [$dispval, $rights]; |
734
|
|
|
|
|
|
|
} |
735
|
|
|
|
|
|
|
else |
736
|
|
|
|
|
|
|
{ |
737
|
|
|
|
|
|
|
$return->{outmagic} = [$dispval]; |
738
|
|
|
|
|
|
|
} |
739
|
|
|
|
|
|
|
} |
740
|
|
|
|
|
|
|
elsif ($right->istype("Lambda")) |
741
|
|
|
|
|
|
|
{ |
742
|
|
|
|
|
|
|
print "Got a lambda"; |
743
|
|
|
|
|
|
|
$return = $right * $left; #simple enough, just use the overloaded operator |
744
|
|
|
|
|
|
|
} |
745
|
|
|
|
|
|
|
# this code isn't being used is it? fuck i need better docs and tests |
746
|
|
|
|
|
|
|
# elsif ($self->{funcs}->isfunc($branch->[1][0])) |
747
|
|
|
|
|
|
|
# { |
748
|
|
|
|
|
|
|
# $left = $left->istype("Array") ? $left : new Language::Farnsworth::Value::Array([$left]); |
749
|
|
|
|
|
|
|
# $return = $self->{funcs}->callfunc($self, $branch->[1][0], $left); |
750
|
|
|
|
|
|
|
# |
751
|
|
|
|
|
|
|
# if ($rights->istype("String")) |
752
|
|
|
|
|
|
|
# { |
753
|
|
|
|
|
|
|
# #right side was a string, use it |
754
|
|
|
|
|
|
|
# my $nm = {%$return}; #do a shallow copy! |
755
|
|
|
|
|
|
|
# bless $nm, ref($return); #rebless it |
756
|
|
|
|
|
|
|
# $return->{outmagic} = [$nm, $rights]; |
757
|
|
|
|
|
|
|
# } |
758
|
|
|
|
|
|
|
# } |
759
|
|
|
|
|
|
|
else |
760
|
|
|
|
|
|
|
{ |
761
|
|
|
|
|
|
|
error "Conformance error, can't convert from ".($left->type($self))." to ".($right->type($self))."\n"; |
762
|
|
|
|
|
|
|
} |
763
|
|
|
|
|
|
|
} |
764
|
|
|
|
|
|
|
else |
765
|
|
|
|
|
|
|
{ |
766
|
|
|
|
|
|
|
#$right doesn't evaluate... so we check for a function? |
767
|
|
|
|
|
|
|
$left = $left->istype("Array") ? $left : new Language::Farnsworth::Value::Array([$left]); |
768
|
|
|
|
|
|
|
$return = $self->{funcs}->callfunc($self, $branch->[1][0], $left); |
769
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
if (defined($rights) && $rights->istype("String")) |
771
|
|
|
|
|
|
|
{ |
772
|
|
|
|
|
|
|
#right side was a string, use it |
773
|
|
|
|
|
|
|
my $nm = {%$return}; #do a shallow copy! |
774
|
|
|
|
|
|
|
bless $nm, ref($return); #rebless it |
775
|
|
|
|
|
|
|
$return->{outmagic} = [$nm, $rights]; |
776
|
|
|
|
|
|
|
} |
777
|
|
|
|
|
|
|
} |
778
|
|
|
|
|
|
|
} |
779
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
if (!defined($return)) |
781
|
|
|
|
|
|
|
{ |
782
|
|
|
|
|
|
|
#this creates a "true" undefined value for returning, this makes things funner! it also introduced a bug from naive coding above, which has been fixed |
783
|
|
|
|
|
|
|
$return = new Language::Farnsworth::Value::Undef(); |
784
|
|
|
|
|
|
|
} |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
return $return; |
787
|
|
|
|
|
|
|
} |
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
sub makevalue |
790
|
|
|
|
|
|
|
{ |
791
|
|
|
|
|
|
|
my $self = $_[0]; |
792
|
|
|
|
|
|
|
my $input = $_[1]; #switching from shift here, so that i can keep @_ intact for recursing |
793
|
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
# print "MAKEVALUE---------\n"; |
795
|
|
|
|
|
|
|
# print Dumper($input); |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
if (ref($input) eq "Num") |
798
|
|
|
|
|
|
|
{ |
799
|
|
|
|
|
|
|
#need to make a value here with Language::Farnsworth::Value! |
800
|
|
|
|
|
|
|
my $val = new Language::Farnsworth::Value::Pari($input->[0]); |
801
|
|
|
|
|
|
|
return $val; |
802
|
|
|
|
|
|
|
} |
803
|
|
|
|
|
|
|
if (ref($input) eq "HexNum") |
804
|
|
|
|
|
|
|
{ |
805
|
|
|
|
|
|
|
#need to make a value here with Language::Farnsworth::Value! |
806
|
|
|
|
|
|
|
#print "HEX VALUE: ".$input->[0]."\n"; |
807
|
|
|
|
|
|
|
#my $value = eval $input->[0]; #this SHOULD work, shouldn't be a security risk since its validated through the lexer and parser. |
808
|
|
|
|
|
|
|
my $val = new Language::Farnsworth::Value::Pari($input->[0],undef,undef,1); |
809
|
|
|
|
|
|
|
return $val; |
810
|
|
|
|
|
|
|
} |
811
|
|
|
|
|
|
|
elsif (ref($input) eq "Fetch") |
812
|
|
|
|
|
|
|
{ |
813
|
|
|
|
|
|
|
#this needs to decide between variable and unit, but that'll come later |
814
|
|
|
|
|
|
|
#esp since i also have to have this overridable for functions! |
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
my $name = $input->[0]; |
817
|
|
|
|
|
|
|
if ($self->{vars}->isvar($name)) |
818
|
|
|
|
|
|
|
{ |
819
|
|
|
|
|
|
|
return $self->{vars}->getvar($input->[0]); |
820
|
|
|
|
|
|
|
} |
821
|
|
|
|
|
|
|
elsif ($self->{units}->isunit($name)) |
822
|
|
|
|
|
|
|
{ |
823
|
|
|
|
|
|
|
#print "FETCH: $name\n" if ($name eq "milli"); |
824
|
|
|
|
|
|
|
return $self->{units}->getunit($name); |
825
|
|
|
|
|
|
|
} |
826
|
|
|
|
|
|
|
|
827
|
|
|
|
|
|
|
error "Undefined symbol '$name'\n"; |
828
|
|
|
|
|
|
|
} |
829
|
|
|
|
|
|
|
elsif (ref($input) eq "GetFunc") |
830
|
|
|
|
|
|
|
{ |
831
|
|
|
|
|
|
|
my $name = $input->[0]; |
832
|
|
|
|
|
|
|
if ($self->{funcs}->isfunc($name)) |
833
|
|
|
|
|
|
|
{ |
834
|
|
|
|
|
|
|
return $self->{funcs}->getfunc($name)->{lambda}; |
835
|
|
|
|
|
|
|
} |
836
|
|
|
|
|
|
|
else |
837
|
|
|
|
|
|
|
{ |
838
|
|
|
|
|
|
|
error "Undefined function '$name'"; |
839
|
|
|
|
|
|
|
} |
840
|
|
|
|
|
|
|
} |
841
|
|
|
|
|
|
|
elsif (ref($input) eq "String") #we've got a string that should be a value! |
842
|
|
|
|
|
|
|
{ |
843
|
|
|
|
|
|
|
my $value = $input->[0]; |
844
|
|
|
|
|
|
|
#here it comes in with quotes, so lets remove them |
845
|
|
|
|
|
|
|
#$value =~ s/^"(.*)"$/$1/; #no longer needed |
846
|
|
|
|
|
|
|
#$value =~ s/\\"/"/g; #i'm gonna move these into the constructor i think |
847
|
|
|
|
|
|
|
#$value =~ s/\\\\/\\/g; |
848
|
|
|
|
|
|
|
$value =~ s/\\(.)/qq("\\$1")/eeg; |
849
|
|
|
|
|
|
|
my $ss = sub |
850
|
|
|
|
|
|
|
{ |
851
|
|
|
|
|
|
|
my $var =shift; |
852
|
|
|
|
|
|
|
$var =~ s/^[\$]//; |
853
|
|
|
|
|
|
|
my $output = undef; |
854
|
|
|
|
|
|
|
if ($var !~ /^{.*}$/) |
855
|
|
|
|
|
|
|
{ |
856
|
|
|
|
|
|
|
$output = new Language::Farnsworth::Output($self->{units}, $self->{vars}->getvar($var), $self); |
857
|
|
|
|
|
|
|
} |
858
|
|
|
|
|
|
|
else |
859
|
|
|
|
|
|
|
{ |
860
|
|
|
|
|
|
|
$var =~ s/[{}]//g; |
861
|
|
|
|
|
|
|
$output = new Language::Farnsworth::Output($self->{units}, $self->eval($var), $self); |
862
|
|
|
|
|
|
|
} |
863
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
"".$output; |
865
|
|
|
|
|
|
|
}; |
866
|
|
|
|
|
|
|
$value =~ s/(?($1)/eg; |
867
|
|
|
|
|
|
|
my $val = new Language::Farnsworth::Value::String($value); |
868
|
|
|
|
|
|
|
return $val; |
869
|
|
|
|
|
|
|
} |
870
|
|
|
|
|
|
|
elsif (ref($input) eq "Date") |
871
|
|
|
|
|
|
|
{ |
872
|
|
|
|
|
|
|
#print "\n\n\nMaking DATE!\n\n\n"; |
873
|
|
|
|
|
|
|
my $val = new Language::Farnsworth::Value::Date($input->[0]); |
874
|
|
|
|
|
|
|
# print Dumper($val); |
875
|
|
|
|
|
|
|
return $val; |
876
|
|
|
|
|
|
|
} |
877
|
|
|
|
|
|
|
elsif (ref($input) eq "VarArg") |
878
|
|
|
|
|
|
|
{ |
879
|
|
|
|
|
|
|
#warn "Got a VarArg, code untested, want to mark when i get them\n"; #just so i can track down the inevitable crash |
880
|
|
|
|
|
|
|
return "VarArg"; |
881
|
|
|
|
|
|
|
} |
882
|
|
|
|
|
|
|
elsif (ref($input) =~ /Language::Farnsworth::Value/) |
883
|
|
|
|
|
|
|
{ |
884
|
|
|
|
|
|
|
debug 5, "Got a Language::Farnsworth::Value::*, i PROBABLY shouldn't be getting these, i'm just going to let it fall through"; |
885
|
|
|
|
|
|
|
return $input; |
886
|
|
|
|
|
|
|
} |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
#return $self->evalbranch($input); |
889
|
|
|
|
|
|
|
goto &evalbranch; #EVIL GOTO! but might save a stack frame! OMG! |
890
|
|
|
|
|
|
|
} |
891
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
1; |
893
|
|
|
|
|
|
|
__END__ |