Closed andrewathalye closed 3 months ago
Hi @andrewathalye , thank you for the suggestion and sorry for the late reply.
Actually, this is a feature we are currently working on, it's still experimental, and not well documented yet but you may find it useful to read the specification of the Libadalang.Rewriting package and its content, which you should find in your libadalang package directory under src/libadalang-rewriting.ads
.
Also, I joined an example below, which contains a small example of how to start using the API (it has been tested with the 24.2 version of Libadalang but it should be compatible with the 24.0.0 version available in the Alire registry).
with Ada.Characters.Latin_1; use Ada.Characters.Latin_1;
with Ada.Text_IO; use Ada.Text_IO;
with Libadalang.Analysis;
with Libadalang.Common;
with Libadalang.Generic_API.Introspection;
with Libadalang.Rewriting;
with Langkit_Support.Text; use Langkit_Support.Text;
procedure Lal_Rewriting_Example is
package LAL renames Libadalang.Analysis;
package LALC renames Libadalang.Common;
package LALI renames Libadalang.Generic_API.Introspection;
package LALR renames Libadalang.Rewriting;
-- Analysis objects
Analysis_Ctx : constant LAL.Analysis_Context := LAL.Create_Context;
Analysis_Unit : constant LAL.Analysis_Unit := Analysis_Ctx.Get_From_Buffer
(Filename => "main.adb",
Buffer => "with Ada.Text_IO; use Ada.Text_IO;" & LF &
"procedure Main is" & LF &
"begin" & LF &
" Put_Line(""Hello!"");" & LF &
"end Main;");
-- Rewriting objects
Ctx_Handle : LALR.Rewriting_Handle;
Unit_Handle : LALR.Unit_Rewriting_Handle;
Apply_Res : LALR.Apply_Result;
begin
-- Display the initial parsing tree
Put_Line ("Initial parsing tree:");
Put_Line ("=====");
Analysis_Unit.Root.Print;
Put_Line ("=====");
Put_Line ("");
-- Start by calling the `Start_Rewriting` function to get a rewriting
-- handle on the context
Ctx_Handle := LALR.Start_Rewriting (Analysis_Ctx);
Unit_Handle := LALR.Handle (Analysis_Unit);
-- Show the rewriting unit initial unparsing result, you can use the
-- `Libadalang.Rewriting.Unparse` function
Put_Line ("Rewriting unit handle unparsing before modifications:");
Put_Line ("=====");
Put_Line (To_UTF8 (To_Text (LALR.Unparse (Unit_Handle))));
Put_Line ("=====");
Put_Line ("");
-- Change the displayed text using the Libadalang rewriting API
LALR.Set_Child
(Handle => LALR.Handle
(Analysis_Unit.Root.As_Compilation_Unit
.F_Body.As_Library_Item
.F_Item.As_Subp_Body
.F_Stmts.As_Handled_Stmts
.F_Stmts.Child (1).As_Call_Stmt
.F_Call.As_Call_Expr
.F_Suffix.Child (1)),
Field => LALI.Member_Refs.Param_Assoc_F_R_Expr,
Child => LALR.Create_Token_Node
(Ctx_Handle,
LALC.Ada_String_Literal,
To_Text ("""Replaced!""")));
-- Display the modified rewriting unit unparsing result
Put_Line ("Rewriting unit handle unparsing after modifications:");
Put_Line ("=====");
Put_Line (To_UTF8 (To_Text (LALR.Unparse (Unit_Handle))));
Put_Line ("=====");
Put_Line ("");
-- Apply modifications to the original rewriting context
Apply_Res := LALR.Apply (Ctx_Handle);
-- Ensure the success of rewriting application
if Apply_Res.Success then
Put_Line ("Modified parsing tree:");
Put_Line ("=====");
Analysis_Unit.Root.Print;
Put_Line ("=====");
else
Put_Line ("Error(s) during the rewriting application phase");
end if;
end Lal_Rewriting_Example;
Do not hesitate to give us some feedback if you give it a try (please keep in mind that this API is experimental and might change in the future)!
Libadalang is already quite comprehensive and provides a function for returning the text form of a Unit. Would it be possible to add support for adding nodes to a unit? This would be ideal for, e.g., dynamically generating Ada bindings for foreign-language library headers.