Exemplo n.º 1
0
        public override ISemantReturn <ABT.ExprType> DecorateType(ABT.Env env, ABT.ExprType targetType)
        {
            var isConst    = this.TypeQuals.Contains(TypeQual.CONST);
            var isVolatile = this.TypeQuals.Contains(TypeQual.VOLATILE);

            return(SemantReturn.Create(env, new ABT.PointerType(targetType, isConst, isVolatile)));
        }
Exemplo n.º 2
0
        public ISemantReturn <ImmutableList <Tuple <Option <String>, ExprType> > > GetMembers(Env env, ImmutableList <StructDecln> memberDeclns)
        {
            var result = memberDeclns.Aggregate(ImmutableList <Tuple <Option <String>, ExprType> > .Empty, (acc, decln) => acc.AddRange(Semant(decln.GetMemberDeclns, ref env))
                                                );

            return(SemantReturn.Create(env, result));
        }
Exemplo n.º 3
0
        public ISemantReturn <ExprType> GetParamType(Env env)
        {
            var baseType = Semant(this.DeclnSpecs.GetExprType, ref env);
            var type     = Semant(this.ParamDeclr.DecorateType, baseType, ref env);

            return(SemantReturn.Create(env, type));
        }
Exemplo n.º 4
0
        public ISemantReturn <ImmutableList <Tuple <Env, ExternDecln> > > GetExternDecln(Env env)
        {
            var declns       = Semant(GetDeclns, ref env);
            var externDeclns = declns.ConvertAll(_ => Tuple.Create(_.Item1, _.Item2 as ExternDecln));

            return(SemantReturn.Create(env, externDeclns));
        }
Exemplo n.º 5
0
        public ISemantReturn <ExprType> GetExprType(Env env)
        {
            var baseType = Semant(this.SpecQualList.GetExprType, ref env);
            var type     = Semant(this.AbstractDeclr.DecorateType, baseType, ref env);

            return(SemantReturn.Create(env, type));
        }
Exemplo n.º 6
0
        public ISemantReturn <ImmutableList <Tuple <Env, ExternDecln> > > GetExternDecln(Env env)
        {
            var storageClass = this.Specs.GetStorageClass();
            var baseType     = Semant(this.Specs.GetExprType, ref env);
            var name         = this.Declr.Name;
            var type         = Semant(this.Declr.DecorateType, baseType, ref env);

            var funcType = type as FunctionType;

            if (funcType == null)
            {
                throw new InvalidOperationException("Expected a function Type.");
            }

            switch (storageClass)
            {
            case StorageClass.AUTO:
            case StorageClass.EXTERN:
            case StorageClass.STATIC:
                env = env.PushEntry(Env.EntryKind.GLOBAL, name, type);
                break;

            case StorageClass.TYPEDEF:
            default:
                throw new InvalidOperationException("Invalid storage class specifier for function definition.");
            }

            env = env.InScope();
            env = env.SetCurrentFunction(funcType);
            var stmt = SemantStmt(this.Stmt.GetStmt, ref env);

            env = env.OutScope();

            return(SemantReturn.Create(env, ImmutableList.Create(Tuple.Create(env, new ABT.FuncDef(name, storageClass, funcType, stmt) as ExternDecln))));
        }
Exemplo n.º 7
0
        public ISemantReturn <ABT.TranslnUnit> GetTranslnUnit()
        {
            var env          = new Env();
            var externDeclns = this.Declns.Aggregate(ImmutableList <Tuple <Env, ExternDecln> > .Empty, (acc, externDecln) => acc.AddRange(Semant(externDecln.GetExternDecln, ref env))
                                                     );

            return(SemantReturn.Create(env, new ABT.TranslnUnit(externDeclns.ToList())));
        }
Exemplo n.º 8
0
        public override ISemantReturn <ABT.Initr> GetInitr(ABT.Env env)
        {
            var initrs = this.Initrs.ConvertAll(
                initr => Semant(initr.GetInitr, ref env)
                );

            return(SemantReturn.Create(env, new ABT.InitList(initrs.ToList())));
        }
