392 lines
18 KiB
C#
392 lines
18 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
using PascalABCCompiler.SyntaxTree;
|
|
using PascalABCCompiler.TreeRealization;
|
|
|
|
namespace PascalABCCompiler.TreeConverter
|
|
{
|
|
public partial class syntax_tree_visitor
|
|
{
|
|
public void semantic_check_assign_tuple(addressed_value_list vars, expression ex)
|
|
{
|
|
// Почти полностью идентичный код в двух проверках
|
|
var expr = convert_strong(ex);
|
|
expr = convert_if_typed_expression_to_function_call(expr);
|
|
|
|
var t = ConvertSemanticTypeNodeToNETType(expr.type);
|
|
if (t == null)
|
|
AddError(expr.location, "TUPLE_OR_SEQUENCE_EXPECTED");
|
|
|
|
var IsTuple = false;
|
|
var IsSequence = false;
|
|
if (t.FullName.StartsWith("System.Tuple"))
|
|
IsTuple = true;
|
|
if (!IsTuple)
|
|
{
|
|
if (t.Name.Equals("IEnumerable`1") || t.GetInterface("IEnumerable`1") != null)
|
|
IsSequence = true;
|
|
}
|
|
if (!IsTuple && !IsSequence)
|
|
{
|
|
AddError(expr.location, "TUPLE_OR_SEQUENCE_EXPECTED");
|
|
}
|
|
|
|
if (IsTuple)
|
|
{
|
|
var n = vars.variables.Count();
|
|
if (n > t.GetGenericArguments().Count())
|
|
AddError(get_location(vars), "TOO_MANY_ELEMENTS_ON_LEFT_SIDE_OF_TUPLE_ASSIGNMRNT");
|
|
}
|
|
}
|
|
|
|
public void semantic_check_assign_var_tuple(ident_list vars, expression ex)
|
|
{
|
|
// Почти полностью идентичный код в двух проверках
|
|
var expr = convert_strong(ex);
|
|
expr = convert_if_typed_expression_to_function_call(expr);
|
|
|
|
var t = ConvertSemanticTypeNodeToNETType(expr.type);
|
|
if (t == null)
|
|
AddError(expr.location, "TUPLE_OR_SEQUENCE_EXPECTED");
|
|
|
|
var IsTuple = false;
|
|
var IsSequence = false;
|
|
if (t.FullName.StartsWith("System.Tuple"))
|
|
IsTuple = true;
|
|
if (!IsTuple)
|
|
{
|
|
if (t.Name.Equals("IEnumerable`1") || t.GetInterface("IEnumerable`1") != null)
|
|
IsSequence = true;
|
|
}
|
|
if (!IsTuple && !IsSequence)
|
|
{
|
|
AddError(expr.location, "TUPLE_OR_SEQUENCE_EXPECTED");
|
|
}
|
|
|
|
if (IsTuple)
|
|
{
|
|
var n = vars.idents.Count();
|
|
if (n > t.GetGenericArguments().Count())
|
|
AddError(get_location(vars), "TOO_MANY_ELEMENTS_ON_LEFT_SIDE_OF_TUPLE_ASSIGNMRNT");
|
|
}
|
|
}
|
|
|
|
void semantic_check_method_call_as_slice_expr(SyntaxTree.method_call mc)
|
|
// нельзя проверять сахарный узел, т.к.могут быть вложенные сахарные expression!!
|
|
{
|
|
var v = (mc.dereferencing_value as dot_node).left;
|
|
var from = mc.parameters.expressions[1] as expression;
|
|
var to = mc.parameters.expressions[2] as expression;
|
|
expression step = mc.parameters.expressions.Count > 3 ? mc.parameters.expressions[3] : null;
|
|
|
|
var semvar = convert_strong(v);
|
|
if (semvar is typed_expression)
|
|
semvar = convert_typed_expression_to_function_call(semvar as typed_expression);
|
|
|
|
var IsSlicedType = 0; // проверим, является ли semvar.type динамическим массивом, списком List или строкой
|
|
if (semvar.type.type_special_kind == SemanticTree.type_special_kind.array_kind)
|
|
IsSlicedType = 1;
|
|
|
|
if (IsSlicedType == 0)
|
|
{
|
|
var t = ConvertSemanticTypeNodeToNETType(semvar.type); // не работает для array of T
|
|
|
|
// semvar.type должен быть array of T, List<T> или string
|
|
if (t == null)
|
|
IsSlicedType = 0; // можно ничего не присваивать :)
|
|
// else if (t.IsArray)
|
|
// IsSlicedType = 1;
|
|
else if (t == typeof(System.String))
|
|
IsSlicedType = 2;
|
|
else if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(System.Collections.Generic.List<>))
|
|
IsSlicedType = 3;
|
|
}
|
|
|
|
if (IsSlicedType == 0)
|
|
AddError(get_location(v), "BAD_SLICE_OBJECT");
|
|
|
|
var semfrom = convert_strong(from);
|
|
var b = convertion_data_and_alghoritms.can_convert_type(semfrom, SystemLibrary.SystemLibrary.integer_type);
|
|
var fromIsIndex = (semfrom is common_constructor_call fromCall) &&
|
|
fromCall.common_type.comprehensive_namespace.namespace_full_name.Equals("PABCSystem") &&
|
|
fromCall.common_type.PrintableName.Equals("SystemIndex");
|
|
if (!b && !fromIsIndex)
|
|
AddError(get_location(from), "INTEGER_VALUE_EXPECTED");
|
|
|
|
// semantic tree - type special kind
|
|
// staticSystemLib посмотреть.
|
|
// SystemIndex - переименовать.
|
|
var semto = convert_strong(to);
|
|
b = convertion_data_and_alghoritms.can_convert_type(semto, SystemLibrary.SystemLibrary.integer_type);
|
|
var toIsIndex = (semto is common_constructor_call toCall) &&
|
|
toCall.common_type.comprehensive_namespace.namespace_full_name.Equals("PABCSystem") &&
|
|
toCall.common_type.PrintableName.Equals("SystemIndex");
|
|
if (!b && !toIsIndex)
|
|
AddError(get_location(to), "INTEGER_VALUE_EXPECTED");
|
|
|
|
if (step != null)
|
|
{
|
|
var semstep = convert_strong(step);
|
|
b = convertion_data_and_alghoritms.can_convert_type(semstep, SystemLibrary.SystemLibrary.integer_type);
|
|
if (!b)
|
|
AddError(get_location(step), "INTEGER_VALUE_EXPECTED");
|
|
}
|
|
|
|
}
|
|
/*void semantic_check_tuple(SyntaxTree.tuple_node tup)
|
|
{
|
|
//if (tup.el.expressions.Count > 7)
|
|
// AddError(get_location(tup),"TUPLE_ELEMENTS_COUNT_MUST_BE_LESSEQUAL_7");
|
|
}*/
|
|
|
|
public void semantic_check_dot_question(SyntaxTree.question_colon_expression qce)
|
|
{
|
|
var av = convert_strong((qce.condition as bin_expr).left);
|
|
Type t = null;
|
|
if (av.type is compiled_generic_instance_type_node ctn2)
|
|
t = ctn2.compiled_original_generic.compiled_type;
|
|
else if (av.type is compiled_type_node ctn1)
|
|
t = ctn1.compiled_type;
|
|
if (av.type.type_special_kind == SemanticTree.type_special_kind.array_kind)
|
|
return;
|
|
if (!av.type.is_class && !av.type.IsInterface && !(t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)))
|
|
AddError(av.location, "OPERATOR_DQ_MUST_BE_USED_WITH_A_REFERENCE_TYPE_VALUETYPE");
|
|
}
|
|
|
|
public void semantic_check_loop_stmt(SyntaxTree.expression ex)
|
|
{
|
|
var sem_ex = convert_strong(ex);
|
|
var b = convertion_data_and_alghoritms.can_convert_type(sem_ex, SystemLibrary.SystemLibrary.integer_type);
|
|
if (!b)
|
|
AddError(sem_ex.location, "INTEGER_VALUE_EXPECTED");
|
|
}
|
|
|
|
public void semantic_check_slice_assignment_types(SyntaxTree.expression expr1, SyntaxTree.expression expr2, method_call mc)
|
|
{
|
|
var slice = expr1 as slice_expr;
|
|
var leftValue = convert_strong(slice.v);
|
|
var leftType = leftValue.type;
|
|
var rightValue = convert_strong(expr2);
|
|
var rightType = rightValue.type;
|
|
|
|
var v = slice.v;
|
|
var from = mc.parameters.expressions[2] as expression;
|
|
var to = mc.parameters.expressions[3] as expression;
|
|
expression step = mc.parameters.expressions.Count > 4 ? mc.parameters.expressions[4] : null;
|
|
|
|
var semvar = convert_strong(v);
|
|
if (semvar is typed_expression)
|
|
semvar = convert_typed_expression_to_function_call(semvar as typed_expression);
|
|
|
|
var IsSlicedType = 0; // проверим, является ли semvar.type динамическим массивом, списком List или строкой
|
|
if (semvar.type.type_special_kind == SemanticTree.type_special_kind.array_kind)
|
|
IsSlicedType = 1;
|
|
|
|
if (IsSlicedType == 0)
|
|
{
|
|
var t = ConvertSemanticTypeNodeToNETType(semvar.type); // не работает для array of T
|
|
|
|
// semvar.type должен быть array of T, List<T> или string
|
|
if (t == null)
|
|
IsSlicedType = 0; // можно ничего не присваивать :)
|
|
// else if (t.IsArray)
|
|
// IsSlicedType = 1;
|
|
else if (t == typeof(System.String))
|
|
IsSlicedType = 2;
|
|
else if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(System.Collections.Generic.List<>))
|
|
IsSlicedType = 3;
|
|
}
|
|
|
|
if (IsSlicedType == 0)
|
|
AddError(get_location(v), "BAD_SLICE_OBJECT");
|
|
|
|
var semfrom = convert_strong(from);
|
|
var fromIsIndex = (semfrom is common_constructor_call fromCall) &&
|
|
fromCall.common_type.comprehensive_namespace.namespace_full_name.Equals("PABCSystem") &&
|
|
fromCall.common_type.PrintableName.Equals("SystemIndex");
|
|
var b = convertion_data_and_alghoritms.can_convert_type(semfrom, SystemLibrary.SystemLibrary.integer_type);
|
|
if (!b && !fromIsIndex)
|
|
AddError(get_location(from), "INTEGER_VALUE_EXPECTED");
|
|
|
|
var semto = convert_strong(to);
|
|
var toIsIndex = (semto is common_constructor_call toCall) &&
|
|
toCall.common_type.comprehensive_namespace.namespace_full_name.Equals("PABCSystem") &&
|
|
toCall.common_type.PrintableName.Equals("SystemIndex");
|
|
b = convertion_data_and_alghoritms.can_convert_type(semto, SystemLibrary.SystemLibrary.integer_type);
|
|
if (!b && !toIsIndex)
|
|
AddError(get_location(to), "INTEGER_VALUE_EXPECTED");
|
|
|
|
if (step != null)
|
|
{
|
|
var semstep = convert_strong(step);
|
|
b = convertion_data_and_alghoritms.can_convert_type(semstep, SystemLibrary.SystemLibrary.integer_type);
|
|
if (!b)
|
|
AddError(get_location(step), "INTEGER_VALUE_EXPECTED");
|
|
}
|
|
|
|
if (!AreTheSameType(leftType, rightType))
|
|
{
|
|
AddError(get_location(expr2), "EXPRESSION_OF_TYPE_{0}_CANNOT_BE_ASSIGNED_TO_SLICE_OF_TYPE_{1}", rightType.PrintableName, leftType.PrintableName);
|
|
}
|
|
}
|
|
|
|
/*void common_diap_check(expression from, expression to)
|
|
{
|
|
|
|
}*/
|
|
|
|
void semantic_check_method_call_as_diapason_expr(SyntaxTree.method_call mc)
|
|
{
|
|
var from = mc.parameters.expressions[0];
|
|
var to = mc.parameters.expressions[1];
|
|
|
|
var semfrom = convert_strong(from);
|
|
var b = convertion_data_and_alghoritms.can_convert_type(semfrom, SystemLibrary.SystemLibrary.integer_type);
|
|
var b1 = false;
|
|
var br = false;
|
|
if (!b)
|
|
b1 = convertion_data_and_alghoritms.can_convert_type(semfrom, SystemLibrary.SystemLibrary.char_type);
|
|
if (!b1)
|
|
br = convertion_data_and_alghoritms.can_convert_type(semfrom, SystemLibrary.SystemLibrary.double_type);
|
|
if (!b && !b1 && !br)
|
|
AddError(get_location(from), "INTEGER_OR_REAL_OR_CHAR_VALUE_EXPECTED");
|
|
|
|
var semto = convert_strong(to);
|
|
var c = convertion_data_and_alghoritms.can_convert_type(semto, SystemLibrary.SystemLibrary.integer_type);
|
|
var c1 = false;
|
|
var cr = false;
|
|
if (!c)
|
|
c1 = convertion_data_and_alghoritms.can_convert_type(semto, SystemLibrary.SystemLibrary.char_type);
|
|
if (!c1)
|
|
cr = convertion_data_and_alghoritms.can_convert_type(semto, SystemLibrary.SystemLibrary.double_type);
|
|
if (!c && !c1 && !cr)
|
|
AddError(get_location(to), "INTEGER_OR_REAL_OR_CHAR_VALUE_EXPECTED");
|
|
//if (b != c || c1 != b1 || cr != br)
|
|
if (b && c || c1 && b1 || cr && br)
|
|
return;
|
|
if (b && cr || c && br)
|
|
return;
|
|
AddError(get_location(to), "INCOMPATIBLE_DIAPASON_BOUNDS_TYPES");
|
|
}
|
|
|
|
void semantic_check_method_call_as_inrange_expr(SyntaxTree.method_call mc)
|
|
{
|
|
var v = mc.parameters.expressions[0];
|
|
var from = mc.parameters.expressions[1];
|
|
var to = mc.parameters.expressions[2];
|
|
|
|
var semv = convert_strong(v);
|
|
var a = convertion_data_and_alghoritms.can_convert_type(semv, SystemLibrary.SystemLibrary.integer_type);
|
|
var a1 = false;
|
|
var ar = false;
|
|
if (!a)
|
|
a1 = convertion_data_and_alghoritms.can_convert_type(semv, SystemLibrary.SystemLibrary.char_type);
|
|
if (!a1)
|
|
ar = convertion_data_and_alghoritms.can_convert_type(semv, SystemLibrary.SystemLibrary.double_type);
|
|
if (!a && !a1 && !ar)
|
|
AddError(get_location(v), "INTEGER_OR_REAL_OR_CHAR_VALUE_EXPECTED");
|
|
|
|
var semfrom = convert_strong(from);
|
|
var b = convertion_data_and_alghoritms.can_convert_type(semfrom, SystemLibrary.SystemLibrary.integer_type);
|
|
var b1 = false;
|
|
var br = false;
|
|
if (!b)
|
|
b1 = convertion_data_and_alghoritms.can_convert_type(semfrom, SystemLibrary.SystemLibrary.char_type);
|
|
if (!b1)
|
|
br = convertion_data_and_alghoritms.can_convert_type(semfrom, SystemLibrary.SystemLibrary.double_type);
|
|
if (!b && !b1 && !br)
|
|
AddError(get_location(from), "INTEGER_OR_REAL_OR_CHAR_VALUE_EXPECTED");
|
|
|
|
var semto = convert_strong(to);
|
|
var c = convertion_data_and_alghoritms.can_convert_type(semto, SystemLibrary.SystemLibrary.integer_type);
|
|
var c1 = false;
|
|
var cr = false;
|
|
if (!c)
|
|
c1 = convertion_data_and_alghoritms.can_convert_type(semto, SystemLibrary.SystemLibrary.char_type);
|
|
if (!c1)
|
|
cr = convertion_data_and_alghoritms.can_convert_type(semto, SystemLibrary.SystemLibrary.double_type);
|
|
if (!c && !c1 && !cr)
|
|
AddError(get_location(to), "INTEGER_OR_REAL_OR_CHAR_VALUE_EXPECTED");
|
|
|
|
var incompbound = true;
|
|
if (b && c || c1 && b1 || cr && br)
|
|
incompbound = false;
|
|
if (b && cr || c && br)
|
|
incompbound = false;
|
|
|
|
if (incompbound)
|
|
AddError(get_location(to), "INCOMPATIBLE_DIAPASON_BOUNDS_TYPES");
|
|
if (a && b1 || ar && b1 || a1 && b || a1 && c)
|
|
AddError(get_location(v), "INCOMPATIBLE_TYPES_OF_ELEMENT_AND_DIAPASON");
|
|
}
|
|
|
|
void semantic_check_for_new_range(SyntaxTree.diapason_expr_new diap, type_definition td, ident id)
|
|
{
|
|
var from = diap.left;
|
|
var to = diap.right;
|
|
|
|
var semfrom = convert_strong(from);
|
|
var b = convertion_data_and_alghoritms.can_convert_type(semfrom, SystemLibrary.SystemLibrary.integer_type);
|
|
var b1 = false;
|
|
if (!b)
|
|
b1 = convertion_data_and_alghoritms.can_convert_type(semfrom, SystemLibrary.SystemLibrary.char_type);
|
|
if (!b && !b1)
|
|
AddError(get_location(from), "INTEGER_OR_CHAR_VALUE_EXPECTED");
|
|
|
|
var semto = convert_strong(to);
|
|
var c = convertion_data_and_alghoritms.can_convert_type(semto, SystemLibrary.SystemLibrary.integer_type);
|
|
var c1 = false;
|
|
if (!c)
|
|
c1 = convertion_data_and_alghoritms.can_convert_type(semto, SystemLibrary.SystemLibrary.char_type);
|
|
if (!c && !c1)
|
|
AddError(get_location(to), "INTEGER_OR_CHAR_VALUE_EXPECTED");
|
|
|
|
if (b != c || c1 != b1)
|
|
AddError(get_location(to), "INCOMPATIBLE_DIAPASON_BOUNDS_TYPES");
|
|
|
|
if (td != null && !(td is no_type_foreach))
|
|
{
|
|
// то мы определили тип явно в заголовке
|
|
var semtype = convert_strong(td);
|
|
var d = convertion_data_and_alghoritms.can_convert_type(semtype, SystemLibrary.SystemLibrary.integer_type);
|
|
var d1 = false;
|
|
if (!d)
|
|
d1 = convertion_data_and_alghoritms.can_convert_type(semtype, SystemLibrary.SystemLibrary.char_type);
|
|
if (!d && !d1)
|
|
AddError(get_location(td), "INTEGER_OR_CHAR_VALUE_EXPECTED");
|
|
if (b != d || b1 != d1)
|
|
AddError(get_location(id), "INCOMPATIBLE_TYPES_OF_ELEMENT_AND_DIAPASON");
|
|
}
|
|
else if (td == null)
|
|
{
|
|
var semid = convert_strong(id);
|
|
var e = convertion_data_and_alghoritms.can_convert_type(semid, SystemLibrary.SystemLibrary.integer_type);
|
|
var e1 = false;
|
|
if (!e)
|
|
e1 = convertion_data_and_alghoritms.can_convert_type(semid, SystemLibrary.SystemLibrary.char_type);
|
|
if (!e && !e1)
|
|
AddError(get_location(id), "INTEGER_OR_CHAR_VALUE_EXPECTED");
|
|
|
|
if (b != e || b1 != e1)
|
|
AddError(get_location(id), "INCOMPATIBLE_TYPES_OF_ELEMENT_AND_DIAPASON");
|
|
}
|
|
}
|
|
|
|
void semantic_check_for_indices(SyntaxTree.expression expr)
|
|
{
|
|
// Надо проверить, что expr - это одноразмерный массив или список. Эта проверка была в visit(foreach)
|
|
var semexpr = convert_strong(expr);
|
|
var Is1DArr = Is1DArray(semexpr);
|
|
var il = IsIList(semexpr);
|
|
// Тут может быть другая ситуация - Indices может быть членом semexpr - и тогда нельзя преобразовывать
|
|
if (!Is1DArr && !il)
|
|
AddError(get_location(expr), "ONE_DIM_ARRAY_OR_LIST_EXPECTED");
|
|
}
|
|
|
|
|
|
}
|
|
}
|