UNPKG

20.4 kBtext/coffeescriptView Raw
1
2
3Eval_simplify = ->
4 push(cadr(p1))
5 runUserDefinedSimplifications()
6 Eval()
7 simplify()
8
9runUserDefinedSimplifications = ->
10 # -----------------------
11 # unfortunately for the time being user
12 # specified simplifications are only
13 # run in things which don't contain
14 # integrals.
15 # Doesn't work yet, could be because of
16 # some clobbering as "transform" is called
17 # recursively?
18 if userSimplificationsInListForm.length != 0 and !Find(cadr(p1), symbol(INTEGRAL))
19 originalexpanding = expanding
20 expanding = false
21 if DEBUG then console.log("runUserDefinedSimplifications passed: " + stack[tos-1].toString())
22 Eval()
23 if DEBUG then console.log("runUserDefinedSimplifications after eval no expanding: " + stack[tos-1].toString())
24 expanding = originalexpanding
25
26
27 p1 = stack[tos-1]
28
29 if DEBUG then console.log "patterns to be checked: "
30 for eachSimplification in userSimplificationsInListForm
31 if DEBUG then console.log "..." + eachSimplification
32
33 atLeastOneSuccessInRouldOfRulesApplications = true
34 numberOfRulesApplications = 0
35
36
37 while atLeastOneSuccessInRouldOfRulesApplications and numberOfRulesApplications < MAX_CONSECUTIVE_APPLICATIONS_OF_ALL_RULES
38 atLeastOneSuccessInRouldOfRulesApplications = false
39 numberOfRulesApplications++
40 for eachSimplification in userSimplificationsInListForm
41 success = true
42 eachConsecutiveRuleApplication = 0
43 while success and eachConsecutiveRuleApplication < MAX_CONSECUTIVE_APPLICATIONS_OF_SINGLE_RULE
44 eachConsecutiveRuleApplication++
45 if DEBUG then console.log "simplify - tos: " + tos + " checking pattern: " + eachSimplification + " on: " + p1
46 push_symbol(NIL)
47 success = transform(eachSimplification, true)
48 if success
49 atLeastOneSuccessInRouldOfRulesApplications = true
50 p1 = stack[tos-1]
51 if DEBUG then console.log "p1 at this stage of simplification: " + p1
52 if eachConsecutiveRuleApplication == MAX_CONSECUTIVE_APPLICATIONS_OF_SINGLE_RULE
53 stop("maximum application of single transformation rule exceeded: " + eachSimplification)
54
55 if numberOfRulesApplications == MAX_CONSECUTIVE_APPLICATIONS_OF_ALL_RULES
56 stop("maximum application of all transformation rules exceeded ")
57
58 if DEBUG
59 console.log "METAX = " + get_binding(symbol(METAX))
60 console.log "METAA = " + get_binding(symbol(METAA))
61 console.log "METAB = " + get_binding(symbol(METAB))
62
63 # ------------------------
64
65simplifyForCodeGeneration = ->
66 save()
67 runUserDefinedSimplifications()
68 codeGen = true
69 # in "codeGen" mode we completely
70 # eval and simplify the function bodies
71 # because we really want to resolve all
72 # the variables indirections and apply
73 # all the simplifications we can.
74 simplify_main()
75 codeGen = false
76 restore()
77
78simplify = ->
79 save()
80 simplify_main()
81 restore()
82
83simplify_main = ->
84 p1 = pop()
85
86 # when we do code generation, we proceed to
87 # fully evaluate and simplify the body of
88 # a function, so we resolve all variables
89 # indirections and we simplify everything
90 # we can given the current assignments.
91 if codeGen and car(p1) == symbol(FUNCTION)
92 fbody = cadr(p1)
93 push fbody
94 # let's simplify the body so we give it a
95 # compact form
96 eval()
97 simplify()
98 p3 = pop()
99
100 # replace the evaled body
101 args = caddr(p1); # p5 is B
102
103 push_symbol(FUNCTION)
104 push p3
105 push args
106 list(3)
107 p1 = pop()
108
109 if (istensor(p1))
110 simplify_tensor()
111 return
112
113 if (Find(p1, symbol(FACTORIAL)))
114 push(p1)
115 simfac()
116 p2 = pop()
117 push(p1)
118 rationalize()
119 simfac()
120 p3 = pop()
121 if (count(p2) < count(p3))
122 p1 = p2
123 else
124 p1 = p3
125
126 f10()
127 f1()
128 f2()
129 f3()
130 f4()
131 f5()
132 f9()
133 simplify_polarRect()
134 if do_simplify_nested_radicals
135 # if there is some de-nesting then
136 # re-run a simplification because
137 # the shape of the expression might
138 # have changed significantly.
139 # e.g. simplify(14^(1/2) - (16 - 4*7^(1/2))^(1/2))
140 # needs some more semplification after the de-nesting.
141 if simplify_nested_radicals()
142 if DEBUG then console.log("de-nesting successful into: " + p1.toString())
143 push(p1)
144 simplify()
145 return
146
147 simplify_rectToClock()
148
149 push(p1)
150
151simplify_tensor = ->
152 i = 0
153 p2 = alloc_tensor(p1.tensor.nelem)
154 p2.tensor.ndim = p1.tensor.ndim
155 for i in [0...p1.tensor.ndim]
156 p2.tensor.dim[i] = p1.tensor.dim[i]
157 for i in [0...p1.tensor.nelem]
158 push(p1.tensor.elem[i])
159 simplify()
160 p2.tensor.elem[i] = pop()
161
162 check_tensor_dimensions p2
163
164 if (iszero(p2))
165 p2 = zero; # null tensor becomes scalar zero
166 push(p2)
167
168
169# try rationalizing
170
171f1 = ->
172 if (car(p1) != symbol(ADD))
173 return
174 push(p1)
175 rationalize()
176 p2 = pop()
177 if (count(p2) < count(p1))
178 p1 = p2
179
180# try condensing
181
182f2 = ->
183 if (car(p1) != symbol(ADD))
184 return
185 push(p1)
186 Condense()
187 p2 = pop()
188 if (count(p2) <= count(p1))
189 p1 = p2
190
191# this simplifies forms like (A-B) / (B-A)
192
193f3 = ->
194 push(p1)
195 rationalize()
196 negate()
197 rationalize()
198 negate()
199 rationalize()
200 p2 = pop()
201 if (count(p2) < count(p1))
202 p1 = p2
203
204
205f10 = ->
206
207 carp1 = car(p1)
208 miao = cdr(p1)
209 if ( carp1 == symbol(MULTIPLY) || isinnerordot(p1))
210 # both operands a transpose?
211
212 if (car(car(cdr(p1))) == symbol(TRANSPOSE)) and (car(car(cdr(cdr(p1)))) == symbol(TRANSPOSE))
213 if DEBUG then console.log "maybe collecting a transpose " + p1
214 a = cadr(car(cdr(p1)))
215 b = cadr(car(cdr(cdr(p1))))
216 if carp1 == symbol(MULTIPLY)
217 push(a)
218 push(b)
219 multiply()
220 else if isinnerordot(p1)
221 push(b)
222 push(a)
223 inner()
224 push_integer(1)
225 push_integer(2)
226 originalexpanding = expanding
227 expanding = false
228 transpose()
229 expanding = originalexpanding
230
231 p2 = pop()
232 if (count(p2) < count(p1))
233 p1 = p2
234 if DEBUG then console.log "collecting a transpose " + p2
235
236# try expanding denominators
237
238f4 = ->
239 if (iszero(p1))
240 return
241 push(p1)
242 rationalize()
243 inverse()
244 rationalize()
245 inverse()
246 rationalize()
247 p2 = pop()
248 if (count(p2) < count(p1))
249 p1 = p2
250
251# simplifies trig forms
252
253simplify_trig = ->
254 save()
255 p1 = pop()
256 f5()
257 push(p1)
258 restore()
259
260f5 = ->
261 if (Find(p1, symbol(SIN)) == 0 && Find(p1, symbol(COS)) == 0)
262 return
263
264 p2 = p1
265
266 trigmode = 1
267 push(p2)
268 Eval()
269 p3 = pop()
270
271 trigmode = 2
272 push(p2)
273 Eval()
274 p4 = pop()
275
276 trigmode = 0
277
278 if (count(p4) < count(p3) || nterms(p4) < nterms(p3))
279 p3 = p4
280
281 if (count(p3) < count(p1) || nterms(p3) < nterms(p1))
282 p1 = p3
283
284# if it's a sum then try to simplify each term
285
286f9 = ->
287 if (car(p1) != symbol(ADD))
288 return
289 push_integer(0)
290 p2 = cdr(p1)
291 while (iscons(p2))
292 push(car(p2))
293 simplify()
294 add()
295 p2 = cdr(p2)
296 p2 = pop()
297 if (count(p2) < count(p1))
298 p1 = p2
299
300# things like 6*(cos(2/9*pi)+i*sin(2/9*pi))
301# where we have sin and cos, those might start to
302# look better in clock form i.e. 6*(-1)^(2/9)
303simplify_rectToClock = ->
304 #debugger
305
306 if (Find(p1, symbol(SIN)) == 0 && Find(p1, symbol(COS)) == 0)
307 return
308
309 push(p1)
310 Eval()
311 clockform()
312
313 p2 = pop(); # put new (hopefully simplified expr) in p2
314 if DEBUG then console.log "before simplification clockform: " + p1 + " after: " + p2
315
316 if (count(p2) < count(p1))
317 p1 = p2
318
319simplify_polarRect = ->
320 push(p1)
321
322 polarRectAMinusOneBase()
323 Eval()
324
325 p2 = pop(); # put new (hopefully simplified expr) in p2
326
327 if (count(p2) < count(p1))
328 p1 = p2
329
330polarRectAMinusOneBase = ->
331 save()
332 p1 = pop()
333
334 if isimaginaryunit(p1)
335 push(p1)
336 restore()
337 return
338
339 if (equal(car(p1), symbol(POWER)) and isminusone(cadr(p1)) )
340
341 # base we just said is minus 1
342 push(one)
343 negate()
344
345 # exponent
346 push(caddr(p1))
347 polarRectAMinusOneBase()
348
349 power()
350 # try to simplify it using polar and rect
351 polar()
352 rect()
353
354 else if (iscons(p1))
355 h = tos
356 while (iscons(p1))
357 #console.log("recursing on: " + car(p1).toString())
358 push(car(p1))
359 polarRectAMinusOneBase()
360 #console.log("...transformed into: " + stack[tos-1].toString())
361 p1 = cdr(p1)
362 list(tos - h)
363 else
364 push(p1)
365
366 restore()
367 return
368
369nterms = (p) ->
370 if (car(p) != symbol(ADD))
371 return 1
372 else
373 return length(p) - 1
374
375simplify_nested_radicals = ->
376 if recursionLevelNestedRadicalsRemoval > 0
377 if DEBUG then console.log("denesting bailing out because of too much recursion")
378 return false
379
380 push(p1)
381 somethingSimplified = take_care_of_nested_radicals()
382
383
384 # in this paragraph we check whether we can collect
385 # common factors without complicating the expression
386 # in particular we want to avoid
387 # collecting radicals like in this case where
388 # we collect sqrt(2):
389 # 2-2^(1/2) into 2^(1/2)*(-1+2^(1/2))
390 # but we do like to collect other non-radicals e.g.
391 # 17/2+3/2*5^(1/2) into 1/2*(17+3*5^(1/2))
392 # so what we do is we count the powers and we check
393 # which version has the least number of them.
394 simplificationWithoutCondense = stack[tos-1]
395
396 prev_expanding = expanding
397 expanding = 0
398 yycondense()
399 expanding = prev_expanding
400
401 simplificationWithCondense = pop()
402 #console.log("occurrences of powers in " + simplificationWithoutCondense + " :" + countOccurrencesOfSymbol(symbol(POWER),simplificationWithoutCondense))
403 #console.log("occurrences of powers in " + simplificationWithCondense + " :" + countOccurrencesOfSymbol(symbol(POWER),simplificationWithCondense))
404
405 if (countOccurrencesOfSymbol(symbol(POWER),simplificationWithoutCondense) < countOccurrencesOfSymbol(symbol(POWER),simplificationWithCondense))
406 push(simplificationWithoutCondense)
407 else
408 push(simplificationWithCondense)
409
410
411 # we got out result, wrap up
412 p1 = pop()
413 return somethingSimplified
414
415take_care_of_nested_radicals = ->
416 if recursionLevelNestedRadicalsRemoval > 0
417 if DEBUG then console.log("denesting bailing out because of too much recursion")
418 return false
419
420
421 save()
422 p1 = pop()
423 #console.log("take_care_of_nested_radicals p1: " + p1.toString())
424
425 if equal(car(p1), symbol(POWER))
426
427 #console.log("ok it's a power ")
428 base = cadr(p1)
429 exponent = caddr(p1)
430 #console.log("possible double radical base: " + base)
431 #console.log("possible double radical exponent: " + exponent)
432
433 if !isminusone(exponent) and equal(car(base), symbol(ADD)) and isfraction(exponent) and (equalq(exponent,1,3) or equalq(exponent,1,2))
434
435 #console.log("ok there is a radix with a term inside")
436 firstTerm = cadr(base)
437 push(firstTerm)
438 take_care_of_nested_radicals()
439 pop()
440 secondTerm = caddr(base)
441 push(secondTerm)
442 take_care_of_nested_radicals()
443 pop()
444
445 #console.log("possible double radical term1: " + firstTerm)
446 #console.log("possible double radical term2: " + secondTerm)
447
448 numberOfTerms = 0
449 countingTerms = base
450 while (cdr(countingTerms) != symbol(NIL))
451 numberOfTerms++
452 countingTerms = cdr(countingTerms)
453 #console.log("number of terms: " + numberOfTerms)
454 if numberOfTerms > 2
455 #console.log("too many terms under outer radix ")
456 push(p1)
457 restore()
458 return false
459
460
461 # list here all the factors
462 commonInnerExponent = null
463 commonBases = []
464 termsThatAreNotPowers = []
465 if (car(secondTerm) == symbol(MULTIPLY))
466 # product of factors
467 secondTermFactor = cdr(secondTerm)
468 if iscons(secondTermFactor)
469 while (iscons(secondTermFactor))
470 #console.log("second term factor BIS: " + car(secondTermFactor).toString())
471 potentialPower = car(secondTermFactor)
472 if (car(potentialPower) == symbol(POWER))
473 innerbase = cadr(potentialPower)
474 innerexponent = caddr(potentialPower)
475 if equalq(innerexponent,1,2)
476 #console.log("tackling double radical 1: " + p1.toString())
477 if !commonInnerExponent?
478 commonInnerExponent = innerexponent
479 commonBases.push(innerbase)
480 else
481 if equal(innerexponent, commonInnerExponent)
482 #console.log("common base: " + innerbase.toString())
483 commonBases.push(innerbase)
484 else
485 #console.log("no common bases here ")
486 #console.log("this one is a power base: " + innerbase + " , exponent: " + innerexponent)
487 else
488 termsThatAreNotPowers.push(potentialPower)
489 secondTermFactor = cdr(secondTermFactor)
490 else if (car(secondTerm) == symbol(POWER))
491 innerbase = cadr(secondTerm)
492 innerexponent = caddr(secondTerm)
493 if !commonInnerExponent? and equalq(innerexponent,1,2)
494 #console.log("tackling double radical 2: " + p1.toString())
495 commonInnerExponent = innerexponent
496 commonBases.push(innerbase)
497
498
499 if commonBases.length == 0
500 push(p1)
501 restore()
502 return false
503
504 A = firstTerm
505 #console.log("A: " + A.toString())
506
507 push_integer(1)
508 for i in commonBases
509 push(i)
510 multiply()
511 #console.log("basis with common exponent: " + i.toString())
512 C = pop()
513 #console.log("C: " + C.toString())
514
515 push_integer(1)
516 for i in termsThatAreNotPowers
517 push(i)
518 multiply()
519 #console.log("terms that are not powers: " + i.toString())
520 B = pop()
521 #console.log("B: " + B.toString())
522
523
524 if equalq(exponent,1,3)
525 push(A)
526 negate()
527 push(C)
528 multiply()
529 push(B)
530 divide() # 4th coeff
531 #console.log("constant coeff " + stack[tos-1].toString())
532 checkSize = pop()
533 push(checkSize)
534 real()
535 yyfloat()
536 if Math.abs(pop().d) > Math.pow(2, 32)
537 push(p1)
538 restore()
539 return false
540 push(checkSize)
541
542 push_integer(3)
543 push(C)
544 multiply() # 3rd coeff
545 #console.log("next coeff " + stack[tos-1].toString())
546 checkSize = pop()
547 push(checkSize)
548 real()
549 yyfloat()
550 if Math.abs(pop().d) > Math.pow(2, 32)
551 pop()
552 push(p1)
553 restore()
554 return false
555 push(checkSize)
556
557 push(symbol(SECRETX))
558 multiply()
559
560
561 push_integer(-3)
562 push(A)
563 multiply()
564 push(B)
565 divide() # 2nd coeff
566 checkSize = pop()
567 push(checkSize)
568 real()
569 yyfloat()
570 if Math.abs(pop().d) > Math.pow(2, 32)
571 pop()
572 pop()
573 push(p1)
574 restore()
575 return false
576 push(checkSize)
577
578 #console.log("next coeff " + stack[tos-1].toString())
579 push(symbol(SECRETX))
580 push_integer(2)
581 power()
582 multiply()
583
584 push_integer(1) # 1st coeff
585 #console.log("next coeff " + stack[tos-1].toString())
586 push(symbol(SECRETX))
587 push_integer(3)
588 power()
589 multiply()
590
591 add()
592 add()
593 add()
594
595 else if equalq(exponent,1,2)
596 push(C) # 3th coeff
597 checkSize = pop()
598 push(checkSize)
599 real()
600 yyfloat()
601 if Math.abs(pop().d) > Math.pow(2, 32)
602 push(p1)
603 restore()
604 return false
605 push(checkSize)
606 #console.log("constant coeff " + stack[tos-1].toString())
607
608 push_integer(-2)
609 push(A)
610 multiply()
611 push(B)
612 divide() # 2nd coeff
613 checkSize = pop()
614 push(checkSize)
615 real()
616 yyfloat()
617 if Math.abs(pop().d) > Math.pow(2, 32)
618 pop()
619 push(p1)
620 restore()
621 return false
622 push(checkSize)
623
624 #console.log("next coeff " + stack[tos-1].toString())
625 push(symbol(SECRETX))
626 multiply()
627
628
629 push_integer(1) # 1st coeff
630 #console.log("next coeff " + stack[tos-1].toString())
631 push(symbol(SECRETX))
632 push_integer(2)
633 power()
634 multiply()
635
636 add()
637 add()
638
639 #console.log("whole polynomial: " + stack[tos-1].toString())
640
641 push(symbol(SECRETX))
642
643
644 recursionLevelNestedRadicalsRemoval++
645 #console.log("invoking roots at recursion level: " + recursionLevelNestedRadicalsRemoval)
646 roots()
647 recursionLevelNestedRadicalsRemoval--
648 if equal(stack[tos-1], symbol(NIL))
649 if DEBUG then console.log("roots bailed out because of too much recursion")
650 pop()
651 push(p1)
652 restore()
653 return false
654
655 #console.log("all solutions: " + stack[tos-1].toString())
656
657 # exclude the solutions with radicals
658 possibleSolutions = []
659 for eachSolution in stack[tos-1].tensor.elem
660 if !Find(eachSolution, symbol(POWER))
661 possibleSolutions.push(eachSolution)
662
663 pop() # popping the tensor with the solutions
664
665 #console.log("possible solutions: " + possibleSolutions.toString())
666 if possibleSolutions.length == 0
667 push(p1)
668 restore()
669 return false
670
671 possibleRationalSolutions = []
672 realOfpossibleRationalSolutions = []
673 #console.log("checking the one with maximum real part ")
674 for i in possibleSolutions
675 push(i)
676 real()
677 yyfloat()
678 possibleRationalSolutions.push(i)
679 realOfpossibleRationalSolutions.push(pop().d)
680
681 whichRationalSolution = realOfpossibleRationalSolutions.indexOf(Math.max.apply(Math, realOfpossibleRationalSolutions))
682 SOLUTION = possibleRationalSolutions[whichRationalSolution]
683 #console.log("picked solution: " + SOLUTION)
684
685
686 ###
687 #possibleNewExpressions = []
688 #realOfPossibleNewExpressions = []
689 # pick the solution which cubic root has no radicals
690 lowercase_b = null
691 for SOLUTION in possibleSolutions
692 console.log("testing solution: " + SOLUTION.toString())
693
694 debugger
695 if equalq(exponent,1,3)
696 push(A)
697 push(SOLUTION)
698 push_integer(3)
699 power()
700 push_integer(3)
701 push(C)
702 multiply()
703 push(SOLUTION)
704 multiply()
705 add()
706 divide()
707 console.log("argument of cubic root: " + stack[tos-1].toString())
708 push_rational(1,3)
709 power()
710 else if equalq(exponent,1,2)
711 push(A)
712 push(SOLUTION)
713 push_integer(2)
714 power()
715 push(C)
716 add()
717 divide()
718 console.log("argument of cubic root: " + stack[tos-1].toString())
719 push_rational(1,2)
720 power()
721 console.log("b is: " + stack[tos-1].toString())
722
723 lowercase_b = pop()
724
725 if !Find(lowercase_b, symbol(POWER))
726 break
727 ###
728
729 if equalq(exponent,1,3)
730 push(A)
731 push(SOLUTION)
732 push_integer(3)
733 power()
734 push_integer(3)
735 push(C)
736 multiply()
737 push(SOLUTION)
738 multiply()
739 add()
740 divide()
741 #console.log("argument of cubic root: " + stack[tos-1].toString())
742 push_rational(1,3)
743 power()
744 else if equalq(exponent,1,2)
745 push(A)
746 push(SOLUTION)
747 push_integer(2)
748 power()
749 push(C)
750 add()
751 divide()
752 #console.log("argument of cubic root: " + stack[tos-1].toString())
753 push_rational(1,2)
754 power()
755 #console.log("b is: " + stack[tos-1].toString())
756
757 lowercase_b = pop()
758
759
760 if !lowercase_b?
761 push(p1)
762 restore()
763 return false
764
765 push(lowercase_b)
766 push(SOLUTION)
767 multiply()
768
769
770 if equalq(exponent,1,3)
771 #console.log("a is: " + stack[tos-1].toString())
772
773 lowercase_a = pop()
774
775 push(lowercase_b)
776 push(C)
777 push_rational(1,2)
778 power()
779 multiply()
780
781 push(lowercase_a)
782 add()
783 simplify()
784 else if equalq(exponent,1,2)
785 #console.log("a could be: " + stack[tos-1].toString())
786
787 lowercase_a = pop()
788
789 push(lowercase_b)
790 push(C)
791 push_rational(1,2)
792 power()
793 multiply()
794
795 push(lowercase_a)
796 add()
797 simplify()
798 possibleNewExpression = pop()
799 #console.log("verifying if " + possibleNewExpression + " is positive")
800 push(possibleNewExpression)
801 real()
802 yyfloat()
803 possibleNewExpressionValue = pop()
804 if !isnegativenumber(possibleNewExpressionValue)
805 #console.log("... it is positive")
806 push(possibleNewExpression)
807 else
808 #console.log("... it is NOT positive")
809 push(lowercase_b)
810 negate()
811 lowercase_b = pop()
812
813 push(lowercase_a)
814 negate()
815 lowercase_a = pop()
816
817
818 push(lowercase_b)
819 push(C)
820 push_rational(1,2)
821 power()
822 multiply()
823
824 push(lowercase_a)
825 add()
826 simplify()
827 # possibleNewExpression is now at top of stack
828
829
830 #console.log("potential new expression: " + stack[tos-1].toString())
831 p1 = pop()
832 #newExpression = pop()
833 #debugger
834 #push(newExpression)
835 #real()
836 #yyfloat()
837 #possibleNewExpressions.push(newExpression)
838 #realOfPossibleNewExpressions.push(pop().d)
839
840 #whichExpression = realOfPossibleNewExpressions.indexOf(Math.max.apply(Math, realOfPossibleNewExpressions))
841 #p1 = possibleNewExpressions[whichExpression]
842 #console.log("final new expression: " + p1.toString())
843
844 push(p1)
845 restore()
846 return true
847
848
849
850 else
851 push(p1)
852 restore()
853 return false
854
855 else if (iscons(p1))
856 h = tos
857 anyRadicalSimplificationWorked = false
858 while (iscons(p1))
859 #console.log("recursing on: " + car(p1).toString())
860 push(car(p1))
861 anyRadicalSimplificationWorked = anyRadicalSimplificationWorked or take_care_of_nested_radicals()
862 #console.log("...transformed into: " + stack[tos-1].toString())
863 p1 = cdr(p1)
864 list(tos - h)
865 restore()
866 return anyRadicalSimplificationWorked
867 else
868 push(p1)
869 restore()
870 return false
871
872 throw new Error("control flow should never reach here")