nightshade

The nightshade programming language, compiler and tools (WIP)
Log | Files | Refs | README

gen.adb (2580B)



with Ada.Text_IO;           use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Strings.Fixed;     use Ada.Strings.Fixed;

package body Gen is

   function Init (AST : Declaration_Vectors.Vector) return Generator is
   begin
      return
        Generator'
          (AST => AST, Globals => To_Unbounded_String (""), Output => To_Unbounded_String (""), Indent => 0);
   end;

   -----------------
   -- gen unident --
   -----------------

   procedure Gen_Unindent (GG : in out Generator) is
   begin
      GG.Indent := GG.Indent - 4;
   end;

   ---------------
   -- gen ident --
   ---------------

   procedure Gen_Indent (GG : in out Generator) is
   begin
      GG.Indent := GG.Indent + 4;
   end;

   ----------------
   -- put indent --
   ----------------

   procedure Put_Indent (GG : in out Generator) is
   begin
      GG.Output := GG.Output & To_Unbounded_String (GG.Indent * ' ');
   end;

   --------------
   -- gen call --
   --------------

   procedure Gen_Call (GG : in out Generator; Call : in Call_Expr) is

   begin
      declare
         Param   : constant Expr_Ref := Call.Params.Element (Call.Params.First_Index);
         Content : Unbounded_String := Param.Lit_Str;
      begin
         --  if Call.Params.Length /= 1 then
         --     raise Program_error with "cannot handle calls of more or less than 1 param yet";
         --  end if;
         GG.Globals := GG.GLobals & "data $str = { b " & (Content) & ", b 0 }" & ASCII.LF;
         Put_Indent (GG);
         GG.Output := GG.Output & "%r =w call $puts(l $str)" & ASCII.LF;
      end;
   end;

   ------------------
   -- gen function --
   ------------------

   procedure Gen_Function (GG : in out Generator; Func : in Func_Decl) is
   begin
      GG.Output := GG.Output & "export function w $" & Func.Name & "() {" & ASCII.LF;
      GG.Output := GG.Output & "@start" & ASCII.LF;

      Gen_Indent (GG);

      for Stmt of Func.Stmts loop
         if Stmt.Kind = Stmt_Call_Kind then
            Gen_Call (GG, Stmt.Call);
         end if;
      end loop;

      Put_Indent (GG);
      GG.Output := GG.Output & "ret 0" & ASCII.LF;

      Gen_Unindent (GG);
      GG.Output := GG.Output & "}" & ASCII.LF;
   end;

   ------------
   -- gen IR --
   ------------

   procedure Gen_IR (GG : in out Generator) is
   begin
      for Decl of GG.AST loop
         if Decl.Kind = Function_Kind then
            Gen_Function (GG, Decl.Func);
         end if;
      end loop;
      Put_Line (To_String (GG.Globals));
      Put_Line (To_String (GG.Output));
   end;
end Gen;