@@ -33,6 +33,8 @@ static SmtTerm deserialize(Object termDtoRaw) throws DeserializationException {
3333 case "application" -> deserializeApplication (termDto ); // a function application
3434 case "exists" -> deserializeQuantifier (termDto , Quantifier .Type .EXISTS ); // an existential quantifier
3535 case "forall" -> deserializeQuantifier (termDto , Quantifier .Type .FOR_ALL ); // a universal quantifier
36+ case "lambda" -> deserializeLambda (termDto ); // a lambda abstraction
37+ case "match" -> deserializeMatch (termDto ); // a pattern matching expression
3638 case "variable" -> deserializeVariable (termDto ); // a variable
3739 case "bitvector" -> deserializeBitVector (termDto ); // a bit vector
3840 default -> throw new DeserializationException (
@@ -132,6 +134,44 @@ private static SmtTerm deserializeQuantifier(JSONObject termDto, Quantifier.Type
132134 return new Quantifier (qType , Arrays .asList (bindings ), child );
133135 }
134136
137+ /**
138+ * Deserializes a lambda abstraction.
139+ *
140+ * @param termDto The JSON representation of the lambda abstraction.
141+ * @return The deserialized lambda abstraction.
142+ * @throws DeserializationException If {@code termDto} is not a valid representation of lambda abstraction.
143+ */
144+ private static SmtTerm deserializeLambda (JSONObject termDto ) throws DeserializationException {
145+ return new Lambda (JsonUtils .getStrings (termDto , "arguments" ), deserializeAt (termDto , "body" ));
146+ }
147+
148+ /**
149+ * Deserializes a pattern-matching expression.
150+ *
151+ * @param termDto The JSON representation of the pattern-matching expression.
152+ * @return The deserialized pattern-matching expression.
153+ * @throws DeserializationException If {@code termDto} is not a valid representation of a pattern match.
154+ */
155+ private static SmtTerm deserializeMatch (JSONObject termDto ) throws DeserializationException {
156+ SmtTerm matchTerm = deserializeAt (termDto , "term" );
157+ List <JSONObject > casesDto = JsonUtils .getObjects (termDto , "binders" );
158+
159+ Match .Case [] cases = new Match .Case [casesDto .size ()];
160+ for (int i = 0 ; i < cases .length ; i ++) {
161+ JSONObject caseDto = casesDto .get (i );
162+ try {
163+ cases [i ] = new Match .Case (
164+ JsonUtils .getString (caseDto , "operator" ),
165+ JsonUtils .getStrings (caseDto , "arguments" ),
166+ deserializeAt (caseDto , "child" ));
167+ } catch (DeserializationException e ) {
168+ throw e .prepend ("binders." + i );
169+ }
170+ }
171+
172+ return new Match (matchTerm , Arrays .asList (cases ));
173+ }
174+
135175 /**
136176 * Deserializes a variable.
137177 *
@@ -229,10 +269,7 @@ record Application(Identifier name, Identifier returnType, List<TypedTerm> argum
229269
230270 @ Override
231271 public String toString () {
232- if (arguments .size () == 0 ) {
233- return "(" + name + ")" ;
234- }
235- return String .format ("(%s %s)" ,
272+ return arguments .isEmpty () ? name .toString () : String .format ("(%s %s)" ,
236273 name , arguments .stream ().map (TypedTerm ::toString ).collect (Collectors .joining (" " )));
237274 }
238275
@@ -269,43 +306,94 @@ public enum Type {
269306 /**
270307 * The existential quantifier.
271308 */
272- EXISTS ("∃" ),
309+ EXISTS ("∃" , "exists" ),
273310
274311 /**
275312 * The universal quantifier.
276313 */
277- FOR_ALL ("∀" );
314+ FOR_ALL ("∀" , "forall" );
278315
279316 /**
280317 * The symbol representing the quantifier.
281318 */
282- public final String symbol ;
319+ public final String symbol , name ;
283320
284321 /**
285322 * Constructs a quantifier type.
286323 *
287324 * @param symbol The symbol representing the quantifier.
288325 */
289- Type (String symbol ) {
326+ Type (String symbol , String name ) {
290327 this .symbol = symbol ;
328+ this .name = name ;
291329 }
292330
293331 @ Override
294332 public String toString () {
295- return symbol ;
333+ return name ;
296334 }
297335 }
298336
299337 @ Override
300338 public String toString () {
301339 return String .format ("(%s (%s) %s)" ,
302340 type ,
303- bindings .stream ().map (TypedVar ::toStringSExpr ).collect (Collectors .joining (" " )),
341+ bindings .stream ().map (TypedVar ::toString ).collect (Collectors .joining (" " )),
304342 child );
305343 }
306344
307345 }
308346
347+ /**
348+ * Represents a lambda abstraction in an SMT formula.
349+ *
350+ * @param arguments The names of the lambda arguments. Beware of conflicts with variables in the outer context!
351+ * @param body The body of the lambda term, which may contain the arguments as bound variables.
352+ */
353+ record Lambda (List <String > arguments , SmtTerm body ) implements SmtTerm {
354+
355+ @ Override
356+ public String toString () {
357+ return String .format ("(lambda (%s) %s)" , String .join (" " , arguments ), body );
358+ }
359+
360+ }
361+
362+ /**
363+ * Represents a pattern-matching expression in an SMT formula. Used to match against constructors for inductive
364+ * types as defined by {@link org.semgus.java.event.SmtSpecEvent.DefineDatatypeEvent}.
365+ *
366+ * @param matchTerm The term being matched on.
367+ * @param cases The match cases.
368+ */
369+ record Match (SmtTerm matchTerm , List <Case > cases ) implements SmtTerm {
370+
371+ @ Override
372+ public String toString () {
373+ return String .format ("(match %s (%s))" ,
374+ matchTerm ,
375+ cases .stream ().map (Case ::toString ).collect (Collectors .joining (" " )));
376+ }
377+
378+ /**
379+ * A match case in a {@link Match} pattern-matching expression.
380+ *
381+ * @param opName The name of the operator to match against.
382+ * @param arguments The names to which the operator's arguments should be bound in the result term.
383+ * @param result The match result.
384+ */
385+ public record Case (String opName , List <String > arguments , SmtTerm result ) {
386+
387+ @ Override
388+ public String toString () {
389+ return arguments .isEmpty () ? String .format ("(%s %s)" , opName , result )
390+ : String .format ("((%s %s) %s)" , opName , String .join (" " , arguments ), result );
391+ }
392+
393+ }
394+
395+ }
396+
309397 /**
310398 * Represents a variable in an SMT formula.
311399 *
@@ -359,11 +447,11 @@ record CBitVector(int size, BitSet value) implements SmtTerm {
359447
360448 @ Override
361449 public String toString () {
362- StringBuilder sb = new StringBuilder ("< " );
450+ StringBuilder sb = new StringBuilder ("#b " );
363451 for (int i = size - 1 ; i >= 0 ; i --) {
364452 sb .append (value .get (i ) ? '1' : '0' );
365453 }
366- return sb .append ( ">" ). toString ();
454+ return sb .toString ();
367455 }
368456
369457 }
0 commit comments