<commit_before>#include "alfe/string.h"
#include "alfe/array.h"
#include "alfe/file.h"
#include "alfe/stack.h"
#include "alfe/hash_table.h"
#include "alfe/main.h"
#include "alfe/space.h"
#include "alfe/config_file.h"
#include "alfe/type.h"
#include "alfe/rational.h"
#include "alfe/pipes.h"
#include "alfe/sdl2.h"
#include "alfe/reference.h"

#include <stdlib.h>
#include <limits.h>

typedef UInt8 BGRI;

//class SourceProgram
//{
//};

template<class T> class SimulatorT;
typedef SimulatorT<void> Simulator;

template<class T> class Intel8088CPUT;
typedef Intel8088CPUT<void> Intel8088CPU;

template<class T> class ComponentT;
typedef ComponentT<void> Component;

template<class T> class Intel8237DMACT;
typedef Intel8237DMACT<void> Intel8237DMAC;

template<class T> class Intel8259PICT;
typedef Intel8259PICT<void> Intel8259PIC;

template<class T> class DMAPageRegistersT;
typedef DMAPageRegistersT<void> DMAPageRegisters;

template<class T> class PCXTKeyboardT;
typedef PCXTKeyboardT<void> PCXTKeyboard;

template<class T> class PCXTKeyboardPortT;
typedef PCXTKeyboardPortT<void> PCXTKeyboardPort;

template<class T> class ConnectorT;
typedef ConnectorT<void> Connector;

Concrete second;

class Tick
{
    typedef int Base;
public:
    Tick() : _t(0) { }
    Tick(const Base& t) : _t(t) { }
    static Tick infinity() { return std::numeric_limits<Base>::max(); }
    bool operator<=(const Tick& other) const { return _t <= other._t; }
    bool operator<(const Tick& other) const { return _t < other._t; }
    bool operator>=(const Tick& other) const { return _t >= other._t; }
    bool operator>(const Tick& other) const { return _t > other._t; }
    const Tick& operator+=(const Tick& other) { _t += other._t; return *this; }
    const Tick& operator-=(const Tick& other) { _t -= other._t; return *this; }
    Tick operator+(const Tick& other) { return Tick(_t + other._t); }
    Tick operator-(const Tick& other) { return Tick(_t - other._t); }
    operator String() const { return decimal(_t); }
    Tick operator-() const { return Tick(-_t); }
    Tick operator*(int other) { return Tick(_t*other); }
    typedef IntegerType Type;
private:
    Base _t;
};
template<> Type typeFromCompileTimeType<Tick>() { return Tick::Type(); }

class HexPersistenceType : public IntegerType
{
public:
    HexPersistenceType(int digits) : IntegerType(create<Body>(digits)) { }
private:
    class Body : public IntegerType::Body
    {
    public:
        Body(int digits) : _digits(digits) { }
        String serialize(void* p, int width, int used, int indent, int delta)
            const
        {
            return hex(*static_cast<int*>(p), _digits);
        }
    private:
        int _digits;
    };
};

class Protocol : public ConstHandle
{
public:
    Protocol() { }
    Protocol(const ConstHandle& r) : ConstHandle(r) { }
};
template<class T> class ProtocolBase : public Nullary<Protocol, T> { };

// The meaning of _output is up to the particular Protocol. In some cases (e.g.
// ISA card edge/slot) neither is really an output so we just have to pick a
// direction arbitrarily. Non-gendered connectors should specify two
// ProtocolDirections, one for each direction.
class ProtocolDirection
{
public:
    ProtocolDirection() : _output(false) { }
    ProtocolDirection(Protocol p, bool o) : _protocol(p), _output(o) { }
    bool matches(ProtocolDirection other) const
    {
        return _protocol == other._protocol && _output != other._output;
    }
    bool operator==(ProtocolDirection r) const
    {
        return _protocol == r._protocol && _output == r._output;
    }
    UInt32 hash() const
    {
        return Hash(typeid(ProtocolDirection)).mixin(_protocol.hash()).
            mixin(_output ? 1 : 0);
    }
    auto operator-() const { return ProtocolDirection(_protocol, !_output); }
private:
    Protocol _protocol;
    bool _output;
};

Value connectorFromValue(Value v);
Type connectorTypeFromType(Type t);

template<class T> class ConnectorT
{
public:
    ConnectorT(Component* component)
      : _component(component), _connected(false) { }
    class Type : public ::Type
    {
    public:
        Type() { }
        Type(::Type type) : ::Type(to<Body>(type)) { }
        bool compatible(Type other) const
        {
            return body()->compatible(other) ||
                other.body()->compatible(*this);
        }
        bool canConnectMultiple() const
        {
            return body()->canConnectMultiple();
        }
        List<ProtocolDirection> protocolDirections() const
        {
            return body()->protocolDirections();
        }
        static String name() { return "Connector"; }
        class Body : public ::Type::Body
        {
        public:
            Body(Simulator* simulator) : _simulator(simulator) { }
            virtual List<ProtocolDirection> protocolDirections() const = 0;
            virtual bool canConnectMultiple() const { return false; }
            virtual bool canConvertFrom(const ::Type& other, String* reason)
                const
            {
                ConnectorT<T>::Type t = connectorTypeFromType(other);
                if (!t.valid()) {
                    *reason = other.toString() + " is not a connector.";
                    return false;
                }
                if (!_simulator->canConnect(Type(type()), t)) {
                    *reason = t.toString() + " and " + this->toString() +
                        " are not compatible connectors.";
                    return false;
                }
                return true;
            }
            virtual ValueT<T> convert(const ValueT<T>& value) const
            {
                return Value(type(), connectorFromValue(value).value(),
                    value.span());
            }
        private:
            Simulator* _simulator;
        };
    public:
        const Body* body() const { return this->template as<Body>(); }
    };
    Value getValue() const
    {
        // The const_cast here is a result of the syntax
        // "componentA.connector1 = componentB.connector2;" in the config file.
        // In pure ALFE syntax, obtaining the "value" of connector2 does not
        // modify componentB, so getValue() is const. However, in Berapa,
        // componentB's state may be modified by this connection.
        return Value(type(), const_cast<Connector*>(this));
    }
    void doConnect(ConnectorT<T>* other, ProtocolDirection pd, Span span)
    {
        if (_connected && !type().canConnectMultiple())
            span.throwError("Connector is already connected");
        connect(other, pd);
        _connected = true;
    }
    void checkConnected()
    {
        if (!_connected && !type().canConnectMultiple())
            _component->simulator()->connectStub(this);
    }
    Component* component() const { return _component; }
    void setName(String name) { _name = name; }
    String name() const { return _component->name() + "." + _name; }

    virtual Type type() const = 0;
    virtual void connect(Connector* other, ProtocolDirection pd)
    {
        connect(other);
    }
    virtual void connect(Connector* other) { }

private:
    bool _connected;
    ComponentT<T>* _component;
    String _name;
};

template<class T, class B = Connector> class ConnectorBase : public B
{
public:
    ConnectorBase(Component* c) : B(c) { }
    static auto protocolDirections()
    {
        List<ProtocolDirection> r;
        r.add(T::protocolDirection());
        return r;
    }
    static auto canConnectMultiple() { return false; }
    Connector::Type type() const { return T::Type(component()->simulator()); }
    class Type : public B::Type
    {
    public:
        Type(Simulator* simulator)
          : B::Type(Type::template create<Body>(simulator)) { }
        Type(const ConstHandle& r) : B::Type(r) { }

        class Body : public B::Type::Body
        {
        public:
            Body(Simulator* simulator) : B::Type::Body(simulator) { }
            List<ProtocolDirection> protocolDirections() const
            {
                return T::protocolDirections();
            }
            bool canConnectMultiple() const { return T::canConnectMultiple(); }
            String toString() const { return T::typeName(); }
        };
    };
};

