backward inference
This commit is contained in:
42
parse.cm
42
parse.cm
@@ -1616,6 +1616,46 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
if (kind == "[" && left_node.right != null) {
|
||||
sem_check_expr(scope, left_node.right)
|
||||
}
|
||||
// Type error detection for known-type constant objects
|
||||
if (obj_expr != null && obj_expr.kind == "name" && obj_expr.name != null) {
|
||||
v = sem_find_var(scope, obj_expr.name)
|
||||
if (v != null && v.is_const && v.type_tag != null) {
|
||||
if (kind == ".") {
|
||||
if (v.type_tag == "array") {
|
||||
sem_error(left_node, "cannot set property on array '" + obj_expr.name + "'")
|
||||
}
|
||||
} else if (kind == "[") {
|
||||
if (left_node.right == null) {
|
||||
// Push: a[] = val
|
||||
if (v.type_tag != "array") {
|
||||
sem_error(left_node, "push only works on arrays, not " + v.type_tag + " '" + obj_expr.name + "'")
|
||||
}
|
||||
} else if (v.type_tag == "array") {
|
||||
if (left_node.right.kind == "text") {
|
||||
sem_error(left_node, "cannot use text key on array '" + obj_expr.name + "'")
|
||||
}
|
||||
} else if (v.type_tag == "record") {
|
||||
if (left_node.right.kind == "number" && is_integer(left_node.right.number)) {
|
||||
sem_error(left_node, "cannot use integer key on record '" + obj_expr.name + "'; use text key")
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (v != null && v.is_const && v.type_tag == null) {
|
||||
// Infer type_tag from usage pattern (def only)
|
||||
if (kind == ".") {
|
||||
v.type_tag = "record"
|
||||
} else if (kind == "[") {
|
||||
if (left_node.right == null) {
|
||||
// Push: a[] = val → array
|
||||
v.type_tag = "array"
|
||||
} else if (left_node.right.kind == "number" && is_integer(left_node.right.number)) {
|
||||
v.type_tag = "array"
|
||||
} else if (left_node.right.kind == "text") {
|
||||
v.type_tag = "record"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1861,7 +1901,7 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
sem_check_expr(scope, stmt.right)
|
||||
if (name != null) {
|
||||
tt = derive_type_tag(stmt.right)
|
||||
if (tt != null) {
|
||||
if (tt != null && tt != "null") {
|
||||
existing = sem_find_var(scope, name)
|
||||
if (existing != null) existing.type_tag = tt
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user