<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Magpie.Compilation
{
    /// <summary>
    /// A symbol table for types.
    /// </summary>
    public class TypeTable
    {
        public IEnumerable<Struct> Structs { get { return mTypes.Values.OfType<Struct>(); } }
        public IEnumerable<Union> Unions { get { return mTypes.Values.OfType<Union>(); } }

        public IEnumerable<GenericStruct> GenericStructs { get { return mGenericStructs; } }
        public IEnumerable<GenericUnion> GenericUnions { get { return mGenericUnions; } }

        public TypeTable()
        {
            // add the built-in types
            Add(Decl.Unit);
            Add(Decl.Bool);
            Add(Decl.Int);
            Add(Decl.String);
        }

        public void Add(INamedType type)
        {
            Add(type, null);
        }

        public void Add(INamedType type, IEnumerable<IBoundDecl> typeArgs)
        {
            var uniqueName = GetUniqueName(type.Name, typeArgs);

            if (mTypes.ContainsKey(uniqueName)) throw new CompileException(type.Position, "There is already a type named " + uniqueName + ".");

            mTypes[uniqueName] = type;
        }

        public void Add(GenericStruct generic)
        {
            mGenericStructs.Add(generic);
        }

        public void Add(GenericUnion generic)
        {
            mGenericUnions.Add(generic);
        }

        //### bob: need to copy this for union
        public Struct FindStruct(string name, IEnumerable<IBoundDecl> typeArgs)
        {
            var uniqueName = GetUniqueName(name, typeArgs);

            INamedType type;
            if (mTypes.TryGetValue(uniqueName, out type))
            {
                // may be a union, so cast using "as"
                return type as Struct;
            }

            return null;
        }

        public INamedType Find(Compiler compiler, NameSearchSpace searchSpace, Position position, string name,
            IEnumerable<IBoundDecl> typeArgs)
        {
            // look through the namespaces
            foreach (var potentialName in searchSpace.SearchFor(name))
            {
                // look for a concrete type
                var type = Find(potentialName, typeArgs);
                if (type != null) return type;

                //### bob: need to copy this for union
                // look for a generic
                foreach (var structure in mGenericStructs)
                {
                    // names must match
                    if (structure.Name != potentialName) continue;

                    // number of type args must match
                    if (typeArgs.Count() != structure.TypeParameters.Count) continue;

                    var instance = structure.Instantiate(compiler, typeArgs);

                    // only instantiate once
                    Add(instance);

                    return instance;
                }
            }

            // not found<commit_msg>Fixed recursive generics.<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Magpie.Compilation
{
    /// <summary>
    /// A symbol table for types.
    /// </summary>
    public class TypeTable
    {
        public IEnumerable<Struct> Structs { get { return mTypes.Values.OfType<Struct>(); } }
        public IEnumerable<Union> Unions { get { return mTypes.Values.OfType<Union>(); } }

        public IEnumerable<GenericStruct> GenericStructs { get { return mGenericStructs; } }
        public IEnumerable<GenericUnion> GenericUnions { get { return mGenericUnions; } }

        public TypeTable()
        {
            // add the built-in types
            Add(Decl.Unit);
            Add(Decl.Bool);
            Add(Decl.Int);
            Add(Decl.String);
        }

        public void Add(INamedType type)
        {
            Add(type, null);
        }

        public void Add(INamedType type, IEnumerable<IBoundDecl> typeArgs)
        {
            var uniqueName = GetUniqueName(type.Name, typeArgs);

            if (mTypes.ContainsKey(uniqueName)) throw new CompileException(type.Position, "There is already a type named " + uniqueName + ".");

            mTypes[uniqueName] = type;
        }

        public void Add(GenericStruct generic)
        {
            mGenericStructs.Add(generic);
        }

        public void Add(GenericUnion generic)
        {
            mGenericUnions.Add(generic);
        }

        public Struct FindStruct(string name, IEnumerable<IBoundDecl> typeArgs)
        {
            var uniqueName = GetUniqueName(name, typeArgs);

            INamedType type;
            if (mTypes.TryGetValue(uniqueName, out type))
            {
                // may be a union, so cast using "as"
                return type as Struct;
            }

            return null;
        }

        //### bob: copy/paste from struct :(
        public Union FindUnion(string name, IEnumerable<IBoundDecl> typeArgs)
        {
            var uniqueName = GetUniqueName(name, typeArgs);

            INamedType type;
            if (mTypes.TryGetValue(uniqueName, out type))
            {
                // may be a struct, so cast using "as"
                return type as Union;
            }

            return null;
        }

        public INamedType Find(Compiler compiler, NameSearchSpace searchSpace, Position position, string name,
            IEnumerable<IBoundDecl> typeArgs)
        {
            // look through the namespaces
            foreach (var potentialName in searchSpace.SearchFor(name))
            {
                // look for a concrete type
                var type = Find(potentialName, typeArgs);
                if (type != null) return type;

                // look for a generic
                foreach (var structure in mGenericStructs)
                {
                    // names must match
                    if (structure.Name != potentialName) continue;

                    // number of type args must match
                    if (typeArgs.Count() != structure.TypeParameters.Count) continue;

                    var instance = structure.Instantiate(compiler, typeArgs);

                    // only instantiate once
                    //Add(instance, typeArgs);

                    return instance;
                }

                //### bob: gross copy/paste of above
                // look for a generic
                foreach (var union in mGenericUnions)
                {
                    // names must match
                    if (union.Name != potentialName) continue;

                    // number of type args must match
                    if (typeArgs.Count() != union.TypeParameters.Count) continue;

                    var instance = union.Instantiate(compiler, typeArgs);

                    // only instantiate once
                    //Add(instance, typeArgs);

                    return instance;
                }
            }

            // not found
{'fraction_non_alphanumeric': 0.08485621192803514, 'fraction_numerical': 0.0, 'mean_word_length': 1.520528382720457, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2359775', 'n_tokens_mistral': 1770, 'n_tokens_neox': 1668, 'n_words': 486}