Beispiel #1
0
        //An entry method for instance compilation
        private void CompileInstances(ElaClassInstance s, LabelMap map)
        {
            var ins = s;

            //First we need to compile default instances so that
            //other instances in this class will be able to use them
            while (ins != null)
            {
                if (ins.TypeName == null)
                {
                    CompileInstanceBody(ins, map);
                }

                ins = ins.And;
            }

            ins = s;

            //Now we compile specific instances
            while (ins != null)
            {
                if (ins.TypeName != null)
                {
                    CompileInstanceBody(ins, map);
                }

                ins = ins.And;
            }
        }
Beispiel #2
0
        //Some members may be generated directly by compiler. Here we check if this is the case for this
        //particular member.
        private bool TryAutogenerate(ScopeVar var, ElaClassInstance inst)
        {
            if ((var.Flags & ElaVariableFlags.Builtin) != ElaVariableFlags.Builtin)
            {
                return(false);
            }

            switch ((ElaBuiltinKind)var.Data)
            {
            //Used to generate Bounded.maxBound constant
            case ElaBuiltinKind.GenMaxBound:
                cw.Emit(Op.PushI4, 1);
                //Obtain type ID, no errors, they are captured elsewhere
                EmitSpecName(inst.TypePrefix, "$$" + inst.TypeName, inst, ElaCompilerError.None);
                cw.Emit(Op.Api, (Int32)Api.TypeConsNumber);
                cw.Emit(Op.Sub);

                EmitSpecName(inst.TypePrefix, "$$" + inst.TypeName, inst, ElaCompilerError.None);
                cw.Emit(Op.Api2, (Int32)Api.ConsCodeByIndex);
                cw.Emit(Op.Api, (Int32)Api.ConsDefault);
                return(true);

            //Used to generate Bounded.minBound constant
            case ElaBuiltinKind.GenMinBound:
            case ElaBuiltinKind.GenDefault:
                cw.Emit(Op.PushI4_0);
                //Obtain type ID, no errors, they are captured elsewhere
                EmitSpecName(inst.TypePrefix, "$$" + inst.TypeName, inst, ElaCompilerError.None);
                cw.Emit(Op.Api2, (Int32)Api.ConsCodeByIndex);
                cw.Emit(Op.Api, (Int32)Api.ConsDefault);
                return(true);

            default:
                return(false);
            }
        }
Beispiel #3
0
        //This function tries to autogenerate an instance (similar to derived in Haskell).
        //It can fully or partially generate it. A default instance (instance without a type) is
        //used for such purpose.
        private List <String> TryGenerateMembers(List <String> members, CodeFrame mod, ElaClassInstance inst)
        {
            if (members.Count == 0)
            {
                return(members);
            }

            var newMem = new List <String>(members);

            for (var i = 0; i < newMem.Count; i++)
            {
                var m     = newMem[i];
                var btVar = ObtainClassFunction(inst.TypeClassPrefix, inst.TypeClassName, m, inst.Line, inst.Column);

                //This is less likely but we better check this anyway
                if (btVar.IsEmpty())
                {
                    AddError(ElaCompilerError.MemberInvalid, inst, m, inst.TypeClassName);
                }

                var defVar = GetGlobalVariable("$default$" + m, GetFlags.NoError, inst.Line, inst.Column);

                //We dont' need to generate errors here, errors will be captured later.
                if (!defVar.IsEmpty())
                {
                    var builtin = (btVar.Flags & ElaVariableFlags.Builtin) == ElaVariableFlags.Builtin;

                    //Check if this member is implemented directly by compiler
                    if (!TryAutogenerate(defVar, inst))
                    {
                        PushVar(defVar);
                    }

                    if (!builtin)
                    {
                        PushVar(btVar);
                    }
                    else
                    {
                        cw.Emit(Op.PushI4, (Int32)btVar.Data);
                    }

                    EmitSpecName(inst.TypePrefix, "$$" + inst.TypeName, inst, ElaCompilerError.UndefinedType);
                    cw.Emit(Op.Addmbr);
                    members.Remove(m);
                }
            }

            return(members);
        }