template<class T> class ComponentT : public Structure
{
public:
    class Type : public ::Type
    {
    public:
        Type() { }
        Type(::Type type) : ::Type(to<Body>(type)) { }
        Reference<Component> createComponent()
        {
            auto c = body()->createComponent();
            body()->simulator()->addComponent(c);
            return c;
        }
        Simulator* simulator() const { return body()->simulator(); }
        typename ConnectorT<T>::Type defaultConnectorType() const
        {
            return body()->defaultConnectorType();
        }
    protected:
        class Body : public ::Type::Body
        {
        public:
            Body(Simulator* simulator) : _simulator(simulator) { }
            ::Type member(Identifier i) const
            {
                if (i.name() == "*")
                    return StringType();
                return ::Type();
            }
            virtual Reference<Component> createComponent() const = 0;
            bool canConvertFrom(const ::Type& other, String* why) const
            {
                return other.canConvertTo(StructuredType::empty().type(), why);
            }
            Value convert(const Value& value) const
            {
                auto v = Type(type()).createComponent();
                return Value(type(), static_cast<Structure*>(&(*v)),
                    value.span());
            }
            Simulator* simulator() const { return _simulator; }
            typename ConnectorT<T>::Type defaultConnectorType() const
            {
                return _defaultConnectorType;
            }
        protected:
            Simulator* _simulator;
            typename ConnectorT<T>::Type _defaultConnectorType;
        };
        const Body* body() const { return as<Body>(); }
    };
    ComponentT(Type type)
      : _type(type), _simulator(type.simulator()), _ticksPerCycle(0),
        _defaultConnector(0), _loopCheck(false)
    {
        persist("tick", &_tick);
    }
    virtual void runTo(Tick tick) { _tick = tick; }
    virtual void maintain(Tick ticks) { _tick -= ticks; }
    String name() const { return _name; }
    virtual Rational cyclesPerSecond() const { return 0; }
    void setTicksPerCycle(Tick ticksPerCycle)
    {
        _ticksPerCycle = ticksPerCycle;
        _tick = 0;
    }
    void set(Identifier name, Value value, Span span)
    {
        String n = name.name();
        if (n == "*") {
            _name = value.value<String>();
            return;
        }
        if (typename ConnectorT<T>::Type(value.type()).valid()) {
            auto l = getValue(name).template value<Connector*>();
            auto r = value.value<Connector*>();
            _simulator->connect(l, r, span);
            return;
        }
        if (_config.hasKey(n)) {
            Member m = _config[n];
            m.type().deserialize(value, m._p);
        }
        Structure::set(name, value, span);
    }
    template<class C> class TypeHelper : public Type
    {
    public:
        TypeHelper(Simulator* simulator)
            : Type(TypeHelper::template create<Body>(simulator)) { }
        TypeHelper(const ConstHandle& other) : Type(other) { }
    protected:
        class Body : public Type::Body
        {
        public:
            Body(Simulator* simulator) : Type::Body(simulator)
            {
                C component(type());
                for (auto i : component._config)
                    _members[i.key()] = i.value().type();
                if (component._defaultConnector != 0) {
                    this->_defaultConnectorType =
                        component._defaultConnector->type();
                }
            }
            Reference<Component> createComponent() const
            {
                return Reference<Component>::create<C>(Type(type()));
            }
            String toString() const { return C::typeName(); }
            ::Type member(Identifier i) const
            {
                if (_members.hasKey(i))
                    return _members[i];
                return Type::Body::member(i);
            }
            int size() const { return sizeof(C); }
            Value value(void* p) const { return static_cast<C*>(p)->value(); }
        private:
            HashTable<Identifier, ::Type> _members;
        };
    };
    virtual String save(int width, int used, int indent, int delta) const
    {
        // First try putting everything on one line
        String s("{ ");
        bool needComma = false;
        bool separate = false;
        used += 5;
        for (auto i : _persist) {
            if (used > width) {
                separate = true;
                break;
            }
            Member m = i.value();
            int u = used + i.key().length() + 2 + (needComma ? 2 : 0);
            String v = "{ }";
            ::Type t = m.type();
            if (t.value(m._p) != Value(t)) {
                v = t.serialize(m._p, width, u, 0, 0);
                if (v == "*") {
                    separate = true;
                    s = "";
                    break;
                }
            }
            if (v != "{ }") {
                if (needComma)
                    s += ", ";
                needComma = true;
                s += i.key() + ": " + v;
                used = u + v.length();
            }
        }
        if (s == "{ ")
            return "{ }";
        if (!separate && used <= width)
            return s + " }";
        else
            s = "";
        if (s == "" && indent == 0)
            return "*";
        // It doesn't all fit on one line, put each member on a separate line.
        s = "{\n";
        needComma = false;
        for (auto i : _persist) {
            Member m = i.value();
            int u = indent + i.key().length();
            String v = "{ }";
            ::Type t = m.type();
            if (t.value(m._p) != Value(t))
                v = t.serialize(m._p, width, u, indent + delta, delta);
            if (v != "{ }") {
                if (needComma)
                    s += ",\n";
                needComma = true;
                s += String(" ")*indent + i.key() + ": " + v;
            }
        }
        return s + " }";
    }
    virtual ::Type persistenceType() const
    {
        List<StructuredType::Member> members;
        for (auto i : _persist)
            members.add(StructuredType::Member(i.key(), i.value()._initial));
        return PersistenceType(_type.toString(), members, _type.size());
    }
    virtual void load(const Value& value)
    {
        auto members = value.value<HashTable<Identifier, Value>>();
        for (auto i : _persist) {
            Member m = i.value();
            m.type().deserialize(members[i.key()], m._p);
        }
    }
    Value value() const
    {
        HashTable<Identifier, Value> h;
        for (auto i : _persist) {
            Member m = i.value();
            h.add(i.key(), m.type().value(m._p));
        }
        return Value(persistenceType(), h);
    }
    Type type() const { return _type; }
    Connector* defaultConnector() const { return _defaultConnector; }
    void checkConnections(int* n)
    {
        for (auto i : _config) {
            Member m = i.value();
            if (typename ConnectorT<T>::Type(m.type()).valid())
                static_cast<ConnectorT<T>*>(m._p)->checkConnected();
        }
        if (_name == "") {
            _name = decimal(*n);
            ++*n;
        }
    }
    SimulatorT<T>* simulator() const { return _simulator; }
    bool loopCheck()
    {
        if (_loopCheck)
            return true;
        _loopCheck = true;
        if (subLoopCheck())
            return true;
        _loopCheck = false;
        return false;
    }
    bool isInLoop() const { return _loopCheck; }
    virtual bool subLoopCheck() { return false; }

    Tick _tick;

protected:
    void connector(String name, ConnectorT<T>* p)
    {
        if (name == "") {
            _defaultConnector = p;
            Identifier i = Identifier(OperatorAssignment());
            OverloadedFunctionSet o(i);
            o.add(AssignmentFunco(this));
            Value v(o);
            _config.add(i, Member(0, v));
            Structure::set(i, v, Span());
        }
        else {
            // Connectors don't have a default value. If they did, a connector
            // supporting multiple connections would always be connected to the
            // default. We can't convert directly from the type to the value,
            // or the conversion would call convert() which would attempt to
            // connect.
            _config.add(name,
                Member(static_cast<void*>(p), Value(p->type(), 0)));
            Structure::set(name, p->getValue(), Span());
        }
        p->setName(name);
    }
    template<class C> void config(String name, C* p,
        ::Type type = typeFromCompileTimeType<C>())
    {
        _config.add(name, Member(static_cast<void*>(p), type));
        Structure::set(name, type, Span());
        set(name, type, Span());
    }
    template<class C, class I, std::enable_if_t<!std::is_base_of<::Type, I>
        ::value>* = nullptr>
        void persist(String name, C* p, I initial,
            ::Type type = typeFromCompileTimeType<C>())
    {
        Value v(type, initial);
        ArrayType arrayType(type);
        if (arrayType.valid()) {
            Value m(arrayType.contained(), initial);
            List<Value> initialArray;
            LessThanType l(arrayType.indexer());
            if (!l.valid()) {
                throw Exception(
                    "Don't know how many elements to put in default.");
            }
            int n = l.n();
            for (int i = 0; i < n; ++i)
                initialArray.add(m);
            v = Value(type, initialArray);
        }
        _persist.add(name, Member(static_cast<void*>(p), v));

    }
    template<class C> void persist(String name, C* p,
        Value initial = Value(typeFromCompileTimeType<C>()))
    {
        _persist.add(name, Member(static_cast<void*>(p), initial));
    }
    Tick _ticksPerCycle;
private:
    class PersistenceType : public StructuredType
    {
    public:
        PersistenceType(String name, List<StructuredType::Member> members,
            int size)
          : StructuredType(create<Body>(name, members, size)) { }
    private:
        class Body : public StructuredType::Body
        {
        public:
            Body(String name, List<Member> members, int size)
              : StructuredType::Body(name, members), _size(size) { }
            Value value(void* p) const
            {
                return static_cast<Component*>(p)->value();
            }
            int size() const { return _size; }
            String serialize(void* p, int width, int used, int indent,
                int delta) const
            {
                return static_cast<Component*>(p)->
                    save(width, used, indent, delta);
            }
            void deserialize(const Value& value, void* p) const
            {
                static_cast<Component*>(p)->load(value);
            }

        private:
            int _size;
        };
    };
    class AssignmentFunco : public Funco
    {
    public:
        AssignmentFunco(Component* component)
          : Funco(create<Body>(component)) { }
        ::Type type() const { return Funco::type(); }
        class Body : public Funco::Body
        {
        public:
            Body(Component* component) : _component(component) { }
            Value evaluate(List<Value> arguments, Span span) const
            {
                auto i = arguments.begin();
                auto ls = i->rValue().value<Structure*>();
                auto l = dynamic_cast<ComponentT<T>*>(ls)->_defaultConnector;
                auto lt = l->getValue().type();
                ++i;
                String reason;
                if (Type(i->type()).valid()) {
                    auto rs = i->value<Structure*>();
                    auto r = dynamic_cast<ComponentT<T>*>(rs)->
                        _defaultConnector;
                    if (!lt.canConvertFrom(r->getValue().type(), &reason))
                        span.throwError(reason);
                    _component->simulator()->connect(l, r, span);
                    return Value();
                }
                auto r = dynamic_cast<ConnectorT<T>*>(i->value<Structure*>());
                if (!lt.canConvertFrom(r->getValue().type(), &reason))
                    span.throwError(reason);
                _component->simulator()->connect(l, r, span);
                return Value();
            }
            Identifier identifier() const { return OperatorAssignment(); }
            bool argumentsMatch(List<::Type> argumentTypes) const
            {
                if (argumentTypes.count() != 2)
                    return false;
                auto i = argumentTypes.begin();
                if (!Type(i->rValue()).valid())
                    return false;
                ++i;
                if (Type(*i).valid())
                    return true;
                return typename ConnectorT<T>::Type(*i).valid();
            }
            // Won't actually be used (since there's only one function matching
            // the argument types) but necessary to avoid AssignmentFunco being
            // an abstract class.
            List<Tyco> parameterTycos() const
            {
                List<Tyco> r;
                r.add(typename ConnectorT<T>::Type());
                r.add(LValueType(_component->type()));
                return r;
            }
        private:
            ComponentT<T>* _component;
        };
    };
    class Member
    {
    public:
        Member() { }
        Member(void* p, Value initial) : _p(p), _initial(initial) { }
        ::Type type() const { return _initial.type(); }
        void* _p;
        Value _initial;
    };
    HashTable<Identifier, Member> _config;
    HashTable<String, Member> _persist;

    String _name;
    Type _type;
    Connector* _defaultConnector;
    SimulatorT<T>* _simulator;
    bool _loopCheck;

    friend class ConnectorT<T>::Type::Body;
    friend class AssignmentFunco::Body;
};

