Ejemplo n.º 1
0
    def runsource(self, source, filename='<input>', symbol='single'):
        global SIMPLE_TRACEBACKS
        try:
            tokens = tokenize(source)
        except PrematureEndOfInput:
            return True
        except LexException as e:
            if e.source is None:
                e.source = source
                e.filename = filename
            sys.stderr.write(str_type(e))
            return False

        try:
            _ast = hy_compile(tokens, "__console__", root=ast.Interactive)
            if self.spy:
                print_python_code(_ast)
            code = ast_compile(_ast, filename, symbol)
        except HyTypeError as e:
            if e.source is None:
                e.source = source
                e.filename = filename
            if SIMPLE_TRACEBACKS:
                sys.stderr.write(str_type(e))
            else:
                self.showtraceback()
            return False
        except Exception:
            self.showtraceback()
            return False

        self.runcode(code)
        return False
Ejemplo n.º 2
0
Archivo: parser.py Proyecto: tuturto/hy
def mangle(s):
    """Stringify the argument and convert it to a valid Python identifier
    according to Hy's mangling rules."""

    assert s

    s = str_type(s)

    s = s.replace("-", "_")
    s2 = s.lstrip('_')
    leading_underscores = '_' * (len(s) - len(s2))
    s = s2

    if s.endswith("?"):
        s = 'is_' + s[:-1]
    if not isidentifier(leading_underscores + s):
        # Replace illegal characters with their Unicode character
        # names, or hexadecimal if they don't have one.
        s = 'hyx_' + ''.join(
            c
               if c != mangle_delim and isidentifier('S' + c)
                 # We prepend the "S" because some characters aren't
                 # allowed at the start of an identifier.
               else '{0}{1}{0}'.format(mangle_delim,
                   unicodedata.name(c, '').lower().replace('-', 'H').replace(' ', '_')
                   or 'U{:x}'.format(ord(c)))
            for c in s)

    s = leading_underscores + s
    assert isidentifier(s)
    return s
Ejemplo n.º 3
0
def macroexpand_1(tree, module_name):
    """Expand the toplevel macro from `tree` once, in the context of
    `module_name`."""
    if isinstance(tree, HyExpression):
        if tree == []:
            return tree

        fn = tree[0]
        if fn in ("quote", "quasiquote"):
            return tree
        ntree = HyExpression(tree[:])
        ntree.replace(tree)

        if isinstance(fn, HyString):
            m = _hy_macros[module_name].get(fn)
            if m is None:
                m = _hy_macros[None].get(fn)
            if m is not None:
                try:
                    obj = _wrap_value(m(*ntree[1:]))
                except HyTypeError as e:
                    if e.expression is None:
                        e.expression = tree
                    raise
                except Exception as e:
                    msg = "expanding `" + str_type(tree[0]) + "': " + repr(e)
                    raise HyMacroExpansionError(tree, msg)
                obj.replace(tree)
                return obj

        return ntree
    return tree
Ejemplo n.º 4
0
def mangle(s):
    """Stringify the argument and convert it to a valid Python identifier
    according to Hy's mangling rules."""
    def unicode_char_to_hex(uchr):
        # Covert a unicode char to hex string, without prefix
        return uchr.encode('unicode-escape').decode('utf-8').lstrip(
            '\\U').lstrip('\\u').lstrip('0')

    assert s

    s = str_type(s)
    s = s.replace("-", "_")
    s2 = s.lstrip('_')
    leading_underscores = '_' * (len(s) - len(s2))
    s = s2

    if s.endswith("?"):
        s = 'is_' + s[:-1]
    if not isidentifier(leading_underscores + s):
        # Replace illegal characters with their Unicode character
        # names, or hexadecimal if they don't have one.
        s = 'hyx_' + ''.join(
            c if c != mangle_delim and isidentifier('S' + c)
            # We prepend the "S" because some characters aren't
            # allowed at the start of an identifier.
            else '{0}{1}{0}'.format(
                mangle_delim,
                unicodedata.name(c, '').lower().replace('-', 'H').
                replace(' ', '_') or 'U{}'.format(unicode_char_to_hex(c)))
            for c in unicode_to_ucs4iter(s))

    s = leading_underscores + s
    assert isidentifier(s)
    return s
