Example #1
0
        public override AST.Node ToAST(Env env)
        {
            /// An iteration statement is a block.
            env.PushBlockScope();

            /// The controlling expression should have scalar type.
            AST.Expr e = expr.ToASTExpr(env);
            if (!e.Type.IsScalar)
            {
                throw new ETypeError(Pos, "the controlling expression of iteration statement should have scalar type");
            }

            /// The loop body is also a block.
            env.PushBlockScope();

            /// Add this loop to the environemnt.
            env.PushLoop(this);

            var b = body.ToASTCompoundStmt(env);

            env.PopBreakable();

            env.PopScope();
            env.PopScope();

            return(new AST.While(breakLabel, continueLabel, secondPlusLabel, firstLabel, e, b));
        }
Example #2
0
        public override AST.Node ToAST(Env env)
        {
            /// An iteration statement is a block.
            env.PushBlockScope();

            /// Check the expressions.
            /// An omitted expression-2 is replaced by a nonzero constant.
            var i = initExpr != null?initExpr.ToAST(env) : (initDecl != null ? initDecl.ToAST(env) : null);

            var p = pred != null?pred.ToASTExpr(env) : new AST.ConstIntExpr(TInt.Instance, 1, env.ASTEnv);

            var q = iter != null?iter.ToAST(env) : null;

            /// The controlling expression of a iteration statement shall have scalar type.
            if (!p.Type.IsScalar)
            {
                throw new ETypeError(Pos, "the controlling expression of iteration statement should have scalar type");
            }

            /// Add this loop to the environment.
            env.PushLoop(this);

            var b = body.ToASTCompoundStmt(env);

            env.PopBreakable();

            env.PopScope();

            return(new AST.For(breakLabel, continueLabel, secondPlusLabel, firstLabel, i, p, q, b));
        }
Example #3
0
        public override AST.Node ToAST(Env env)
        {
            env.PushBlockScope();
            env.PushBlockScope();
            env.PushLoop(this);

            var b = body.ToASTCompoundStmt(env);

            env.PopBreakable();
            env.PopScope();

            AST.Expr e = expr.ToASTExpr(env);
            if (!e.Type.IsScalar)
            {
                throw new ETypeError(Pos, "the controlling expression of iteration statement should be have scalar type");
            }

            env.PopScope();
            return(new AST.Do(breakLabel, continueLabel, secondPlusLabel, firstLabel, e, b));
        }
Example #4
0
        public AST.CompoundStmt ToASTCompoundStmt(Env env)
        {
            env.PushBlockScope();
            LinkedList <AST.Node> results = new LinkedList <AST.Node>();

            foreach (var stmt in stmts)
            {
                results.AddLast(stmt.ToAST(env));
            }
            env.PopScope();
            return(new AST.CompoundStmt(results));
        }
Example #5
0
        /// <summary>
        /// A selection statement is a block whose scope is a strict subset
        /// of the scope of its enclosing block.
        ///
        /// The controlling expression of an if statement shall have scalar type.
        /// </summary>
        /// <param name="env"></param>
        /// <returns></returns>
        public override AST.Node ToAST(Env env)
        {
            env.PushBlockScope();
            AST.Expr e = expr.ToASTExpr(env);
            if (!e.Type.IsScalar)
            {
                throw new ETypeError(Pos, string.Format("expecting scalar type, given {0}", e.Type));
            }

            AST.Node t = then.ToAST(env);
            AST.Node o = other != null?other.ToAST(env) : null;

            env.PopScope();

            var labels = env.AllocIfLabel();

            return(new AST.If(e, t, o, labels.Item1, labels.Item2));
        }
Example #6
0
        public override AST.Node ToAST(Env env)
        {
            T   baseType = specifiers.GetT(env);
            var result   = declarator.Declare(env, baseType);

            if (declarations != null)
            {
                throw new Error(Pos, "sorry we donot support old-style function definition");
            }

            /// The identifier declared in a function definition (which is the name of the function) shall
            /// have a function type
            if (!result.Item2.IsFunc)
            {
                throw new ETypeError(Pos, "function definition should have function type");
            }

            /// The storage-class specifier, if any, shall be either extern or static.
            if (specifiers.storage != StoreSpec.Kind.EXTERN &&
                specifiers.storage != StoreSpec.Kind.NONE &&
                specifiers.storage != StoreSpec.Kind.STATIC)
            {
                throw new Error(Pos, string.Format("illegal storage specifier {0} in function definition", specifiers.storage));
            }

            /// Determine the linkage.
            var link = specifiers.storage == StoreSpec.Kind.STATIC ? SymbolEntry.Link.INTERNAL : SymbolEntry.Link.EXTERNAL;

            var entry = env.GetSymbol(result.Item1);

            if (entry == null)
            {
                /// This identifier has not been used.
                env.AddFunc(result.Item1, result.Item2, link, Pos);
            }
            else
            {
                /// This identifier has been declared.
                /// Check if it's a function type.
                if (!entry.type.Equals(result.Item2))
                {
                    throw new ERedefineSymbolTypeConflict(Pos, result.Item1, entry.type, result.Item2);
                }

                /// Check if the function has already been defined.
                if (entry.type.IsDefined)
                {
                    throw new ERedefineFunction(Pos, result.Item1);
                }

                /// Define the function.
                entry.type.DefFunc();
            }

            TFunc type = result.Item2.nake as TFunc;

            /// Push a new scope.
            env.PushFuncScope(result.Item1, type, result.Item3, Pos);

            /// Semantic check the function body.
            AST.CompoundStmt b = body.ToASTCompoundStmt(env);

            string returnLabel = env.GetReturnLabel();

            env.PopScope();

            return(new AST.FuncDef(
                       result.Item1,
                       returnLabel,
                       type,
                       result.Item3,
                       b,
                       env.ASTEnv,
                       specifiers.storage != StoreSpec.Kind.STATIC
                       ));
        }