feat: add expression statements and assign expressions
This commit is contained in:
@@ -390,6 +390,14 @@ impl Sema {
|
||||
span: stmt.span,
|
||||
}
|
||||
}
|
||||
StmtKind::Expression { expr } => {
|
||||
let typed_expr = self.analyze_expr(expr);
|
||||
|
||||
TypedStmt {
|
||||
kind: TypedStmtKind::Expression { expr: typed_expr },
|
||||
span: stmt.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,6 +526,31 @@ impl Sema {
|
||||
span: expr.span,
|
||||
}
|
||||
}
|
||||
ExprKind::Assign { lval, rval } => {
|
||||
let typed_rval = self.analyze_expr(rval);
|
||||
let typed_lval = self.analyze_expr(lval);
|
||||
|
||||
match &typed_lval.kind {
|
||||
TypedExprKind::Identifier { .. } => {}
|
||||
_ => self.errors.push(SemanticError::new(
|
||||
"invalid left-hand side of assignment",
|
||||
lval.span,
|
||||
)),
|
||||
}
|
||||
|
||||
if let Err(e) = self.unify(&typed_lval.ty, &typed_rval.ty) {
|
||||
self.errors.push(SemanticError::new(e, expr.span));
|
||||
}
|
||||
|
||||
TypedExpr {
|
||||
ty: typed_rval.ty.clone(),
|
||||
kind: TypedExprKind::Assign {
|
||||
lval: Box::new(typed_lval),
|
||||
rval: Box::new(typed_rval),
|
||||
},
|
||||
span: expr.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -586,6 +619,9 @@ impl Sema {
|
||||
ty: self.apply_subst(&ty),
|
||||
initializer: initializer.map(|e| self.apply_subst_expr(e)),
|
||||
},
|
||||
TypedStmtKind::Expression { expr } => TypedStmtKind::Expression {
|
||||
expr: self.apply_subst_expr(expr),
|
||||
},
|
||||
};
|
||||
|
||||
TypedStmt { kind, span }
|
||||
@@ -610,6 +646,10 @@ impl Sema {
|
||||
lhs: Box::new(self.apply_subst_expr(*lhs)),
|
||||
rhs: Box::new(self.apply_subst_expr(*rhs)),
|
||||
},
|
||||
TypedExprKind::Assign { lval, rval } => TypedExprKind::Assign {
|
||||
lval: Box::new(self.apply_subst_expr(*lval)),
|
||||
rval: Box::new(self.apply_subst_expr(*rval)),
|
||||
},
|
||||
};
|
||||
|
||||
TypedExpr { kind, ty, span }
|
||||
@@ -863,4 +903,34 @@ mod test {
|
||||
let src = "fn test() { let a; }";
|
||||
assert!(analyze(src).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valid_expression_stmt() {
|
||||
let src = "fn test() { 5 + 5; }";
|
||||
assert!(analyze(src).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valid_assignment() {
|
||||
let src = "fn test() { let a = 5; a = 10; }";
|
||||
assert!(analyze(src).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_assignment_type() {
|
||||
let src = "fn test() { let a: i32 = 5; a = true; }";
|
||||
let errors = analyze(src).unwrap_err();
|
||||
assert!(errors.iter().any(|e| e.message.contains("type mismatch")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_lvalue() {
|
||||
let src = "fn test() { 5 = 10; }";
|
||||
let errors = analyze(src).unwrap_err();
|
||||
assert!(
|
||||
errors
|
||||
.iter()
|
||||
.any(|e| e.message.contains("invalid left-hand side of assignment"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user