Beispiel #4
0
        //Main method for instance compilation
        private void CompileInstanceBody(ElaClassInstance s, LabelMap map)
        {
            //Obtain type class data
            var mod     = default(CodeFrame);
            var mbr     = default(ClassData);
            var modId   = -1;
            var classId = ObtainTypeClass(s, out mbr, out modId, out mod);

            //It's OK if mbr (class members) is null. It is not null only if a class declaration is local.
            //However mod shouldn't be null in such a case (non-local class), and we will use it to obtain
            //class members. If mod==null and mbr==null, or mod doesn't have our class, than we really can't find it.
            var notFound = mbr == null && (mod == null || !mod.InternalClasses.TryGetValue(s.TypeClassName, out mbr));

            //Type class not found, nothing else to do
            if (notFound)
            {
                if (!options.IgnoreUndefined)
                {
                    AddError(ElaCompilerError.UnknownClass, s, s.TypeClassName);
                }
                else if (s.TypeName != null) //It is valid if this is a 'default' instance
                {
                    //Add an instance anyway - the IgnoreUndefine flag is usually set just to gather some module metadata,
                    //so we need to populate it anyway.
                    frame.InternalInstances.Add(new InstanceData(s.TypeName, s.TypeClassName, -1, modId, s.Line, s.Column));
                }
            }
            else
            {
                //Now we need to obtain a local ID of a module where type is defined
                var typeModuleCode = -1;
                var typeId         = -1;

                //Type name is null if this is a default instance
                if (s.TypeName != null)
                {
                    typeId = ObtainType(s, out typeModuleCode);

                    //Add new instance registration information
                    frame.InternalInstances.Add(new InstanceData(s.TypeName, s.TypeClassName, typeModuleCode, modId, s.Line, s.Column));
                }

                //Fill a list of classMembers, this list is used in this method to validate
                //whether all members of a class have an implementation
                var classMembers = new List <String>(mbr.Members.Length);

                for (var i = 0; i < mbr.Members.Length; i++)
                {
                    classMembers.Add(mbr.Members[i].Name);
                }

                if (s.Where != null)
                {
                    foreach (var b in s.Where.Equations)
                    {
                        var err = false;

                        //Patterns are now allowed in member bindings
                        if (!b.IsFunction() && b.Left.Type != ElaNodeType.NameReference)
                        {
                            AddError(ElaCompilerError.MemberNoPatterns, b.Left, FormatNode(b.Left));
                            err = true;
                        }

                        var name = b.GetLeftName();

                        //Only member functions can be declared inside instance
                        if (!classMembers.Contains(name))
                        {
                            AddError(ElaCompilerError.MemberInvalid, b, name, s.TypeClassName);
                            err = true;
                        }

                        //Compile member function
                        if (!err)
                        {
                            classMembers.Remove(name);

                            //It's OK if s.TypeName is null, this situation (default instance) is handled in this method
                            CompileInstanceMember(s.TypeClassName, s.TypeClassPrefix, b, map, s.TypePrefix, s.TypeName);
                        }
                    }
                }

                //If this is not a default instance, we can try to autogenerate it.
                if (s.TypeName != null)
                {
                    classMembers = TryGenerateMembers(classMembers, mod, s);
                }

                //Not all of the members are implemented, which is an error if an instance is
                //not generated by a compiler or this is a 'default' instance.
                if (s.TypeName != null && !IsBuiltIn(classId, typeId) && classMembers.Count > 0)
                {
                    if (s.Where != null)
                    {
                        AddError(ElaCompilerError.MemberNotAll, s, s.TypeClassName, s.TypeClassName + " " + s.TypeName);
                    }
                    else
                    {
                        //If a 'where' clause is not specified at all we need to generate a better
                        //error message (most likely this instance appears in 'deriving' clause).
                        AddError(ElaCompilerError.UnableDerive, s, s.TypeClassName, s.TypeName);
                    }
                }
            }
        }
