Exemple #1
0
def block(lst, withResult, prepend=None):
    if len(lst) == 0:
        if withResult:
            return ast.Const(None)
        else:
            return ast.Pass()

    def stm(x):
        if hasResult(x):
            dis = ast.Discard(topy(x))
            dis.lineno = getmeta(x, 'lineno')
            return dis
        else:
            return topy(x)

    if withResult:
        stms = [stm(s) for s in lst[:-1]]
        last = lst[-1]
        lastpy = topy(last)

        if hasResult(last):
            # Insert a pass so pycodegen emits a SET_LINENO
            p = ast.Pass()
            p.lineno = getmeta(last, 'lineno')
        
            statements = stms + [p, lastpy]
        else:
            statements = stms + [lastpy, ast.Const(None)]
    else:
        statements = [stm(s) for s in lst]

    if prepend:
        return ast.Stmt(prepend + statements)
    else:
        return ast.Stmt(statements)
Exemple #2
0
 def bind(self, expr, name):
     """
     Generates code for binding a name to a value in the rule's locals dict.
     """
     return ast.Stmt([
              ast.Assign([ast.Subscript(ast.Name('__locals'),
                                        'OP_ASSIGN',
                                        [ast.Const(name)])],
                         expr),
              ast.Subscript(ast.Name('__locals'),
                            'OP_APPLY', [ast.Const(name)])])
Exemple #3
0
 def apply(self, ruleName, codeName='', *exprs):
     """
     Create a call to self.apply(ruleName, *args).
     """
     args = [self.compilePythonExpr(codeName, arg) for arg in exprs]
     if ruleName == "super":
         return ast.CallFunc(ast.Getattr(ast.Name("self"),
                                         "superApply"),
                             [ast.Const(codeName)] + args,
                             None, None)
     return ast.CallFunc(ast.Getattr(ast.Name("self"),
                                     "apply"),
                         [ast.Const(ruleName)] + args,
                     None, None)
Exemple #4
0
 def visitConst(self, node):
     if isinstance(node.value, str):
         try:  # If the string is ASCII, return a `str` object
             node.value.decode('ascii')
         except ValueError:  # Otherwise return a `unicode` object
             return ast.Const(node.value.decode('utf-8'))
     return node
Exemple #5
0
 def _return(self, val):
     if val is None:
         pyval = ast.Const(None)
     else:
         assertResult(val, "return")
         pyval = topy(val)
     return ast.Return(pyval)
Exemple #6
0
def compileDeflang(self, name, parentx, body):
    assert isinstance(name, Symbol)

    if parentx:
        assertResult(parentx, "derive language from")
        parent = topy(parentx)
    else:
        parent = logixglobal('langlang')

    funcname = "#lang:%s" % name

    body = len(body) > 0 and block(body, False).nodes or []

    funcbody = ast.Stmt(
        body
        + [ast.CallFunc(ast.Getattr(ast.Getattr(ast.Name(str(name)),
                                                '__impl__'),
                                    'addDeflangLocals'),
                        [ast.CallFunc(ast.Name('locals'), [])])])
    
    res = ast.Stmt([
        ast.Assign([compilePlace(Symbol(name))],
                   ast.CallFunc(logixglobal('defLanguage'),
                                [ast.Const(str(name)),
                                 parent,
                                 ast.CallFunc(GlobalName("globals"), [])])),
        astFunction(funcname, tuple(), tuple(), 0, None, funcbody),
        ast.CallFunc(ast.Name(funcname), []),
        ast.AssName(funcname, 'OP_DELETE')])
    
    lineno = getmeta(self, 'lineno')
    for n in res.nodes:
        n.lineno = lineno
    res.lineno = lineno
    return res
Exemple #7
0
 def visitAssert(self, node):
     end = Label()
     self.visit(node.test)
     self.emit('jumpif', end)
     self.visit(node.fail or ast.Const(None))
     self.emit('assertfail')
     self.emit(end)
