1: %% 2: %% %CopyrightBegin% 3: %% 4: %% Copyright Ericsson AB 2003-2011. All Rights Reserved. 5: %% 6: %% The contents of this file are subject to the Erlang Public License, 7: %% Version 1.1, (the "License"); you may not use this file except in 8: %% compliance with the License. You should have received a copy of the 9: %% Erlang Public License along with this software. If not, it can be 10: %% retrieved online at http://www.erlang.org/. 11: %% 12: %% Software distributed under the License is distributed on an "AS IS" 13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 14: %% the License for the specific language governing rights and limitations 15: %% under the License. 16: %% 17: %% %CopyrightEnd% 18: %% 19: 20: %% 21: -module(trycatch_SUITE). 22: 23: -export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, 24: init_per_testcase/2,end_per_testcase/2, 25: init_per_suite/1,end_per_suite/1, 26: basic/1,lean_throw/1,try_of/1,try_after/1,%after_bind/1, 27: catch_oops/1,after_oops/1,eclectic/1,rethrow/1, 28: nested_of/1,nested_catch/1,nested_after/1]). 29: 30: -include_lib("test_server/include/test_server.hrl"). 31: 32: suite() -> [{ct_hooks,[ts_install_cth]}]. 33: 34: all() -> 35: cases(). 36: 37: groups() -> 38: []. 39: 40: init_per_group(_GroupName, Config) -> 41: Config. 42: 43: end_per_group(_GroupName, Config) -> 44: Config. 45: 46: 47: cases() -> 48: [basic, lean_throw, try_of, try_after, catch_oops, 49: after_oops, eclectic, rethrow, nested_of, nested_catch, 50: nested_after]. 51: 52: init_per_testcase(_Case, Config) -> 53: test_lib:interpret(?MODULE), 54: Dog = test_server:timetrap(?t:minutes(1)), 55: [{watchdog,Dog}|Config]. 56: 57: end_per_testcase(_Case, Config) -> 58: Dog = ?config(watchdog, Config), 59: ?t:timetrap_cancel(Dog), 60: ok. 61: 62: init_per_suite(Config) when is_list(Config) -> 63: ?line test_lib:interpret(?MODULE), 64: ?line true = lists:member(?MODULE, int:interpreted()), 65: Config. 66: 67: end_per_suite(Config) when is_list(Config) -> 68: ok. 69: 70: basic(Conf) when is_list(Conf) -> 71: ?line 2 = 72: try my_div(4, 2) 73: catch 74: Class:Reason -> {Class,Reason} 75: end, 76: ?line error = 77: try my_div(1, 0) 78: catch 79: error:badarith -> error 80: end, 81: ?line error = 82: try 1/0 83: catch 84: error:badarith -> error 85: end, 86: ?line ok = 87: try my_add(53, atom) 88: catch 89: error:badarith -> ok 90: end, 91: ?line exit_nisse = 92: try exit(nisse) 93: catch 94: exit:nisse -> exit_nisse 95: end, 96: ?line ok = 97: try throw(kalle) 98: catch 99: kalle -> ok 100: end, 101: 102: %% Try some stuff where the compiler will optimize away the try. 103: 104: V = id({a,variable}), 105: ?line V = try V catch nisse -> error end, 106: ?line 42 = try 42 catch nisse -> error end, 107: ?line [V] = try [V] catch nisse -> error end, 108: ?line {ok,V} = try {ok,V} catch nisse -> error end, 109: 110: %% Same idea, but use an after too. 111: 112: ?line V = try V catch nisse -> error after after_call() end, 113: ?line after_clean(), 114: ?line 42 = try 42 after after_call() end, 115: ?line after_clean(), 116: ?line [V] = try [V] catch nisse -> error after after_call() end, 117: ?line after_clean(), 118: ?line {ok,V} = try {ok,V} after after_call() end, 119: 120: %% Try/of 121: ?line ok = try V of 122: {a,variable} -> ok 123: catch nisse -> erro 124: end, 125: 126: ok. 127: 128: after_call() -> 129: put(basic, after_was_called). 130: 131: after_clean() -> 132: after_was_called = erase(basic). 133: 134: lean_throw(Conf) when is_list(Conf) -> 135: ?line {throw,kalle} = 136: try throw(kalle) 137: catch 138: Kalle -> {throw,Kalle} 139: end, 140: ?line {exit,kalle} = 141: try exit(kalle) 142: catch 143: Throw1 -> {throw,Throw1}; 144: exit:Reason1 -> {exit,Reason1} 145: end, 146: ?line {exit,kalle} = 147: try exit(kalle) 148: catch 149: exit:Reason2 -> {exit,Reason2}; 150: Throw2 -> {throw,Throw2} 151: end, 152: ?line {exit,kalle} = 153: try try exit(kalle) 154: catch 155: Throw3 -> {throw,Throw3} 156: end 157: catch 158: exit:Reason3 -> {exit,Reason3} 159: end, 160: ok. 161: 162: try_of(Conf) when is_list(Conf) -> 163: ?line {ok,{some,content}} = 164: try_of_1({value,{good,{some,content}}}), 165: ?line {error,[other,content]} = 166: try_of_1({value,{bad,[other,content]}}), 167: ?line {caught,{exit,{ex,it,[reason]}}} = 168: try_of_1({exit,{ex,it,[reason]}}), 169: ?line {caught,{throw,[term,{in,a,{tuple}}]}} = 170: try_of_1({throw,[term,{in,a,{tuple}}]}), 171: ?line {caught,{error,[bad,arg]}} = 172: try_of_1({error,[bad,arg]}), 173: ?line {caught,{error,badarith}} = 174: try_of_1({'div',{1,0}}), 175: ?line {caught,{error,badarith}} = 176: try_of_1({'add',{a,0}}), 177: ?line {caught,{error,badarg}} = 178: try_of_1({'abs',x}), 179: ?line {caught,{error,function_clause}} = 180: try_of_1(illegal), 181: ?line {error,{try_clause,{some,other_garbage}}} = 182: try try_of_1({value,{some,other_garbage}}) 183: catch error:Reason -> {error,Reason} 184: end, 185: ok. 186: 187: try_of_1(X) -> 188: try foo(X) of 189: {good,Y} -> {ok,Y}; 190: {bad,Y} -> {error,Y} 191: catch 192: Class:Reason -> 193: {caught,{Class,Reason}} 194: end. 195: 196: try_after(Conf) when is_list(Conf) -> 197: ?line {{ok,[some,value],undefined},finalized} = 198: try_after_1({value,{ok,[some,value]}},finalized), 199: ?line {{error,badarith,undefined},finalized} = 200: try_after_1({'div',{1,0}},finalized), 201: ?line {{error,badarith,undefined},finalized} = 202: try_after_1({'add',{1,a}},finalized), 203: ?line {{error,badarg,undefined},finalized} = 204: try_after_1({'abs',a},finalized), 205: ?line {{error,[the,{reason}],undefined},finalized} = 206: try_after_1({error,[the,{reason}]},finalized), 207: ?line {{throw,{thrown,[reason]},undefined},finalized} = 208: try_after_1({throw,{thrown,[reason]}},finalized), 209: ?line {{exit,{exited,{reason}},undefined},finalized} = 210: try_after_1({exit,{exited,{reason}}},finalized), 211: ?line {{error,function_clause,undefined},finalized} = 212: try_after_1(function_clause,finalized), 213: ?line ok = 214: try try_after_1({'add',{1,1}}, finalized) 215: catch 216: error:{try_clause,2} -> ok 217: end, 218: ?line finalized = erase(try_after), 219: ?line ok = 220: try try foo({exit,[reaso,{n}]}) 221: after put(try_after, finalized) 222: end 223: catch 224: exit:[reaso,{n}] -> ok 225: end, 226: ok. 227: 228: try_after_1(X, Y) -> 229: erase(try_after), 230: Try = 231: try foo(X) of 232: {ok,Value} -> {ok,Value,get(try_after)} 233: catch 234: Reason -> {throw,Reason,get(try_after)}; 235: error:Reason -> {error,Reason,get(try_after)}; 236: exit:Reason -> {exit,Reason,get(try_after)} 237: after 238: put(try_after, Y) 239: end, 240: {Try,erase(try_after)}. 241: 242: -ifdef(begone). 243: 244: after_bind(Conf) when is_list(Conf) -> 245: V = [make_ref(),self()|value], 246: ?line {value,{value,V}} = 247: after_bind_1({value,V}, V, {value,V}), 248: ok. 249: 250: after_bind_1(X, V, Y) -> 251: try 252: Try = 253: try foo(X) of 254: V -> value 255: catch 256: C1:V -> {caught,C1} 257: after 258: After = foo(Y) 259: end, 260: {Try,After} 261: of 262: V -> {value,V} 263: catch 264: C:D -> {caught,{C,D}} 265: end. 266: 267: -endif. 268: 269: catch_oops(Conf) when is_list(Conf) -> 270: V = {v,[a,l|u],{e},self()}, 271: ?line {value,V} = catch_oops_1({value,V}), 272: ?line {value,1} = catch_oops_1({'div',{1,1}}), 273: ?line {error,badarith} = catch_oops_1({'div',{1,0}}), 274: ?line {error,function_clause} = catch_oops_1(function_clause), 275: ?line {throw,V} = catch_oops_1({throw,V}), 276: ?line {exit,V} = catch_oops_1({exit,V}), 277: ok. 278: 279: catch_oops_1(X) -> 280: Ref = make_ref(), 281: try try foo({error,Ref}) 282: catch 283: error:Ref -> 284: foo(X) 285: end of 286: Value -> {value,Value} 287: catch 288: Class:Data -> {Class,Data} 289: end. 290: 291: 292: 293: after_oops(Conf) when is_list(Conf) -> 294: V = {self(),make_ref()}, 295: ?line {{value,V},V} = after_oops_1({value,V}, {value,V}), 296: ?line {{exit,V},V} = after_oops_1({exit,V}, {value,V}), 297: ?line {{error,V},undefined} = after_oops_1({value,V}, {error,V}), 298: ?line {{error,function_clause},undefined} = 299: after_oops_1({exit,V}, function_clause), 300: ok. 301: 302: after_oops_1(X, Y) -> 303: erase(after_oops), 304: Try = 305: try try foo(X) 306: after 307: put(after_oops, foo(Y)) 308: end of 309: V -> {value,V} 310: catch 311: C:D -> {C,D} 312: end, 313: {Try,erase(after_oops)}. 314: 315: 316: 317: eclectic(Conf) when is_list(Conf) -> 318: V = {make_ref(),3.1415926535,[[]|{}]}, 319: ?line {{value,{value,V},V},V} = 320: eclectic_1({foo,{value,{value,V}}}, undefined, {value,V}), 321: ?line {{'EXIT',{V,[{?MODULE,foo,_,_}|_]}},V} = 322: eclectic_1({catch_foo,{error,V}}, undefined, {value,V}), 323: ?line {{error,{exit,V},{'EXIT',V}},V} = 324: eclectic_1({foo,{error,{exit,V}}}, error, {value,V}), 325: ?line {{value,{value,V},V},{'EXIT',{badarith,[{?MODULE,my_add,_,_}|_]}}} = 326: eclectic_1({foo,{value,{value,V}}}, undefined, {'add',{0,a}}), 327: ?line {{'EXIT',V},V} = 328: eclectic_1({catch_foo,{exit,V}}, undefined, {throw,V}), 329: ?line {{error,{'div',{1,0}},{'EXIT',{badarith,[{?MODULE,my_div,_,_}|_]}}}, 330: {'EXIT',V}} = 331: eclectic_1({foo,{error,{'div',{1,0}}}}, error, {exit,V}), 332: ?line {{{error,V},{'EXIT',{V,[{?MODULE,foo,_,_}|_]}}},{'EXIT',V}} = 333: eclectic_1({catch_foo,{throw,{error,V}}}, undefined, {exit,V}), 334: %% 335: ?line {{value,{value,{value,V},V}},V} = 336: eclectic_2({value,{value,V}}, undefined, {value,V}), 337: ?line {{value,{throw,{value,V},V}},V} = 338: eclectic_2({throw,{value,V}}, throw, {value,V}), 339: ?line {{caught,{'EXIT',V}},undefined} = 340: eclectic_2({value,{value,V}}, undefined, {exit,V}), 341: ?line {{caught,{'EXIT',{V,[{?MODULE,foo,_,_}|_]}}},undefined} = 342: eclectic_2({error,{value,V}}, throw, {error,V}), 343: ?line {{caught,{'EXIT',{badarg,[{erlang,abs,[V],_}|_]}}},V} = 344: eclectic_2({value,{'abs',V}}, undefined, {value,V}), 345: ?line {{caught,{'EXIT',{badarith,[{?MODULE,my_add,_,_}|_]}}},V} = 346: eclectic_2({exit,{'add',{0,a}}}, exit, {value,V}), 347: ?line {{caught,{'EXIT',V}},undefined} = 348: eclectic_2({value,{error,V}}, undefined, {exit,V}), 349: ?line {{caught,{'EXIT',{V,[{?MODULE,foo,_,_}|_]}}},undefined} = 350: eclectic_2({throw,{'div',{1,0}}}, throw, {error,V}), 351: ok. 352: 353: eclectic_1(X, C, Y) -> 354: erase(eclectic), 355: Done = make_ref(), 356: Try = 357: try case X of 358: {catch_foo,V} -> catch {Done,foo(V)}; 359: {foo,V} -> {Done,foo(V)} 360: end of 361: {Done,D} -> {value,D,catch foo(D)}; 362: {'EXIT',_}=Exit -> Exit; 363: D -> {D,catch foo(D)} 364: catch 365: C:D -> {C,D,catch foo(D)} 366: after 367: put(eclectic, catch foo(Y)) 368: end, 369: {Try,erase(eclectic)}. 370: 371: eclectic_2(X, C, Y) -> 372: Done = make_ref(), 373: erase(eclectic), 374: Catch = 375: case 376: catch 377: {Done, 378: try foo(X) of 379: V -> {value,V,foo(V)} 380: catch 381: C:D -> {C,D,foo(D)} 382: after 383: put(eclectic, foo(Y)) 384: end} of 385: {Done,Z} -> {value,Z}; 386: Z -> {caught,Z} 387: end, 388: {Catch,erase(eclectic)}. 389: 390: rethrow(Conf) when is_list(Conf) -> 391: V = {a,[b,{c,self()},make_ref]}, 392: ?line {value2,value1} = 393: rethrow_1({value,V}, V), 394: ?line {caught2,{error,V}} = 395: rethrow_2({error,V}, undefined), 396: ?line {caught2,{exit,V}} = 397: rethrow_1({exit,V}, error), 398: ?line {caught2,{throw,V}} = 399: rethrow_1({throw,V}, undefined), 400: ?line {caught2,{throw,V}} = 401: rethrow_2({throw,V}, undefined), 402: ?line {caught2,{error,badarith}} = 403: rethrow_1({'add',{0,a}}, throw), 404: ?line {caught2,{error,function_clause}} = 405: rethrow_2(function_clause, undefined), 406: ?line {caught2,{error,{try_clause,V}}} = 407: rethrow_1({value,V}, exit), 408: ?line {value2,{caught1,V}} = 409: rethrow_1({error,V}, error), 410: ?line {value2,{caught1,V}} = 411: rethrow_1({exit,V}, exit), 412: ?line {value2,caught1} = 413: rethrow_2({throw,V}, V), 414: ok. 415: 416: rethrow_1(X, C1) -> 417: try try foo(X) of 418: C1 -> value1 419: catch 420: C1:D1 -> {caught1,D1} 421: end of 422: V2 -> {value2,V2} 423: catch 424: C2:D2 -> {caught2,{C2,D2}} 425: end. 426: 427: rethrow_2(X, C1) -> 428: try try foo(X) of 429: C1 -> value1 430: catch 431: C1 -> caught1 % Implicit class throw: 432: end of 433: V2 -> {value2,V2} 434: catch 435: C2:D2 -> {caught2,{C2,D2}} 436: end. 437: 438: 439: 440: nested_of(Conf) when is_list(Conf) -> 441: V = {[self()|make_ref()],1.4142136}, 442: ?line {{value,{value1,{V,x2}}}, 443: {V,x3}, 444: {V,x4}, 445: finalized} = 446: nested_of_1({{value,{V,x1}},void,{V,x1}}, 447: {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), 448: ?line {{caught,{throw,{V,x2}}}, 449: {V,x3}, 450: {V,x4}, 451: finalized} = 452: nested_of_1({{value,{V,x1}},void,{V,x1}}, 453: {throw,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), 454: ?line {{caught,{error,badarith}}, 455: undefined, 456: {V,x4}, 457: finalized} = 458: nested_of_1({{value,{V,x1}},void,{V,x1}}, 459: {throw,{V,x2}}, {'div',{1,0}}, {value,{V,x4}}), 460: ?line {{caught,{error,badarith}}, 461: undefined, 462: undefined, 463: finalized} = 464: nested_of_1({{value,{V,x1}},void,{V,x1}}, 465: {throw,{V,x2}}, {'div',{1,0}}, {'add',{0,b}}), 466: %% 467: ?line {{caught,{error,{try_clause,{V,x1}}}}, 468: {V,x3}, 469: {V,x4}, 470: finalized} = 471: nested_of_1({{value,{V,x1}},void,try_clause}, 472: void, {value,{V,x3}}, {value,{V,x4}}), 473: ?line {{caught,{exit,{V,x3}}}, 474: undefined, 475: {V,x4}, 476: finalized} = 477: nested_of_1({{value,{V,x1}},void,try_clause}, 478: void, {exit,{V,x3}}, {value,{V,x4}}), 479: ?line {{caught,{throw,{V,x4}}}, 480: undefined, 481: undefined, 482: finalized} = 483: nested_of_1({{value,{V,x1}},void,try_clause}, 484: void, {exit,{V,x3}}, {throw,{V,x4}}), 485: %% 486: ?line {{value,{caught1,{V,x2}}}, 487: {V,x3}, 488: {V,x4}, 489: finalized} = 490: nested_of_1({{error,{V,x1}},error,{V,x1}}, 491: {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), 492: ?line {{caught,{error,badarith}}, 493: {V,x3}, 494: {V,x4}, 495: finalized} = 496: nested_of_1({{error,{V,x1}},error,{V,x1}}, 497: {'add',{1,c}}, {value,{V,x3}}, {value,{V,x4}}), 498: ?line {{caught,{error,badarith}}, 499: undefined, 500: {V,x4}, 501: finalized} = 502: nested_of_1({{error,{V,x1}},error,{V,x1}}, 503: {'add',{1,c}}, {'div',{17,0}}, {value,{V,x4}}), 504: ?line {{caught,{error,badarg}}, 505: undefined, 506: undefined, 507: finalized} = 508: nested_of_1({{error,{V,x1}},error,{V,x1}}, 509: {'add',{1,c}}, {'div',{17,0}}, {'abs',V}), 510: %% 511: ?line {{caught,{error,badarith}}, 512: {V,x3}, 513: {V,x4}, 514: finalized} = 515: nested_of_1({{'add',{2,c}},rethrow,void}, 516: void, {value,{V,x3}}, {value,{V,x4}}), 517: ?line {{caught,{error,badarg}}, 518: undefined, 519: {V,x4}, 520: finalized} = 521: nested_of_1({{'add',{2,c}},rethrow,void}, 522: void, {'abs',V}, {value,{V,x4}}), 523: ?line {{caught,{error,function_clause}}, 524: undefined, 525: undefined, 526: finalized} = 527: nested_of_1({{'add',{2,c}},rethrow,void}, 528: void, {'abs',V}, function_clause), 529: ok. 530: 531: nested_of_1({X1,C1,V1}, 532: X2, X3, X4) -> 533: erase(nested3), 534: erase(nested4), 535: erase(nested), 536: Self = self(), 537: Try = 538: try 539: try self() 540: of 541: Self -> 542: try 543: foo(X1) 544: of 545: V1 -> {value1,foo(X2)} 546: catch 547: C1:V1 -> {caught1,foo(X2)} 548: after 549: put(nested3, foo(X3)) 550: end 551: after 552: put(nested4, foo(X4)) 553: end 554: of 555: V -> {value,V} 556: catch 557: C:D -> {caught,{C,D}} 558: after 559: put(nested, finalized) 560: end, 561: {Try,erase(nested3),erase(nested4),erase(nested)}. 562: 563: 564: 565: nested_catch(Conf) when is_list(Conf) -> 566: V = {[make_ref(),1.4142136,self()]}, 567: ?line {{value,{value1,{V,x2}}}, 568: {V,x3}, 569: {V,x4}, 570: finalized} = 571: nested_catch_1({{value,{V,x1}},void,{V,x1}}, 572: {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), 573: ?line {{caught,{throw,{V,x2}}}, 574: {V,x3}, 575: {V,x4}, 576: finalized} = 577: nested_catch_1({{value,{V,x1}},void,{V,x1}}, 578: {throw,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), 579: ?line {{caught,{error,badarith}}, 580: undefined, 581: {V,x4}, 582: finalized} = 583: nested_catch_1({{value,{V,x1}},void,{V,x1}}, 584: {throw,{V,x2}}, {'div',{1,0}}, {value,{V,x4}}), 585: ?line {{caught,{error,badarith}}, 586: undefined, 587: undefined, 588: finalized} = 589: nested_catch_1({{value,{V,x1}},void,{V,x1}}, 590: {throw,{V,x2}}, {'div',{1,0}}, {'add',{0,b}}), 591: %% 592: ?line {{caught,{error,{try_clause,{V,x1}}}}, 593: {V,x3}, 594: {V,x4}, 595: finalized} = 596: nested_catch_1({{value,{V,x1}},void,try_clause}, 597: void, {value,{V,x3}}, {value,{V,x4}}), 598: ?line {{caught,{exit,{V,x3}}}, 599: undefined, 600: {V,x4}, 601: finalized} = 602: nested_catch_1({{value,{V,x1}},void,try_clause}, 603: void, {exit,{V,x3}}, {value,{V,x4}}), 604: ?line {{caught,{throw,{V,x4}}}, 605: undefined, 606: undefined, 607: finalized} = 608: nested_catch_1({{value,{V,x1}},void,try_clause}, 609: void, {exit,{V,x3}}, {throw,{V,x4}}), 610: %% 611: ?line {{value,{caught1,{V,x2}}}, 612: {V,x3}, 613: {V,x4}, 614: finalized} = 615: nested_catch_1({{error,{V,x1}},error,{V,x1}}, 616: {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), 617: ?line {{caught,{error,badarith}}, 618: {V,x3}, 619: {V,x4}, 620: finalized} = 621: nested_catch_1({{error,{V,x1}},error,{V,x1}}, 622: {'add',{1,c}}, {value,{V,x3}}, {value,{V,x4}}), 623: ?line {{caught,{error,badarith}}, 624: undefined, 625: {V,x4}, 626: finalized} = 627: nested_catch_1({{error,{V,x1}},error,{V,x1}}, 628: {'add',{1,c}}, {'div',{17,0}}, {value,{V,x4}}), 629: ?line {{caught,{error,badarg}}, 630: undefined, 631: undefined, 632: finalized} = 633: nested_catch_1({{error,{V,x1}},error,{V,x1}}, 634: {'add',{1,c}}, {'div',{17,0}}, {'abs',V}), 635: %% 636: ?line {{caught,{error,badarith}}, 637: {V,x3}, 638: {V,x4}, 639: finalized} = 640: nested_catch_1({{'add',{2,c}},rethrow,void}, 641: void, {value,{V,x3}}, {value,{V,x4}}), 642: ?line {{caught,{error,badarg}}, 643: undefined, 644: {V,x4}, 645: finalized} = 646: nested_catch_1({{'add',{2,c}},rethrow,void}, 647: void, {'abs',V}, {value,{V,x4}}), 648: ?line {{caught,{error,function_clause}}, 649: undefined, 650: undefined, 651: finalized} = 652: nested_catch_1({{'add',{2,c}},rethrow,void}, 653: void, {'abs',V}, function_clause), 654: ok. 655: 656: nested_catch_1({X1,C1,V1}, 657: X2, X3, X4) -> 658: erase(nested3), 659: erase(nested4), 660: erase(nested), 661: Throw = make_ref(), 662: Try = 663: try 664: try throw(Throw) 665: catch 666: Throw -> 667: try 668: foo(X1) 669: of 670: V1 -> {value1,foo(X2)} 671: catch 672: C1:V1 -> {caught1,foo(X2)} 673: after 674: put(nested3, foo(X3)) 675: end 676: after 677: put(nested4, foo(X4)) 678: end 679: of 680: V -> {value,V} 681: catch 682: C:D -> {caught,{C,D}} 683: after 684: put(nested, finalized) 685: end, 686: {Try,erase(nested3),erase(nested4),erase(nested)}. 687: 688: nested_after(Conf) when is_list(Conf) -> 689: V = [{make_ref(),1.4142136,self()}], 690: ?line {value, 691: {V,x3}, 692: {value1,{V,x2}}, 693: finalized} = 694: nested_after_1({{value,{V,x1}},void,{V,x1}}, 695: {value,{V,x2}}, {value,{V,x3}}), 696: ?line {{caught,{error,{V,x2}}}, 697: {V,x3}, 698: undefined, 699: finalized} = 700: nested_after_1({{value,{V,x1}},void,{V,x1}}, 701: {error,{V,x2}}, {value,{V,x3}}), 702: ?line {{caught,{exit,{V,x3}}}, 703: undefined, 704: undefined, 705: finalized} = 706: nested_after_1({{value,{V,x1}},void,{V,x1}}, 707: {error,{V,x2}}, {exit,{V,x3}}), 708: %% 709: ?line {{caught,{error,{try_clause,{V,x1}}}}, 710: {V,x3}, 711: undefined, 712: finalized} = 713: nested_after_1({{value,{V,x1}},void,try_clause}, 714: void, {value,{V,x3}}), 715: ?line {{caught,{error,badarith}}, 716: undefined, 717: undefined, 718: finalized} = 719: nested_after_1({{value,{V,x1}},void,try_clause}, 720: void, {'div',{17,0}}), 721: %% 722: ?line {value, 723: {V,x3}, 724: {caught1,{V,x2}}, 725: finalized} = 726: nested_after_1({{throw,{V,x1}},throw,{V,x1}}, 727: {value,{V,x2}}, {value,{V,x3}}), 728: ?line {{caught,{error,badarith}}, 729: {V,x3}, 730: undefined, 731: finalized} = 732: nested_after_1({{throw,{V,x1}},throw,{V,x1}}, 733: {'add',{a,b}}, {value,{V,x3}}), 734: ?line {{caught,{error,badarg}}, 735: undefined, 736: undefined, 737: finalized} = 738: nested_after_1({{throw,{V,x1}},throw,{V,x1}}, 739: {'add',{a,b}}, {'abs',V}), 740: %% 741: ?line {{caught,{throw,{V,x1}}}, 742: {V,x3}, 743: undefined, 744: finalized} = 745: nested_after_1({{throw,{V,x1}},rethrow,void}, 746: void, {value,{V,x3}}), 747: ?line {{caught,{error,badarith}}, 748: undefined, 749: undefined, 750: finalized} = 751: nested_after_1({{throw,{V,x1}},rethrow,void}, 752: void, {'div',{1,0}}), 753: ok. 754: 755: nested_after_1({X1,C1,V1}, 756: X2, X3) -> 757: erase(nested3), 758: erase(nested4), 759: erase(nested), 760: Self = self(), 761: Try = 762: try 763: try self() 764: after 765: After = 766: try 767: foo(X1) 768: of 769: V1 -> {value1,foo(X2)} 770: catch 771: C1:V1 -> {caught1,foo(X2)} 772: after 773: put(nested3, foo(X3)) 774: end, 775: put(nested4, After) 776: end 777: of 778: Self -> value 779: catch 780: C:D -> {caught,{C,D}} 781: after 782: put(nested, finalized) 783: end, 784: {Try,erase(nested3),erase(nested4),erase(nested)}. 785: 786: foo({value,Value}) -> Value; 787: foo({'div',{A,B}}) -> 788: my_div(A, B); 789: foo({'add',{A,B}}) -> 790: my_add(A, B); 791: foo({'abs',X}) -> 792: my_abs(X); 793: foo({error,Error}) -> 794: erlang:error(Error); 795: foo({throw,Throw}) -> 796: erlang:throw(Throw); 797: foo({exit,Exit}) -> 798: erlang:exit(Exit); 799: foo({raise,{Class,Reason}}) -> 800: erlang:raise(Class, Reason). 801: %%foo(function_clause) -> % must not be defined! 802: 803: my_div(A, B) -> 804: A div B. 805: 806: my_add(A, B) -> 807: A + B. 808: 809: my_abs(X) -> abs(X). 810: 811: id(I) -> I.