Beispiel #5
0
        //Here we obtain type information - local ID of a module where a type is defined.
        private int ObtainType(ElaClassInstance s, out int typeModuleCode)
        {
            typeModuleCode = -1;

            if (s.TypePrefix == null)
            {
                //First we check that type is not defined locally
                if (!frame.InternalTypes.ContainsKey(s.TypeName))
                {
                    var sv = GetVariable("$$" + s.TypeName, CurrentScope, GetFlags.NoError, s.Line, s.Column);

                    if (sv.IsEmpty() && !options.IgnoreUndefined)
                    {
                        AddError(ElaCompilerError.UndefinedType, s, s.TypeName);
                        return(-1);
                    }

                    //The trick is - here sv can be only an external name (we do check prior to this
                    //if a type is not local). If it is an external name that first byte contains a
                    //local index of a referenced module - and typeModuleCode is effectly a local ID of a module
                    //where a type is declared
                    typeModuleCode = sv.Address & Byte.MaxValue;
                    return(sv.Data);
                }
                else
                {
                    var sv = GetVariable("$$" + s.TypeName, CurrentScope, GetFlags.NoError, s.Line, s.Column);
                    return(sv.Data);
                }
            }
            else
            {
                //TypePrefix is a local name that should correspond to a module alias
                var sv = GetVariable(s.TypePrefix, s.Line, s.Column);

                if (sv.IsEmpty())
                {
                    return(-1);
                }

                //A name exists but this is not a module alias
                if ((sv.Flags & ElaVariableFlags.Module) != ElaVariableFlags.Module)
                {
                    AddError(ElaCompilerError.InvalidQualident, s, s.TypePrefix);
                    return(-1);
                }

                //Obtain a local ID of a module based on TypePrefix (which is module alias
                //that should be unique within this module).
                var frm = frame.References[s.TypePrefix];
                typeModuleCode = frm.LogicalHandle;

                //Now we need to obtain type variable data - it may have the typeId of a type
                //if this is a built-in type.
                ScopeVar sv2;

                if (frm != null && typeModuleCode < refs.Count && typeModuleCode >= 0 &&
                    refs[typeModuleCode].GlobalScope.Locals.TryGetValue("$$" + s.TypeName, out sv2))
                {
                    return(sv2.Data);
                }

                return(-1);
            }
        }
Beispiel #6
0
        //This method returns type class data including: type class metadata (ClassData), module local ID
        //(modId) and compiled module where class is defined.
        private int ObtainTypeClass(ElaClassInstance s, out ClassData mbr, out int modId, out CodeFrame mod)
        {
            mbr   = null;
            modId = -1;
            mod   = null;

            //If a type class prefix is not set we need to obtain a type class ID using a special '$$$*' variable
            //that is initialized during type class compilation
            if (s.TypeClassPrefix == null)
            {
                //We first check if a class definition is non-local
                if (!frame.InternalClasses.TryGetValue(s.TypeClassName, out mbr))
                {
                    var sv = GetVariable("$$$" + s.TypeClassName, CurrentScope, GetFlags.NoError, s.Line, s.Column);

                    if (sv.IsEmpty() && !options.IgnoreUndefined)
                    {
                        AddError(ElaCompilerError.UnknownClass, s, s.TypeClassName);
                        return(-1);
                    }

                    //The trick is - here sv can be only an external name (we do check prior to this
                    //if a class is not local). If it is an external name that first byte contains a
                    //local index of a referenced module - that is exactly what we need here to obtain
                    //a compiled module frame (from refs array).
                    modId = sv.Address & Byte.MaxValue;

                    if (modId < refs.Count && modId >= 0)
                    {
                        mod = refs[modId];
                    }

                    return(sv.Data);
                }
                else
                {
                    var sv = GetVariable("$$$" + s.TypeClassName, CurrentScope, GetFlags.NoError, s.Line, s.Column);
                    return(sv.Data);
                }
            }
            else
            {
                //Type class prefix is set. The prefix itself should be local name (a module alias)
                var sv = GetVariable(s.TypeClassPrefix, s.Line, s.Column);

                if (sv.IsEmpty())
                {
                    return(-1);
                }

                //A name was found but this is not a module alias
                if ((sv.Flags & ElaVariableFlags.Module) != ElaVariableFlags.Module)
                {
                    AddError(ElaCompilerError.InvalidQualident, s, s.TypeClassPrefix);
                    return(-1);
                }

                //In this case we can look for a reference based on its alias (alias should be unique within
                //the current module).
                modId = frame.References[s.TypeClassPrefix].LogicalHandle;

                if (modId < refs.Count && modId >= 0)
                {
                    mod = refs[modId];
                }

                //Now we need to obtain 'data' of a type class variable - it might a type class
                //typeId if this type class is built-in.
                ScopeVar sv2;

                if (mod != null && mod.GlobalScope.Locals.TryGetValue("$$$" + s.TypeClassName, out sv2))
                {
                    return(sv.Data);
                }
                else
                {
                    return(-1);
                }
            }
        }
