@@ -8,10 +8,13 @@ import {
88 isSemanticGraph ,
99 readApplyExpression ,
1010 readFunctionExpression ,
11+ readIndexExpression ,
1112 readLookupExpression ,
1213 serialize ,
1314 type ApplyExpression ,
1415 type FunctionExpression ,
16+ type IndexExpression ,
17+ type KeyPath ,
1518 type LookupExpression ,
1619 type SemanticGraph ,
1720} from '../semantics.js'
@@ -48,6 +51,12 @@ export const moleculeUnparser =
4851 right : functionExpression =>
4952 unparseSugaredFunction ( functionExpression , unparseAtomOrMolecule ) ,
5053 } )
54+ case '@index' :
55+ return either . match ( readIndexExpression ( value ) , {
56+ left : _ => unparseSugarFreeMolecule ( value , unparseAtomOrMolecule ) ,
57+ right : indexExpression =>
58+ unparseSugaredIndex ( indexExpression , unparseAtomOrMolecule ) ,
59+ } )
5160 case '@lookup' :
5261 return either . match ( readLookupExpression ( value ) , {
5362 left : _ => unparseSugarFreeMolecule ( value , unparseAtomOrMolecule ) ,
@@ -84,7 +93,7 @@ export const moleculeAsKeyValuePairStrings = (
8493 } else {
8594 keyValuePairsAsStrings . push (
8695 kleur
87- . cyan ( quoteIfNecessary ( propertyKey ) . concat ( colon ) )
96+ . cyan ( quoteAtomIfNecessary ( propertyKey ) . concat ( colon ) )
8897 . concat ( ' ' )
8998 . concat ( valueAsStringResult . value ) ,
9099 )
@@ -96,11 +105,11 @@ export const moleculeAsKeyValuePairStrings = (
96105export const unparseAtom = ( atom : string ) : Right < string > =>
97106 either . makeRight (
98107 / ^ @ [ ^ @ ] / . test ( atom )
99- ? kleur . bold ( kleur . underline ( quoteIfNecessary ( atom ) ) )
100- : quoteIfNecessary ( atom ) ,
108+ ? kleur . bold ( kleur . underline ( quoteAtomIfNecessary ( atom ) ) )
109+ : quoteAtomIfNecessary ( atom ) ,
101110 )
102111
103- const quoteIfNecessary = ( value : string ) : string => {
112+ const quoteAtomIfNecessary = ( value : string ) : string => {
104113 const unquotedAtomResult = parsing . parse ( unquotedAtomParser , value )
105114 if ( either . isLeft ( unquotedAtomResult ) ) {
106115 return quote . concat ( escapeStringContents ( value ) ) . concat ( quote )
@@ -109,6 +118,15 @@ const quoteIfNecessary = (value: string): string => {
109118 }
110119}
111120
121+ const quoteKeyPathComponentIfNecessary = ( value : string ) : string => {
122+ const unquotedAtomResult = parsing . parse ( unquotedAtomParser , value )
123+ if ( either . isLeft ( unquotedAtomResult ) || value . includes ( '.' ) ) {
124+ return quote . concat ( escapeStringContents ( value ) ) . concat ( quote )
125+ } else {
126+ return value
127+ }
128+ }
129+
112130const serializeIfNeeded = (
113131 nodeOrMolecule : SemanticGraph | Molecule ,
114132) : Either < UnserializableValueError , Atom | Molecule > =>
@@ -168,10 +186,54 @@ const unparseSugaredFunction = (
168186 ) ,
169187 )
170188
189+ const unparseSugaredIndex = (
190+ expression : IndexExpression ,
191+ unparseAtomOrMolecule : UnparseAtomOrMolecule ,
192+ ) => {
193+ const objectUnparseResult = either . flatMap (
194+ serializeIfNeeded ( expression . object ) ,
195+ unparseAtomOrMolecule ,
196+ )
197+ if ( either . isLeft ( objectUnparseResult ) ) {
198+ return objectUnparseResult
199+ }
200+
201+ const keyPath = Object . entries ( expression . query ) . reduce (
202+ ( accumulator : KeyPath | 'invalid' , [ key , value ] ) => {
203+ if ( accumulator === 'invalid' ) {
204+ return accumulator
205+ } else {
206+ if ( key === String ( accumulator . length ) && typeof value === 'string' ) {
207+ return [ ...accumulator , value ]
208+ } else {
209+ return 'invalid'
210+ }
211+ }
212+ } ,
213+ [ ] ,
214+ )
215+
216+ if (
217+ keyPath === 'invalid' ||
218+ Object . keys ( expression . query ) . length !== keyPath . length
219+ ) {
220+ return either . makeLeft ( {
221+ kind : 'unserializableValue' ,
222+ message : 'invalid key path' ,
223+ } )
224+ }
225+
226+ return either . makeRight (
227+ objectUnparseResult . value
228+ . concat ( dot )
229+ . concat ( keyPath . map ( quoteKeyPathComponentIfNecessary ) . join ( dot ) ) ,
230+ )
231+ }
232+
171233const unparseSugaredLookup = (
172234 expression : LookupExpression ,
173- unparseAtomOrMolecule : UnparseAtomOrMolecule ,
235+ _unparseAtomOrMolecule : UnparseAtomOrMolecule ,
174236) =>
175- either . map ( unparseAtomOrMolecule ( expression . key ) , key =>
176- kleur . cyan ( colon . concat ( key ) ) ,
237+ either . makeRight (
238+ kleur . cyan ( colon . concat ( quoteKeyPathComponentIfNecessary ( expression . key ) ) ) ,
177239 )
0 commit comments