ms_transform.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 982 行 · 第 1/2 页
ERL
982 行
L) -> NV = tg(Value,B), [{Key,NV}|L]; ({record_field,_,{var,_,'_'},Value}, L) -> NV = tg(Value,B), [{{default},NV}|L]; (_,_) -> throw({error,Line, {?ERR_GENBADREC+B#tgd.eb, RName}}) end, [], RFields), DefValue = case lists:keysearch({default},1,KeyList0) of {value,{{default},OverriddenDefValue}} -> {true,OverriddenDefValue}; _ -> false end, KeyList = lists:keydelete({default},1,KeyList0), case lists:keysearch({default},1,KeyList) of {value,{{default},_}} -> throw({error,Line,{?ERR_GENMULTIFIELD+B#tgd.eb,RName,'_'}}); _ -> ok end, case lists:keysearch(RName,1,RDefs) of {value, {RName, FieldList0}} -> FieldList1 = lists:foldl( fun({FN,_,Def},Acc) -> El = case lists:keysearch(FN,1,KeyList) of {value, {FN, X0}} -> X0; _ -> case DefValue of {true,Overridden} -> Overridden; false -> Def end end, [El | Acc] end, [], FieldList0), check_multi_field(RName,Line,KeyList, ?ERR_GENMULTIFIELD+B#tgd.eb), check_undef_field(RName,Line,KeyList,FieldList0, ?ERR_GENBADFIELD+B#tgd.eb), {tuple,Line,[{tuple,Line,[{atom,Line,RName}|FieldList1]}]}; _ -> throw({error,Line,{?ERR_GENBADREC+B#tgd.eb,RName}}) end;tg({record_index,Line,RName,{atom,Line2,KeyName}},B) -> RDefs = get_records(), case lists:keysearch(RName,1,RDefs) of {value, {RName, FieldList}} -> case lists:keysearch(KeyName,1, FieldList) of {value, {KeyName,Position,_}} -> {integer, Line2, Position}; _ -> throw({error,Line2,{?ERR_GENBADFIELD+B#tgd.eb, RName, KeyName}}) end; _ -> throw({error,Line,{?ERR_GENBADREC+B#tgd.eb,RName}}) end;tg({record,Line,{var,Line2,_VName}=AVName, RName,RFields},B) -> RDefs = get_records(), MSVName = tg(AVName,B), KeyList = lists:foldl(fun({record_field,_,{atom,_,Key},Value}, L) -> NV = tg(Value,B), [{Key,NV}|L]; (_,_) -> throw({error,Line,?ERR_HEADBADREC}) end, [], RFields), case lists:keysearch(RName,1,RDefs) of {value, {RName, FieldList0}} -> FieldList1 = lists:foldl( fun({FN,Pos,_},Acc) -> El = case lists:keysearch(FN,1,KeyList) of {value, {FN, X0}} -> X0; _ -> {tuple, Line2, [{atom, Line2, element}, {integer, Line2, Pos}, MSVName]} end, [El | Acc] end, [], FieldList0), check_multi_field(RName,Line,KeyList, ?ERR_GENMULTIFIELD+B#tgd.eb), check_undef_field(RName,Line,KeyList,FieldList0, ?ERR_GENBADFIELD+B#tgd.eb), {tuple,Line,[{tuple,Line,[{atom,Line,RName}|FieldList1]}]}; _ -> throw({error,Line,{?ERR_GENBADREC+B#tgd.eb,RName}}) end;tg({bin_element,_Line0,{var, Line, A},_,_} = Whole,B) -> case lkup_bind(A, B#tgd.b) of undefined -> Whole; % exists in environment hopefully _AtomName -> throw({error,Line,{?ERR_GENBINCONSTRUCT+B#tgd.eb,A}}) end; tg(default,_B) -> default;tg({bin_element,Line,X,Y,Z},B) -> {bin_element, Line, tg(X,B), tg(Y,B), Z};tg({bin,Line,List},B) -> {bin,Line,[tg(X,B) || X <- List]}; tg(T,B) when is_tuple(T), size(T) >= 2 -> Element = element(1,T), Line = element(2,T), throw({error,Line,{?ERR_GENELEMENT+B#tgd.eb, translate_language_element(Element)}}); tg(Other,B) -> Element = io_lib:format("unknown element ~w", [Other]), throw({error,unknown,{?ERR_GENELEMENT+B#tgd.eb,Element}}).transform_head([V]) -> Bind = cre_bind(), {NewV,NewBind} = toplevel_head_match(V,Bind), th(NewV,NewBind).toplevel_head_match({match,_,{var,_,VName},Expr},B) -> {Expr,new_bind({VName,'$_'},B)};toplevel_head_match({match,_,Expr,{var,_,VName}},B) -> {Expr,new_bind({VName,'$_'},B)};toplevel_head_match(Other,B) -> {Other,B}.th({record,Line,RName,RFields},B) -> % youch... RDefs = get_records(), {KeyList0,NewB} = lists:foldl(fun({record_field,_,{atom,_,Key},Value}, {L,B0}) -> {NV,B1} = th(Value,B0), {[{Key,NV}|L],B1}; ({record_field,_,{var,_,'_'},Value}, {L,B0}) -> {NV,B1} = th(Value,B0), {[{{default},NV}|L],B1}; (_,_) -> throw({error,Line,{?ERR_HEADBADREC, RName}}) end, {[],B}, RFields), DefValue = case lists:keysearch({default},1,KeyList0) of {value,{{default},OverriddenDefValue}} -> OverriddenDefValue; _ -> {atom,Line,'_'} end, KeyList = lists:keydelete({default},1,KeyList0), case lists:keysearch({default},1,KeyList) of {value,{{default},_}} -> throw({error,Line,{?ERR_HEADMULTIFIELD,RName,'_'}}); _ -> ok end, case lists:keysearch(RName,1,RDefs) of {value, {RName, FieldList0}} -> FieldList1 = lists:foldl( fun({FN,_,_},Acc) -> El = case lists:keysearch(FN,1,KeyList) of {value, {FN, X0}} -> X0; _ -> DefValue end, [El | Acc] end, [], FieldList0), check_multi_field(RName,Line,KeyList, ?ERR_HEADMULTIFIELD), check_undef_field(RName,Line,KeyList,FieldList0, ?ERR_HEADBADFIELD), {{tuple,Line,[{atom,Line,RName}|FieldList1]},NewB}; _ -> throw({error,Line,{?ERR_HEADBADREC,RName}}) end;th({match,Line,_,_},_) -> throw({error,Line,?ERR_HEADMATCH});th({atom,Line,A},B) -> case atom_to_list(A) of [$$|NL] -> case (catch list_to_integer(NL)) of N when is_integer(N) -> throw({error,Line,{?ERR_HEADDOLLARATOM,A}}); _ -> {{atom,Line,A},B} end; _ -> {{atom,Line,A},B} end;th({bin_element,_Line0,{var, Line, A},_,_},_) -> throw({error,Line,{?ERR_HEADBINMATCH,A}});th({var,Line,Name},B) -> case lkup_bind(Name,B) of undefined -> NewB = new_bind(Name,B), {{atom,Line,lkup_bind(Name,NewB)},NewB}; Trans -> {{atom,Line,Trans},B} end;th([H|T],B) -> {NH,NB} = th(H,B), {NT,NNB} = th(T,NB), {[NH|NT],NNB};th(T,B) when is_tuple(T) -> {L,NB} = th(tuple_to_list(T),B), {list_to_tuple(L),NB};th(Nonstruct,B) -> {Nonstruct,B}.% Could be more efficient...check_multi_field(_,_,[],_) -> ok;check_multi_field(RName, Line, [{Key,_}|T], ErrCode) -> case lists:keysearch(Key,1,T) of {value,_} -> throw({error,Line,{ErrCode,RName,Key}}); _ -> check_multi_field(RName, Line, T, ErrCode) end.check_undef_field(_,_,[],_,_) -> ok;check_undef_field(RName, Line, [{Key,_}|T], FieldList, ErrCode) -> case lists:keysearch(Key,1,FieldList) of {value,_} -> check_undef_field(RName, Line, T, FieldList, ErrCode); _ -> throw({error,Line,{ErrCode,RName,Key}}) end.cre_bind() -> {1,[{'_','_'}]}.lkup_bind(Name,{_,List}) -> case lists:keysearch(Name,1,List) of {value, {Name, Trans}} -> Trans; _ -> undefined end.new_bind({Name,Trans},{Next,L}) -> {Next,[{Name,Trans}|L]};new_bind(Name,{Next,L}) -> Trans = list_to_atom([$$|integer_to_list(Next)]), {Next+1,[{Name,Trans}|L]}.translate_language_element(Atom) -> Transtab = [ {lc,"list comprehension"}, {bc,"binary comprehension"}, {block, "begin/end block"}, {'if', "if"}, {'case', "case"}, {'receive', "receive"}, {'try', "try"}, {'catch', "catch"}, {'match', "match (=)"}, {remote, "external function call"} ], case lists:keysearch(Atom,1,Transtab) of {value,{Atom, String}} -> String; _ -> atom_to_list(Atom) end.old_bool_test(atom,1) -> is_atom;old_bool_test(constant,1) -> is_constant;old_bool_test(float,1) -> is_float;old_bool_test(integer,1) -> is_integer;old_bool_test(list,1) -> is_list;old_bool_test(number,1) -> is_number;old_bool_test(pid,1) -> is_pid;old_bool_test(port,1) -> is_port;old_bool_test(reference,1) -> is_reference;old_bool_test(tuple,1) -> is_tuple;old_bool_test(binary,1) -> is_binary;old_bool_test(function,1) -> is_function;old_bool_test(record,2) -> is_record;old_bool_test(_,_) -> undefined.bool_test(is_atom,1) -> true;bool_test(is_constant,1) -> true;bool_test(is_float,1) -> true;bool_test(is_integer,1) -> true;bool_test(is_list,1) -> true;bool_test(is_number,1) -> true;bool_test(is_pid,1) -> true;bool_test(is_port,1) -> true;bool_test(is_reference,1) -> true;bool_test(is_tuple,1) -> true;bool_test(is_binary,1) -> true;bool_test(is_function,1) -> true;bool_test(is_record,2) -> true;bool_test(is_seq_trace,0) -> true;bool_test(_,_) -> false.real_guard_function(abs,1) -> true;real_guard_function(element,2) -> true;real_guard_function(hd,1) -> true;real_guard_function(length,1) -> true;real_guard_function(node,0) -> true;real_guard_function(node,1) -> true;real_guard_function(round,1) -> true;real_guard_function(size,1) -> true;real_guard_function(tl,1) -> true;real_guard_function(trunc,1) -> true;real_guard_function(self,0) -> true;real_guard_function(float,1) -> true;real_guard_function(_,_) -> false.pseudo_guard_function(get_tcw,0) -> true;pseudo_guard_function(_,_) -> false.guard_function(X,A) -> real_guard_function(X,A) or pseudo_guard_function(X,A).action_function(set_seq_token,2) -> true;action_function(get_seq_token,0) -> true;action_function(message,1) -> true;action_function(return_trace,0) -> true;action_function(process_dump,0) -> true;action_function(enable_trace,1) -> true;action_function(enable_trace,2) -> true;action_function(disable_trace,1) -> true;action_function(disable_trace,2) -> true;action_function(display,1) -> true;action_function(caller,0) -> true;action_function(set_tcw,1) -> true;action_function(silent,1) -> true;action_function(_,_) -> false.bool_operator('and',2) -> true;bool_operator('or',2) -> true;bool_operator('xor',2) -> true;bool_operator('not',1) -> true;bool_operator('andalso',2) -> true;bool_operator('orelse',2) -> true;bool_operator(_,_) -> false.arith_operator('+',1) -> true;arith_operator('+',2) -> true;arith_operator('-',1) -> true;arith_operator('-',2) -> true;arith_operator('*',2) -> true;arith_operator('/',2) -> true;arith_operator('div',2) -> true;arith_operator('rem',2) -> true;arith_operator('band',2) -> true;arith_operator('bor',2) -> true;arith_operator('bxor',2) -> true;arith_operator('bnot',1) -> true;arith_operator('bsl',2) -> true;arith_operator('bsr',2) -> true;arith_operator(_,_) -> false.cmp_operator('>',2) -> true;cmp_operator('>=',2) -> true;cmp_operator('<',2) -> true;cmp_operator('=<',2) -> true;cmp_operator('==',2) -> true;cmp_operator('=:=',2) -> true;cmp_operator('/=',2) -> true;cmp_operator('=/=',2) -> true;cmp_operator(_,_) -> false.is_operator(X,A,_) -> bool_operator(X,A) or arith_operator(X,A) or cmp_operator(X,A).is_imported_from_erlang(X,A,_) -> real_guard_function(X,A) or bool_test(X,A) or bool_operator(X,A) or arith_operator(X,A) or cmp_operator(X,A).is_ms_function(X,A,body) -> action_function(X,A) or guard_function(X,A) or bool_test(X,A);is_ms_function(X,A,guard) -> guard_function(X,A) or bool_test(X,A).fixup_environment(L,B) when is_list(L) -> lists:map(fun(X) -> fixup_environment(X,B) end, L);fixup_environment({var,Line,Name},B) -> case lists:keysearch(Name,1,B) of {value,{Name,Value}} -> freeze(Line,Value); _ -> throw({error,Line,{?ERR_UNBOUND_VARIABLE,atom_to_list(Name)}}) end;fixup_environment(T,B) when is_tuple(T) -> list_to_tuple( lists:map(fun(X) -> fixup_environment(X,B) end, tuple_to_list(T)));fixup_environment(Other,_B) -> Other. freeze(Line,Term) -> {frozen,Line,Term}.% Most of this is bluntly stolen from erl_parse.normalise({frozen,_,Term}) -> Term;normalise({char,_,C}) -> C;normalise({integer,_,I}) -> I;normalise({float,_,F}) -> F;normalise({atom,_,A}) -> A;normalise({string,_,S}) -> S;normalise({nil,_}) -> [];normalise({bin,_,Fs}) -> {value, B, _} = eval_bits:expr_grp(Fs, [], fun(E, _) -> {value, normalise(E), []} end, [], true), B;normalise({cons,_,Head,Tail}) -> [normalise(Head)|normalise(Tail)];normalise({tuple,_,Args}) -> list_to_tuple(normalise_list(Args));%% Special case for unary +/-.normalise({op,_,'+',{char,_,I}}) -> I;normalise({op,_,'+',{integer,_,I}}) -> I;normalise({op,_,'+',{float,_,F}}) -> F;normalise({op,_,'-',{char,_,I}}) -> -I; %Weird, but compatible!normalise({op,_,'-',{integer,_,I}}) -> -I;normalise({op,_,'-',{float,_,F}}) -> -F.normalise_list([H|T]) -> [normalise(H)|normalise_list(T)];normalise_list([]) -> [].
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?