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