Skip to content

Commit

Permalink
[core refactor] Preparing to make ARGV real vars
Browse files Browse the repository at this point in the history
Simplify mem.{PushCall,PopCall}

More logic goes in ctx_{Proc,Func}
  • Loading branch information
Andy Chu committed Apr 13, 2024
1 parent d642ef8 commit 4405950
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 28 deletions.
66 changes: 46 additions & 20 deletions core/state.py
Expand Up @@ -926,7 +926,11 @@ class ctx_FuncCall(object):

def __init__(self, mem, func):
# type: (Mem, value.Func) -> None
mem.PushCall(func.name, func.parsed.name, None)

frame = NewDict() # type: Dict[str, Cell]
mem.var_stack.append(frame)

mem.PushCall(func.name, func.parsed.name)
self.mem = mem

def __enter__(self):
Expand All @@ -935,7 +939,8 @@ def __enter__(self):

def __exit__(self, type, value, traceback):
# type: (Any, Any, Any) -> None
self.mem.PopCall(False)
self.mem.PopCall()
self.mem.var_stack.pop()


class ctx_ProcCall(object):
Expand All @@ -953,7 +958,21 @@ def __init__(self, mem, mutable_opts, proc, argv):
# - dynamic scope is one difference
# - '$@" shift etc. are another difference

mem.PushCall(proc.name, proc.name_tok, argv)
frame = NewDict() # type: Dict[str, Cell]

assert argv is not None
if True:
# shell function
mem.argv_stack.append(_ArgFrame(argv))
else:
# TODO: procs get argv
# - open: the args
# - closed: always empty
frame['ARGV'] = _MakeArgvCell(argv)

mem.var_stack.append(frame)

mem.PushCall(proc.name, proc.name_tok)

# Dynamic scope is only for shell functions
mutable_opts.PushDynamicScope(proc.sh_compat)
Expand All @@ -970,7 +989,11 @@ def __enter__(self):
def __exit__(self, type, value, traceback):
# type: (Any, Any, Any) -> None
self.mutable_opts.PopDynamicScope()
self.mem.PopCall(True)
self.mem.PopCall()
self.mem.var_stack.pop()

# TODO: do this conditionally
self.mem.argv_stack.pop()


class ctx_Temp(object):
Expand Down Expand Up @@ -1054,11 +1077,15 @@ def __exit__(self, type, value, traceback):
self.mem.this_dir.pop()


def _MakeArgvCell(argv):
# type: (List[str]) -> Cell
items = [value.Str(a) for a in argv] # type: List[value_t]
return Cell(False, False, False, value.List(items))


class Mem(object):
"""For storing variables.
Mem is better than "Env" -- Env implies OS stuff.
Callers:
User code: assigning and evaluating variables, in command context or
arithmetic context.
Expand All @@ -1079,8 +1106,13 @@ def __init__(self, dollar0, argv, arena, debug_stack):
self.unsafe_arith = None # type: sh_expr_eval.UnsafeArith

self.dollar0 = dollar0
# If you only use YSH procs and funcs, this will remain at length 1.
self.argv_stack = [_ArgFrame(argv)]

frame = NewDict() # type: Dict[str, Cell]

#frame['ARGV'] = _MakeArgvCell(argv)

self.var_stack = [frame]

# The debug_stack isn't strictly necessary for execution. We use it
Expand Down Expand Up @@ -1297,8 +1329,8 @@ def SetProcessSubStatus(self, x):
# Call Stack
#

def PushCall(self, func_name, def_tok, argv):
# type: (str, Token, Optional[List[str]]) -> None
def PushCall(self, func_name, def_tok):
# type: (str, Token) -> None
"""Push argv, var, and debug stack frames.
Currently used for proc and func calls. TODO: New func evaluator may
Expand All @@ -1308,28 +1340,19 @@ def PushCall(self, func_name, def_tok, argv):
def_tok: Token where proc or func was defined, used to compute
BASH_SOURCE.
"""
if argv is not None:
self.argv_stack.append(_ArgFrame(argv))
frame = NewDict() # type: Dict[str, Cell]
self.var_stack.append(frame)

# self.token_for_line can be None?
self.debug_stack.append(
debug_frame.Call(self.token_for_line, def_tok, func_name))

def PopCall(self, should_pop_argv_stack):
# type: (bool) -> None
def PopCall(self):
# type: () -> None
"""
Args:
should_pop_argv_stack: Pass False if PushCall was given None for argv
True for proc, False for func
"""
self.debug_stack.pop()

self.var_stack.pop()

if should_pop_argv_stack:
self.argv_stack.pop()

def ShouldRunDebugTrap(self):
# type: () -> bool

Expand Down Expand Up @@ -2378,3 +2401,6 @@ def GetInteger(mem, name):
raise error.Runtime("$%s doesn't look like an integer, got %r" %
(name, s))
return i


# vim: sw=4
16 changes: 8 additions & 8 deletions spec/ysh-proc.test.sh
Expand Up @@ -394,14 +394,14 @@ shopt -s ysh:upgrade
argv.py global @ARGV
# should not be ignored
call ARGV->append("global")
call ARGV->append("GG")
argv.py global @ARGV
proc p {
argv.py @ARGV
call ARGV->append("local")
argv.py @ARGV
argv.py local @ARGV
call ARGV->append("LL")
argv.py local @ARGV
}
p local @ARGV
Expand All @@ -412,9 +412,9 @@ argv.py global @ARGV

## STDOUT:
['global', 'a b', 'c']
['global', 'a b', 'c', 'global']
['local', 'a b', 'c']
['local', 'a b', 'c', 'local']
['global', 'a b', 'c', 'global']
['global', 'a b', 'c', 'GG']
['local', 'a b', 'c', 'GG']
['local', 'a b', 'c', 'GG', 'LL']
['global', 'a b', 'c', 'GG', 'LL']
## END

0 comments on commit 4405950

Please sign in to comment.