template<class C> class ComponentBase : public Component
{
public:
    ComponentBase(Component::Type type) : Component(type) { }
    typedef Component::TypeHelper<C> Type;
};

// For sub-components (like RAM) the type doesn't create the component, it just
// returns the pointer to the member of the parent component.
template<class C> class SubComponent : public ComponentBase<C>
{
public:
    SubComponent(Component::Type type) : ComponentBase(type) { }
    class Type : public ComponentBase<C>::Type
    {
    public:
        Type(Simulator* simulator, C* c = 0)
          : Component::TypeHelper<C>(
                Component::TypeHelper<C>::template create<Body>(simulator, c))
        { }
    private:
        class Body : public ComponentBase<C>::Type::Body
        {
        public:
            Body(Simulator* simulator, C* c)
              : ComponentBase<C>::Type::Body(simulator), _c(c) { }
            Value convert(const Value& value) const
            {
                return Value(this->type(), static_cast<Structure*>(_c),
                    value.span());
            }
        private:
            C* _c;
        };
    };
};

Value connectorFromValue(Value v)
{
    Component::Type ct(v.type());
    if (ct.valid()) {
        Structure* s = v.value<Structure*>();
        auto component = static_cast<Component*>(s);
        Connector* connector = component->defaultConnector();
        return connector->getValue();
    }
    return v;
}

Type connectorTypeFromType(Type t)
{
    Component::Type ct(t);
    if (ct.valid())
        return ct.defaultConnectorType();
    return t;
}

class ClockedComponent : public Component
{
public:
    ClockedComponent(Type type) : Component(type)
    {
        config("frequency", &_cyclesPerSecond, (1/second).type());
    }
    Rational cyclesPerSecond() const { return _cyclesPerSecond; }
private:
    Rational _cyclesPerSecond;
};

template<class C> class ClockedComponentBase : public ClockedComponent
{
public:
    ClockedComponentBase(Component::Type t) : ClockedComponent(t) { }
    typedef Component::TypeHelper<C> Type;
};

template<class T> class SimpleProtocol
  : public ProtocolBase<SimpleProtocol<T>> { };
template<class T> class BidirectionalProtocol
  : public ProtocolBase<BidirectionalProtocol<T>> { };

template<class T> class OutputConnector;
template<class T> class InputConnector;
template<class T> class BidirectionalConnector;

class TransportConnector : public Connector
{
public:
    TransportConnector(Component* c) : Connector(c) { }
    class Type : public Connector::Type
    {
    public:
        Type(const ConstHandle& other) : Connector::Type(other) { }
        ::Type transportType() const { return body()->transportType(); }
    protected:
        class Body : public Connector::Type::Body
        {
        public:
            Body(Simulator* s) : Connector::Type::Body(s) { }
            virtual ::Type transportType() const = 0;
        };
        const Body* body() const { return as<Body>(); }
    };
};

template<class C, class T, class B = TransportConnector>
    class TransportConnectorBase : public ConnectorBase<C, B>
{
public:
    TransportConnectorBase(Component* c) : ConnectorBase(c) { }
    static String typeName()
    {
        return C::tycoName() + "<" + typeFromCompileTimeType<T>().toString() +
            ">";
    }
    class Type : public ConnectorBase<C, B>::Type
    {
    public:
        Type(Simulator* s) : ConnectorBase<C, B>::Type(create<Body>(s)) { }
        Type(const ConstHandle& r) : ConnectorBase<C, B>::Type(r) { }
        class Body : public ConnectorBase<C, B>::Type::Body
        {
        public:
            Body(Simulator* s) : ConnectorBase<C, B>::Type::Body(s) { }
            ::Type transportType() const
            {
                return typeFromCompileTimeType<T>();
            }
        };
    };
    BidirectionalConnector<T>* _other;
    Component* _otherComponent;
};


template<class T> class ConstantComponent;
template<class T> class BucketComponent;

template<class T> class BidirectionalConnector
  : public TransportConnectorBase<BidirectionalConnector<T>, T>
{
public:
    static String tycoName() { return "BidirectionalConnector"; }
    static auto protocolDirections()
    {
        List<ProtocolDirection> r;
        r.add(ProtocolDirection(SimpleProtocol<T>(), true));
        r.add(ProtocolDirection(SimpleProtocol<T>(), false));
        r.add(ProtocolDirection(BidirectionalProtocol<T>(), true));
        r.add(ProtocolDirection(BidirectionalProtocol<T>(), false));
        return r;
    }
    BidirectionalConnector(Component* c) : TransportConnectorBase(c) { }
    virtual void setData(Tick t, T v) = 0;
    void connect(::Connector* other)
    {
        _other = static_cast<BidirectionalConnector<T>*>(other);
        _otherComponent = _other->component();
    }
    BidirectionalConnector<T>* _other;
    Component* _otherComponent;
};

template<class T> class OutputConnector
  : public TransportConnectorBase<OutputConnector<T>, T,
        BidirectionalConnector<T>>
{
public:
    static String tycoName() { return "OutputConnector"; }
    static auto protocolDirection()
    {
        return ProtocolDirection(SimpleProtocol<T>(), true);
    }
    OutputConnector(Component* c) : TransportConnectorBase(c) { }
    void setData(Tick t, T v) { }
    bool loopCheck() { return this->_otherComponent->loopCheck(); }
};

template<class T> class OptimizedOutputConnector : public OutputConnector<T>
{
public:
    OptimizedOutputConnector(Component* c) : OutputConnector(c) { }
    void set(Tick t, T v)
    {
        if (v != _v) {
            _v = v;
            _other->setData(t, v);
        }
    }
    void init(T v) { _v = v; }
private:
    T _v;
};

template<class T> class InputConnector
  : public TransportConnectorBase<InputConnector<T>, T,
        BidirectionalConnector<T>>
{
public:
    static String tycoName() { return "InputConnector"; }
    static auto protocolDirection()
    {
        return ProtocolDirection(SimpleProtocol<T>(), false);
    }
    InputConnector(Component* c) : TransportConnectorBase(c) { }
    virtual void setData(Tick t, T v) = 0;
};

