public Tuple<AST.Env, AST.FuncDef> GetFuncDef(AST.Env env) { // Get storage class specifier and base type from declaration specifiers. Tuple<AST.Env, AST.Decln.SCS, AST.ExprType> r_specs = this.specs.GetSCSType(env); env = r_specs.Item1; AST.Decln.SCS scs = r_specs.Item2; AST.ExprType base_type = r_specs.Item3; // Get function name and function type from declarator. Tuple<String, AST.ExprType> r_declr = this.declr.GetNameAndType(env, base_type); String name = r_declr.Item1; AST.ExprType type = r_declr.Item2; AST.TFunction func_type; if (type.kind == AST.ExprType.Kind.FUNCTION) { func_type = (AST.TFunction)type; } else { throw new InvalidOperationException($"{name} is not a function."); } switch (scs) { case AST.Decln.SCS.AUTO: case AST.Decln.SCS.EXTERN: case AST.Decln.SCS.STATIC: env = env.PushEntry(AST.Env.EntryKind.GLOBAL, name, type); break; case AST.Decln.SCS.TYPEDEF: default: throw new InvalidOperationException("Invalid storage class specifier for function definition."); } env = env.SetCurrentFunction(func_type); Tuple<AST.Env, AST.Stmt> r_stmt = this.stmt.GetStmt(env); env = r_stmt.Item1; AST.Stmt stmt = r_stmt.Item2; env = env.SetCurrentFunction(new AST.TEmptyFunction()); return Tuple.Create(env, new AST.FuncDef(name, scs, func_type, stmt)); }