コード例 #1
0
ファイル: Builder.Types.cs プロジェクト: ngoffee/ela
        //Builds a list of attribute headers for types
        private void CompileHeaders(ElaNewtype v)
        {
            var t    = v;
            var oldt = default(ElaNewtype);

            while (t != null)
            {
                if (t.Header)
                {
                    if (oldt == null || t.Extends != oldt.Extends || t.Opened != oldt.Opened)
                    {
                        AddError(ElaCompilerError.TypeHeaderNotConnected, t, t.Name);
                    }
                    else
                    {
                        oldt.Flags = t.Flags;
                    }
                }
                else
                {
                    oldt = t;
                }

                t = t.And;
            }
        }
コード例 #2
0
ファイル: Builder.Types.cs プロジェクト: ngoffee/ela
 //An entry method for type compilation. Ensures that types ('type') are
 //always compiled before type extensions ('data').
 private void CompileTypes(ElaNewtype v, LabelMap map)
 {
     CompileHeaders(v);
     CompileTypeHeaderOnly(v, map);
     CompileDataHeaderOnly(v, map);
     CompileTypeBodyOnly(v, map);
     CompileDataBodyOnly(v, map);
 }
コード例 #3
0
ファイル: Builder.Types.cs プロジェクト: ngoffee/ela
 private void CompileTypeBody(ElaNewtype v, LabelMap map)
 {
     if (v.HasBody)
     {
         for (var i = 0; i < v.Constructors.Count; i++)
         {
             var c  = v.Constructors[i];
             var cf = v.ConstructorFlags[i];
             cf = cf == ElaVariableFlags.None ? v.Flags : cf | v.Flags;
             CompileConstructor(v.Name, v.ScopeVar, c, cf, v.TypeModuleId);
         }
     }
 }
コード例 #4
0
ファイル: Builder.Types.cs プロジェクト: ngoffee/ela
        //This method only compiles types declared through 'type' keyword
        //and not type extensions ('data' declarations).
        private void CompileTypeBodyOnly(ElaNewtype nt, LabelMap map)
        {
            var v = nt;

            while (v != null)
            {
                if (!v.Extends && !v.Header)
                {
                    CompileTypeBody(v, map);
                }

                v = v.And;
            }
        }
コード例 #5
0
ファイル: Builder.Types.cs プロジェクト: ngoffee/ela
        //Checks if a constructor is actually a list constructor which implementation can be optimized.
        private bool IsCons(ElaExpression exp, ElaNewtype t)
        {
            if (exp.Type != ElaNodeType.Juxtaposition)
            {
                return(false);
            }

            var j = (ElaJuxtaposition)exp;

            //We check that a constructor is in the form 'a :: a'
            return(j.Parameters.Count == 2 &&
                   j.Parameters[0].Type == ElaNodeType.NameReference &&
                   j.Parameters[1].Type == ElaNodeType.NameReference &&
                   !Char.IsUpper(j.Parameters[0].GetName()[0]) &&
                   !Char.IsUpper(j.Parameters[1].GetName()[0]));
        }
コード例 #6
0
ファイル: Builder.Types.cs プロジェクト: ngoffee/ela
        //Main method for type compilation
        private void CompileTypeHeader(ElaNewtype v, LabelMap map)
        {
            //We need to obtain typeId for a type
            var tc    = -1;
            var sca   = -1;
            var flags = v.Flags;

            //A body may be null only if this is a built-in type
            if (!v.HasBody && v.Extends)
            {
                AddError(ElaCompilerError.ExtendsNoDefinition, v, v.Name);
            }
            else if (!v.HasBody)
            {
                tc  = (Int32)TCF.GetTypeCode(v.Name);
                tc  = tc == 0 ? -1 : tc;
                sca = AddVariable("$$" + v.Name, v, flags | ElaVariableFlags.ClosedType | ElaVariableFlags.CompilerGenerated, tc);
                var sv = GetVariable("$$" + v.Name, v.Line, v.Column);

                //OK, type is built-in
                if (tc > 0)
                {
                    //We add a special variable that contains a global type ID
                    cw.Emit(Op.PushI4, tc);
                    PopVar(sca);
                }
            }
            else
            {
                var tf = flags;

                if (!v.Opened)
                {
                    tf |= ElaVariableFlags.ClosedType;
                }

                sca = v.Extends ? AddVariable() : AddVariable("$$" + v.Name, v, tf | ElaVariableFlags.CompilerGenerated, -1);
            }

            //Type is already declared within the same module (types from different
            //modules can shadow each, so this is perfectly OK).
            if (!v.Extends && frame.InternalTypes.ContainsKey(v.Name))
            {
                AddError(ElaCompilerError.TypeAlreadyDeclared, v, v.Name);
                frame.InternalTypes.Remove(v.Name);
            }

            if (v.Prefix != null && !v.Extends)
            {
                AddError(ElaCompilerError.InvalidTypeDefinition, v);
            }

            if (!v.Extends)
            {
                frame.InternalTypes.Add(v.Name, tc);
            }

            AddLinePragma(v);

            //-1 mean "this" module (considered by default).
            var typeModuleId = -1;

            //Add a type var for a non built-in type with a body
            if (tc == -1)
            {
                //Add a special variable with global type ID which will be calculated at run-time
                if (v.Extends)
                {
                    var sv = EmitSpecName(v.Prefix, "$$" + v.Name, v, ElaCompilerError.UndefinedType, out typeModuleId);

                    //We can only extend type that are explicitly declared as open
                    if ((sv.Flags & ElaVariableFlags.ClosedType) == ElaVariableFlags.ClosedType)
                    {
                        AddError(ElaCompilerError.UnableExtendOpenType, v, v.Name);
                    }
                }
                else
                {
                    cw.Emit(Op.Typeid, AddString(v.Name));
                }

                PopVar(sca);
                v.TypeModuleId = typeModuleId;
                v.ScopeVar     = sca;

                //if (v.HasBody)
                //{
                //    for (var i = 0; i < v.Constructors.Count; i++)
                //    {
                //        var c = v.Constructors[i];
                //        var cf = v.ConstructorFlags[i];
                //        cf = cf == ElaVariableFlags.None ? flags : cf|flags;
                //        CompileConstructor(v.Name, sca, c, cf, typeModuleId);
                //    }
                //}
            }
            else
            {
                cw.Emit(Op.Nop);
            }
        }