Skip to content
Permalink
Browse files

[translation] osh/word_parse_.py now translates

There were a handful of issues to fix.

It still has over 50 compile errors (via examples/pgen2_demo)
  • Loading branch information
Andy Chu
Andy Chu committed Nov 16, 2019
1 parent 026361d commit 6756cc29e3cf757684314896cd5fff917f7df0e3
Showing with 78 additions and 48 deletions.
  1. +4 −4 mycpp/const_pass.py
  2. +67 −34 mycpp/cppgen_pass.py
  3. +1 −1 mycpp/examples.sh
  4. +6 −9 osh/word_parse.py
@@ -497,10 +497,10 @@ def visit_try_stmt(self, o: 'mypy.nodes.TryStmt') -> T:
for t, v, handler in zip(o.types, o.vars, o.handlers):
self.accept(handler)

if o.else_body:
raise AssertionError('try/else not supported')
if o.finally_body:
raise AssertionError('try/finally not supported')
#if o.else_body:
# raise AssertionError('try/else not supported')
#if o.finally_body:
# raise AssertionError('try/finally not supported')

def visit_print_stmt(self, o: 'mypy.nodes.PrintStmt') -> T:
pass
@@ -43,6 +43,34 @@ def _GetCastKind(module_path, subtype_name):
return cast_kind


def _GetContainsFunc(t):
contains_func = None

if isinstance(t, Instance):
type_name = t.type.fullname()

if type_name == 'builtins.list':
contains_func = 'list_contains'

elif type_name == 'builtins.str':
contains_func = 'str_contains'

elif type_name == 'builtins.dict':
contains_func = 'dict_contains'

elif isinstance(t, UnionType):
# Special case for Optional[T] == Union[T, None]
if len(t.items) != 2:
raise NotImplementedError('Expected Optional, got %s' % t)

if not isinstance(t.items[1], NoneTyp):
raise NotImplementedError('Expected Optional, got %s' % t)

contains_func = _GetContainsFunc(t.items[0])

return contains_func # None checked later


def get_c_type(t):
if isinstance(t, NoneTyp): # e.g. a function that doesn't return anything
return 'void'
@@ -656,15 +684,7 @@ def visit_comparison_expr(self, o: 'mypy.nodes.ComparisonExpr') -> T:
# Note: we could get rid of this altogether and rely on C++ function
# overloading. But somehow I like it more explicit, closer to C (even
# though we use templates).
contains_func = None
if isinstance(t1, Instance):
right_type_name = t1.type.fullname()
if right_type_name == 'builtins.list':
contains_func = 'list_contains'
elif right_type_name == 'builtins.str':
contains_func = 'str_contains'
elif right_type_name == 'builtins.dict':
contains_func = 'dict_contains'
contains_func = _GetContainsFunc(t1)

if operator == 'in':
if isinstance(right, TupleExpr):
@@ -681,7 +701,7 @@ def visit_comparison_expr(self, o: 'mypy.nodes.ComparisonExpr') -> T:
self.write(')')
return

assert contains_func, right_type_name
assert contains_func, t1
# x in mylist => list_contains(mylist, x)
self.write('%s(', contains_func)
self.accept(right)
@@ -691,7 +711,21 @@ def visit_comparison_expr(self, o: 'mypy.nodes.ComparisonExpr') -> T:
return

if operator == 'not in':
assert contains_func, right_type_name
if isinstance(right, TupleExpr):
# x not in (1, 2, 3) => (x != 1 && x != 2 && x != 3)
self.write('(')

for i, item in enumerate(right.items):
if i != 0:
self.write(' && ')
self.accept(left)
self.write(' != ')
self.accept(item)

self.write(')')
return

assert contains_func, t1

# x not in mylist => !list_contains(mylist, x)
self.write('!%s(', contains_func)
@@ -1325,26 +1359,25 @@ def visit_func_def(self, o: 'mypy.nodes.FuncDef') -> T:
if (self.current_class_name and o.name() == '_Next' and
len(o.arguments) == 2):
default_val = o.arguments[1].initializer
assert default_val

if self.decl:
func_name = o.name()
else:
func_name = '%s::%s' % (self.current_class_name, o.name())
self.write('\n')
if default_val: # e.g. osh/bool_parse.py has default val
if self.decl:
func_name = o.name()
else:
func_name = '%s::%s' % (self.current_class_name, o.name())
self.write('\n')