Ejemplo n.º 5
0
def require(source_module, target_module, assignments, prefix=""):
    """Load macros from `source_module` in the namespace of
    `target_module`. `assignments` maps old names to new names, or
    should be the string "ALL". If `prefix` is nonempty, it is
    prepended to the name of each imported macro. (This means you get
    macros named things like "mymacromodule.mymacro", which looks like
    an attribute of a module, although it's actually just a symbol
    with a period in its name.)

    This function is called from the `require` special form in the compiler.

    """

    seen_names = set()
    if prefix:
        prefix += "."
    if assignments != "ALL":
        assignments = {mangle(str_type(k)): v for k, v in assignments}

    for d in _hy_macros, _hy_tag:
        for name, macro in d[source_module].items():
            seen_names.add(name)
            if assignments == "ALL":
                d[target_module][mangle(prefix + name)] = macro
            elif name in assignments:
                d[target_module][mangle(prefix + assignments[name])] = macro

    if assignments != "ALL":
        unseen = frozenset(assignments.keys()).difference(seen_names)
        if unseen:
            raise ImportError("cannot require names: " + repr(list(unseen)))
Ejemplo n.º 6
0
Archivo: macros.py Proyecto: kartikm/hy
def require(source_module, target_module, assignments, prefix=""):
    """Load macros from `source_module` in the namespace of
    `target_module`. `assignments` maps old names to new names, or
    should be the string "ALL". If `prefix` is nonempty, it is
    prepended to the name of each imported macro. (This means you get
    macros named things like "mymacromodule.mymacro", which looks like
    an attribute of a module, although it's actually just a symbol
    with a period in its name.)

    This function is called from the `require` special form in the compiler.

    """

    seen_names = set()
    if prefix:
        prefix += "."
    if assignments != "ALL":
        assignments = {mangle(str_type(k)): v for k, v in assignments}

    for d in _hy_macros, _hy_tag:
        for name, macro in d[source_module].items():
            seen_names.add(name)
            if assignments == "ALL":
                d[target_module][mangle(prefix + name)] = macro
            elif name in assignments:
                d[target_module][mangle(prefix + assignments[name])] = macro

    if assignments != "ALL":
        unseen = frozenset(assignments.keys()).difference(seen_names)
        if unseen:
            raise ImportError("cannot require names: " + repr(list(unseen)))
Ejemplo n.º 7
0
 def __str__(self):
     if isinstance(self.exception, HyTypeError):
         return str_type(self.exception)
     if self.traceback:
         tb = "".join(traceback.format_tb(self.traceback)).strip()
     else:
         tb = "No traceback available. 😟"
     return("Internal Compiler Bug 😱\n⤷ %s: %s\nCompilation traceback:\n%s"
            % (self.exception.__class__.__name__,
               self.exception, tb))
Ejemplo n.º 8
0
def test_unicode_exception_messages():
    """Ensure we can generate error messages containing unicode."""
    try:
        hy_compile(tokenize("(defmacro ❤ () (throw Exception)) (❤)"),
                   "__main__")
        assert False
    except HyMacroExpansionError as e:
        assert isinstance(e.expression, HyObject)
        message = str_type(e)
        assert '❤' in message
        assert "Exception()" in message
Ejemplo n.º 9
0
def run_file(filename):
    from hy.importer import import_file_to_module
    try:
        import_file_to_module("__main__", filename)
    except (HyTypeError, LexException) as e:
        if SIMPLE_TRACEBACKS:
            sys.stderr.write(str_type(e))
            return 1
        raise
    except Exception:
        raise
    return 0
Ejemplo n.º 10
0
def run_command(source):
    try:
        if not PY3:
            # TODO: Encoding type should depend on locale.
            source = source.decode('utf-8')
        import_buffer_to_module("__main__", source)
    except (HyTypeError, LexException) as e:
        if SIMPLE_TRACEBACKS:
            sys.stderr.write(str_type(e))
            return 1
        raise
    except Exception:
        raise
    return 0
