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);
            }
        }
Beispiel #2
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);
        }