using System.Collections.Generic;
using System.Linq;
using Parsley;
using Rook.Compiling.Types;

namespace Rook.Compiling.Syntax
{
    public class Class : TypedSyntaxTree, Binding
    {
        public Position Position { get; private set; }
        public Name Name { get; private set; }
        public IEnumerable<Function> Methods { get; private set; }
        public DataType Type { get; private set; }

        public Class(Position position, Name name, IEnumerable<Function> methods)
            : this(position, name, methods, ConstructorFunctionType(name)) { }

        private Class(Position position, Name name, IEnumerable<Function> methods, DataType type)
        {
            Position = position;
            Name = name;
            Methods = methods;
            Type = type;
        }

        public TResult Visit<TResult>(Visitor<TResult> visitor)
        {
            return visitor.Visit(this);
        }

        public TypeChecked<Class> WithTypes(Environment environment)
        {
            var localEnvironment = new Environment(environment);

            foreach (var method in Methods)
                if (!environment.TryIncludeUniqueBinding(method))
                    return TypeChecked<Class>.DuplicateIdentifierError(method);

            var typeCheckedMethods = Methods.WithTypes(localEnvironment);

            var errors = typeCheckedMethods.Errors();
            if (errors.Any())
                return TypeChecked<Class>.Failure(errors);

            return TypeChecked<Class>.Success(new Class(Position, Name, typeCheckedMethods.Functions()));
        }

        private static NamedType ConstructorFunctionType(Name name)
        {
            return NamedType.Constructor(new NamedType(name.Identifier));
        }

        string Binding.Identifier
        {
            get { return Name.Identifier; }
        }
    }
}
using System.Collections.Generic;
using System.Linq;
using Parsley;
using Rook.Compiling.Types;

namespace Rook.Compiling.Syntax
{
    public class Class : TypedSyntaxTree, Binding
    {
        public Position Position { get; private set; }
        public Name Name { get; private set; }
        public IEnumerable<Function> Methods { get; private set; }
        public DataType Type { get; private set; }

        public Class(Position position, Name name, IEnumerable<Function> methods)
            : this(position, name, methods, ConstructorFunctionType(name)) { }

        private Class(Position position, Name name, IEnumerable<Function> methods, DataType type)
        {
            Position = position;
            Name = name;
            Methods = methods;
            Type = type;
        }

        public TResult Visit<TResult>(Visitor<TResult> visitor)
        {
            return visitor.Visit(this);
        }

        public TypeChecked<Class> WithTypes(Environment environment)
        {
            var localEnvironment = new Environment(environment);

            foreach (var method in Methods)
                if (!localEnvironment.TryIncludeUniqueBinding(method))
                    return TypeChecked<Class>.DuplicateIdentifierError(method);

            var typeCheckedMethods = Methods.WithTypes(localEnvironment);

            var errors = typeCheckedMethods.Errors();
            if (errors.Any())
                return TypeChecked<Class>.Failure(errors);

            return TypeChecked<Class>.Success(new Class(Position, Name, typeCheckedMethods.Functions()));
        }

        private static NamedType ConstructorFunctionType(Name name)
        {
            return NamedType.Constructor(new NamedType(name.Identifier));
        }

        string Binding.Identifier
        {
            get { return Name.Identifier; }
        }
    }
}
Fix bug in which class members polluted the surrounding namespace.
Fix bug in which class members polluted the surrounding namespace.