Beispiel #7
0
        void ClassInstance()
        {
            var block = default(ElaEquationSet);
            var ot = t;
            var list = default(List<ElaClassInstance>);

            Expect(44);
            var ci = new ElaClassInstance(t);
            ci.And = Program.Instances;
            Program.Instances = ci;
            ot = t;

            if (la.kind == 1) {
            Get();
            ci.TypeClassPrefix=t.val;
            Expect(27);
            Expect(2);
            ci.TypeClassName=t.val;
            } else if (la.kind == 2) {
            Get();
            ci.TypeClassName=t.val;
            } else SynErr(116);
            while (la.kind == 1 || la.kind == 2) {
            if (ci.TypeName != null)
            {
                if (list == null)
                {
                    list = new List<ElaClassInstance>();
                    list.Add(ci);
                }

                ci = new ElaClassInstance { TypeClassPrefix = ci.TypeClassPrefix, TypeClassName = ci.TypeClassName };
                ci.SetLinePragma(ot.line, ot.col);
                ci.And = Program.Instances;
                Program.Instances = ci;
                list.Add(ci);
            }

            if (la.kind == 1) {
                Get();
                ci.TypePrefix = t.val;
                Expect(27);
                Expect(2);
                ci.TypeName=t.val;
            } else {
                Get();
                ci.TypeName=t.val;
            }
            }
            if (la.kind == 43) {
            WhereBinding(out block);
            if (list == null)
               ci.Where = block;
            else
            {
                for (var i = 0; i < list.Count; i++)
                    list[i].Where = block;
            }

            }
        }
Beispiel #8
0
        //This function tries to autogenerate an instance (similar to derived in Haskell).
        //It can fully or partially generate it. A default instance (instance without a type) is
        //used for such purpose.
        private List<String> TryGenerateMembers(List<String> members, CodeFrame mod, ElaClassInstance inst)
        {
            if (members.Count == 0)
                return members;

            var newMem = new List<String>(members);

            for (var i = 0; i < newMem.Count; i++)
            {
                var m = newMem[i];
                var btVar = ObtainClassFunction(inst.TypeClassPrefix, inst.TypeClassName, m, inst.Line, inst.Column);

                //This is less likely but we better check this anyway
                if (btVar.IsEmpty())
                    AddError(ElaCompilerError.MemberInvalid, inst, m, inst.TypeClassName);

                var defVar = GetGlobalVariable("$default$" + m, GetFlags.NoError, inst.Line, inst.Column);

                //We dont' need to generate errors here, errors will be captured later.
                if (!defVar.IsEmpty())
                {
                    var builtin = (btVar.Flags & ElaVariableFlags.Builtin) == ElaVariableFlags.Builtin;

                    //Check if this member is implemented directly by compiler
                    if (!TryAutogenerate(defVar, inst))
                        PushVar(defVar);

                    if (!builtin)
                        PushVar(btVar);
                    else
                        cw.Emit(Op.PushI4, (Int32)btVar.Data);

                    EmitSpecName(inst.TypePrefix, "$$" + inst.TypeName, inst, ElaCompilerError.UndefinedType);
                    cw.Emit(Op.Addmbr);
                    members.Remove(m);
                }
            }

            return members;
        }
