示例#1
0
    def compile(self, source_obj, tc, cont):
        """
        Compile a supported source object into an expression.

        pair, symbol, keyword, and the pythonic constant types are
        valid source obj types.
        """

        self.require_active()

        tc = self.tco_enabled and tc

        if is_pair(source_obj):
            dispatch = self.compile_pair
        elif is_symbol(source_obj) or is_lazygensym(source_obj):
            dispatch = self.compile_symbol
        elif is_keyword(source_obj):
            dispatch = self.compile_keyword
        elif isinstance(source_obj, CONST_TYPES):
            dispatch = self.compile_constant
        else:
            msg = "Unsupported source object %r" % source_obj
            raise CompilerException(msg)

        try:
            return dispatch(source_obj, tc, cont or self._compile_cont)
        except (CompilerException, SibilantSyntaxError):
            # these two should be propogated unchanged
            raise
        except Exception as ex:
            raise UncaughtCompilerException(ex, source_obj)
示例#2
0
    def find_compiled(self, namesym: Symbol, env=None):
        """
        Search for and return a Compiled instance within the activated
        environment for this compiler. Returns None if nothing was
        found.
        """

        env = self.env if env is None else env

        # self.require_active()

        if is_lazygensym(namesym):
            # I might make this work some day, with macrolet, but for
            # now ... no.
            return None

        for tmp_env in reversed(self.env_tmp_compiled):
            if namesym in tmp_env:
                return tmp_env[namesym]
        else:
            return env_find_compiled(env, namesym)
示例#3
0
    def find_compiled(self, namesym: Symbol, env=None):
        """
        Search for and return a Compiled instance within the activated
        environment for this compiler. Returns None if nothing was
        found.
        """

        env = self.env if env is None else env

        # self.require_active()

        if is_lazygensym(namesym):
            # I might make this work some day, with macrolet, but for
            # now ... no.
            return None

        for tmp_env in reversed(self.env_tmp_compiled):
            if namesym in tmp_env:
                return tmp_env[namesym]
        else:
            return env_find_compiled(env, namesym)
示例#4
0
    def compile_symbol(self, sym: Symbol, tc, cont):
        """
        Compile a symbol expression. This can result in a constant for
        certain specialty Python values (None, True, False, and ...)

        Dotted symbols will be compiled into attr calls. Non-dotted
        symbols will be compiled into variable references.

        If a symbol correlates to an Alias in the module namespace,
        then that alias will be expanded and compilation will continue
        from the expanded form.
        """

        comp = self.find_compiled(sym)
        if comp and is_alias(comp):
            return tcf(comp.compile, self, sym, tc, cont)

        elif sym is _symbol_None:
            return tcf(self.compile_constant, None, tc, cont)

        elif sym is _symbol_True:
            return tcf(self.compile_constant, True, tc, cont)

        elif sym is _symbol_False:
            return tcf(self.compile_constant, False, tc, cont)

        elif sym is _symbol_ellipsis:
            return tcf(self.compile_constant, ..., tc, cont)

        elif is_lazygensym(sym):
            return tcf(cont, self.pseudop_get_var(sym), tc)

        else:
            ex = sym.rsplit(".", 1)
            if len(ex) == 1:
                return tcf(cont, self.pseudop_get_var(sym), None)
            else:
                source = cons(_symbol_attr, *ex, nil)
                return tcf(self.compile, source, tc, cont)
