nightshade

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

sem.adb (4268B)



with Parser;      use Parser;
with Ada.Containers.Indefinite_Vectors;
with Ada.Text_IO; use Ada.Text_IO;

package body Sem is

   procedure Load_STD_Symbols (S : in out Sem);

   ----------
   -- init --
   ----------

   function Init (AST : Declaration_Vectors.Vector) return Sem is
      Symbols : Symbols_Map.Map;
      Sc      : Scope_Ref;
      S       : Sem;
   begin
      Sc := new Scope'(Parent => null, Symbols => Symbols);
      S := (Scope => Sc, AST => AST);
      Load_STD_Symbols (S);
      return S;
   end Init;

   -----------------------
   -- load std in scope --
   -----------------------

   procedure Load_STD_Symbols (S : in out Sem) is
      Info        : Symbol_Info;
      Int_Type    : constant Type_Info_Ref := new Type_Info'(Kind => TY_INT);
      String_Type : constant Type_Info_Ref := new Type_Info'(Kind => TY_STRING);
      Bool_Type   : constant Type_Info_Ref := new Type_Info'(Kind => TY_BOOL);
      Void_Type   : constant Type_Info_Ref := new Type_Info'(Kind => TY_VOID);
      Error_Type  : constant Type_Info_Ref := new Type_Info'(Kind => TY_ERROR);
      Print_Type  : constant Type_Info_Ref :=
        new Type_Info'
          (Kind => TY_FUNC,
           Func =>
             (Return_Type => Void_Type, Params => new Type_List'(1 => String_Type)));
   begin
      Put_Line ("load std symbols");
      Info := (Kind => SYM_FUNC, Typ => Print_Type);
      S.Scope.Symbols.Include ("print", Info);
   end;

   --------------------------
   -- new scope from scope --
   --------------------------

   procedure New_Scope_From_Scope (S : in out Sem) is
      Symbols : Symbols_Map.Map;
      Sc      : Scope_Ref;
   begin
      Sc := new Scope'(Parent => S.Scope, Symbols => Symbols);
      S.Scope := Sc;
   end;

   -----------------------------
   -- scope contains or error --
   -----------------------------

   procedure Scope_Contains_Or_Error
     (Sc : Scope_Ref; Name : Unbounded_String; Kind : Symbol_Kind_Enum)
   is
      Info : Symbol_Info;
   begin
      if Sc.Symbols.Contains (To_String (Name)) then
         Info := Sc.Symbols.Element (To_String (Name));
         if Info.Kind = Kind then
            Put_Line
              ("Found "
               & To_String (Name)
               & " of kind "
               & Symbol_Kind_Enum'Image (Kind)
               & " in scope.");
            return;
         else
            raise Program_Error
              with
                "Symbol found in scope was not of expected type "
                & Symbol_Kind_Enum'Image (Kind)
                & " but is in fact "
                & Symbol_Kind_Enum'Image (Info.Kind);
         end if;
      elsif Sc.Parent /= null then
         Scope_Contains_Or_Error (Sc.Parent, Name, Kind);
      else
         raise Program_Error
           with "Could not find symbol " & To_String (Name) & " in scope.";
      end if;
   end;

   ---------------------
   -- scope func call --
   ---------------------

   procedure Scope_Call (S : in out Sem; Callee : in Call_Stmt) is
   begin
      -- determine whether the callee exist in scope or bail with error
      Put_Line ("scoping call wip");
      Scope_Contains_Or_Error (S.Scope, Callee.Name, SYM_FUNC);
      null;
   end;

   --------------------
   -- scope var decl --
   --------------------

   procedure Scope_Var_Decl (S : in out Sem) is
   begin

      -- TODO we do not yet add to scope, but we do not currently have
      --      variables so this is a waste of time for now

      null;
   end;

   ----------------
   -- scope func --
   ----------------

   procedure Scope_Func (S : in out Sem; Fn : in Func_Decl) is
   begin
      -- go through statements and +scope var_decl and -scope calls
      for Statement of Fn.Stmts loop
         if Statement.Kind = Stmt_Call then
            Put_Line ("scoping call");
            Scope_Call (S, Statement.Call);
         end if;
      end loop;
   end;

   --------------
   -- analysis --
   --------------

   procedure Analysis (S : in out Sem) is
   begin
      for Declaration of S.AST loop
         if Declaration.Kind = Function_Kind then
            Put_Line ("scoping function");
            Scope_Func (S, Declaration.Func);
         end if;
         null;
      end loop;
   end Analysis;

end Sem;