Beispiel #9
0
        void NewType()
        {
            scanner.InjectBlock();
            var extends = false;
            var opened = false;

            if (la.kind == 45) {
            Get();
            } else if (la.kind == 48) {
            Get();
            extends=true;
            } else if (la.kind == 49) {
            Get();
            opened=true;
            } else SynErr(114);
            var nt = new ElaNewtype(t) { Extends=extends,Opened=opened };
            if (la.kind == 1) {
            Get();
            nt.Prefix = t.val;
            Expect(27);
            Expect(2);
            nt.Name = t.val;
            } else if (la.kind == 2) {
            Get();
            nt.Name = t.val;
            } else SynErr(115);
            nt.And = Program.Types;
            Program.Types = nt;

            if (la.kind == 51 || la.kind == 57) {
            if (la.kind == 57) {
                Get();
                if (la.kind == 23) {
                    Get();
                }
                NewTypeConstructor(nt);
                while (la.kind == 23) {
                    Get();
                    NewTypeConstructor(nt);
                }
            } else {
                Get();
                nt.Header = true;
                Expect(1);
                nt.Flags = ProcessAttribute(t.val,nt.Flags);
                while (la.kind == 1) {
                    Get();
                    nt.Flags = ProcessAttribute(t.val,nt.Flags);
                }
            }
            }
            if (la.kind == 65) {
            Get();
            var tt = t;
            string pf;
            string nm;

            while (la.kind == 1 || la.kind == 2) {
                if (la.kind == 1) {
                    Get();
                    pf=t.val;
                    Expect(27);
                    Expect(2);
                    nm=t.val;
                } else {
                    Get();
                    pf=null;nm=t.val;
                }
                var ci = new ElaClassInstance(tt);
                ci.And = Program.Instances;
                Program.Instances = ci;
                ci.TypeName = nt.Name;
                ci.TypePrefix = nt.Prefix;
                ci.TypeClassPrefix = pf;
                ci.TypeClassName = nm;

            }
            }
            EndBlock();
        }
Beispiel #10
0
        //Some members may be generated directly by compiler. Here we check if this is the case for this
        //particular member.
        private bool TryAutogenerate(ScopeVar var, ElaClassInstance inst)
        {
            if ((var.Flags & ElaVariableFlags.Builtin) != ElaVariableFlags.Builtin)
                return false;

            switch ((ElaBuiltinKind)var.Data)
            {
                //Used to generate Bounded.maxBound constant
                case ElaBuiltinKind.GenMaxBound:
                    cw.Emit(Op.PushI4, 1);
                    //Obtain type ID, no errors, they are captured elsewhere
                    EmitSpecName(inst.TypePrefix, "$$" + inst.TypeName, inst, ElaCompilerError.None);
                    cw.Emit(Op.Api, (Int32)Api.TypeConsNumber);
                    cw.Emit(Op.Sub);

                    EmitSpecName(inst.TypePrefix, "$$" + inst.TypeName, inst, ElaCompilerError.None);
                    cw.Emit(Op.Api2, (Int32)Api.ConsCodeByIndex);
                    cw.Emit(Op.Api, (Int32)Api.ConsDefault);
                    return true;
                //Used to generate Bounded.minBound constant
                case ElaBuiltinKind.GenMinBound:
                case ElaBuiltinKind.GenDefault:
                    cw.Emit(Op.PushI4_0);
                    //Obtain type ID, no errors, they are captured elsewhere
                    EmitSpecName(inst.TypePrefix, "$$" + inst.TypeName, inst, ElaCompilerError.None);
                    cw.Emit(Op.Api2, (Int32)Api.ConsCodeByIndex);
                    cw.Emit(Op.Api, (Int32)Api.ConsDefault);
                    return true;
                default:
                    return false;
            }
        }