示例#5
0
    def compile_symbol(self, sym: Symbol, tc, cont):
        """
        Compile a symbol expression. This can result in a constant for
        certain specialty Python values (None, True, False, and ...)

        Dotted symbols will be compiled into attr calls. Non-dotted
        symbols will be compiled into variable references.

        If a symbol correlates to an Alias in the module namespace,
        then that alias will be expanded and compilation will continue
        from the expanded form.
        """

        comp = self.find_compiled(sym)
        if comp and is_alias(comp):
            return tcf(comp.compile, self, sym, tc, cont)

        elif sym is _symbol_None:
            return tcf(self.compile_constant, None, tc, cont)

        elif sym is _symbol_True:
            return tcf(self.compile_constant, True, tc, cont)

        elif sym is _symbol_False:
            return tcf(self.compile_constant, False, tc, cont)

        elif sym is _symbol_ellipsis:
            return tcf(self.compile_constant, ..., tc, cont)

        elif is_lazygensym(sym):
            return tcf(cont, self.pseudop_get_var(sym), tc)

        else:
            ex = sym.rsplit(".", 1)
            if len(ex) == 1:
                return tcf(cont, self.pseudop_get_var(sym), None)
            else:
                source = cons(_symbol_attr, *ex, nil)
                return tcf(self.compile, source, tc, cont)
示例#6
0
    def compile_pair(self, source_obj: pair, tc, cont):
        """
        Compile a pair expression. This will become either a literal nil,
        a macro expansion, a special invocation, or a runtime function
        application.
        """

        if is_nil(source_obj):
            return tcf(self.compile_nil, source_obj, tc, cont)

        if not is_proper(source_obj):
            # print("** WUT", self, source_obj, tc, cont)
            msg = "cannot evaluate improper lists as expressions"
            raise self.error(msg, source_obj)

        self.pseudop_position_of(source_obj)

        head, tail = source_obj

        if is_symbol(head) or is_lazygensym(head):
            comp = self.find_compiled(head)
            if comp:
                # the head of the pair is a symbolic reference which
                # resolved to a compile-time object. Invoke that.
                return tcf(comp.compile, self, source_obj, tc, cont)

            else:
                return tcf(self.compile_apply, source_obj, tc, cont)

        elif is_pair(head):
            return tcf(self.compile_apply, source_obj, tc, cont)

        else:
            # TODO: should this be a compile-time error? If we have
            # something that isn't a symbolic reference or isn't a
            # pair, then WTF else would it be? Let's just let it break
            # at runtime, for now.
            return tcf(self.compile_apply, source_obj, tc, cont)
示例#7
0
    def compile_pair(self, source_obj: pair, tc, cont):
        """
        Compile a pair expression. This will become either a literal nil,
        a macro expansion, a special invocation, or a runtime function
        application.
        """

        if is_nil(source_obj):
            return tcf(self.compile_nil, source_obj, tc, cont)

        if not is_proper(source_obj):
            # print("** WUT", self, source_obj, tc, cont)
            msg = "cannot evaluate improper lists as expressions"
            raise self.error(msg, source_obj)

        self.pseudop_position_of(source_obj)

        head, tail = source_obj

        if is_symbol(head) or is_lazygensym(head):
            comp = self.find_compiled(head)
            if comp:
                # the head of the pair is a symbolic reference which
                # resolved to a compile-time object. Invoke that.
                return tcf(comp.compile, self, source_obj, tc, cont)

            else:
                return tcf(self.compile_apply, source_obj, tc, cont)

        elif is_pair(head):
            return tcf(self.compile_apply, source_obj, tc, cont)

        else:
            # TODO: should this be a compile-time error? If we have
            # something that isn't a symbolic reference or isn't a
            # pair, then WTF else would it be? Let's just let it break
            # at runtime, for now.
            return tcf(self.compile_apply, source_obj, tc, cont)
示例#8
0
    def compile(self, source_obj, tc, cont):
        """
        Compile a supported source object into an expression.

        pair, symbol, keyword, and the pythonic constant types are
        valid source obj types.
        """

        tc = self.tco_enabled and tc

        if is_pair(source_obj):
            dispatch = self.compile_pair
        elif is_symbol(source_obj) or is_lazygensym(source_obj):
            dispatch = self.compile_symbol
        elif is_keyword(source_obj):
            dispatch = self.compile_keyword
        elif isinstance(source_obj, CONST_TYPES):
            dispatch = self.compile_constant
        else:
            msg = "Unsupported source object %r" % source_obj
            raise self.error(msg, source_obj)

        return tcf(dispatch, source_obj, tc, cont or self._compile_cont)
