View
@@ -9,10 +9,9 @@
from core import state # module under test
from core import util
# Hm this doesn't use scope_e or var_flags_e
scope = runtime.scope
scope_e = runtime.scope_e
value_e = runtime.value_e
var_flags = runtime.var_flags
var_flags_e = runtime.var_flags_e
class MemTest(unittest.TestCase):
@@ -33,7 +32,7 @@ def testSetVarClearFlag(self):
# local x=y
mem.SetVar(
runtime.LhsName('x'), runtime.Str('y'), (), scope.LocalOnly)
runtime.LhsName('x'), runtime.Str('y'), (), scope_e.LocalOnly)
self.assertEqual('y', mem.var_stack[-1]['x'].val.s)
# New frame
@@ -42,78 +41,78 @@ def testSetVarClearFlag(self):
# x=y -- test out dynamic scope
mem.SetVar(
runtime.LhsName('x'), runtime.Str('YYY'), (), scope.Dynamic)
runtime.LhsName('x'), runtime.Str('YYY'), (), scope_e.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)
runtime.LhsName('myglobal'), runtime.Str('g'), (), scope_e.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)
runtime.LhsName('PYTHONPATH'), runtime.Str('/'), (var_flags_e.Exported,),
scope_e.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)
runtime.LhsName('PYTHONPATH'), None, (var_flags_e.Exported,),
scope_e.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)
runtime.LhsName('myglobal'), None, (var_flags_e.Exported,),
scope_e.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)
runtime.LhsName('g2'), None, (var_flags_e.Exported,),
scope_e.Dynamic)
self.assertEqual(value_e.Undef, mem.var_stack[0]['g2'].val.tag)
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)
runtime.LhsName('myglobal'), None, (var_flags_e.ReadOnly,),
scope_e.Dynamic)
self.assertEqual(True, mem.var_stack[0]['myglobal'].readonly)
mem.SetVar(
runtime.LhsName('PYTHONPATH'), runtime.Str('/lib'), (),
scope.Dynamic)
scope_e.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)
(), scope_e.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)
runtime.LhsName('COMPREPLY'), None, (var_flags_e.Exported,),
scope_e.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)
runtime.LhsName('r'), runtime.Str('1'), (var_flags_e.ReadOnly,),
scope_e.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)
@@ -122,58 +121,58 @@ def testSetVarClearFlag(self):
# r=newvalue
try:
mem.SetVar(
runtime.LhsName('r'), runtime.Str('newvalue'), (), scope.Dynamic)
runtime.LhsName('r'), runtime.Str('newvalue'), (), scope_e.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)
runtime.LhsName('r2'), None, (var_flags_e.ReadOnly,),
scope_e.Dynamic)
self.assertEqual(value_e.Undef, mem.var_stack[0]['r2'].val.tag)
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)
mem.ClearFlag('PYTHONPATH', var_flags_e.Exported, scope_e.Dynamic)
self.assertEqual(False, mem.var_stack[0]['PYTHONPATH'].exported)
# a[2]=2
mem.SetVar(
runtime.LhsIndexedName('a', 1), runtime.Str('2'), (),
scope.Dynamic)
scope_e.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)
scope_e.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)
scope_e.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)
runtime.LhsName('a'), None, (var_flags_e.ReadOnly,),
scope_e.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)
scope_e.Dynamic)
except util.FatalRuntimeError as e:
pass
else:
@@ -184,13 +183,13 @@ def testGetVar(self):
# readonly a=x
mem.SetVar(
runtime.LhsName('a'), runtime.Str('x'), (var_flags.ReadOnly,),
scope.Dynamic)
runtime.LhsName('a'), runtime.Str('x'), (var_flags_e.ReadOnly,),
scope_e.Dynamic)
val = mem.GetVar('a', scope.Dynamic)
val = mem.GetVar('a', scope_e.Dynamic)
self.assertEqual(runtime.Str('x'), val)
val = mem.GetVar('undef', scope.Dynamic)
val = mem.GetVar('undef', scope_e.Dynamic)
self.assertEqual(runtime.Undef(), val)
def testExportThenAssign(self):
@@ -199,25 +198,25 @@ def testExportThenAssign(self):
# export U
mem.SetVar(
runtime.LhsName('U'), None, (var_flags.Exported,), scope.Dynamic)
runtime.LhsName('U'), None, (var_flags_e.Exported,), scope_e.Dynamic)
print(mem)
# U=u
mem.SetVar(
runtime.LhsName('U'), runtime.Str('u'), (), scope.Dynamic)
runtime.LhsName('U'), runtime.Str('u'), (), scope_e.Dynamic)
print(mem)
e = mem.GetExported()
self.assertEqual({'U': 'u'}, e)
def testUnset(self):
mem = state.Mem('', [], {})
# unset a
mem.Unset(runtime.LhsName('a'), scope.Dynamic)
mem.Unset(runtime.LhsName('a'), scope_e.Dynamic)
return # not implemented yet
# unset a[1]
mem.Unset(runtime.LhsIndexedName('a', 1), scope.Dynamic)
mem.Unset(runtime.LhsIndexedName('a', 1), scope_e.Dynamic)
def testArgv(self):
mem = state.Mem('', [], {})
View
@@ -131,10 +131,13 @@ def __init__(self, namespace, name, value):
def __repr__(self):
return '<%s.%s %s>' % (self.namespace, self.name, self.value)
def __hash__(self):
# Needed for the LEXER_DEF dictionary
return hash(self.name)
# I think this is not needed?
#def __hash__(self):
# # Needed for the LEXER_DEF dictionary
# return hash(self.name)
# Why is this needed? For ASDL serialization? But we're not using it like
# that.
def __eq__(self, other):
if isinstance(other, int):
return self.value == other
View
@@ -74,6 +74,13 @@ def testEnum(self):
else:
self.fail("Expected error")
d = {
Color.red: 'R',
Color.green: 'Blue',
Color.blue: 'B',
}
self.assertEqual('R', d[Color.red])
if __name__ == '__main__':
unittest.main()
View
@@ -11,7 +11,7 @@
word_e = ast.word_e
word_part_e = ast.word_part_e
assign_op = ast.assign_op
assign_op_e = ast.assign_op_e
def _LiteralPartId(p):
@@ -419,10 +419,10 @@ def LooksLikeAssignment(w):
s = part0.token.val
assert s.endswith('=')
if s[-2] == '+':
op = assign_op.PlusEqual
op = assign_op_e.PlusEqual
name = s[:-2]
else:
op = assign_op.Equal
op = assign_op_e.Equal
name = s[:-1]
rhs = ast.CompoundWord()
View
@@ -24,7 +24,7 @@
log = util.log
command_e = ast.command_e
word_e = ast.word_e
assign_op = ast.assign_op
assign_op_e = ast.assign_op_e
class CommandParser(object):
@@ -363,7 +363,7 @@ def _MakeSimpleCommand(self, prefix_bindings, suffix_words, redirects):
node.words = words3
node.redirects = redirects
for name, op, val, left_spid in prefix_bindings:
if op != assign_op.Equal:
if op != assign_op_e.Equal:
# NOTE: Using spid of RHS for now, since we don't have one for op.
self.AddErrorContext('Expected = in environment binding, got +=',
word=val)
@@ -422,7 +422,7 @@ def _MakeAssignment(self, assign_kw, suffix_words):
if not m:
self.AddErrorContext('Invalid variable name %r', static_val, word=w)
return None
a = (static_val, assign_op.Equal, None, left_spid)
a = (static_val, assign_op_e.Equal, None, left_spid)
assignments.append(a)
i += 1
View
@@ -14,6 +14,9 @@
from osh import parse_lib
from osh import ast_ as ast
from osh.lex import LEXER_DEF, LexMode
from osh import ast_ as ast
lex_mode_e = ast.lex_mode_e
def _InitLexer(s):
@@ -22,6 +25,13 @@ def _InitLexer(s):
return lexer
class AsdlTest(unittest.TestCase):
def testLexMode(self):
print lex_mode_e.DQ
CMD = """\
ls /
ls /home/
View
@@ -216,4 +216,30 @@ module osh
-- In-memory format for all the functions snipped out of a file.
partial_file = (string path, arena* funcs)
--
-- These types are not used in the LST. But they could be statically
-- from values in the LST.
--
-- NOTE: This is invalid: ASDL is case-sensitive!
-- OperandType = Undefined | Path | Int | Str | Other
-- RedirType = Path | Desc | Here
-- Also invalid because of duplicate 'Path' -- to fix
-- bool_operand_type = Undefined | Path | Int | Str | Other
-- redir_type = Path | Desc | Here
--
-- APIs
--
lex_mode =
NONE
| COMMENT
| OUTER
| DBRACKET
| SQ | DQ | DOLLAR_SQ
| ARITH
| EXTGLOB
| VS_1 | VS_2 | VS_ARG_UNQ | VS_ARG_DQ
| BASH_REGEX | BASH_REGEX_CHARS
}
View
@@ -7,28 +7,6 @@ set -o nounset
set -o pipefail
set -o errexit
replace() {
#sed -r -i 's/UNDEFINED_(.*)/Id.UNDEFINED_\1/g' */*.py
#sed -r -i 's/UNDEFINED_TOK/Id.UNDEFINED_Tok/g' */*.py
#sed -r -i 's/UNKNOWN_TOK/Id.UNKNOWN_Tok/g' */*.py
# http://stackoverflow.com/questions/1538676/uppercasing-first-letter-of-words-using-sed
# http://stackoverflow.com/questions/4569825/sed-one-liner-to-convert-all-uppercase-to-lowercase
# GNU extension: \u next character of match
# Finally, as a GNU `sed' extension, you can include a special sequence made
# of a backslash and one of the letters `L', `l', `U', `u', or `E'. The
# meaning is as follows:
# First make it all lower case
sed -r -i 's/Eof_([A-Z]+)/Id.Eof_\L\1/g' */*.py
# Now make the first one upper case
sed -r -i 's/Eof_([a-zA-Z]+)/Eof_\u\1/g' */*.py
}
# TODO:
# Rparen -> RParen, Dgreat -> DGreat, Colon_Hyphen -> ColonHyphen, etc.
# IGNORED_LINECONT -> IGNORED_LineCont
@@ -69,6 +47,7 @@ k2() {
replace() {
local file=$1
# NOTE: Escaping here is messed up. sed doesn't have --name like awk?
while read pat replace; do
sed -r -i "s/${pat}/${replace}/g" */*.py
done < $file
View
@@ -356,7 +356,7 @@ def DoAssignment(self, node, at_top_level, local_symbols):
defined_locally = False # is it a local variable in this function?
# can't tell if global
# We can change it from = to := or ::= (in pedantic mode)
new_assign_op = None
new_assign_op_e = None
if node.keyword == Id.Assign_Local:
# Assume that 'local' it's a declaration. In osh, it's an error if
@@ -396,18 +396,18 @@ def DoAssignment(self, node, at_top_level, local_symbols):
# Would be nice to assume that it's a local though.
if at_top_level:
self.f.write('global ') # can't be redefined
new_assign_op = '::='
new_assign_op_e = '::='
#self.f.write('global TODO := TODO') # mutate global or define it
elif defined_locally:
new_assign_op = ':=' # assume mutation of local
new_assign_op_e = ':=' # assume mutation of local
#self.f.write('[local mutated]')
else:
# we're in a function, but it's not defined locally.
self.f.write('global ') # assume mutation of local
if self.mode == PEDANTIC: # assume globals defined
new_assign_op = '::='
new_assign_op_e = '::='
else:
new_assign_op = ':='
new_assign_op_e = ':='
elif node.keyword == Id.Assign_Readonly:
# Explicit const. Assume it can't be redefined.
@@ -452,7 +452,7 @@ def DoAssignment(self, node, at_top_level, local_symbols):
# Replace name. I guess it's Lit_Chars.
self.f.write(pair.lhs.name)
op = new_assign_op if new_assign_op else '='
op = new_assign_op_e if new_assign_op_e else '='
self.f.write(' %s ' % op)
# foo=bar -> foo = 'bar'