Beispiel #1
0
        public override ABT.Expr GetExpr(ABT.Env env)
        {
            Option <ABT.Env.Entry> entry_opt = env.Find(this.Name);

            if (entry_opt.IsNone)
            {
                throw new InvalidOperationException($"Cannot find variable '{this.Name}'");
            }

            ABT.Env.Entry entry = entry_opt.Value;

            switch (entry.Kind)
            {
            case ABT.Env.EntryKind.TYPEDEF:
                throw new InvalidOperationException($"Expected a variable '{this.Name}', not a typedef.");

            case ABT.Env.EntryKind.ENUM:
                return(new ABT.ConstLong(entry.Offset, env));

            case ABT.Env.EntryKind.FRAME:
            case ABT.Env.EntryKind.GLOBAL:
            case ABT.Env.EntryKind.STACK:
                return(new ABT.Variable(entry.Type, this.Name, env));

            default:
                throw new InvalidOperationException($"Cannot find variable '{this.Name}'");
            }
        }
Beispiel #2
0
        public static R Semant <R>(Func <ABT.Env, ISemantReturn <R> > semantFunc, ref ABT.Env env)
        {
            var semantReturn = semantFunc(env);

            env = semantReturn.Env;
            return(semantReturn.Value);
        }
Beispiel #3
0
        public static ABT.Expr SemantExpr(Func <ABT.Env, ABT.Expr> semantFunc, ref ABT.Env env)
        {
            var semantReturn = semantFunc(env);

            env = semantReturn.Env;
            return(semantReturn);
        }
Beispiel #4
0
        public override Tuple <ABT.Env, ABT.Stmt> GetStmt(ABT.Env env)
        {
            env = env.InScope();
            List <Tuple <ABT.Env, ABT.Decln> > declns = new List <Tuple <ABT.Env, ABT.Decln> >();
            List <Tuple <ABT.Env, ABT.Stmt> >  stmts  = new List <Tuple <ABT.Env, ABT.Stmt> >();

            foreach (Decln decln in this.Declns)
            {
                //Tuple<AST.Env, List<Tuple<AST.Env, AST.Decln>>> r_decln = decln.GetDeclns_(env);
                //env = r_decln.Item1;
                //declns.AddRange(r_decln.Item2);

                var declns_ = Semant(decln.GetDeclns, ref env);
                declns.AddRange(declns_);
            }

            foreach (Stmt stmt in this.Stmts)
            {
                Tuple <ABT.Env, ABT.Stmt> r_stmt = stmt.GetStmt(env);
                env = r_stmt.Item1;
                stmts.Add(r_stmt);
            }

            env = env.OutScope();

            return(new Tuple <ABT.Env, ABT.Stmt>(env, new ABT.CompoundStmt(declns, stmts)));
        }
Beispiel #5
0
        public override Tuple <ABT.Env, ABT.Stmt> GetStmt(ABT.Env env)
        {
            var expr = this.Expr.Map(_ => _.GetExpr(env));

            expr = expr.Map(_ => ABT.TypeCast.MakeCast(_, env.GetCurrentFunction().ReturnType));
            return(new Tuple <ABT.Env, ABT.Stmt>(env, new ABT.ReturnStmt(expr)));
        }
Beispiel #6
0
        public override Tuple <ABT.Env, ABT.Stmt> GetStmt(ABT.Env env)
        {
            var expr = this.Expr.Map(_ => _.GetExpr(env));

            env = expr.IsSome ? expr.Value.Env : env;
            return(new Tuple <ABT.Env, ABT.Stmt>(env, new ABT.ExprStmt(expr)));
        }
Beispiel #7
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)));
        }