Exemplo n.º 9
0
        public override ISemantReturn <ExprType> GetExprType(Env env)
        {
            if (this.Enumrs.IsNone)
            {
                // If no enumerators provided: must find enum Type in the current environment.

                if (this.Name.IsNone)
                {
                    throw new InvalidProgramException("This should not pass the parser.");
                }

                var name     = this.Name.Value;
                var entryOpt = env.Find($"enum {name}");

                if (entryOpt.IsNone || entryOpt.Value.Kind != Env.EntryKind.TYPEDEF)
                {
                    throw new InvalidOperationException($"enum {name} has not been defined.");
                }

                return(SemantReturn.Create(env, new LongType()));
            }

            // If enumerators are provided: add names to environment
            Int32 offset = 0;

            foreach (var enumr in this.Enumrs.Value)
            {
                if (enumr.Init.IsSome)
                {
                    // If the user provides an initialization Value, use it.
                    var init = SemantExpr(enumr.Init.Value, ref env);
                    init = ABT.TypeCast.MakeCast(init, new LongType());
                    if (!init.IsConstExpr)
                    {
                        throw new InvalidOperationException("Enumerator initialization must have a constant Value.");
                    }
                    offset = ((ConstLong)init).Value;
                }

                env = env.PushEnum(enumr.Name, new LongType(), offset);

                offset++;
            }

            // If the user provides a name to the enum, add it to the environment.
            if (this.Name.IsSome)
            {
                var typeName = $"enum {this.Name.Value}";

                if (env.FindInCurrentScope(typeName).IsSome)
                {
                    throw new InvalidOperationException($"{typeName} is already defined.");
                }
                env = env.PushEntry(Env.EntryKind.TYPEDEF, typeName, new LongType());
            }

            return(SemantReturn.Create(env, new LongType()));
        }
Exemplo n.º 10
0
        public ISemantReturn <ABT.ExprType> DecorateType(ABT.Env env, ABT.ExprType baseType)
        {
            var type = this.TypeModifiers
                       .Reverse()  // The first Type modifier is nearest to the symbol name, which indicates the outmost Type.
                       .Aggregate( // Wrap up the Type based on the Type modifiers.
                baseType, (currentType, typeModifier) => Semant(typeModifier.DecorateType, currentType, ref env)
                );

            return(SemantReturn.Create(env, type));
        }
Exemplo n.º 11
0
        public ISemantReturn <ImmutableList <Tuple <Option <String>, ABT.ExprType> > > GetNamesAndTypes(ABT.Env env)
        {
            var namesAndTypes = this.ParamDeclns.ConvertAll(
                paramDecln =>
                Tuple.Create(
                    paramDecln.ParamDeclr.Name,
                    Semant(paramDecln.GetParamType, ref env)
                    )
                );

            return(SemantReturn.Create(env, namesAndTypes));
        }
Exemplo n.º 12
0
        public ISemantReturn <Tuple <ABT.ExprType, Option <ABT.Initr> > > GetDecoratedTypeAndInitr(ABT.Env env, ABT.ExprType baseType)
        {
            // Get the Type based on the declarator. Note that this might be an incomplete array.
            var type = Semant(this.Declr.DecorateType, baseType, ref env);

            Option <ABT.Initr> initrOption;

            if (this.Initr.IsNone)
            {
                initrOption = Option <ABT.Initr> .None;
            }
            else
            {
                // If an initializer is present:

                var initr = Semant(this.Initr.Value.GetInitr, ref env);

                // Check that the initializer conforms to the Type.
                initr = initr.ConformType(type);

                // If the object is an incomplete array, we must determine the length based on the initializer.
                if (type.Kind == ABT.ExprTypeKind.INCOMPLETE_ARRAY)
                {
                    // Now we need to determine the length.
                    // Find the last element in the Init list.
                    var lastOffset = -1;
                    initr.Iterate(type, (offset, _) => { lastOffset = offset; });

                    if (lastOffset == -1)
                    {
                        throw new InvalidOperationException("Cannot determine the length of the array based on an empty initializer list.");
                    }

                    var elemType = ((ABT.IncompleteArrayType)type).ElemType;

                    var numElems = 1 + lastOffset / ((ABT.IncompleteArrayType)type).ElemType.SizeOf;

                    type = new ABT.ArrayType(elemType, numElems);
                }

                initrOption = Option.Some(initr);
            }

            // Now everything is created. Check that the Type is complete.
            if (!type.IsComplete)
            {
                throw new InvalidOperationException("Cannot create an object with an incomplete Type.");
            }

            return(SemantReturn.Create(env, Tuple.Create(type, initrOption)));
        }
