Permalink
Browse files

Implement a basic version of declare/typeset -f / -F / -p.

- If any of these three flags are detected, then the statement is parsed
  like a builtin rather than an assignment.
- declare and typeset have identical behavior, like they do in bash.
  mksh doesn't implement 'declare'.

Addresses issue #59.
  • Loading branch information...
Andy Chu
Andy Chu committed Jan 20, 2018
1 parent c7da30c commit 9a9d3421f06bd801dcee8e03af3984c692dc65ba
Showing with 152 additions and 3 deletions.
  1. +47 −0 core/builtin.py
  2. +4 −1 core/cmd_exec.py
  3. +2 −2 core/expr_eval.py
  4. +1 −0 osh/cmd_parse.py
  5. +98 −0 spec/assign.test.sh
View
@@ -66,6 +66,7 @@
COLON
TEST BRACKET GETOPTS
COMMAND TYPE HELP
DECLARE TYPESET
""".split())
@@ -213,6 +214,11 @@ def Resolve(argv0):
elif argv0 == "type":
return EBuiltin.TYPE
elif argv0 == "declare":
return EBuiltin.DECLARE
elif argv0 == "typeset":
return EBuiltin.TYPESET
elif argv0 == "help":
return EBuiltin.HELP
@@ -970,6 +976,47 @@ def Type(argv, funcs, path_val):
return status
DECLARE_SPEC = _Register('declare')
DECLARE_SPEC.ShortFlag('-f')
DECLARE_SPEC.ShortFlag('-F')
DECLARE_SPEC.ShortFlag('-p')
def DeclareTypeset(argv, mem, funcs):
arg, i = DECLARE_SPEC.Parse(argv)
status = 0
# NOTE: in bash, -f shows the function body, while -F shows the name. In
# osh, they're identical and behave like -F.
if arg.f or arg.F: # Lookup and print functions.
for name in argv[i:]:
if name in funcs:
print(name)
# TODO: Could print LST, or render LST. Bash does this.
#print(funcs[name])
else:
status = 1
elif arg.p: # Lookup and print variables.
for name in argv[i:]:
val = mem.GetVar(name)
if val.tag != value_e.Undef:
# TODO: Print flags.
print(name)
else:
status = 1
else:
raise NotImplementedError
sys.stdout.flush()
return status
def Trap(argv, traps):
# TODO: register trap
View
@@ -341,6 +341,10 @@ def _RunBuiltin(self, builtin_id, argv):
path = self.mem.GetVar('PATH')
status = builtin.Type(argv, self.funcs, path)
elif builtin_id in (EBuiltin.DECLARE, EBuiltin.TYPESET):
# These are synonyms
status = builtin.DeclareTypeset(argv, self.mem, self.funcs)
elif builtin_id == EBuiltin.HELP:
loader = util.GetResourceLoader()
status = builtin.Help(argv, loader)
@@ -505,7 +509,6 @@ def _RunSimpleCommand(self, argv, fork_external):
if not argv:
return 0 # status 0, or skip it?
# TODO: respect the special builtin order too
arg0 = argv[0]
builtin_id = builtin.ResolveSpecial(arg0)
View
@@ -136,7 +136,7 @@ def _LookupVar(name, mem, exec_opts):
return val
def EvalLhs(node, arith_ev, mem, exec_opts):
def _EvalLhs(node, arith_ev, mem, exec_opts):
"""Evaluate the operand for a++ a[0]++ as an R-value.
Args:
@@ -225,7 +225,7 @@ def _EvalLhsToArith(self, node):
Returns:
int or list of strings, runtime.lvalue
"""
val, lval = EvalLhs(node, self, self.mem, self.exec_opts)
val, lval = _EvalLhs(node, self, self.mem, self.exec_opts)
#log('Evaluating node %r -> %r', node, val)
return self._ValToArithOrError(val), lval
View
@@ -457,6 +457,7 @@ def _MakeAssignment(self, assign_kw, suffix_words):
# Maybe we could change this.
#(Id.Assign_Export, '-p'),
])
# Flags to parse like assignments: -a -r -x (and maybe -i)
def ParseSimpleCommand(self):
"""
View
@@ -192,3 +192,101 @@ argv.py "${a[@]}"
# stdout: ['x', 'z']
# N-I dash stdout-json: ""
# N-I dash status: 2
### declare -f
func2=x # var names are NOT found
declare -f myfunc func2
echo $?
myfunc() { echo myfunc; }
# This prints the source code.
declare -f myfunc func2 > /dev/null
echo $?
func2() { echo func2; }
declare -f myfunc func2 > /dev/null
echo $?
## STDOUT:
1
1
0
## END
## N-I dash/mksh STDOUT:
127
127
127
## END
### declare -p
var1() { echo func; } # function names are NOT found.
declare -p var1 var2 >/dev/null
echo $?
var1=x
declare -p var1 var2 >/dev/null
echo $?
var2=y
declare -p var1 var2 >/dev/null
echo $?
## STDOUT:
1
1
0
## N-I dash/mksh STDOUT:
127
127
127
## END
### typeset -f
# mksh implement typeset but not declare
typeset -f myfunc func2
echo $?
myfunc() { echo myfunc; }
# This prints the source code.
typeset -f myfunc func2 > /dev/null
echo $?
func2() { echo func2; }
typeset -f myfunc func2 > /dev/null
echo $?
## STDOUT:
1
1
0
## END
## N-I dash STDOUT:
127
127
127
## END
### typeset -p
var1() { echo func; } # function names are NOT found.
typeset -p var1 var2 >/dev/null
echo $?
var1=x
typeset -p var1 var2 >/dev/null
echo $?
var2=y
typeset -p var1 var2 >/dev/null
echo $?
## STDOUT:
1
1
0
## BUG mksh STDOUT:
# mksh doesn't respect exit codes
0
0
0
## END
## N-I dash STDOUT:
127
127
127
## END

0 comments on commit 9a9d342

Please sign in to comment.