Exemple #8
0
    def Symbol(symbol):
        if symbol == data.true:
            return ast.Const(True)
        
        elif symbol == data.false:
            return ast.Const(False)
        
        elif symbol == data.none:
            return ast.Const(None)

        elif symbol.namespace == "":
            return ast.Name(symbol.name)

        else:
            debug()
            raise CompileError, "can't compile symbol with namespace: %s" % symbol
Exemple #9
0
    def flist(obj):
        for x in obj: assertResult(x, 'use in flist')

        return ast.CallFunc(ast.Getattr(logixglobal('flist'), 'new'),
                            [ast.List(map(topy, obj.elems)),
                             ast.Dict([(ast.Const(n), topy(v))
                                       for n,v in obj.items()])])
Exemple #10
0
def compileGetOp(op):
    lang = op.__language__
    opmodname = op.__language__.__module__

    if opmodname == modulename:
        langexpr = GlobalName(lang.__impl__.name)
    else:
        langexpr = ast.Getattr(ast.Subscript(logixglobal('lmodules'),
                                             'OP_APPLY',
                                             [ast.Const(opmodname)]),
                               lang.__impl__.name)

    return ast.Subscript(
        ast.Getattr(ast.Getattr(langexpr, '__impl__'), 'operators'),
        'OP_APPLY',
        [ast.Const(op.__syntax__.token)])
Exemple #11
0
def compileGetops(doc):
    fromlang = doc[0]
    targetlang = doc.get("lang")
    ops = [op.strip() for op in doc[1:]]
    
    if targetlang is None:
        raise CompileError("No target language for getops"
                           "(getops in non-exec parse?)")

    assertResult(fromlang, "get operators from")

    lineno = getattr(doc, 'lineno', None)

    lastdot = targetlang.rfind('.')
    if lastdot == -1:
        def targetlangexpr():
            return GlobalName(targetlang)
    else:
        assert 0, ("PROBE: Why are we getting ops into an imported language?")
        langname = targetlang[lastdot+1:]
        langmod = targetlang[:lastdot]
        def targetlangexpr():
            return ast.Getattr(ast.Subscript(logixglobal('lmodules'),
                                             'OP_APPLY',
                                             [ast.Const(langmod)]),
                               langname)

    if len(ops) == 0:
        # get all operators
        res = ast.CallFunc(ast.Getattr(ast.Getattr(targetlangexpr(), '__impl__'),
                                       'addAllOperators'),
                           [topy(fromlang)])
        
    else:
        stmts = [ast.CallFunc(ast.Getattr(ast.Getattr(targetlangexpr(), '__impl__'),
                                          'addOp'),
                              [ast.CallFunc(ast.Getattr(ast.Getattr(topy(fromlang),
                                                                    "__impl__"),
                                                        "getOp"),
                                            [ast.Const(op), ast.Const(False)])])
                 for op in ops]

        for s in stmts: s.lineno = lineno
        res = ast.Stmt(stmts)

    res.lineno = lineno
    return res
Exemple #12
0
 def visitAugAssign(self, node):
     if isinstance(node.node, ast.Name) and (
             not self.locals or node.node.name not in flatten(self.locals)):
         name = node.node.name
         node.node = ast.Subscript(ast.Name('data'), 'OP_APPLY',
                                   [ast.Const(name)])
         node.expr = self.visit(node.expr)
         return ast.If(
             [(ast.Compare(ast.Const(name),
                           [('in', ast.Name('data'))]), ast.Stmt([node]))],
             ast.Stmt([
                 ast.Raise(
                     ast.CallFunc(ast.Name('UndefinedError'),
                                  [ast.Const(name)]), None, None)
             ]))
     else:
         return ASTTransformer.visitAugAssign(self, node)
Exemple #13
0
 def exactly(self, expr):
     """
     Create a call to self.exactly(expr).
     """
     return ast.CallFunc(ast.Getattr(ast.Name("self"),
                                     "exactly"),
                         [ast.Const(expr)],
                         None, None)
Exemple #14
0
 def visitName(self, node):
     # If the name refers to a local inside a lambda, list comprehension, or
     # generator expression, leave it alone
     if node.name not in flatten(self.locals):
         # Otherwise, translate the name ref into a context lookup
         func_args = [ast.Name('data'), ast.Const(node.name)]
         node = ast.CallFunc(ast.Name('_lookup_name'), func_args)
     return node