Exemplo n.º 13
0
        public override ISemantReturn <ABT.ExprType> DecorateType(ABT.Env env, ABT.ExprType returnType)
        {
            if (this.ParamTypeList.IsNone)
            {
                return(SemantReturn.Create(env, ABT.FunctionType.Create(returnType)));
            }

            var paramTypeList = this.ParamTypeList.Value;

            var namesAndTypes = Semant(paramTypeList.GetNamesAndTypes, ref env);
            var hasVarArgs    = paramTypeList.HasVarArgs;

            return(SemantReturn.Create(env, ABT.FunctionType.Create(returnType, namesAndTypes, hasVarArgs)));
        }
Exemplo n.º 14
0
        public ISemantReturn <ImmutableList <Tuple <Env, ABT.Decln> > > GetDeclns(Env env)
        {
            var storageClass = this.DeclnSpecs.GetStorageClass();
            var baseType     = Semant(this.DeclnSpecs.GetExprType, ref env);

            var declns = this.InitDeclrs.ConvertAll(
                initDeclr => {
                var typeAndInitr = Semant(initDeclr.GetDecoratedTypeAndInitr, baseType, ref env);
                var type         = typeAndInitr.Item1;
                var initr        = typeAndInitr.Item2;
                var name         = initDeclr.GetName();

                // Add the new symbol into the environment.
                Env.EntryKind kind;
                switch (storageClass)
                {
                case StorageClass.AUTO:
                    if (env.IsGlobal())
                    {
                        kind = Env.EntryKind.GLOBAL;
                    }
                    else
                    {
                        kind = Env.EntryKind.STACK;
                    }
                    break;

                case StorageClass.EXTERN:
                    kind = Env.EntryKind.GLOBAL;
                    break;

                case StorageClass.STATIC:
                    kind = Env.EntryKind.GLOBAL;
                    break;

                case StorageClass.TYPEDEF:
                    kind = Env.EntryKind.TYPEDEF;
                    break;

                default:
                    throw new InvalidOperationException();
                }
                env = env.PushEntry(kind, name, type);

                return(Tuple.Create(env, new ABT.Decln(name, storageClass, type, initr)));
            }
                );

            return(SemantReturn.Create(env, declns));
        }
Exemplo n.º 15
0
        public override ISemantReturn <ExprType> GetExprType(Env env)
        {
            var entryOpt = env.Find(this.Name);

            if (entryOpt.IsNone)
            {
                throw new InvalidProgramException("This should not pass the parser.");
            }
            var entry = entryOpt.Value;

            if (entry.Kind != Env.EntryKind.TYPEDEF)
            {
                throw new InvalidProgramException("This should not pass the parser.");
            }
            return(SemantReturn.Create(env, entry.Type));
        }
Exemplo n.º 16
0
        public ISemantReturn <ExprType> GetExprType(Env env)
        {
            Boolean isConst    = this.TypeQuals.Contains(TypeQual.CONST);
            Boolean isVolatile = this.TypeQuals.Contains(TypeQual.VOLATILE);

            // If no Type specifier is given, assume long Type.
            if (this.TypeSpecs.IsEmpty)
            {
                return(SemantReturn.Create(env, new LongType(isConst, isVolatile)));
            }

            // If every Type specifier is basic, go to the lookup table.
            if (this.TypeSpecs.All(typeSpec => typeSpec.Kind != TypeSpecKind.NON_BASIC))
            {
                var basicTypeSpecKinds =
                    this.TypeSpecs
                    .ConvertAll(typeSpec => typeSpec.Kind)
                    .Distinct()
                    .ToImmutableSortedSet();

                foreach (var pair in BasicTypeSpecLookupTable)
                {
                    if (pair.Key.SetEquals(basicTypeSpecKinds))
                    {
                        return(SemantReturn.Create(env, pair.Value));
                    }
                }

                throw new InvalidOperationException("Invalid Type specifier set.");
            }

            // If there is a non-basic Type specifier, semant it.
            if (this.TypeSpecs.Count != 1)
            {
                throw new InvalidOperationException("Invalid Type specifier set.");
            }

            var type = Semant(this.TypeSpecs[0].GetExprType, ref env);

            return(SemantReturn.Create(env, type.GetQualifiedType(isConst, isVolatile)));
        }
Exemplo n.º 17
0
        public ISemantReturn <ImmutableList <Tuple <Option <String>, ExprType> > > GetMemberDeclns(Env env)
        {
            // Semant specifier-qualifier-list.
            var baseType = Semant(this.SpecQualList.GetExprType, ref env);

            // Decorate types, based on struct declarators.
            var memberTypes =
                this.StructDeclrs
                .ConvertAll(
                    structDeclr =>
                    Semant(structDeclr.DecorateType, baseType, ref env)
                    );

            // Get (optional) member names.
            var memberNames =
                this.StructDeclrs
                .ConvertAll(
                    structDeclr => structDeclr.Name
                    );

            return(SemantReturn.Create(env, memberNames.Zip(memberTypes, Tuple.Create).ToImmutableList()));
        }
