IMPLEMENTATION MODULE YaflClDefinition;

IMPORT LookAhead;
IMPORT String;
FROM YaflParser IMPORT NonTerminal;
FROM YaflCfg IMPORT CurrentSpot;
FROM YaflIdentifiers IMPORT Ident;
FROM YaflDeclarations IMPORT Declaration;
FROM YaflLex IMPORT LexicalAnalyzer;
FROM YaflSymbols IMPORT SymbolTable;
FROM YaflMethods IMPORT MethodDeclaration;
FROM YaflMetImplementation IMPORT MethodImplementation;
FROM YaflMetDefinition IMPORT MethodDefinition;
FROM YaflModules IMPORT ImplementationModule;
FROM YaflType IMPORT Type;
FROM YaflGClass IMPORT ClassDefCodeGenerator;

  CLASS ClassDefinition(gc IN ClassDefCodeGenerator);
    INHERITS ClassDeclaration(MethodDefinition, 
                              DefinitionModule,
                              gc);

    VAR
      TheLineCount: INTEGER;

    REDEFINE METHOD Parse(Lkh: LookAhead);
      VAR
        EndId: Ident;
        FirstLine: INTEGER;
      BEGIN
      FirstLine := Lkh.LineNr;
      ParseClassDeclaration(Lkh);
      IF Lkh.Ok THEN
        ParseDeclarationList(Lkh, FALSE);
--        SubDecls.AppendFromList (Lkh.AcceptDeclarationList (FALSE,
--                                 LookAhead.ClassContext));
        END;
      Lkh.Accept (LexicalAnalyzer.End);
      EndId := Lkh.AcceptIdent;
      --------------------------------------
      -- Make sure it matches the header    
      --------------------------------------
      IF (EndId <> VOID) AND (EndId.Data <> Id.Data) THEN
        Error ("Non matching closing identifier");
        END;
      TheLineCount := Lkh.LineNr - FirstLine + 1;
      Lkh.Accept (LexicalAnalyzer.SemiColon);
      END Parse;

    REDEFINE METHOD Tag;
      BEGIN
      SymbolTable.Check;
      CurrentSpot.PushCurrentClass (THIS);
      IF ClassFormals <> VOID THEN
        ClassFormals.UniqueTag;
        END;
      SymbolTable.PushLevel;
      EnterInheritedSymbols;
      SymbolTable.PushLevel;
      ------------------------------------
      -- Enter classe's formal parameters.
      ------------------------------------
      EnterFormalClasses; 
      SubDecls.Enter;
      SubDecls.UniqueTag;
      SymbolTable.PopLevel;
      SymbolTable.PopLevel;

      IF CyclicInherits THEN
        Error ("Cyclic inheritance relationship");
        END;
      CurrentSpot.PopCurrentClass;
      END Tag;
      
    REDEFINE METHOD WhatAmI: ARRAY OF CHAR;
      BEGIN
      RESULT := "ClassDefinition";
      END WhatAmI;

    METHOD EnterDeferred;
      BEGIN
      FOR i := 0 TO Methods.Size - 1 DO
        IF Methods.Get(i).Deferred THEN
          Methods.Get(i).Enter;
          END;
        END;
      END EnterDeferred;

    REDEFINE METHOD LineCount: INTEGER;
      BEGIN
      RESULT := TheLineCount;
      END LineCount;
      
    METHOD Implementation: ClassImplementation;
      BEGIN
      WHAT CurrentSpot.CurrentModule OF
        IN ImplementationModule:
          IF TAG.DefModule = Module THEN
            RESULT := TAG.GetClassImplementation (Id.Data);
           ELSE
            ASSERT TAG.DefModule.Id.Data <> Module.Id.Data;
            ASSERT NOT String.Equals(TAG.DefModule.Id.Data,
                                     Module.Id.Data);
            END;
          END;
       ELSE
        END;
      END Implementation;
      
    REDEFINE METHOD GetDecl (IdSearched: ARRAY OF CHAR): Declaration;
      VAR
        Imp: ClassImplementation;
      BEGIN
      RESULT := GetLocalDecl (IdSearched);
      IF RESULT = VOID THEN
        Imp := Implementation;
        IF Imp <> VOID THEN
          RESULT := Imp.GetLocalDecl (IdSearched);
          END;
        END;
      END GetDecl;
      
    REDEFINE METHOD ConstrainedReturn (Meth: MethodDeclaration): Type;
      BEGIN
      IF Implementation <> VOID THEN
        RESULT := Implementation.ConstrainedReturn (Meth);
       ELSE
        RESULT := BASE (Meth);
        END;
      ASSERT RESULT <> VOID;
      END ConstrainedReturn;

    REDEFINE METHOD EnterInDictionary;
      BEGIN
      BASE;
                    
      ASSERT Reference <> VOID;
      Reference.SetDeclPos (Id.ColNr, Id.LineNr);
      END EnterInDictionary;
        
  END ClassDefinition;
-----------------------------------------------------------

  CLASS InstClassDefinition;
    INHERITS ClassDefinition(InstClassDefCodeGenerator);
    
  END InstClassDefinition;
  

END YaflClDefinition;