Exemple #15
0
 def visitPower(self, node, *args):
     walk(node.left, self)
     walk(node.right, self)
     cnode = ast.CallFunc(ast.Name('pow'), [node.left, node.right], None,
                          None)
     node.left = cnode
     # Little hack: instead of trying to turn node into a CallFunc, we just do pow(left, right)**1
     node.right = ast.Const(1)
Exemple #16
0
def block(lst, withResult, prepend=None):
    if len(lst) == 0:
        if withResult:
            return ast.Const(None)
        else:
            return ast.Pass()

    def stm(x):
        if hasResult(x):
            dis = ast.Discard(topy(x))
            dis.lineno = getattr(x, 'lineno', None)
            return dis
        else:
            return topy(x)

    if withResult:
        stms = [stm(s) for s in lst[:-1]]
        last = lst[-1]
        lastpy = topy(last)

        if hasResult(last):
            # Insert a pass so pycodegen emits a SET_LINENO
            p = ast.Pass()
            p.lineno = getattr(last, "lineno", None)
        
            statements = stms + [p, lastpy]
        else:
            statements = stms + [lastpy, ast.Const(None)]
    else:
        statements = [stm(s) for s in lst]

    # HACK: No lineno info was emitted for "del a[0]" statements
    # (insert a Pass to fix that)
    s2 = []
    for s in statements:
        if isinstance(s, ast.Subscript) and s.flags == "OP_DELETE" and hasattr(s, "lineno"):
            p = ast.Pass()
            p.lineno = s.lineno
            s2.append(p)
        s2.append(s)

    if prepend:
        return ast.Stmt(prepend + s2)
    else:
        return ast.Stmt(s2)
Exemple #17
0
 def sequence(self, exprs):
     """
     Creates a sequence of exprs, returning the value of the last one.
     """
     if len(exprs) > 0:
         stmtExprs = [ast.Discard(e) for e in exprs[:-1]] + [exprs[-1]]
         return ast.Stmt(stmtExprs)
     else:
         return ast.Const(None)
Exemple #18
0
 def atom_string(self, nodelist):
     k = ''
     for node in nodelist:
         k = k + eval(node[1])
     n = ast.Const(k)
     if self.__template_type and self.__template_type[-1] == "html":
         # change "foo" to _q_htmltext("foo")
         n = ast.CallFunc(ast.Name(MARKUP_MANGLED_CLASS), [n])
     return n
Exemple #19
0
def quote(obj, depth=1):
    assert depth > 0

    if isinstance(obj, rootops.quote):
        depth += 1

    elif isinstance(obj, rootops.escape):
        extra = obj.__operands__.get('extra', [])
        escapelevel = 1 + len(extra)
        if escapelevel > depth:
            raise CompileError("invalid quote escape")
        
        elif escapelevel == depth:
            if obj.__operands__.hasField('splice'):
                raise CompileError("Can't splice here")

            elif obj.__operands__.hasField("localmodule"):
                return topy(localModuleQuote())
            
            else:
                assertResult(obj[0], "insert into quote")
                return topy(obj[0])

    if isinstance(type(obj), OperatorType):
        # {{{ generate code to build the operator
        cls = obj.__class__
        if cls.__module__ == '%s.rootops' % logixModuleName:
            classx = ast.Getattr(logixglobal('rootops'), cls.__name__)
        else:
            optoken = obj.__class__.__syntax__.token
            classx = compileGetOp(obj)

        operands = macros.gensym("operands")
        return ast.Stmt([ast.Assign([compilePlace(operands)],
                                    quotedArgs(obj.__operands__, depth)),
                         ast.CallFunc(classx, [],
                                      ast.Getattr(topy(operands), "elems"),
                                      ast.Getattr(topy(operands), "fields"))])
        # }}}

    elif isinstance(obj, flist):
        # {{{ generate code to build the flist
        return quotedArgs(obj, depth)
        # }}}

    elif isinstance(obj, Symbol):
        # {{{ generate code to build the symbol
        return ast.CallFunc(logixglobal('Symbol'), [ast.Const(obj.asStr())])
        # }}}

    elif isinstance(obj, (tuple, list, dict)):
        # Q: Is this ok?
        assert 0, "didn't expect one of those to be quoted"

    else:
        return topy(obj)
