Пример #1
0
        public override string VisitEnumTypeExpr(AstEnumTypeExpr en, int data = 0)
        {
            var body = string.Join("\n", en.Declarations.Select(m => m.Accept(this)));
            var head = $"enum";

            if (en.Parameters != null && en.Parameters.Count > 0)
            {
                head += $"({string.Join(", ", en.Parameters.Select(p => p.Accept(this)))})";
            }
            // return $"{head} {{\n{body.Indent(4)}\n}}";
            return(head);
        }
Пример #2
0
        public AstEnumValueExpr(AstEnumTypeExpr ed, AstEnumMemberNew member, AstExpression arg = null, ILocation loc = null)
            : base(loc)
        {
            Member   = member;
            Type     = ed.EnumType;
            Argument = arg;
            EnumDecl = ed;

            if (ed.IsFlags)
            {
                Value = new EnumValue(ed.EnumType, member);
            }
        }
Пример #3
0
 private void AddEnum(AstEnumTypeExpr en)
 {
     mAllEnums.Add(en);
     mUnresolvedEnums.Enqueue(en);
 }
Пример #4
0
 public EnumType(AstEnumTypeExpr en, bool isCopy, object[] args = null) : base(false)
 {
     Declaration = en;
     IsCopy      = isCopy;
     Arguments   = args ?? en.Parameters.Select(p => p.Value).ToArray();
 }
Пример #5
0
 public virtual ReturnType VisitEnumTypeExpr(AstEnumTypeExpr expr, DataType data           = default) => default;
Пример #6
0
 private AstEnumTypeExpr InstantiatePolyEnum(AstEnumTypeExpr decl, List <(CheezType type, object value)> args, ILocation location = null)
Пример #7
0
        private AstExpression InferTypeEnumTypeExpr(AstEnumTypeExpr expr)
        {
            if (expr.IsPolyInstance)
            {
            }
            else
            {
                expr.SubScope = new Scope("enum", expr.Scope);
                if (expr.Parent is AstConstantDeclaration c)
                {
                    expr.Name = c.Name.Name;
                }
            }

            bool isCopy = false;

            if (!expr.IsPolymorphic && expr.TryGetDirective("copy", out var d))
            {
                isCopy = true;
                foreach (var arg in d.Arguments)
                {
                    arg.AttachTo(expr, expr.SubScope);
                    ResolveTypeNow(arg, out var t);
                    isCopy &= t.IsCopy;
                }
            }

            expr.TagType = IntType.GetIntType(8, true);
            if (expr.TryGetDirective("tag_type", out var bt))
            {
                if (bt.Arguments.Count != 1)
                {
                    ReportError(bt, $"#tag_type requires one argument");
                }
                else
                {
                    var arg = bt.Arguments[0];
                    arg.AttachTo(expr);
                    arg = InferType(arg, CheezType.Type);

                    if (!arg.Type.IsErrorType)
                    {
                        if (arg.Type != CheezType.Type)
                        {
                            ReportError(arg, $"Argument must be an int type");
                        }
                        else if (arg.Value is IntType i)
                        {
                            expr.TagType = i;
                        }
                        else
                        {
                            ReportError(arg, $"Argument must be an int type");
                        }
                    }
                }
            }

            if (expr.TryGetDirective("untagged", out var _))
            {
                expr.Untagged = true;
                expr.TagType  = null;
            }

            if (expr.TryGetDirective("repr", out var repr))
            {
                if (repr.Arguments.Count != 1 || !(repr.Arguments[0] is AstStringLiteral str))
                {
                    ReportError(bt, $"#repr requires one string argument");
                }
                else
                {
                    var val = str.StringValue;
                    if (val == "C")
                    {
                        expr.IsReprC = true;
                    }
                    else
                    {
                        ReportError(repr, $"unknown repr");
                    }
                }
            }

            // setup scopes and separate members
            expr.Members = new List <AstEnumMemberNew>();
            foreach (var decl in expr.Declarations)
            {
                decl.Scope = expr.SubScope;

                switch (decl)
                {
                case AstConstantDeclaration con:
                    throw new System.Exception();

                case AstVariableDecl mem:
                    var m = new AstEnumMemberNew(expr, mem, expr.Members.Count);
                    expr.Members.Add(m);
                    var(ok, other) = expr.SubScope.DefineSymbol(m);
                    if (!ok)
                    {
                        ReportError(mem.Name, $"A member with this name already exists", ("Other member here: ", other));
                    }
                    break;
                }
            }

            if (expr.IsPolymorphic)
            {
                // @todo
                foreach (var p in expr.Parameters)
                {
                    p.Scope          = expr.Scope;
                    p.TypeExpr.Scope = expr.Scope;
                    p.TypeExpr       = ResolveTypeNow(p.TypeExpr, out var t);
                    p.Type           = t;

                    ValidatePolymorphicParameterType(p, p.Type);

                    expr.SubScope.DefineTypeSymbol(p.Name.Name, new PolyType(p.Name.Name, true));
                }

                expr.Type  = CheezType.Type;
                expr.Value = new GenericEnumType(expr, expr.Name);
                return(expr);
            }

            foreach (var decl in expr.Declarations)
            {
                if (decl is AstConstantDeclaration con)
                {
                    AnalyseConstantDeclaration(con);
                }
            }

            var enumType = new EnumType(expr, isCopy);

            AddEnum(expr);

            if (expr.HasDirective("flags"))
            {
                expr.IsFlags = true;
                expr.IsReprC = true;

                // GlobalScope.DefineBinaryOperator(new EnumFlagsCompineOperator(enumType));
                // GlobalScope.DefineBinaryOperator(new EnumFlagsTestOperator(enumType));
                expr.Scope.DefineBinaryOperator(new EnumFlagsCombineOperator(enumType));
                expr.Scope.DefineBinaryOperator(new EnumFlagsAndOperator(enumType));
                expr.Scope.DefineBinaryOperator(new EnumFlagsTestOperator(enumType));
                expr.Scope.DefineUnaryOperator(new EnumFlagsNotOperator(enumType));
            }

            expr.Type  = CheezType.Type;
            expr.Value = enumType;
            return(expr);
        }