Exemplo n.º 18
0
        public override ISemantReturn <ABT.ExprType> DecorateType(ABT.Env env, ABT.ExprType elemType)
        {
            if (this.NumElems.IsNone)
            {
                return(SemantReturn.Create(env, new ABT.IncompleteArrayType(elemType)));
            }

            // Get number of elements.
            // Be careful: the environment might change.
            var numElems = SemantExpr(this.NumElems.Value, ref env);

            // Try to cast number of elements to a integer.
            // TODO: allow float???
            numElems = ABT.TypeCast.MakeCast(numElems, new ABT.LongType(true, false));

            if (!numElems.IsConstExpr)
            {
                throw new InvalidOperationException("Number of elements of an array must be constant.");
            }

            return(SemantReturn.Create(env, new ABT.ArrayType(elemType, ((ABT.ConstLong)numElems).Value)));
        }
Exemplo n.º 19
0
        public override ISemantReturn <ABT.Initr> GetInitr(ABT.Env env)
        {
            var expr = SemantExpr(this.Expr, ref env);

            return(SemantReturn.Create(env, new ABT.InitExpr(expr)));
        }
Exemplo n.º 20
0
        public override ISemantReturn <ExprType> GetExprType(Env env)
        {
            StructOrUnionType type;

            // If no members provided, then we need to find the Type in the current environment.
            if (this.MemberDeclns.IsNone)
            {
                if (this.Name.IsNone)
                {
                    throw new InvalidProgramException("This should not pass the parser");
                }

                var name     = this.Name.Value;
                var typeName = (this.StructOrUnion == StructOrUnion.STRUCT ? "struct" : "union") + $" {name}";

                // Try to find Type name in the current environment.
                var entryOpt = env.Find(typeName);

                // If name not found: create an incomplete Type and add it into the environment.
                if (entryOpt.IsNone)
                {
                    type = StructOrUnionType.CreateIncompleteType(this.StructOrUnion, name);
                    env  = env.PushEntry(Env.EntryKind.TYPEDEF, typeName, type);
                    return(SemantReturn.Create(env, type));
                }

                // If name found: fetch it.
                if (entryOpt.Value.Kind != Env.EntryKind.TYPEDEF)
                {
                    throw new InvalidProgramException("A struct or union in env that is not typedef? This should not appear.");
                }

                return(SemantReturn.Create(env, entryOpt.Value.Type));
            }

            // If members are provided, the user is trying to define a new struct/union.

            if (this.Name.IsSome)
            {
                var name     = this.Name.Value;
                var typeName = (this.StructOrUnion == StructOrUnion.STRUCT ? "struct" : "union") + $" {name}";

                // Try to find Type name in the current environment.
                // Notice we need to search the current **scope** only.
                var entryOpt = env.FindInCurrentScope(typeName);

                // If name not found: create an incomplete Type and add it into the environment.
                if (entryOpt.IsNone)
                {
                    type = StructOrUnionType.CreateIncompleteType(this.StructOrUnion, name);
                    env  = env.PushEntry(Env.EntryKind.TYPEDEF, typeName, type);
                }
                else
                {
                    if (entryOpt.Value.Kind != Env.EntryKind.TYPEDEF)
                    {
                        throw new InvalidProgramException(
                                  "A struct or union in env that is not typedef? This should not appear.");
                    }

                    type = entryOpt.Value.Type as StructOrUnionType;
                    if (type == null)
                    {
                        throw new InvalidProgramException(
                                  $"{typeName} is not a struct or union? This should not appear.");
                    }
                }

                // Current Type mustn't be already complete.
                if (type.IsComplete)
                {
                    throw new InvalidOperationException($"Redifinition of {typeName}");
                }
            }
            else
            {
                var typeName = (this.StructOrUnion == StructOrUnion.STRUCT ? "struct" : "union") + " <unnamed>";
                type = StructOrUnionType.CreateIncompleteType(this.StructOrUnion, typeName);
            }

            var members = Semant(GetMembers, this.MemberDeclns.Value, ref env);

            type.Define(this.StructOrUnion, members);

            return(SemantReturn.Create(env, type));
        }