40
40
VarSubState ,
41
41
Piece ,
42
42
)
43
- from _devbuild .gen .option_asdl import option_i
43
+ from _devbuild .gen .option_asdl import option_i , builtin_i
44
44
from _devbuild .gen .value_asdl import (
45
45
value ,
46
46
value_e ,
@@ -2141,22 +2141,66 @@ def _EvalAssignBuiltin(self, builtin_id, arg0, words):
2141
2141
2142
2142
return cmd_value .Assign (builtin_id , flags , flag_locs , assign_args )
2143
2143
2144
+ def _DetectAssignBuiltinStr (self , arg0 , words ):
2145
+ # type: (str, List[CompoundWord]) -> Optional[cmd_value.Assign]
2146
+ builtin_id = consts .LookupAssignBuiltin (arg0 )
2147
+ if builtin_id != consts .NO_INDEX :
2148
+ return self ._EvalAssignBuiltin (builtin_id , arg0 , words )
2149
+ return None
2150
+
2151
+ def _DetectAssignBuiltin (self , val0 , words ):
2152
+ # type: (part_value_t, List[CompoundWord]) -> Optional[cmd_value.Assign]
2153
+ UP_val0 = val0
2154
+ if val0 .tag () == part_value_e .String :
2155
+ val0 = cast (Piece , UP_val0 )
2156
+ if not val0 .quoted :
2157
+ return self ._DetectAssignBuiltinStr (val0 .s , words )
2158
+ return None
2159
+
2160
+ def _DetectMetaBuiltinStr (self , s ):
2161
+ # type: (str) -> bool
2162
+ """
2163
+ We need to detect all of these cases:
2164
+
2165
+ builtin local
2166
+ command local
2167
+ builtin builtin local
2168
+ builtin command local
2169
+
2170
+ Fundamentally, assignment builtins have different WORD EVALUATION RULES
2171
+ for a=$x (no word splitting), so it seems hard to do this in
2172
+ meta_osh.Builtin() or meta_osh.Command()
2173
+ """
2174
+ return (consts .LookupNormalBuiltin (s )
2175
+ in (builtin_i .builtin , builtin_i .command ))
2176
+
2177
+ def _DetectMetaBuiltin (self , val0 ):
2178
+ # type: (part_value_t) -> bool
2179
+ UP_val0 = val0
2180
+ if val0 .tag () == part_value_e .String :
2181
+ val0 = cast (Piece , UP_val0 )
2182
+ if not val0 .quoted :
2183
+ return self ._DetectMetaBuiltinStr (val0 .s )
2184
+ return False
2185
+
2144
2186
def SimpleEvalWordSequence2 (self , words , allow_assign ):
2145
2187
# type: (List[CompoundWord], bool) -> cmd_value_t
2146
2188
"""Simple word evaluation for YSH."""
2147
2189
strs = [] # type: List[str]
2148
2190
locs = [] # type: List[CompoundWord]
2149
2191
2192
+ assign_builtin_offset = 0
2150
2193
for i , w in enumerate (words ):
2151
2194
# No globbing in the first arg for command.Simple.
2152
- if i == 0 and allow_assign :
2195
+ if i == assign_builtin_offset and allow_assign :
2153
2196
strs0 = self ._EvalWordToArgv (w )
2197
+ # Same logic as legacy word eval, with no splitting
2198
+ # TODO: Remove this because we should remove assignment
2199
+ # builtins? What about export?
2154
2200
if len (strs0 ) == 1 :
2155
- arg0 = strs0 [0 ]
2156
- builtin_id = consts .LookupAssignBuiltin (arg0 )
2157
- if builtin_id != consts .NO_INDEX :
2158
- # Same logic as legacy word eval, with no splitting
2159
- return self ._EvalAssignBuiltin (builtin_id , arg0 , words )
2201
+ cmd_val = self ._DetectAssignBuiltinStr (strs0 [0 ], words )
2202
+ if cmd_val :
2203
+ return cmd_val
2160
2204
2161
2205
strs .extend (strs0 )
2162
2206
for _ in strs0 :
@@ -2201,22 +2245,6 @@ def SimpleEvalWordSequence2(self, words, allow_assign):
2201
2245
2202
2246
return cmd_value .Argv (strs , locs , None , None , None , None )
2203
2247
2204
- def _DetectAssignBuiltinStr (self , arg0 , words ):
2205
- # type: (str, List[CompoundWord]) -> Optional[cmd_value.Assign]
2206
- builtin_id = consts .LookupAssignBuiltin (arg0 )
2207
- if builtin_id != consts .NO_INDEX :
2208
- return self ._EvalAssignBuiltin (builtin_id , arg0 , words )
2209
- return None
2210
-
2211
- def _DetectAssignBuiltin (self , val0 , words ):
2212
- # type: (part_value_t, List[CompoundWord]) -> Optional[cmd_value.Assign]
2213
- UP_val0 = val0
2214
- if val0 .tag () == part_value_e .String :
2215
- val0 = cast (Piece , UP_val0 )
2216
- if not val0 .quoted :
2217
- return self ._DetectAssignBuiltinStr (val0 .s , words )
2218
- return None
2219
-
2220
2248
def EvalWordSequence2 (self , words , allow_assign = False ):
2221
2249
# type: (List[CompoundWord], bool) -> cmd_value_t
2222
2250
"""Turns a list of Words into a list of strings.
@@ -2245,6 +2273,8 @@ def EvalWordSequence2(self, words, allow_assign=False):
2245
2273
strs = [] # type: List[str]
2246
2274
locs = [] # type: List[CompoundWord]
2247
2275
2276
+ assign_builtin_offset = 0
2277
+
2248
2278
n = 0
2249
2279
for i , w in enumerate (words ):
2250
2280
fast_str = word_ .FastStrEval (w )
@@ -2253,10 +2283,14 @@ def EvalWordSequence2(self, words, allow_assign=False):
2253
2283
locs .append (w )
2254
2284
2255
2285
# e.g. the 'local' in 'local a=b c=d' will be here
2256
- if allow_assign and i == 0 :
2286
+ if allow_assign and i == assign_builtin_offset :
2257
2287
cmd_val = self ._DetectAssignBuiltinStr (fast_str , words )
2258
2288
if cmd_val :
2259
2289
return cmd_val
2290
+ #print('YO %s' % fast_str)
2291
+ if self ._DetectMetaBuiltinStr (fast_str ):
2292
+ #print('META')
2293
+ assign_builtin_offset += 1
2260
2294
continue
2261
2295
2262
2296
part_vals = [] # type: List[part_value_t]
@@ -2271,11 +2305,16 @@ def EvalWordSequence2(self, words, allow_assign=False):
2271
2305
#
2272
2306
# But we don't want to evaluate the first word twice in the case of:
2273
2307
# $(some-command) --flag
2274
- if allow_assign and i == 0 and len (part_vals ) == 1 :
2308
+ if (allow_assign and i == assign_builtin_offset and
2309
+ len (part_vals ) == 1 ):
2275
2310
cmd_val = self ._DetectAssignBuiltin (part_vals [0 ], words )
2276
2311
if cmd_val :
2277
2312
return cmd_val
2278
2313
2314
+ if len (part_vals ) == 1 :
2315
+ if self ._DetectMetaBuiltin (part_vals [0 ]):
2316
+ assign_builtin_offset += 1
2317
+
2279
2318
if 0 :
2280
2319
log ('' )
2281
2320
log ('part_vals after _EvalWordToParts:' )
0 commit comments