1%% Copyright (c) 2016 Robert Virding
2%%
3%% Licensed under the Apache License, Version 2.0 (the "License");
4%% you may not use this file except in compliance with the License.
5%% You may obtain a copy of the License at
6%%
7%%     http://www.apache.org/licenses/LICENSE-2.0
8%%
9%% Unless required by applicable law or agreed to in writing, software
10%% distributed under the License is distributed on an "AS IS" BASIS,
11%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12%% See the License for the specific language governing permissions and
13%% limitations under the License.
14
15%% File    : lfe_internal.erl
16%% Author  : Robert Virding
17%% Purpose : Define Lisp Flavoured Erlang internal bifs, guards.
18
19-module(lfe_internal).
20
21%% General library functions.
22-export([is_bif/2,is_guard_bif/2,is_erl_bif/2,is_lfe_bif/2]).
23-export([is_core_form/1,is_core_func/2]).
24
25%% -compile([export_all]).
26
27%% is_bif(Name, Arity) -> bool().
28%% is_guard_bif(Name, Arity) -> bool().
29%% is_erl_bif(Name, Arity) -> bool().
30%%  Collected tests for valid BIFs in expressions and guards.
31
32is_bif(Name, Ar) ->
33    is_core_func(Name, Ar)
34%%        orelse is_lfe_bif(Name, Ar)
35        orelse is_erl_bif(Name, Ar).
36
37is_guard_bif(Op ,Ar) ->
38    erl_internal:guard_bif(Op, Ar)
39    orelse erl_internal:arith_op(Op, Ar)
40    orelse erl_internal:bool_op(Op, Ar)
41    orelse erl_internal:comp_op(Op, Ar).
42
43is_erl_bif(Op, Ar) ->
44    erl_internal:bif(Op, Ar)
45    orelse erl_internal:arith_op(Op, Ar)
46    orelse erl_internal:bool_op(Op, Ar)
47    orelse erl_internal:comp_op(Op, Ar)
48    orelse erl_internal:list_op(Op, Ar)
49    orelse erl_internal:send_op(Op, Ar).
50
51%% is_core_form(Form) -> bool().
52%%  Return true if Form (name) is one of the LFE core forms, else false.
53
54%% Core data special forms.
55is_core_form(quote) -> true;
56is_core_form(cons) -> true;
57is_core_form(car) -> true;
58is_core_form(cdr) -> true;
59is_core_form(list) -> true;
60is_core_form(tuple) -> true;
61is_core_form(tref) -> true;
62is_core_form(tset) -> true;
63is_core_form(binary) -> true;
64is_core_form(map) -> true;
65is_core_form(mref) -> true;
66is_core_form(mset) -> true;
67is_core_form(mupd) -> true;
68is_core_form('map-get') -> true;
69is_core_form('map-set') -> true;
70is_core_form('map-update') -> true;
71is_core_form(function) -> true;
72%% Core closure special forms.
73is_core_form(lambda) -> true;
74is_core_form('match-lambda') -> true;
75is_core_form('let') -> true;
76is_core_form('let-function') -> true;
77is_core_form('letrec-function') -> true;
78is_core_form('let-macro') -> true;
79%% Core control special forms.
80is_core_form('progn') -> true;
81is_core_form('if') -> true;
82is_core_form('case') -> true;
83is_core_form('receive') -> true;
84is_core_form('catch') -> true;
85is_core_form('try') -> true;
86is_core_form('funcall') -> true;
87is_core_form(call) -> true;
88%% Core definition special forms.
89is_core_form('eval-when-compile') -> true;
90is_core_form('define-module') -> true;
91is_core_form('extend-module') -> true;
92is_core_form('define-type') -> true;
93is_core_form('define-opaque-type') -> true;
94is_core_form('define-function-spec') -> true;
95is_core_form('define-function') -> true;
96is_core_form('define-macro') -> true;
97%% And don't forget when.
98is_core_form('when') -> true;
99%% Everything else is not a core form.
100is_core_form(_) -> false.
101
102%% is_core_func(Name, Arity) -> bool().
103%%  Return true if Name/Arity is one of the LFE core functions, else
104%%  false. For those which can take multiple arguments we accept any
105%%  number and push checking to run time.
106
107is_core_func(cons, 2) -> true;
108is_core_func(car, 1) -> true;
109is_core_func(cdr, 1) -> true;
110is_core_func(list, Ar) when Ar >= 0 -> true;
111is_core_func(tuple, Ar) when Ar >= 0  -> true;
112is_core_func(tref, 2) -> true;
113is_core_func(tset, 3) -> true;
114is_core_func(binary, Ar) when Ar >= 0  -> true;
115is_core_func(map, Ar) when Ar >= 0, (Ar rem 2) =:= 0 -> true;
116is_core_func(mref, 2) -> true;
117is_core_func(mset, Ar) when Ar >= 0, (Ar rem 2) =:= 1 -> true;
118is_core_func(mupd, Ar) when Ar >= 0, (Ar rem 2) =:= 1 -> true;
119is_core_func('map-get', 2) -> true;
120is_core_func('map-set', Ar) when Ar >= 0, (Ar rem 2) =:= 1 -> true;
121is_core_func('map-upd', Ar) when Ar >= 0, (Ar rem 2) =:= 1 -> true;
122is_core_func(funcall, Ar) when Ar >= 1 -> true;
123is_core_func(call, Ar) when Ar >= 2 -> true;
124is_core_func(_, _) -> false.
125
126%% is_lfe_bif(Name, Arity) -> bool().
127%%  Return true if Name/Arity is one of the standard LFE bifs defined
128%%  in the lfe module.
129
130is_lfe_bif(eval, 1) -> true;
131is_lfe_bif(eval, 2) -> true;
132is_lfe_bif('macro-function', 1) -> true;
133is_lfe_bif('macro-function', 2) -> true;
134is_lfe_bif(macroexpand, 1) -> true;
135is_lfe_bif(macroexpand, 2) -> true;
136is_lfe_bif('macroexpand-1', 1) -> true;
137is_lfe_bif('macroexpand-1', 2) -> true;
138is_lfe_bif('macroexpand-all', 1) -> true;
139is_lfe_bif('macroexpand-all', 2) -> true;
140is_lfe_bif(_, _) -> false.
141