Skip to content

Commit fbdcc31

Browse files
committed
Use generalized keyword expression sugar in unparsers
1 parent 2c940d3 commit fbdcc31

File tree

2 files changed

+56
-9
lines changed

2 files changed

+56
-9
lines changed

src/language/compiling/unparsing.test.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,7 @@ testCases(
8686
},
8787
},
8888
},
89-
either.makeRight(
90-
'{ "@runtime", { context => :context.program.start_time } }',
91-
),
89+
either.makeRight('@runtime { context => :context.program.start_time }'),
9290
],
9391
[
9492
{
@@ -182,9 +180,7 @@ testCases(
182180
},
183181
},
184182
},
185-
either.makeRight(
186-
'{\n "@runtime"\n {\n context => :context.program.start_time\n }\n}',
187-
),
183+
either.makeRight('@runtime {\n context => :context.program.start_time\n}'),
188184
],
189185
[
190186
{

src/language/unparsing/plz-utilities.ts

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ import type { UnserializableValueError } from '../errors.js'
55
import type { Atom, Molecule } from '../parsing.js'
66
import { unquotedAtomParser } from '../parsing/atom.js'
77
import {
8+
isExpression,
89
isSemanticGraph,
910
readApplyExpression,
1011
readFunctionExpression,
1112
readIndexExpression,
1213
readLookupExpression,
1314
serialize,
1415
type ApplyExpression,
16+
type Expression,
1517
type FunctionExpression,
1618
type IndexExpression,
1719
type KeyPath,
@@ -55,7 +57,19 @@ export const moleculeUnparser =
5557
unparseSugaredLookup(lookupExpression, unparseAtomOrMolecule),
5658
})
5759
default:
58-
return unparseSugarFreeMolecule(value, unparseAtomOrMolecule)
60+
if (isExpression(value)) {
61+
const result = unparseSugaredGeneralizedKeywordExpression(
62+
value,
63+
unparseAtomOrMolecule,
64+
)
65+
if (either.isLeft(result)) {
66+
return unparseSugarFreeMolecule(value, unparseAtomOrMolecule)
67+
} else {
68+
return result
69+
}
70+
} else {
71+
return unparseSugarFreeMolecule(value, unparseAtomOrMolecule)
72+
}
5973
}
6074
}
6175

@@ -101,10 +115,12 @@ export const unparseAtom = (atom: string): Right<string> =>
101115
: quoteAtomIfNecessary(atom),
102116
)
103117

118+
const requiresQuotation = (atom: string): boolean =>
119+
either.isLeft(parsing.parse(unquotedAtomParser, atom))
120+
104121
const quoteAtomIfNecessary = (value: string): string => {
105122
const { quote } = punctuation(kleur)
106-
const unquotedAtomResult = parsing.parse(unquotedAtomParser, value)
107-
if (either.isLeft(unquotedAtomResult)) {
123+
if (requiresQuotation(value)) {
108124
return quote.concat(escapeStringContents(value)).concat(quote)
109125
} else {
110126
return value
@@ -252,3 +268,38 @@ const unparseSugaredLookup = (
252268
),
253269
),
254270
)
271+
272+
const unparseSugaredGeneralizedKeywordExpression = (
273+
expression: Expression,
274+
unparseAtomOrMolecule: UnparseAtomOrMolecule,
275+
) => {
276+
if (
277+
// Not every valid keyword expression can be expressed with the
278+
// generalized sugar, e.g. if there are any additional properties
279+
// besides the keyword and its argument, or if the keyword requires
280+
// quotation (which won't be the case for any built-in keywords, but
281+
// maybe eventually users will be able to create custom keywords).
282+
requiresQuotation(expression['0'].substring(1)) ||
283+
Object.keys(expression).some(key => key !== '0' && key !== '1')
284+
) {
285+
return either.makeLeft({
286+
kind: 'unserializableValue',
287+
message:
288+
'expression cannot be faithfully represented using generalized keyword expression sugar',
289+
})
290+
} else {
291+
const unparsedKeyword = kleur.bold(kleur.underline(expression['0']))
292+
if ('1' in expression) {
293+
return either.map(
294+
either.flatMap(
295+
serializeIfNeeded(expression['1']),
296+
unparseAtomOrMolecule,
297+
),
298+
unparsedArgument =>
299+
unparsedKeyword.concat(' ').concat(unparsedArgument),
300+
)
301+
} else {
302+
return either.makeRight(unparsedKeyword)
303+
}
304+
}
305+
}

0 commit comments

Comments
 (0)