示例#9
0
def gather_formals(args, declared_at=None, filename=None):
    """
    parses formals pair args into five values:
    (positional, keywords, defaults, stararg, starstararg)

    - positional is a list of symbols defining positional arguments

    - defaults is a list of keywords and expr pairs defining keyword
      arguments and their default value expression

    - kwonly is a list of keywords and expr pairs which are
      keyword-only arguments and theid default value expression

    - stararg is a symbol for variadic positional arguments

    - starstararg is a symbol for variadic keyword arguments
    """

    undefined = object()

    err = partial(SibilantSyntaxError, location=declared_at, filename=filename)

    if is_symbol(args):
        return ((), (), (), args, None)

    elif isinstance(args, (list, tuple)):
        improper = False
        args = cons(*args, nil)

    elif is_proper(args):
        improper = False

    elif is_pair(args):
        improper = True

    else:
        raise err("formals must be symbol or pair, not %r" % args)

    positional = []

    iargs = iter(args.unpack())
    for arg in iargs:
        if is_keyword(arg):
            if improper:
                raise err("cannot mix improper formal with keywords")
            else:
                break
        elif is_symbol(arg) or is_lazygensym(arg):
            positional.append(arg)
        else:
            raise err("positional formals must be symbols, not %r" % arg)
    else:
        # handled all of args, done deal.
        if improper:
            return (positional[:-1], (), (), positional[-1], None)
        else:
            return (positional, (), (), None, None)

    defaults = []
    kwonly = []

    while arg not in (_keyword_star, _keyword_starstar):
        value = next(iargs, undefined)
        if value is undefined:
            raise err("missing value for keyword formal %s" % args)
        else:
            defaults.append((arg, value))

        arg = next(iargs, undefined)

        if arg is undefined:
            break
        elif is_keyword(arg):
            continue
        else:
            raise err("keyword formals must be alternating keywords and"
                      " values, not %r" % arg)

    star = None
    starstar = None

    if arg is undefined:
        return (positional, defaults, kwonly, None, None)

    if arg is _keyword_star:
        star = next(iargs, undefined)
        if star is undefined:
            raise err("* keyword requires symbol binding")
        elif star is nil:
            # nil means an ignored star arg, this is allowed.
            pass
        elif not (is_symbol(star) or is_lazygensym(star)):
            raise err("* keyword requires symbol binding, not %r" % star)
        arg = next(iargs, undefined)

    if arg is undefined:
        return (positional, defaults, kwonly, star, starstar)

    # while is_symbol(arg):
    #     kwonly.append(arg)
    #     arg = next(iargs, undefined)
    #
    # if arg is undefined:
    #     return (positional, defaults, kwonly, star, starstar)

    if not is_keyword(arg):
        raise err("expected keyword in formals, got %r" % arg)

    # keyword formals after *: are considered keyword-only
    while arg not in (_keyword_star, _keyword_starstar):
        value = next(iargs, undefined)
        if value is undefined:
            raise err("missing value for keyword-only formal %s" % arg)
        else:
            kwonly.append((arg, value))

        arg = next(iargs, undefined)
        if arg is undefined:
            break
        elif is_keyword(arg):
            continue
        else:
            raise err("keyword-only formals must be alternating keywords"
                      " and values, not %r" % arg)

    if arg is _keyword_starstar:
        starstar = next(iargs, undefined)
        if starstar is undefined:
            raise err("** keyword requires symbol binding")
        elif not (is_symbol(starstar) or is_lazygensym(starstar)):
            raise err("** keyword requires symbol binding, not %r" % star)
        arg = next(iargs, undefined)

    if arg is not undefined:
        raise err("leftover formals %r" % arg)

    return (positional, defaults, kwonly, star, starstar)
