def testUnset(self): mem = _InitMem() # unset a mem.Unset(runtime.LhsName('a'), scope_e.Dynamic) return # not implemented yet # unset a[1] mem.Unset(runtime.LhsIndexedName('a', 1), scope_e.Dynamic)
def testUnset(self): mem = state.Mem('', [], {}) # unset a mem.Unset(runtime.LhsName('a'), scope.Dynamic) return # not implemented yet # unset a[1] mem.Unset(runtime.LhsIndexedName('a', 1), scope.Dynamic)
def EvalLhs(node, arith_ev, mem, exec_opts): """Evaluate the operand for a++ a[0]++ as an R-value. Used by Executor as well. Args: node: osh_ast.lhs_expr Returns: runtime.value, runtime.lvalue """ #log('lhs_expr NODE %s', node) assert isinstance(node, ast.lhs_expr), node if node.tag == lhs_expr_e.LhsName: # a = b # Problem: It can't be an array? # a=(1 2) # (( a++ )) lval = runtime.LhsName(node.name) val = _LookupVar(node.name, mem, exec_opts) elif node.tag == lhs_expr_e.LhsIndexedName: # a[1] = b # See tdop.IsIndexable for valid values: # - ArithVarRef (not LhsName): a[1] # - FuncCall: f(x), 1 # - ArithBinary LBracket: f[1][1] -- no semantics for this? index = arith_ev.Eval(node.index) lval = runtime.LhsIndexedName(node.name, index) val = mem.GetVar(node.name) if val.tag == value_e.Str: e_die("Can't assign to characters of string %r", node.name) elif val.tag == value_e.Undef: # It would make more sense for 'nounset' to control this, but bash # doesn't work that way. #if self.exec_opts.strict_arith: # e_die('Undefined array %r', node.name) # TODO: error location val = runtime.Str('') elif val.tag == value_e.StrArray: #log('ARRAY %s -> %s, index %d', node.name, array, index) array = val.strs # NOTE: Similar logic in RHS Arith_LBracket try: item = array[index] except IndexError: val = runtime.Str('') else: assert isinstance(item, str), item val = runtime.Str(item) else: raise AssertionError(val.tag) else: raise AssertionError(node.tag) return val, lval
def _EvalLhs(self, node): """lhs_expr -> lvalue.""" assert isinstance(node, ast.lhs_expr), node if node.tag == lhs_expr_e.LhsName: # a=x return runtime.LhsName(node.name) if node.tag == lhs_expr_e.LhsIndexedName: # a[1+2]=x i = self.arith_ev.Eval(node.index) return runtime.LhsIndexedName(node.name, i) raise AssertionError(node.tag)
def testSetVarClearFlag(self): mem = state.Mem('', [], {}) print(mem) mem.PushCall('my-func', ['ONE']) self.assertEqual(2, len(mem.var_stack)) # internal details # local x=y mem.SetVar(runtime.LhsName('x'), runtime.Str('y'), (), scope.LocalOnly) self.assertEqual('y', mem.var_stack[-1]['x'].val.s) # New frame mem.PushCall('my-func', ['TWO']) self.assertEqual(3, len(mem.var_stack)) # internal details # x=y -- test out dynamic scope mem.SetVar(runtime.LhsName('x'), runtime.Str('YYY'), (), scope.Dynamic) self.assertEqual('YYY', mem.var_stack[-2]['x'].val.s) self.assertEqual(None, mem.var_stack[-1].get('x')) # myglobal=g mem.SetVar(runtime.LhsName('myglobal'), runtime.Str('g'), (), scope.Dynamic) self.assertEqual('g', mem.var_stack[0]['myglobal'].val.s) self.assertEqual(False, mem.var_stack[0]['myglobal'].exported) # 'export PYTHONPATH=/' mem.SetVar(runtime.LhsName('PYTHONPATH'), runtime.Str('/'), (var_flags.Exported, ), scope.Dynamic) self.assertEqual('/', mem.var_stack[0]['PYTHONPATH'].val.s) self.assertEqual(True, mem.var_stack[0]['PYTHONPATH'].exported) self.assertEqual({'PYTHONPATH': '/'}, mem.GetExported()) mem.SetVar(runtime.LhsName('PYTHONPATH'), None, (var_flags.Exported, ), scope.Dynamic) self.assertEqual(True, mem.var_stack[0]['PYTHONPATH'].exported) # 'export myglobal'. None means don't touch it. Undef would be confusing # because it might mean "unset", but we have a separated API for that. mem.SetVar(runtime.LhsName('myglobal'), None, (var_flags.Exported, ), scope.Dynamic) self.assertEqual(True, mem.var_stack[0]['myglobal'].exported) # export g2 -- define and export empty mem.SetVar(runtime.LhsName('g2'), None, (var_flags.Exported, ), scope.Dynamic) self.assertEqual('', mem.var_stack[0]['g2'].val.s) self.assertEqual(True, mem.var_stack[0]['g2'].exported) # readonly myglobal self.assertEqual(False, mem.var_stack[0]['myglobal'].readonly) mem.SetVar(runtime.LhsName('myglobal'), None, (var_flags.ReadOnly, ), scope.Dynamic) self.assertEqual(True, mem.var_stack[0]['myglobal'].readonly) mem.SetVar(runtime.LhsName('PYTHONPATH'), runtime.Str('/lib'), (), scope.Dynamic) self.assertEqual('/lib', mem.var_stack[0]['PYTHONPATH'].val.s) self.assertEqual(True, mem.var_stack[0]['PYTHONPATH'].exported) # COMPREPLY=(1 2 3) # invariant to enforce: arrays can't be exported mem.SetVar(runtime.LhsName('COMPREPLY'), runtime.StrArray(['1', '2', '3']), (), scope.GlobalOnly) self.assertEqual(['1', '2', '3'], mem.var_stack[0]['COMPREPLY'].val.strs) # export COMPREPLY try: mem.SetVar(runtime.LhsName('COMPREPLY'), None, (var_flags.Exported, ), scope.Dynamic) except util.FatalRuntimeError as e: pass else: self.fail("Expected failure") # readonly r=1 mem.SetVar(runtime.LhsName('r'), runtime.Str('1'), (var_flags.ReadOnly, ), scope.Dynamic) self.assertEqual('1', mem.var_stack[0]['r'].val.s) self.assertEqual(False, mem.var_stack[0]['r'].exported) self.assertEqual(True, mem.var_stack[0]['r'].readonly) print(mem) # r=newvalue try: mem.SetVar(runtime.LhsName('r'), runtime.Str('newvalue'), (), scope.Dynamic) except util.FatalRuntimeError as e: pass else: self.fail("Expected failure") # readonly r2 -- define empty readonly mem.SetVar(runtime.LhsName('r2'), None, (var_flags.ReadOnly, ), scope.Dynamic) self.assertEqual('', mem.var_stack[0]['r2'].val.s) self.assertEqual(True, mem.var_stack[0]['r2'].readonly) # export -n PYTHONPATH # Remove the exported property. NOTE: scope is LocalOnly for Oil? self.assertEqual(True, mem.var_stack[0]['PYTHONPATH'].exported) mem.ClearFlag('PYTHONPATH', var_flags.Exported, scope.Dynamic) self.assertEqual(False, mem.var_stack[0]['PYTHONPATH'].exported) # a[2]=2 mem.SetVar(runtime.LhsIndexedName('a', 1), runtime.Str('2'), (), scope.Dynamic) self.assertEqual(['', '2'], mem.var_stack[0]['a'].val.strs) # a[2]=3 mem.SetVar(runtime.LhsIndexedName('a', 1), runtime.Str('3'), (), scope.Dynamic) self.assertEqual(['', '3'], mem.var_stack[0]['a'].val.strs) # a[2]=(x y z) # illegal try: mem.SetVar(runtime.LhsIndexedName('a', 1), runtime.StrArray(['x', 'y', 'z']), (), scope.Dynamic) except util.FatalRuntimeError as e: pass else: self.fail("Expected failure") # readonly a mem.SetVar(runtime.LhsName('a'), None, (var_flags.ReadOnly, ), scope.Dynamic) self.assertEqual(True, mem.var_stack[0]['a'].readonly) try: # a[2]=3 mem.SetVar(runtime.LhsIndexedName('a', 1), runtime.Str('3'), (), scope.Dynamic) except util.FatalRuntimeError as e: pass else: self.fail("Expected failure")