|
28 | 28 | import java.io.ByteArrayOutputStream; |
29 | 29 | import java.io.ObjectInputStream; |
30 | 30 | import java.io.ObjectOutputStream; |
| 31 | +import java.io.Serializable; |
31 | 32 | import java.util.ArrayList; |
32 | 33 | import java.util.Arrays; |
33 | 34 | import java.util.HashMap; |
|
40 | 41 |
|
41 | 42 | //var parseSignature = require('./signature'); |
42 | 43 | @SuppressWarnings({"unchecked"}) |
43 | | -public class Parser { |
| 44 | +public class Parser implements Serializable { |
44 | 45 |
|
45 | 46 | boolean dbg = false; |
46 | 47 |
|
@@ -92,7 +93,7 @@ public static<T> T clone(T object) { |
92 | 93 | } |
93 | 94 | } |
94 | 95 |
|
95 | | - public class Symbol implements Cloneable { |
| 96 | + public class Symbol implements Cloneable, Serializable { |
96 | 97 |
|
97 | 98 | //Symbol s; |
98 | 99 | String id; |
@@ -505,7 +506,7 @@ public Parser() { |
505 | 506 | c.value = "("; |
506 | 507 | Symbol p = new Symbol(); |
507 | 508 | c.procedure = p; p.type = "variable"; p.value = "exists"; |
508 | | - c.arguments = List.of(left); |
| 509 | + c.arguments = List.of(Parser.clone(left)); |
509 | 510 | } |
510 | 511 | this.then = left; |
511 | 512 | this._else = expression(0); |
@@ -812,7 +813,12 @@ Symbol led(Symbol left) { |
812 | 813 |
|
813 | 814 | @Override Symbol led(Symbol left) { |
814 | 815 | this.type = "condition"; |
815 | | - this.condition = left; |
| 816 | + // Deep-clone `left` so the condition and then branches have |
| 817 | + // independent AST nodes. Sharing the same reference causes |
| 818 | + // post-parse processing (e.g. predicate stages, unary minus |
| 819 | + // folding on number literals) to mutate the same node twice, |
| 820 | + // producing wrong results (see #773 for the equivalent ?? fix). |
| 821 | + this.condition = Parser.clone(left); |
816 | 822 | this.then = left; |
817 | 823 | this._else = expression(0); |
818 | 824 | return this; |
|
0 commit comments