Beispiel #11
0
        //This method returns type class data including: type class metadata (ClassData), module local ID
        //(modId) and compiled module where class is defined.
        private int ObtainTypeClass(ElaClassInstance s, out ClassData mbr, out int modId, out CodeFrame mod)
        {
            mbr = null;
            modId = -1;
            mod = null;

            //If a type class prefix is not set we need to obtain a type class ID using a special '$$$*' variable
            //that is initialized during type class compilation
            if (s.TypeClassPrefix == null)
            {
                //We first check if a class definition is non-local
                if (!frame.InternalClasses.TryGetValue(s.TypeClassName, out mbr))
                {
                    var sv = GetVariable("$$$" + s.TypeClassName, CurrentScope, GetFlags.NoError, s.Line, s.Column);

                    if (sv.IsEmpty() && !options.IgnoreUndefined)
                    {
                        AddError(ElaCompilerError.UnknownClass, s, s.TypeClassName);
                        return -1;
                    }

                    //The trick is - here sv can be only an external name (we do check prior to this
                    //if a class is not local). If it is an external name that first byte contains a
                    //local index of a referenced module - that is exactly what we need here to obtain
                    //a compiled module frame (from refs array).
                    modId = sv.Address & Byte.MaxValue;

                    if (modId < refs.Count && modId >= 0)
                        mod = refs[modId];

                    return sv.Data;
                }
                else
                {
                    var sv = GetVariable("$$$" + s.TypeClassName, CurrentScope, GetFlags.NoError, s.Line, s.Column);
                    return sv.Data;
                }
            }
            else
            {
                //Type class prefix is set. The prefix itself should be local name (a module alias)
                var sv = GetVariable(s.TypeClassPrefix, s.Line, s.Column);

                if (sv.IsEmpty())
                    return -1;

                //A name was found but this is not a module alias
                if ((sv.Flags & ElaVariableFlags.Module) != ElaVariableFlags.Module)
                {
                    AddError(ElaCompilerError.InvalidQualident, s, s.TypeClassPrefix);
                    return -1;
                }

                //In this case we can look for a reference based on its alias (alias should be unique within
                //the current module).
                modId = frame.References[s.TypeClassPrefix].LogicalHandle;

                if (modId < refs.Count && modId >= 0)
                    mod = refs[modId];

                //Now we need to obtain 'data' of a type class variable - it might a type class
                //typeId if this type class is built-in.
                ScopeVar sv2;

                if (mod != null && mod.GlobalScope.Locals.TryGetValue("$$$" + s.TypeClassName, out sv2))
                    return sv.Data;
                else
                    return -1;
            }
        }
Beispiel #12
0
        //Here we obtain type information - local ID of a module where a type is defined.
        private int ObtainType(ElaClassInstance s, out int typeModuleCode)
        {
            typeModuleCode = -1;

            if (s.TypePrefix == null)
            {
                //First we check that type is not defined locally
                if (!frame.InternalTypes.ContainsKey(s.TypeName))
                {
                    var sv = GetVariable("$$" + s.TypeName, CurrentScope, GetFlags.NoError, s.Line, s.Column);

                    if (sv.IsEmpty() && !options.IgnoreUndefined)
                    {
                        AddError(ElaCompilerError.UndefinedType, s, s.TypeName);
                        return -1;
                    }

                    //The trick is - here sv can be only an external name (we do check prior to this
                    //if a type is not local). If it is an external name that first byte contains a
                    //local index of a referenced module - and typeModuleCode is effectly a local ID of a module
                    //where a type is declared
                    typeModuleCode = sv.Address & Byte.MaxValue;
                    return sv.Data;
                }
                else
                {
                    var sv = GetVariable("$$" + s.TypeName, CurrentScope, GetFlags.NoError, s.Line, s.Column);
                    return sv.Data;
                }
            }
            else
            {
                //TypePrefix is a local name that should correspond to a module alias
                var sv = GetVariable(s.TypePrefix, s.Line, s.Column);

                if (sv.IsEmpty())
                    return -1;

                //A name exists but this is not a module alias
                if ((sv.Flags & ElaVariableFlags.Module) != ElaVariableFlags.Module)
                {
                    AddError(ElaCompilerError.InvalidQualident, s, s.TypePrefix);
                    return -1;
                }

                //Obtain a local ID of a module based on TypePrefix (which is module alias
                //that should be unique within this module).
                var frm = frame.References[s.TypePrefix];
                typeModuleCode = frm.LogicalHandle;

                //Now we need to obtain type variable data - it may have the typeId of a type
                //if this is a built-in type.
                ScopeVar sv2;

                if (frm != null && typeModuleCode < refs.Count && typeModuleCode >= 0 &&
                    refs[typeModuleCode].GlobalScope.Locals.TryGetValue("$$" + s.TypeName, out sv2))
                    return sv2.Data;

                return -1;
            }
        }