Exemple #20
0
    def visitListCompFor(self, node):
        self.set_lineno(node)
        start = self.newBlock()
        anchor = self.newBlock()

        self.visit(node.list)
        self.visit(ast.Const(0))
        self.emit('SET_LINENO', node.lineno)
        self.nextBlock(start)
        self.emit('FOR_LOOP', anchor)
        self.visit(node.assign)
        return start, anchor
Exemple #21
0
def compileGetOp(symbol):
    lang = language.getLanguage(symbol.namespace)

    if lang is None:
        debug()
        raise CompileError, "not an operator symbol: %s" % symbol
        
    opmodname = lang.__module__

    if opmodname == modulename:
        langexpr = GlobalName(lang.__impl__.name)
    else:
        langexpr = ast.Getattr(ast.Subscript(logixglobal('lmodules'),
                                             'OP_APPLY',
                                             [ast.Const(opmodname)]),
                               lang.__impl__.name)

    return ast.Subscript(
        ast.Getattr(ast.Getattr(langexpr, '__impl__'), 'operators'),
        'OP_APPLY',
        [ast.Const(symbol.name)])
Exemple #22
0
 def _generate(node):
     if node.type == node.TERM:
         return ast.Compare(ast.Const(node.value),
                            [('in', ast.Name('text'))])
     elif node.type == node.AND:
         return ast.And([_generate(node.left), _generate(node.right)])
     elif node.type == node.OR:
         return ast.Or([_generate(node.left), _generate(node.right)])
     elif node.type == node.NOT:
         return ast.Not(_generate(node.left))
     elif node.type == node.ATTR:
         raise NotImplementedError
Exemple #23
0
    def function(self, name, expr):
        """
        Create a function of one argument with the given name returning the
        given expr.

        @param name: The function name.
        @param expr: The AST to insert into the function.
        """

        fexpr = ast.Stmt([ast.Assign([ast.AssName('__locals', 'OP_ASSIGN')],
                                     ast.Dict([(ast.Const('self'),
                                                ast.Name('self'))])),
                          ast.Assign([ast.Subscript(ast.Getattr(
                                                  ast.Name('self'), 'locals'),
                                                    'OP_ASSIGN',
                                                    [ast.Const(
                                                     name.split('_',1)[1])])],
                                     ast.Name('__locals')),
                          expr])
        f = ast.Lambda(['self'], [], 0, fexpr)
        f.filename = self.name
        return f
Exemple #24
0
    def compilePythonExpr(self, name, expr):
        """
        Compile an embedded Python expression.

        @param name: The current rule name.
        @param expr: The Python expression to compile.
        """
        c = python_compile(expr, "<grammar rule %s>" % (name,), "eval")
        return ast.Stmt([
                ast.CallFunc(ast.Name('eval'),
                             [ast.Const(c),
                              ast.Getattr(ast.Name("self"), "globals"),
                              ast.Name('__locals')])])
Exemple #25
0
    def _def(self, name, body, args=None):
        flags, argnames, defaults = funcArgs(args)

        if len(body) > 0:
            bod = block(body, True)
            stmts = bod.nodes
            if len(stmts) > 1 and isinstance(stmts[0], ast.Pass):
                first = 1
            else:
                first = 0
            stmt1 = stmts[first]
            if isinstance(stmt1, ast.Const) and isinstance(stmt1.value, str):
                doc = stmt1.value
                del stmts[:first+1]
                if len(stmts) == 0:
                    bod = ast.Const(None)
            else:
                doc = None
        else:
            bod = ast.Const(None)
            doc = None

        return astFunction(str(name), argnames, defaults, flags, doc, ast.Return(bod))