Beispiel #8
0
        public override Tuple <ABT.Env, ABT.Stmt> GetStmt(ABT.Env env)
        {
            Option <ABT.Expr> init = this.Init.Map(_ => _.GetExpr(env));

            if (init.IsSome)
            {
                env = init.Value.Env;
            }

            Option <ABT.Expr> cond = this.Cond.Map(_ => _.GetExpr(env));

            if (cond.IsSome)
            {
                env = cond.Value.Env;
            }

            if (cond.IsSome && !cond.Value.Type.IsScalar)
            {
                throw new InvalidOperationException("Error: conditional expression in while Loop must be scalar.");
            }

            Option <ABT.Expr> loop = this.Loop.Map(_ => _.GetExpr(env));

            if (loop.IsSome)
            {
                env = loop.Value.Env;
            }

            Tuple <ABT.Env, ABT.Stmt> r_body = this.Body.GetStmt(env);

            env = r_body.Item1;
            ABT.Stmt body = r_body.Item2;

            return(new Tuple <ABT.Env, ABT.Stmt>(env, new ABT.ForStmt(init, cond, loop, body)));
        }
Beispiel #9
0
        public override Tuple <ABT.Env, ABT.Stmt> GetStmt(ABT.Env env)
        {
            Tuple <ABT.Env, ABT.Stmt> r_stmt = this.Stmt.GetStmt(env);

            env = r_stmt.Item1;
            return(new Tuple <ABT.Env, ABT.Stmt>(env, new ABT.LabeledStmt(this.Label, r_stmt.Item2)));
        }
Beispiel #10
0
        public override ABT.Expr GetExpr(ABT.Env env)
        {
            ABT.Expr expr = this.Expr.GetExpr(env);

            if (!expr.Type.IsIntegral)
            {
                throw new InvalidOperationException("Expected integral Type.");
            }

            expr = ABT.TypeCast.IntegralPromotion(expr).Item1;

            if (expr.IsConstExpr)
            {
                switch (expr.Type.Kind)
                {
                case ABT.ExprTypeKind.LONG:
                    return(new ABT.ConstLong(~((ABT.ConstLong)expr).Value, env));

                case ABT.ExprTypeKind.ULONG:
                    return(new ABT.ConstULong(~((ABT.ConstULong)expr).Value, env));

                default:
                    throw new InvalidOperationException();
                }
            }

            return(new ABT.BitwiseNot(expr));
        }
Beispiel #11
0
        public override ABT.Expr GetExpr(ABT.Env env)
        {
            var left  = SemantExpr(this.Left, ref env);
            var right = SemantExpr(this.Right, ref env);

            right = ABT.TypeCast.MakeCast(right, left.Type);
            return(new ABT.Assign(left, right));
        }
Beispiel #12
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())));
        }
Beispiel #13
0
        public override ABT.Expr GetExpr(ABT.Env env)
        {
            var left  = SemantExpr(this.Left, ref env);
            var right = SemantExpr(this.Right, ref env);

            if (left.Type is ABT.ArrayType)
            {
                left = ABT.TypeCast.MakeCast(left, new ABT.PointerType((left.Type as ABT.ArrayType).ElemType, left.Type.IsConst, left.Type.IsVolatile));
            }

            if (right.Type is ABT.ArrayType)
            {
                right = ABT.TypeCast.MakeCast(right, new ABT.PointerType((right.Type as ABT.ArrayType).ElemType, right.Type.IsConst, right.Type.IsVolatile));
            }

            var isConst    = left.Type.IsConst || right.Type.IsConst;
            var isVolatile = left.Type.IsVolatile || right.Type.IsVolatile;

            if (left.Type.Kind == ABT.ExprTypeKind.POINTER)
            {
                // 1. ptr - ptr
                if (right.Type.Kind == ABT.ExprTypeKind.POINTER)
                {
                    ABT.PointerType leftType  = (ABT.PointerType)(left.Type);
                    ABT.PointerType rightType = (ABT.PointerType)(right.Type);
                    if (!leftType.RefType.EqualType(rightType.RefType))
                    {
                        throw new InvalidOperationException("The 2 pointers don't match.");
                    }

                    Int32 scale = leftType.RefType.SizeOf;

                    if (left.IsConstExpr && right.IsConstExpr)
                    {
                        return(new ABT.ConstLong((Int32)(((ABT.ConstPtr)left).Value - ((ABT.ConstPtr)right).Value) / scale, env));
                    }

                    return(new ABT.Divide(
                               new ABT.Sub(
                                   ABT.TypeCast.MakeCast(left, new ABT.LongType(isConst, isVolatile)),
                                   ABT.TypeCast.MakeCast(right, new ABT.LongType(isConst, isVolatile))
                                   ),
                               new ABT.ConstLong(scale, env)
                               ));
                }

                // 2. ptr - integral
                if (!right.Type.IsIntegral)
                {
                    throw new InvalidOperationException("Expected an integral.");
                }
                right = ABT.TypeCast.MakeCast(right, new ABT.LongType(right.Type.IsConst, right.Type.IsVolatile));
                return(GetPointerSubtraction(left, right));
            }

            // 3. arith - arith
            return(base.GetExpr(env));
        }
