Add tests & semantic checks

This commit is contained in:
Alexander Zakharenko 2018-05-18 18:18:38 +03:00
parent ac5dff7717
commit dd90bee60e
8 changed files with 122 additions and 7 deletions

View file

@ -111,6 +111,7 @@ namespace SyntaxVisitors.SugarVisitors
public override void visit(is_pattern_expr isPatternExpr)
{
// TODO Patterns: convert to compilation error
Debug.Assert(GetLocation(isPatternExpr) != PatternLocation.Unknown, "Is-pattern expression is in an unknown context");
Debug.Assert(GetAscendant<statement_list>(isPatternExpr) != null, "Couldn't find statement list in upper nodes");
@ -357,7 +358,6 @@ namespace SyntaxVisitors.SugarVisitors
}
}
// TODO Patterns: convert to compilation error
Debug.Assert(definitionsAdded, "Couldn't add definitions");
}

View file

@ -0,0 +1,5 @@
begin
var s: string;
if 'asd' is string(s) then
Print(1);
end.

View file

@ -0,0 +1,4 @@
begin
var res := Arr(object(new List<integer>), object('asd'), object(1), object(2.0)).First(x -> x is string(s));
Assert(res = 'asd');
end.

View file

@ -0,0 +1,10 @@
begin
var a:='asd';
if (a is string(s)) and (s is string(s1)) then
if (s1 is string(s2)) and (s2 is string(s3)) and (s3 = 'asd') then
Assert(s3 = 'asd')
else
Assert(false)
else
Assert(false);
end.

View file

@ -0,0 +1,20 @@
type
Pair<T1, T2> = class
_a: T1; _b: T2;
procedure Deconstruct(var a: T1; var b: T2);
begin
a := _a;
b := _b;
end;
end;
begin
var p := new Pair<integer, string>;
p._a := 1;
p._b := 'asd';
if p is Pair<integer, string>(integer(a), string(b)) then
Assert((a = 1) and (b = 'asd'))
else
Assert(false);
end.

View file

@ -0,0 +1,9 @@
function Y1(): sequence of integer;
begin
if 1 is integer(i) then
yield i;
end;
begin
Assert(System.Linq.Enumerable.SequenceEqual(Seq(1), Y1));
end.

View file

@ -115,7 +115,7 @@ namespace PascalABCCompiler.TreeConverter
if (genericDeduceNeeded && (candidateParameter.is_generic_parameter || candidateParameter.is_generic_type_instance))
candidateParameter = InstantiateParameter(candidateParameter, deducedGenerics);
if (givenParameter != null && !AreTheSameTypes(candidateParameter, givenParameter))
if (givenParameter != null && !AreTheSameType(candidateParameter, givenParameter))
return false;
parameterTypes[i] = candidateParameter;
@ -124,7 +124,7 @@ namespace PascalABCCompiler.TreeConverter
return true;
}
private bool AreTheSameTypes(type_node type1, type_node type2)
private bool AreTheSameType(type_node type1, type_node type2)
{
return convertion_data_and_alghoritms.possible_equal_types(type1, type2);
}
@ -146,7 +146,7 @@ namespace PascalABCCompiler.TreeConverter
function.parameters.Count == 2 &&
function.parameters[0].type.is_generic_parameter &&
function.parameters[1].type.is_generic_parameter &&
AreTheSameTypes(function.parameters[0].type, function.parameters[1].type);
AreTheSameType(function.parameters[0].type, function.parameters[1].type);
}
private bool CheckIfParameterListElementsAreTheSame(List<type_node[]> parametersList)
@ -158,7 +158,7 @@ namespace PascalABCCompiler.TreeConverter
return false;
for (int j = 0; j < first.Length; j++)
if (!AreTheSameTypes(first[j], parametersList[i][j]))
if (!AreTheSameType(first[j], parametersList[i][j]))
return false;
}
@ -181,5 +181,36 @@ namespace PascalABCCompiler.TreeConverter
return genericNode as type_node;
}
}
private IEnumerable<int> GenericParameterIndices(SemanticTree.ITypeNode node)
{
if (node.is_generic_parameter)
yield return (node as type_node).generic_param_index;
if (node is generic_instance_type_node genericNode)
foreach (var index in genericNode.instance_params.Aggregate(
Enumerable.Empty<int>(),
(indices, nextNode) => indices.Concat(GenericParameterIndices(nextNode)))
.Distinct())
yield return index;
yield break;
}
private parameter GetSelfParameter(function_node node) => node.parameters.FirstOrDefault(x => IsSelfParameter(x));
/// <summary>
/// Проводит проверки, общие для экземплярных деконструкторов и расширений
/// </summary>
/// <param name="deconstructor"></param>
private void ExecuteCommonChecks(common_function_node deconstructor)
{
if (deconstructor.return_value_type != null)
AddError(deconstructor.loc, "DECONSTRUCTOR_SOULD_BE_A_PROCEDURE");
foreach (var parameter in deconstructor.parameters.Where(x => !IsSelfParameter(x)))
if (parameter.parameter_type != SemanticTree.parameter_type.var && parameter is common_parameter p)
AddError(p.loc, "DECONSTRUCTION_PARAMETERS_SHOULD_HAVE_VAR_MODIFIER");
}
}
}

View file

@ -12171,7 +12171,44 @@ namespace PascalABCCompiler.TreeConverter
hard_node_test_and_visit(_procedure_definition.proc_header);
}
//\lroman//
// Patterns
if (context.top_function != null &&
context.top_function is common_namespace_function_node commonNode &&
commonNode.name.ToLower() == compiler_string_consts.deconstruct_method_name)
{
var deconstructor = commonNode;
// TODO Patterns: add warning for non-extension deconstruct
if (!deconstructor.is_extension_method)
{
//AddWarning();
}
else
{
if (deconstructor.is_generic_function &&
deconstructor.generic_parameters_count != GenericParameterIndices(GetSelfParameter(deconstructor).type).Count())
AddError(get_location(_procedure_definition), "DECONSTRUCTOR_GENERIC_PARAMETERS_SHOULD_BE_DEFINED_BY_SELF_PARAMETER");
ExecuteCommonChecks(deconstructor);
}
}
if (context.top_function != null &&
context.top_function is common_method_node methodNode &&
methodNode.name.ToLower() == compiler_string_consts.deconstruct_method_name)
{
var deconstructor = methodNode;
if (deconstructor.is_generic_function)
AddError(get_location(_procedure_definition), "INSTANCE_DECONSTRUCTORS_CANNOT_BE_GENERIC");
ExecuteCommonChecks(deconstructor);
}
// !Patterns
//ssyy
if (context.converted_template_type != null)
@ -12765,7 +12802,6 @@ namespace PascalABCCompiler.TreeConverter
pa.source_context = _procedure_header.source_context;
_procedure_header.proc_attributes.proc_attributes.Add(pa);
}
weak_node_test_and_visit(_procedure_header.proc_attributes);
with_class_name = false;
CheckOverrideOrReintroduceExpectedWarning(get_location(_procedure_header));