示例#10
0
def gather_parameters(args, declared_at=None, filename=None):
    """
    parses parameter args into five values:
    (positional, keywords, values, stararg, starstararg)

    - positional is a list of expressions for positional arguments
    - keywords is a list of keywords defining keyword arguments
    - values is a list of expressions defining values for keywords
    - stararg is a symbol for variadic positional expression
    - starstararg is a symbol for variadic keyword expression
    """

    undefined = object()

    def err(msg):
        return SibilantSyntaxError(msg,
                                   location=declared_at,
                                   filename=filename)

    if is_symbol(args) or is_lazygensym(args):
        return ((), (), (), args, None)

    elif isinstance(args, (list, tuple)):
        improper = False
        args = cons(*args, nil) if args else nil

    elif is_proper(args):
        improper = False

    elif is_pair(args):
        improper = True

    else:
        raise err("parameters must be symbol or pair, not %r" % args)

    positional = []

    iargs = iter(args.unpack())
    for arg in iargs:
        if is_keyword(arg):
            break
        else:
            positional.append(arg)
    else:
        # handled all of args, done deal.
        if improper:
            return (positional[:-1], (), (), positional[-1], None)
        else:
            return (positional, (), (), None, None)

    keywords = []
    defaults = []

    while arg not in (_keyword_star, _keyword_starstar):
        keywords.append(arg)

        value = next(iargs, undefined)
        if value is undefined:
            raise err("missing value for keyword parameter %s" % arg)
        else:
            defaults.append(value)

        arg = next(iargs, undefined)
        if arg is undefined:
            break
        elif is_keyword(arg):
            continue
        else:
            raise err("keyword parameters must be alternating keywords and"
                      " values, not %r" % arg)

    star = None
    starstar = None

    if arg is undefined:
        return (positional, keywords, defaults, None, None)

    if arg is _keyword_star:
        star = next(iargs, undefined)
        if star is undefined:
            raise err("* keyword parameter needs value")
        arg = next(iargs, undefined)

    if arg is _keyword_starstar:
        starstar = next(iargs, undefined)
        if starstar is undefined:
            raise err("** keyword parameter needs value")
        arg = next(iargs, undefined)

    if arg is not undefined:
        raise err("leftover parameters %r" % arg)

    return (positional, keywords, defaults, star, starstar)
示例#11
0
def gather_formals(args, declared_at=None, filename=None):
    """
    parses formals pair args into five values:
    (positional, keywords, defaults, stararg, starstararg)

    - positional is a list of symbols defining positional arguments

    - defaults is a list of keywords and expr pairs defining keyword
      arguments and their default value expression

    - kwonly is a list of keywords and expr pairs which are
      keyword-only arguments and theid default value expression

    - stararg is a symbol for variadic positional arguments

    - starstararg is a symbol for variadic keyword arguments
    """

    undefined = object()

    err = partial(SibilantSyntaxError,
                  location=declared_at,
                  filename=filename)

    if is_symbol(args):
        return ((), (), (), args, None)

    elif isinstance(args, (list, tuple)):
        improper = False
        args = cons(*args, nil)

    elif is_proper(args):
        improper = False

    elif is_pair(args):
        improper = True

    else:
        raise err("formals must be symbol or pair, not %r" % args)

    positional = []

    iargs = iter(args.unpack())
    for arg in iargs:
        if is_keyword(arg):
            if improper:
                raise err("cannot mix improper formal with keywords")
            else:
                break
        elif is_symbol(arg) or is_lazygensym(arg):
            positional.append(arg)
        else:
            raise err("positional formals must be symbols, nor %r" % arg)
    else:
        # handled all of args, done deal.
        if improper:
            return (positional[:-1], (), (), positional[-1], None)
        else:
            return (positional, (), (), None, None)

    defaults = []
    kwonly = []

    while arg not in (_keyword_star, _keyword_starstar):
        value = next(iargs, undefined)
        if value is undefined:
            raise err("missing value for keyword formal %s" % args)
        else:
            defaults.append((arg, value))

        arg = next(iargs, undefined)

        if arg is undefined:
            break
        elif is_keyword(arg):
            continue
        else:
            raise err("keyword formals must be alternating keywords and"
                      " values, not %r" % arg)

    star = None
    starstar = None

    if arg is undefined:
        return (positional, defaults, kwonly, None, None)

    if arg is _keyword_star:
        star = next(iargs, undefined)
        if star is undefined:
            raise err("* keyword requires symbol binding")
        elif star is nil:
            # nil means an ignored star arg, this is allowed.
            pass
        elif not (is_symbol(star) or is_lazygensym(star)):
            raise err("* keyword requires symbol binding, not %r" % star)
        arg = next(iargs, undefined)

    if arg is undefined:
        return (positional, defaults, kwonly, star, starstar)

    # while is_symbol(arg):
    #     kwonly.append(arg)
    #     arg = next(iargs, undefined)
    #
    # if arg is undefined:
    #     return (positional, defaults, kwonly, star, starstar)

    if not is_keyword(arg):
        raise err("expected keyword in formals, got %r" % arg)

    # keyword formals after *: are considered keyword-only
    while arg not in (_keyword_star, _keyword_starstar):
        value = next(iargs, undefined)
        if value is undefined:
            raise err("missing value for keyword-only formal %s" % arg)
        else:
            kwonly.append((arg, value))

        arg = next(iargs, undefined)
        if arg is undefined:
            break
        elif is_keyword(arg):
            continue
        else:
            raise err("keyword-only formals must be alternating keywords"
                      " and values, not %r" % arg)

    if arg is _keyword_starstar:
        starstar = next(iargs, undefined)
        if starstar is undefined:
            raise err("** keyword requires symbol binding")
        elif not (is_symbol(starstar) or is_lazygensym(starstar)):
            raise err("** keyword requires symbol binding, not %r" % star)
        arg = next(iargs, undefined)

    if arg is not undefined:
        raise err("leftover formals %r" % arg)

    return (positional, defaults, kwonly, star, starstar)