Ejemplo n.º 11
0
def macroexpand_1(tree, compiler):
    """Expand the toplevel macro from `tree` once, in the context of
    `module_name`."""
    if isinstance(tree, HyExpression):
        if tree == []:
            return tree

        fn = tree[0]
        if fn in ("quote", "quasiquote"):
            return tree
        ntree = HyExpression(tree[:])
        ntree.replace(tree)

        opts = {}

        if isinstance(fn, HySymbol):
            fn = mangle(str_type(fn))
            m = _hy_macros[compiler.module_name].get(fn)
            if m is None:
                m = _hy_macros[None].get(fn)
            if m is not None:
                if m._hy_macro_pass_compiler:
                    opts['compiler'] = compiler

                try:
                    m_copy = make_empty_fn_copy(m)
                    m_copy(compiler.module_name, *ntree[1:], **opts)
                except TypeError as e:
                    msg = "expanding `" + str(tree[0]) + "': "
                    msg += str(e).replace("<lambda>()", "", 1).strip()
                    raise HyMacroExpansionError(tree, msg)

                try:
                    obj = m(compiler.module_name, *ntree[1:], **opts)
                except HyTypeError as e:
                    if e.expression is None:
                        e.expression = tree
                    raise
                except Exception as e:
                    msg = "expanding `" + str(tree[0]) + "': " + repr(e)
                    raise HyMacroExpansionError(tree, msg)
                replace_hy_obj(obj, tree)
                return obj
        return ntree
    return tree
Ejemplo n.º 12
0
    def __str__(self):

        line = self.expression.start_line
        start = self.expression.start_column
        end = self.expression.end_column

        source = []
        if self.source is not None:
            source = self.source.split("\n")[line-1:self.expression.end_line]

            if line == self.expression.end_line:
                length = end - start
            else:
                length = len(source[0]) - start

        result = ""

        result += '  File "%s", line %d, column %d\n\n' % (self.filename,
                                                           line,
                                                           start)

        if len(source) == 1:
            result += '  %s\n' % colored.red(source[0])
            result += '  %s%s\n' % (' '*(start-1),
                                    colored.green('^' + '-'*(length-1) + '^'))
        if len(source) > 1:
            result += '  %s\n' % colored.red(source[0])
            result += '  %s%s\n' % (' '*(start-1),
                                    colored.green('^' + '-'*length))
            if len(source) > 2:  # write the middle lines
                for line in source[1:-1]:
                    result += '  %s\n' % colored.red("".join(line))
                    result += '  %s\n' % colored.green("-"*len(line))

            # write the last line
            result += '  %s\n' % colored.red("".join(source[-1]))
            result += '  %s\n' % colored.green('-'*(end-1) + '^')

        result += str_type(colored.yellow("%s: %s\n\n" %
                                          (self.__class__.__name__,
                                           self.message)))

        return result
Ejemplo n.º 13
0
def hy_symbol_unmangle(p):
    # hy_symbol_mangle is one-way, so this can't be perfect.
    # But it can be useful till we have a way to get the original
    # symbol (https://github.com/hylang/hy/issues/360).
    p = str_type(p)

    if p.endswith("_bang") and p != "_bang":
        p = p[:-len("_bang")] + "!"

    if p.startswith("is_") and p != "is_":
        p = p[len("is_"):] + "?"

    if "_" in p and p != "_":
        p = p.replace("_", "-")

    if (all([c.isalpha() and c.isupper() or c == '_' for c in p])
            and any([c.isalpha() for c in p])):
        p = '*' + p.lower() + '*'

    return p
Ejemplo n.º 14
0
def hy_symbol_unmangle(p):
    # hy_symbol_mangle is one-way, so this can't be perfect.
    # But it can be useful till we have a way to get the original
    # symbol (https://github.com/hylang/hy/issues/360).
    p = str_type(p)

    if p.endswith("_bang") and p != "_bang":
        p = p[:-len("_bang")] + "!"

    if p.startswith("is_") and p != "is_":
        p = p[len("is_"):] + "?"

    if "_" in p and p != "_":
        p = p.replace("_", "-")

    if (all([c.isalpha() and c.isupper() or c == '_' for c in p]) and
            any([c.isalpha() for c in p])):
        p = '*' + p.lower() + '*'

    return p