Beispiel #14
0
        public override ABT.Expr GetExpr(ABT.Env env)
        {
            // 1. semant operands
            var left  = SemantExpr(this.Left, ref env);
            var right = SemantExpr(this.Right, ref env);

            // 2. perform usual arithmetic conversion
            Tuple <ABT.Expr, ABT.Expr, ABT.ExprTypeKind> castReturn = ABT.TypeCast.UsualArithmeticConversion(left, right);

            left  = castReturn.Item1;
            right = castReturn.Item2;
            var typeKind = castReturn.Item3;

            var isConst    = left.Type.IsConst || right.Type.IsConst;
            var isVolatile = left.Type.IsVolatile || right.Type.IsVolatile;

            // 3. if both operands are constants
            if (left.IsConstExpr && right.IsConstExpr)
            {
                switch (typeKind)
                {
                case ABT.ExprTypeKind.DOUBLE:
                    return(new ABT.ConstDouble(OperateDouble(((ABT.ConstDouble)left).Value, ((ABT.ConstDouble)right).Value), env));

                case ABT.ExprTypeKind.FLOAT:
                    return(new ABT.ConstFloat(OperateFloat(((ABT.ConstFloat)left).Value, ((ABT.ConstFloat)right).Value), env));

                case ABT.ExprTypeKind.ULONG:
                    return(new ABT.ConstULong(OperateULong(((ABT.ConstULong)left).Value, ((ABT.ConstULong)right).Value), env));

                case ABT.ExprTypeKind.LONG:
                    return(new ABT.ConstLong(OperateLong(((ABT.ConstLong)left).Value, ((ABT.ConstLong)right).Value), env));

                default:
                    throw new InvalidOperationException("Expected arithmetic Type.");
                }
            }

            // 4. if not both operands are constants
            switch (typeKind)
            {
            case ABT.ExprTypeKind.DOUBLE:
                return(ConstructExpr(left, right, new ABT.DoubleType(isConst, isVolatile)));

            case ABT.ExprTypeKind.FLOAT:
                return(ConstructExpr(left, right, new ABT.FloatType(isConst, isVolatile)));

            case ABT.ExprTypeKind.ULONG:
                return(ConstructExpr(left, right, new ABT.ULongType(isConst, isVolatile)));

            case ABT.ExprTypeKind.LONG:
                return(ConstructExpr(left, right, new ABT.LongType(isConst, isVolatile)));

            default:
                throw new InvalidOperationException("Expected arithmetic Type.");
            }
        }
Beispiel #15
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));
        }
Beispiel #16
0
        public override ABT.Expr GetExpr(ABT.Env env)
        {
            //Tuple<AST.Env, AST.ExprType> type_env = this.TypeName.GetTypeEnv(env);
            //env = type_env.Item1;
            //AST.ExprType Type = type_env.Item2;

            var type = Semant(this.TypeName.GetExprType, ref env);

            return(new ABT.ConstULong((UInt32)type.SizeOf, env));
        }
Beispiel #17
0
        public override ABT.Expr GetExpr(ABT.Env env)
        {
            ABT.Expr expr = this.Expr.GetExpr(env);

            if (!expr.Type.IsArith)
            {
                throw new InvalidOperationException("Expected arithmetic Type.");
            }

            return(expr);
        }
