visitDeclare()

in lib/semantic.js [3196:3224]


  visitDeclare(ast, env) {
    const id = ast.id.lexeme;
    // 当前作用域是否定义过
    if (env.local.has(id)) {
      this.error(`the id "${id}" was defined`, ast.id);
    }
    this.visitExpr(ast.expr, env);

    const type = this.getExprType(ast.expr, env);
    let expected;

    if (type.type === 'basic' && type.name === 'null') {
      if (!ast.expectedType) {
        this.error(`must declare type when value is null`, ast.id);
      }
      expected = this.getType(ast.expectedType);
    } else {
      if (ast.expectedType) {
        expected = this.getType(ast.expectedType);
        if (!isAssignable(expected, type, ast.expr)) {
          this.error(`declared variable with mismatched type, ` +
            `expected: ${display(expected)}, actual: ${display(type)}`, ast.id);
        }
      }
    }

    env.local.set(id, expected || type); 
    ast.expr.inferred = expected || type;
  }