1: %% 2: %% %CopyrightBegin% 3: %% 4: %% Copyright Ericsson AB 2003-2013. 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: -module(erl_eval_SUITE). 20: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 21: init_per_group/2,end_per_group/2]). 22: 23: -export([guard_1/1, guard_2/1, 24: match_pattern/1, 25: match_bin/1, 26: string_plusplus/1, 27: pattern_expr/1, 28: guard_3/1, guard_4/1, 29: lc/1, 30: simple_cases/1, 31: unary_plus/1, 32: apply_atom/1, 33: otp_5269/1, 34: otp_6539/1, 35: otp_6543/1, 36: otp_6787/1, 37: otp_6977/1, 38: otp_7550/1, 39: otp_8133/1, 40: funs/1, 41: try_catch/1, 42: eval_expr_5/1]). 43: 44: %% 45: %% Define to run outside of test server 46: %% 47: %%-define(STANDALONE,1). 48: 49: -import(lists,[concat/1, sort/1]). 50: 51: -export([count_down/2, count_down_fun/0, do_apply/2, 52: local_func/3, local_func_value/2]). 53: 54: -ifdef(STANDALONE). 55: -define(config(A,B),config(A,B)). 56: -export([config/2]). 57: -define(line, noop, ). 58: config(priv_dir,_) -> 59: ".". 60: -else. 61: -include_lib("test_server/include/test_server.hrl"). 62: -export([init_per_testcase/2, end_per_testcase/2]). 63: % Default timetrap timeout (set in init_per_testcase). 64: -define(default_timeout, ?t:minutes(1)). 65: init_per_testcase(_Case, Config) -> 66: ?line Dog = ?t:timetrap(?default_timeout), 67: [{watchdog, Dog} | Config]. 68: end_per_testcase(_Case, Config) -> 69: Dog = ?config(watchdog, Config), 70: test_server:timetrap_cancel(Dog), 71: ok. 72: -endif. 73: 74: suite() -> [{ct_hooks,[ts_install_cth]}]. 75: 76: all() -> 77: [guard_1, guard_2, match_pattern, string_plusplus, 78: pattern_expr, match_bin, guard_3, guard_4, lc, 79: simple_cases, unary_plus, apply_atom, otp_5269, 80: otp_6539, otp_6543, otp_6787, otp_6977, otp_7550, 81: otp_8133, funs, try_catch, eval_expr_5]. 82: 83: groups() -> 84: []. 85: 86: init_per_suite(Config) -> 87: Config. 88: 89: end_per_suite(_Config) -> 90: ok. 91: 92: init_per_group(_GroupName, Config) -> 93: Config. 94: 95: end_per_group(_GroupName, Config) -> 96: Config. 97: 98: 99: guard_1(doc) -> 100: ["(OTP-2405)"]; 101: guard_1(suite) -> 102: []; 103: guard_1(Config) when is_list(Config) -> 104: ?line {ok,Tokens ,_} = 105: erl_scan:string("if a+4 == 4 -> yes; true -> no end. "), 106: ?line {ok, [Expr]} = erl_parse:parse_exprs(Tokens), 107: ?line no = guard_1_compiled(), 108: ?line {value, no, []} = erl_eval:expr(Expr, []), 109: ok. 110: 111: guard_1_compiled() -> 112: if a+4 == 4 -> yes; true -> no end. 113: 114: guard_2(doc) -> 115: ["Similar to guard_1, but type-correct"]; 116: guard_2(suite) -> 117: []; 118: guard_2(Config) when is_list(Config) -> 119: ?line {ok,Tokens ,_} = 120: erl_scan:string("if 6+4 == 4 -> yes; true -> no end. "), 121: ?line {ok, [Expr]} = erl_parse:parse_exprs(Tokens), 122: ?line no = guard_2_compiled(), 123: ?line {value, no, []} = erl_eval:expr(Expr, []), 124: ok. 125: 126: guard_2_compiled() -> 127: if 6+4 == 4 -> yes; true -> no end. 128: 129: string_plusplus(doc) -> 130: ["OTP-3069: syntactic sugar string ++ ..."]; 131: string_plusplus(suite) -> 132: []; 133: string_plusplus(Config) when is_list(Config) -> 134: ?line check(fun() -> case "abc" of "ab" ++ L -> L end end, 135: "case \"abc\" of \"ab\" ++ L -> L end. ", 136: "c"), 137: ?line check(fun() -> case "abcde" of "ab" ++ "cd" ++ L -> L end end, 138: "case \"abcde\" of \"ab\" ++ \"cd\" ++ L -> L end. ", 139: "e"), 140: ?line check(fun() -> case "abc" of [97, 98] ++ L -> L end end, 141: "case \"abc\" of [97, 98] ++ L -> L end. ", 142: "c"), 143: ok. 144: 145: match_pattern(doc) -> 146: ["OTP-2983: match operator in pattern"]; 147: match_pattern(suite) -> 148: []; 149: match_pattern(Config) when is_list(Config) -> 150: ?line check(fun() -> case {a, b} of {a, _X}=Y -> {x,Y} end end, 151: "case {a, b} of {a, X}=Y -> {x,Y} end. ", 152: {x, {a, b}}), 153: ?line check(fun() -> case {a, b} of Y={a, _X} -> {x,Y} end end, 154: "case {a, b} of Y={a, X} -> {x,Y} end. ", 155: {x, {a, b}}), 156: ?line check(fun() -> case {a, b} of Y={a, _X}=Z -> {Z,Y} end end, 157: "case {a, b} of Y={a, X}=Z -> {Z,Y} end. ", 158: {{a, b}, {a, b}}), 159: ?line check(fun() -> A = 4, B = 28, <<13:(A+(X=B))>>, X end, 160: "begin A = 4, B = 28, <<13:(A+(X=B))>>, X end.", 161: 28), 162: ok. 163: 164: match_bin(doc) -> 165: ["binary match problems"]; 166: match_bin(suite) -> 167: []; 168: match_bin(Config) when is_list(Config) -> 169: ?line check(fun() -> <<"abc">> = <<"abc">> end, 170: "<<\"abc\">> = <<\"abc\">>. ", 171: <<"abc">>), 172: ?line check(fun() -> 173: <<Size,B:Size/binary,Rest/binary>> = <<2,"AB","CD">>, 174: {Size,B,Rest} 175: end, 176: "begin <<Size,B:Size/binary,Rest/binary>> = <<2,\"AB\",\"CD\">>, " 177: "{Size,B,Rest} end. ", 178: {2,<<"AB">>,<<"CD">>}), 179: ok. 180: 181: pattern_expr(doc) -> 182: ["OTP-3144: compile-time expressions in pattern"]; 183: pattern_expr(suite) -> 184: []; 185: pattern_expr(Config) when is_list(Config) -> 186: ?line check(fun() -> case 4 of 2+2 -> ok end end, 187: "case 4 of 2+2 -> ok end. ", 188: ok), 189: ?line check(fun() -> case 2 of +2 -> ok end end, 190: "case 2 of +2 -> ok end. ", 191: ok), 192: ok. 193: 194: guard_3(doc) -> 195: ["OTP-4518."]; 196: guard_3(suite) -> 197: []; 198: guard_3(Config) when is_list(Config) -> 199: ?line check(fun() -> if false -> false; true -> true end end, 200: "if false -> false; true -> true end.", 201: true), 202: ?line check(fun() -> if <<"hej">> == <<"hopp">> -> true; 203: true -> false end end, 204: "begin if <<\"hej\">> == <<\"hopp\">> -> true; 205: true -> false end end.", 206: false), 207: ?line check(fun() -> if <<"hej">> == <<"hej">> -> true; 208: true -> false end end, 209: "begin if <<\"hej\">> == <<\"hej\">> -> true; 210: true -> false end end.", 211: true), 212: ok. 213: 214: guard_4(doc) -> 215: ["OTP-4885."]; 216: guard_4(suite) -> 217: []; 218: guard_4(Config) when is_list(Config) -> 219: check(fun() -> if erlang:'+'(3,a) -> true ; true -> false end end, 220: "if erlang:'+'(3,a) -> true ; true -> false end.", 221: false), 222: check(fun() -> if erlang:is_integer(3) -> true ; true -> false end 223: end, 224: "if erlang:is_integer(3) -> true ; true -> false end.", 225: true), 226: ?line check(fun() -> [X || X <- [1,2,3], erlang:is_integer(X)] end, 227: "[X || X <- [1,2,3], erlang:is_integer(X)].", 228: [1,2,3]), 229: ?line check(fun() -> if is_atom(is_integer(a)) -> true ; true -> false end 230: end, 231: "if is_atom(is_integer(a)) -> true ; true -> false end.", 232: true), 233: check(fun() -> if erlang:is_atom(erlang:is_integer(a)) -> true; 234: true -> false end end, 235: "if erlang:is_atom(erlang:is_integer(a)) -> true; " 236: "true -> false end.", 237: true), 238: ?line check(fun() -> if is_atom(3+a) -> true ; true -> false end end, 239: "if is_atom(3+a) -> true ; true -> false end.", 240: false), 241: ?line check(fun() -> if erlang:is_atom(3+a) -> true ; true -> false end 242: end, 243: "if erlang:is_atom(3+a) -> true ; true -> false end.", 244: false), 245: ok. 246: 247: 248: lc(doc) -> 249: ["OTP-4518."]; 250: lc(suite) -> 251: []; 252: lc(Config) when is_list(Config) -> 253: ?line check(fun() -> X = 32, [X || X <- [1,2,3]] end, 254: "begin X = 32, [X || X <- [1,2,3]] end.", 255: [1,2,3]), 256: ?line check(fun() -> X = 32, 257: [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end, 258: %% "binsize variable" ^ 259: "begin X = 32, 260: [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end.", 261: [1,2]), 262: ?line check(fun() -> Y = 13,[X || {X,Y} <- [{1,2}]] end, 263: "begin Y = 13,[X || {X,Y} <- [{1,2}]] end.", 264: [1]), 265: ?line error_check("begin [A || X <- [{1,2}], 1 == A] end.", 266: {unbound_var,'A'}), 267: ?line error_check("begin X = 32, 268: [{Y,W} || X <- [1,2,32,Y=4], Z <- [1,2,W=3]] end.", 269: {unbound_var,'Y'}), 270: ?line error_check("begin X = 32,<<A:B>> = <<100:X>> end.", 271: {unbound_var,'B'}), 272: ?line check(fun() -> [X || X <- [1,2,3,4], not (X < 2)] end, 273: "begin [X || X <- [1,2,3,4], not (X < 2)] end.", 274: [2,3,4]), 275: ?line check(fun() -> [X || X <- [true,false], X] end, 276: "[X || X <- [true,false], X].", [true]), 277: ok. 278: 279: simple_cases(doc) -> 280: ["Simple cases, just to cover some code."]; 281: simple_cases(suite) -> 282: []; 283: simple_cases(Config) when is_list(Config) -> 284: ?line check(fun() -> A = $C end, "A = $C.", $C), 285: %% ?line check(fun() -> A = 3.14 end, "A = 3.14.", 3.14), 286: ?line check(fun() -> self() ! a, A = receive a -> true end end, 287: "begin self() ! a, A = receive a -> true end end.", 288: true), 289: ?line check(fun() -> c:flush(), self() ! a, self() ! b, self() ! c, 290: receive b -> b end, 291: {messages, [a,c]} = 292: erlang:process_info(self(), messages), 293: c:flush() end, 294: "begin c:flush(), self() ! a, self() ! b, self() ! c," 295: "receive b -> b end," 296: "{messages, [a,c]} =" 297: " erlang:process_info(self(), messages), c:flush() end.", 298: ok), 299: ?line check(fun() -> self() ! a, A = receive a -> true 300: after 0 -> false end end, 301: "begin self() ! a, A = receive a -> true" 302: " after 0 -> false end end.", 303: true), 304: ?line check(fun() -> c:flush(), self() ! a, self() ! b, self() ! c, 305: receive b -> b after 0 -> true end, 306: {messages, [a,c]} = 307: erlang:process_info(self(), messages), 308: c:flush() end, 309: "begin c:flush(), self() ! a, self() ! b, self() ! c," 310: "receive b -> b after 0 -> true end," 311: "{messages, [a,c]} =" 312: " erlang:process_info(self(), messages), c:flush() end.", 313: ok), 314: ?line check(fun() -> receive _ -> true after 10 -> false end end, 315: "receive _ -> true after 10 -> false end.", 316: false), 317: ?line check(fun() -> F = fun(A) -> A end, true = 3 == F(3) end, 318: "begin F = fun(A) -> A end, true = 3 == F(3) end.", 319: true), 320: ?line check(fun() -> F = fun(A) -> A end, true = 3 == apply(F, [3]) end, 321: "begin F = fun(A) -> A end, true = 3 == apply(F,[3]) end.", 322: true), 323: ?line check(fun() -> catch throw(a) end, "catch throw(a).", a), 324: ?line check(fun() -> catch a end, "catch a.", a), 325: ?line check(fun() -> 4 == 3 end, "4 == 3.", false), 326: ?line check(fun() -> not true end, "not true.", false), 327: ?line check(fun() -> -3 end, "-3.", -3), 328: 329: ?line error_check("3.0 = 4.0.", {badmatch,4.0}), 330: ?line check(fun() -> <<(3.0+2.0):32/float>> = <<5.0:32/float>> end, 331: "<<(3.0+2.0):32/float>> = <<5.0:32/float>>.", 332: <<5.0:32/float>>), 333: 334: ?line check(fun() -> false andalso kludd end, "false andalso kludd.", 335: false), 336: ?line check(fun() -> true andalso true end, "true andalso true.", 337: true), 338: ?line check(fun() -> true andalso false end, "true andalso false.", 339: false), 340: ?line check(fun() -> true andalso kludd end, "true andalso kludd.", 341: kludd), 342: ?line error_check("kladd andalso kludd.", {badarg,kladd}), 343: 344: ?line check(fun() -> if false andalso kludd -> a; true -> b end end, 345: "if false andalso kludd -> a; true -> b end.", 346: b), 347: ?line check(fun() -> if true andalso true -> a; true -> b end end, 348: "if true andalso true -> a; true -> b end.", 349: a), 350: ?line check(fun() -> if true andalso false -> a; true -> b end end, 351: "if true andalso false -> a; true -> b end.", 352: b), 353: 354: ?line check(fun() -> true orelse kludd end, 355: "true orelse kludd.", true), 356: ?line check(fun() -> false orelse false end, 357: "false orelse false.", false), 358: ?line check(fun() -> false orelse true end, 359: "false orelse true.", true), 360: ?line check(fun() -> false orelse kludd end, 361: "false orelse kludd.", kludd), 362: ?line error_check("kladd orelse kludd.", {badarg,kladd}), 363: ?line error_check("[X || X <- [1,2,3], begin 1 end].",{bad_filter,1}), 364: ?line error_check("[X || X <- a].",{bad_generator,a}), 365: 366: ?line check(fun() -> if true orelse kludd -> a; true -> b end end, 367: "if true orelse kludd -> a; true -> b end.", a), 368: ?line check(fun() -> if false orelse false -> a; true -> b end end, 369: "if false orelse false -> a; true -> b end.", b), 370: ?line check(fun() -> if false orelse true -> a; true -> b end end, 371: "if false orelse true -> a; true -> b end.", a), 372: 373: ?line check(fun() -> [X || X <- [1,2,3], X+2] end, 374: "[X || X <- [1,2,3], X+2].", []), 375: 376: ?line check(fun() -> [X || X <- [1,2,3], [X] == [X || X <- [2]]] end, 377: "[X || X <- [1,2,3], [X] == [X || X <- [2]]].", 378: [2]), 379: ?line check(fun() -> F = fun(1) -> ett; (2) -> zwei end, 380: ett = F(1), zwei = F(2) end, 381: "begin F = fun(1) -> ett; (2) -> zwei end, 382: ett = F(1), zwei = F(2) end.", 383: zwei), 384: ?line check(fun() -> F = fun(X) when X == 1 -> ett; 385: (X) when X == 2 -> zwei end, 386: ett = F(1), zwei = F(2) end, 387: "begin F = fun(X) when X == 1 -> ett; 388: (X) when X == 2 -> zwei end, 389: ett = F(1), zwei = F(2) end.", 390: zwei), 391: ?line error_check("begin F = fun(1) -> ett end, zwei = F(2) end.", 392: function_clause), 393: ?line check(fun() -> if length([1]) == 1 -> yes; 394: true -> no end end, 395: "if length([1]) == 1 -> yes; 396: true -> no end.", 397: yes), 398: ?line check(fun() -> if is_integer(3) -> true; true -> false end end, 399: "if is_integer(3) -> true; true -> false end.", true), 400: ?line check(fun() -> if integer(3) -> true; true -> false end end, 401: "if integer(3) -> true; true -> false end.", true), 402: ?line check(fun() -> if is_float(3) -> true; true -> false end end, 403: "if is_float(3) -> true; true -> false end.", false), 404: ?line check(fun() -> if float(3) -> true; true -> false end end, 405: "if float(3) -> true; true -> false end.", false), 406: ?line check(fun() -> if is_number(3) -> true; true -> false end end, 407: "if is_number(3) -> true; true -> false end.", true), 408: ?line check(fun() -> if number(3) -> true; true -> false end end, 409: "if number(3) -> true; true -> false end.", true), 410: ?line check(fun() -> if is_atom(a) -> true; true -> false end end, 411: "if is_atom(a) -> true; true -> false end.", true), 412: ?line check(fun() -> if atom(a) -> true; true -> false end end, 413: "if atom(a) -> true; true -> false end.", true), 414: ?line check(fun() -> if is_list([]) -> true; true -> false end end, 415: "if is_list([]) -> true; true -> false end.", true), 416: ?line check(fun() -> if list([]) -> true; true -> false end end, 417: "if list([]) -> true; true -> false end.", true), 418: ?line check(fun() -> if is_tuple({}) -> true; true -> false end end, 419: "if is_tuple({}) -> true; true -> false end.", true), 420: ?line check(fun() -> if tuple({}) -> true; true -> false end end, 421: "if tuple({}) -> true; true -> false end.", true), 422: ?line check(fun() -> if is_pid(self()) -> true; true -> false end end, 423: "if is_pid(self()) -> true; true -> false end.", true), 424: ?line check(fun() -> if pid(self()) -> true; true -> false end end, 425: "if pid(self()) -> true; true -> false end.", true), 426: ?line check(fun() -> R = make_ref(), if is_reference(R) -> true; 427: true -> false end end, 428: "begin R = make_ref(), if is_reference(R) -> true;" 429: "true -> false end end.", true), 430: ?line check(fun() -> R = make_ref(), if reference(R) -> true; 431: true -> false end end, 432: "begin R = make_ref(), if reference(R) -> true;" 433: "true -> false end end.", true), 434: ?line check(fun() -> if is_port(a) -> true; true -> false end end, 435: "if is_port(a) -> true; true -> false end.", false), 436: ?line check(fun() -> if port(a) -> true; true -> false end end, 437: "if port(a) -> true; true -> false end.", false), 438: ?line check(fun() -> if is_function(a) -> true; true -> false end end, 439: "if is_function(a) -> true; true -> false end.", false), 440: ?line check(fun() -> if function(a) -> true; true -> false end end, 441: "if function(a) -> true; true -> false end.", false), 442: ?line check(fun() -> if is_binary(<<>>) -> true; true -> false end end, 443: "if is_binary(<<>>) -> true; true -> false end.", true), 444: ?line check(fun() -> if binary(<<>>) -> true; true -> false end end, 445: "if binary(<<>>) -> true; true -> false end.", true), 446: ?line check(fun() -> if is_integer(a) == true -> yes; 447: true -> no end end, 448: "if is_integer(a) == true -> yes; 449: true -> no end.", 450: no), 451: ?line check(fun() -> if [] -> true; true -> false end end, 452: "if [] -> true; true -> false end.", false), 453: ?line error_check("if lists:member(1,[1]) -> true; true -> false end.", 454: illegal_guard_expr), 455: ?line error_check("if false -> true end.", if_clause), 456: ?line check(fun() -> if a+b -> true; true -> false end end, 457: "if a + b -> true; true -> false end.", false), 458: ?line check(fun() -> if + b -> true; true -> false end end, 459: "if + b -> true; true -> false end.", false), 460: ?line error_check("case foo of bar -> true end.", {case_clause,foo}), 461: ?line error_check("case 4 of 2+a -> true; _ -> false end.", 462: illegal_pattern), 463: ?line error_check("case 4 of +a -> true; _ -> false end.", 464: illegal_pattern), 465: ?line check(fun() -> case a of 466: X when X == b -> one; 467: X when X == a -> two 468: end end, 469: "begin case a of 470: X when X == b -> one; 471: X when X == a -> two 472: end end.", two), 473: ?line error_check("3 = 4.", {badmatch,4}), 474: ?line error_check("a = 3.", {badmatch,3}), 475: %% ?line error_check("3.1 = 2.7.",{badmatch,2.7}), 476: ?line error_check("$c = 4.", {badmatch,4}), 477: ?line check(fun() -> $c = $c end, "$c = $c.", $c), 478: ?line check(fun() -> _ = bar end, "_ = bar.", bar), 479: ?line check(fun() -> A = 14, A = 14 end, 480: "begin A = 14, A = 14 end.", 14), 481: ?line error_check("begin A = 14, A = 16 end.", {badmatch,16}), 482: ?line error_check("\"hej\" = \"san\".", {badmatch,"san"}), 483: ?line check(fun() -> "hej" = "hej" end, 484: "\"hej\" = \"hej\".", "hej"), 485: ?line error_check("[] = [a].", {badmatch,[a]}), 486: ?line check(fun() -> [] = [] end, "[] = [].", []), 487: ?line error_check("[a] = [].", {badmatch,[]}), 488: ?line error_check("{a,b} = 34.", {badmatch,34}), 489: ?line check(fun() -> <<X:7>> = <<8:7>>, X end, 490: "begin <<X:7>> = <<8:7>>, X end.", 8), 491: ?line error_check("<<34:32>> = \"hej\".", {badmatch,"hej"}), 492: ?line check(fun() -> trunc((1 * 3 div 3 + 4 - 3) / 1) rem 2 end, 493: "begin trunc((1 * 3 div 3 + 4 - 3) / 1) rem 2 end.", 0), 494: ?line check(fun() -> (2#101 band 2#10101) bor (2#110 bxor 2#010) end, 495: "(2#101 band 2#10101) bor (2#110 bxor 2#010).", 5), 496: ?line check(fun() -> (2#1 bsl 4) + (2#10000 bsr 3) end, 497: "(2#1 bsl 4) + (2#10000 bsr 3).", 18), 498: ?line check(fun() -> ((1<3) and ((1 =:= 2) or (1 =/= 2))) xor (1=<2) end, 499: "((1<3) and ((1 =:= 2) or (1 =/= 2))) xor (1=<2).", false), 500: ?line check(fun() -> (a /= b) or (2 > 4) or (3 >= 3) end, 501: "(a /= b) or (2 > 4) or (3 >= 3).", true), 502: ?line check(fun() -> "hej" ++ "san" =/= "hejsan" -- "san" end, 503: "\"hej\" ++ \"san\" =/= \"hejsan\" -- \"san\".", true), 504: ?line check(fun() -> (bnot 1) < -0 end, "(bnot (+1)) < -0.", true), 505: ok. 506: 507: unary_plus(doc) -> 508: ["OTP-4929. Unary plus rejects non-numbers."]; 509: unary_plus(suite) -> 510: []; 511: unary_plus(Config) when is_list(Config) -> 512: ?line check(fun() -> F = fun(X) -> + X end, 513: true = -1 == F(-1) end, 514: "begin F = fun(X) -> + X end," 515: " true = -1 == F(-1) end.", true, ['F'], none, none), 516: ?line error_check("+a.", badarith), 517: ok. 518: 519: apply_atom(doc) -> 520: ["OTP-5064. Can no longer apply atoms."]; 521: apply_atom(suite) -> 522: []; 523: apply_atom(Config) when is_list(Config) -> 524: ?line error_check("[X || X <- [[1],[2]], 525: begin L = length, L(X) =:= 1 end].", 526: {badfun,length}), 527: ok. 528: 529: otp_5269(doc) -> 530: ["OTP-5269. Bugs in the bit syntax."]; 531: otp_5269(suite) -> 532: []; 533: otp_5269(Config) when is_list(Config) -> 534: ?line check(fun() -> L = 8, 535: F = fun(<<A:L,B:A>>) -> B end, 536: F(<<16:8, 7:16>>) 537: end, 538: "begin 539: L = 8, F = fun(<<A:L,B:A>>) -> B end, F(<<16:8, 7:16>>) 540: end.", 541: 7), 542: ?line check(fun() -> L = 8, 543: F = fun(<<L:L,B:L>>) -> B end, 544: F(<<16:8, 7:16>>) 545: end, 546: "begin 547: L = 8, F = fun(<<L:L,B:L>>) -> B end, F(<<16:8, 7:16>>) 548: end.", 549: 7), 550: ?line check(fun() -> L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end, 551: "begin L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end.", 552: 7), 553: ?line error_check("begin L = 8, <<L:L,B:L>> = <<16:8, 7:16>> end.", 554: {badmatch,<<16:8,7:16>>}), 555: 556: ?line error_check("begin <<L:16,L:L>> = <<16:16,8:16>>, L end.", 557: {badmatch, <<16:16,8:16>>}), 558: ?line check(fun() -> U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end, 559: "begin U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end.", 560: 32), 561: ?line check(fun() -> U = 8, [U || <<U:U>> <- [<<32:8>>]] end, 562: "begin U = 8, [U || <<U:U>> <- [<<32:8>>]] end.", 563: [32]), 564: ?line error_check("(fun({3,<<A:32,A:32>>}) -> a end) 565: ({3,<<17:32,19:32>>}).", 566: function_clause), 567: ?line check(fun() -> [X || <<A:8, 568: B:A>> <- [<<16:8,19:16>>], 569: <<X:8>> <- [<<B:8>>]] end, 570: "[X || <<A:8, 571: B:A>> <- [<<16:8,19:16>>], 572: <<X:8>> <- [<<B:8>>]].", 573: [19]), 574: ok. 575: 576: otp_6539(doc) -> 577: ["OTP-6539. try/catch bugs."]; 578: otp_6539(suite) -> 579: []; 580: otp_6539(Config) when is_list(Config) -> 581: ?line check(fun() -> 582: F = fun(A,B) -> 583: try A+B 584: catch _:_ -> dontthinkso 585: end 586: end, 587: lists:zipwith(F, [1,2], [2,3]) 588: end, 589: "begin 590: F = fun(A,B) -> 591: try A+B 592: catch _:_ -> dontthinkso 593: end 594: end, 595: lists:zipwith(F, [1,2], [2,3]) 596: end.", 597: [3, 5]), 598: ok. 599: 600: otp_6543(doc) -> 601: ["OTP-6543. bitlevel binaries."]; 602: otp_6543(suite) -> 603: []; 604: otp_6543(Config) when is_list(Config) -> 605: ?line check(fun() -> 606: << <<X>> || <<X>> <- [1,2,3] >> 607: end, 608: "<< <<X>> || <<X>> <- [1,2,3] >>.", 609: <<>>), 610: ?line check(fun() -> 611: << <<X>> || X <- [1,2,3] >> 612: end, 613: "<< <<X>> || X <- [1,2,3] >>.", 614: <<1,2,3>>), 615: ?line check(fun() -> 616: << <<X:8>> || <<X:2>> <= <<"hej">> >> 617: end, 618: "<< <<X:8>> || <<X:2>> <= <<\"hej\">> >>.", 619: <<1,2,2,0,1,2,1,1,1,2,2,2>>), 620: ?line check(fun() -> 621: << <<X:8>> || 622: <<65,X:4>> <= <<65,7:4,65,3:4,66,8:4>> >> 623: end, 624: "<< <<X:8>> || 625: <<65,X:4>> <= <<65,7:4,65,3:4,66,8:4>> >>.", 626: <<7,3>>), 627: ?line check(fun() -> <<34:18/big>> end, 628: "<<34:18/big>>.", 629: <<0,8,2:2>>), 630: ?line check(fun() -> <<34:18/big-unit:2>> end, 631: "<<34:18/big-unit:2>>.", 632: <<0,0,0,2,2:4>>), 633: ?line check(fun() -> <<34:18/little>> end, 634: "<<34:18/little>>.", 635: <<34,0,0:2>>), 636: ?line case eval_string("<<34:18/native>>.") of 637: <<0,8,2:2>> -> ok; 638: <<34,0,0:2>> -> ok 639: end, 640: ?line check(fun() -> <<34:18/big-signed>> end, 641: "<<34:18/big-signed>>.", 642: <<0,8,2:2>>), 643: ?line check(fun() -> <<34:18/little-signed>> end, 644: "<<34:18/little-signed>>.", 645: <<34,0,0:2>>), 646: ?line case eval_string("<<34:18/native-signed>>.") of 647: <<0,8,2:2>> -> ok; 648: <<34,0,0:2>> -> ok 649: end, 650: ?line check(fun() -> <<34:18/big-unsigned>> end, 651: "<<34:18/big-unsigned>>.", 652: <<0,8,2:2>>), 653: ?line check(fun() -> <<34:18/little-unsigned>> end, 654: "<<34:18/little-unsigned>>.", 655: <<34,0,0:2>>), 656: ?line case eval_string("<<34:18/native-unsigned>>.") of 657: <<0,8,2:2>> -> ok; 658: <<34,0,0:2>> -> ok 659: end, 660: ?line check(fun() -> <<3.14:32/float-big>> end, 661: "<<3.14:32/float-big>>.", 662: <<64,72,245,195>>), 663: ?line check(fun() -> <<3.14:32/float-little>> end, 664: "<<3.14:32/float-little>>.", 665: <<195,245,72,64>>), 666: ?line case eval_string("<<3.14:32/float-native>>.") of 667: <<64,72,245,195>> -> ok; 668: <<195,245,72,64>> -> ok 669: end, 670: ?line error_check("<<(<<17,3:2>>)/binary>>.", badarg), 671: ?line check(fun() -> <<(<<17,3:2>>)/bitstring>> end, 672: "<<(<<17,3:2>>)/bitstring>>.", 673: <<17,3:2>>), 674: ?line check(fun() -> <<(<<17,3:2>>):10/bitstring>> end, 675: "<<(<<17,3:2>>):10/bitstring>>.", 676: <<17,3:2>>), 677: ?line check(fun() -> <<<<344:17>>/binary-unit:17>> end, 678: "<<<<344:17>>/binary-unit:17>>.", 679: <<344:17>>), 680: 681: ?line check(fun() -> <<X:18/big>> = <<34:18/big>>, X end, 682: "begin <<X:18/big>> = <<34:18/big>>, X end.", 683: 34), 684: ?line check(fun() -> <<X:18/big-unit:2>> = <<34:18/big-unit:2>>, X end, 685: "begin <<X:18/big-unit:2>> = <<34:18/big-unit:2>>, X end.", 686: 34), 687: ?line check(fun() -> <<X:18/little>> = <<34:18/little>>, X end, 688: "begin <<X:18/little>> = <<34:18/little>>, X end.", 689: 34), 690: ?line check(fun() -> <<X:18/native>> = <<34:18/native>>, X end, 691: "begin <<X:18/native>> = <<34:18/native>>, X end.", 692: 34), 693: ?line check(fun() -> <<X:18/big-signed>> = <<34:18/big-signed>>, X end, 694: "begin <<X:18/big-signed>> = <<34:18/big-signed>>, X end.", 695: 34), 696: ?line check(fun() -> <<X:18/little-signed>> = <<34:18/little-signed>>, 697: X end, 698: "begin <<X:18/little-signed>> = <<34:18/little-signed>>, 699: X end.", 700: 34), 701: ?line check(fun() -> <<X:18/native-signed>> = <<34:18/native-signed>>, 702: X end, 703: "begin <<X:18/native-signed>> = <<34:18/native-signed>>, 704: X end.", 705: 34), 706: ?line check(fun() -> <<X:18/big-unsigned>> = <<34:18/big-unsigned>>, 707: X end, 708: "begin <<X:18/big-unsigned>> = <<34:18/big-unsigned>>, 709: X end.", 710: 34), 711: ?line check(fun() -> 712: <<X:18/little-unsigned>> = <<34:18/little-unsigned>>, 713: X end, 714: "begin <<X:18/little-unsigned>> = <<34:18/little-unsigned>>, 715: X end.", 716: 34), 717: ?line check(fun() -> 718: <<X:18/native-unsigned>> = <<34:18/native-unsigned>>, 719: X end, 720: "begin <<X:18/native-unsigned>> = <<34:18/native-unsigned>>, 721: X end.", 722: 34), 723: ?line check(fun() -> <<X:32/float-big>> = <<2.0:32/float-big>>, X end, 724: "begin <<X:32/float-big>> = <<2.0:32/float-big>>, 725: X end.", 726: 2.0), 727: ?line check(fun() -> <<X:32/float-little>> = <<2.0:32/float-little>>, 728: X end, 729: "begin <<X:32/float-little>> = <<2.0:32/float-little>>, 730: X end.", 731: 2.0), 732: ?line check(fun() -> <<X:32/float-native>> = <<2.0:32/float-native>>, 733: X end, 734: "begin <<X:32/float-native>> = <<2.0:32/float-native>>, 735: X end.", 736: 2.0), 737: 738: ?line check( 739: fun() -> 740: [X || <<"hej",X:8>> <= <<"hej",8,"san",9,"hej",17,"hej">>] 741: end, 742: "[X || <<\"hej\",X:8>> <= 743: <<\"hej\",8,\"san\",9,\"hej\",17,\"hej\">>].", 744: [8,17]), 745: ?line check( 746: fun() -> 747: L = 8, << <<B:32>> || <<L:L,B:L>> <= <<16:8, 7:16>> >> 748: end, 749: "begin L = 8, << <<B:32>> || <<L:L,B:L>> <= <<16:8, 7:16>> >> 750: end.", 751: <<0,0,0,7>>), 752: %% Test the Value part of a binary segment. 753: %% "Old" bugs have been fixed (partial_eval is called on Value). 754: ?line check(fun() -> [ 3 || <<17/float>> <= <<17.0/float>>] end, 755: "[ 3 || <<17/float>> <= <<17.0/float>>].", 756: [3]), 757: ?line check(fun() -> [ 3 || <<17/float>> <- [<<17.0/float>>]] end, 758: "[ 3 || <<17/float>> <- [<<17.0/float>>]].", 759: [3]), 760: ?line check(fun() -> [ X || <<17/float,X:3>> <= <<17.0/float,2:3>>] end, 761: "[ X || <<17/float,X:3>> <= <<17.0/float,2:3>>].", 762: [2]), 763: ?line check(fun() -> 764: [ foo || <<(1 bsl 1023)/float>> <= <<(1 bsl 1023)/float>>] 765: end, 766: "[ foo || <<(1 bsl 1023)/float>> <= <<(1 bsl 1023)/float>>].", 767: [foo]), 768: ?line check(fun() -> 769: [ foo || <<(1 bsl 1023)/float>> <- [<<(1 bsl 1023)/float>>]] 770: end, 771: "[ foo || <<(1 bsl 1023)/float>> <- [<<(1 bsl 1023)/float>>]].", 772: [foo]), 773: ?line error_check("[ foo || <<(1 bsl 1024)/float>> <- 774: [<<(1 bsl 1024)/float>>]].", 775: badarg), 776: ?line check(fun() -> 777: [ foo || <<(1 bsl 1024)/float>> <- [<<(1 bsl 1023)/float>>]] 778: end, 779: "[ foo || <<(1 bsl 1024)/float>> <- 780: [<<(1 bsl 1023)/float>>]].", 781: []), 782: ?line check(fun() -> 783: [ foo || <<(1 bsl 1024)/float>> <= <<(1 bsl 1023)/float>>] 784: end, 785: "[ foo || <<(1 bsl 1024)/float>> <= 786: <<(1 bsl 1023)/float>>].", 787: []), 788: ?line check(fun() -> 789: L = 8, 790: [{L,B} || <<L:L,B:L/float>> <= <<32:8,7:32/float>>] 791: end, 792: "begin L = 8, 793: [{L,B} || <<L:L,B:L/float>> <= <<32:8,7:32/float>>] 794: end.", 795: [{32,7.0}]), 796: ?line check(fun() -> 797: L = 8, 798: [{L,B} || <<L:L,B:L/float>> <- [<<32:8,7:32/float>>]] 799: end, 800: "begin L = 8, 801: [{L,B} || <<L:L,B:L/float>> <- [<<32:8,7:32/float>>]] 802: end.", 803: [{32,7.0}]), 804: ?line check(fun() -> 805: [foo || <<"s">> <= <<"st">>] 806: end, 807: "[foo || <<\"s\">> <= <<\"st\">>].", 808: [foo]), 809: ?line check(fun() -> <<_:32>> = <<17:32>> end, 810: "<<_:32>> = <<17:32>>.", 811: <<17:32>>), 812: ?line check(fun() -> [foo || <<_:32>> <= <<17:32,20:32>>] end, 813: "[foo || <<_:32>> <= <<17:32,20:32>>].", 814: [foo,foo]), 815: 816: ?line check(fun() -> << <<X:32>> || X <- [1,2,3], X > 1 >> end, 817: "<< <<X:32>> || X <- [1,2,3], X > 1 >>.", 818: <<0,0,0,2,0,0,0,3>>), 819: ?line error_check("[X || <<X>> <= [a,b]].",{bad_generator,[a,b]}), 820: ok. 821: 822: otp_6787(doc) -> 823: ["OTP-6787. bitlevel binaries."]; 824: otp_6787(suite) -> 825: []; 826: otp_6787(Config) when is_list(Config) -> 827: ?line check( 828: fun() -> <<16:(1024*1024)>> = <<16:(1024*1024)>> end, 829: "<<16:(1024*1024)>> = <<16:(1024*1024)>>.", 830: <<16:1048576>>), 831: ok. 832: 833: otp_6977(doc) -> 834: ["OTP-6977. ++ bug."]; 835: otp_6977(suite) -> 836: []; 837: otp_6977(Config) when is_list(Config) -> 838: ?line check( 839: fun() -> (fun([$X] ++ _) -> ok end)("X") end, 840: "(fun([$X] ++ _) -> ok end)(\"X\").", 841: ok), 842: ok. 843: 844: otp_7550(doc) -> 845: ["OTP-7550. Support for UTF-8, UTF-16, UTF-32."]; 846: otp_7550(Config) when is_list(Config) -> 847: 848: %% UTF-8. 849: ?line check( 850: fun() -> <<65>> = <<65/utf8>> end, 851: "<<65>> = <<65/utf8>>.", 852: <<65>>), 853: ?line check( 854: fun() -> <<350/utf8>> = <<197,158>> end, 855: "<<350/utf8>> = <<197,158>>.", 856: <<197,158>>), 857: ?line check( 858: fun() -> <<$b,$j,$\303,$\266,$r,$n>> = <<"bj\366rn"/utf8>> end, 859: "<<$b,$j,$\303,$\266,$r,$n>> = <<\"bj\366rn\"/utf8>>.", 860: <<$b,$j,$\303,$\266,$r,$n>>), 861: 862: %% UTF-16. 863: ?line check( 864: fun() -> <<0,65>> = <<65/utf16>> end, 865: "<<0,65>> = <<65/utf16>>.", 866: <<0,65>>), 867: ?line check( 868: fun() -> <<16#D8,16#08,16#DF,16#45>> = <<16#12345/utf16>> end, 869: "<<16#D8,16#08,16#DF,16#45>> = <<16#12345/utf16>>.", 870: <<16#D8,16#08,16#DF,16#45>>), 871: ?line check( 872: fun() -> <<16#08,16#D8,16#45,16#DF>> = <<16#12345/little-utf16>> end, 873: "<<16#08,16#D8,16#45,16#DF>> = <<16#12345/little-utf16>>.", 874: <<16#08,16#D8,16#45,16#DF>>), 875: 876: ?line check( 877: fun() -> <<350/utf16>> = <<1,94>> end, 878: "<<350/utf16>> = <<1,94>>.", 879: <<1,94>>), 880: ?line check( 881: fun() -> <<350/little-utf16>> = <<94,1>> end, 882: "<<350/little-utf16>> = <<94,1>>.", 883: <<94,1>>), 884: ?line check( 885: fun() -> <<16#12345/utf16>> = <<16#D8,16#08,16#DF,16#45>> end, 886: "<<16#12345/utf16>> = <<16#D8,16#08,16#DF,16#45>>.", 887: <<16#D8,16#08,16#DF,16#45>>), 888: ?line check( 889: fun() -> <<16#12345/little-utf16>> = <<16#08,16#D8,16#45,16#DF>> end, 890: "<<16#12345/little-utf16>> = <<16#08,16#D8,16#45,16#DF>>.", 891: <<16#08,16#D8,16#45,16#DF>>), 892: 893: %% UTF-32. 894: ?line check( 895: fun() -> <<16#12345/utf32>> = <<16#0,16#01,16#23,16#45>> end, 896: "<<16#12345/utf32>> = <<16#0,16#01,16#23,16#45>>.", 897: <<16#0,16#01,16#23,16#45>>), 898: ?line check( 899: fun() -> <<16#0,16#01,16#23,16#45>> = <<16#12345/utf32>> end, 900: "<<16#0,16#01,16#23,16#45>> = <<16#12345/utf32>>.", 901: <<16#0,16#01,16#23,16#45>>), 902: ?line check( 903: fun() -> <<16#12345/little-utf32>> = <<16#45,16#23,16#01,16#00>> end, 904: "<<16#12345/little-utf32>> = <<16#45,16#23,16#01,16#00>>.", 905: <<16#45,16#23,16#01,16#00>>), 906: ?line check( 907: fun() -> <<16#12345/little-utf32>> end, 908: "<<16#12345/little-utf32>>.", 909: <<16#45,16#23,16#01,16#00>>), 910: 911: %% Mixed. 912: ?line check( 913: fun() -> <<16#41,16#12345/utf32,16#0391:16,16#2E:8>> end, 914: "<<16#41,16#12345/utf32,16#0391:16,16#2E:8>>.", 915: <<16#41,16#00,16#01,16#23,16#45,16#03,16#91,16#2E>>), 916: ok. 917: 918: 919: otp_8133(doc) -> 920: ["OTP-8133. Bit comprehension bug."]; 921: otp_8133(suite) -> 922: []; 923: otp_8133(Config) when is_list(Config) -> 924: ?line check( 925: fun() -> 926: E = fun(N) -> 927: if 928: is_integer(N) -> <<N/integer>>; 929: true -> throw(foo) 930: end 931: end, 932: try << << (E(V))/binary >> || V <- [1,2,3,a] >> 933: catch foo -> ok 934: end 935: end, 936: "begin 937: E = fun(N) -> 938: if is_integer(N) -> <<N/integer>>; 939: true -> throw(foo) 940: end 941: end, 942: try << << (E(V))/binary >> || V <- [1,2,3,a] >> 943: catch foo -> ok 944: end 945: end.", 946: ok), 947: ?line check( 948: fun() -> 949: E = fun(N) -> 950: if 951: is_integer(N) -> <<N/integer>>; 952: true -> erlang:error(foo) 953: end 954: end, 955: try << << (E(V))/binary >> || V <- [1,2,3,a] >> 956: catch error:foo -> ok 957: end 958: end, 959: "begin 960: E = fun(N) -> 961: if is_integer(N) -> <<N/integer>>; 962: true -> erlang:error(foo) 963: end 964: end, 965: try << << (E(V))/binary >> || V <- [1,2,3,a] >> 966: catch error:foo -> ok 967: end 968: end.", 969: ok), 970: ok. 971: 972: funs(doc) -> 973: ["Simple cases, just to cover some code."]; 974: funs(suite) -> 975: []; 976: funs(Config) when is_list(Config) -> 977: do_funs(none, none), 978: do_funs(lfh(), none), 979: do_funs(lfh(), efh()), 980: 981: ?line error_check("nix:foo().", {access_not_allowed,nix}, lfh(), efh()), 982: ?line error_check("bar().", undef, none, none), 983: 984: ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end, 985: F1(F1, 1000) end, 986: "begin F1 = fun(F,N) -> count_down(F, N) end," 987: "F1(F1,1000) end.", 988: 0, ['F1'], lfh(), none), 989: 990: ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end, 991: F1(F1, 1000) end, 992: "begin F1 = fun(F,N) -> count_down(F, N) end," 993: "F1(F1,1000) end.", 994: 0, ['F1'], lfh_value(), none), 995: 996: ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end, 997: F1(F1, 1000) end, 998: "begin F1 = fun(F,N) -> count_down(F, N) end," 999: "F1(F1,1000) end.", 1000: 0, ['F1'], lfh_value_extra(), none), 1001: 1002: ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end, 1003: F1(F1, 1000) end, 1004: "begin F1 = fun(F,N) -> count_down(F, N) end," 1005: "F1(F1,1000) end.", 1006: 0, ['F1'], {?MODULE,local_func_value}, none), 1007: %% This is not documented, and only for backward compatibility (good!). 1008: B0 = erl_eval:new_bindings(), 1009: ?line check(fun() -> is_function(?MODULE:count_down_fun()) end, 1010: "begin is_function(count_down_fun()) end.", 1011: true, [], {?MODULE,local_func,[B0]},none), 1012: 1013: EF = fun({timer,sleep}, As) when length(As) == 1 -> exit({got_it,sleep}); 1014: ({M,F}, As) -> apply(M, F, As) 1015: end, 1016: EFH = {value, EF}, 1017: ?line error_check("apply(timer, sleep, [1]).", got_it, none, EFH), 1018: ?line error_check("begin F = fun(T) -> timer:sleep(T) end,F(1) end.", 1019: got_it, none, EFH), 1020: ?line error_check("fun c/1.", undef), 1021: ?line error_check("fun a:b/0().", undef), 1022: 1023: MaxArgs = 20, 1024: ?line [true] = 1025: lists:usort([run_many_args(SAs) || SAs <- many_args(MaxArgs)]), 1026: ?line {'EXIT',{{argument_limit,_},_}} = 1027: (catch run_many_args(many_args1(MaxArgs+1))), 1028: ok. 1029: 1030: run_many_args({S, As}) -> 1031: apply(eval_string(S), As) =:= As. 1032: 1033: many_args(N) -> 1034: [many_args1(I) || I <- lists:seq(1, N)]. 1035: 1036: many_args1(N) -> 1037: F = fun(L, P) -> 1038: tl(lists:flatten([","++P++integer_to_list(E) || E <- L])) 1039: end, 1040: L = lists:seq(1, N), 1041: T = F(L, "V"), 1042: S = lists:flatten(io_lib:format("fun(~s) -> [~s] end.", [T, T])), 1043: {S, L}. 1044: 1045: do_funs(LFH, EFH) -> 1046: %% LFH is not really used by these examples... 1047: 1048: %% These tests do not prove that tail recursive functions really 1049: %% work (that the process does not grow); one should also run them 1050: %% manually with 1000 replaced by 1000000. 1051: 1052: M = atom_to_list(?MODULE), 1053: ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end, 1054: F1(F1, 1000) end, 1055: concat(["begin F1 = fun(F,N) -> ", M, 1056: ":count_down(F, N) end, F1(F1,1000) end."]), 1057: 0, ['F1'], LFH, EFH), 1058: ?line check(fun() -> F1 = fun(F,N) -> apply(?MODULE,count_down,[F,N]) 1059: end, F1(F1, 1000) end, 1060: concat(["begin F1 = fun(F,N) -> apply(", M, 1061: ",count_down,[F, N]) end, F1(F1,1000) end."]), 1062: 0, ['F1'], LFH, EFH), 1063: ?line check(fun() -> F = fun(F,N) when N > 0 -> apply(F,[F,N-1]); 1064: (_F,0) -> ok end, 1065: F(F, 1000) 1066: end, 1067: "begin F = fun(F,N) when N > 0 -> apply(F,[F,N-1]);" 1068: "(_F,0) -> ok end," 1069: "F(F, 1000) end.", 1070: ok, ['F'], LFH, EFH), 1071: ?line check(fun() -> F = fun(F,N) when N > 0 -> 1072: apply(erlang,apply,[F,[F,N-1]]); 1073: (_F,0) -> ok end, 1074: F(F, 1000) 1075: end, 1076: "begin F = fun(F,N) when N > 0 ->" 1077: "apply(erlang,apply,[F,[F,N-1]]);" 1078: "(_F,0) -> ok end," 1079: "F(F, 1000) end.", 1080: ok, ['F'], LFH, EFH), 1081: ?line check(fun() -> F = count_down_fun(), 1082: SF = fun(SF, F1, N) -> F(SF, F1, N) end, 1083: SF(SF, F, 1000) end, 1084: concat(["begin F = ", M, ":count_down_fun()," 1085: "SF = fun(SF, F1, N) -> F(SF, F1, N) end," 1086: "SF(SF, F, 1000) end."]), 1087: ok, ['F','SF'], LFH, EFH), 1088: 1089: 1090: ?line check(fun() -> F = fun(X) -> A = 1+X, {X,A} end, 1091: true = {2,3} == F(2) end, 1092: "begin F = fun(X) -> A = 1+X, {X,A} end, 1093: true = {2,3} == F(2) end.", true, ['F'], LFH, EFH), 1094: ?line check(fun() -> F = fun(X) -> byte_size(X) end, 1095: ?MODULE:do_apply(F,<<"hej">>) end, 1096: concat(["begin F = fun(X) -> size(X) end,", 1097: M,":do_apply(F,<<\"hej\">>) end."]), 1098: 3, ['F'], LFH, EFH), 1099: 1100: ?line check(fun() -> F1 = fun(X, Z) -> {X,Z} end, 1101: Z = 5, 1102: F2 = fun(X, Y) -> F1(Z,{X,Y}) end, 1103: F3 = fun(X, Y) -> {a,F1(Z,{X,Y})} end, 1104: {5,{x,y}} = F2(x,y), 1105: {a,{5,{y,x}}} = F3(y,x), 1106: {5,{5,y}} = F2(Z,y), 1107: true = {5,{x,5}} == F2(x,Z) end, 1108: "begin F1 = fun(X, Z) -> {X,Z} end, 1109: Z = 5, 1110: F2 = fun(X, Y) -> F1(Z,{X,Y}) end, 1111: F3 = fun(X, Y) -> {a,F1(Z,{X,Y})} end, 1112: {5,{x,y}} = F2(x,y), 1113: {a,{5,{y,x}}} = F3(y,x), 1114: {5,{5,y}} = F2(Z,y), 1115: true = {5,{x,5}} == F2(x,Z) end.", 1116: true, ['F1','Z','F2','F3'], LFH, EFH), 1117: ?line check(fun() -> F = fun(X) -> byte_size(X) end, 1118: F2 = fun(Y) -> F(Y) end, 1119: ?MODULE:do_apply(F2,<<"hej">>) end, 1120: concat(["begin F = fun(X) -> size(X) end,", 1121: "F2 = fun(Y) -> F(Y) end,", 1122: M,":do_apply(F2,<<\"hej\">>) end."]), 1123: 3, ['F','F2'], LFH, EFH), 1124: ?line check(fun() -> Z = 5, F = fun(X) -> {Z,X} end, 1125: F2 = fun(Z) -> F(Z) end, F2(3) end, 1126: "begin Z = 5, F = fun(X) -> {Z,X} end, 1127: F2 = fun(Z) -> F(Z) end, F2(3) end.", 1128: {5,3},['F','F2','Z'], LFH, EFH), 1129: ?line check(fun() -> F = fun(Z) -> Z end, 1130: F2 = fun(X) -> F(X), Z = {X,X}, Z end, 1131: {1,1} = F2(1), Z = 7, Z end, 1132: "begin F = fun(Z) -> Z end, 1133: F2 = fun(X) -> F(X), Z = {X,X}, Z end, 1134: {1,1} = F2(1), Z = 7, Z end.", 7, ['F','F2','Z'], 1135: LFH, EFH), 1136: ?line check(fun() -> F = fun(F, N) -> [?MODULE:count_down(F,N) || X <-[1]] 1137: end, F(F,2) end, 1138: concat(["begin F = fun(F, N) -> [", M, 1139: ":count_down(F,N) || X <-[1]] end, F(F,2) end."]), 1140: [[[0]]], ['F'], LFH, EFH), 1141: ok. 1142: 1143: count_down(F, N) when N > 0 -> 1144: F(F, N-1); 1145: count_down(_F, N) -> 1146: N. 1147: 1148: count_down_fun() -> 1149: fun(SF,F,N) when N > 0 -> SF(SF,F,N-1); 1150: (_SF,_F,_N) -> ok 1151: end. 1152: 1153: do_apply(F, V) -> 1154: F(V). 1155: 1156: lfh() -> 1157: {eval, fun(F, As, Bs) -> local_func(F, As, Bs) end}. 1158: 1159: local_func(F, As0, Bs0) when is_atom(F) -> 1160: {As,Bs} = erl_eval:expr_list(As0, Bs0, {eval,lfh()}), 1161: case erlang:function_exported(?MODULE, F, length(As)) of 1162: true -> 1163: {value,apply(?MODULE, F, As),Bs}; 1164: false -> 1165: {value,apply(shell_default, F, As),Bs} 1166: end. 1167: 1168: lfh_value_extra() -> 1169: %% Not documented. 1170: {value, fun(F, As) -> local_func_value(F, As) end, []}. 1171: 1172: lfh_value() -> 1173: {value, fun(F, As) -> local_func_value(F, As) end}. 1174: 1175: local_func_value(F, As) when is_atom(F) -> 1176: case erlang:function_exported(?MODULE, F, length(As)) of 1177: true -> 1178: apply(?MODULE, F, As); 1179: false -> 1180: apply(shell_default, F, As) 1181: end. 1182: 1183: efh() -> 1184: {value, fun(F, As) -> external_func(F, As) end}. 1185: 1186: external_func({M,_}, _As) when M == nix -> 1187: exit({{access_not_allowed,M},[mfa]}); 1188: external_func(F, As) when is_function(F) -> 1189: apply(F, As); 1190: external_func({M,F}, As) -> 1191: apply(M, F, As). 1192: 1193: 1194: 1195: try_catch(doc) -> 1196: ["Test try-of-catch-after-end statement"]; 1197: try_catch(suite) -> 1198: []; 1199: try_catch(Config) when is_list(Config) -> 1200: %% Match in of with catch 1201: ?line check(fun() -> try 1 of 1 -> 2 catch _:_ -> 3 end end, 1202: "try 1 of 1 -> 2 catch _:_ -> 3 end.", 2), 1203: ?line check(fun() -> try 1 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end end, 1204: "try 1 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end.", 2), 1205: ?line check(fun() -> try 3 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end end, 1206: "try 3 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end.", 4), 1207: %% Just after 1208: ?line check(fun () -> X = try 1 after put(try_catch, 2) end, 1209: {X,get(try_catch)} end, 1210: "begin X = try 1 after put(try_catch, 2) end, " 1211: "{X,get(try_catch)} end.", {1,2}), 1212: %% Match in of with after 1213: ?line check(fun() -> X = try 1 of 1 -> 2 after put(try_catch, 3) end, 1214: {X,get(try_catch)} end, 1215: "begin X = try 1 of 1 -> 2 after put(try_catch, 3) end, " 1216: "{X,get(try_catch)} end.", {2,3}), 1217: ?line check(fun() -> X = try 1 of 1 -> 2; 3 -> 4 1218: after put(try_catch, 5) end, 1219: {X,get(try_catch)} end, 1220: "begin X = try 1 of 1 -> 2; 3 -> 4 " 1221: " after put(try_catch, 5) end, " 1222: " {X,get(try_catch)} end.", {2,5}), 1223: ?line check(fun() -> X = try 3 of 1 -> 2; 3 -> 4 1224: after put(try_catch, 5) end, 1225: {X,get(try_catch)} end, 1226: "begin X = try 3 of 1 -> 2; 3 -> 4 " 1227: " after put(try_catch, 5) end, " 1228: " {X,get(try_catch)} end.", {4,5}), 1229: %% Nomatch in of 1230: ?line error_check("try 1 of 2 -> 3 catch _:_ -> 4 end.", 1231: {try_clause,1}), 1232: %% Nomatch in of with after 1233: ?line check(fun () -> {'EXIT',{{try_clause,1},_}} = 1234: begin catch try 1 of 2 -> 3 1235: after put(try_catch, 4) end end, 1236: get(try_catch) end, 1237: "begin {'EXIT',{{try_clause,1},_}} = " 1238: " begin catch try 1 of 2 -> 3 " 1239: " after put(try_catch, 4) end end, " 1240: " get(try_catch) end. ", 4), 1241: %% Exception in try 1242: ?line check(fun () -> try 1=2 catch error:{badmatch,2} -> 3 end end, 1243: "try 1=2 catch error:{badmatch,2} -> 3 end.", 3), 1244: ?line check(fun () -> try 1=2 of 3 -> 4 1245: catch error:{badmatch,2} -> 5 end end, 1246: "try 1=2 of 3 -> 4 " 1247: "catch error:{badmatch,2} -> 5 end.", 5), 1248: %% Exception in try with after 1249: ?line check(fun () -> X = try 1=2 1250: catch error:{badmatch,2} -> 3 1251: after put(try_catch, 4) end, 1252: {X,get(try_catch)} end, 1253: "begin X = try 1=2 " 1254: " catch error:{badmatch,2} -> 3 " 1255: " after put(try_catch, 4) end, " 1256: " {X,get(try_catch)} end. ", {3,4}), 1257: ?line check(fun () -> X = try 1=2 of 3 -> 4 1258: catch error:{badmatch,2} -> 5 1259: after put(try_catch, 6) end, 1260: {X,get(try_catch)} end, 1261: "begin X = try 1=2 of 3 -> 4" 1262: " catch error:{badmatch,2} -> 5 " 1263: " after put(try_catch, 6) end, " 1264: " {X,get(try_catch)} end. ", {5,6}), 1265: %% Uncaught exception 1266: ?line error_check("try 1=2 catch error:undefined -> 3 end. ", 1267: {badmatch,2}), 1268: ?line error_check("try 1=2 of 3 -> 4 catch error:undefined -> 5 end. ", 1269: {badmatch,2}), 1270: %% Uncaught exception with after 1271: ?line check(fun () -> {'EXIT',{{badmatch,2},_}} = 1272: begin catch try 1=2 1273: after put(try_catch, 3) end end, 1274: get(try_catch) end, 1275: "begin {'EXIT',{{badmatch,2},_}} = " 1276: " begin catch try 1=2 " 1277: " after put(try_catch, 3) end end, " 1278: " get(try_catch) end. ", 3), 1279: ?line check(fun () -> {'EXIT',{{badmatch,2},_}} = 1280: begin catch try 1=2 of 3 -> 4 1281: after put(try_catch, 5) end end, 1282: get(try_catch) end, 1283: "begin {'EXIT',{{badmatch,2},_}} = " 1284: " begin catch try 1=2 of 3 -> 4" 1285: " after put(try_catch, 5) end end, " 1286: " get(try_catch) end. ", 5), 1287: ?line check(fun () -> {'EXIT',{{badmatch,2},_}} = 1288: begin catch try 1=2 catch error:undefined -> 3 1289: after put(try_catch, 4) end end, 1290: get(try_catch) end, 1291: "begin {'EXIT',{{badmatch,2},_}} = " 1292: " begin catch try 1=2 catch error:undefined -> 3 " 1293: " after put(try_catch, 4) end end, " 1294: " get(try_catch) end. ", 4), 1295: ?line check(fun () -> {'EXIT',{{badmatch,2},_}} = 1296: begin catch try 1=2 of 3 -> 4 1297: catch error:undefined -> 5 1298: after put(try_catch, 6) end end, 1299: get(try_catch) end, 1300: "begin {'EXIT',{{badmatch,2},_}} = " 1301: " begin catch try 1=2 of 3 -> 4 " 1302: " catch error:undefined -> 5 " 1303: " after put(try_catch, 6) end end, " 1304: " get(try_catch) end. ", 6), 1305: ok. 1306: 1307: 1308: eval_expr_5(doc) -> 1309: ["(OTP-7933)"]; 1310: eval_expr_5(suite) -> 1311: []; 1312: eval_expr_5(Config) when is_list(Config) -> 1313: ?line {ok,Tokens ,_} = 1314: erl_scan:string("if a+4 == 4 -> yes; true -> no end. "), 1315: ?line {ok, [Expr]} = erl_parse:parse_exprs(Tokens), 1316: ?line {value, no, []} = erl_eval:expr(Expr, [], none, none, none), 1317: ?line no = erl_eval:expr(Expr, [], none, none, value), 1318: try 1319: erl_eval:expr(Expr, [], none, none, 4711), 1320: ?line function_clause = should_never_reach_here 1321: catch 1322: error:function_clause -> 1323: ok 1324: end. 1325: 1326: %% Check the string in different contexts: as is; in fun; from compiled code. 1327: check(F, String, Result) -> 1328: check1(F, String, Result), 1329: FunString = concat(["fun() -> ", no_final_dot(String), " end(). "]), 1330: check1(F, FunString, Result), 1331: CompileString = concat(["hd(lists:map(fun(_) -> ", no_final_dot(String), 1332: " end, [foo])). "]), 1333: check1(F, CompileString, Result). 1334: 1335: check1(F, String, Result) -> 1336: Result = F(), 1337: case catch parse_and_run(String) of 1338: {value, Result, _} -> 1339: ok; 1340: Other -> 1341: test_server:fail({eval, Other, Result}) 1342: end. 1343: 1344: check(F, String, Result, BoundVars, LFH, EFH) -> 1345: Result = F(), 1346: case catch parse_and_run(String, LFH, EFH) of 1347: {value, Result, Bs} -> 1348: %% We just assume that Bs is an orddict... 1349: Keys = orddict:fetch_keys(Bs), 1350: case sort(BoundVars) == Keys of 1351: true -> 1352: ok; 1353: false -> 1354: test_server:fail({check, BoundVars, Keys}) 1355: end, 1356: ok; 1357: Other -> 1358: test_server:fail({check, Other, Result}) 1359: end. 1360: 1361: error_check(String, Result) -> 1362: case catch parse_and_run(String) of 1363: {'EXIT', {Result,_}} -> 1364: ok; 1365: Other -> 1366: test_server:fail({eval, Other, Result}) 1367: end. 1368: 1369: error_check(String, Result, LFH, EFH) -> 1370: case catch parse_and_run(String, LFH, EFH) of 1371: {'EXIT', {Result,_}} -> 1372: ok; 1373: Other -> 1374: test_server:fail({eval, Other, Result}) 1375: end. 1376: 1377: eval_string(String) -> 1378: {value, Result, _} = parse_and_run(String), 1379: Result. 1380: 1381: parse_and_run(String) -> 1382: {ok,Tokens,_} = erl_scan:string(String), 1383: {ok, [Expr]} = erl_parse:parse_exprs(Tokens), 1384: erl_eval:expr(Expr, []). 1385: 1386: parse_and_run(String, LFH, EFH) -> 1387: {ok,Tokens,_} = erl_scan:string(String), 1388: {ok, [Expr]} = erl_parse:parse_exprs(Tokens), 1389: erl_eval:expr(Expr, [], LFH, EFH). 1390: 1391: no_final_dot(S) -> 1392: case lists:reverse(S) of 1393: " ." ++ R -> lists:reverse(R); 1394: "." ++ R -> lists:reverse(R); 1395: _ -> S 1396: end.