Beispiel #18
0
        public override ABT.Expr GetExpr(ABT.Env env)
        {
            ABT.Expr expr = this.Expr.GetExpr(env);

            if (!expr.Type.IsScalar)
            {
                throw new InvalidOperationException("Expected a scalar.");
            }

            return(new ABT.PostDecrement(expr));
        }
Beispiel #19
0
        public override Tuple <ABT.Env, ABT.Stmt> GetStmt(ABT.Env env)
        {
            ABT.Expr expr = this.Expr.GetExpr(env);

            Tuple <ABT.Env, ABT.Stmt> r_stmt = this.Stmt.GetStmt(env);

            env = r_stmt.Item1;
            ABT.Stmt stmt = r_stmt.Item2;

            return(new Tuple <ABT.Env, ABT.Stmt>(env, new ABT.SwitchStmt(expr, stmt)));
        }
Beispiel #20
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)));
        }
Beispiel #21
0
        public override ABT.Expr GetExpr(ABT.Env env)
        {
            switch (this.FloatSuffix)
            {
            case TokenFloat.FloatSuffix.F:
                return(new ABT.ConstFloat((Single)this.Value, env));

            case TokenFloat.FloatSuffix.NONE:
            case TokenFloat.FloatSuffix.L:
                return(new ABT.ConstDouble(this.Value, env));

            default:
                throw new InvalidOperationException();
            }
        }
Beispiel #22
0
        public override ABT.Expr GetExpr(ABT.Env env)
        {
            ABT.Expr expr = this.Expr.GetExpr(env);
            String   name = this.Member;

            if (expr.Type.Kind != ABT.ExprTypeKind.STRUCT_OR_UNION)
            {
                throw new InvalidOperationException("Must get the attribute from a struct or union.");
            }

            ABT.Utils.StoreEntry entry = (expr.Type as ABT.StructOrUnionType).Attribs.First(_ => _.name == name);
            ABT.ExprType         type  = entry.type;

            return(new ABT.Attribute(expr, name, type));
        }
Beispiel #23
0
        public override Tuple <ABT.Env, ABT.Stmt> GetStmt(ABT.Env env)
        {
            ABT.Expr cond = this.Cond.GetExpr(env);

            if (!cond.Type.IsScalar)
            {
                throw new InvalidOperationException("Error: expected scalar Type");
            }

            Tuple <ABT.Env, ABT.Stmt> r_stmt = this.Stmt.GetStmt(env);

            env = r_stmt.Item1;
            ABT.Stmt stmt = r_stmt.Item2;

            return(new Tuple <ABT.Env, ABT.Stmt>(env, new ABT.IfStmt(cond, stmt)));
        }
Beispiel #24
0
        public override ABT.Expr GetExpr(ABT.Env env)
        {
            switch (this.Suffix)
            {
            case TokenInt.IntSuffix.U:
            case TokenInt.IntSuffix.UL:
                return(new ABT.ConstULong((UInt32)this.Value, env));

            case TokenInt.IntSuffix.NONE:
            case TokenInt.IntSuffix.L:
                return(new ABT.ConstLong((Int32)this.Value, env));

            default:
                throw new InvalidOperationException();
            }
        }
Beispiel #25
0
        public override Tuple <ABT.Env, ABT.Stmt> GetStmt(ABT.Env env)
        {
            Tuple <ABT.Env, ABT.Stmt> r_body = this.Body.GetStmt(env);

            env = r_body.Item1;
            ABT.Stmt body = r_body.Item2;

            ABT.Expr cond = this.Cond.GetExpr(env);
            env = cond.Env;

            if (!cond.Type.IsScalar)
            {
                throw new InvalidOperationException("Error: conditional expression in while Loop must be scalar.");
            }

            return(new Tuple <ABT.Env, ABT.Stmt>(env, new ABT.DoWhileStmt(body, cond)));
        }
Beispiel #26
0
        public override ABT.Expr GetExpr(ABT.Env env)
        {
            ABT.Expr expr = this.Expr.GetExpr(env);

            if (expr.Type.Kind != ABT.ExprTypeKind.POINTER)
            {
                throw new InvalidOperationException("Expected a pointer.");
            }

            ABT.ExprType type = ((ABT.PointerType)expr.Type).RefType;
            if (type.Kind == ABT.ExprTypeKind.STRUCT_OR_UNION && !((ABT.StructOrUnionType)type).IsComplete)
            {
                throw new InvalidOperationException("Cannot dereference incomplete Type.");
            }

            return(new ABT.Dereference(expr, type));
        }