Beispiel #13
0
        //An entry method for instance compilation
        private void CompileInstances(ElaClassInstance s, LabelMap map)
        {
            var ins = s;

            //First we need to compile default instances so that
            //other instances in this class will be able to use them
            while (ins != null)
            {
                if (ins.TypeName == null)
                    CompileInstanceBody(ins, map);

                ins = ins.And;
            }

            ins = s;

            //Now we compile specific instances
            while (ins != null)
            {
                if (ins.TypeName != null)
                    CompileInstanceBody(ins, map);

                ins = ins.And;
            }
        }
Beispiel #14
0
        //Main method for instance compilation
        private void CompileInstanceBody(ElaClassInstance s, LabelMap map)
        {
            //Obtain type class data
            var mod = default(CodeFrame);
            var mbr = default(ClassData);
            var modId = -1;
            var classId = ObtainTypeClass(s, out mbr, out modId, out mod);

            //It's OK if mbr (class members) is null. It is not null only if a class declaration is local.
            //However mod shouldn't be null in such a case (non-local class), and we will use it to obtain
            //class members. If mod==null and mbr==null, or mod doesn't have our class, than we really can't find it.
            var notFound = mbr == null && (mod == null || !mod.InternalClasses.TryGetValue(s.TypeClassName, out mbr));

            //Type class not found, nothing else to do
            if (notFound)
            {
                if (!options.IgnoreUndefined)
                    AddError(ElaCompilerError.UnknownClass, s, s.TypeClassName);
                else if (s.TypeName != null) //It is valid if this is a 'default' instance
                {
                    //Add an instance anyway - the IgnoreUndefine flag is usually set just to gather some module metadata,
                    //so we need to populate it anyway.
                    frame.InternalInstances.Add(new InstanceData(s.TypeName, s.TypeClassName, -1, modId, s.Line, s.Column));
                }
            }
            else
            {
                //Now we need to obtain a local ID of a module where type is defined
                var typeModuleCode = -1;
                var typeId = -1;

                //Type name is null if this is a default instance
                if (s.TypeName != null)
                {
                    typeId = ObtainType(s, out typeModuleCode);

                    //Add new instance registration information
                    frame.InternalInstances.Add(new InstanceData(s.TypeName, s.TypeClassName, typeModuleCode, modId, s.Line, s.Column));
                }

                //Fill a list of classMembers, this list is used in this method to validate
                //whether all members of a class have an implementation
                var classMembers = new List<String>(mbr.Members.Length);

                for (var i = 0; i < mbr.Members.Length; i++)
                    classMembers.Add(mbr.Members[i].Name);

                if (s.Where != null)
                    foreach (var b in s.Where.Equations)
                    {
                        var err = false;

                        //Patterns are now allowed in member bindings
                        if (!b.IsFunction() && b.Left.Type != ElaNodeType.NameReference)
                        {
                            AddError(ElaCompilerError.MemberNoPatterns, b.Left, FormatNode(b.Left));
                            err = true;
                        }

                        var name = b.GetLeftName();

                        //Only member functions can be declared inside instance
                        if (!classMembers.Contains(name))
                        {
                            AddError(ElaCompilerError.MemberInvalid, b, name, s.TypeClassName);
                            err = true;
                        }

                        //Compile member function
                        if (!err)
                        {
                            classMembers.Remove(name);

                            //It's OK if s.TypeName is null, this situation (default instance) is handled in this method
                            CompileInstanceMember(s.TypeClassName, s.TypeClassPrefix, b, map, s.TypePrefix, s.TypeName);
                        }
                    }

                //If this is not a default instance, we can try to autogenerate it.
                if (s.TypeName != null)
                    classMembers = TryGenerateMembers(classMembers, mod, s);

                //Not all of the members are implemented, which is an error if an instance is
                //not generated by a compiler or this is a 'default' instance.
                if (s.TypeName != null && !IsBuiltIn(classId, typeId) && classMembers.Count > 0)
                {
                    if (s.Where != null)
                        AddError(ElaCompilerError.MemberNotAll, s, s.TypeClassName, s.TypeClassName + " " + s.TypeName);
                    else
                    {
                        //If a 'where' clause is not specified at all we need to generate a better
                        //error message (most likely this instance appears in 'deriving' clause).
                        AddError(ElaCompilerError.UnableDerive, s, s.TypeClassName, s.TypeName);
                    }
                }
            }
        }