def _is_unascribed_match_head(cls, e):
if isinstance(e, ast.Subscript):
value = e.value
if isinstance(value, ast.Name) and value.id == 'match':
slice = e.slice
if isinstance(slice, ast.Index):
e.is_match_head = True
e.scrutinee = slice.value
e.asc_ast = None
return True
else:
raise _errors.TyError("Invalid match scrutinee.", e)
return False
python类Index()的实例源码
def _translate_subscript(self, value, slice, ctx, location):
value_node = self._translate_node(value)
value_general_type = self._general_type(value_node['pseudo_type'])
if value_general_type not in INDEXABLE_TYPES:
raise type_check_error('pseudo-python can use [] only on String, List, Dictionary or Tuple',
location, self.lines[location[0]],
wrong_type=value_node['pseudo_type'])
if isinstance(slice, ast.Index):
z = self._translate_node(slice.value)
if value_general_type in ['String', 'List', 'Tuple'] and z['pseudo_type'] != 'Int':
raise PseudoPythonTypeCheckError('a non int index for %s %s' % (value_general_type, z['pseudo_type']))
if value_general_type == 'Dictionary' and z['pseudo_type'] != value_node['pseudo_type'][1]:
raise PseudoPythonTypeCheckError('a non %s index for %s %s' % (value_node['pseudo_type'][1], value_general_type, z['pseudo_type']))
if value_general_type == 'String':
pseudo_type = 'String'
elif value_general_type == 'List' or value_general_type == 'Array':
pseudo_type = value_node['pseudo_type'][1]
elif value_general_type == 'Tuple':
if z['type'] != 'int':
raise PseudoPythonTypeCheckError('pseudo-python can support only literal int indices of a heterogenous tuple ' +
'because otherwise the index type is not predictable %s %s ' % (serialize_type(value_node['pseudo_type']), z['type']))
elif z['value'] > len(value_node['pseudo_type']) - 2:
raise PseudoPythonTypeCheckError('%s has only %d elements' % serialize_type(value_node['pseudo_type']), len(value_node['pseudo_type']))
pseudo_type = value_node['pseudo_type'][z['value'] + 1]
else:
pseudo_type = value_node['pseudo_type'][2]
if 'special' in value_node: # sys.argv[index]
if z['pseudo_type'] != 'Int':
raise type_check_error('pseudo-python supports only int indices for sys.argv',
location, self.lines[location[0]],
wrong_type=z['pseudo_type'])
return {
'type': 'standard_call',
'namespace': 'system',
'function': 'index',
'args': [z],
'pseudo_type': 'String'
}
result = {
'type': 'index',
'sequence': value_node,
'index': z,
'pseudo_type': pseudo_type
}
if result in self._tuple_assigned:
j = z.get('value', z.get('name', z.get('attr', '_x')))
k = value_node.get('value', value_node.get('name', value_node.get('attr', '_y')))
# i kno c:
if not any(a[0] == '_old_%s_%s' % (j, k) for a in self._tuple_used):
self._tuple_used.append(('_old_%s_%s' % (j, k), result))
result = {'type': 'local', 'name': '_old_%s_%s' % (j, k), 'pseudo_type': pseudo_type}
return result
else:
return self._translate_slice(receiver=value_node, upper=slice.upper, step=slice.step, lower=slice.lower, location=location)
def _hint(self, x):
if isinstance(x, (ast.Name, ast.Str)):
name = x.id if isinstance(x, ast.Name) else x.s
if name in BUILTIN_SIMPLE_TYPES:
return BUILTIN_SIMPLE_TYPES[name]
elif name in self.type_env.top.values:
return name
elif isinstance(x, ast.Subscript) and isinstance(x.value, (ast.Name, ast.Str)):
name = x.value.id if isinstance(x.value, ast.Name) else x.value.s
if name in ['List', 'Set', 'Dict', 'Tuple', 'Callable']:
if name not in self._typing_imports:
raise translation_error('please add\nfrom typing import %s on top to use it\n' % name, (x.value.lineno, x.value.col_offset), self.lines[x.value.lineno])
if not isinstance(x.slice, ast.Index):
raise translation_error('invalid index', (x.value.lineno, x.value.col_offset), self.lines[x.lineno])
index = x.slice.value
if name in ['List', 'Set']:
if not isinstance(index, (ast.Name, ast.Subscript)):
raise type_check_error('%s expects one valid generic arguments' % name, (x.value.lineno, x.value.col_offset), self.lines[x.value.lineno])
return [name, self._hint(index)]
elif name == 'Tuple':
if not isinstance(index, ast.Tuple) or any(not isinstance(y, (ast.Name, ast.Subscript)) for y in index.elts):
raise type_check_error('Tuple expected valid generic arguments', (x.value.lineno, x.value.col_offset), self.lines[x.value.lineno])
return ['Tuple'] + [self._hint(y) for y in index.elts]
elif name == 'Dict':
if not isinstance(index, ast.Tuple) or len(index.elts) != 2 or not isinstance(index.elts[1], (ast.Name, ast.Subscript)):
raise type_check_error('Dict expected 2 valid generic arguments', (x.value.lineno, x.value.col_offset), self.lines[x.value.lineno])
if not isinstance(index.elts[0], ast.Name) or index.elts[0].id not in KEY_TYPES:
raise type_check_error('type not supported as a dictionary key type', (x.value.lineno, x.value.col_offset), self.lines[x.value.lineno],
suggestions='only those types are supported:\n %s ' % '\n '.join(PSEUDO_KEY_TYPES),
right=' Dict[str, List[int]]',
wrong=' Dict[List[int], Tuple[int]]')
return ['Dictionary', self._hint(index.elts[0]), self._hint(index.elts[1])]
else:
if not isinstance(index, ast.Tuple) or len(index.elts) != 2 or not isinstance(index.elts[0], ast.List) or not isinstance(index.elts[1], (ast.Name, ast.Subscript)) or any(not isinstance(y, (ast.Name, ast.Subscript)) for y in index.elts[0].elts):
raise type_check_error('Callable expected valid generic arguments of the form Callable[[<arg_type>, <arg_type>*], <return>]', (x.value.lineno, x.value.col_offset), self.lines[x.value.lineno])
return ['Function'] + [self._hint(y) for y in index.elts[0].elts] + [self._hint(index.elts[1])]
raise type_check_error('type not recognized',
(x.lineno, x.col_offset), self.lines[x.lineno],
suggestions='supported type hints are:\n ' + '\n '.join(
['int', 'float', 'str', 'bool',
'List[<element_hint>]', 'Dict[<key_hint>, <value_hint>]', 'Tuple[<element_hints>..]', 'Set[<element_hint>]', 'Callable[[<arg_hint>*], <return_hin>]'
'your class e.g. Human']))
def visit_Delete(self, node):
"""
Delete(expr* targets)
"""
id = ''
num = ''
key = ''
slice = ''
attr = ''
for stmt in node.targets:
if isinstance(stmt, (ast.Name)):
id = self.visit(stmt)
elif isinstance(stmt, (ast.Subscript)):
if isinstance(stmt.value, (ast.Name)):
id = self.visit(stmt.value)
if isinstance(stmt.slice, (ast.Index)):
if isinstance(stmt.slice.value, (ast.Str)):
key = self.visit(stmt.slice)
if isinstance(stmt.slice.value, (ast.Num)):
num = self.visit(stmt.slice)
if isinstance(stmt.slice, (ast.Slice)):
slice = self.visit(stmt.slice)
elif isinstance(stmt, (ast.Attribute)):
if isinstance(stmt.value, (ast.Name)):
id = self.visit(stmt.value)
attr = stmt.attr
if num != '':
""" <Python> del foo[0]
<Ruby> foo.delete_at[0] """
self.write("%s.delete_at(%s)" % (id, num))
elif key != '':
""" <Python> del foo['hoge']
<Ruby> foo.delete['hoge'] """
self.write("%s.delete(%s)" % (id, key))
elif slice != '':
""" <Python> del foo[1:3]
<Ruby> foo.slise!(1...3) """
self.write("%s.slice!(%s)" % (id, slice))
elif attr != '':
""" <Python> del foo.bar
<Ruby> foo.instance_eval { remove_instance_variable(:@bar) } """
self.write("%s.instance_eval { remove_instance_variable(:@%s) }" % (id, attr))
else:
""" <Python> del foo
<Ruby> foo = nil """
self.write("%s = nil" % (id))
def visit_Assign(self, node):
"""
Assign(expr* targets, expr value)
"""
assert len(node.targets) == 1
target = node.targets[0]
#~ if self._class_name:
#~ target = self._class_name + '.' + target
# ast.Tuple, ast.List, ast.*
value = self.visit(node.value)
#if isinstance(node.value, (ast.Tuple, ast.List)):
# value = "[%s]" % self.visit(node.value)
#else:
# value = self.visit(node.value)
if isinstance(target, (ast.Tuple, ast.List)):
# multiassign.py
""" x, y, z = [1, 2, 3] """
x = [self.visit(t) for t in target.elts]
self.write("%s = %s" % (','.join(x), value))
elif isinstance(target, ast.Subscript) and isinstance(target.slice, ast.Index):
# found index assignment # a[0] = xx
#self.write("%s%s = %s" % (self.visit(target.value), # a[0] = xx
name = self.visit(target.value)
for arg in self._function_args:
if arg == ("**%s" % name):
self._is_string_symbol = True
self.write("%s[%s] = %s" % (name, self.visit(target.slice), value))
self._is_string_symbol = False
elif isinstance(target, ast.Subscript) and isinstance(target.slice, ast.Slice):
# found slice assignmnet
self.write("%s[%s...%s] = %s" % (self.visit(target.value),
self.visit(target.slice.lower), self.visit(target.slice.upper),
value))
else:
if isinstance(target, ast.Name):
var = self.visit(target)
if not (var in self._scope):
self._scope.append(var)
if isinstance(node.value, ast.Call):
if isinstance(node.value.func, ast.Name):
if node.value.func.id in self._class_names:
self._classes_self_functions_args[var] = self._classes_self_functions_args[node.value.func.id]
# set lambda functions
if isinstance(node.value, ast.Lambda):
self._lambda_functions.append(var)
self.write("%s = %s" % (var, value))
elif isinstance(target, ast.Attribute):
var = self.visit(target)
""" [instance variable] :
<Python> self.foo = hoge
<Ruby> @foo = hoge
"""
if var == 'self':
self.write("@%s = %s" % (str(target.attr), value))
self._class_self_variables.append(str(target.attr))
else:
self.write("%s = %s" % (var, value))
else:
raise RubyError("Unsupported assignment type")