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 + -
显示快捷键?