我正在尝试编写一个程序,它将在Javascript和另一种语言(Elm)之间自动生成FFI文件。
我在想,是否有任何工具可以使用Javascript模块并列出所有可用的功能,可能带有参数数量?如果它只能做顶级函数,那没关系,我意识到这会因闭包和thunks等而变得复杂。
是否可以在Javascript中做一些类似内省的内容,或者我是否必须使用某种解析器/分析器?如果是这样,是否存在任何此类工具并且相当成熟/易于使用?
编辑:我意识到JavaScript是动态的。我的主要目标是为库和API生成FFI接口,所以那里的东西应该很容易静态推理,因为它们不会动态地改变。我没关系,如果它不完美,我正在寻找一种工具来减轻我对样板的写作,而不是保证防弹的东西。答案 0 :(得分:2)
对你来说很棘手的是,创建Javascript模块有许多不同的约定:将变量放在全局范围内,从文件返回表等等。模块创建也非常动态,所以它可能是更容易从Javascript内部做事。
假设您可以使用与模块对应的javascript对象,可以使用for in
循环进行检查:
var myModule = ...
for(var key in myModule){
if( Object.hasOwnProperty.call(myModule, key) ){
var func = myModule[key];
...
}
}
要检查对象属性是否为函数,可以使用typeof
运算符:
if(typeod func == "function")
并查看参数的数量,您可以检查函数的length属性:
func.length
请注意,如果函数是可变参数或以其他方式从arguments
数组获取参数,则参数的数量可能是错误的。但检查源文本的内容也会出错......
答案 1 :(得分:2)
可以在node.js中执行此操作。运行脚本时出于安全原因:
node script.js
无法查看nodejs提供的global
对象中的函数或变量,但在运行带node -e "some script"
的脚本时,可以访问global object
中的函数和变量。
所以我写了3个脚本。
<强> scriptThatNeedsToBeParsed.js:强>
function A(a,b,c){}
var abc;
function T(){}
<强> readFile.js:强>
我正在读取需要解析的文件,我定义了2个变量:
在文件内容之前START_FROM_THIS_OBJECT
,在文件内容之后END_TO_THIS_OBJECT
。所以稍后我会知道在哪里搜索函数和变量。
if(process.argv.length !=4 )
{
console.log("Usage %s <input-file> <interpret-file>",process.argv[0]);
process.exit(0);
}
var input_file = process.argv[2];
var interpret_file = process.argv[3];
var fs = require('fs');
var fileToParse = ";var START_FROM_THIS_OBJECT;";
fileToParse += fs.readFileSync(input_file, "utf8");
var interpretFile = fs.readFileSync(interpret_file, "utf8");
fileToParse += ";var END_TO_THIS_OBJECT;";
var script = fileToParse + interpretFile;
var child = require('child_process').execFile('node',
[
'-e', script,
], function(err, stdout, stderr) {
console.log(stdout);
});
<强> interpretFile.js:强> 我只是在上面定义的2个控制变量之间搜索函数和变量
var printObjects = false;
for(var item in global)
{
if(item == "END_TO_THIS_OBJECT")
{
printObjects = false;
}
if(printObjects)
{
if(typeof(global[item]) == "function")
{
console.log("Function :%s with nr args: %d",item,global[item].length);
}
else
{
console.log("Variable :%s with value: %d",item,global[item]);
}
}
if(item == "START_FROM_THIS_OBJECT")
{
printObjects = true;
}
}
来自nodejs的global
对象的最后一部分:console.log(global);
module:
{ id: '[eval]',
exports: {},
parent: undefined,
filename: 'E:\\LOCAL\\xampp\\htdocs\\nodejs\\[eval]',
loaded: false,
children: [],
paths:
[ 'E:\\LOCAL\\xampp\\htdocs\\nodejs\\node_modules',
'E:\\LOCAL\\xampp\\htdocs\\node_modules',
'E:\\LOCAL\\xampp\\node_modules',
'E:\\LOCAL\\node_modules',
'E:\\node_modules' ] },
__dirname: '.',
require:
{ [Function: require]
resolve: [Function],
main: undefined,
extensions: { '.js': [Function], '.json': [Function], '.node': [Function] },
registerExtension: [Function],
cache: {} },
START_FROM_THIS_OBJECT: undefined,<<<<<<<<<<<<<<
A: [Function: A],
abc: undefined,
T: [Function: T],
END_TO_THIS_OBJECT: undefined,<<<<<<<<<<<<<<<<
我用以下代码运行脚本:node readFile.js scriptThatNeedsToBeParsed.js interpretFile.js
这是输出:
功能:A与nr args:3
变量:abc with value:NaN
功能:T with nr args:0