Beispiel #27
0
        public override Tuple <ABT.Env, ABT.Stmt> GetStmt(ABT.Env env)
        {
            ABT.Expr expr = this.Expr.GetExpr(env);
            env = expr.Env;

            expr = ABT.TypeCast.MakeCast(expr, new ABT.LongType());
            if (!expr.IsConstExpr)
            {
                throw new InvalidOperationException("case Expr not const");
            }
            Int32 value = ((ABT.ConstLong)expr).Value;

            Tuple <ABT.Env, ABT.Stmt> r_stmt = this.Stmt.GetStmt(env);

            env = r_stmt.Item1;

            return(new Tuple <ABT.Env, ABT.Stmt>(env, new ABT.CaseStmt(value, r_stmt.Item2)));
        }
Beispiel #28
0
        public override ABT.Expr GetExpr(ABT.Env env)
        {
            var expr = this.Expr.GetExpr(env);

            if (!expr.Type.IsArith)
            {
                throw new InvalidOperationException("Expected arithmetic Type.");
            }

            if (expr.Type.IsIntegral)
            {
                expr = ABT.TypeCast.IntegralPromotion(expr).Item1;
            }

            if (expr.IsConstExpr)
            {
                Boolean isZero;
                switch (expr.Type.Kind)
                {
                case ABT.ExprTypeKind.LONG:
                    isZero = ((ABT.ConstLong)expr).Value == 0;
                    break;

                case ABT.ExprTypeKind.ULONG:
                    isZero = ((ABT.ConstULong)expr).Value == 0;
                    break;

                case ABT.ExprTypeKind.FLOAT:
                    isZero = ((ABT.ConstFloat)expr).Value == 0;
                    break;

                case ABT.ExprTypeKind.DOUBLE:
                    isZero = ((ABT.ConstDouble)expr).Value == 0;
                    break;

                default:
                    throw new InvalidOperationException();
                }
                return(new ABT.ConstLong(Convert.ToInt32(isZero), env));
            }

            return(new ABT.LogicalNot(expr));
        }
Beispiel #29
0
        public override ABT.Expr GetExpr(ABT.Env env)
        {
            // 1. semant the operands
            var left  = SemantExpr(this.Left, ref env);
            var right = SemantExpr(this.Right, ref env);

            if (left.Type is ABT.ArrayType)
            {
                left = ABT.TypeCast.MakeCast(left, new ABT.PointerType(((ABT.ArrayType)left.Type).ElemType, left.Type.IsConst, left.Type.IsVolatile));
            }

            if (right.Type is ABT.ArrayType)
            {
                right = ABT.TypeCast.MakeCast(right, new ABT.PointerType(((ABT.ArrayType)right.Type).ElemType, right.Type.IsConst, right.Type.IsVolatile));
            }

            // 2. ptr + int
            if (left.Type.Kind == ABT.ExprTypeKind.POINTER)
            {
                if (!right.Type.IsIntegral)
                {
                    throw new InvalidOperationException("Expected integral to be added to a pointer.");
                }
                right = ABT.TypeCast.MakeCast(right, new ABT.LongType(right.Type.IsConst, right.Type.IsVolatile));
                return(GetPointerAddition(left, right));
            }

            // 3. int + ptr
            if (right.Type.Kind == ABT.ExprTypeKind.POINTER)
            {
                if (!left.Type.IsIntegral)
                {
                    throw new InvalidOperationException("Expected integral to be added to a pointer.");
                }
                left = ABT.TypeCast.MakeCast(left, new ABT.LongType(left.Type.IsConst, left.Type.IsVolatile));
                return(GetPointerAddition(right, left, false));
            }

            // 4. usual arithmetic conversion
            return(base.GetExpr(env));
        }
Beispiel #30
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)));
        }