feat(selfhost-sema): check annotation vs initializer type in let/var
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
func Main() -> int {
|
func Main() -> int {
|
||||||
let bad: int = "a" + 1;
|
let x: int = "hello";
|
||||||
|
let y: bool = 42;
|
||||||
let z: int = undefined_variable;
|
let z: int = undefined_variable;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -198,6 +198,33 @@ module Sema {
|
|||||||
return kind == tyBool || kind == tyBool8 || kind == tyBool16 || kind == tyBool32;
|
return kind == tyBool || kind == tyBool8 || kind == tyBool16 || kind == tyBool32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Strict numeric predicate for assignment checking: unlike Sema_IsNumeric,
|
||||||
|
// this does NOT treat tyNamed/tyTypeParam as numeric.
|
||||||
|
func Sema_IsStrictNumeric(kind: int) -> bool {
|
||||||
|
if kind == tyInt8 || kind == tyInt16 || kind == tyInt32 || kind == tyInt64 || kind == tyInt { return true; }
|
||||||
|
if kind == tyUInt8 || kind == tyUInt16 || kind == tyUInt32 || kind == tyUInt64 || kind == tyUInt { return true; }
|
||||||
|
if kind == tyFloat32 || kind == tyFloat64 { return true; }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display-name helper for assignment diagnostics.
|
||||||
|
func Sema_TypeNameForDiag(te: *TypeExpr, kind: int) -> String {
|
||||||
|
if te != null as *TypeExpr {
|
||||||
|
if te.kind == tekPointer && te.pointerPointee != null as *TypeExpr {
|
||||||
|
return String_Concat(te.pointerPointee.typeName, "*");
|
||||||
|
}
|
||||||
|
if !String_Eq(te.typeName, "") { return te.typeName; }
|
||||||
|
}
|
||||||
|
if kind == tyBool { return "bool"; }
|
||||||
|
if kind == tyStr { return "String"; }
|
||||||
|
if kind == tyInt { return "int"; }
|
||||||
|
if kind == tyInt64 { return "int64"; }
|
||||||
|
if kind == tyUInt { return "uint"; }
|
||||||
|
if kind == tyFloat64 { return "float64"; }
|
||||||
|
if kind == tyPointer { return "*void"; }
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Block checking helper
|
// Block checking helper
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -1466,6 +1493,37 @@ module Sema {
|
|||||||
sym.typeName = stmt.child1.refType.typeName;
|
sym.typeName = stmt.child1.refType.typeName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Assignment check: annotation vs initializer (skip when either side is unknown)
|
||||||
|
if stmt.refStmtType != null as *TypeExpr && initType != tyUnknown {
|
||||||
|
let annotKind: int = Sema_ResolveType(sema, stmt.refStmtType);
|
||||||
|
if annotKind != tyUnknown {
|
||||||
|
var mismatch: bool = false;
|
||||||
|
if initType == tyNamed && annotKind == tyNamed {
|
||||||
|
// Both named: kinds are equal, compare type names (when available).
|
||||||
|
if stmt.child1 != null as *Expr && stmt.child1.refType != null as *TypeExpr {
|
||||||
|
if !String_Eq(stmt.child1.refType.typeName, "") &&
|
||||||
|
!String_Eq(stmt.child1.refType.typeName, stmt.refStmtType.typeName) {
|
||||||
|
mismatch = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if initType != annotKind {
|
||||||
|
let numericOk: bool = Sema_IsStrictNumeric(initType) && Sema_IsStrictNumeric(annotKind);
|
||||||
|
let initIsPtr: bool = initType == tyPointer || initType == tyStr;
|
||||||
|
let annotIsPtr: bool = annotKind == tyPointer || annotKind == tyStr;
|
||||||
|
let ptrOk: bool = initIsPtr && annotIsPtr;
|
||||||
|
if !numericOk && !ptrOk {
|
||||||
|
mismatch = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if mismatch {
|
||||||
|
let gotName: String = Sema_TypeNameForDiag(stmt.child1.refType, initType);
|
||||||
|
let wantName: String = Sema_TypeNameForDiag(stmt.refStmtType, annotKind);
|
||||||
|
let msg: String = String_Concat("cannot assign ",
|
||||||
|
String_Concat(gotName, String_Concat(" to ", wantName)));
|
||||||
|
Sema_EmitError(sema, stmt.line, stmt.column, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
sym.isMutable = stmt.boolValue;
|
sym.isMutable = stmt.boolValue;
|
||||||
sym.isPublic = false;
|
sym.isPublic = false;
|
||||||
sym.decl = null as *Decl;
|
sym.decl = null as *Decl;
|
||||||
|
|||||||
Reference in New Issue
Block a user