我正在开发一个新的Python到JavaScript compiler,它为包含编译器指令的__pragma__语句生成特殊代码。为了能够做到这一点,我必须使用包含本地函数的上下文来评估Ast的一部分。
我的代码是:
eval (compile (ast.Expression (arg), '<string>', 'eval'), globals (), locals ())
其中arg是一个表达式节点,用于调用本地函数“include”。如果我检查locals(),'include'确实存在。但'eval'抱怨道:
name 'include' is not defined.
我看了一个在Eli Bendersky's website提供的例子。他做了同样的事情,只是没有提供当地背景。谁知道我做错了什么?
[编辑]
现在一切都很完美(感谢Martijn!)。我也忘记了需要引用字典的字面键。这些天给很多JS编程......
def emitKwargDict ():
self.emit ('__kwargdict__ (')
hasSeparateKeyArgs = False
hasKwargs = False
for keyword in node.keywords:
if keyword.arg:
hasSeparateKeyArgs = True
else:
hasKwargs = True
break # **kwargs is always the last arg
if hasSeparateKeyArgs:
if hasKwargs:
self.emit ('__merge__ (')
self.emit ('{{') # Allways if hasSeparateKeyArgs
for keywordIndex, keyword in enumerate (node.keywords):
if keyword.arg:
self.emitComma (keywordIndex)
self.emit ('{}: ', keyword.arg)
self.visit (keyword.value)
else:
# It's the **kwargs arg, so the last arg
# In JavaScript this must be an expression denoting an Object (sometimes specialized as kwargdict)
# The keyword args in there have to be added to the __kwargdict__ as well
if hasSeparateKeyArgs:
self.emit ('}}, ')
self.visit (keyword.value)
if hasSeparateKeyArgs:
if hasKwargs:
self.emit (')') # Terminate merge
else:
self.emit ('}}') # Only if not terminated already because hasKwargs
self.emit (')')
def include (fileName):
searchedIncludePaths = []
for searchDir in self.module.program.moduleSearchDirs:
filePath = '{}/{}'.format (searchDir, fileName)
if os.path.isfile (filePath):
return open (filePath) .read ()
else:
searchedIncludePaths.append (filePath)
else:
raise utils.Error (
moduleName = self.module.metadata.name,
lineNr = self.lineNr,
message = '\n\tAttempt to include file: {}\n\tCan\'t find any of:\n\t\t{}\n'.format (
node.args [0], '\n\t\t'. join (searchedIncludePaths)
)
)
if type (node.func) == ast.Name:
if node.func.id == 'property':
self.emit ('{0}.call ({1}, {1}.{2}'.format (node.func.id, self.getscope (ast.ClassDef) .name, node.args [0].id))
if len (node.args) > 1:
self.emit (', {}.{}'.format (self.getscope (ast.ClassDef) .name, node.args [1].id))
self.emit (')')
return
elif node.func.id == '__pragma__':
if node.args [0] .s == 'kwargs': # Start emitting kwargs code for FunctionDef's
self.allowKeywordArgs = True
elif node.args [0] .s == 'nokwargs': # Stop emitting kwargs code for FunctionDef's
self.allowKeywordArgs = False
elif node.args [0] .s == 'js': # Include JavaScript code literally in the output
self.emit ('\n{}\n', node.args [1] .s.format (* [
eval (
compile (
ast.Expression (arg),
'<string>',
'eval'
),
{},
{'include': include}
)
for arg in node.args [2:]
]))
elif node.args [0] .s == 'alias':
self.aliases [args [1]] = args [2]
return
elif node.func.id == '__new__':
self.emit ('new ')
self.visit (node.args [0])
return
self.visit (node.func)
for index, expr in enumerate (node.args):
if type (expr) == ast.Starred:
self.emit ('.apply (null, ') # Note that in generated a.b.f (), a.b.f is a bound function already
for index, expr in enumerate (node.args):
if index:
self.emit ('.concat (')
if type (expr) == ast.Starred:
self.visit (expr)
else:
self.emit ('[')
self.visit (expr)
self.emit (']')
if index:
self.emit (')')
if node.keywords:
self.emit ('.concat ([') # At least *args was present before this point
emitKwargDict ()
self.emit ('])')
self.emit (')')
break;
else:
self.emit (' (')
for index, expr in enumerate (node.args):
self.emitComma (index)
self.visit (expr)
if node.keywords:
self.emitComma (len (node.args))
emitKwargDict ()
self.emit (')')
答案 0 :(得分:1)
您有一个NameError
例外,表示该名称被查找为全局,而非本地名称。将名称放在globals
字典中。