fix checking of array literal compatability

This commit is contained in:
Dave Holoway
2020-06-15 16:57:00 +01:00
parent 2f3349c359
commit a8653f26df

View File

@@ -1645,20 +1645,14 @@ function checkAssignmentExpression(tokens, variable, op, value) {
addproblem(tokens, ParseProblem.Error(op, `Invalid assignment: left-hand side is not a variable`)); addproblem(tokens, ParseProblem.Error(op, `Invalid assignment: left-hand side is not a variable`));
return; return;
} }
let is_assignable; const is_assignable = isAssignable(variable.type, value);
// we need to special-case ArrayLiteral because it has no type associated with it if (!is_assignable) {
if (value instanceof ArrayLiteral) { if (value instanceof ArrayLiteral) {
is_assignable = isArrayAssignable(variable.type, value);
if (!is_assignable) {
addproblem(tokens, ParseProblem.Error(op, `Array literal expression is not compatible with variable of type '${variable.type.fullyDottedTypeName}'`)); addproblem(tokens, ParseProblem.Error(op, `Array literal expression is not compatible with variable of type '${variable.type.fullyDottedTypeName}'`));
} } else {
return;
}
is_assignable = isAssignable(variable.type, value);
if (!is_assignable) {
addproblem(tokens, ParseProblem.Error(op, `Incompatible types: Expression of type '${value.type.fullyDottedTypeName}' cannot be assigned to a variable of type '${variable.type.fullyDottedTypeName}'`)); addproblem(tokens, ParseProblem.Error(op, `Incompatible types: Expression of type '${value.type.fullyDottedTypeName}' cannot be assigned to a variable of type '${variable.type.fullyDottedTypeName}'`));
} }
}
if (value instanceof TernaryValue) { if (value instanceof TernaryValue) {
checkAssignmentExpression(tokens, variable, value.colon, value.falseValue); checkAssignmentExpression(tokens, variable, value.colon, value.falseValue);
@@ -1667,35 +1661,20 @@ function checkAssignmentExpression(tokens, variable, op, value) {
/** /**
* @param {JavaType} variable_type * @param {JavaType} variable_type
* @param {ArrayLiteral} value * @param {ArrayLiteral} arr_literal_value
*/ */
function isArrayAssignable(variable_type, value) { function isArrayAssignable(variable_type, arr_literal_value) {
if (!(variable_type instanceof ArrayType)) { if (!(variable_type instanceof ArrayType)) {
return false; return false;
} }
// empty array literals are compatible with all arrays // empty array literals are compatible with all arrays
if (value.elements.length === 0) { if (arr_literal_value.elements.length === 0) {
return true; return true;
} }
const required_element_type = variable_type.elementType; const required_element_type = variable_type.elementType;
for (let i=0; i < value.elements.length; i++) { for (let i=0; i < arr_literal_value.elements.length; i++) {
const element = value.elements[i]; const element_value = arr_literal_value.elements[i].variables[0];
let is_assignable; let is_assignable = !!element_value && isAssignable(required_element_type, element_value);
if (required_element_type instanceof ArrayType) {
// the element must be another array literal expression or a value with a matching array type
if (element instanceof ArrayLiteral) {
is_assignable = isArrayAssignable(required_element_type, element);
} else {
is_assignable = element.variables[0] ? isAssignable(required_element_type, element.variables[0]) : false;
}
} else {
// base type = the element must match the (non-array) type
if (element instanceof ArrayLiteral) {
is_assignable = false;
} else {
is_assignable = element.variables[0] ? isAssignable(required_element_type, element.variables[0]) : false;
}
}
if (!is_assignable) { if (!is_assignable) {
return false; return false;
} }
@@ -1712,6 +1691,9 @@ function isAssignable(type, value) {
if (value instanceof LiteralNumber) { if (value instanceof LiteralNumber) {
return value.isCompatibleWith(type); return value.isCompatibleWith(type);
} }
if (value instanceof ArrayLiteral) {
return isArrayAssignable(type, value);
}
return isTypeAssignable(type, value.type); return isTypeAssignable(type, value.type);
} }