Ejemplo n.º 15
0
def unmangle(s):
    """Stringify the argument and try to convert it to a pretty unmangled
    form. This may not round-trip, because different Hy symbol names can
    mangle to the same Python identifier."""

    s = str_type(s)

    s2 = s.lstrip('_')
    leading_underscores = len(s) - len(s2)
    s = s2

    if s.startswith('hyx_'):
        s = re.sub(
            '{0}(U)?([_a-z0-9H]+?){0}'.format(mangle_delim),
            lambda mo: chr(int(mo.group(2), base=16))
            if mo.group(1) else unicodedata.lookup(
                mo.group(2).replace('_', ' ').replace('H', '-').upper()),
            s[len('hyx_'):])
    if s.startswith('is_'):
        s = s[len("is_"):] + "?"
    s = s.replace('_', '-')

    return '-' * leading_underscores + s
Ejemplo n.º 16
0
def mangle(s):
    """Stringify the argument and convert it to a valid Python identifier
    according to Hy's mangling rules."""
    def unicode_char_to_hex(uchr):
        # Covert a unicode char to hex string, without prefix
        if len(uchr) == 1 and ord(uchr) < 128:
            return format(ord(uchr), 'x')
        return (uchr.encode('unicode-escape').decode('utf-8')
            .lstrip('\\U').lstrip('\\u').lstrip('\\x').lstrip('0'))

    assert s

    s = str_type(s)
    s = s.replace("-", "_")
    s2 = s.lstrip('_')
    leading_underscores = '_' * (len(s) - len(s2))
    s = s2

    if s.endswith("?"):
        s = 'is_' + s[:-1]
    if not isidentifier(leading_underscores + s):
        # Replace illegal characters with their Unicode character
        # names, or hexadecimal if they don't have one.
        s = 'hyx_' + ''.join(
            c
               if c != mangle_delim and isidentifier('S' + c)
                 # We prepend the "S" because some characters aren't
                 # allowed at the start of an identifier.
               else '{0}{1}{0}'.format(mangle_delim,
                   unicodedata.name(c, '').lower().replace('-', 'H').replace(' ', '_')
                   or 'U{}'.format(unicode_char_to_hex(c)))
            for c in unicode_to_ucs4iter(s))

    s = leading_underscores + s
    assert isidentifier(s)
    return s
Ejemplo n.º 17
0
Archivo: parser.py Proyecto: tuturto/hy
def unmangle(s):
    """Stringify the argument and try to convert it to a pretty unmangled
    form. This may not round-trip, because different Hy symbol names can
    mangle to the same Python identifier."""

    s = str_type(s)

    s2 = s.lstrip('_')
    leading_underscores = len(s) - len(s2)
    s = s2

    if s.startswith('hyx_'):
        s = re.sub('{0}(U)?([_a-z0-9H]+?){0}'.format(mangle_delim),
            lambda mo:
               chr(int(mo.group(2), base=16))
               if mo.group(1)
               else unicodedata.lookup(
                   mo.group(2).replace('_', ' ').replace('H', '-').upper()),
            s[len('hyx_'):])
    if s.startswith('is_'):
        s = s[len("is_"):] + "?"
    s = s.replace('_', '-')

    return '-' * leading_underscores + s
Ejemplo n.º 18
0
def read_str(input):
    return read(StringIO(str_type(input)))
Ejemplo n.º 19
0
def test_replace_string_type():
    """Test replacing python string"""
    replaced = replace_hy_obj(str_type("foo"), HyString("bar"))
    assert replaced == HyString("foo")
Ejemplo n.º 20
0
def read_str(input):
    return read(StringIO(str_type(input)))
Ejemplo n.º 21
0
def test_replace_string_type():
    """Test replacing python string"""
    replaced = replace_hy_obj(str_type("foo"), HyString("bar"))
    assert replaced == HyString("foo")