示例#12
0
def gather_parameters(args, declared_at=None, filename=None):
    """
    parses parameter args into five values:
    (positional, keywords, values, stararg, starstararg)

    - positional is a list of expressions for positional arguments
    - keywords is a list of keywords defining keyword arguments
    - values is a list of expressions defining values for keywords
    - stararg is a symbol for variadic positional expression
    - starstararg is a symbol for variadic keyword expression
    """

    undefined = object()

    def err(msg):
        return SibilantSyntaxError(msg, location=declared_at,
                                   filename=filename)

    if is_symbol(args) or is_lazygensym(args):
        return ((), (), (), args, None)

    elif isinstance(args, (list, tuple)):
        improper = False
        args = cons(*args, nil) if args else nil

    elif is_proper(args):
        improper = False

    elif is_pair(args):
        improper = True

    else:
        raise err("parameters must be symbol or pair, not %r" % args)

    positional = []

    iargs = iter(args.unpack())
    for arg in iargs:
        if is_keyword(arg):
            break
        else:
            positional.append(arg)
    else:
        # handled all of args, done deal.
        if improper:
            return (positional[:-1], (), (), positional[-1], None)
        else:
            return (positional, (), (), None, None)

    keywords = []
    defaults = []

    while arg not in (_keyword_star, _keyword_starstar):
        keywords.append(arg)

        value = next(iargs, undefined)
        if value is undefined:
            raise err("missing value for keyword parameter %s" % arg)
        else:
            defaults.append(value)

        arg = next(iargs, undefined)
        if arg is undefined:
            break
        elif is_keyword(arg):
            continue
        else:
            raise err("keyword parameters must be alternating keywords and"
                      " values, not %r" % arg)

    star = None
    starstar = None

    if arg is undefined:
        return (positional, keywords, defaults, None, None)

    if arg is _keyword_star:
        star = next(iargs, undefined)
        if star is undefined:
            raise err("* keyword parameter needs value")
        arg = next(iargs, undefined)

    if arg is _keyword_starstar:
        starstar = next(iargs, undefined)
        if starstar is undefined:
            raise err("** keyword parameter needs value")
        arg = next(iargs, undefined)

    if arg is not undefined:
        raise err("leftover parameters %r" % arg)

    return (positional, keywords, defaults, star, starstar)