visitStaticCall()

in lib/semantic.js [1590:1634]


  visitStaticCall(ast, env) {
    assert.equal(ast.left.type, 'static_call');
    const moduleId = ast.left.id;
    const moduleName = moduleId.lexeme;
    const checker = this.dependencies.get(moduleName) || builtin.get(moduleName);
    const method = ast.left.propertyPath[0];
    const methodName = method.lexeme;

    const def = checker.methods.get(methodName);
    if (!def) {
      this.error(`the static function "${methodName}" is undefined in ${moduleName}`, method);
    }

    if (!def.isStatic) {
      this.error(`the "${methodName}" is not static function`, method);
    }

    const expected = this.getParameterTypes(def, moduleName);

    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);
    }

    if (!eql(expected, actual)) {
      this.error(`the parameter` +
        ` types are mismatched. expected ` +
        `${moduleName}.${methodName}(${expected.map((item) => display(item)).join(', ')}), but ` +
        `${moduleName}.${methodName}(${actual.map((item) => display(item)).join(', ')})`, method);
    }

    for (let i = 0; i < ast.args.length; i++) {
      const arg = ast.args[i];
      arg.expectedType = expected[i];
      arg.needCast = isNeedToMap(expected[i], arg.inferred);
    }

    ast.isAsync = def.isAsync;
    ast.isStatic = def.isStatic;
    ast.hasThrow = def.isAsync || def.hasThrow;
    ast.inferred = this.getType(def.returnType, moduleName);
  }