Exemple #26
0
def compileCodeObjects(filename, codeobjs):
    if len(codeobjs) == 0:
        stmts = []
    else:
        stmts = [ast.For(ast.AssName('[--codeobj--]', 'OP_ASSIGN'),
                         ast.Const(codeobjs),
                         ast.Stmt([ast.Exec(ast.Name('[--codeobj--]'),
                                            None, None)]),
                         None),
                 ast.AssName('[--codeobj--]', 'OP_DELETE')]

    module = ast.Module(None, ast.Stmt(stmts))
    compiler.misc.set_filename(filename, module)
    return pycodegen.ModuleCodeGenerator(module).getCode()
Exemple #27
0
    def _if(self, tests, else_=None):
        for test in tests:
                assertResult(test['test'], "use as if test")
                
        tests = [(el['test'], el['body']) for el in tests]

        pytests = []
        for t,b in tests:
            pyt = topy(t)
            pyt.lineno = getattr(t, 'lineno', None)
            pytests.append( (pyt, block(b, True)) )

        # HACK: For line numbers. Workaround for a test with no metadata
        # (e.g. just a symbol)
        # TODO: make this work for elifs (it doesn't)
        if pytests[0][0].lineno is None:
            pytests[0][0].lineno =  getattr(self, 'lineno', None)

        if else_: else_ = block(else_, True)

        return ast.If(pytests, else_ or ast.Const(None))
Exemple #28
0
    def visitFor(self, node):
	start = self.newBlock()
        anchor = self.newBlock()
	after = self.newBlock()
        self.loops.push(start)

        self.set_lineno(node)
	self.emit('SETUP_LOOP', after)
        self.visit(node.list)
        self.visit(ast.Const(0))
	self.nextBlock(start)
        self.set_lineno(node)
        self.emit('FOR_LOOP', anchor)
        self.visit(node.assign)
        self.visit(node.body)
        self.emit('JUMP_ABSOLUTE', start)
	self.nextBlock(anchor)
        self.emit('POP_BLOCK')
        if node.else_:
            self.visit(node.else_)
	self.loops.pop()
	self.nextBlock(after)
Exemple #29
0
def compileGetops(self, fromlang, *ops, **kw):
    targetlang = kw.get("lang")
    if targetlang is None:
        raise CompileError("No target language for getops"
                           "(getops in non-exec parse?)")

    assertResult(fromlang, "get operators from")

    lineno = getmeta(self, 'lineno')

    lastdot = targetlang.rfind('.')
    if lastdot == -1:
        targetlangexpr = GlobalName(targetlang)
    else:
        assert 0, ("PROBE: Why are we getting ops into an imported language?")
        langname = targetlang[lastdot+1:]
        langmod = targetlang[:lastdot]
        targetlangexpr = ast.Getattr(ast.Subscript(logixglobal('lmodules'),
                                                   'OP_APPLY',
                                                   [ast.Const(langmod)]),
                               langname)

    if len(ops) == 0:
        # get all operators
        res = ast.CallFunc(ast.Getattr(ast.Getattr(targetlangexpr, '__impl__'),
                                       'addAllOperators'),
                           [topy(fromlang)])
        
    else:
        stmts = [ast.CallFunc(ast.Getattr(ast.Getattr(targetlangexpr, '__impl__'),
                                          'addOp'),
                              [compileGetOp(op)])
                 for op in ops]

        for s in stmts: s.lineno = lineno
        res = ast.Stmt(stmts)

    res.lineno = lineno
    return res
Exemple #30
0
    def _if(self, test, body, elifs=None, _else=None):
        assertResult(test, "use as if test")

        if elifs:
            for el in elifs:
                assertResult(el['test'], "use as elif test")
            tests = [(test, body)] + [(el['test'], el['body']) for el in elifs]
        else:
            tests = [(test, body)]

        pytests = []
        for t,b in tests:
            pyt = topy(t)
            pyt.lineno = getmeta(t, 'lineno')
            pytests.append( (pyt, block(b, True)) )

        # HACK: For line numbers. Workaround for a test with no metadata
        # (e.g. just a symbol), but this doesn't work for elifs
        if pytests[0][0].lineno is None:
            pytests[0][0].lineno =  getmeta(self, 'lineno')

        if _else: _else = block(_else, True)

        return ast.If(pytests, _else or ast.Const(None))