Permalink
Browse files

Replace util.Enum OperandType with bool_arg_type in types.asdl.

Ran into the __hash__ problem again.  Still need to investigate.

Also:

- Don't report namespace conflicts for simple sum types.
- Rename to redir_arg_type to be consistent with bool_arg_type.
  • Loading branch information...
Andy Chu
Andy Chu committed Feb 7, 2018
1 parent 0b69297 commit f7b22d7df0311dc921064d25ce261fe31f4e5f8b
Showing with 67 additions and 46 deletions.
  1. +3 −0 asdl/asdl_.py
  2. +12 −0 asdl/py_meta.py
  3. +4 −4 core/cmd_exec.py
  4. +9 −8 core/expr_eval.py
  5. +23 −19 core/id_kind.py
  6. +14 −13 osh/meta.py
  7. +2 −2 osh/types.asdl
View
@@ -371,6 +371,9 @@ def visitType(self, type):
def visitSum(self, sum, name):
for t in sum.types:
# Simple sum types can't conflict
if is_simple(sum):
continue
self.visit(t, name)
def visitConstructor(self, cons, name):
View
@@ -111,6 +111,18 @@ def __init__(self, enum_id, name):
self.enum_id = enum_id
self.name = name
# TODO: Why is __hash__ needed? Otherwise native/fastlex_test.py fails.
# util.Enum required it too. I thought that instances would hash by
# identity?
#
# Example:
# class bool_arg_type_e(py_meta.SimpleObj):
# ASDL_TYPE = TYPE_LOOKUP.ByTypeName('bool_arg_type')
# bool_arg_type_e.Undefined = bool_arg_type_e(1, 'Undefined')
def __hash__(self):
return hash(self.__class__.__name__ + self.name)
def __repr__(self):
return '<%s %s %s>' % (self.__class__.__name__, self.name, self.enum_id)
View
@@ -49,7 +49,7 @@
EBuiltin = builtin.EBuiltin
lex_mode_e = types.lex_mode_e
redir_type_e = types.redir_type_e
redir_arg_type_e = types.redir_arg_type_e
command_e = ast.command_e
redir_e = ast.redir_e
@@ -424,7 +424,7 @@ def _EvalRedirect(self, n):
if n.tag == redir_e.Redir:
redir_type = REDIR_TYPE[n.op_id] # could be static in the LST?
if redir_type == redir_type_e.Path:
if redir_type == redir_arg_type_e.Path:
# NOTE: no globbing. You can write to a file called '*.py'.
val = self.word_ev.EvalWordToString(n.arg_word)
if val.tag != value_e.Str: # TODO: This error never fires
@@ -438,7 +438,7 @@ def _EvalRedirect(self, n):
return runtime.PathRedirect(n.op_id, fd, filename)
elif redir_type == redir_type_e.Desc: # e.g. 1>&2
elif redir_type == redir_arg_type_e.Desc: # e.g. 1>&2
val = self.word_ev.EvalWordToString(n.arg_word)
if val.tag != value_e.Str: # TODO: This error never fires
util.error("Redirect descriptor should be a string, got %s", val)
@@ -456,7 +456,7 @@ def _EvalRedirect(self, n):
return runtime.DescRedirect(n.op_id, fd, target_fd)
elif redir_type == redir_type_e.Here: # here word
elif redir_type == redir_arg_type_e.Here: # here word
# TODO: decay should be controlled by an option
val = self.word_ev.EvalWordToString(n.arg_word, decay=True)
if val.tag != value_e.Str: # TODO: This error never fires
View
@@ -17,8 +17,7 @@
except ImportError:
from benchmarks import fake_libc as libc
from osh.meta import BOOL_OPS, Id
from core.id_kind import OperandType
from osh.meta import BOOL_OPS, Id, types
from core import util
from osh.meta import runtime
@@ -28,6 +27,8 @@
warn = util.warn
e_die = util.e_die
bool_arg_type_e = types.bool_arg_type_e
arith_expr_e = ast.arith_expr_e
lhs_expr_e = ast.lhs_expr_e
bool_expr_e = ast.bool_expr_e # used for dispatch
@@ -481,7 +482,7 @@ def Eval(self, node):
# Now dispatch on arg type
arg_type = BOOL_OPS[op_id] # could be static in the LST?
if arg_type == OperandType.Path:
if arg_type == bool_arg_type_e.Path:
# Only use lstat if we're testing for a symlink.
if op_id in (Id.BoolUnary_h, Id.BoolUnary_L):
try:
@@ -518,15 +519,15 @@ def Eval(self, node):
raise NotImplementedError(op_id)
if arg_type == OperandType.Str:
if arg_type == bool_arg_type_e.Str:
if op_id == Id.BoolUnary_z:
return not bool(s)
if op_id == Id.BoolUnary_n:
return bool(s)
raise NotImplementedError(op_id)
if arg_type == OperandType.Other:
if arg_type == bool_arg_type_e.Other:
if op_id == Id.BoolUnary_t:
try:
fd = int(s)
@@ -551,7 +552,7 @@ def Eval(self, node):
# Now dispatch on arg type
arg_type = BOOL_OPS[op_id]
if arg_type == OperandType.Path:
if arg_type == bool_arg_type_e.Path:
st1 = os.stat(s1)
st2 = os.stat(s2)
@@ -563,7 +564,7 @@ def Eval(self, node):
raise NotImplementedError(op_id)
if arg_type == OperandType.Int:
if arg_type == bool_arg_type_e.Int:
# NOTE: We assume they are constants like [[ 3 -eq 3 ]].
# Bash also allows [[ 1+2 -eq 3 ]].
i1 = self._StringToIntegerOrError(s1)
@@ -584,7 +585,7 @@ def Eval(self, node):
raise NotImplementedError(op_id)
if arg_type == OperandType.Str:
if arg_type == bool_arg_type_e.Str:
# TODO:
# - Compare arrays. (Although bash coerces them to string first)
View
@@ -13,6 +13,7 @@
"""
from core import util
log = util.log
class IdSpec(object):
@@ -60,7 +61,7 @@ def _AddId(self, token_name, kind=None):
def _AddKind(self, kind_name):
# TODO: Should be instantiated or folded into ASDL.
setattr(self.kind_enum, kind_name, self.kind_index)
#util.log('%s = %d', kind_name, self.kind_index)
#log('%s = %d', kind_name, self.kind_index)
self.kind_index += 1
def AddKind(self, kind_name, tokens):
@@ -93,6 +94,8 @@ def AddKindPairs(self, kind_name, pairs):
def AddBoolKind(self, kind_name, arg_type_pairs):
"""
Args:
kind_name: string
arg_type_pairs: dictionary of bool_arg_type_e -> []
"""
lexer_pairs = []
num_tokens = 0
@@ -116,14 +119,14 @@ def AddBoolKind(self, kind_name, arg_type_pairs):
self._AddKind(kind_name)
self.kind_sizes.append(num_tokens) # debug info
def AddBoolBinaryForBuiltin(self, token_name, kind):
def AddBoolBinaryForBuiltin(self, token_name, kind, bool_arg_type_e):
"""For [ = ] [ == ] and [ != ].
These operators are NOT added to the lexer. The are "lexed" as StringWord.
"""
token_name = 'BoolBinary_%s' % token_name
id_val = self._AddId(token_name, kind=kind)
self.AddBoolOp(id_val, OperandType.Str)
self.AddBoolOp(id_val, bool_arg_type_e.Str)
return id_val
def AddBoolOp(self, id_, arg_type):
@@ -371,41 +374,40 @@ def AddKinds(spec):
_BINARY_PATH = ['ef', 'nt', 'ot']
_BINARY_INT = ['eq', 'ne', 'gt', 'ge', 'lt', 'le']
OperandType = util.Enum('OperandType', 'Undefined Path Int Str Other'.split())
def _Dash(strs):
# Gives a pair of (token name, string to match)
return [(s, '-' + s) for s in strs]
def AddBoolKinds(spec, Id):
def AddBoolKinds(spec, Id, bool_arg_type_e):
spec.AddBoolKind('BoolUnary', {
OperandType.Str: _Dash(list(_UNARY_STR_CHARS)),
OperandType.Other: _Dash(list(_UNARY_OTHER_CHARS)),
OperandType.Path: _Dash(list(_UNARY_PATH_CHARS)),
bool_arg_type_e.Str: _Dash(list(_UNARY_STR_CHARS)),
bool_arg_type_e.Other: _Dash(list(_UNARY_OTHER_CHARS)),
bool_arg_type_e.Path: _Dash(list(_UNARY_PATH_CHARS)),
})
spec.AddBoolKind('BoolBinary', {
OperandType.Str: [
bool_arg_type_e.Str: [
('GlobEqual', '='), ('GlobDEqual', '=='), ('GlobNEqual', '!='),
('EqualTilde', '=~'),
],
OperandType.Path: _Dash(_BINARY_PATH),
OperandType.Int: _Dash(_BINARY_INT),
bool_arg_type_e.Path: _Dash(_BINARY_PATH),
bool_arg_type_e.Int: _Dash(_BINARY_INT),
})
# logical, arity, arg_type
spec.AddBoolOp(Id.Op_DAmp, OperandType.Undefined)
spec.AddBoolOp(Id.Op_DPipe, OperandType.Undefined)
spec.AddBoolOp(Id.KW_Bang, OperandType.Undefined)
spec.AddBoolOp(Id.Op_DAmp, bool_arg_type_e.Undefined)
spec.AddBoolOp(Id.Op_DPipe, bool_arg_type_e.Undefined)
spec.AddBoolOp(Id.KW_Bang, bool_arg_type_e.Undefined)
spec.AddBoolOp(Id.Redir_Less, OperandType.Str)
spec.AddBoolOp(Id.Redir_Great, OperandType.Str)
spec.AddBoolOp(Id.Redir_Less, bool_arg_type_e.Str)
spec.AddBoolOp(Id.Redir_Great, bool_arg_type_e.Str)
def SetupTestBuiltin(Id, Kind, id_spec,
unary_lookup, binary_lookup, other_lookup):
unary_lookup, binary_lookup, other_lookup,
bool_arg_type_e):
"""Setup tokens for test/[.
Similar to _AddBoolKinds above. Differences:
@@ -425,7 +427,9 @@ def SetupTestBuiltin(Id, Kind, id_spec,
for token_name, token_str in [
('Equal', '='), ('DEqual', '=='), ('NEqual', '!=')]:
id_val = id_spec.AddBoolBinaryForBuiltin(token_name, Kind.BoolBinary)
id_val = id_spec.AddBoolBinaryForBuiltin(token_name, Kind.BoolBinary,
bool_arg_type_e)
binary_lookup[token_str] = id_val
# Some of these names don't quite match, but it keeps the BoolParser simple.
View
@@ -14,7 +14,7 @@
from asdl import py_meta
from asdl import asdl_ as asdl
from core import id_kind
from core import id_kind
from core import util
@@ -91,7 +91,7 @@ def IdInstance(i):
f.close()
# Id -> OperandType
# Id -> bool_arg_type_e
BOOL_OPS = {} # type: dict
# Used by test_builtin.py
@@ -109,10 +109,11 @@ def IdInstance(i):
BOOL_OPS)
id_kind.AddKinds(ID_SPEC)
id_kind.AddBoolKinds(ID_SPEC, Id) # must come second
id_kind.AddBoolKinds(ID_SPEC, Id, types.bool_arg_type_e) # must come second
id_kind.SetupTestBuiltin(Id, Kind, ID_SPEC,
TEST_UNARY_LOOKUP, TEST_BINARY_LOOKUP,
TEST_OTHER_LOOKUP)
TEST_OTHER_LOOKUP,
types.bool_arg_type_e)
# Debug
_kind_sizes = ID_SPEC.kind_sizes
@@ -185,20 +186,20 @@ def IdInstance(i):
Id.Redir_DLessDash: 0,
}
redir_type_e = types.redir_type_e
redir_arg_type_e = types.redir_arg_type_e
REDIR_TYPE = {
# filename
Id.Redir_Less: redir_type_e.Path,
Id.Redir_Great: redir_type_e.Path,
Id.Redir_DGreat: redir_type_e.Path,
Id.Redir_Clobber: redir_type_e.Path,
Id.Redir_LessGreat: redir_type_e.Path,
Id.Redir_Less: redir_arg_type_e.Path,
Id.Redir_Great: redir_arg_type_e.Path,
Id.Redir_DGreat: redir_arg_type_e.Path,
Id.Redir_Clobber: redir_arg_type_e.Path,
Id.Redir_LessGreat: redir_arg_type_e.Path,
# descriptor
Id.Redir_GreatAnd: redir_type_e.Desc,
Id.Redir_LessAnd: redir_type_e.Desc,
Id.Redir_GreatAnd: redir_arg_type_e.Desc,
Id.Redir_LessAnd: redir_arg_type_e.Desc,
Id.Redir_TLess: redir_type_e.Here, # here word
Id.Redir_TLess: redir_arg_type_e.Here, # here word
# note: here docs aren't included
}
View
@@ -2,8 +2,8 @@
module types {
-- Also invalid because of duplicate 'Path' -- to fix
-- bool_operand_type = Undefined | Path | Int | Str | Other
redir_type = Path | Desc | Here
bool_arg_type = Undefined | Path | Int | Str | Other
redir_arg_type = Path | Desc | Here
-- Fifteen lexer modes for osh.
-- Possible additional modes:

0 comments on commit f7b22d7

Please sign in to comment.