fix(purescript): extract exp_apply callees so function applications form CALLS edges

PureScript function application (greet "world", log (...)) is an exp_apply node
whose function head is an exp_name child — extract_fp_callee only handled
apply/application_expression, and PureScript wasn't routed to it, so the callee
was never extracted and no call to greet was found.

Route PureScript through extract_fp_callee (like Haskell/OCaml) and teach it
exp_apply: the head is an exp_name (its text is the qualified function name), and
curried applications nest exp_apply, so descend the function head to recover the
leftmost callee. Haskell/OCaml apply handling is unchanged.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This commit is contained in:
Martin Vogel committed 2026-06-28 08:45:57 +02:00
1 parent 42213168b4
commit 8e332bc2ac
1 file changed
+13 -3
+13 -3
View File
@@ -322,14 +322,24 @@ static char *extract_callee_from_fields(CBMArena *a, TSNode node, const char *so
// Haskell/OCaml: extract callee from apply/infix nodes.
static char *extract_fp_callee(CBMArena *a, TSNode node, const char *source, const char *nk) {
if (strcmp(nk, "apply") == 0 || strcmp(nk, "application_expression") == 0) {
if (strcmp(nk, "apply") == 0 || strcmp(nk, "application_expression") == 0 ||
strcmp(nk, "exp_apply") == 0) {
if (ts_node_child_count(node) > 0) {
TSNode callee = ts_node_child(node, 0);
const char *ck = ts_node_type(callee);
if (strcmp(ck, "identifier") == 0 || strcmp(ck, "variable") == 0 ||
strcmp(ck, "constructor") == 0 || strcmp(ck, "value_path") == 0) {
strcmp(ck, "constructor") == 0 || strcmp(ck, "value_path") == 0 ||
/* PureScript: exp_apply's function head is an `exp_name` whose
* text is the (possibly qualified) function name. */
strcmp(ck, "exp_name") == 0) {
return cbm_node_text(a, callee, source);
}
/* Curried application `f a b` nests exp_apply/apply — descend the
* function head to recover the leftmost callee. */
if (strcmp(ck, "exp_apply") == 0 || strcmp(ck, "apply") == 0 ||
strcmp(ck, "application_expression") == 0) {
return extract_fp_callee(a, callee, source, ck);
}
}
}
if (strcmp(nk, "infix") == 0 || strcmp(nk, "infix_expression") == 0) {
@@ -1081,7 +1091,7 @@ static char *extract_callee_lang_specific(CBMArena *a, TSNode node, const char *
if (lang == CBM_LANG_ERLANG) {
return extract_erlang_callee(a, node, source, nk);
}
if (lang == CBM_LANG_HASKELL || lang == CBM_LANG_OCAML) {
if (lang == CBM_LANG_HASKELL || lang == CBM_LANG_OCAML || lang == CBM_LANG_PURESCRIPT) {
return extract_fp_callee(a, node, source, nk);
}
if (lang == CBM_LANG_WOLFRAM && strcmp(nk, "apply") == 0) {