From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Yuan Fu Newsgroups: gmane.emacs.bugs Subject: bug#62368: 29.0.60; Evaluating predicates before creating captured nodes in treesit-query-capture Date: Tue, 21 Mar 2023 21:49:37 -0700 Message-ID: <09A7EAB7-332E-4123-A6DB-8921FBD325C4@gmail.com> Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3731.400.51.1.1\)) Content-Type: multipart/mixed; boundary="Apple-Mail=_F0AA0D58-CC72-4D8F-8886-266955D615F2" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="1063"; mail-complaints-to="usenet@ciao.gmane.io" Cc: dgutov@yandex.ru To: 62368@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Wed Mar 22 05:50:22 2023 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1peqQX-00005b-QM for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 22 Mar 2023 05:50:22 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1peqQJ-0005Bo-C4; Wed, 22 Mar 2023 00:50:07 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1peqQE-0005BX-5t for bug-gnu-emacs@gnu.org; Wed, 22 Mar 2023 00:50:03 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1peqQD-0001Ey-SZ for bug-gnu-emacs@gnu.org; Wed, 22 Mar 2023 00:50:01 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1peqQD-0007mV-MR; Wed, 22 Mar 2023 00:50:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Yuan Fu Original-Sender: "Debbugs-submit" Resent-CC: dgutov@yandex.ru, bug-gnu-emacs@gnu.org Resent-Date: Wed, 22 Mar 2023 04:50:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 62368 X-GNU-PR-Package: emacs X-Debbugs-Original-To: Bug Report Emacs X-Debbugs-Original-Xcc: dgutov@yandex.ru Original-Received: via spool by submit@debbugs.gnu.org id=B.167946059429891 (code B ref -1); Wed, 22 Mar 2023 04:50:01 +0000 Original-Received: (at submit) by debbugs.gnu.org; 22 Mar 2023 04:49:54 +0000 Original-Received: from localhost ([127.0.0.1]:33194 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1peqQ6-0007m3-Dv for submit@debbugs.gnu.org; Wed, 22 Mar 2023 00:49:54 -0400 Original-Received: from lists.gnu.org ([209.51.188.17]:39286) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1peqQ5-0007lw-7p for submit@debbugs.gnu.org; Wed, 22 Mar 2023 00:49:53 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1peqQ4-0005Aj-NM for bug-gnu-emacs@gnu.org; Wed, 22 Mar 2023 00:49:52 -0400 Original-Received: from mail-pl1-x62a.google.com ([2607:f8b0:4864:20::62a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1peqQ3-0001Di-2j for bug-gnu-emacs@gnu.org; Wed, 22 Mar 2023 00:49:52 -0400 Original-Received: by mail-pl1-x62a.google.com with SMTP id iw3so18234384plb.6 for ; Tue, 21 Mar 2023 21:49:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1679460589; h=to:date:message-id:subject:mime-version:from:from:to:cc:subject :date:message-id:reply-to; bh=ocXgcamwd7J0CklU/TAkU+V4oFdupUANhofKGbeD4vw=; b=dvFb2EuUr79a1Yt/bFRp6JDlD+mVwSlwsA56C+h5KhYQWbUdP2StEVkzKQHiKfuZ6K gBQK6WcFURMGeUKjqVhrsGWG84+64vPV4vlMmZjAbqtgOSKVOzju8zoryd+7L+ypZ5Wp P/+BJFEdL6h1rVEWtparJVMsUWOnh0e4mPv0PD+E2Gz1vMuVGZY0pZPqUAKsK64faZBT Nwu1WKcm4waAMzjMg7AghuprOTD/Kbd/crCWPzRIqzYbwAk3mtVy0R8eDQHU0TTvq/um ds6b5owWeT+lue+j1EQORst70tVJVU7n118OZg010TiESnHolXn+8q2C3vQJ1IKyjmyu v65w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679460589; h=to:date:message-id:subject:mime-version:from:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=ocXgcamwd7J0CklU/TAkU+V4oFdupUANhofKGbeD4vw=; b=uCGY9cFRHy3B36F5u0XrI7vtr9axn9GHKYdnKsF1ug1uE3kBK9XP/V5ycugxih4gNS s3nZJLQfh+BHpqQQ/qWu3/U4Zy4Ie9jEu5vD+tJ5yNCBB6H4spp1zEAC/cJvT8iihZoI 7BPc6H0T2pqzDS0/W7F4MGUP5b8ogufAKvNFXrTHtCIStQsc2rD7tDInC+PhuleMQNRG 5Yo3uUV3dh/E4Ln+Oyy7+QZSmxYDhZw4WEyMMmbMubssP0V4iQpoHGbb0/9jorSqOWem MUzPUTFkcpZZuse4EsvtpGXcUbW/ptjf5qTqU0akdEPVJCD6yMjTEA2/aWV0k5GjFSIU yKkw== X-Gm-Message-State: AO0yUKXaDHGWg/xxNm84tfPzBs59j/Yx9ch68lUh9/YFOewgaiBXdLED 69FpX/Cma8imMAiVbG2TK95WczUE93o= X-Google-Smtp-Source: AK7set/On5A98uEbgrkuQec/rKS79FhewHawsSerUKXGvPA04H773DX/JaL7QtYwzfyQIG5AW8o1lw== X-Received: by 2002:a05:6a20:4b07:b0:d4:c41c:24e0 with SMTP id fp7-20020a056a204b0700b000d4c41c24e0mr4362427pzb.20.1679460588806; Tue, 21 Mar 2023 21:49:48 -0700 (PDT) Original-Received: from smtpclient.apple (cpe-172-117-161-177.socal.res.rr.com. [172.117.161.177]) by smtp.gmail.com with ESMTPSA id s3-20020aa78d43000000b00625c96db7desm8677870pfe.198.2023.03.21.21.49.47 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 21 Mar 2023 21:49:48 -0700 (PDT) X-Mailer: Apple Mail (2.3731.400.51.1.1) Received-SPF: pass client-ip=2607:f8b0:4864:20::62a; envelope-from=casouri@gmail.com; helo=mail-pl1-x62a.google.com X-Spam_score_int: -10 X-Spam_score: -1.1 X-Spam_bar: - X-Spam_report: (-1.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, FREEMAIL_REPLY=1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:258384 Archived-At: --Apple-Mail=_F0AA0D58-CC72-4D8F-8886-266955D615F2 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=us-ascii X-Debbugs-CC: dgutov@yandex.ru Dmitry, when you have time, could you try your benchmark in bug#60953 with this patch? I made predicates evaluate before we create any nodes, so #equal and #match should be more efficient now, when there are a lot of rejections. In the same time #pred is made slightly worst since they now create a lisp node and discard it. (But this can be fixed with a little more complexity.) Yuan --Apple-Mail=_F0AA0D58-CC72-4D8F-8886-266955D615F2 Content-Disposition: attachment; filename=pred-first.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="pred-first.patch" Content-Transfer-Encoding: quoted-printable =46rom=20312063d389ea4e4f17ab82ab3da093c172e4142d=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Yuan=20Fu=20=0ADate:=20Tue,=20= 21=20Mar=202023=2016:03:08=20-0700=0ASubject:=20[PATCH=201/3]=20Refactor=20= Ftreesit_query_capture=0A=0ARefactor=20some=20part=20of=20= Ftreesit_query_capture=20out=20into=20separate=0Afunctions,=20to=20pave=20= the=20way=20for=20other=20query-based=20functions.=0A=0A*=20= src/treesit.c=20(treesit_resolve_node):=20New=20function.=0A= (treesit_initialize_query):=20New=20function.=0A= (Ftreesit_query_capture):=20Refactor=20some=20part=20into=20new=20= functions.=0A---=0A=20src/treesit.c=20|=20153=20= ++++++++++++++++++++++++++++++++------------------=0A=201=20file=20= changed,=2097=20insertions(+),=2056=20deletions(-)=0A=0Adiff=20--git=20= a/src/treesit.c=20b/src/treesit.c=0Aindex=205a4fe3e8803..e728d697c9d=20= 100644=0A---=20a/src/treesit.c=0A+++=20b/src/treesit.c=0A@@=20-2631,8=20= +2631,8=20@@=20DEFUN=20("treesit-query-compile",=0A=20=20=20=20=20=20=20= Lisp_Object=20signal_symbol=20=3D=20Qnil;=0A=20=20=20=20=20=20=20= Lisp_Object=20signal_data=20=3D=20Qnil;=0A=20=20=20=20=20=20=20TSQuery=20= *treesit_query=20=3D=20treesit_ensure_query_compiled=20(lisp_query,=0A-=09= =09=09=09=09=09=09=20&signal_symbol,=0A-=09=09=09=09=09=09=09=20= &signal_data);=0A+=09=09=09=09=09=09=09=20=20=20=20=20=20&signal_symbol,=0A= +=09=09=09=09=09=09=09=20=20=20=20=20=20&signal_data);=0A=20=0A=20=20=20=20= =20=20=20if=20(treesit_query=20=3D=3D=20NULL)=0A=20=09xsignal=20= (signal_symbol,=20signal_data);=0A@@=20-2641,6=20+2641,92=20@@=20DEFUN=20= ("treesit-query-compile",=0A=20=20=20=20=20}=0A=20}=0A=20=0A+/*=20= Resolve=20OBJ=20into=20a=20tree-sitter=20node=20Lisp_Object.=20=20OBJ=20= can=20be=20a=0A+=20=20=20node,=20a=20parser,=20or=20a=20language=20= symbol.=20=20Note=20that=20this=20function=20can=0A+=20=20=20signal.=20=20= */=0A+static=20Lisp_Object=20treesit_resolve_node=20(Lisp_Object=20obj)=0A= +{=0A+=20=20if=20(TS_NODEP=20(obj))=0A+=20=20=20=20{=0A+=20=20=20=20=20=20= treesit_check_node=20(obj);=20/*=20Check=20if=20up-to-date.=20=20*/=0A+=20= =20=20=20=20=20return=20obj;=0A+=20=20=20=20}=0A+=20=20else=20if=20= (TS_PARSERP=20(obj))=0A+=20=20=20=20{=0A+=20=20=20=20=20=20= treesit_check_parser=20(obj);=20/*=20Check=20if=20deleted.=20=20*/=0A+=20= =20=20=20=20=20return=20Ftreesit_parser_root_node=20(obj);=0A+=20=20=20=20= }=0A+=20=20else=20if=20(SYMBOLP=20(obj))=0A+=20=20=20=20{=0A+=20=20=20=20= =20=20Lisp_Object=20parser=0A+=09=3D=20Ftreesit_parser_create=20(obj,=20= Fcurrent_buffer=20(),=20Qnil);=0A+=20=20=20=20=20=20return=20= Ftreesit_parser_root_node=20(parser);=0A+=20=20=20=20}=0A+=20=20else=0A+=20= =20=20=20xsignal2=20(Qwrong_type_argument,=0A+=09=20=20=20=20=20=20list4=20= (Qor,=20Qtreesit_node_p,=20Qtreesit_parser_p,=20Qsymbolp),=0A+=09=20=20=20= =20=20=20obj);=0A+}=0A+=0A+/*=20Create=20and=20initialize=20QUERY.=20=20= When=20success,=20initialize=20TS_QUERY,=0A+=20=20=20CURSOR,=20and=20= NEED_FREE,=20and=20return=20true;=20if=20failed,=20initialize=0A+=20=20=20= SIGNAL_SYMBOL=20and=20SIGNAL_DATA,=20and=20return=20false.=20=20If=20= NEED_FREE=20is=0A+=20=20=20initialized=20to=20true,=20the=20TS_QUERY=20= and=20CURSOR=20needs=20to=20be=20freed=0A+=20=20=20after=20use;=20= otherwise=20they=20shouldn't=20be=20freed=20by=20hand.=0A+=0A+=20=20=20= Basically=20this=20function=20looks=20at=20QUERY=20and=20check=20its=20= type,=20if=20QUERY=0A+=20=20=20is=20a=20compiled=20query,=20this=20= function=20takes=20out=20its=20query=20and=20cursor;=0A+=20=20=20if=20= QUERY=20is=20a=20string=20or=20a=20cons,=20this=20function=20creates=20a=20= new=20query=0A+=20=20=20and=20cursor=20(so=20they=20need=20to=20be=20= manually=20freed).=0A+=0A+=20=20=20This=20function=20assumes=20QUERY=20= is=20either=20a=20compiled=20query,=20a=20string=20or=0A+=20=20=20a=20= cons,=20the=20caller=20should=20make=20sure=20QUERY=20is=20valid.=0A+=0A= +=20=20=20LANG=20is=20the=20language=20to=20use=20if=20we=20need=20to=20= create=20the=20query=20and=0A+=20=20=20cursor.=20=20*/=0A+static=20bool=0A= +treesit_initialize_query=20(Lisp_Object=20query,=20const=20TSLanguage=20= *lang,=0A+=09=09=09=20=20TSQuery=20**ts_query,=20TSQueryCursor=20= **cursor,=0A+=09=09=09=20=20bool=20*need_free,=20Lisp_Object=20= *signal_symbol,=0A+=09=09=09=20=20Lisp_Object=20*signal_data)=0A+{=0A+=20= =20if=20(TS_COMPILED_QUERY_P=20(query))=0A+=20=20=20=20{=0A+=20=20=20=20=20= =20*ts_query=20=3D=20treesit_ensure_query_compiled=20(query,=20= signal_symbol,=0A+=09=09=09=09=09=09=20signal_data);=0A+=20=20=20=20=20=20= *cursor=20=3D=20XTS_COMPILED_QUERY=20(query)->cursor;=0A+=20=20=20=20=20=20= /*=20We=20don't=20need=20to=20free=20ts_query=20and=20cursor=20because=20= they=0A+=09=20are=20stored=20in=20a=20lisp=20object,=20which=20is=20= tracked=20by=20gc.=20=20*/=0A+=20=20=20=20=20=20*need_free=20=3D=20= false;=0A+=20=20=20=20=20=20return=20(*ts_query=20!=3D=20NULL);=0A+=20=20= =20=20}=0A+=20=20else=0A+=20=20=20=20{=0A+=20=20=20=20=20=20/*=20Since=20= query=20is=20not=20TS_COMPILED_QUERY,=20it=20can=20only=20be=20a=20= string=0A+=09=20or=20a=20cons.=20=20*/=0A+=20=20=20=20=20=20if=20(CONSP=20= (query))=0A+=09query=20=3D=20Ftreesit_query_expand=20(query);=0A+=20=20=20= =20=20=20char=20*query_string=20=3D=20SSDATA=20(query);=0A+=20=20=20=20=20= =20uint32_t=20error_offset;=0A+=20=20=20=20=20=20TSQueryError=20= error_type;=0A+=20=20=20=20=20=20*ts_query=20=3D=20ts_query_new=20(lang,=20= query_string,=20strlen=20(query_string),=0A+=09=09=09=09&error_offset,=20= &error_type);=0A+=20=20=20=20=20=20if=20(*ts_query=20=3D=3D=20NULL)=0A+=09= {=0A+=09=20=20*signal_symbol=20=3D=20Qtreesit_query_error;=0A+=09=20=20= *signal_data=20=3D=20treesit_compose_query_signal_data=20(error_offset,=0A= +=09=09=09=09=09=09=09=20=20=20=20error_type,=20query);=0A+=09=20=20= return=20false;=0A+=09}=0A+=20=20=20=20=20=20else=0A+=09{=0A+=09=20=20= *cursor=20=3D=20ts_query_cursor_new=20();=0A+=09=20=20*need_free=20=3D=20= true;=0A+=09=20=20return=20true;=0A+=09}=0A+=20=20=20=20}=0A+}=0A+=0A=20= DEFUN=20("treesit-query-capture",=0A=20=20=20=20=20=20=20=20= Ftreesit_query_capture,=0A=20=20=20=20=20=20=20=20= Streesit_query_capture,=202,=205,=200,=0A@@=20-2681,27=20+2767,7=20@@=20= DEFUN=20("treesit-query-capture",=0A=20=20=20treesit_initialize=20();=0A=20= =0A=20=20=20/*=20Resolve=20NODE=20into=20an=20actual=20node.=20=20*/=0A-=20= =20Lisp_Object=20lisp_node;=0A-=20=20if=20(TS_NODEP=20(node))=0A-=20=20=20= =20{=0A-=20=20=20=20=20=20treesit_check_node=20(node);=20/*=20Check=20if=20= up-to-date.=20=20*/=0A-=20=20=20=20=20=20lisp_node=20=3D=20node;=0A-=20=20= =20=20}=0A-=20=20else=20if=20(TS_PARSERP=20(node))=0A-=20=20=20=20{=0A-=20= =20=20=20=20=20treesit_check_parser=20(node);=20/*=20Check=20if=20= deleted.=20=20*/=0A-=20=20=20=20=20=20lisp_node=20=3D=20= Ftreesit_parser_root_node=20(node);=0A-=20=20=20=20}=0A-=20=20else=20if=20= (SYMBOLP=20(node))=0A-=20=20=20=20{=0A-=20=20=20=20=20=20Lisp_Object=20= parser=0A-=09=3D=20Ftreesit_parser_create=20(node,=20Fcurrent_buffer=20= (),=20Qnil);=0A-=20=20=20=20=20=20lisp_node=20=3D=20= Ftreesit_parser_root_node=20(parser);=0A-=20=20=20=20}=0A-=20=20else=0A-=20= =20=20=20xsignal2=20(Qwrong_type_argument,=0A-=09=20=20=20=20=20=20list4=20= (Qor,=20Qtreesit_node_p,=20Qtreesit_parser_p,=20Qsymbolp),=0A-=09=20=20=20= =20=20=20node);=0A+=20=20Lisp_Object=20lisp_node=20=3D=20= treesit_resolve_node=20(node);=0A=20=0A=20=20=20/*=20Extract=20C=20= values=20from=20Lisp=20objects.=20=20*/=0A=20=20=20TSNode=20treesit_node=0A= @@=20-2725,40=20+2791,15=20@@=20DEFUN=20("treesit-query-capture",=0A=20=20= =20TSQuery=20*treesit_query;=0A=20=20=20TSQueryCursor=20*cursor;=0A=20=20= =20bool=20needs_to_free_query_and_cursor;=0A-=20=20if=20= (TS_COMPILED_QUERY_P=20(query))=0A-=20=20=20=20{=0A-=20=20=20=20=20=20= Lisp_Object=20signal_symbol=20=3D=20Qnil;=0A-=20=20=20=20=20=20= Lisp_Object=20signal_data=20=3D=20Qnil;=0A-=20=20=20=20=20=20= treesit_query=20=3D=20treesit_ensure_query_compiled=20(query,=20= &signal_symbol,=0A-=09=09=09=09=09=09=20=20=20=20=20&signal_data);=0A-=20= =20=20=20=20=20cursor=20=3D=20XTS_COMPILED_QUERY=20(query)->cursor;=0A-=20= =20=20=20=20=20/*=20We=20don't=20need=20to=20free=20ts_query=20and=20= cursor=20because=20they=0A-=09=20are=20stored=20in=20a=20lisp=20object,=20= which=20is=20tracked=20by=20gc.=20=20*/=0A-=20=20=20=20=20=20= needs_to_free_query_and_cursor=20=3D=20false;=0A-=20=20=20=20=20=20if=20= (treesit_query=20=3D=3D=20NULL)=0A-=09xsignal=20(signal_symbol,=20= signal_data);=0A-=20=20=20=20}=0A-=20=20else=0A-=20=20=20=20{=0A-=20=20=20= =20=20=20/*=20Since=20query=20is=20not=20TS_COMPILED_QUERY,=20it=20can=20= only=20be=20a=20string=0A-=09=20or=20a=20cons.=20=20*/=0A-=20=20=20=20=20= =20if=20(CONSP=20(query))=0A-=09query=20=3D=20Ftreesit_query_expand=20= (query);=0A-=20=20=20=20=20=20char=20*query_string=20=3D=20SSDATA=20= (query);=0A-=20=20=20=20=20=20uint32_t=20error_offset;=0A-=20=20=20=20=20= =20TSQueryError=20error_type;=0A-=20=20=20=20=20=20treesit_query=20=3D=20= ts_query_new=20(lang,=20query_string,=20strlen=20(query_string),=0A-=09=09= =09=09=20=20=20=20&error_offset,=20&error_type);=0A-=20=20=20=20=20=20if=20= (treesit_query=20=3D=3D=20NULL)=0A-=09xsignal=20(Qtreesit_query_error,=0A= -=09=09=20treesit_compose_query_signal_data=20(error_offset,=0A-=09=09=09= =09=09=09=20=20=20=20error_type,=20query));=0A-=20=20=20=20=20=20cursor=20= =3D=20ts_query_cursor_new=20();=0A-=20=20=20=20=20=20= needs_to_free_query_and_cursor=20=3D=20true;=0A-=20=20=20=20}=0A+=20=20= Lisp_Object=20signal_symbol;=0A+=20=20Lisp_Object=20signal_data;=0A+=20=20= if=20(!treesit_initialize_query=20(query,=20lang,=20&treesit_query,=20= &cursor,=0A+=09=09=09=09=20&needs_to_free_query_and_cursor,=0A+=09=09=09=09= =20&signal_symbol,=20&signal_data))=0A+=20=20=20=20xsignal=20= (signal_symbol,=20signal_data);=0A=20=0A-=20=20/*=20WARN:=20After=20this=20= point,=20free=20treesit_query=20and=20cursor=20before=20every=0A-=20=20=20= =20=20signal=20and=20return.=20=20*/=0A+=20=20/*=20WARN:=20After=20this=20= point,=20free=20TREESIT_QUERY=20and=20CURSOR=20before=20every=0A+=20=20=20= =20=20signal=20and=20return=20if=20NEEDS_TO_FREE_QUERY_AND_CURSOR=20is=20= true.=20=20*/=0A=20=0A=20=20=20/*=20Set=20query=20range.=20=20*/=0A=20=20= =20if=20(!NILP=20(beg)=20&&=20!NILP=20(end))=0A--=20=0A2.33.1=0A=0A=0A= =46rom=20b166cb228cfe23ede54718d4b5ab6d1753d8337e=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Yuan=20Fu=20=0ADate:=20Tue,=20= 21=20Mar=202023=2016:13:23=20-0700=0ASubject:=20[PATCH=202/3]=20;=20= Minor=20refactor=20of=20Ftreesit_query_capture=0A=0A*=20src/treesit.c=20= (Ftreesit_query_capture):=20Move=20around=20some=20variable=0A= initialization.=0A---=0A=20src/treesit.c=20|=2011=20+++++------=0A=201=20= file=20changed,=205=20insertions(+),=206=20deletions(-)=0A=0Adiff=20= --git=20a/src/treesit.c=20b/src/treesit.c=0Aindex=20= e728d697c9d..cd98ff38293=20100644=0A---=20a/src/treesit.c=0A+++=20= b/src/treesit.c=0A@@=20-2770,12=20+2770,9=20@@=20DEFUN=20= ("treesit-query-capture",=0A=20=20=20Lisp_Object=20lisp_node=20=3D=20= treesit_resolve_node=20(node);=0A=20=0A=20=20=20/*=20Extract=20C=20= values=20from=20Lisp=20objects.=20=20*/=0A-=20=20TSNode=20treesit_node=0A= -=20=20=20=20=3D=20XTS_NODE=20(lisp_node)->node;=0A-=20=20Lisp_Object=20= lisp_parser=0A-=20=20=20=20=3D=20XTS_NODE=20(lisp_node)->parser;=0A-=20=20= ptrdiff_t=20visible_beg=0A-=20=20=20=20=3D=20XTS_PARSER=20(XTS_NODE=20= (lisp_node)->parser)->visible_beg;=0A+=20=20TSNode=20treesit_node=20=3D=20= XTS_NODE=20(lisp_node)->node;=0A+=20=20Lisp_Object=20lisp_parser=20=3D=20= XTS_NODE=20(lisp_node)->parser;=0A+=0A=20=20=20const=20TSLanguage=20= *lang=0A=20=20=20=20=20=3D=20ts_parser_language=20(XTS_PARSER=20= (lisp_parser)->parser);=0A=20=0A@@=20-2804,6=20+2801,8=20@@=20DEFUN=20= ("treesit-query-capture",=0A=20=20=20/*=20Set=20query=20range.=20=20*/=0A= =20=20=20if=20(!NILP=20(beg)=20&&=20!NILP=20(end))=0A=20=20=20=20=20{=0A= +=20=20=20=20=20=20ptrdiff_t=20visible_beg=0A+=09=3D=20XTS_PARSER=20= (XTS_NODE=20(lisp_node)->parser)->visible_beg;=0A=20=20=20=20=20=20=20= ptrdiff_t=20beg_byte=20=3D=20CHAR_TO_BYTE=20(XFIXNUM=20(beg));=0A=20=20=20= =20=20=20=20ptrdiff_t=20end_byte=20=3D=20CHAR_TO_BYTE=20(XFIXNUM=20= (end));=0A=20=20=20=20=20=20=20/*=20We=20never=20let=20tree-sitter=20run=20= on=20buffers=20too=20large,=20so=20these=0A--=20=0A2.33.1=0A=0A=0A=46rom=20= 5c6c111a92c1da0a81b97a42a0b84fe8d9f03524=20Mon=20Sep=2017=2000:00:00=20= 2001=0AFrom:=20Yuan=20Fu=20=0ADate:=20Tue,=2021=20Mar=20= 2023=2021:10:59=20-0700=0ASubject:=20[PATCH=203/3]=20Evaluate=20= tree-sitter=20predicate=20functions=20before=20create=0A=20node=0A=0ABy=20= evaluating=20predicates=20before=20creating=20nodes,=20we=20can=20= eliminate=20some=0Awasteful=20consing=20when=20there=20are=20many=20= rejections=20(bug#60953).=20=20The=20one=0Adown=20side=20is=20that=20= #pred=20predicate=20now=20creates=20superfluous=20nodes:=20it=0Acreates=20= a=20node=20to=20feed=20to=20the=20function,=20but=20then=20discard=20it.=20= =20We=20can=0Aimprove=20it=20later=20if=20it=20proves=20problematic.=0A=0A= *=20src/treesit.c:=0A(capture_range):=20Remove.=0A(predicate_context):=20= New=20struct.=0A(treesit_predicates_for_pattern):=20Capture=20names=20= are=0Anot=20symbols=20anymore,=20but=20rather=20index=20numbers.=0A= (treesit_capture_id_to_name):=20New=20subroutine=20function=20that=20= converts=0Aan=20index=20number=20to=20the=20capture=20name.=20=20This=20= is=20only=20used=20by=20error=0Areporting.=0A= (treesit_predicate_capture_name_to_node):=20Remove.=0A= (treesit_capture_id_to_node):=20New=20function.=0A= (treesit_predicate_capture_name_to_text):=20Remove.=0A= (treesit_capture_id_to_text):=20New=20function.=0A= (treesit_predicate_equal)=0A(treesit_predicate_match)=0A= (treesit_predicate_pred)=0A(treesit_eval_predicates):=20Change=20to=20= the=20new=20index-based=20format.=20=20Also=0Anow=20we=20return=20the=20= signal=20data=20rather=20than=20signaling=20directly.=0A= (Ftreesit_query_capture):=20Now=20we=20evaluate=20predicates=20before=20= creating=0Anodes.=20=20We=20also=20set=20the=20current=20buffer=20to=20= that=20of=20the=20node=20we=20are=0Aworking=20on,=20so=20that=20the=20= predicate=20functions=20don't=20need=20to=20switch=0Abuffers=20= back-and-forth.=20=20Also,=20handle=20signals=20gracefully=20so=20we=20= don't=0Aleak=20memory.=0A---=0A=20src/treesit.c=20|=20337=20= +++++++++++++++++++++++++++++++-------------------=0A=201=20file=20= changed,=20208=20insertions(+),=20129=20deletions(-)=0A=0Adiff=20--git=20= a/src/treesit.c=20b/src/treesit.c=0Aindex=20cd98ff38293..c751223fc19=20= 100644=0A---=20a/src/treesit.c=0A+++=20b/src/treesit.c=0A@@=20-2349,23=20= +2349,38=20@@=20DEFUN=20("treesit-query-expand",=0A=20=20=20return=20= Fmapconcat=20(Qtreesit_pattern_expand,=20query,=20Vtreesit_str_space);=0A= =20}=0A=20=0A-/*=20This=20struct=20is=20used=20for=20passing=20captures=20= to=20be=20check=20against=0A-=20=20=20predicates.=20=20Captures=20we=20= check=20for=20are=20the=20ones=20in=20START=20before=0A-=20=20=20END.=20=20= For=20example,=20if=20START=20and=20END=20are=0A+/*=20This=20struct=20is=20= used=20passing=20context=20for=20evaluating=20predicates.=0A+=20=20=20= QUERY=20and=20MATCH=20are=20self-explanatory,=20ROOT_NODE=20is=20the=20= node=20we=20are=0A+=20=20=20querying.=0A=20=0A-=20=20=20START=20=20=20=20= =20=20=20END=0A+=20=20=20START=20and=20END=20points=20to=20the=20list=20= of=20captured=20nodes=20we=20are=20returning=0A+=20=20=20from=20= Ftreesit_query_capture.=20=20They=20mark=20the=20nodes=20we=20captured=20= in=0A+=20=20=20this=20match.=20=20Because=20we=20evaluate=20predicates=20= before=20adding=20captured=0A+=20=20=20nodes=20to=20the=20result=20list,=20= right=20now=20START=20simply=20equal=20to=20END.=0A+=0A+=20=20=20But=20= if=20we=20later=20decide=20we=20want=20to=20optimize=20for=20#pred=20= predicate,=0A+=20=20=20these=20two=20pointer=20will=20be=20useful.=0A+=0A= +=20=20=20An=20example:=0A+=0A+=20=20=20=20START=20=20=20=20=20=20=20=20=20= =20END=0A=20=20=20=20=20v=20=20=20=20=20=20=20=20=20=20=20=20=20=20v=0A-=20= =20=20(1=20.=20(2=20.=20(3=20.=20(4=20.=20(5=20.=20(6=20.=20nil))))))=0A= +=20=20=20(1=20.=20(2=20.=20(3=20.=20(4=20.=20(5=20.=20(6=20.=20= nil))))))=20->=20complete=20result=20list=0A=20=0A-=20=20=20We=20only=20= look=20at=20captures=201=202=203.=20=20*/=0A-struct=20capture_range=0A+=20= =20=201=202=203=20are=20the=20nodes=20captured=20by=20the=20current=20= match.=20=20*/=0A+struct=20predicate_context=0A=20{=0A+=20=20TSQuery=20= *query;=0A+=20=20TSQueryMatch=20*match;=0A+=20=20Lisp_Object=20= root_node;=0A=20=20=20Lisp_Object=20start;=0A=20=20=20Lisp_Object=20end;=0A= =20};=0A=20=0A=20/*=20Collect=20predicates=20for=20this=20match=20and=20= return=20them=20in=20a=20list.=20=20Each=0A-=20=20=20predicate=20is=20a=20= list=20of=20strings=20and=20symbols.=20=20*/=0A+=20=20=20predicate=20is=20= a=20list=20of=20strings=20and=20numbers.=20=20A=20number=20represents=0A= +=20=20=20the=20id=20of=20a=20capture=20name,=20the=20same=20thing=20as=20= the=20index=20attribute=20of=0A+=20=20=20a=20TSQueryCapture.=20=20*/=0A=20= static=20Lisp_Object=0A=20treesit_predicates_for_pattern=20(TSQuery=20= *query,=20uint32_t=20pattern_index)=0A=20{=0A@@=20-2381,12=20+2396,7=20= @@=20treesit_predicates_for_pattern=20(TSQuery=20*query,=20uint32_t=20= pattern_index)=0A=20=09{=0A=20=09case=20TSQueryPredicateStepTypeCapture:=0A= =20=09=20=20{=0A-=09=20=20=20=20uint32_t=20str_len;=0A-=09=20=20=20=20= const=20char=20*str=20=3D=20ts_query_capture_name_for_id=20(query,=0A-=09= =09=09=09=09=09=09=20=20=20=20step.value_id,=0A-=09=09=09=09=09=09=09=20=20= =20=20&str_len);=0A-=09=20=20=20=20predicate=20=3D=20Fcons=20= (intern_c_string_1=20(str,=20str_len),=0A-=09=09=09=20=20=20=20=20=20=20= predicate);=0A+=09=20=20=20=20predicate=20=3D=20Fcons=20(make_fixnum=20= (step.value_id),=20predicate);=0A=20=09=20=20=20=20break;=0A=20=09=20=20= }=0A=20=09case=20TSQueryPredicateStepTypeString:=0A@@=20-2407,118=20= +2417,159=20@@=20treesit_predicates_for_pattern=20(TSQuery=20*query,=20= uint32_t=20pattern_index)=0A=20=20=20return=20Fnreverse=20(result);=0A=20= }=0A=20=0A-/*=20Translate=20a=20capture=20NAME=20(symbol)=20to=20a=20= node.=0A-=20=20=20Signals=20treesit-query-error=20if=20such=20node=20is=20= not=20captured.=20=20*/=0A=20static=20Lisp_Object=0A= -treesit_predicate_capture_name_to_node=20(Lisp_Object=20name,=0A-=09=09=09= =09=09struct=20capture_range=20captures)=0A+treesit_capture_id_to_name=20= (TSQuery=20*query,=20ptrdiff_t=20id)=0A=20{=0A-=20=20Lisp_Object=20node=20= =3D=20Qnil;=0A-=20=20for=20(Lisp_Object=20tail=20=3D=20captures.start;=20= !EQ=20(tail,=20captures.end);=0A-=20=20=20=20=20=20=20tail=20=3D=20XCDR=20= (tail))=0A-=20=20=20=20{=0A-=20=20=20=20=20=20if=20(EQ=20(XCAR=20(XCAR=20= (tail)),=20name))=0A-=09{=0A-=09=20=20node=20=3D=20XCDR=20(XCAR=20= (tail));=0A-=09=20=20break;=0A-=09}=0A-=20=20=20=20}=0A-=0A-=20=20if=20= (NILP=20(node))=0A-=20=20=20=20xsignal3=20(Qtreesit_query_error,=0A-=09=20= =20=20=20=20=20build_string=20("Cannot=20find=20captured=20node"),=0A-=09= =20=20=20=20=20=20name,=20build_string=20("A=20predicate=20can=20only=20= refer"=0A-=09=09=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"=20= to=20captured=20nodes=20in=20the=20"=0A-=09=09=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20"same=20pattern"));=0A-=20=20return=20node;=0A= +=20=20uint32_t=20len;=0A+=20=20const=20char*=20name_str=20=3D=20= ts_query_capture_name_for_id=20(query,=20(uint32_t)=20id,=0A+=09=09=09=09= =09=09=20=20=20=20=20=20=20&len);=0A+=20=20return=20make_string=20= (name_str,=20(ptrdiff_t)=20len);=0A=20}=0A=20=0A-/*=20Translate=20a=20= capture=20NAME=20(symbol)=20to=20the=20text=20of=20the=20captured=20= node.=0A-=20=20=20Signals=20treesit-query-error=20if=20such=20node=20is=20= not=20captured.=20=20*/=0A-static=20Lisp_Object=0A= -treesit_predicate_capture_name_to_text=20(Lisp_Object=20name,=0A-=09=09=09= =09=09struct=20capture_range=20captures)=0A+/*=20Translate=20a=20capture=20= id=20(fixnum)=20into=20the=20captured=20TSNode=20and=20set=20to=0A+=20=20= =20NODE.=20=20If=20we=20can't=20find=20the=20captured=20node,=20set=20= SIGNAL_DATA=20and=0A+=20=20=20return=20false,=20otherwise=20return=20= true.=20=20*/=0A+static=20bool=0A+treesit_capture_id_to_node=20(TSNode=20= *node,=20Lisp_Object=20id,=0A+=09=09=09=20=20=20=20struct=20= predicate_context=20*context,=0A+=09=09=09=20=20=20=20Lisp_Object=20= *signal_data)=0A=20{=0A-=20=20Lisp_Object=20node=20=3D=20= treesit_predicate_capture_name_to_node=20(name,=20captures);=0A+=20=20= const=20TSQueryCapture=20*captures=20=3D=20context->match->captures;=0A+=20= =20for=20(int=20idx=20=3D=200;=20idx=20<=20= context->match->capture_count;=20idx++)=0A+=20=20=20=20{=0A+=20=20=20=20=20= =20if=20(captures[idx].index=20=3D=3D=20XFIXNUM=20(id))=0A+=09{=0A+=09=20= =20*node=20=3D=20captures->node;=0A+=09=20=20return=20true;=0A+=09}=0A+=20= =20=20=20}=0A+=20=20Lisp_Object=20name=20=3D=20= treesit_capture_id_to_name=20(context->query,=20XFIXNUM=20(id));=0A+=20=20= *signal_data=20=3D=20list3=20(build_string=20("Cannot=20find=20captured=20= node"),=0A+=09=09=09name,=20build_string=20("A=20predicate=20can=20only=20= refer"=0A+=09=09=09=09=09=20=20=20=20"=20to=20captured=20nodes=20in=20= the=20"=0A+=09=09=09=09=09=20=20=20=20"same=20pattern"));=0A+=20=20= return=20false;=0A+}=0A=20=0A-=20=20struct=20buffer=20*old_buffer=20=3D=20= current_buffer;=0A-=20=20set_buffer_internal=20(XBUFFER=20(XTS_PARSER=20= (XTS_NODE=20(node)->parser)->buffer));=0A-=20=20Lisp_Object=20text=20=3D=20= Fbuffer_substring=20(Ftreesit_node_start=20(node),=0A-=09=09=09=09=09= Ftreesit_node_end=20(node));=0A-=20=20set_buffer_internal=20= (old_buffer);=0A-=20=20return=20text;=0A+/*=20Translate=20a=20capture=20= id=20(fixnum)=20into=20the=20text=20of=20the=20captured=20node=0A+=20=20=20= in=20the=20current=20buffer,=20and=20populate=20TEXT=20with=20it.=20=20= (Assumes=20current=0A+=20=20=20buffer=20is=20the=20buffer=20in=20which=20= the=20captured=20node=20and=20ROOT_NODE=20is).=0A+=20=20=20ROOT_NODE=20= is=20the=20root=20node=20of=20the=20query.=20=20If=20we=20can't=20find=20= the=0A+=20=20=20captured=20node,=20set=20SIGNAL_DATA=20and=20return=20= false,=20otherwise=20return=0A+=20=20=20true.=20=20*/=0A+static=20bool=0A= +treesit_capture_id_to_text=20(Lisp_Object=20*text,=20Lisp_Object=20id,=0A= +=09=09=09=20=20=20=20struct=20predicate_context=20*context,=0A+=09=09=09= =20=20=20=20Lisp_Object=20*signal_data)=0A+{=0A+=20=20TSNode=20node;=0A+=20= =20if=20(!treesit_capture_id_to_node=20(&node,=20id,=20context,=20= signal_data))=0A+=20=20=20=20return=20false;=0A+=0A+=20=20Lisp_Object=20= parser=20=3D=20XTS_NODE=20(context->root_node)->parser;=0A+=20=20= ptrdiff_t=20begin_v=20=3D=20XTS_PARSER=20(parser)->visible_beg;=0A+=0A+=20= =20ptrdiff_t=20start_byte=20=3D=20(ptrdiff_t)=20ts_node_start_byte=20= (node)=20+=20begin_v;=0A+=20=20ptrdiff_t=20end_byte=20=3D=20(ptrdiff_t)=20= ts_node_end_byte=20(node)=20+=20begin_v;=0A+=0A+=20=20ptrdiff_t=20start=20= =3D=20BYTE_TO_CHAR=20(start_byte);=0A+=20=20ptrdiff_t=20end=20=3D=20= BYTE_TO_CHAR=20(end_byte);=0A+=0A+=20=20*text=20=3D=20= make_buffer_string_both=20(start,=20start_byte,=0A+=09=09=09=09=20=20=20= end,=20end_byte,=20false);=0A+=20=20return=20true;=0A=20}=0A=20=0A=20/*=20= Handles=20predicate=20(#equal=20A=20B).=20=20Return=20true=20if=20A=20= equals=20B;=20return=0A-=20=20=20false=20otherwise.=20=20A=20and=20B=20= can=20be=20either=20string,=20or=20a=20capture=20name.=0A-=20=20=20The=20= capture=20name=20evaluates=20to=20the=20text=20its=20captured=20node=20= spans=20in=0A-=20=20=20the=20buffer.=20=20*/=0A+=20=20=20false=20= otherwise.=20=20A=20and=20B=20can=20be=20a=20either=20string=20or=20a=20= capture=20id.=0A+=20=20=20The=20capture=20id=20evaluates=20to=20the=20= text=20spanned=20by=20the=20captured=20node=0A+=20=20=20in=20the=20= buffer.=20=20Assume=20current=20buffer=20is=20the=20buffer=20of=20the=20= captured=0A+=20=20=20node=20and=20ROOT_NODE.=20=20If=20something=20went=20= wrong,=20set=20signal_data,=0A+=20=20=20otherwise=20set=20it=20to=20= Qnil.=20=20IOW,=20caller=20should=20check=20the=20nullness=20of=0A+=20=20= =20signal_data=20for=20errors.=20=20*/=0A=20static=20bool=0A= -treesit_predicate_equal=20(Lisp_Object=20args,=20struct=20capture_range=20= captures)=0A+treesit_predicate_equal=20(Lisp_Object=20args,=20struct=20= predicate_context=20*context,=0A+=09=09=09=20Lisp_Object=20*signal_data)=0A= =20{=0A+=20=20*signal_data=20=3D=20Qnil;=0A=20=20=20if=20(XFIXNUM=20= (Flength=20(args))=20!=3D=202)=0A-=20=20=20=20xsignal2=20= (Qtreesit_query_error,=0A-=09=20=20=20=20=20=20build_string=20= ("Predicate=20`equal'=20requires=20"=0A-=09=09=20=20=20=20=20=20=20=20=20= =20=20=20"two=20arguments=20but=20only=20given"),=0A-=09=20=20=20=20=20=20= Flength=20(args));=0A-=0A+=20=20=20=20{=0A+=20=20=20=20=20=20= *signal_data=20=3D=20list2=20(build_string=20("Predicate=20`equal'=20= requires=20"=0A+=09=09=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20"two=20arguments=20but=20was=20given"),=0A+=09= =09=09=20=20=20=20Flength=20(args));=0A+=20=20=20=20=20=20return=20= false;=0A+=20=20=20=20}=0A=20=20=20Lisp_Object=20arg1=20=3D=20XCAR=20= (args);=0A=20=20=20Lisp_Object=20arg2=20=3D=20XCAR=20(XCDR=20(args));=0A= -=20=20Lisp_Object=20text1=20=3D=20(STRINGP=20(arg1)=0A-=09=09=20=20=20=20= =20=20=20?=20arg1=0A-=09=09=20=20=20=20=20=20=20:=20= treesit_predicate_capture_name_to_text=20(arg1,=0A-=09=09=09=09=09=09=09=09= =20captures));=0A-=20=20Lisp_Object=20text2=20=3D=20(STRINGP=20(arg2)=0A= -=09=09=20=20=20=20=20=20=20?=20arg2=0A-=09=09=20=20=20=20=20=20=20:=20= treesit_predicate_capture_name_to_text=20(arg2,=0A-=09=09=09=09=09=09=09=09= =20captures));=0A+=20=20Lisp_Object=20text1=20=3D=20arg1;=0A+=20=20= Lisp_Object=20text2=20=3D=20arg2;=0A+=20=20if=20(FIXNUMP=20(arg1))=0A+=20= =20=20=20{=0A+=20=20=20=20=20=20if=20(!treesit_capture_id_to_text=20= (&text1,=20arg1,=20context,=20signal_data))=0A+=09return=20false;=0A=20=0A= +=20=20=20=20}=0A+=20=20if=20(FIXNUMP=20(arg2))=0A+=20=20=20=20{=0A+=20=20= =20=20=20=20if=20(!treesit_capture_id_to_text=20(&text2,=20arg2,=20= context,=20signal_data))=0A+=09return=20false;=0A+=20=20=20=20}=0A=20=20=20= return=20!NILP=20(Fstring_equal=20(text1,=20text2));=0A=20}=0A=20=0A=20= /*=20Handles=20predicate=20(#match=20"regexp"=20@node).=20=20Return=20= true=20if=20"regexp"=0A-=20=20=20matches=20the=20text=20spanned=20by=20= @node;=20return=20false=20otherwise.=20=20Matching=0A-=20=20=20is=20= case-sensitive.=20=20*/=0A+=20=20=20matches=20the=20text=20spanned=20by=20= @node;=20return=20false=20otherwise.=0A+=20=20=20Matching=20is=20= case-sensitive.=20=20Assume=20current=20buffer=20is=20the=20buffer=20of=0A= +=20=20=20the=20captured=20node=20and=20ROOT_NODE.=20=20If=20something=20= went=20wrong,=20set=0A+=20=20=20signal_data,=20otherwise=20set=20it=20to=20= Qnil.=20=20IOW,=20caller=20should=20check=0A+=20=20=20the=20nullness=20= of=20signal_data=20for=20errors.=20=20*/=0A=20static=20bool=0A= -treesit_predicate_match=20(Lisp_Object=20args,=20struct=20capture_range=20= captures)=0A+treesit_predicate_match=20(Lisp_Object=20args,=20struct=20= predicate_context=20*context,=0A+=09=09=09=20Lisp_Object=20*signal_data)=0A= =20{=0A+=20=20*signal_data=20=3D=20Qnil;=0A=20=20=20if=20(XFIXNUM=20= (Flength=20(args))=20!=3D=202)=0A-=20=20=20=20xsignal2=20= (Qtreesit_query_error,=0A-=09=20=20=20=20=20=20build_string=20= ("Predicate=20`match'=20requires=20two=20"=0A-=09=09=20=20=20=20=20=20=20= =20=20=20=20=20"arguments=20but=20only=20given"),=0A-=09=20=20=20=20=20=20= Flength=20(args));=0A+=20=20=20=20{=0A+=20=20=20=20=20=20*signal_data=20= =3D=20list2=20(build_string=20("Predicate=20`match'=20requires=20two=20"=0A= +=09=09=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20"arguments=20but=20only=20given"),=0A+=09=09=09=20=20=20=20= Flength=20(args));=0A+=20=20=20=20=20=20return=20false;=0A+=20=20=20=20}=0A= =20=0A=20=20=20Lisp_Object=20regexp=20=3D=20XCAR=20(args);=0A-=20=20= Lisp_Object=20capture_name=20=3D=20XCAR=20(XCDR=20(args));=0A+=20=20= Lisp_Object=20capture_id=20=3D=20XCAR=20(XCDR=20(args));=0A=20=0A=20=20=20= /*=20It's=20probably=20common=20to=20get=20the=20argument=20order=20= backwards.=20=20Catch=0A=20=20=20=20=20=20this=20mistake=20early=20and=20= show=20helpful=20explanation,=20because=20Emacs=0A=20=20=20=20=20=20= loves=20you.=20=20(We=20put=20the=20regexp=20first=20because=20that's=20= what=0A=20=20=20=20=20=20string-match=20does.)=20=20*/=0A=20=20=20if=20= (!STRINGP=20(regexp))=0A-=20=20=20=20xsignal1=20(Qtreesit_query_error,=0A= -=09=20=20=20=20=20=20build_string=20("The=20first=20argument=20to=20= `match'=20should=20"=0A-=09=09=20=20=20=20=20=20=20=20=20=20=20=20"be=20= a=20regexp=20string,=20not=20a=20capture=20name"));=0A-=20=20if=20= (!SYMBOLP=20(capture_name))=0A-=20=20=20=20xsignal1=20= (Qtreesit_query_error,=0A-=09=20=20=20=20=20=20build_string=20("The=20= second=20argument=20to=20`match'=20should=20"=0A-=09=09=20=20=20=20=20=20= =20=20=20=20=20=20"be=20a=20capture=20name,=20not=20a=20string"));=0A+=20= =20=20=20{=0A+=20=20=20=20=20=20*signal_data=20=3D=20build_string=20= ("The=20first=20argument=20to=20`match'=20should=20"=0A+=09=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"be=20= a=20regexp=20string,=20not=20a=20capture=20name");=0A+=20=20=20=20=20=20= return=20false;=0A+=20=20=20=20}=0A+=20=20if=20(!FIXNUMP=20(capture_id))=0A= +=20=20=20=20{=0A+=20=20=20=20=20=20*signal_data=20=3D=20build_string=20= ("The=20second=20argument=20to=20`match'=20should=20"=0A+=09=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"be=20= a=20capture=20name,=20not=20a=20string");=0A+=20=20=20=20=20=20return=20= false;=0A+=20=20=20=20}=0A=20=0A-=20=20Lisp_Object=20node=20=3D=20= treesit_predicate_capture_name_to_node=20(capture_name,=0A-=09=09=09=09=09= =09=09=20=20=20=20=20captures);=0A+=20=20TSNode=20treesit_node;=0A+=20=20= if=20(!treesit_capture_id_to_node=20(&treesit_node,=20capture_id,=20= context,=0A+=09=09=09=09=20=20=20signal_data))=0A+=20=20=20=20return=20= false;=0A=20=0A-=20=20struct=20buffer=20*old_buffer=20=3D=20= current_buffer;=0A-=20=20struct=20buffer=20*buffer=20=3D=20XBUFFER=20= (XTS_PARSER=20(XTS_NODE=20(node)->parser)->buffer);=0A-=20=20= set_buffer_internal=20(buffer);=0A-=0A-=20=20TSNode=20treesit_node=20=3D=20= XTS_NODE=20(node)->node;=0A-=20=20ptrdiff_t=20visible_beg=20=3D=20= XTS_PARSER=20(XTS_NODE=20(node)->parser)->visible_beg;=0A+=20=20= Lisp_Object=20parser=20=3D=20XTS_NODE=20(context->root_node)->parser;=0A= +=20=20ptrdiff_t=20visible_beg=20=3D=20XTS_PARSER=20= (parser)->visible_beg;=0A=20=20=20uint32_t=20start_byte_offset=20=3D=20= ts_node_start_byte=20(treesit_node);=0A=20=20=20uint32_t=20= end_byte_offset=20=3D=20ts_node_end_byte=20(treesit_node);=0A-=20=20= ptrdiff_t=20start_byte=20=3D=20visible_beg=20+=20start_byte_offset;=0A-=20= =20ptrdiff_t=20end_byte=20=3D=20visible_beg=20+=20end_byte_offset;=0A+=20= =20ptrdiff_t=20start_byte=20=3D=20visible_beg=20+=20(ptrdiff_t)=20= start_byte_offset;=0A+=20=20ptrdiff_t=20end_byte=20=3D=20visible_beg=20+=20= (ptrdiff_t)=20end_byte_offset;=0A=20=20=20ptrdiff_t=20start_pos=20=3D=20= BYTE_TO_CHAR=20(start_byte);=0A=20=20=20ptrdiff_t=20end_pos=20=3D=20= BYTE_TO_CHAR=20(end_byte);=0A+=0A=20=20=20ptrdiff_t=20old_begv=20=3D=20= BEGV;=0A=20=20=20ptrdiff_t=20old_begv_byte=20=3D=20BEGV_BYTE;=0A=20=20=20= ptrdiff_t=20old_zv=20=3D=20ZV;=0A@@=20-2537,63=20+2588,78=20@@=20= treesit_predicate_match=20(Lisp_Object=20args,=20struct=20capture_range=20= captures)=0A=20=20=20ZV=20=3D=20old_zv;=0A=20=20=20ZV_BYTE=20=3D=20= old_zv_byte;=0A=20=0A-=20=20set_buffer_internal=20(old_buffer);=0A-=0A=20= =20=20return=20(val=20>=200);=0A=20}=0A=20=0A=20/*=20Handles=20predicate=20= (#pred=20FN=20ARG...).=20=20Return=20true=20if=20FN=20returns=0A=20=20=20= =20non-nil;=20return=20false=20otherwise.=20=20The=20arity=20of=20FN=20= must=20match=20the=0A-=20=20=20number=20of=20ARGs=20=20*/=0A+=20=20=20= number=20of=20ARGs.=20=20If=20something=20went=20wrong,=20set=20= signal_data,=0A+=20=20=20otherwise=20set=20it=20to=20Qnil.=20=20IOW,=20= caller=20should=20check=20the=20nullness=20of=0A+=20=20=20signal_data=20= for=20errors.=20=20*/=0A=20static=20bool=0A-treesit_predicate_pred=20= (Lisp_Object=20args,=20struct=20capture_range=20captures)=0A= +treesit_predicate_pred=20(Lisp_Object=20args,=20struct=20= predicate_context=20*context,=0A+=09=09=09Lisp_Object=20*signal_data)=0A=20= {=0A+=20=20*signal_data=20=3D=20Qnil;=0A=20=20=20if=20(XFIXNUM=20= (Flength=20(args))=20<=202)=0A-=20=20=20=20xsignal2=20= (Qtreesit_query_error,=0A-=09=20=20=20=20=20=20build_string=20= ("Predicate=20`pred'=20requires=20"=0A-=09=09=20=20=20=20=20=20=20=20=20=20= =20=20"at=20least=20two=20arguments,=20"=0A-=09=09=20=20=20=20=20=20=20=20= =20=20=20=20"but=20was=20only=20given"),=0A-=09=20=20=20=20=20=20Flength=20= (args));=0A-=0A+=20=20=20=20{=0A+=20=20=20=20=20=20*signal_data=20=3D=20= list2=20(build_string=20("Predicate=20`pred'=20requires=20"=0A+=09=09=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= "at=20least=20two=20arguments,=20"=0A+=09=09=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"but=20was=20only=20= given"),=0A+=09=09=09=20=20=20=20Flength=20(args));=0A+=20=20=20=20=20=20= return=20false;=0A+=20=20=20=20}=0A=20=20=20Lisp_Object=20fn=20=3D=20= Fintern=20(XCAR=20(args),=20Qnil);=0A=20=20=20Lisp_Object=20nodes=20=3D=20= Qnil;=0A=20=20=20Lisp_Object=20tail=20=3D=20XCDR=20(args);=0A+=20=20= Lisp_Object=20parser=20=3D=20XTS_NODE=20(context->root_node)->parser;=0A=20= =20=20FOR_EACH_TAIL=20(tail)=0A-=20=20=20=20nodes=20=3D=20Fcons=20= (treesit_predicate_capture_name_to_node=20(XCAR=20(tail),=0A-=09=09=09=09= =09=09=09=20=20=20captures),=0A-=09=09=20=20=20nodes);=0A+=20=20{=0A+=20=20= =20=20TSNode=20ts_node;=0A+=20=20=20=20if=20(!treesit_capture_id_to_node=20= (&ts_node,=20XCAR=20(tail),=20context,=0A+=09=09=09=09=20=20=20=20=20= signal_data))=0A+=20=20=20=20=20=20return=20false;=0A+=20=20=20=20= Lisp_Object=20lisp_node=20=3D=20make_treesit_node=20(parser,=20ts_node);=0A= +=20=20=20=20nodes=20=3D=20Fcons=20(lisp_node,=20nodes);=0A+=20=20}=0A=20= =20=20nodes=20=3D=20Fnreverse=20(nodes);=0A=20=0A=20=20=20return=20!NILP=20= (CALLN=20(Fapply,=20fn,=20nodes));=0A=20}=0A=20=0A=20/*=20If=20all=20= predicates=20in=20PREDICATES=20passes,=20return=20true;=20otherwise=0A-=20= =20=20return=20false.=20=20*/=0A+=20=20=20return=20false.=20=20If=20= something=20went=20wrong,=20set=20signal_data,=20otherwise=0A+=20=20=20= set=20it=20to=20Qnil.=20=20IOW,=20caller=20should=20check=20the=20= nullness=20of=0A+=20=20=20signal_data=20for=20errors.=20=20*/=0A=20= static=20bool=0A-treesit_eval_predicates=20(struct=20capture_range=20= captures,=20Lisp_Object=20predicates)=0A+treesit_eval_predicates=20= (Lisp_Object=20predicates,=0A+=09=09=09=20struct=20predicate_context=20= *context,=0A+=09=09=09=20Lisp_Object=20*signal_data)=0A=20{=0A=20=20=20= bool=20pass=20=3D=20true;=0A+=20=20*signal_data=20=3D=20Qnil;=0A=20=20=20= /*=20Evaluate=20each=20predicates.=20=20*/=0A=20=20=20for=20(Lisp_Object=20= tail=20=3D=20predicates;=0A-=20=20=20=20=20=20=20!NILP=20(tail);=20tail=20= =3D=20XCDR=20(tail))=0A+=20=20=20=20=20=20=20!NILP=20(tail)=20&&=20pass;=20= tail=20=3D=20XCDR=20(tail))=0A=20=20=20=20=20{=0A=20=20=20=20=20=20=20= Lisp_Object=20predicate=20=3D=20XCAR=20(tail);=0A=20=20=20=20=20=20=20= Lisp_Object=20fn=20=3D=20XCAR=20(predicate);=0A=20=20=20=20=20=20=20= Lisp_Object=20args=20=3D=20XCDR=20(predicate);=0A=20=20=20=20=20=20=20if=20= (!NILP=20(Fstring_equal=20(fn,=20Vtreesit_str_equal)))=0A-=09pass=20&=3D=20= treesit_predicate_equal=20(args,=20captures);=0A+=09pass=20&=3D=20= treesit_predicate_equal=20(args,=20context,=20signal_data);=0A=20=20=20=20= =20=20=20else=20if=20(!NILP=20(Fstring_equal=20(fn,=20= Vtreesit_str_match)))=0A-=09pass=20&=3D=20treesit_predicate_match=20= (args,=20captures);=0A+=09pass=20&=3D=20treesit_predicate_match=20(args,=20= context,=20signal_data);=0A=20=20=20=20=20=20=20else=20if=20(!NILP=20= (Fstring_equal=20(fn,=20Vtreesit_str_pred)))=0A-=09pass=20&=3D=20= treesit_predicate_pred=20(args,=20captures);=0A+=09pass=20&=3D=20= treesit_predicate_pred=20(args,=20context,=20signal_data);=0A=20=20=20=20= =20=20=20else=0A-=09xsignal3=20(Qtreesit_query_error,=0A-=09=09=20=20= build_string=20("Invalid=20predicate"),=0A-=09=09=20=20fn,=20= build_string=20("Currently=20Emacs=20only=20supports"=0A-=09=09=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"=20equal,=20match,=20= and=20pred"=0A-=09=09=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20"=20predicate"));=0A+=09{=0A+=09=20=20*signal_data=20=3D=20list3=20= (build_string=20("Invalid=20predicate"),=0A+=09=09=09=09fn,=20= build_string=20("Currently=20Emacs=20only=20supports"=0A+=09=09=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20"=20equal,=20match,=20and=20pred"=0A+=09=09=09=09=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"=20predicate"));=0A+=09=20=20= break;=0A+=09}=0A=20=20=20=20=20}=0A-=20=20/*=20If=20all=20predicates=20= passed,=20add=20captures=20to=20result=20list.=20=20*/=0A=20=20=20return=20= pass;=0A=20}=0A=20=0A@@=20-2831,10=20+2897,34=20@@=20DEFUN=20= ("treesit-query-capture",=0A=20=20=20Lisp_Object=20result=20=3D=20Qnil;=0A= =20=20=20Lisp_Object=20prev_result=20=3D=20result;=0A=20=20=20= Lisp_Object=20predicates_table=20=3D=20make_vector=20(patterns_count,=20= Qt);=0A+=0A+=20=20struct=20buffer=20*old_buf=20=3D=20current_buffer;=0A+=20= =20set_buffer_internal=20(buf);=0A+=0A+=20=20signal_data=20=3D=20Qnil;=0A= =20=20=20while=20(ts_query_cursor_next_match=20(cursor,=20&match))=0A=20=20= =20=20=20{=0A=20=20=20=20=20=20=20/*=20Record=20the=20checkpoint=20that=20= we=20may=20roll=20back=20to.=20=20*/=0A=20=20=20=20=20=20=20prev_result=20= =3D=20result;=0A+=0A+=20=20=20=20=20=20/*=20Get=20predicates.=20=20*/=0A= +=20=20=20=20=20=20Lisp_Object=20predicates=20=3D=20AREF=20= (predicates_table,=20match.pattern_index);=0A+=20=20=20=20=20=20if=20(EQ=20= (predicates,=20Qt))=0A+=09{=0A+=09=20=20predicates=20=3D=20= treesit_predicates_for_pattern=20(treesit_query,=0A+=09=09=09=09=09=09=20= =20=20=20=20=20=20match.pattern_index);=0A+=09=20=20ASET=20= (predicates_table,=20match.pattern_index,=20predicates);=0A+=09}=0A+=0A+=20= =20=20=20=20=20/*=20Evaluate=20predicates.=20=20*/=0A+=20=20=20=20=20=20= struct=20predicate_context=20context=0A+=09=3D=20{=20treesit_query,=20= &match,=20lisp_node,=20result,=20prev_result=20};=0A+=20=20=20=20=20=20= bool=20pass=20=3D=20treesit_eval_predicates=20(predicates,=20&context,=20= &signal_data);=0A+=20=20=20=20=20=20if=20(!NILP=20(signal_data))=0A+=09= break;=0A+=20=20=20=20=20=20else=20if=20(!pass)=0A+=09continue;=0A+=0A=20= =20=20=20=20=20=20/*=20Get=20captured=20nodes.=20=20*/=0A=20=20=20=20=20=20= =20const=20TSQueryCapture=20*captures=20=3D=20match.captures;=0A=20=20=20= =20=20=20=20for=20(int=20idx=20=3D=200;=20idx=20<=20match.capture_count;=20= idx++)=0A@@=20-2858,26=20+2948,15=20@@=20DEFUN=20= ("treesit-query-capture",=0A=20=0A=20=09=20=20result=20=3D=20Fcons=20= (cap,=20result);=0A=20=09}=0A-=20=20=20=20=20=20/*=20Get=20predicates.=20= =20*/=0A-=20=20=20=20=20=20Lisp_Object=20predicates=20=3D=20AREF=20= (predicates_table,=20match.pattern_index);=0A-=20=20=20=20=20=20if=20(EQ=20= (predicates,=20Qt))=0A-=09{=0A-=09=20=20predicates=20=3D=20= treesit_predicates_for_pattern=20(treesit_query,=0A-=09=09=09=09=09=09=20= =20=20=20=20=20=20match.pattern_index);=0A-=09=20=20ASET=20= (predicates_table,=20match.pattern_index,=20predicates);=0A-=09}=0A-=0A-=20= =20=20=20=20=20/*=20captures_lisp=20=3D=20Fnreverse=20(captures_lisp);=20= */=0A-=20=20=20=20=20=20struct=20capture_range=20captures_range=20=3D=20= {=20result,=20prev_result=20};=0A-=20=20=20=20=20=20if=20= (!treesit_eval_predicates=20(captures_range,=20predicates))=0A-=09/*=20= Predicates=20didn't=20pass,=20roll=20back.=20=20*/=0A-=09result=20=3D=20= prev_result;=0A=20=20=20=20=20}=0A+=20=20set_buffer_internal=20= (old_buf);=0A=20=20=20if=20(needs_to_free_query_and_cursor)=0A=20=20=20=20= =20{=0A=20=20=20=20=20=20=20ts_query_delete=20(treesit_query);=0A=20=20=20= =20=20=20=20ts_query_cursor_delete=20(cursor);=0A=20=20=20=20=20}=0A+=20=20= if=20(!NILP=20(signal_data))=0A+=20=20=20=20xsignal=20= (Qtreesit_query_error,=20signal_data);=0A=20=20=20return=20Fnreverse=20= (result);=0A=20}=0A=20=0A--=20=0A2.33.1=0A=0A= --Apple-Mail=_F0AA0D58-CC72-4D8F-8886-266955D615F2--