public Type CreateGenericType(IStaticScope parent, IOrType <NameKey, ImplicitKey> key, IReadOnlyList <TypeAndConverter> placeholders, IConvertTo <Type, IOrType <WeakTypeDefinition, WeakGenericTypeDefinition, Tac.SyntaxModel.Elements.AtomicTypes.IPrimitiveType> > converter)
                {
                    var res = new Type(
                        this,
                        $"generic-{key}-{placeholders.Aggregate("", (x, y) => x + "-" + y)}",
                        Possibly.Is(key),
                        converter,
                        Possibly.IsNot <Guid>(),
                        Possibly.IsNot <IInterfaceType>());

                    IsChildOf(parent, res);
                    HasType(parent, key.SwitchReturns <IKey>(x => x, x => x), res);
                    var i = 0;

                    foreach (var placeholder in placeholders)
                    {
                        var placeholderType = new TypeProblem2.GenericTypeParameter(this, $"generic-parameter-{placeholder.key}", i++, Prototypist.Toolbox.OrType.Make <MethodType, Type, Method, InferredType>(res));
                        //var placeholderType = new Type(
                        //    this,
                        //    $"generic-parameter-{placeholder.key}",
                        //    Possibly.Is(placeholder.key),
                        //    placeholder.converter,
                        //    Possibly.IsNot<Guid>(),
                        //    Possibly.IsNot<IInterfaceType>());
                        HasGenericType(Prototypist.Toolbox.OrType.Make <MethodType, Type, Method>(res), placeholder.key, placeholderType);
                    }
                    return(res);
                }
                public Scope CreateScope(IStaticScope parent, IConvertTo <Scope, IOrType <WeakBlockDefinition, WeakScope, WeakEntryPointDefinition> > converter)
                {
                    var res = new Scope(this, $"child-of-{((TypeProblemNode)parent).DebugName}", converter);

                    IsChildOf(parent, res);
                    return(res);
                }
                // why do objects have keys?
                // that is wierd
                public Object CreateObjectOrModule(IStaticScope parent, IKey key, IConvertTo <Object, IOrType <WeakObjectDefinition, WeakRootScope> > converter, IConvertTo <Scope, IOrType <WeakBlockDefinition, WeakScope, WeakEntryPointDefinition> > innerConverter)
                {
                    var res = new Object(this, key.ToString() !, converter, innerConverter);

                    IsChildOf(parent, res);
                    HasObject(parent, key, res);
                    return(res);
                }
                public Type CreateType(IStaticScope parent, IOrType <NameKey, ImplicitKey> key, IConvertTo <Type, IOrType <WeakTypeDefinition, WeakGenericTypeDefinition, Tac.SyntaxModel.Elements.AtomicTypes.IPrimitiveType> > converter, IIsPossibly <Guid> primitive)
                {
                    var res = new Type(this, key.ToString() !, Possibly.Is(key), converter, primitive, Possibly.IsNot <IInterfaceType>());

                    IsChildOf(parent, res);
                    HasType(parent, key.SwitchReturns <IKey>(x => x, x => x), res);
                    return(res);
                }
                public TypeReference CreateTypeReference(IStaticScope context, IKey typeKey, IConvertTo <TypeReference, IFrontendType <IVerifiableType> > converter)
                {
                    var res = new TypeReference(this, typeKey.ToString() !, converter);

                    HasReference(context, res);
                    res.Context = Possibly.Is(context);
                    res.TypeKey = Prototypist.Toolbox.OrType.Make <IKey, IError, Unset>(typeKey);
                    return(res);
                }
                public Type CreateTypeExternalType(IStaticScope parent, IConvertTo <Type, IOrType <WeakTypeDefinition, WeakGenericTypeDefinition, Tac.SyntaxModel.Elements.AtomicTypes.IPrimitiveType> > converter, IInterfaceType interfaceType)
                {
                    var key = new ImplicitKey(Guid.NewGuid());
                    var res = new Type(this, key.ToString() !, Possibly.IsNot <IOrType <NameKey, ImplicitKey> >(), converter, Possibly.IsNot <Guid>(), Possibly.Is(interfaceType));

                    IsChildOf(parent, res);
                    // migiht need this, let's try without first
                    //HasType(parent, key, res);
                    return(res);
                }
                public Member CreatePrivateMember(
                    IStaticScope scope,
                    IHavePrivateMembers havePrivateMembers,
                    IKey key)
                {
                    var res = new Member(this, key.ToString() !);

                    HasPrivateMember(havePrivateMembers, key, res);
                    res.Context = Possibly.Is(scope);
                    return(res);
                }
                public Member CreatePrivateMember(
                    IStaticScope scope,
                    IHavePrivateMembers havePrivateMembers,
                    IKey key,
                    IOrType <IKey, IError> typeKey)
                {
                    var res = new Member(this, key.ToString() !);

                    HasPrivateMember(havePrivateMembers, key, res);
                    res.Context = Possibly.Is(scope);
                    res.TypeKey = typeKey.SwitchReturns(x => Prototypist.Toolbox.OrType.Make <IKey, IError, Unset>(x), x => Prototypist.Toolbox.OrType.Make <IKey, IError, Unset>(x));
                    return(res);
                }
                public (Method, IOrType <TypeReference, IError>, IOrType <TypeReference, IError>) CreateMethod(
                    IStaticScope parent,
                    Func <IStaticScope, IOrType <TypeReference, IError> > inputTypeBuilder, // these type references look up from inside the method they could look up to a generic type defined in the method
                    Func <IStaticScope, IOrType <TypeReference, IError> > outputTypeBuilder,
                    string inputName,
                    IConvertTo <Method, IOrType <WeakMethodDefinition, WeakImplementationDefinition, WeakEntryPointDefinition, WeakGenericMethodDefinition> > converter)
                {
                    //if (!inputType.Is1(out var inputTypeValue))
                    //{
                    //    throw new NotImplementedException();
                    //}
                    //if (!outputType.Is1(out var outputTypeValue))
                    //{
                    //    throw new NotImplementedException();
                    //}

                    var res       = new Method(this, $"method{{inputName:{inputName}}}", converter);
                    var inputType = inputTypeBuilder(res);

                    if (!inputType.Is1(out var inputTypeValue))
                    {
                        throw new NotImplementedException();
                    }
                    var outputType = outputTypeBuilder(res);

                    if (!outputType.Is1(out var outputTypeValue))
                    {
                        throw new NotImplementedException();
                    }
                    IsChildOf(parent, res);
                    HasMethod(parent, new ImplicitKey(Guid.NewGuid()), res);
                    {
                        var returns = outputTypeValue.TypeKey is IIsDefinately <IKey> typeKey?CreateTransientMember(res, typeKey.Value, $"return of {res.DebugName}") : CreateTransientMember(res, $"return of {res.DebugName}");

                        res.Returns = Possibly.Is(returns);
                    }
                    {
                        if (inputTypeValue.TypeKey is IIsDefinately <IKey> typeKey)
                        {
                            // here it is ok for these to be members because we are using a method
                            res.Input = Possibly.Is(CreatePrivateMember(res, res, new NameKey(inputName), Prototypist.Toolbox.OrType.Make <IKey, IError>(typeKey.Value)));
                        }
                        else
                        {
                            // here it is ok for these to be members because we are using a method
                            res.Input = Possibly.Is(CreatePrivateMember(res, res, new NameKey(inputName)));
                        }
                    }
                    return(res, inputType, outputType);
                }
 public TransientMember GetReturns(IStaticScope s)
 {
     if (s is Method method)
     {
         return(GetReturns(method));
     }
     else if (s.Parent is IIsDefinately <IStaticScope> definatelyScope)
     {
         return(GetReturns(definatelyScope.Value));
     }
     else
     {
         throw new Exception("s.Parent should not be null");
     }
 }
                public Method CreateMethod(IStaticScope parent, string inputName, IConvertTo <Method, IOrType <WeakMethodDefinition, WeakImplementationDefinition, WeakEntryPointDefinition, WeakGenericMethodDefinition> > converter)
                {
                    var res = new Method(this, $"method{{inputName:{inputName}}}", converter);

                    IsChildOf(parent, res);
                    HasMethod(parent, new ImplicitKey(Guid.NewGuid()), res);
                    // here it is ok for these to be members because we are using a method
                    var returns = CreateTransientMember(res, $"return of {res.DebugName}");

                    res.Returns = Possibly.Is(returns);
                    var input = CreatePrivateMember(res, res, new NameKey(inputName));

                    res.Input = Possibly.Is(input);
                    return(res);
                }
                public OrType CreateOrType(IStaticScope s, IKey key, IOrType <TypeReference, IError> setUpSideNode1, IOrType <TypeReference, IError> setUpSideNode2, IConvertTo <OrType, IFrontendType <IVerifiableType> > converter)
                {
                    if (!setUpSideNode1.Is1(out var node1))
                    {
                        throw new NotImplementedException();
                    }
                    if (!setUpSideNode2.Is1(out var node2))
                    {
                        throw new NotImplementedException();
                    }

                    var res = new OrType(this, $"{node1.DebugName} || {node2.DebugName}", converter);

                    Ors(res, node1, node2);
                    HasOrType(s, key, res);

                    return(res);
                }
                public Member CreateMemberPossiblyOnParent(IStaticScope scope, IHavePossibleMembers havePossibleMembers, IKey key)
                {
                    // this is weird, but since C# does not have and types...
                    // scope and havePossibleMembers are expected to be the same object
                    if (!ReferenceEquals(scope, havePossibleMembers))
                    {
                        throw new Exception($"{scope} and {havePossibleMembers} should be the same object");
                    }

                    if (havePossibleMembers.PossibleMembers.TryGetValue(key, out var res1))
                    {
                        return(res1);
                    }

                    var res = HasMembersPossiblyOnParent(havePossibleMembers, key, () => new Member(this, "possibly on parent -" + key.ToString()));

                    res.Context = Possibly.Is(scope);
                    return(res);
                }
                public Member CreateMember(
                    IStaticScope scope,
                    IKey key,
                    IOrType <IKey, IError> typeKey)
                {
                    var res = new Member(this, key.ToString() !);

                    if (scope is IHavePublicMembers publicMembers)
                    {
                        HasPublicMember(publicMembers, key, res);
                    }
                    else
                    if (scope is IHavePrivateMembers privateMembers)
                    {
                        HasPrivateMember(privateMembers, key, res);
                    }
                    else
                    {
                        throw new Exception("this is probably really an IError - you tried to add a member somewhere one cannot go");
                    }
                    res.Context = Possibly.Is(scope);
                    res.TypeKey = typeKey.SwitchReturns(x => Prototypist.Toolbox.OrType.Make <IKey, IError, Unset>(x), x => Prototypist.Toolbox.OrType.Make <IKey, IError, Unset>(x));
                    return(res);
                }
 public void HasMethodType(IStaticScope parent, IKey key, MethodType type)
 {
     parent.MethodTypes.Add(key, type);
 }
 // why do objects have keys?
 // that is wierd
 public static void HasObject(IStaticScope parent, IKey key, Object @object)
 {
     parent.Objects.Add(key, @object);
 }
 public static void HasOrType(IStaticScope scope, IKey kay, OrType orType1)
 {
     scope.OrTypes[kay] = orType1;
 }
 public void IsChildOf(IStaticScope parent, IStaticScope kid)
 {
     kid.Parent = Possibly.Is(parent);
 }
                //public void HasEntryPoint(IStaticScope parent, Scope entry)
                //{
                //    parent.EntryPoints.Add(entry);
                //}

                public static void HasType(IStaticScope parent, IKey key, Type type)
                {
                    parent.Types.Add(key, type);
                }
 public Type CreateType(IStaticScope parent, IOrType <NameKey, ImplicitKey> key, IConvertTo <Type, IOrType <WeakTypeDefinition, WeakGenericTypeDefinition, Tac.SyntaxModel.Elements.AtomicTypes.IPrimitiveType> > converter)
 {
     return(CreateType(parent, key, converter, Possibly.IsNot <Guid>()));
 }
                public (Method, IOrType <TypeReference, IError>, IOrType <TypeReference, IError>) CreateGenericMethod(IStaticScope parent, Func <IStaticScope, IOrType <TypeReference, IError> > inputTypeBuilder, Func <IStaticScope, IOrType <TypeReference, IError> > outputTypeBuilder, string inputName, IConvertTo <Method, IOrType <WeakMethodDefinition, WeakImplementationDefinition, WeakEntryPointDefinition, WeakGenericMethodDefinition> > converter, IReadOnlyList <TypeAndConverter> placeholders)
                {
                    var(method, inputType, outputType) = CreateMethod(parent, inputTypeBuilder, outputTypeBuilder, inputName, converter);
                    var i = 0;

                    foreach (var placeholder in placeholders)
                    {
                        var placeholderType = new GenericTypeParameter(this, $"generic-parameter-{placeholder.key}", i++, Prototypist.Toolbox.OrType.Make <MethodType, Type, Method, InferredType>(method));

                        HasGenericType(Prototypist.Toolbox.OrType.Make <MethodType, Type, Method>(method), placeholder.key, placeholderType);
                    }

                    // why doesn't this have genericOverlays ({4BFD0274-B70F-4BD8-B290-63B69FF74FE7})
                    // the overlays are t1 and t2 of the base method "method [t1,t2]"
                    // they are never references anywhere so we don't care to overlay them
                    // we build the right MethodType
                    // at {2E20DFFB-7BD2-4351-9CAF-10A63491ABCF}
                    // this isn't great
                    // it would be a little work to build the genericOverlays
                    // genericOverlays take a looked up type not a key

                    return(method, inputType, outputType);
                }
 public static void HasMethod(IStaticScope parent, IKey key, Method method)
 {
     parent.Methods.Add(key, method);
 }
 public static void HasReference(IStaticScope parent, TypeReference reference)
 {
     parent.Refs.Add(reference);
 }