in lib/semantic.js [2380:2462]
visitInstanceCall(ast, env) {
assert.equal(ast.left.type, 'instance_call');
const type = this.getVariableType(ast.left.id, env);
let moduleName = type.name;
if(isBasicType(type.type)) {
moduleName = this.getBuiltinModule(type.type);
ast.builtinModule = moduleName;
ast.left.id.moduleType = {
type: 'basic',
name: type.type,
};
} else if(type.type === 'basic' && isBasicType(type.name)) {
moduleName = this.getBuiltinModule(type.name);
ast.builtinModule = moduleName;
ast.left.id.moduleType = {
type: 'basic',
name: type.name,
};
} else if(type.type === 'model') {
moduleName = '$ModelInstance';
ast.builtinModule = moduleName;
ast.left.id.moduleType = {
type: 'model',
name: type.name,
};
} else if(builtin.has(moduleName)) {
ast.builtinModule = moduleName;
ast.left.id.moduleType = {
type: 'builtin_module',
name: moduleName,
};
} else if (ast.left.id.tag === Tag.ID) {
moduleName = type.name;
ast.left.id.moduleType = {
type: 'module',
name: moduleName
};
}
const checker = this.getChecker(moduleName);
const method = ast.left.propertyPath[0];
const name = method.lexeme;
const def = checker.getInstanceMethod(name, moduleName);
if (!def) {
this.error(`the instance function/api "${name}" is undefined in ${moduleName}`, method);
}
const { method: definedApi, module: moduleNameOfDef } = def;
const actual = [];
for (let i = 0; i < ast.args.length; i++) {
const arg = ast.args[i];
this.visitExpr(arg, env);
const type = this.getExprType(arg, env);
actual.push(type);
}
const expected = this.getParameterTypes(definedApi, moduleNameOfDef);
if (!eql(expected, actual)) {
this.error(`the parameter` +
` types are mismatched. expected ` +
`${moduleName}.${name}(${expected.map((item) => display(item)).join(', ')}), but ` +
`${moduleName}.${name}(${actual.map((item) => display(item)).join(', ')})`, method);
}
for (let i = 0; i < ast.args.length; i++) {
const arg = ast.args[i];
arg.needCast = isNeedToMap(expected[i], arg.inferred);
arg.expectedType = expected[i];
}
if(this.checkMagicType(definedApi.returnType)) {
const magicType = this.getInstanceType(ast.left.id, env);
ast.inferred = this.getMagicType(definedApi.returnType, magicType);
} else {
ast.inferred = this.getType(definedApi.returnType, moduleName);
}
ast.isAsync = definedApi.isAsync;
ast.isStatic = definedApi.isStatic;
ast.hasThrow = definedApi.isAsync || definedApi.hasThrow;
}