# Write _Next() with no args
virtual = ''
c_type = get_c_type(o.type.ret_type)
self.decl_write_ind('%s%s %s()', virtual, c_type, func_name)
if self.decl:
self.decl_write(';\n')
else:
self.write(' {\n')
self.write(' _Next(')
self.accept(default_val) # e.g. lex_mode_e::DBracket
self.write(');\n')
self.write('}\n')
# Write _Next() with no args
virtual = ''
c_type = get_c_type(o.type.ret_type)
self.decl_write_ind('%s%s %s()', virtual, c_type, func_name)
if self.decl:
self.decl_write(';\n')
else:
self.write(' {\n')
self.write(' _Next(')
self.accept(default_val) # e.g. lex_mode_e::DBracket
self.write(');\n')
self.write('}\n')

virtual = ''
if self.decl:
@@ -1795,10 +1828,10 @@ def visit_try_stmt(self, o: 'mypy.nodes.TryStmt') -> T:
self.write_ind('catch (%s) ', c_type)
self.accept(handler)

if o.else_body:
raise AssertionError('try/else not supported')
if o.finally_body:
raise AssertionError('try/finally not supported')
#if o.else_body:
# raise AssertionError('try/else not supported')
#if o.finally_body:
# raise AssertionError('try/finally not supported')

def visit_print_stmt(self, o: 'mypy.nodes.PrintStmt') -> T:
pass
@@ -300,9 +300,9 @@ namespace arith_nt {
$REPO_ROOT/oil_lang/expr_to_ast.py \
$REPO_ROOT/osh/word_.py \
$REPO_ROOT/osh/bool_parse.py \
$REPO_ROOT/osh/word_parse.py \
examples/$name.py

# $REPO_ROOT/osh/word_parse.py \
# try/finally not supported

# TODO: these files need their own test cases, for shorter generated code
@@ -85,6 +85,9 @@

_ = log

KINDS_THAT_END_WORDS = [Kind.Eof, Kind.WS, Kind.Op, Kind.Right]


class WordParser(object):

def __init__(self, parse_ctx, lexer, line_reader,
@@ -1135,8 +1138,6 @@ def _ParseCallArguments(self, arglist):
# Call into expression language.
self.parse_ctx.ParseOilArgList(self.lexer, arglist)

KINDS_THAT_END_WORDS = (Kind.Eof, Kind.WS, Kind.Op, Kind.Right)

def _ReadCompoundWord(self, eof_type=Id.Undefined_Tok,
lex_mode=lex_mode_e.ShCommand, empty_ok=True):
# type: (Id_t, lex_mode_t, bool) -> word__Compound
@@ -1182,7 +1183,7 @@ def _ReadCompoundWord(self, eof_type=Id.Undefined_Tok,
self._Next(lex_mode)
self._Peek()
# EOF, whitespace, newline, Right_Subshell
if self.token_kind not in self.KINDS_THAT_END_WORDS:
if self.token_kind not in KINDS_THAT_END_WORDS:
p_die('Unexpected token after array literal',
token=self.cur_token)
done = True
@@ -1206,7 +1207,7 @@ def _ReadCompoundWord(self, eof_type=Id.Undefined_Tok,
self._Next(lex_mode)
self._Peek()
# EOF, whitespace, newline, Right_Subshell
if self.token_kind not in self.KINDS_THAT_END_WORDS:
if self.token_kind not in KINDS_THAT_END_WORDS:
p_die('Unexpected token after array splice',
token=self.cur_token)
done = True
@@ -1332,9 +1333,7 @@ def _ReadArithWord(self):
return w, False

else:
assert False, ("Unexpected token parsing arith sub: %s" % self.cur_token)

raise AssertionError("Shouldn't get here")
raise AssertionError(self.cur_token)

def _ReadWord(self, lex_mode):
# type: (lex_mode_t) -> Tuple[word_t, bool]
@@ -1399,8 +1398,6 @@ def _ReadWord(self, lex_mode):
raise AssertionError(
'Unhandled: %s (%s)' % (self.cur_token, self.token_kind))

raise AssertionError("Shouldn't get here")

def LookAhead(self):
# type: () -> Id_t
"""Look ahead to the next token.

0 comments on commit 6756cc2

Please sign in to comment.
You can’t perform that action at this time.