Пример #8
0
        private void ComputeEnumMembers(AstEnumTypeExpr expr)
        {
            if (expr.MembersComputed)
            {
                return;
            }
            expr.MembersComputed = true;

            BigInteger value      = 0;
            var        usedValues = new Dictionary <BigInteger, AstEnumMemberNew>();

            foreach (var mem in expr.Members)
            {
                var memDecl = mem.Decl;

                if (!(memDecl.Pattern is AstIdExpr memName))
                {
                    ReportError(memDecl.Pattern, $"Only single names allowed");
                    continue;
                }

                if (memDecl.Directives != null)
                {
                    foreach (var dir in memDecl.Directives)
                    {
                        InferTypeAttributeDirective(dir, memDecl, memDecl.Scope);
                    }
                }

                if (memDecl.TypeExpr != null)
                {
                    memDecl.TypeExpr.AttachTo(memDecl);
                    memDecl.TypeExpr = ResolveTypeNow(memDecl.TypeExpr, out var t);
                    memDecl.Type     = t;

                    // @todo: check if type is valid as enum member, eg no void
                }

                if (memDecl.Initializer != null)
                {
                    memDecl.Initializer.AttachTo(memDecl);
                    memDecl.Initializer = InferType(memDecl.Initializer, expr.TagType);
                    ConvertLiteralTypeToDefaultType(memDecl.Initializer, expr.TagType);
                    memDecl.Initializer = CheckType(memDecl.Initializer, expr.TagType);

                    if (memDecl.Initializer.Type is IntType i)
                    {
                        if (memDecl.Initializer.IsCompTimeValue)
                        {
                            value = ((NumberData)memDecl.Initializer.Value).IntValue;
                            CheckValueRangeForType(i, memDecl.Initializer.Value, memDecl.Initializer);
                        }
                        else
                        {
                            ReportError(memDecl.Initializer, $"Value of enum member has to be an constant integer");
                        }
                    }
                }

                if (!expr.IsPolymorphic && expr.EnumType.IsCopy && (!memDecl.Type?.IsCopy ?? false))
                {
                    ReportError(memDecl, "Member is not copyable");
                }

                if (usedValues.TryGetValue(value, out var other))
                {
                    if (other.AssociatedType != mem.AssociatedType)
                    {
                        ReportError(memDecl,
                                    $"Member has value {value} which is already being used by another member with different type",
                                    ("Other member here:", other.Location));
                    }
                }
                else
                {
                    usedValues.Add(value, mem);
                }

                if (memDecl.Type != null)
                {
                    ComputeTypeMembers(memDecl.Type);
                }

                if (expr.IsFlags && memDecl.Initializer == null && value != 0 && !value.IsPowerOfTwo())
                {
                    ReportError(memDecl, $"Member would have a value of '{value}', but this is not a power of two, so please provide a custom value for this member");
                }
                mem.Value = NumberData.FromBigInt(value);

                if (expr.IsFlags)
                {
                    if (value == 0)
                    {
                        value += 1;
                    }
                    else if (value.IsPowerOfTwo())
                    {
                        value *= 2;
                    }
                }
                else
                {
                    value += 1;
                }
            }

            if (expr.IsReprC)
            {
                foreach (var mem in expr.Members)
                {
                    if (mem.AssociatedType != null)
                    {
                        ReportError(mem.Location, $"Member can't have an associated value in repr c enum");
                    }
                }
            }
        }