feat: add support for let statements
This commit is contained in:
@@ -348,6 +348,48 @@ impl Sema {
|
||||
}
|
||||
}
|
||||
}
|
||||
StmtKind::Let {
|
||||
name,
|
||||
name_span,
|
||||
ty: type_annotation,
|
||||
initializer,
|
||||
} => {
|
||||
let explicit_ty = type_annotation.as_ref().map(|t| Ty::from(&t.kind));
|
||||
|
||||
let (inferred_ty, typed_initializer) = match initializer {
|
||||
Some(expr) => {
|
||||
let typed_expr = self.analyze_expr(expr);
|
||||
if let Some(ref ext_ty) = explicit_ty {
|
||||
if let Err(err) = self.unify(&typed_expr.ty, ext_ty) {
|
||||
self.errors.push(SemanticError::new(err, expr.span));
|
||||
}
|
||||
}
|
||||
(typed_expr.ty.clone(), Some(typed_expr))
|
||||
}
|
||||
None => {
|
||||
if let Some(ref ext_ty) = explicit_ty {
|
||||
(ext_ty.clone(), None)
|
||||
} else {
|
||||
self.errors
|
||||
.push(SemanticError::new("type annotation needed", *name_span));
|
||||
(self.new_var(), None)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let final_ty = explicit_ty.unwrap_or(inferred_ty);
|
||||
self.bind(name, final_ty.clone());
|
||||
|
||||
TypedStmt {
|
||||
kind: TypedStmtKind::Let {
|
||||
name: name.clone(),
|
||||
name_span: *name_span,
|
||||
ty: final_ty,
|
||||
initializer: typed_initializer,
|
||||
},
|
||||
span: stmt.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,6 +574,18 @@ impl Sema {
|
||||
TypedStmtKind::Return { value } => TypedStmtKind::Return {
|
||||
value: value.map(|e| self.apply_subst_expr(e)),
|
||||
},
|
||||
|
||||
TypedStmtKind::Let {
|
||||
name,
|
||||
name_span,
|
||||
ty,
|
||||
initializer,
|
||||
} => TypedStmtKind::Let {
|
||||
name,
|
||||
name_span,
|
||||
ty: self.apply_subst(&ty),
|
||||
initializer: initializer.map(|e| self.apply_subst_expr(e)),
|
||||
},
|
||||
};
|
||||
|
||||
TypedStmt { kind, span }
|
||||
@@ -797,4 +851,16 @@ mod test {
|
||||
let src = "fn test() { if 12 {} }";
|
||||
assert!(analyze(src).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valid_let() {
|
||||
let src = "fn test() { let a = 5; let b: i32 = a; }";
|
||||
assert!(analyze(src).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn let_missing_type() {
|
||||
let src = "fn test() { let a; }";
|
||||
assert!(analyze(src).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user