template<class C, class T> class TransportComponentBase
  : public ComponentBase<C>
{
public:
    TransportComponentBase(Component::Type t) : ComponentBase(t) { }
    static String typeName()
    {
        return C::tycoName() + "<" + typeFromCompileTimeType<T>().toString() +
            ">";
    }
};

template<class T, class C> class BooleanComponent
  : public TransportComponentBase<C, T>
{
public:
    BooleanComponent(Component::Type type)
      : TransportComponentBase(type), _input0(this), _input1(this),
        _output(this)
    {
        connector("input0", &_input0);
        connector("input1", &_input1);
        connector("output", &_output);
    }
    bool subLoopCheck() { return _output.loopCheck(); }
    virtual void update0(Tick t, T v) = 0;
    virtual void update1(Tick t, T v) = 0;
private:
    class InputConnector : public ::InputConnector<T>
    {
    public:
        InputConnector(BooleanComponent *c)
          : ::InputConnector<T>(c), _component(c) { }
        void connect(::Connector* other)
        {
            _other = other;
            ::InputConnector<T>::connect(other);
        }
        ::Connector* _other;
        T _v;
        BooleanComponent* _component;
    };
    class InputConnector0 : public InputConnector
    {
    public:
        InputConnector0(BooleanComponent *c) : InputConnector(c) { }
        void setData(Tick t, T v)
        {
            this->_component->update0(t, v);
            this->_v = v;
        }
    };
    class InputConnector1 : public InputConnector
    {
    public:
        InputConnector1(BooleanComponent *c) : InputConnector(c) { }
        void setData(Tick t, T v)
        {
            this->_component->update1(t, v);
            this->_v = v;
        }
    };
protected:
    InputConnector0 _input0;
    InputConnector1 _input1;
    OptimizedOutputConnector<T> _output;
};

template<class T> class BinaryTraits
{
public:
    static T zero() { return 0; }
    static T invert(const T& other) { return ~other; }
    static T one() { return invert(zero()); }
};

template<> class BinaryTraits<bool>
{
public:
    static bool zero() { return false; }
    static bool invert(const bool& other) { return !other; }
    static bool one() { return true; }
};

template<class T> class AndComponent
  : public BooleanComponent<T, AndComponent<T>>
{
public:
    static String tycoName() { return "And"; }
    AndComponent(Component::Type type)
      : BooleanComponent<T, AndComponent<T>>(type) { }
    void load(const Value& v)
    {
        BooleanComponent::load(v);
        _output.init(_input0._v & _input1._v);
    }
    void runTo(Tick tick)
    {
        _input0._otherComponent->runTo(tick);
        if (this->_input0._v != BinaryTraits<T>::zero())
            _input1._otherComponent->runTo(tick);
        Component::runTo(tick);
    }
    void update0(Tick t, T v)
    {
        if (t > this->_input1._otherComponent->_tick)
            this->_input1._otherComponent->runTo(t);
        else {
            this->_tick = t;
            if (this->_input1._v != BinaryTraits<T>::zero())
                this->_output.set(t, v & this->_input1._v);
        }
    }
    void update1(Tick t, T v)
    {
        if (t > this->_input0._otherComponent->_tick)
            this->_input0._otherComponent->runTo(t);
        else {
            this->_tick = t;
            if (this->_input0._v != BinaryTraits<T>::zero())
                this->_output.set(t, v & this->_input0._v);
        }
    }
};

template<class T> class OrComponent
  : public BooleanComponent<T, OrComponent<T>>
{
public:
    static String tycoName() { return "Or"; }
    OrComponent(Component::Type type)
      : BooleanComponent<T, OrComponent<T>>(type) { }
    void load(const Value& v)
    {
        BooleanComponent::load(v);
        _output.init(_input0._v | _input1._v);
    }
    void runTo(Tick tick)
    {
        _input0._otherComponent->runTo(tick);
        if (this->_input0._v != BinaryTraits<T>::one())
            _input1._otherComponent->runTo(tick);
        Component::runTo(tick);
    }
    void update0(Tick t, T v)
    {
        if (t > this->_input1._otherComponent->_tick)
            this->_input1._otherComponent->runTo(t);
        else {
            this->_tick = t;
            if (this->_input1._v != BinaryTraits<T>::one())
                this->_output.set(t, v | this->_input1._v);
        }
    }
    void update1(Tick t, T v)
    {
        if (t > this->_input0._otherComponent->_tick)
            this->_input0._otherComponent->runTo(t);
        else {
            this->_tick = t;
            if (this->_input0._v != BinaryTraits<T>::one())
                this->_output.set(t, v | this->_input0._v);
        }
    }
};

template<class T> class NotComponent
  : public TransportComponentBase<NotComponent<T>, T>
{
public:
    static String tycoName() { return "Not"; }
    NotComponent(Component::Type type)
      : TransportComponentBase(type), _input(this), _output(this)
    {
        connector("input", &_input);
        connector("output", &_output);
    }
    bool subLoopCheck() { return _output.loopCheck(); }
    void runTo(Tick tick)
    {
        // We're up to date if our input is up to date.
        _input._otherComponent->runTo(tick);
        Component::runTo(tick);
    }
    void update(Tick t, T v)
    {
        _output._other->setData(t, BinaryTraits<T>::invert(v));
    }
private:
    class InputConnector : public ::InputConnector<T>
    {
    public:
        InputConnector(NotComponent *c)
          : ::InputConnector<T>(c),
            _component(static_cast<NotComponent<T>*>(c))
        { }
        void setData(Tick t, T v) { _component->update(t, v); }
        NotComponent<T>* _component;
    };
protected:
    InputConnector _input;
    OutputConnector<T> _output;
};

template<class T> class BucketComponent
  : public TransportComponentBase<BucketComponent<T>, T>
{
public:
    static String tycoName() { return "Bucket"; }
    BucketComponent(Component::Type t)
      : TransportComponentBase(t), _connector(this)
    {
        connector("", &_connector);
    }
    class Connector : public InputConnector<T>
    {
    public:
        Connector(BucketComponent* c) : InputConnector<T>(c) { }
        void setData(Tick tick, T t) { }
    };
    Connector _connector;
};

template<class T> class ConstantComponent
  : public TransportComponentBase<ConstantComponent<T>, T>
{
public:
    static String tycoName() { return "Constant"; }
    ConstantComponent(Component::Type t, T v = BinaryTraits<T>::one())
      : TransportComponentBase(t), _v(v), _connector(this)
    {
        connector("", &_connector);
    }
private:
    void load(const Value& v) { _connector.setData(0, _v); }
    T _v;
    OutputConnector<T> _connector;
};

template<class T> class FanoutComponent
  : public TransportComponentBase<FanoutComponent<T>, T>
{
public:
    static String tycoName() { return "Fanout"; }
    FanoutComponent(Component::Type t)
      : TransportComponentBase(t), _input(this), _output(this)
    {
        connector("input", &_input);
        connector("output", &_output);
    }
private:
    class InputConnector : public ::InputConnector<T>
    {
    public:
        InputConnector(FanoutComponent* c, OutputConnector* o)
          : ::InputConnector(c), _output(o) { }
        void setData(Tick t, T v) { _output->update(t, v); }
    private:
        OutputConnector* _output;
    };
    class OutputConnector
      : public TransportConnectorBase<OutputConnector, T, ::OutputConnector<T>>
    {
    public:
        OutputConnector(FanoutComponent* c) :: TransportConnectorBase(c) { }
        void update(Tick t, T v)
        {
            for (auto c : _connected)
                c->update(t, v);
        }
        static auto canConnectMultiple() { return true; }
        void connect(Connector* other, ProtocolDirection pd)
        {

        }
    private:
        List<BidirectionalConnector<T>*> _connected;
    };
    InputConnector _input;
    OutputConnector _output;
};

