static void ThrowIfStateHasRecursiveTypeDefeinitionReq(ITicNodeState state, int bypassNumber) { switch (state) { case StateRefTo refTo: ThrowIfNodeHasRecursiveTypeDefenitionReq(refTo.Node, 1); break; case ICompositeState composite: foreach (var member in composite.Members) { ThrowIfNodeHasRecursiveTypeDefenitionReq(member, 1); } break; case ConstrainsState constrains: if (constrains.HasDescendant) { ThrowIfStateHasRecursiveTypeDefeinitionReq(constrains.Descedant, 1); } if (constrains.HasAncestor) { ThrowIfStateHasRecursiveTypeDefeinitionReq(constrains.Ancestor, 1); } break; } }
public IncompatibleAncestorSyntaxNodeException(int syntaxNodeId, ITicNodeState ancestor, ITicNodeState descendant) : base($"Incompatible ancestor {ancestor}=>{descendant} at node {syntaxNodeId}") { SyntaxNodeId = syntaxNodeId; Ancestor = ancestor; Descendant = descendant; }
public static void AssertGenericType(this ITicNodeState state, StatePrimitive desc, StatePrimitive anc, bool isComparable = false) { var generic = state as ConstrainsState; Assert.IsNotNull(generic); if (desc == null) { Assert.IsFalse(generic.HasDescendant); } else { Assert.AreEqual(desc, generic.Descedant, "Actual generic type is " + generic); } if (anc == null) { Assert.IsFalse(generic.HasAncestor); } else { Assert.AreEqual(anc, generic.Ancestor); } Assert.AreEqual(isComparable, generic.IsComparable, "IsComparable claim missed"); }
private TicNode(object name, ITicNodeState state, TicNodeType type) { _uid = Interlocked.Increment(ref _interlockedId); Name = name; State = state; Type = type; }
public static void SetCall(this GraphBuilder builder, StatePrimitive ofTheCall, params int[] argumentsThenResult) { var types = new ITicNodeState[argumentsThenResult.Length]; for (int i = 0; i < types.Length; i++) { types[i] = ofTheCall; } builder.SetCall(types, argumentsThenResult); }
public static bool AreSame(ITicNodeState a, ITicNodeState b) { if (a is StateRefTo r1) { a = r1.Node.GetNonReference().State; } if (b is StateRefTo r2) { b = r2.Node.GetNonReference().State; } return(a.Equals(b)); }
public static Exception CannotSetState(TicNode node, ITicNodeState b) { if (node.Type == TicNodeType.SyntaxNode) { return(new IncompatibleAncestorSyntaxNodeException((int)node.Name, node.State, b)); } if (node.Type == TicNodeType.Named) { return(new IncompatibleAncestorNamedNodeException(node.Name.ToString(), node.State, b)); } return(new TicNoDetailsException()); }
public static StateArray Of(ITicNodeState state) { if (state is ITypeState type) { return(Of(type)); } if (state is StateRefTo refTo) { return(Of(refTo.Node)); } throw new InvalidOperationException(); }
public static void AssertAreSame(ITicNodeState expected, ITicNodeState actual) { if (!AreSame(expected, actual)) { if (expected is StateRefTo r1) { expected = r1.Node.GetNonReference().State; } if (actual is StateRefTo r2) { actual = r2.Node.GetNonReference().State; } Assert.Fail($"Expected: {expected} but was: {actual}"); } }
private static bool AreStatesEqualByValue(ITicNodeState a, ITicNodeState b) { while (a is StateRefTo arefTo) { a = arefTo.Node.State; } while (b is StateRefTo brefTo) { b = brefTo.Node.State; } if (a.GetType() != b.GetType()) { return(false); } if (a is StatePrimitive) { return(a.Equals(b)); } if (a is ConstrainsState) { return(a.Equals(b)); } if (a is ICompositeState aComposite && b is ICompositeState bComposite) { var aMembers = aComposite.Members.ToArray(); var bMembers = bComposite.Members.ToArray(); if (aMembers.Length != bMembers.Length) { return(false); } for (int i = 0; i < aMembers.Length; i++) { if (!AreStatesEqualByValue(aMembers[i].State, bMembers[i].State)) { return(false); } } return(true); } return(false); }
private static ITicNodeState GetNonReferencedState(ITicNodeState state) { if (state is StatePrimitive) { return(state); } if (state is ConstrainsState) { return(state); } if (state is StateRefTo refTo) { return(GetNonReferencedState(refTo.Node.State)); } if (state is ICompositeState compositeState) { return(compositeState.GetNonReferenced()); } throw new NotSupportedException(); }
public static StateFun Of(ITicNodeState[] argTypes, ITicNodeState returnType) { TicNode[] argNodes = new TicNode[argTypes.Length]; TicNode retNode = null; if (returnType is ITypeState rt) { retNode = TicNode.CreateTypeVariableNode(rt); } else if (returnType is StateRefTo retRef) { retNode = retRef.Node; } else { throw new InvalidOperationException(); } for (int i = 0; i < argTypes.Length; i++) { if (argTypes[i] is ITypeState at) { argNodes[i] = TicNode.CreateTypeVariableNode(at); } else if (argTypes[i] is StateRefTo aRef) { argNodes[i] = aRef.Node; } else { throw new InvalidOperationException(); } } return(new StateFun(argNodes, retNode)); }
public static TicNode CreateTypeVariableNode(string name, ITicNodeState state, bool registrated = false) => new TicNode(name, state, TicNodeType.TypeVariable) { Registrated = registrated };
public static TicNode CreateNamedNode(object name, ITicNodeState state) => new TicNode(name, state, TicNodeType.Named) { Registrated = true };
public static TicNode CreateSyntaxNode(int id, ITicNodeState state, bool registrated = false) => new TicNode(id, state, TicNodeType.SyntaxNode) { Registrated = registrated };
public static ITicNodeState GetMergedStateOrNull(ITicNodeState stateA, ITicNodeState stateB) { if (stateB is ConstrainsState c && c.NoConstrains) { return(stateA); } if (stateA is ITypeState typeA && !typeA.IsMutable) { if (stateB is ITypeState typeB && !typeB.IsMutable) { return(!typeB.Equals(typeA) ? null : typeA); } if (stateB is ConstrainsState constrainsB) { return(!constrainsB.Fits(typeA) ? null : typeA); } } switch (stateA) { case StateArray arrayA when stateB is StateArray arrayB: MergeInplace(arrayA.ElementNode, arrayB.ElementNode); return(arrayA); case StateFun funA when stateB is StateFun funB: { if (funA.ArgsCount != funB.ArgsCount) { return(null); } for (int i = 0; i < funA.ArgsCount; i++) { MergeInplace(funA.ArgNodes[i], funB.ArgNodes[i]); } MergeInplace(funA.RetNode, funB.RetNode); return(funA); } case StateStruct strA when stateB is StateStruct strB: { var result = new Dictionary <string, TicNode>(); foreach (var aField in strA.Fields) { var bNode = strB.GetFieldOrNull(aField.Key); if (bNode != null) { MergeInplace(aField.Value, bNode); } result.Add(aField.Key, aField.Value); } foreach (var bField in strB.Fields) { if (!result.ContainsKey(bField.Key)) { result.Add(bField.Key, bField.Value); } } return(new StateStruct(result)); } case ConstrainsState constrainsA when stateB is ConstrainsState constrainsB: return(constrainsB.MergeOrNull(constrainsA)); case ConstrainsState _: return(GetMergedStateOrNull(stateB, stateA)); case StateRefTo refA: { var state = GetMergedStateOrNull(refA.Node.State, stateB); if (state == null) { return(null); } refA.Node.State = state; return(stateA); } } if (stateB is StateRefTo) { return(GetMergedStateOrNull(stateB, stateA)); } return(null); }
public bool Visit(FunCallSyntaxNode node) { var signature = _dictionary.GetOrNull(node.Id, node.Args.Length); node.FunctionSignature = signature; //Apply visitor to child types for (int i = 0; i < node.Args.Length; i++) { if (signature != null) { _parentFunctionArgType = signature.ArgTypes[i]; } node.Args[i].Accept(this); } //Setup ids arrays var ids = new int[node.Args.Length + 1]; for (int i = 0; i < node.Args.Length; i++) { ids[i] = node.Args[i].OrderNumber; } ids[ids.Length - 1] = node.OrderNumber; var userFunction = _resultsBuilder.GetUserFunctionSignature(node.Id, node.Args.Length); if (userFunction != null) { //Call user-function if it is being built at the same time as the current expression is being built //for example: recursive calls, or if function relates to global variables #if DEBUG Trace(node, $"Call UF{node.Id}({string.Join(",", ids)})"); #endif _ticTypeGraph.SetCall(userFunction, ids); //in the case of generic user function - we dont know generic arg types yet //we need to remember generic TIC signature to used it at the end of interpritation _resultsBuilder.RememberRecursiveCall(node.OrderNumber, userFunction); return(true); } if (signature == null) { //Functional variable #if DEBUG Trace(node, $"Call hi order {node.Id}({string.Join(",", ids)})"); #endif _ticTypeGraph.SetCall(node.Id, ids); return(true); } //Normal function call #if DEBUG Trace(node, $"Call {node.Id}({string.Join(",", ids)})"); #endif if (signature is PureGenericFunctionBase pure) { // Сase of (T,T):T signatures // This case is most common, so the call is optimized var genericType = InitializeGenericType(pure.Constrainses[0]); _resultsBuilder.RememberGenericCallArguments(node.OrderNumber, new[] { genericType }); _ticTypeGraph.SetCall(genericType, ids); return(true); } StateRefTo[] genericTypes; if (signature is GenericFunctionBase t) { // Optimization // Remember generic arguments to use it again at the built time genericTypes = InitializeGenericTypes(t.Constrainses); // save refernces to generic types, for use at 'apply tic results' step _resultsBuilder.RememberGenericCallArguments(node.OrderNumber, genericTypes); } else { genericTypes = new StateRefTo[0]; } var types = new ITicNodeState[signature.ArgTypes.Length + 1]; for (int i = 0; i < signature.ArgTypes.Length; i++) { types[i] = signature.ArgTypes[i].ConvertToTiType(genericTypes); } types[types.Length - 1] = signature.ReturnType.ConvertToTiType(genericTypes); _ticTypeGraph.SetCall(types, ids); return(true); }
private static void AssertNodeStateEqualToState(ITypeState expected, ITicNodeState actual, object id) => Assert.IsTrue(AreStatesEqualByValue(actual, expected), $"States are not equal for '{id}': \r\nExpected: {expected}\r\nActual: {actual}");
public static StateFun Of(ITicNodeState argType, ITicNodeState returnType) => Of(new[] { argType }, returnType);
public override FunnyType Convert(ITicNodeState type) => type switch {
private static TicNode CreateNode(string name, ITicNodeState state = null) => TicNode.CreateNamedNode(name, state ?? new ConstrainsState());
public IncompatibleAncestorNamedNodeException(string nodeName, ITicNodeState ancestor, ITicNodeState descendant) : base($"Incompatible ancestor {ancestor}=>{descendant} at node {nodeName}") { NodeName = nodeName; Ancestor = ancestor; Descendant = descendant; }
public abstract FunnyType Convert(ITicNodeState type);
private BasicDescType ToBasicDescType(ITicNodeState state) => state switch {
void AssertGetMergedStateIsNull(ITicNodeState stateA, ITicNodeState stateB) { Assert.IsNull(SolvingFunctions.GetMergedStateOrNull(stateA, stateB)); Assert.IsNull(SolvingFunctions.GetMergedStateOrNull(stateB, stateA)); }
public override FunnyType Convert(ITicNodeState type) { switch (type) { case StateRefTo refTo: return(Convert(refTo.Element)); case StatePrimitive primitive: return(ToConcrete(primitive.Name)); case ConstrainsState constrains when constrains.Prefered != null: return(ToConcrete(constrains.Prefered.Name)); case ConstrainsState constrains when !constrains.HasAncestor: { if (constrains.IsComparable) { return(FunnyType.Real); } return(FunnyType.Anything); } case ConstrainsState constrains: { if (constrains.Ancestor.Name.HasFlag(PrimitiveTypeName._isAbstract)) { switch (constrains.Ancestor.Name) { case PrimitiveTypeName.I96: { if (constrains.HasDescendant || constrains.Descedant.CanBeImplicitlyConvertedTo(StatePrimitive.I32)) { return(FunnyType.Int32); } return(FunnyType.Int64); } case PrimitiveTypeName.I48: { if (constrains.HasDescendant || constrains.Descedant.CanBeImplicitlyConvertedTo(StatePrimitive.I32)) { return(FunnyType.Int32); } return(FunnyType.UInt32); } case PrimitiveTypeName.U48: return(FunnyType.UInt32); case PrimitiveTypeName.U24: return(FunnyType.UInt16); case PrimitiveTypeName.U12: return(FunnyType.UInt8); default: throw new NotSupportedException(); } } return(ToConcrete(constrains.Ancestor.Name)); } case StateArray array: return(FunnyType.ArrayOf(Convert(array.Element))); case StateFun fun: return(FunnyType.Fun(Convert(fun.ReturnType), fun.ArgNodes.SelectToArray(a => Convert(a.State)))); case StateStruct str: return(FunnyType.StructOf(str.Fields.ToDictionary(f => f.Key, f => Convert(f.Value.State)))); default: throw new NotSupportedException(); } }