@@ -68,6 +68,110 @@ class WordImpl implements Word {
6868 }
6969}
7070
71+ class ArithmeticCommandImpl implements ArithmeticCommand {
72+ type : "ArithmeticCommand" = "ArithmeticCommand" ;
73+ pos : number ;
74+ end : number ;
75+ body : string ;
76+ #expression: ArithmeticExpression | undefined | null = null ;
77+
78+ constructor ( pos : number , end : number , body : string ) {
79+ this . pos = pos ;
80+ this . end = end ;
81+ this . body = body ;
82+ }
83+
84+ get expression ( ) : ArithmeticExpression | undefined {
85+ if ( this . #expression === null ) {
86+ this . #expression = parseArithmeticExpression ( this . body , this . pos + 2 ) ?? undefined ;
87+ }
88+ return this . #expression;
89+ }
90+ set expression ( v : ArithmeticExpression | undefined ) {
91+ this . #expression = v ?? undefined ;
92+ }
93+ }
94+
95+ class ArithmeticForImpl implements ArithmeticFor {
96+ type : "ArithmeticFor" = "ArithmeticFor" ;
97+ pos : number ;
98+ end : number ;
99+ body : CompoundList ;
100+ #initStr: string ;
101+ #testStr: string ;
102+ #updateStr: string ;
103+ #initPos: number ;
104+ #testPos: number ;
105+ #updatePos: number ;
106+ #initialize: ArithmeticExpression | undefined | null = null ;
107+ #test: ArithmeticExpression | undefined | null = null ;
108+ #update: ArithmeticExpression | undefined | null = null ;
109+
110+ constructor (
111+ pos : number , end : number , body : CompoundList ,
112+ initStr : string , testStr : string , updateStr : string ,
113+ initPos : number , testPos : number , updatePos : number ,
114+ ) {
115+ this . pos = pos ;
116+ this . end = end ;
117+ this . body = body ;
118+ this . #initStr = initStr ;
119+ this . #testStr = testStr ;
120+ this . #updateStr = updateStr ;
121+ this . #initPos = initPos ;
122+ this . #testPos = testPos ;
123+ this . #updatePos = updatePos ;
124+ }
125+
126+ get initialize ( ) : ArithmeticExpression | undefined {
127+ if ( this . #initialize === null ) {
128+ if ( this . #initStr) {
129+ const expr = parseArithmeticExpression ( this . #initStr) ;
130+ if ( expr ) offsetArith ( expr , this . #initPos) ;
131+ this . #initialize = expr ?? undefined ;
132+ } else {
133+ this . #initialize = undefined ;
134+ }
135+ }
136+ return this . #initialize;
137+ }
138+ set initialize ( v : ArithmeticExpression | undefined ) {
139+ this . #initialize = v ?? undefined ;
140+ }
141+
142+ get test ( ) : ArithmeticExpression | undefined {
143+ if ( this . #test === null ) {
144+ if ( this . #testStr) {
145+ const expr = parseArithmeticExpression ( this . #testStr) ;
146+ if ( expr ) offsetArith ( expr , this . #testPos) ;
147+ this . #test = expr ?? undefined ;
148+ } else {
149+ this . #test = undefined ;
150+ }
151+ }
152+ return this . #test;
153+ }
154+ set test ( v : ArithmeticExpression | undefined ) {
155+ this . #test = v ?? undefined ;
156+ }
157+
158+ get update ( ) : ArithmeticExpression | undefined {
159+ if ( this . #update === null ) {
160+ if ( this . #updateStr) {
161+ const expr = parseArithmeticExpression ( this . #updateStr) ;
162+ if ( expr ) offsetArith ( expr , this . #updatePos) ;
163+ this . #update = expr ?? undefined ;
164+ } else {
165+ this . #update = undefined ;
166+ }
167+ }
168+ return this . #update;
169+ }
170+ set update ( v : ArithmeticExpression | undefined ) {
171+ this . #update = v ?? undefined ;
172+ }
173+ }
174+
71175const CASE_TERMINATORS : Record < number , CaseTerminator > = {
72176 [ Token . DoubleSemi ] : ";;" ,
73177 [ Token . SemiAmp ] : ";&" ,
@@ -469,12 +573,8 @@ class Parser {
469573 // arith_command := (( expr ))
470574 private arithCommand ( ) : ArithmeticCommand {
471575 const tok = this . tok . next ( LexContext . CommandStart ) ;
472- const body = tok . value ;
473- const tokPos = tok . pos ;
474- const tokEnd = tok . end ;
475- const expr = parseArithmeticExpression ( body , tokPos + 2 ) ?? undefined ;
476576 this . _redirects = this . collectTrailingRedirects ( ) ;
477- return { type : "ArithmeticCommand" , pos : tokPos , end : tokEnd , expression : expr , body } ;
577+ return new ArithmeticCommandImpl ( tok . pos , tok . end , tok . value ) ;
478578 }
479579
480580 // coproc := COPROC [name] command [redirections]
@@ -629,41 +729,19 @@ class Parser {
629729 // C-style for: (( expr; expr; expr )) [;|NL] do list done | { list }
630730 private cStyleFor ( pos : number ) : ArithmeticFor {
631731 const [ initStr , testStr , updateStr , initPos , testPos , updatePos ] = this . tok . readCStyleForExprs ( ) ;
632- const init = initStr ? ( parseArithmeticExpression ( initStr ) ?? undefined ) : undefined ;
633- const test_ = testStr ? ( parseArithmeticExpression ( testStr ) ?? undefined ) : undefined ;
634- const update = updateStr ? ( parseArithmeticExpression ( updateStr ) ?? undefined ) : undefined ;
635- if ( init ) offsetArith ( init , initPos ) ;
636- if ( test_ ) offsetArith ( test_ , testPos ) ;
637- if ( update ) offsetArith ( update , updatePos ) ;
638732 if ( this . tok . peek ( LexContext . CommandStart ) . token === Token . Semi ) this . tok . next ( LexContext . CommandStart ) ;
639733 this . skipNewlines ( LexContext . CommandStart ) ;
640734 if ( this . tok . peek ( LexContext . CommandStart ) . token === Token . LBrace ) {
641735 const bg = this . braceGroup ( ) ;
642- return {
643- type : "ArithmeticFor" ,
644- pos,
645- end : bg . end ,
646- initialize : init ,
647- test : test_ ,
648- update,
649- body : bg . body ,
650- } satisfies ArithmeticFor ;
736+ return new ArithmeticForImpl ( pos , bg . end , bg . body , initStr , testStr , updateStr , initPos , testPos , updatePos ) ;
651737 }
652738 if ( ! this . accept ( Token . Do , LexContext . CommandStart ) ) this . error ( "expected 'do'" , this . tok . getPos ( ) ) ;
653739 const body = this . list ( ) ;
654740 const closeEnd = this . acceptEnd ( Token . Done , LexContext . CommandStart ) ;
655741 if ( closeEnd < 0 ) this . error ( "expected 'done' to close 'for'" , this . tok . getPos ( ) ) ;
656742 const end = closeEnd >= 0 ? closeEnd : pos ;
657743 this . _redirects = this . collectTrailingRedirects ( ) ;
658- return {
659- type : "ArithmeticFor" ,
660- pos,
661- end,
662- initialize : init ,
663- test : test_ ,
664- update,
665- body : this . makeCompoundList ( body ) ,
666- } satisfies ArithmeticFor ;
744+ return new ArithmeticForImpl ( pos , end , this . makeCompoundList ( body ) , initStr , testStr , updateStr , initPos , testPos , updatePos ) ;
667745 }
668746
669747 private whileClause ( ) : While {
0 commit comments