// SRLatch works like a NAND latch with inverters on the inputs.
class SRLatch : public ComponentBase<SRLatch>
{
public:
    static String typeName() { return "SRLatch"; }
    SRLatch(Component::Type type)
      : ComponentBase(type), _set(this), _reset(this), _isSet(false),
        _lastSet(this), _lastReset(this)
    {
        connector("set", &_set);
        connector("reset", &_reset);<commit_msg>More fanout<commit_after>#include "alfe/string.h"
#include "alfe/array.h"
#include "alfe/file.h"
#include "alfe/stack.h"
#include "alfe/hash_table.h"
#include "alfe/main.h"
#include "alfe/space.h"
#include "alfe/config_file.h"
#include "alfe/type.h"
#include "alfe/rational.h"
#include "alfe/pipes.h"
#include "alfe/sdl2.h"
#include "alfe/reference.h"

#include <stdlib.h>
#include <limits.h>

typedef UInt8 BGRI;

//class SourceProgram
//{
//};

template<class T> class SimulatorT;
typedef SimulatorT<void> Simulator;

template<class T> class Intel8088CPUT;
typedef Intel8088CPUT<void> Intel8088CPU;

template<class T> class ComponentT;
typedef ComponentT<void> Component;

template<class T> class Intel8237DMACT;
typedef Intel8237DMACT<void> Intel8237DMAC;

template<class T> class Intel8259PICT;
typedef Intel8259PICT<void> Intel8259PIC;

template<class T> class DMAPageRegistersT;
typedef DMAPageRegistersT<void> DMAPageRegisters;

template<class T> class PCXTKeyboardT;
typedef PCXTKeyboardT<void> PCXTKeyboard;

template<class T> class PCXTKeyboardPortT;
typedef PCXTKeyboardPortT<void> PCXTKeyboardPort;

template<class T> class ConnectorT;
typedef ConnectorT<void> Connector;

Concrete second;

class Tick
{
    typedef int Base;
public:
    Tick() : _t(0) { }
    Tick(const Base& t) : _t(t) { }
    static Tick infinity() { return std::numeric_limits<Base>::max(); }
    bool operator<=(const Tick& other) const { return _t <= other._t; }
    bool operator<(const Tick& other) const { return _t < other._t; }
    bool operator>=(const Tick& other) const { return _t >= other._t; }
    bool operator>(const Tick& other) const { return _t > other._t; }
    const Tick& operator+=(const Tick& other) { _t += other._t; return *this; }
    const Tick& operator-=(const Tick& other) { _t -= other._t; return *this; }
    Tick operator+(const Tick& other) { return Tick(_t + other._t); }
    Tick operator-(const Tick& other) { return Tick(_t - other._t); }
    operator String() const { return decimal(_t); }
    Tick operator-() const { return Tick(-_t); }
    Tick operator*(int other) { return Tick(_t*other); }
    typedef IntegerType Type;
private:
    Base _t;
};
template<> Type typeFromCompileTimeType<Tick>() { return Tick::Type(); }

class HexPersistenceType : public IntegerType
{
public:
    HexPersistenceType(int digits) : IntegerType(create<Body>(digits)) { }
private:
    class Body : public IntegerType::Body
    {
    public:
        Body(int digits) : _digits(digits) { }
        String serialize(void* p, int width, int used, int indent, int delta)
            const
        {
            return hex(*static_cast<int*>(p), _digits);
        }
    private:
        int _digits;
    };
};

class Protocol : public ConstHandle
{
public:
    Protocol() { }
    Protocol(const ConstHandle& r) : ConstHandle(r) { }
};
template<class T> class ProtocolBase : public Nullary<Protocol, T> { };

// The meaning of _output is up to the particular Protocol. In some cases (e.g.
// ISA card edge/slot) neither is really an output so we just have to pick a
// direction arbitrarily. Non-gendered connectors should specify two
// ProtocolDirections, one for each direction.
class ProtocolDirection
{
public:
    ProtocolDirection() : _output(false) { }
    ProtocolDirection(Protocol p, bool o) : _protocol(p), _output(o) { }
    bool matches(ProtocolDirection other) const
    {
        return _protocol == other._protocol && _output != other._output;
    }
    bool operator==(ProtocolDirection r) const
    {
        return _protocol == r._protocol && _output == r._output;
    }
    UInt32 hash() const
    {
        return Hash(typeid(ProtocolDirection)).mixin(_protocol.hash()).
            mixin(_output ? 1 : 0);
    }
    auto operator-() const { return ProtocolDirection(_protocol, !_output); }
private:
    Protocol _protocol;
    bool _output;
};

Value connectorFromValue(Value v);
Type connectorTypeFromType(Type t);

template<class T> class ConnectorT
{
public:
    ConnectorT(Component* component)
      : _component(component), _connected(false) { }
    class Type : public ::Type
    {
    public:
        Type() { }
        Type(::Type type) : ::Type(to<Body>(type)) { }
        bool compatible(Type other) const
        {
            return body()->compatible(other) ||
                other.body()->compatible(*this);
        }
        bool canConnectMultiple() const
        {
            return body()->canConnectMultiple();
        }
        List<ProtocolDirection> protocolDirections() const
        {
            return body()->protocolDirections();
        }
        static String name() { return "Connector"; }
        class Body : public ::Type::Body
        {
        public:
            Body(Simulator* simulator) : _simulator(simulator) { }
            virtual List<ProtocolDirection> protocolDirections() const = 0;
            virtual bool canConnectMultiple() const { return false; }
            virtual bool canConvertFrom(const ::Type& other, String* reason)
                const
            {
                ConnectorT<T>::Type t = connectorTypeFromType(other);
                if (!t.valid()) {
                    *reason = other.toString() + " is not a connector.";
                    return false;
                }
                if (!_simulator->canConnect(Type(type()), t)) {
                    *reason = t.toString() + " and " + this->toString() +
                        " are not compatible connectors.";
                    return false;
                }
                return true;
            }
            virtual ValueT<T> convert(const ValueT<T>& value) const
            {
                return Value(type(), connectorFromValue(value).value(),
                    value.span());
            }
        private:
            Simulator* _simulator;
        };
    public:
        const Body* body() const { return this->template as<Body>(); }
    };
    Value getValue() const
    {
        // The const_cast here is a result of the syntax
        // "componentA.connector1 = componentB.connector2;" in the config file.
        // In pure ALFE syntax, obtaining the "value" of connector2 does not
        // modify componentB, so getValue() is const. However, in Berapa,
        // componentB's state may be modified by this connection.
        return Value(type(), const_cast<Connector*>(this));
    }
    void doConnect(ConnectorT<T>* other, ProtocolDirection pd, Span span)
    {
        if (_connected && !type().canConnectMultiple())
            span.throwError("Connector is already connected");
        connect(other, pd);
        _connected = true;
    }
    void checkConnected()
    {
        if (!_connected && !type().canConnectMultiple())
            _component->simulator()->connectStub(this);
    }
    Component* component() const { return _component; }
    void setName(String name) { _name = name; }
    String name() const { return _component->name() + "." + _name; }

    virtual Type type() const = 0;
    virtual void connect(Connector* other, ProtocolDirection pd)
    {
        connect(other);
    }
    virtual void connect(Connector* other) { }

private:
    bool _connected;
    ComponentT<T>* _component;
    String _name;
};

template<class T, class B = Connector> class ConnectorBase : public B
{
public:
    ConnectorBase(Component* c) : B(c) { }
    static auto protocolDirections()
    {
        List<ProtocolDirection> r;
        r.add(T::protocolDirection());
        return r;
    }
    static auto canConnectMultiple() { return false; }
    Connector::Type type() const { return T::Type(component()->simulator()); }
    class Type : public B::Type
    {
    public:
        Type(Simulator* simulator)
          : B::Type(Type::template create<Body>(simulator)) { }
        Type(const ConstHandle& r) : B::Type(r) { }

        class Body : public B::Type::Body
        {
        public:
            Body(Simulator* simulator) : B::Type::Body(simulator) { }
            List<ProtocolDirection> protocolDirections() const
            {
                return T::protocolDirections();
            }
            bool canConnectMultiple() const { return T::canConnectMultiple(); }
            String toString() const { return T::typeName(); }
        };
    };
};

template<class T> class ComponentT : public Structure
{
public:
    class Type : public ::Type
    {
    public:
        Type() { }
        Type(::Type type) : ::Type(to<Body>(type)) { }
        Reference<Component> createComponent()
        {
            auto c = body()->createComponent();
            body()->simulator()->addComponent(c);
            return c;
        }
        Simulator* simulator() const { return body()->simulator(); }
        typename ConnectorT<T>::Type defaultConnectorType() const
        {
            return body()->defaultConnectorType();
        }
    protected:
        class Body : public ::Type::Body
        {
        public:
            Body(Simulator* simulator) : _simulator(simulator) { }
            ::Type member(Identifier i) const
            {
                if (i.name() == "*")
                    return StringType();
                return ::Type();
            }
            virtual Reference<Component> createComponent() const = 0;
            bool canConvertFrom(const ::Type& other, String* why) const
            {
                return other.canConvertTo(StructuredType::empty().type(), why);
            }
            Value convert(const Value& value) const
            {
                auto v = Type(type()).createComponent();
                return Value(type(), static_cast<Structure*>(&(*v)),
                    value.span());
            }
            Simulator* simulator() const { return _simulator; }
            typename ConnectorT<T>::Type defaultConnectorType() const
            {
                return _defaultConnectorType;
            }
        protected:
            Simulator* _simulator;
            typename ConnectorT<T>::Type _defaultConnectorType;
        };
        const Body* body() const { return as<Body>(); }
    };
    ComponentT(Type type)
      : _type(type), _simulator(type.simulator()), _ticksPerCycle(0),
        _defaultConnector(0), _loopCheck(false)
    {
        persist("tick", &_tick);
    }
    virtual void runTo(Tick tick) { _tick = tick; }
    virtual void maintain(Tick ticks) { _tick -= ticks; }
    String name() const { return _name; }
    virtual Rational cyclesPerSecond() const { return 0; }
    void setTicksPerCycle(Tick ticksPerCycle)
    {
        _ticksPerCycle = ticksPerCycle;
        _tick = 0;
    }
    void set(Identifier name, Value value, Span span)
    {
        String n = name.name();
        if (n == "*") {
            _name = value.value<String>();
            return;
        }
        if (typename ConnectorT<T>::Type(value.type()).valid()) {
            auto l = getValue(name).template value<Connector*>();
            auto r = value.value<Connector*>();
            _simulator->connect(l, r, span);
            return;
        }
        if (_config.hasKey(n)) {
            Member m = _config[n];
            m.type().deserialize(value, m._p);
        }
        Structure::set(name, value, span);
    }
    template<class C> class TypeHelper : public Type
    {
    public:
        TypeHelper(Simulator* simulator)
            : Type(TypeHelper::template create<Body>(simulator)) { }
        TypeHelper(const ConstHandle& other) : Type(other) { }
    protected:
        class Body : public Type::Body
        {
        public:
            Body(Simulator* simulator) : Type::Body(simulator)
            {
                C component(type());
                for (auto i : component._config)
                    _members[i.key()] = i.value().type();
                if (component._defaultConnector != 0) {
                    this->_defaultConnectorType =
                        component._defaultConnector->type();
                }
            }
            Reference<Component> createComponent() const
            {
                return Reference<Component>::create<C>(Type(type()));
            }
            String toString() const { return C::typeName(); }
            ::Type member(Identifier i) const
            {
                if (_members.hasKey(i))
                    return _members[i];
                return Type::Body::member(i);
            }
            int size() const { return sizeof(C); }
            Value value(void* p) const { return static_cast<C*>(p)->value(); }
        private:
            HashTable<Identifier, ::Type> _members;
        };
    };
    virtual String save(int width, int used, int indent, int delta) const
    {
        // First try putting everything on one line
        String s("{ ");
        bool needComma = false;
        bool separate = false;
        used += 5;
        for (auto i : _persist) {
            if (used > width) {
                separate = true;
                break;
            }
            Member m = i.value();
            int u = used + i.key().length() + 2 + (needComma ? 2 : 0);
            String v = "{ }";
            ::Type t = m.type();
            if (t.value(m._p) != Value(t)) {
                v = t.serialize(m._p, width, u, 0, 0);
                if (v == "*") {
                    separate = true;
                    s = "";
                    break;
                }
            }
            if (v != "{ }") {
                if (needComma)
                    s += ", ";
                needComma = true;
                s += i.key() + ": " + v;
                used = u + v.length();
            }
        }
        if (s == "{ ")
            return "{ }";
        if (!separate && used <= width)
            return s + " }";
        else
            s = "";
        if (s == "" && indent == 0)
            return "*";
        // It doesn't all fit on one line, put each member on a separate line.
        s = "{\n";
        needComma = false;
        for (auto i : _persist) {
            Member m = i.value();
            int u = indent + i.key().length();
            String v = "{ }";
            ::Type t = m.type();
            if (t.value(m._p) != Value(t))
                v = t.serialize(m._p, width, u, indent + delta, delta);
            if (v != "{ }") {
                if (needComma)
                    s += ",\n";
                needComma = true;
                s += String(" ")*indent + i.key() + ": " + v;
            }
        }
        return s + " }";
    }
    virtual ::Type persistenceType() const
    {
        List<StructuredType::Member> members;
        for (auto i : _persist)
            members.add(StructuredType::Member(i.key(), i.value()._initial));
        return PersistenceType(_type.toString(), members, _type.size());
    }
    virtual void load(const Value& value)
    {
        auto members = value.value<HashTable<Identifier, Value>>();
        for (auto i : _persist) {
            Member m = i.value();
            m.type().deserialize(members[i.key()], m._p);
        }
    }
    Value value() const
    {
        HashTable<Identifier, Value> h;
        for (auto i : _persist) {
            Member m = i.value();
            h.add(i.key(), m.type().value(m._p));
        }
        return Value(persistenceType(), h);
    }
    Type type() const { return _type; }
    Connector* defaultConnector() const { return _defaultConnector; }
    void checkConnections(int* n)
    {
        for (auto i : _config) {
            Member m = i.value();
            if (typename ConnectorT<T>::Type(m.type()).valid())
                static_cast<ConnectorT<T>*>(m._p)->checkConnected();
        }
        if (_name == "") {
            _name = decimal(*n);
            ++*n;
        }
    }
    SimulatorT<T>* simulator() const { return _simulator; }
    bool loopCheck()
    {
        if (_loopCheck)
            return true;
        _loopCheck = true;
        if (subLoopCheck())
            return true;
        _loopCheck = false;
        return false;
    }
    bool isInLoop() const { return _loopCheck; }
    virtual bool subLoopCheck() { return false; }

    Tick _tick;

protected:
    void connector(String name, ConnectorT<T>* p)
    {
        if (name == "") {
            _defaultConnector = p;
            Identifier i = Identifier(OperatorAssignment());
            OverloadedFunctionSet o(i);
            o.add(AssignmentFunco(this));
            Value v(o);
            _config.add(i, Member(0, v));
            Structure::set(i, v, Span());
        }
        else {
            // Connectors don't have a default value. If they did, a connector
            // supporting multiple connections would always be connected to the
            // default. We can't convert directly from the type to the value,
            // or the conversion would call convert() which would attempt to
            // connect.
            _config.add(name,
                Member(static_cast<void*>(p), Value(p->type(), 0)));
            Structure::set(name, p->getValue(), Span());
        }
        p->setName(name);
    }
    template<class C> void config(String name, C* p,
        ::Type type = typeFromCompileTimeType<C>())
    {
        _config.add(name, Member(static_cast<void*>(p), type));
        Structure::set(name, type, Span());
        set(name, type, Span());
    }
    template<class C, class I, std::enable_if_t<!std::is_base_of<::Type, I>
        ::value>* = nullptr>
        void persist(String name, C* p, I initial,
            ::Type type = typeFromCompileTimeType<C>())
    {
        Value v(type, initial);
        ArrayType arrayType(type);
        if (arrayType.valid()) {
            Value m(arrayType.contained(), initial);
            List<Value> initialArray;
            LessThanType l(arrayType.indexer());
            if (!l.valid()) {
                throw Exception(
                    "Don't know how many elements to put in default.");
            }
            int n = l.n();
            for (int i = 0; i < n; ++i)
                initialArray.add(m);
            v = Value(type, initialArray);
        }
        _persist.add(name, Member(static_cast<void*>(p), v));

    }
    template<class C> void persist(String name, C* p,
        Value initial = Value(typeFromCompileTimeType<C>()))
    {
        _persist.add(name, Member(static_cast<void*>(p), initial));
    }
    Tick _ticksPerCycle;
private:
    class PersistenceType : public StructuredType
    {
    public:
        PersistenceType(String name, List<StructuredType::Member> members,
            int size)
          : StructuredType(create<Body>(name, members, size)) { }
    private:
        class Body : public StructuredType::Body
        {
        public:
            Body(String name, List<Member> members, int size)
              : StructuredType::Body(name, members), _size(size) { }
            Value value(void* p) const
            {
                return static_cast<Component*>(p)->value();
            }
            int size() const { return _size; }
            String serialize(void* p, int width, int used, int indent,
                int delta) const
            {
                return static_cast<Component*>(p)->
                    save(width, used, indent, delta);
            }
            void deserialize(const Value& value, void* p) const
            {
                static_cast<Component*>(p)->load(value);
            }

        private:
            int _size;
        };
    };
    class AssignmentFunco : public Funco
    {
    public:
        AssignmentFunco(Component* component)
          : Funco(create<Body>(component)) { }
        ::Type type() const { return Funco::type(); }
        class Body : public Funco::Body
        {
        public:
            Body(Component* component) : _component(component) { }
            Value evaluate(List<Value> arguments, Span span) const
            {
                auto i = arguments.begin();
                auto ls = i->rValue().value<Structure*>();
                auto l = dynamic_cast<ComponentT<T>*>(ls)->_defaultConnector;
                auto lt = l->getValue().type();
                ++i;
                String reason;
                if (Type(i->type()).valid()) {
                    auto rs = i->value<Structure*>();
                    auto r = dynamic_cast<ComponentT<T>*>(rs)->
                        _defaultConnector;
                    if (!lt.canConvertFrom(r->getValue().type(), &reason))
                        span.throwError(reason);
                    _component->simulator()->connect(l, r, span);
                    return Value();
                }
                auto r = dynamic_cast<ConnectorT<T>*>(i->value<Structure*>());
                if (!lt.canConvertFrom(r->getValue().type(), &reason))
                    span.throwError(reason);
                _component->simulator()->connect(l, r, span);
                return Value();
            }
            Identifier identifier() const { return OperatorAssignment(); }
            bool argumentsMatch(List<::Type> argumentTypes) const
            {
                if (argumentTypes.count() != 2)
                    return false;
                auto i = argumentTypes.begin();
                if (!Type(i->rValue()).valid())
                    return false;
                ++i;
                if (Type(*i).valid())
                    return true;
                return typename ConnectorT<T>::Type(*i).valid();
            }
            // Won't actually be used (since there's only one function matching
            // the argument types) but necessary to avoid AssignmentFunco being
            // an abstract class.
            List<Tyco> parameterTycos() const
            {
                List<Tyco> r;
                r.add(typename ConnectorT<T>::Type());
                r.add(LValueType(_component->type()));
                return r;
            }
        private:
            ComponentT<T>* _component;
        };
    };
    class Member
    {
    public:
        Member() { }
        Member(void* p, Value initial) : _p(p), _initial(initial) { }
        ::Type type() const { return _initial.type(); }
        void* _p;
        Value _initial;
    };
    HashTable<Identifier, Member> _config;
    HashTable<String, Member> _persist;

    String _name;
    Type _type;
    Connector* _defaultConnector;
    SimulatorT<T>* _simulator;
    bool _loopCheck;

    friend class ConnectorT<T>::Type::Body;
    friend class AssignmentFunco::Body;
};

template<class C> class ComponentBase : public Component
{
public:
    ComponentBase(Component::Type type) : Component(type) { }
    typedef Component::TypeHelper<C> Type;
};

// For sub-components (like RAM) the type doesn't create the component, it just
// returns the pointer to the member of the parent component.
template<class C> class SubComponent : public ComponentBase<C>
{
public:
    SubComponent(Component::Type type) : ComponentBase(type) { }
    class Type : public ComponentBase<C>::Type
    {
    public:
        Type(Simulator* simulator, C* c = 0)
          : Component::TypeHelper<C>(
                Component::TypeHelper<C>::template create<Body>(simulator, c))
        { }
    private:
        class Body : public ComponentBase<C>::Type::Body
        {
        public:
            Body(Simulator* simulator, C* c)
              : ComponentBase<C>::Type::Body(simulator), _c(c) { }
            Value convert(const Value& value) const
            {
                return Value(this->type(), static_cast<Structure*>(_c),
                    value.span());
            }
        private:
            C* _c;
        };
    };
};

Value connectorFromValue(Value v)
{
    Component::Type ct(v.type());
    if (ct.valid()) {
        Structure* s = v.value<Structure*>();
        auto component = static_cast<Component*>(s);
        Connector* connector = component->defaultConnector();
        return connector->getValue();
    }
    return v;
}

Type connectorTypeFromType(Type t)
{
    Component::Type ct(t);
    if (ct.valid())
        return ct.defaultConnectorType();
    return t;
}

class ClockedComponent : public Component
{
public:
    ClockedComponent(Type type) : Component(type)
    {
        config("frequency", &_cyclesPerSecond, (1/second).type());
    }
    Rational cyclesPerSecond() const { return _cyclesPerSecond; }
private:
    Rational _cyclesPerSecond;
};

template<class C> class ClockedComponentBase : public ClockedComponent
{
public:
    ClockedComponentBase(Component::Type t) : ClockedComponent(t) { }
    typedef Component::TypeHelper<C> Type;
};

template<class T> class SimpleProtocol
  : public ProtocolBase<SimpleProtocol<T>> { };

template<class T> class OutputConnector;
template<class T> class InputConnector;
template<class T> class BidirectionalConnector;

class TransportConnector : public Connector
{
public:
    TransportConnector(Component* c) : Connector(c) { }
    class Type : public Connector::Type
    {
    public:
        Type(const ConstHandle& other) : Connector::Type(other) { }
        ::Type transportType() const { return body()->transportType(); }
    protected:
        class Body : public Connector::Type::Body
        {
        public:
            Body(Simulator* s) : Connector::Type::Body(s) { }
            virtual ::Type transportType() const = 0;
        };
        const Body* body() const { return as<Body>(); }
    };
};

template<class C, class T, class B = TransportConnector>
    class TransportConnectorBase : public ConnectorBase<C, B>
{
public:
    TransportConnectorBase(Component* c) : ConnectorBase(c) { }
    static String typeName()
    {
        return C::tycoName() + "<" + typeFromCompileTimeType<T>().toString() +
            ">";
    }
    class Type : public ConnectorBase<C, B>::Type
    {
    public:
        Type(Simulator* s) : ConnectorBase<C, B>::Type(create<Body>(s)) { }
        Type(const ConstHandle& r) : ConnectorBase<C, B>::Type(r) { }
        class Body : public ConnectorBase<C, B>::Type::Body
        {
        public:
            Body(Simulator* s) : ConnectorBase<C, B>::Type::Body(s) { }
            ::Type transportType() const
            {
                return typeFromCompileTimeType<T>();
            }
        };
    };
};


template<class T> class ConstantComponent;
template<class T> class BucketComponent;

template<class T> class BidirectionalConnector
  : public TransportConnectorBase<BidirectionalConnector<T>, T>
{
public:
    static String tycoName() { return "BidirectionalConnector"; }
    static auto protocolDirections()
    {
        List<ProtocolDirection> r;
        r.add(ProtocolDirection(SimpleProtocol<T>(), true));
        r.add(ProtocolDirection(SimpleProtocol<T>(), false));
        return r;
    }
    static auto canConnectMultiple() { return true; }
    BidirectionalConnector(Component* c)
      : TransportConnectorBase(c), _other(0) { }
    virtual void setData(Tick t, T v) = 0;
    void connect(::Connector* other)
    {
        if (_other == 0) {
            _other = static_cast<BidirectionalConnector<T>*>(other);
            _otherComponent = _other->component();
        }

    }
    BidirectionalConnector<T>* _other;
    Component* _otherComponent;
};

template<class T> class OutputConnector
  : public TransportConnectorBase<OutputConnector<T>, T,
        BidirectionalConnector<T>>
{
public:
    static String tycoName() { return "OutputConnector"; }
    static auto protocolDirection()
    {
        return ProtocolDirection(SimpleProtocol<T>(), true);
    }
    OutputConnector(Component* c) : TransportConnectorBase(c) { }
    void setData(Tick t, T v) { }
    bool loopCheck() { return this->_otherComponent->loopCheck(); }
};

template<class T> class OptimizedOutputConnector : public OutputConnector<T>
{
public:
    OptimizedOutputConnector(Component* c) : OutputConnector(c) { }
    void set(Tick t, T v)
    {
        if (v != _v) {
            _v = v;
            _other->setData(t, v);
        }
    }
    void init(T v) { _v = v; }
private:
    T _v;
};

template<class T> class InputConnector
  : public TransportConnectorBase<InputConnector<T>, T,
        BidirectionalConnector<T>>
{
public:
    static String tycoName() { return "InputConnector"; }
    // It may seem strange that we don't override protocolDirections() here,
    // meaning that we speak ProtocolDirection(SimpleProtocol<T>(), true). This
    // is because it's allowed for two InputConnectors to be connected to each
    // other. The result will be that both are connected to outputs on the same
    // fanout, with the input stubbbed (and hence connected to
    // ConstantComponent). The result is ultimately the same as if both
    // InputConnectors are left disconnected (and hence stubbed to separate
    // ConstantComponents).
    InputConnector(Component* c) : TransportConnectorBase(c) { }
    virtual void setData(Tick t, T v) = 0;
};

template<class C, class T> class TransportComponentBase
  : public ComponentBase<C>
{
public:
    TransportComponentBase(Component::Type t) : ComponentBase(t) { }
    static String typeName()
    {
        return C::tycoName() + "<" + typeFromCompileTimeType<T>().toString() +
            ">";
    }
};

template<class T, class C> class BooleanComponent
  : public TransportComponentBase<C, T>
{
public:
    BooleanComponent(Component::Type type)
      : TransportComponentBase(type), _input0(this), _input1(this),
        _output(this)
    {
        connector("input0", &_input0);
        connector("input1", &_input1);
        connector("output", &_output);
    }
    bool subLoopCheck() { return _output.loopCheck(); }
    virtual void update0(Tick t, T v) = 0;
    virtual void update1(Tick t, T v) = 0;
private:
    class InputConnector : public ::InputConnector<T>
    {
    public:
        InputConnector(BooleanComponent *c)
          : ::InputConnector<T>(c), _component(c) { }
        void connect(::Connector* other)
        {
            _other = other;
            ::InputConnector<T>::connect(other);
        }
        ::Connector* _other;
        T _v;
        BooleanComponent* _component;
    };
    class InputConnector0 : public InputConnector
    {
    public:
        InputConnector0(BooleanComponent *c) : InputConnector(c) { }
        void setData(Tick t, T v)
        {
            this->_component->update0(t, v);
            this->_v = v;
        }
    };
    class InputConnector1 : public InputConnector
    {
    public:
        InputConnector1(BooleanComponent *c) : InputConnector(c) { }
        void setData(Tick t, T v)
        {
            this->_component->update1(t, v);
            this->_v = v;
        }
    };
protected:
    InputConnector0 _input0;
    InputConnector1 _input1;
    OptimizedOutputConnector<T> _output;
};

template<class T> class BinaryTraits
{
public:
    static T zero() { return 0; }
    static T invert(const T& other) { return ~other; }
    static T one() { return invert(zero()); }
};

template<> class BinaryTraits<bool>
{
public:
    static bool zero() { return false; }
    static bool invert(const bool& other) { return !other; }
    static bool one() { return true; }
};

template<class T> class AndComponent
  : public BooleanComponent<T, AndComponent<T>>
{
public:
    static String tycoName() { return "And"; }
    AndComponent(Component::Type type)
      : BooleanComponent<T, AndComponent<T>>(type) { }
    void load(const Value& v)
    {
        BooleanComponent::load(v);
        _output.init(_input0._v & _input1._v);
    }
    void runTo(Tick tick)
    {
        _input0._otherComponent->runTo(tick);
        if (this->_input0._v != BinaryTraits<T>::zero())
            _input1._otherComponent->runTo(tick);
        Component::runTo(tick);
    }
    void update0(Tick t, T v)
    {
        if (t > this->_input1._otherComponent->_tick)
            this->_input1._otherComponent->runTo(t);
        else {
            this->_tick = t;
            if (this->_input1._v != BinaryTraits<T>::zero())
                this->_output.set(t, v & this->_input1._v);
        }
    }
    void update1(Tick t, T v)
    {
        if (t > this->_input0._otherComponent->_tick)
            this->_input0._otherComponent->runTo(t);
        else {
            this->_tick = t;
            if (this->_input0._v != BinaryTraits<T>::zero())
                this->_output.set(t, v & this->_input0._v);
        }
    }
};

template<class T> class OrComponent
  : public BooleanComponent<T, OrComponent<T>>
{
public:
    static String tycoName() { return "Or"; }
    OrComponent(Component::Type type)
      : BooleanComponent<T, OrComponent<T>>(type) { }
    void load(const Value& v)
    {
        BooleanComponent::load(v);
        _output.init(_input0._v | _input1._v);
    }
    void runTo(Tick tick)
    {
        _input0._otherComponent->runTo(tick);
        if (this->_input0._v != BinaryTraits<T>::one())
            _input1._otherComponent->runTo(tick);
        Component::runTo(tick);
    }
    void update0(Tick t, T v)
    {
        if (t > this->_input1._otherComponent->_tick)
            this->_input1._otherComponent->runTo(t);
        else {
            this->_tick = t;
            if (this->_input1._v != BinaryTraits<T>::one())
                this->_output.set(t, v | this->_input1._v);
        }
    }
    void update1(Tick t, T v)
    {
        if (t > this->_input0._otherComponent->_tick)
            this->_input0._otherComponent->runTo(t);
        else {
            this->_tick = t;
            if (this->_input0._v != BinaryTraits<T>::one())
                this->_output.set(t, v | this->_input0._v);
        }
    }
};

template<class T> class NotComponent
  : public TransportComponentBase<NotComponent<T>, T>
{
public:
    static String tycoName() { return "Not"; }
    NotComponent(Component::Type type)
      : TransportComponentBase(type), _input(this), _output(this)
    {
        connector("input", &_input);
        connector("output", &_output);
    }
    bool subLoopCheck() { return _output.loopCheck(); }
    void runTo(Tick tick)
    {
        // We're up to date if our input is up to date.
        _input._otherComponent->runTo(tick);
        Component::runTo(tick);
    }
    void update(Tick t, T v)
    {
        _output._other->setData(t, BinaryTraits<T>::invert(v));
    }
private:
    class InputConnector : public ::InputConnector<T>
    {
    public:
        InputConnector(NotComponent *c)
          : ::InputConnector<T>(c),
            _component(static_cast<NotComponent<T>*>(c))
        { }
        void setData(Tick t, T v) { _component->update(t, v); }
        NotComponent<T>* _component;
    };
protected:
    InputConnector _input;
    OutputConnector<T> _output;
};

template<class T> class BucketComponent
  : public TransportComponentBase<BucketComponent<T>, T>
{
public:
    static String tycoName() { return "Bucket"; }
    BucketComponent(Component::Type t)
      : TransportComponentBase(t), _connector(this)
    {
        connector("", &_connector);
    }
    class Connector : public InputConnector<T>
    {
    public:
        Connector(BucketComponent* c) : InputConnector<T>(c) { }
        void setData(Tick tick, T t) { }
    };
    Connector _connector;
};

template<class T> class ConstantComponent
  : public TransportComponentBase<ConstantComponent<T>, T>
{
public:
    static String tycoName() { return "Constant"; }
    ConstantComponent(Component::Type t, T v = BinaryTraits<T>::one())
      : TransportComponentBase(t), _v(v), _connector(this)
    {
        connector("", &_connector);
    }
private:
    void load(const Value& v) { _connector.setData(0, _v); }
    T _v;
    OutputConnector<T> _connector;
};

template<class T> class FanoutComponent
  : public TransportComponentBase<FanoutComponent<T>, T>
{
public:
    static String tycoName() { return "Fanout"; }
    FanoutComponent(Component::Type t)
      : TransportComponentBase(t), _input(this), _output(this)
    {
        connector("input", &_input);
        connector("output", &_output);
    }
private:
    class InputConnector : public ::InputConnector<T>
    {
    public:
        InputConnector(FanoutComponent* c, OutputConnector* o)
          : ::InputConnector(c), _output(o) { }
        void setData(Tick t, T v) { _output->update(t, v); }
    private:
        OutputConnector* _output;
    };
    class OutputConnector
      : public TransportConnectorBase<OutputConnector, T, ::OutputConnector<T>>
    {
    public:
        OutputConnector(FanoutComponent* c) :: TransportConnectorBase(c) { }
        void update(Tick t, T v)
        {
            for (auto c : _connected)
                c->update(t, v);
        }
        static auto canConnectMultiple() { return true; }
        void connect(Connector* other, ProtocolDirection pd)
        {
            _connected.add(static_cast<BidirectionalConnector<T>*>(other));
        }
    private:
        List<BidirectionalConnector<T>*> _connected;
    };
    InputConnector _input;
    OutputConnector _output;
};

// SRLatch works like a NAND latch with inverters on the inputs.
class SRLatch : public ComponentBase<SRLatch>
{
public:
    static String typeName() { return "SRLatch"; }
    SRLatch(Component::Type type)
      : ComponentBase(type), _set(this), _reset(this), _isSet(false),
        _lastSet(this), _lastReset(this)
    {
        connector("set", &_set);
        connector("reset", &_reset);
{'fraction_non_alphanumeric': 0.12779406622374048, 'fraction_numerical': 0.003308497189122307, 'mean_word_length': 2.1682219097532918, 'pattern_counts': {'":': 4, '<': 473, '<?xml version=': 0, '>': 677, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7174185', 'n_tokens_mistral': 21555, 'n_tokens_neox': 21175, 'n_words': 5196}