示例#1
0
        public override AST.Node ToAST(Env env)
        {
            /// A return statement with an expression shall not appear in a function whose return type is void.
            /// A return statement without an expression shall only appear in a function whose return type is void.
            TFunc  f           = env.GetFuncType();
            string returnLabel = env.GetReturnLabel();

            if (expr != null)
            {
                if (f.ret.IsVoid)
                {
                    throw new Error(Pos, "a return statement with an expression shall not appear a function whose return type is void");
                }
                AST.Expr e = expr.ToASTExpr(env).ValueTransform();
                if (!Assign.SimpleAssignable(f.ret, e))
                {
                    throw new ETypeError(Pos, string.Format("cannot assign {0} to {1}", e.Type, f.ret));
                }
                return(new AST.Return(returnLabel, e.ImplicitConvert(f.ret)));
            }
            else
            {
                if (!f.ret.IsVoid)
                {
                    throw new Error(Pos, "a return statement without an expression shall only appear in a function whose return type is void");
                }
                return(new AST.Return(returnLabel, null));
            }
        }
示例#2
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
                       ));
        }