qlc.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,743 行 · 第 1/5 页
ERL
1,743 行
%% The funcspecs qlc:q/1 and qlc:q/2 are known by erl_eval.erl and%% erl_lint.erl.q(QLC_lc) -> q(QLC_lc, []).q(#qlc_lc{}=QLC_lc, Options) -> case options(Options, [unique, cache, max_lookup, join, lookup]) of [Unique, Cache, Max, Join, Lookup] -> Opt = #qlc_opt{unique = Unique, cache = Cache, max_lookup = Max, join = Join, lookup = Lookup}, #qlc_handle{h = QLC_lc#qlc_lc{opt = Opt}}; _ -> erlang:error(badarg, [QLC_lc, Options]) end;q(T1, T2) -> erlang:error(badarg, [T1, T2]).sort(QH) -> sort(QH, []).sort(QH, Options) -> case {options(Options, [tmpdir, order, unique, compressed, size, no_files]), get_handle(QH)} of {B1, B2} when B1 =:= badarg; B2 =:= badarg -> erlang:error(badarg, [QH, Options]); {[TD, Order, Unique, Compressed | _], H} -> #qlc_handle{h = #qlc_sort{h = H, keypos = sort, unique = Unique, compressed = Compressed, order = Order, opts = listify(Options), tmpdir = TD}} end.%% Note that the generated code is evaluated by (the slow) erl_eval.string_to_handle(Str) -> string_to_handle(Str, []).string_to_handle(Str, Options) -> string_to_handle(Str, Options, []).string_to_handle(Str, Options, Bindings) when is_list(Str), is_list(Bindings) -> case options(Options, [unique, cache, max_lookup, join, lookup]) of badarg -> erlang:error(badarg, [Str, Options, Bindings]); [Unique, Cache, MaxLookup, Join, Lookup] -> case erl_scan:string(Str) of {ok, Tokens, _} -> case erl_parse:parse_exprs(Tokens) of {ok, [Expr]} -> case qlc_pt:transform_expression(Expr, Bindings) of {ok, {call, _, _QlcQ, Handle}} -> {value, QLC_lc, _} = erl_eval:exprs(Handle, Bindings), O = #qlc_opt{unique = Unique, cache = Cache, max_lookup = MaxLookup, join = Join, lookup = Lookup}, #qlc_handle{h = QLC_lc#qlc_lc{opt = O}}; {not_ok, [{error, Error} | _]} -> error(Error) end; {ok, _ExprList} -> erlang:error(badarg, [Str, Options, Bindings]); {error, ErrorInfo} -> error(ErrorInfo) end; {error, ErrorInfo, _EndLine} -> error(ErrorInfo) end end;string_to_handle(T1, T2, T3) -> erlang:error(badarg, [T1, T2, T3]).table(TraverseFun, Options) when is_function(TraverseFun) -> case {is_function(TraverseFun, 0), IsFun1 = is_function(TraverseFun, 1)} of {false, false} -> erlang:error(badarg, [TraverseFun, Options]); _ -> case options(Options, [pre_fun, post_fun, info_fun, format_fun, lookup_fun, parent_fun]) of [PreFun, PostFun, InfoFun, FormatFun, LookupFun, ParentFun] -> T = #qlc_table{trav_fun = TraverseFun, pre_fun = PreFun, post_fun = PostFun, info_fun = InfoFun, parent_fun = ParentFun, trav_MS = IsFun1, format_fun = FormatFun, lookup_fun = LookupFun}, #qlc_handle{h = T}; badarg -> erlang:error(badarg, [TraverseFun, Options]) end end;table(T1, T2) -> erlang:error(badarg, [T1, T2]).transform_from_evaluator(LC, Bs0) -> qlc_pt:transform_from_evaluator(LC, Bs0).%%%%%% Local functions%%%options(Options, Keys) when is_list(Options) -> options(Options, Keys, []);options(Option, Keys) -> options([Option], Keys, []).options(Options0, [Key | Keys], L) when is_list(Options0) -> Options = case lists:member(Key, Options0) of true -> [atom_option(Key) | lists:delete(Key, Options0)]; false -> Options0 end, V = case lists:keysearch(Key, 1, Options) of {value, {format_fun, U=undefined}} -> {ok, U}; {value, {info_fun, U=undefined}} -> {ok, U}; {value, {lookup_fun, U=undefined}} -> {ok, U}; {value, {parent_fun, U=undefined}} -> {ok, U}; {value, {post_fun, U=undefined}} -> {ok, U}; {value, {pre_fun, U=undefined}} -> {ok, U}; {value, {info_fun, Fun}} when is_function(Fun), is_function(Fun, 1) -> {ok, Fun}; {value, {pre_fun, Fun}} when is_function(Fun), is_function(Fun, 1) -> {ok, Fun}; {value, {post_fun, Fun}} when is_function(Fun), is_function(Fun, 0) -> {ok, Fun}; {value, {lookup_fun, Fun}} when is_function(Fun), is_function(Fun, 2) -> {ok, Fun}; {value, {max_lookup, Max}} when is_integer(Max), Max >= 0 -> {ok, Max}; {value, {max_lookup, infinity}} -> {ok, -1}; {value, {format_fun, Fun}} when is_function(Fun), is_function(Fun, 1) -> {ok, Fun}; {value, {parent_fun, Fun}} when is_function(Fun), is_function(Fun, 0) -> {ok, Fun}; {value, {join, J=any}} -> {ok, J}; {value, {join, J=nested_loop}} -> {ok, J}; {value, {join, J=merge}} -> {ok, J}; {value, {join, J=lookup}} -> {ok, J}; {value, {lookup, LookUp}} when LookUp; not LookUp; LookUp =:= any -> {ok, LookUp}; {value, {max_list_size, Max}} when is_integer(Max), Max >= 0 -> {ok, Max}; {value, {unique, Unique}} when Unique; not Unique -> {ok, Unique}; {value, {cache, Cache}} when Cache; not Cache; Cache =:= list -> {ok, Cache}; {value, {cache, ets}} -> {ok, true}; {value, {cache, no}} -> {ok, false}; {value, {unique_all, UniqueAll}} when UniqueAll; not UniqueAll -> {ok, UniqueAll}; {value, {cache_all, CacheAll}} when CacheAll; not CacheAll; CacheAll =:= list -> {ok, CacheAll}; {value, {cache_all, ets}} -> {ok, true}; {value, {cache_all, no}} -> {ok, false}; {value, {spawn_options, default}} -> {ok, default}; {value, {spawn_options, SpawnOptions}} -> case is_proper_list(SpawnOptions) of true -> {ok, SpawnOptions}; false -> badarg end; {value, {flat, Flat}} when Flat; not Flat -> {ok, Flat}; {value, {format, Format}} when Format =:= string; Format =:= abstract_code; Format =:= debug -> {ok, Format}; {value, {n_elements, NElements}} when NElements =:= infinity; is_integer(NElements), NElements > 0 -> {ok, NElements}; {value, {order, Order}} when is_function(Order), is_function(Order, 2); (Order =:= ascending); (Order =:= descending) -> {ok, Order}; {value, {compressed, Comp}} when Comp -> {ok, [compressed]}; {value, {compressed, Comp}} when not Comp -> {ok, []}; {value, {tmpdir, T}} -> {ok, T}; {value, {size, Size}} when is_integer(Size), Size > 0 -> {ok, Size}; {value, {no_files, NoFiles}} when is_integer(NoFiles), NoFiles > 1 -> {ok, NoFiles}; {value, {Key, _}} -> badarg; false -> Default = default_option(Key), {ok, Default} end, case V of badarg -> badarg; {ok, Value} -> NewOptions = lists:keydelete(Key, 1, Options), options(NewOptions, Keys, [Value | L]) end;options([], [], L) -> lists:reverse(L);options(_Options, _, _L) -> badarg.default_option(pre_fun) -> undefined;default_option(post_fun) -> undefined;default_option(info_fun) -> undefined;default_option(format_fun) -> undefined;default_option(lookup_fun) -> undefined;default_option(max_lookup) -> -1;default_option(join) -> any;default_option(lookup) -> any;default_option(parent_fun) -> undefined;default_option(spawn_options) -> default;default_option(flat) -> true;default_option(format) -> string;default_option(n_elements) -> infinity;default_option(max_list_size) -> ?MAX_LIST_SIZE;default_option(cache) -> false;default_option(cache_all) -> false;default_option(unique) -> false;default_option(unique_all) -> false;default_option(order) -> ascending; % default values from file_sorter.erldefault_option(compressed) -> [];default_option(tmpdir) -> "";default_option(size) -> 524288;default_option(no_files) -> 16.atom_option(cache) -> {cache, true};atom_option(unique) -> {unique, true};atom_option(cache_all) -> {cache_all, true};atom_option(unique_all) -> {unique_all, true};atom_option(lookup) -> {lookup, true};atom_option(flat) -> {flat, true};atom_option(Key) -> Key.is_proper_list([_ | L]) -> is_proper_list(L);is_proper_list(L) -> L =:= [].spawn_options(default) -> [link];spawn_options(SpawnOptions) -> lists:delete(monitor, case lists:member(link, SpawnOptions) of true -> SpawnOptions; false -> [link | SpawnOptions] end).is_keypos(Keypos) when is_integer(Keypos), Keypos > 0 -> true;is_keypos([]) -> false;is_keypos(L) -> is_keyposs(L).is_keyposs([Kp | Kps]) when is_integer(Kp), Kp > 0 -> is_keyposs(Kps);is_keyposs(Kps) -> Kps =:= [].listify(L) when is_list(L) -> L;listify(T) -> [T].%% Optimizations to be carried out.-record(optz, {unique = false, % bool() cache = false, % bool() | list join_option = any, % constraint set by the 'join' option fast_join = no, % no | #qlc_join. 'no' means nested loop. opt % #qlc_opt }).%% Prepared #qlc_lc.-record(qlc, {lcf, % fun() -> Val codef, qdata, % with evaluated list expressions init_value, optz % #optz }).%% Prepared simple #qlc_lc.-record(simple_qlc, {p, % atom(), pattern variable le, line, init_value, optz % #optz }).-record(prepared, {qh, % #qlc_append | #qlc_table | #qlc | #simple_qlc | % #qlc_sort | list() sorted = no, % yes | no | ascending | descending sort_info = [], % sort_info2 = [], % 'sort_info' updated with pattern info; qh is LE join = {[],[]}, % {Lookup, Merge} n_objs = undefined, % for join (not used yet) is_unique_objects = false, % bool() is_cached = false % bool() (true means 'ets' or 'list') }).ensure_collecting(Prep, Objs) -> case Prep#prepared.qh of #qlc{optz = #optz{unique = false, cache = false}} -> Objs; _ -> fun() -> collect(Objs, []) end end.%%% Cursor process functions.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?