public static void SetDownwardsLimits(SolvingNode[] toposortedNodes) { void Downwards(SolvingNode descendant) { if (descendant.State is ICompositeType composite) { foreach (var member in composite.Members) { Downwards(member); } } foreach (var ancestor in descendant.Ancestors) { descendant.State = SetDownwardsLimits(descendant, ancestor); } } for (int i = toposortedNodes.Length - 1; i >= 0; i--) { var descendant = toposortedNodes[i]; if (descendant.MemberOf.Any()) { continue; } Downwards(descendant); } }
public static void Destruction(SolvingNode[] toposorteNodes) { void Destruction(SolvingNode node) { if (node.State is ICompositeType composite) { if (composite.Members.Any(m => m.State is RefTo)) { node.State = composite.GetNonReferenced(); } foreach (var member in composite.Members) { Destruction(member); } } foreach (var ancestor in node.Ancestors.ToArray()) { TryMergeDestructive(node, ancestor); } } for (int i = toposorteNodes.Length - 1; i >= 0; i--) { var descendant = toposorteNodes[i]; if (descendant.MemberOf.Any()) { continue; } Destruction(descendant); } }
public void SetCall(IState[] argThenReturnTypes, int[] argThenReturnIds) { if (argThenReturnTypes.Length != argThenReturnIds.Length) { throw new ArgumentException("Sizes of type and id array have to be equal"); } for (int i = 0; i < argThenReturnIds.Length - 1; i++) { var type = argThenReturnTypes[i]; var argId = argThenReturnIds[i]; switch (type) { case Primitive primitive: { var node = GetOrCreateNode(argId); if (!node.TrySetAncestor(primitive)) { throw new InvalidOperationException(); } break; } case Array array: { //var node = GetOrCreateNode(argId); //var ancestor = CreateVarType(array); //ancestor.BecomeAncestorFor(node); //todo Upcast support GetOrCreateArrayNode(argId, array.ElementNode); break; } case Fun fun: { var node = GetOrCreateNode(argId); var ancestor = CreateVarType(fun); ancestor.BecomeAncestorFor(node); break; } case RefTo refTo: { var node = GetOrCreateNode(argId); refTo.Node.BecomeAncestorFor(node); break; } default: throw new InvalidOperationException(); } } var returnId = argThenReturnIds[argThenReturnIds.Length - 1]; var returnType = argThenReturnTypes[argThenReturnIds.Length - 1]; var returnNode = GetOrCreateNode(returnId); returnNode.State = SolvingFunctions.GetMergedState(returnNode.State, returnType); }
public void GetLastCommonAncestorOrNull_ConcreteFunTypeAndConstrainsArray_ReturnsAny() { var fun = Fun.Of(Primitive.I32, Primitive.I64); var array = Array.Of(CreateConstrainsNode()); Assert.AreEqual(Primitive.Any, fun.GetLastCommonAncestorOrNull(array)); Assert.AreEqual(Primitive.Any, array.GetLastCommonAncestorOrNull(fun)); }
static void ConcreteConcatEx() { // 2 0 1 //a:int[]; y = concat(a,b) var graph = new GraphBuilder(); graph.SetVarType("a", Array.Of(Primitive.I32)); graph.SetVar("a", 0); graph.SetVar("b", 1); graph.SetConcatCall(0, 1, 2); graph.SetDef("y", 2); var result = graph.Solve(); }
public void SetIfElse(int[] conditions, int[] expressions, int resultId) { var result = GetOrCreateNode(resultId); foreach (var exprId in expressions) { var expr = GetOrCreateNode(exprId); result.BecomeReferenceFor(expr); } foreach (var condId in conditions) { SetOrCreatePrimitive(condId, Primitive.Bool); } }
public void Array_referencesItself() { // 1 0 //x = reverse(x) var graph = new GraphBuilder(); graph.SetVar("x", 0); graph.SetReverse(0, 1); graph.SetDef("x", 1); var result = graph.Solve(); var res = result.AssertAndGetSingleGeneric(null, null); result.AssertNamed(Array.Of(res), "x"); }
public void ConcreteFunAndUpcast() { // 2 0 1 //a:int[]; y = First(a, isNan) var graph = new GraphBuilder(); graph.SetVarType("a", Array.Of(Primitive.I32)); graph.SetVar("a", 0); graph.SetVarType("isNan", Fun.Of(Primitive.Real, Primitive.Bool)); graph.SetVar("isNan", 1); graph.SetGetFirst(0, 1, 2); graph.SetDef("y", 2); var result = graph.Solve(); result.AssertNoGenerics(); }
public void Anything_WithConcreteFun() { // 2 0 1 //y = Any(a, isNan) var graph = new GraphBuilder(); graph.SetVar("a", 0); graph.SetVarType("isNan", Fun.Of(Primitive.Real, Primitive.Bool)); graph.SetVar("isNan", 1); graph.SetIsAny(0, 1, 2); graph.SetDef("y", 2); var result = graph.Solve(); result.AssertNoGenerics(); result.AssertNamed(Array.Of(Primitive.Real), "a"); }
public void ConcreteArg() { // 2 0 //x:int[]; y = sum(x) var graph = new GraphBuilder(); graph.SetVarType("x", Array.Of(Primitive.I32)); graph.SetVar("x", 0); graph.SetSumCall(0, 1); graph.SetDef("y", 1); var result = graph.Solve(); result.AssertNoGenerics(); result.AssertNamedEqualToArrayOf(Primitive.I32, "x"); result.AssertNamed(Primitive.I32, "y"); }
public void ConcreteCall() { // 1 0 //y = NoNans(x) var graph = new GraphBuilder(); graph.SetVar("x", 0); graph.SetCall(new IState[] { Array.Of(Primitive.Real), Primitive.Bool }, new [] { 0, 1 }); graph.SetDef("y", 1); var result = graph.Solve(); result.AssertNoGenerics(); result.AssertNamed(Array.Of(Primitive.Real), "x"); result.AssertNamed(Primitive.Bool, "y"); }
public void ConcreteArg() { // 2 0,1 //x:int[]; y = get(x,0) var graph = new GraphBuilder(); graph.SetVarType("x", Array.Of(Primitive.I32)); graph.SetVar("x", 0); graph.SetConst(1, Primitive.I32); graph.SetArrGetCall(0, 1, 2); graph.SetDef("y", 2); var result = graph.Solve(); result.AssertNoGenerics(); result.AssertNamedEqualToArrayOf(Primitive.I32, "x"); result.AssertNamed(Primitive.I32, "y"); }
public void ConcreteFun() { // 2 0 1 //y = Map(a, SQRT) var graph = new GraphBuilder(); graph.SetVar("a", 0); graph.SetVarType("SQRT", Fun.Of(Primitive.Real, Primitive.Real)); graph.SetVar("SQRT", 1); graph.SetMap(0, 1, 2); graph.SetDef("y", 2); var result = graph.Solve(); result.AssertNoGenerics(); result.AssertNamed(Array.Of(Primitive.Real), "a", "y"); }
public void Array_referencesItselfManyTimes() { // 4 0 3 1 2 //x = concat(x,concat(x,x) var graph = new GraphBuilder(); graph.SetVar("x", 0); graph.SetVar("x", 1); graph.SetVar("x", 2); graph.SetConcatCall(1, 2, 3); graph.SetConcatCall(0, 3, 4); graph.SetDef("x", 4); var result = graph.Solve(); var res = result.AssertAndGetSingleGeneric(null, null); result.AssertNamed(Array.Of(res), "x"); }
public void Anything_WithBoolArray() { // 3 0 2 1 //y = Any(a, x->x) var graph = new GraphBuilder(); graph.SetVar("a", 0); graph.SetVar("2lx", 1); graph.CreateLambda(1, 2, "2lx"); graph.SetIsAny(0, 2, 3); graph.SetDef("y", 3); var result = graph.Solve(); result.AssertNoGenerics(); result.AssertNamed(Array.Of(Primitive.Bool), "a"); result.AssertNamed(Primitive.Bool, "2lx"); result.AssertNode(Fun.Of(Primitive.Bool, Primitive.Bool), 2); }
public void Array_referencesItselfWithMap() { // 0 5 4 132 //x = x.map(f(a)=a+1) var graph = new GraphBuilder(); graph.SetVar("x", 0); graph.SetVar("la", 1); graph.SetIntConst(2, Primitive.U8); graph.SetArith(1, 2, 3); graph.CreateLambda(3, 4, "la"); graph.SetMap(0, 4, 5); graph.SetDef("x", 5); var result = graph.Solve(); var res = result.AssertAndGetSingleArithGeneric(); result.AssertNamed(Array.Of(res), "x"); }
public void TwoDimentions_Generic() { // 4 2 0,1 3 //y = get(get(x,0),0) var graph = new GraphBuilder(); graph.SetVar("x", 0); graph.SetConst(1, Primitive.I32); graph.SetArrGetCall(0, 1, 2); graph.SetConst(3, Primitive.I32); graph.SetArrGetCall(2, 3, 4); graph.SetDef("y", 4); var result = graph.Solve(); var generic = result.AssertAndGetSingleGeneric(null, null); result.AssertNamed(Array.Of(new Array(generic)), "x"); result.AssertAreGenerics(generic, "y"); }
public void Array_referencesItselfWithMap_RetTypeIsConcrete() { // 0 5 4 132 //x = x.map(f(a):i64=a+1) var graph = new GraphBuilder(); graph.SetVar("x", 0); graph.SetVar("la", 1); graph.SetIntConst(2, Primitive.U8); graph.SetArith(1, 2, 3); graph.CreateLambda(3, 4, Primitive.I64, "la"); graph.SetMap(0, 4, 5); graph.SetDef("x", 5); var result = graph.Solve(); result.AssertNoGenerics(); result.AssertNamed(Array.Of(Primitive.I64), "x"); }
public void ArrayCycle_Solved() { // 4 2 0 1 3 //x = [ get(x,0) , 1] var graph = new GraphBuilder(); graph.SetVar("x", 0); graph.SetIntConst(1, Primitive.U8); graph.SetArrGetCall(0, 1, 2); graph.SetIntConst(3, Primitive.U8); graph.SetArrayInit(4, 2, 3); graph.SetDef("x", 4); var res = graph.Solve(); var t = res.AssertAndGetSingleGeneric(Primitive.U8, Primitive.Real); res.AssertNamed(Array.Of(t), "x"); }
public void ThreeDimentions_ConcreteDefArrayOf() { // 4 2 0,1 3 //y:real[] = get(get(x,0),0) var graph = new GraphBuilder(); graph.SetVar("x", 0); graph.SetConst(1, Primitive.I32); graph.SetArrGetCall(0, 1, 2); graph.SetConst(3, Primitive.I32); graph.SetArrGetCall(2, 3, 4); graph.SetVarType("y", Array.Of(Primitive.Real)); graph.SetDef("y", 4); var result = graph.Solve(); result.AssertNoGenerics(); result.AssertNamed(Array.Of(Array.Of(Array.Of(Primitive.Real))), "x"); result.AssertNamed(Array.Of(Primitive.Real), "y"); }
public void TwoDimentions_ConcreteArg() { // 4 2 0,1 3 //x:int[][]; y = get(get(x,0),0) var graph = new GraphBuilder(); graph.SetVarType("x", Array.Of(Array.Of(Primitive.I32))); graph.SetVar("x", 0); graph.SetConst(1, Primitive.I32); graph.SetArrGetCall(0, 1, 2); graph.SetConst(3, Primitive.I32); graph.SetArrGetCall(2, 3, 4); graph.SetDef("y", 4); var result = graph.Solve(); result.AssertNoGenerics(); result.AssertNamed(Array.Of(Array.Of(Primitive.I32)), "x"); result.AssertNamed(Primitive.I32, "y"); }
public static void MergeGroup(SolvingNode[] cycleRoute) { var main = cycleRoute.First(); foreach (var current in cycleRoute) { if (current == main) { continue; } if (current.State is RefTo refState) { if (!cycleRoute.Contains(refState.Node)) { throw new InvalidOperationException(); } } else { //merge main and current main.State = GetMergedState(main.State, current.State); } main.Ancestors.AddRange(current.Ancestors); current.Ancestors.Clear(); if (!current.IsSolved) { current.State = new RefTo(main); } } var newAncestors = main.Ancestors.Distinct() .SelectMany(r => r.Ancestors) .Where(r => !cycleRoute.Contains(r)) .Distinct() .ToList(); main.Ancestors.Clear(); main.Ancestors.AddRange(newAncestors); }
public void Impossible_ConcreteArgAndDef_throws() { try { // 1 0 //x:real[]; y:int = sum(x) var graph = new GraphBuilder(); graph.SetVarType("x", Array.Of(Primitive.Real)); graph.SetVar("x", 0); graph.SetSumCall(0, 1); graph.SetVarType("y", Primitive.I32); graph.SetDef("y", 1); var result = graph.Solve(); Assert.Fail("Impossible equation solved"); } catch (Exception e) { Console.WriteLine(e); } }
public void Generic() { // 3 0 2 1 //y = Map(a, x->x) var graph = new GraphBuilder(); graph.SetVar("a", 0); graph.SetVar("2lx", 1); graph.CreateLambda(1, 2, "2lx"); graph.SetMap(0, 2, 3); graph.SetDef("y", 3); var result = graph.Solve(); var t = result.AssertAndGetSingleGeneric(null, null); result.AssertNamed(Array.Of(t), "a", "y"); result.AssertNode(Fun.Of(t, t)); }
//[Ignore("Upcast for complex types")] public void ConcreteCall_WithGenericArray() { // 3 2 0 1 //y = NoNans( [ 1, -1]) var graph = new GraphBuilder(); graph.SetIntConst(0, Primitive.U8); graph.SetIntConst(1, Primitive.I16); graph.SetArrayInit(2, 0, 1); graph.SetCall(new IState[] { Array.Of(Primitive.Real), Primitive.Bool }, new[] { 2, 3 }); graph.SetDef("y", 3); var result = graph.Solve(); result.AssertNoGenerics(); result.AssertNode(Array.Of(Primitive.Real), 2); result.AssertNode(Primitive.Real, 0, 1); result.AssertNamed(Primitive.Bool, "y"); }
public void ImpossibleArgType_Throws() { // 1 0 //x:Any[]; y = NoNans(x) var graph = new GraphBuilder(); graph.SetVarType("x", Array.Of(Primitive.Any)); graph.SetVar("x", 0); try { graph.SetCall(new IState[] { Array.Of(Primitive.Real), Primitive.Bool }, new[] { 0, 1 }); graph.SetDef("y", 1); graph.Solve(); Assert.Fail(); } catch (Exception e) { Console.WriteLine(e); } }
private void SetOrCreateLambda(int lambdaId, SolvingNode[] args, SolvingNode ret) { var fun = Fun.Of(args, ret); while (_syntaxNodes.Count <= lambdaId) { _syntaxNodes.Add(null); } var alreadyExists = _syntaxNodes[lambdaId]; if (alreadyExists != null) { alreadyExists.State = SolvingFunctions.GetMergedState(fun, alreadyExists.State); } else { var res = new SolvingNode(lambdaId.ToString(), fun, SolvingNodeType.SyntaxNode); _syntaxNodes[lambdaId] = res; } }
public void ConcreteArgAndDef_Impossible() { try { // 2 0,1 //x:real[]; y:int = get(x,0) var graph = new GraphBuilder(); graph.SetVarType("x", Array.Of(Primitive.Real)); graph.SetVar("x", 0); graph.SetConst(1, Primitive.I32); graph.SetArrGetCall(0, 1, 2); graph.SetVarType("y", Primitive.I32); graph.SetDef("y", 2); var result = graph.Solve(); Assert.Fail("Impossible equation solved"); } catch (Exception e) { Console.WriteLine(e); } }
public void ConcreteOutput() { // 3 0 2 1 //y:u16[] = Map(a, x->x) var graph = new GraphBuilder(); graph.SetVar("a", 0); graph.SetVar("2lx", 1); graph.CreateLambda(1, 2, "2lx"); graph.SetMap(0, 2, 3); graph.SetVarType("y", Array.Of(Primitive.U16)); graph.SetDef("y", 3); var result = graph.Solve(); result.AssertNoGenerics(); result.AssertNamed(Array.Of(Primitive.U16), "a", "y"); result.AssertNode(Fun.Of(Primitive.U16, Primitive.U16)); }
/// <summary> /// Превращает неопределенное ограничение в ограничение с массивом /// </summary> /// <param name="descNodeName"></param> /// <param name="descendant"></param> /// <param name="ancestor"></param> /// <returns></returns> private static Array TransformToArrayOrNull(string descNodeName, Constrains descendant, Array ancestor) { if (descendant.NoConstrains) { var constrains = new Constrains(); string eName; if (descNodeName.StartsWith("T") && descNodeName.Length > 1) { eName = "e" + descNodeName.Substring(1).ToLower() + "'"; } else { eName = "e" + descNodeName.ToLower() + "'"; } var node = new SolvingNode(eName, constrains, SolvingNodeType.TypeVariable); node.Ancestors.Add(ancestor.ElementNode); return(new Array(node)); } if (descendant.HasDescendant && descendant.Descedant is Array arrayEDesc) { if (arrayEDesc.Element is RefTo) { var origin = arrayEDesc.ElementNode.GetNonReference(); if (origin.IsSolved) { return(new Array(origin)); } } else if (arrayEDesc.ElementNode.IsSolved) { return(arrayEDesc); } } return(null); }