IMPLEMENTATION MODULE CGCode;

FROM YaflGC    IMPORT YaflGC;
FROM YaflPredefined IMPORT VoidType;
FROM Streams   IMPORT StdOut, StdErr;
FROM YaflAsGC  IMPORT AssertionGC;

------------------------------
-- C Code Generators.
------------------------------
FROM CGType          IMPORT CIntLiteralCodeGenerator,
                            CRealLiteralCodeGenerator,
                            CBooleanLiteralCodeGenerator,
                            CVoidLitCodeGenerator,
                            CExpressionCodeGenerator;
FROM CGDesig         IMPORT CDesigCodeGenerator,
                            CDesigElementCodeGenerator;
FROM CGModules       IMPORT CImplModuleCodeGenerator;
FROM CGPreconditions IMPORT CPostCondCodeGenerator,
                            CPreCondCodeGenerator;
FROM CGDeclarations  IMPORT CSingleDataItemCodeGenerator;

FROM CGClass         IMPORT CClassDecl, CClassDecl;
FROM CGMethods       IMPORT CMethDecl;
FROM CGQuantifier    IMPORT CQuantifierCodeGenerator;
------------------------------
-- Generic Code Generators.
------------------------------
FROM YaflGType             IMPORT TypeCodeGenerator; 
FROM YaflGClass            IMPORT ClassDeclCodeGenerator;


------------------------------
-- Non Terminals.
------------------------------
FROM YaflParser            IMPORT NonTerminal, LimitedWalker;
FROM YaflPredefined        IMPORT PredefClass,
                                  PredefNoChangeMethod;
FROM YaflModules           IMPORT CompilationUnit,
                                  DefinitionModule,
                                  ImplementationModule;
FROM YaflClImplementation  IMPORT ClassImplementation;
FROM YaflDesignator        IMPORT Desig;
FROM YaflMethods           IMPORT Formal,
                                  FormalList;
FROM YaflClasses           IMPORT ClassDeclaration;

FROM YaflQuantifiers       IMPORT Quantifier;
------------------------------
FROM YaflType              IMPORT Type;
FROM YaflMetImplementation IMPORT MethodImplementation;
FROM YaflMetDefinition     IMPORT MethodDefinition;
FROM YaflParamClasses      IMPORT ClassFormal, 
                                  ClassActual;
FROM YaflPredefined        IMPORT ThisDataItem;
FROM List                  IMPORT List;
FROM YaflIdentifiers       IMPORT Ident;
FROM YaflCfg               IMPORT CurrentSpot,
                                  YaflCfg;
FROM YaflNTList            IMPORT DeclList, 
                                  NTList, 
                                  MethodList;
FROM YaflPredefined        IMPORT PredefItems;
FROM Conversions           IMPORT IntConversions;
FROM YaflDictionary        IMPORT MethodReference;
IMPORT SYSTEM;

------------------------------
  CLASS CGcContext;
    INHERITS GcContext(ImplementationModule);

    VAR
      TheOut: YaflGC;

    REDEFINE METHOD CREATE;
      BEGIN
      BASE;
      END CREATE;                          

    METHOD Output: YaflGC;
      BEGIN
      RESULT := TheOut;
      END Output;
    
    METHOD SetOutput(Out: YaflGC);
      BEGIN
      TheOut := Out;
      END SetOutput;

   ---------------------------------------- 
   -- TypedNTCodeGenerator 
   ----------------------------------------

    METHOD TypedNTGenerateTempVariableDecl(Gc: TypedNTCodeGenerator);  
      BEGIN
      TypeGenerateCode (Gc.Obj.GetType.Gc);
      Output.UniqueItem (Gc.Number);
      Output.SemiColon;
      Output.WriteLn;
      END TypedNTGenerateTempVariableDecl;

    METHOD TypedNTGenerateCodeWithTarget (Gc: TypedNTCodeGenerator;
					  TargetNr: INTEGER);
      BEGIN
      IF Gc.Obj.Functional THEN
        Output.UniqueItem (TargetNr);
	Output.Becomes;
	Gc.GenerateCode;
	Output.SemiColon;
	Output.WriteLn;
       ELSE
	Gc.GenerateCodeWithTarget (TargetNr);
	END;
      END TypedNTGenerateCodeWithTarget;

    METHOD TypedNTGenerateWithTempSaving(Gc: TypedNTCodeGenerator);
      VAR
        PleaseSave: BOOLEAN;
      BEGIN
      PleaseSave := Gc.Obj.RequiresTempSaving;
      IF PleaseSave THEN
        Output.FlyVReg;
        Output.LeftParent;
        END;
      Gc.GenerateCode;
      IF PleaseSave THEN
        Output.RightParent;
        END;
      END TypedNTGenerateWithTempSaving;

    METHOD TypedNTGenerateCode(Gc: TypedNTCodeGenerator);  
      BEGIN
      Gc.GenerateEvaluationCode;
      END TypedNTGenerateCode;

   ----------------------------------------  
   -- DesigCodeGenerator
   ---------------------------------------- 
    METHOD DesigGenerateAddressWithTarget (Gc: DesigCodeGenerator;
         				  TargetNr: INTEGER);
      BEGIN
      WHAT Gc OF
	IN CDesigCodeGenerator:
	  TAG.GenerateAddressWithTarget (TargetNr);
	  END;
        END;
      END DesigGenerateAddressWithTarget;

   ---------------------------------------- 
   -- TypeCodeGenerator
   ----------------------------------------

    METHOD TypeGenerateCode(Gc: TypeCodeGenerator);
      BEGIN
      WHAT Gc.Obj OF
        IN VoidType:
          Output.ObjPtr;
	  END;
       ELSE
        ASSERT Gc.Obj.SimpleType <> VOID;
        IF Gc.Obj.ArrayLevel <> 0 THEN
          Output.ObjPtr;
         ELSE  -- Check out if it is a predefined type or not.
          WHAT Gc.Obj.SimpleType OF
            IN PredefClass:
              Output.WriteString (TAG.CName);
              END;
           ELSE -- Otherwise, it is an object
            Output.ObjPtr;
            END;
          END;
        Output.WriteChar (' ');
	END;
      END TypeGenerateCode;

   ---------------------------------------- 
   -- MethDeclCodeGenerator
   ----------------------------------------

    METHOD MethDeclGenerateFunctionReturnType(Gc: MethDeclCodeGenerator);
      BEGIN
      IF Gc.Obj.Return <> VOID THEN
        IF Gc.Obj.ReturnObjPtr THEN
          Output.ObjPtrFunc;
        ELSE
          IF Gc.Obj.Return.SimpleType = PredefItems.Integer THEN
            Output.IntegerFunc;
           ELSIF Gc.Obj.Return.SimpleType = PredefItems.Real THEN
            Output.RealFunc;
           ELSIF Gc.Obj.Return.SimpleType = PredefItems.Boolean THEN
            Output.BooleanFunc;
           ELSIF Gc.Obj.Return.SimpleType = PredefItems.Char THEN
            Output.CharFunc;
            END;
          END;
      ELSE
        Output.VoidFunc;
        END;
      END MethDeclGenerateFunctionReturnType;


    METHOD MethDeclGenerateDualExtraction(Gc: MethDeclCodeGenerator);
      VAR
        Cl: ClassDeclaration;
        Mod: CompilationUnit;
      BEGIN
      Output.LeftParents (2);
      Cl := Gc.Obj.Class;
      Mod := Cl.Module;
      Output.DualType (Mod.Id.Data, Cl.Id.Data);
      Output.Star;
      Output.RightParent;
      Output.LeftParents(4);
      Output.Header;
      Output.Star;
      Output.RightParent;
      Output.LeftParent;
      Output.This;
      Output.RightParents(2);
      Output.Minus;
      Output.WriteChar ('1');
      Output.RightParent;
      Output.Arrow;
      Output.Dual;
      Output.RightParents(2);
      Output.Arrow;
      MethDeclGenerateMethodPointer(Gc);
      --Output.Method (Mod.Id.Data, Cl.Id.Data, Id.Data);
      END MethDeclGenerateDualExtraction;

    METHOD MethDeclGenerateReturnType (Gc: MethDeclCodeGenerator);
      BEGIN
      IF Gc.Obj.Return = VOID THEN
        Output.Void;
--------------------------------------------------------------------------
-- caution: LocalResult can be void in the case of a DEFERRED method for
-- example; but in this case the VarType pragma should not be used so CName
-- has no meaning
--------------------------------------------------------------------------
       ELSIF (Gc.Obj.LocalResult <> VOID) AND
             (Gc.Obj.LocalResult.GetCName <> VOID) THEN
        Output.WriteString(Gc.Obj.LocalResult.GetCName);
        Output.WriteChar(" ");
       ELSE
        Gc.Obj.Return.Gc.GenerateCode;
        END;
      END MethDeclGenerateReturnType;

    -----------------------------------------------------
    -- The GenerateFormals method generates
    -- the list of the formals to THIS between parents.
    -- If WithCommas is set to TRUE, commas are generated
    -- between each item (See the FORMALS0, FORMALS2, etc...
    -- macros in /yafl/lib/yafl_rnt.h)
    -- If WithTypes is set to true, then the types are mentionned
    -- Otherwise, only the formals's names are enumerated.
    --
    -- The WithThis parameters must be set to TRUE to include
    -- THIS in the parameter list.
    -----------------------------------------------------
    METHOD MethDeclGenerateFormals (Gc: MethDeclCodeGenerator;
                                    WithThis,
                                    WithCommas,
                                    WithTypes,
                                    WithSemiColons,
                                    WithParents: BOOLEAN);
      VAR
        NeedComma: BOOLEAN;
        Papa: MethodImplementation;
        TheType : Type;
      BEGIN
      -- Vachon: Beware, assert failed on one of my programs...
      -- I removed it...
      -- ASSERT WithTypes OR NOT WithCommas;
      IF WithParents THEN
        Output.LeftParent;
        END;
      IF WithThis THEN
        IF WithTypes THEN
          Output.ObjPtr;
          END;
        IF WithCommas THEN
          Output.Comma;
          END;
        Output.This;
        NeedComma := TRUE;
        END;
      --------------------------
      -- Also pass pointers to context
      -- structures for enclosing methods.
      --------------------------
      Papa := Gc.Obj.Enclosing;
      WHILE Papa <> VOID DO
        IF NeedComma THEN
          IF WithSemiColons THEN
            Output.SemiColon;
           ELSE
            Output.Comma;
            END;
          END;
        NeedComma := TRUE;
        IF WithTypes THEN
          Output.UniqueItem (Papa.StructNr);
          Output.Star;
          END;
        IF WithCommas THEN
          Output.Comma;
          END;
        Output.UniqueItem (Papa.ContextNr);
        Papa := Papa.Enclosing;
        END;
      FOR i := 0 TO Gc.Obj.Formals.Size - 1 DO
        IF NeedComma THEN
          IF WithSemiColons THEN
            Output.SemiColon;
           ELSE
            Output.Comma;
            END;
          END;
        NeedComma := TRUE;
        IF WithTypes THEN
          TheType := Gc.Obj.Formals.Get(i).GetType;
          ---------------------------------------
          -- Now, handle special case where
          -- a character parameter is specified
          -- Gizmo knows why, but it will only work
          -- if it translated into an integerr
          ---------------------------------------
          IF (TheType.ArrayLevel = 0) AND
             (TheType.SimpleType = PredefItems.Char) THEN
            Output.UnsignedInt;
           ELSE
            WHAT Gc.Obj.Formals.Get(i).Gc OF 
              IN CSingleDataItemCodeGenerator: 
                TAG.GenerateType;
                END;
              END;
            END;
          END;
        IF WithCommas THEN
          Output.Comma;
          END;
        Gc.Obj.Formals.Get(i).Gc.GenerateCode;
        END;
      IF WithParents THEN        
        Output.RightParent;
        END;
      END MethDeclGenerateFormals;

    METHOD MethDeclGenerateNativeFormals (Gc: MethDeclCodeGenerator;
                                          WithThis: BOOLEAN);
      VAR
        TrueArity: INTEGER;                                  
      BEGIN                
      TrueArity := Gc.Obj.Arity + Gc.Obj.Nesting;
      IF WithThis THEN
        TrueArity := TrueArity + 1;
        END;
      IF 2 * (TrueArity) <= YaflCfg.MaxPreprocessorFormals THEN
        Output.YFormals (TrueArity);
        IF TrueArity > 0 THEN
          MethDeclGenerateFormals (Gc,
                           WithThis,
                           WithCommas := TRUE,
                           WithTypes := TRUE,
                           WithSemiColons := FALSE,
                           WithParents := TRUE);      
          END;
       ELSE
        Output.WriteLn;
        Output.IfDef;
        Output.Ansi;
        Output.WriteLn;
        MethDeclGenerateFormals (Gc, 
                         WithThis,
                         WithCommas := FALSE,
                         WithTypes := TRUE,
                         WithSemiColons := FALSE,
                         WithParents := TRUE);     
        Output.WriteLn;                         
        Output.ElseDef;                     
        Output.WriteLn;
        MethDeclGenerateFormals (Gc, 
                         WithThis,
                         WithCommas := FALSE,
                         WithTypes := FALSE,
                         WithSemiColons := FALSE,     
                         WithParents := TRUE);     
        Output.WriteLn;                         
        MethDeclGenerateFormals (Gc, 
                         WithThis,
                         WithCommas := FALSE,
                         WithTypes := TRUE,
                         WithSemiColons := TRUE,     
                         WithParents := FALSE);     
        Output.SemiColon;                         
        Output.EndIf;
        Output.WriteLn;
        END;
      END MethDeclGenerateNativeFormals;

    METHOD MethDeclGenerateAnchorId (Gc: MethDeclCodeGenerator);
      BEGIN                                                        
      IF Gc.Obj.IsCreate THEN
        CClassDecl.GenerateCreateAnchorId(Gc.Obj.Class.Gc);
       ELSE
        Output.Anchor (Gc.Obj.Class.Module.Id.Data, Gc.Obj.Class.Id.Data, Gc.Obj.Id.Data);
        END;
      END MethDeclGenerateAnchorId;
      
      
    METHOD MethDeclGenerateAnchorFormals (Gc: MethDeclCodeGenerator);
      BEGIN
      Output.YArgs;
      Output.LeftParent;
      MethDeclGenerateFormals(Gc,
                      WithThis := TRUE,
                      WithCommas := FALSE,
                      WithTypes := TRUE,
                      WithSemiColons := FALSE,
                      WithParents := TRUE);
      Output.RightParent;
      END MethDeclGenerateAnchorFormals;
              
    METHOD MethDeclGenerateAnchorDefinition (Gc: MethDeclCodeGenerator);
      BEGIN
      IF Gc.Obj.UseStaticAnchor THEN
        Output.Static;
        END;
      MethDeclGenerateReturnType(Gc);
      CMethDecl.GenerateAnchorId(Gc);
      MethDeclGenerateAnchorFormals(Gc);
      Output.SemiColon;
      Output.WriteLn;           
      -- XXJC (d)
      IF Gc.Obj.GetPreCondition <> VOID THEN
        Gc.Obj.GetPreCondition.Gc.GenerateFunctionDeclaration(TRUE);
      ELSE
        WHAT Gc.Obj OF
          IN MethodImplementation:
            IF (TAG.Definition <> VOID) 
                AND (TAG.Definition.GetPreCondition <> VOID) THEN
              TAG.Definition.GetPreCondition.Gc.
                                        GenerateFunctionDeclaration(TRUE);
              END;
            END;
        ELSE
          END;
        END;
      IF Gc.Obj.GetPostCondition <> VOID THEN
        Gc.Obj.GetPostCondition.Gc.GenerateFunctionDeclaration(TRUE);
      ELSE
        WHAT Gc.Obj OF
          IN MethodImplementation:
            IF (TAG.Definition <> VOID) 
               AND (TAG.Definition.GetPostCondition <> VOID) THEN
              TAG.Definition.GetPostCondition.Gc.
                                        GenerateFunctionDeclaration(TRUE);
              END;
            END;
        ELSE
          END;   
        END;
      -- END XXJC (d)
      END MethDeclGenerateAnchorDefinition;

    -----------------------------------------
    -- This method generates the identifier attached to
    -- the structure related to THIS in the dual
    -- data structure.
    -----------------------------------------
    METHOD MethDeclGenerateMethodRef (Gc: MethDeclCodeGenerator);    
      BEGIN
      Output.MethodStructRef(Gc.Obj.Class.Module.Id.Data, Gc.Obj.Class.Id.Data, Gc.Obj.Id.Data);
      END MethDeclGenerateMethodRef;
      
    METHOD MethDeclGenerateMethodPointer (Gc: MethDeclCodeGenerator);
      BEGIN        
      MethDeclGenerateMethodRef(Gc);
      Output.Dot;  
      Output.Current;
      Output.Dot;
      MethDeclGenerateFunctionReturnType(Gc);
      END MethDeclGenerateMethodPointer;
    
    METHOD MethDeclGenerateCheckVoidObj (Gc: MethDeclCodeGenerator);
      BEGIN
      Output.If;
      Output.LeftParent;
      Output.Not;
      Output.This;
      Output.RightParent;
      Output.FailVoidMethod;
      Output.LeftParent;
      WHAT Gc.Obj.Class.Module OF
        IN CompilationUnit:
          CompilationUnitGenerateLiteral(TAG.Gc);
          END;
        END;
      --Obj.Class.Module.Gc.GenerateLiteral;
      Output.Comma;
      CClassDecl.GenerateLiteral(Gc.Obj.Class.Gc);
      Output.Comma;
      Output.QuotedString (Gc.Obj.Id.Data, UseEsc := FALSE);
      Output.RightParent;
      Output.SemiColon;
      Output.WriteLn;
      END MethDeclGenerateCheckVoidObj;

    METHOD MethDeclGenerateCallBack (Gc: MethDeclCodeGenerator;
                                     Name: ARRAY OF CHAR;
                                     WithBody: BOOLEAN);
      BEGIN                
      MethDeclGenerateReturnType(Gc);
      Output.WriteString(Name);
      Output.WriteChar(' ');
      MethDeclGenerateNativeFormals(Gc,
                            WithThis := FALSE);
      IF WithBody THEN
        Output.WriteLn;
        Output.LeftBrace;
        Output.WriteLn;
        Output.ObjPtr;
        Output.This;
        Output.Becomes;
        Output.OnceClassInstance (Gc.Obj.Class.Module.Id.Data, Gc.Obj.Class.Id.Data);
        Output.SemiColon;
        Output.WriteLn;
        IF Gc.Obj.Return <> VOID THEN
          Output.Return;
          END;
        CMethDecl.GenerateAnchorId(Gc);
        MethDeclGenerateFormals (Gc,
                         WithThis := TRUE,
                         WithCommas := FALSE,
                         WithTypes := FALSE,
                         WithSemiColons := FALSE,
                         WithParents := TRUE);
        Output.SemiColon;
        Output.WriteLn;
        Output.RightBrace;                 
        Output.WriteLn;
       ELSE
        Output.SemiColon;
        Output.WriteLn;
        END;
      END MethDeclGenerateCallBack;

-- XXJC 3

    METHOD MethDeclGenerateDbxExtRefVariable(Gc: MethDeclCodeGenerator);
      BEGIN
      Output.Extern;
      MethDeclGenerateDbxReferenceVariable(Gc);
      END MethDeclGenerateDbxExtRefVariable;

    METHOD MethDeclGenerateDbxReferenceVariable(Gc: MethDeclCodeGenerator);
      BEGIN
      Output.DbxMethod;
      Output.Star;
      Output.Space;
      Output.DbxMethodReference(Gc.Obj.Class.Module.Id.Data, 
                                Gc.Obj.Class.Id.Data, 
                                Gc.Obj.Id.Data);
      Output.SemiColon;
      Output.WriteLn;
      END MethDeclGenerateDbxReferenceVariable;

    METHOD MethDeclGenerateDualOffsetValue(Gc: MethDeclCodeGenerator);
      VAR
        ModName,ClaName,MethName : ARRAY OF CHAR;
      BEGIN
      MethName := Gc.Obj.Id.Data;
      ClaName := Gc.Obj.Class.Id.Data;
      ModName := Gc.Obj.Class.Module.Id.Data;
      Output.Offset;
      Output.LeftParent;
      Output.DualInstance(ModName, ClaName);
      Output.Comma;
      Output.MethodStructRef(ModName, ClaName, MethName);
      Output.RightParent;
      END MethDeclGenerateDualOffsetValue;

-- END XXJC 3

-- XXJC	(d)
    METHOD MethAssertPushLevel; 
      BEGIN
      Output.AssertionStackPushLevel;
      Output.LeftParent;
      Output.Ampersand;
      Output.AssertionStackName;
      Output.RightParent;
      Output.SemiColon;
      Output.WriteLn;
      END MethAssertPushLevel;

    METHOD MethAssertPopLevel; 
      BEGIN
      Output.AssertionStackPopLevel;
      Output.LeftParent;
      Output.Ampersand;
      Output.AssertionStackName;
      Output.RightParent;
      Output.SemiColon;
      Output.WriteLn;
      END MethAssertPopLevel;

    METHOD MethAssertPushOldLevel; 
      BEGIN
      Output.AssertionStackPushLevel;
      Output.LeftParent;
      Output.Ampersand;
      Output.OldStackName;
      Output.RightParent;
      Output.SemiColon;
      Output.WriteLn;
      END MethAssertPushOldLevel;

    METHOD MethAssertPopOldLevel; 
      BEGIN
      Output.AssertionStackPopLevel;
      Output.LeftParent;
      Output.Ampersand;
      Output.OldStackName;
      Output.RightParent;
      Output.SemiColon;
      Output.WriteLn;
      END MethAssertPopOldLevel;

    METHOD MethAssertPushFormals (Gc: MethDeclCodeGenerator; 
                                  NeedResult: BOOLEAN;
                                  InAnchor: BOOLEAN);
       VAR
         TheFormals: FormalList;
         Tmp:        Formal;
       BEGIN
       ASSERT Gc <> VOID;
       TheFormals := Gc.Obj.Formals;
       FOR Ind := 0 TO TheFormals.Size-1 DO
         Tmp := TheFormals.Get(Ind);
         AssertionGC.MethAssertPushFormal(Output, Tmp);
         END;
       IF (Gc.Obj.Return <> VOID) AND NeedResult THEN
         WHAT Gc OF 
           IN CMethImplCodeGenerator:
             AssertionGC.MethAssertPushResult(Output, 
                                              TAG, 
                                              TAG.Obj.Return, 
                                              InAnchor);
             END;
         ELSE
           AssertionGC.MethAssertPushResult(Output, 
                                            VOID, 
                                            Gc.Obj.Return, 
                                            InAnchor);
           END;
         END;
       END MethAssertPushFormals; 
-- END XXJC (d)


    METHOD MethDeclGenerateAnchorBody (Gc: MethDeclCodeGenerator);
      BEGIN
      ASSERT Gc.Obj.NeedsSeparateAnchor;
      MethDeclGenerateReturnType(Gc);
      CMethDecl.GenerateAnchorId(Gc);
      MethDeclGenerateNativeFormals (Gc, WithThis := TRUE);
      -------------------------------------
      Output.LeftBrace;
      Output.WriteLn;          
      
      -- XXJC (d)
      IF Gc.Obj.Return <> VOID THEN
        -- if we evaluate the postconditions, we need a temporary
        -- to store the return value.
        --Output.IfDefined(Output.FullTraceModeLabel);
        Output.IfDefined(Output.CheckPostCondLabel);
        MethDeclGenerateReturnType(Gc);
        Output.Result;
        Output.SemiColon;
        Output.WriteLn;
        Output.EndIf;
        --Output.EndIf;
        END;
      -- END XXJC (d)
      
      Output.IfDefined (YaflGC.CheckVoidObjectLabel);
      MethDeclGenerateCheckVoidObj (Gc);          
      Output.EndIf;
      
      -------------------------------------
      -- If the original method THIS refers to happens to
      -- be a deferred method, check dynamically whether at
      -- least a redefinition has occured.
      -------------------------------------
      Output.IfDefined (YaflGC.CheckVoidMethodLabel);
      IF Gc.Obj.Deferred THEN
        Output.If;
        Output.LeftParent;
        Output.Not;
        MethDeclGenerateDualExtraction(Gc);
        Output.RightParent;
        Output.FailUndefMethod (Gc.Obj.Class.Module.Id.Data, Gc.Obj.Class.Id.Data, Gc.Obj.Id.Data);
        Output.WriteLn;
        END;
      
      --------------------------------------
      -- The following code has been used
      -- to track down a subtle error in
      -- the code generation process. Under
      -- normal circumstances, it should not
      -- be required at all.
      --------------------------------------
      Output.If;
      Output.LeftParent;
      Output.Not;
      Output.IsIn;
      Output.LeftParent;
      Output.This;
      Output.Comma;
      CClassDecl.GenerateMinDualRef(Gc.Obj.Class.Gc);
      Output.RightParents(2);
      Output.FailBadClass (Gc.Obj.Class.Module.Id.Data, Gc.Obj.Class.Id.Data, Gc.Obj.Id.Data);
      Output.WriteLn;
      Output.EndIf;
      
      -- XXJC (d)
      IF (Gc.Obj.Formals <> VOID) AND (Gc.Obj.Formals.Size > 0) THEN
        --Output.IfDefined(Output.FullTraceModeLabel);
        Output.IfDefined(Output.CheckPreCondLabel);
        Output.Comment("Eval PreCond: Push Params");
        MethAssertPushLevel;
        MethAssertPushFormals(Gc, FALSE, TRUE);
        Output.EndIf;
        --Output.EndIf;
      ELSE
        Output.Comment("Eval PreCond: NO Params");
        END;
      --Output.IfDefined(Output.FullTraceModeLabel);
      Output.IfDefined(Output.CheckPostCondLabel);
      -- push_old_level is now done by the runtime
      --MethAssertPushOldLevel;
      AssertionGC.CallToComputeOldExpressions(Output, Gc.Obj);
      Output.EndIf;
      --Output.EndIf;
      --Output.IfDefined(Output.FullTraceModeLabel);
      Output.IfDefined(Output.CheckPreCondLabel);
      Output.Comment("Eval PreCond: call to evaluate");
      AssertionGC.CallToCheckPreConditions(Output, Gc.Obj);
      IF (Gc.Obj.Formals <> VOID) AND (Gc.Obj.Formals.Size > 0) THEN
        MethAssertPopLevel;
        END;
      Output.EndIf;
      --Output.EndIf;

      --Output.IfDefined(Output.FullTraceModeLabel);
      Output.IfDefined(Output.CheckPostCondLabel);
      -- if we want to check post conditions, we need to differ the return.
      IF Gc.Obj.Return <> VOID THEN
        Output.Result;
        Output.Becomes;
        END;
      Output.LeftParent;
      Output.Star;
      MethDeclGenerateDualExtraction (Gc);
      Output.RightParent;
      MethDeclGenerateFormals (Gc,
                       WithThis := TRUE,
                       WithCommas := FALSE,
                       WithTypes := FALSE,
                       WithSemiColons := FALSE,
                       WithParents := TRUE);
      Output.SemiColon;
      Output.WriteLn;
      IF Gc.MustPushParamStackLevel THEN
--      IF ((Gc.Obj.Formals <> VOID) AND (Gc.Obj.Formals.Size > 0))
--         OR (Gc.Obj.Return <> VOID) THEN
        Output.Comment("Eval PostCond: Push Params");
        MethAssertPushLevel;
        MethAssertPushFormals(Gc, TRUE, TRUE);
      ELSE
        Output.Comment("Eval PostCond: NO Params");
        END;
      Output.Comment("Eval PostCond: call to evaluate");
      AssertionGC.CallToCheckPostConditions(Output, Gc.Obj);
      IF Gc.MustPushParamStackLevel THEN
--      IF (Gc.Obj.Formals <> VOID) AND (Gc.Obj.Formals.Size > 0) 
--         OR (Gc.Obj.Return <> VOID) THEN
        MethAssertPopLevel;
        --MethAssertPopOldLevel;
        END;
      IF Gc.Obj.Return <> VOID THEN
        Output.Return;
        Output.Result;
        Output.SemiColon;
        Output.WriteLn;
        END;
      Output.EndIf;
      --Output.EndIf;

      -- If we do not want to evaluate post conditions
      Output.IfNDefined(Output.CheckPostCondLabel);
      IF Gc.Obj.Return <> VOID THEN
        Output.Return;
        END;
      Output.LeftParent;
      Output.Star;
      MethDeclGenerateDualExtraction (Gc);
      Output.RightParent;
      MethDeclGenerateFormals (Gc,
                       WithThis := TRUE,
                       WithCommas := FALSE,
                       WithTypes := FALSE,
                       WithSemiColons := FALSE,
                       WithParents := TRUE);
      Output.SemiColon;
      Output.WriteLn;
      Output.EndIf;

      Output.RightBrace;
      Output.WriteLn;
      END MethDeclGenerateAnchorBody;

   ---------------------------------------- 
   -- ClassDeclCodeGenerator
   ----------------------------------------
    METHOD ClassDeclGenerateCast (Gc:ClassDeclCodeGenerator);
      BEGIN 
      Output.LeftParent;
      Output.Class (Gc.Obj.ModuleName, Gc.Obj.Id.Data);
      Output.Star;
      Output.RightParent;
      END ClassDeclGenerateCast;
    
    METHOD ClassDeclGenerateConstructFuncId (Gc:ClassDeclCodeGenerator);
      BEGIN
      ASSERT Gc.Obj.NeedsConstructFunc;
      Output.ConstructFunc (Gc.Obj.ModuleName, Gc.Obj.Id.Data);
      END ClassDeclGenerateConstructFuncId;
      
    METHOD ClassDeclGenerateMinimalDualExtract (Gc:ClassDeclCodeGenerator);
      BEGIN
      Output.LeftParent;
      Output.Star;
      ClassDeclGenerateMinDualRef(Gc);
      Output.RightParent;
      END ClassDeclGenerateMinimalDualExtract;
        
    METHOD ClassDeclGenerateCreateAnchorId(Gc:ClassDeclCodeGenerator);
      BEGIN
      Output.CreateAnchor (Gc.Obj.ModuleName, Gc.Obj.Id.Data);
      END ClassDeclGenerateCreateAnchorId;
      
    METHOD ClassDeclGenerateLiteral (Gc:ClassDeclCodeGenerator);
      BEGIN
      Output.ClassLiteral (Gc.Obj.ModuleName, Gc.Obj.Id.Data);
      END ClassDeclGenerateLiteral;
      
    METHOD ClassDeclGenerateVersionChecking (Gc:ClassDeclCodeGenerator;
                                             ImportingModule: ImplementationModule);
      BEGIN
      IF NOT Gc.Obj.Deleted THEN
        Output.WriteLn;
        Output.CheckVersion;
        Output.LeftParent;  
        CompilationUnitGenerateLiteral(ImportingModule.Gc);
        Output.Comma; 
        CClassDecl.GenerateMinDualRef(Gc);
        Output.Comma;
        Output.SizeOf;
        Output.LeftParent;
        Output.Class (Gc.Obj.ModuleName, Gc.Obj.Id.Data);
        Output.RightParent;
        Output.Comma;
        Output.SizeOf;
        Output.LeftParent;
        Output.DualType(Gc.Obj.ModuleName, Gc.Obj.Id.Data);
        Output.RightParent;
        Output.RightParent;
        Output.SemiColon;
        Output.WriteLn;   
        END;
      END ClassDeclGenerateVersionChecking;      
      
    METHOD ClassDeclGenerateDualRef (Gc:ClassDeclCodeGenerator);
     VAR
       ModName, ClassName       : ARRAY OF CHAR;
      BEGIN
      ASSERT Output <> VOID;
      ModName := Gc.Obj.ModuleName;
      ClassName := Gc.Obj.Id.Data;
--      IF Gc.Obj.SkipDualPtr THEN
        Output.LeftParent;
        Output.Ampersand;
        Output.DualInstance(ModName, ClassName);
        Output.RightParent;
--       ELSE
--        Output.DualPointer(ModName, ClassName);
--        END;
      END ClassDeclGenerateDualRef;

    METHOD ClassDeclGenerateMinDualRef (Gc:ClassDeclCodeGenerator);
      BEGIN
      ASSERT Output <> VOID;
      Output.LeftParent;
      Output.LeftParent;
      Output.MinimalDual;
      Output.Star;
      Output.RightParent;
      CClassDecl.GenerateDualRef(Gc);
      Output.RightParent;
      END ClassDeclGenerateMinDualRef;
      
   ---------------------------------------- 
   -- CompilationUnitCodeGenerator
   ----------------------------------------

    METHOD CompilationUnitGenerateLiteral(Gc: CompilationUnitCodeGenerator);
      BEGIN   
      Output.ModuleLiteral (Gc.Obj.Id.Data);
      END CompilationUnitGenerateLiteral;

    METHOD CompilationUnitGenerateVersionChecking (Gc: CompilationUnitCodeGenerator;
                                                   ImportingModule: ImplementationModule);
      BEGIN
      -- Well...
      WHAT Gc.Obj OF
        IN ImplementationModule:
          FOR i := 0 TO TAG.Classes.Size - 1 DO
            ClassDeclGenerateVersionChecking (TAG.Classes.Get(i).Gc, ImportingModule);
            END;
          END;
        IN DefinitionModule:
          FOR i := 0 TO TAG.Classes.Size - 1 DO
            ClassDeclGenerateVersionChecking (TAG.Classes.Get(i).Gc, ImportingModule);
            END;
          END;
        END;  
      END CompilationUnitGenerateVersionChecking;

   ---------------------------------------- 
   -- AssertionCodeGenerator
   ----------------------------------------

     METHOD AssertionGenerateCode(Gc: AssertionCodeGenerator);
       BEGIN 
       IF YaflCfg.VerboseLevel > 3 THEN
         StdOut.WriteLine ("Generate Code : invariant");
         END;
       END AssertionGenerateCode;
       
     METHOD AssertionGenerateTestExpression (Gc: AssertionCodeGenerator;
                                             TheExpr: TypedNonTerminal;
                                             ExprNr: INTEGER);
       VAR
         IsFunc: BOOLEAN;
       BEGIN
       ASSERT TheExpr <> VOID;
       IsFunc := TheExpr.Functional;
       IF NOT IsFunc THEN
         Output.WriteLn;
         Output.LeftBrace;
         Output.Int;
         Output.UniqueItem (TheExpr.Gc.Number);
         Output.SemiColon;
         Output.WriteLn;
         TheExpr.Gc.GenerateCodeWithTarget (TheExpr.Gc.Number);
         END;
       Output.TraceStep(TheExpr.LineNr);
       Output.If;
       Output.LeftParent;
       Output.Not;
       Output.LeftParent;
         -- XXJC  (d)
       IF IsFunc THEN
         TheExpr.Gc.GenerateCode;
       ELSE
         Output.UniqueItem (TheExpr.Gc.Number);
         END;
       Output.RightParents(2);
       Output.WriteString(AssertionGC.LocalResult);
       Output.Becomes;
       Output.SetBit;
       Output.LeftParent;
       Output.WriteString(AssertionGC.LocalResult);
       Output.Comma;
       Output.WriteInt(ExprNr,0);
       Output.RightParent;
       Output.SemiColon;
       IF NOT IsFunc THEN
         Output.RightBrace;
         END;
       END AssertionGenerateTestExpression;
       
-- XXJC (d)
   ---------------------------------------- 
   -- MethAssertCodeGenerator
   ----------------------------------------
    
     METHOD MethStructNr(Meth: MethodDeclaration): INTEGER;
       BEGIN
       ASSERT Meth <> VOID;
       RESULT := -1;
       IF NOT Meth.Deferred THEN
         WHAT Meth OF 
           IN MethodImplementation:
             IF TAG.UseStruct THEN
               RESULT := TAG.StructNr; 
               END;
             END;
           END;
         END;
       END MethStructNr;
    
     METHOD MethAssertGenerateFormalParamAccessDecl(Gc:   MethAssertCodeGenerator;
                                                    Meth: MethodDeclaration);
       VAR
         TheFormals: FormalList;
         Tmp:        Formal;
         StructNr:   INTEGER;
       BEGIN
       ASSERT Meth <> VOID;
       TheFormals := Gc.Obj.Method.Formals;
       StructNr := MethStructNr(Meth); 
       IF StructNr <> -1 THEN
         Output.UniqueItem (StructNr);
         Output.Context;
         Output.SemiColon;
         Output.WriteLn;
       ELSE
         FOR Ind := 0 TO TheFormals.Size-1 DO
            Tmp := TheFormals.Get(Ind);
            ASSERT (Tmp <> VOID);
            Tmp.GetType.Gc.GenerateCode;
            Output.Yu(Tmp.Id.Data);
            Output.SemiColon;
            Output.WriteLn;
            END;
         END;
       END MethAssertGenerateFormalParamAccessDecl;

       
     METHOD MethAssertGenerateFormalParamAccessInit(Gc: MethAssertCodeGenerator;
                                                    Meth: MethodDeclaration;
                                                    HasReturn: BOOLEAN);
       VAR
         TheFormals: FormalList;
         Tmp:        Formal;
         MetIGc:     CMethImplCodeGenerator;
       BEGIN
       TheFormals := Gc.Obj.Method.Formals;
       WHAT Meth.Gc OF
         IN CMethImplCodeGenerator:
           MetIGc := TAG;
           END;
       ELSE
         -- nothing here.
         END;
       FOR Ind := 0 TO TheFormals.Size-1 DO
         Tmp := TheFormals.Get(Ind);
         --DEBUG
         --  Output.WriteLn;
         --  Output.WriteString("printf(");
         --  Output.Quote;
         --  Output.WriteString("GetParam: " + Gc.Obj.Method.Class.Module.Id.Data + "(" 
         --                     + IntConversions.IntToString(Tmp.LineNr,0) + ","
         --                     + IntConversions.IntToString(Tmp.ColNr,0) + ")\n");
         --  Output.Quote;
         --  Output.WriteLine(");");
         --  END;
         IF MetIGc <> VOID THEN
           MetIGc.GenerateLocal(Tmp);
         ELSE 
           Tmp.Gc.GenerateCode;
           END;
         Output.Becomes;
         IF HasReturn THEN
           AssertionGC.GenerateGetParam(Output, 
                                        TheFormals.Size+1 - Ind, 
                                        Tmp.GetType);
         ELSE
           AssertionGC.GenerateGetParam(Output, 
                                        TheFormals.Size - Ind, 
                                        Tmp.GetType);
           END;
         Output.SemiColon;
         END;
       END MethAssertGenerateFormalParamAccessInit;

     METHOD MethAssertGenerateOldExprAccess(Gc: PostCondCodeGenerator);
       VAR
         TheOlds: List(TypedNonTerminal);
         Tmp:     TypedNonTerminal;
       BEGIN
       TheOlds := Gc.Obj.OldExpressions;
       --StdOut.WriteLine("GenerateOld: " + Gc.Obj.Method.Id.Data 
       --             + "(" + IntConversions.IntToString(Gc.Obj.LineNr,0)
       --             + "," + IntConversions.IntToString(Gc.Obj.ColNr,0)
       --             + ")-> " + IntConversions.IntToString(TheOlds.Size,0));
       FOR Ind := 0 TO TheOlds.Size-1 DO
         Tmp := TheOlds.Get(Ind);
         --DEBUG
         --  Output.WriteLn;
         --  Output.WriteString("printf(");
         --  Output.Quote;
         --  Output.WriteString("GetOld: " + Gc.Obj.Method.Class.Module.Id.Data + "(" 
         --                     + IntConversions.IntToString(Gc.Obj.LineNr,0) + ","
         --                     + IntConversions.IntToString(Gc.Obj.ColNr,0) +")\n");
         --  Output.Quote;
         --  Output.WriteLine(");");
         --  END;
         WHAT Tmp.Gc OF
           IN COldExprCodeGenerator:
             TAG.GenerateExprName;
             END;
           END;
         Output.Becomes;
         AssertionGC.GenerateGetOld(Output, 
                                    Tmp.GetType);
         Output.SemiColon;
         END;
       END MethAssertGenerateOldExprAccess;

     METHOD MethAssertGenerateOldExprAccessDecl(Gc: PostCondCodeGenerator);
       VAR
         TheOlds: List(TypedNonTerminal);
         Tmp:     TypedNonTerminal;
       BEGIN
       TheOlds := Gc.Obj.OldExpressions;
       FOR Ind := 0 TO TheOlds.Size-1 DO
         Tmp := TheOlds.Get(Ind);
         ASSERT (Tmp <> VOID);
         Tmp.GetType.Gc.GenerateCode;
         WHAT Tmp.Gc OF
           IN COldExprCodeGenerator:
             TAG.GenerateExprName;
             END;
           END;
         Output.SemiColon;
         Output.WriteLn;
         END;
       END MethAssertGenerateOldExprAccessDecl;
       
     METHOD MethAssertGenerateResultAccessDecl(Gc: MethAssertCodeGenerator;
                                               Meth: MethodDeclaration);
       BEGIN
       IF MethStructNr(Meth) = -1 THEN
         Gc.Obj.Method.Return.Gc.GenerateCode;
         Output.Result;
         Output.SemiColon;
         END;
       END MethAssertGenerateResultAccessDecl;
       
     METHOD MethAssertGenerateResultAccessInit(Gc: MethAssertCodeGenerator;
                                               Meth: MethodDeclaration);
       VAR
         MetIGc:     CMethImplCodeGenerator;
       BEGIN
       ASSERT Meth <> VOID;
       --DEBUG
       --  Output.WriteLn;
       --  Output.WriteString("printf(");
       --  Output.Quote;
       --  Output.WriteString("GetRESULT: " + Gc.Obj.Method.Class.Module.Id.Data + "(" 
       --                     + IntConversions.IntToString(Meth.LineNr,0) + ","
       --                     + IntConversions.IntToString(Meth.ColNr,0) + ")\n");
       --  Output.Quote;
       --  Output.WriteLine(");");
       --  END;
       WHAT Meth.Gc OF
         IN CMethImplCodeGenerator:
           MetIGc := TAG;
           END;
       ELSE    
         END;
       IF MetIGc <> VOID THEN
         MetIGc.GenerateLocal(Gc.Obj.Method.LocalResult);
       ELSE
         Gc.Obj.Method.LocalResult.Gc.GenerateCode;
         END;
       Output.Becomes;
       AssertionGC.GenerateGetParam(Output, 
                                    1,
                                  --  TheFormalsSize+1, 
                                  --  TheFormalsSize+1, 
                                    Gc.Obj.Method.Return);
       Output.SemiColon;
       END MethAssertGenerateResultAccessInit;
       
  END CGcContext;
 
  CLASS CDummyCodeGenerator (ObjType IN NonTerminal);
    INHERITS GC(ObjType, CGcContext);

    END CDummyCodeGenerator;
 
  CLASS CCodeGeneratorCreator; 
    INHERITS CodeGeneratorCreator;

    REDEFINE METHOD CreateImplModuleCG(NT: ImplementationModule): CImplModuleCodeGenerator;
      BEGIN 
      RESULT.CREATE(NT);
      END CreateImplModuleCG;
         
    REDEFINE METHOD CreateDefModuleCG(NT: DefinitionModule): CDefModuleCodeGenerator;
      BEGIN 
      RESULT.CREATE(NT);
      END CreateDefModuleCG;
         
    REDEFINE METHOD CreateClassImplCG(NT: ClassImplementation): CClassImplCodeGenerator;
      BEGIN 
      RESULT.CREATE(NT);
      END CreateClassImplCG;
         
    REDEFINE METHOD CreateClassDefCG(NT: InstClassDefinition): CInstClassDefCodeGenerator;
      BEGIN 
      RESULT.CREATE(NT);
      END CreateClassDefCG;
         
    REDEFINE METHOD CreateMethodDefCG(NT: MethodDefinition): CMethDefCodeGenerator;
      BEGIN 
      RESULT.CREATE(NT);
      END CreateMethodDefCG;
 
    REDEFINE METHOD CreateVirtualClassDeclCG(NT: VirtualClassDecl): CVirtualClassDeclCodeGenerator;
      BEGIN                        
      RESULT.CREATE(NT);
      END CreateVirtualClassDeclCG;
           
    REDEFINE METHOD CreatePredefClassCG (NT: PredefClass): CPredefClassCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreatePredefClassCG; 
      
    REDEFINE METHOD CreateImportClauseCG (NT: ImportClause): CImportClauseCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateImportClauseCG; 
      
    REDEFINE METHOD CreateConstDeclCG (NT: ConstDeclaration): CConstDeclCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateConstDeclCG; 
      
    REDEFINE METHOD CreateSingleDataItemCG (NT: SingleDataItem): CSingleDataItemCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateSingleDataItemCG; 
      
    REDEFINE METHOD CreatePredefMethCG (NT: PredefMethod): CPredefMethCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreatePredefMethCG; 
      
    REDEFINE METHOD CreateMethDefCG (NT: MethodDefinition): CMethDefCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateMethDefCG; 
      
    REDEFINE METHOD CreateMethImplCG (NT: MethodImplementation): CMethImplCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateMethImplCG; 
      
    REDEFINE METHOD CreatePreCondCG (NT: PreCondition): CPreCondCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreatePreCondCG; 
      
    REDEFINE METHOD CreatePostCondCG (NT: PostCondition): CPostCondCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreatePostCondCG; 
      
    REDEFINE METHOD CreateClassInvCG (NT: ClassInvariant): CClassInvCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateClassInvCG; 
      
    REDEFINE METHOD CreateLoopInvCG (NT: LoopInvariant): CLoopInvCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateLoopInvCG; 
      
    REDEFINE METHOD CreateOldExprCG (NT: OldExpression): COldExprCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateOldExprCG; 
      
    REDEFINE METHOD CreateNopStatementCG (NT: NopStatement): CNopStatementCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateNopStatementCG; 
      
    REDEFINE METHOD CreateAssignmentCG (NT: Assignment): CAssignmentCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateAssignmentCG; 
      
    REDEFINE METHOD CreateMethInvStatCG (NT: MethodInvStatement): CMethInvStatCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateMethInvStatCG; 
      
    REDEFINE METHOD CreateDebugStatCG (NT: DebugStatement): CDebugStatCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateDebugStatCG; 
      
    REDEFINE METHOD CreateAssertStatCG (NT: AssertStatement): CAssertStatCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateAssertStatCG; 
      
    REDEFINE METHOD CreateInLineStatCG (NT: InLineStatement): CInLineStatCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateInLineStatCG; 
      
    REDEFINE METHOD CreateLoopStatCG (NT: LoopStatement): CLoopStatCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateLoopStatCG; 
      
    REDEFINE METHOD CreateIfStatCG (NT: IfStatement): CIfStatCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateIfStatCG; 
      
    REDEFINE METHOD CreateElsIfCG (NT: IfAlt): CElsIfCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateElsIfCG; 
      
    REDEFINE METHOD CreateCaseStatCG (NT: CaseStatement): CCaseStatCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateCaseStatCG; 
      
    REDEFINE METHOD CreateCaseAltCG (NT: CaseAlt): CCaseAltCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateCaseAltCG; 
      
    REDEFINE METHOD CreateCaseTagCG (NT: CaseTag): CCaseTagCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateCaseTagCG; 
      
    REDEFINE METHOD CreateWhatStatCG (NT: WhatStatement): CWhatStatCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateWhatStatCG; 
      
    REDEFINE METHOD CreateWhatAltCG (NT: WhatAlt): CWhatAltCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateWhatAltCG; 
      
    REDEFINE METHOD CreateWhatTagCG (NT: WhatTag): CWhatTagCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateWhatTagCG; 
      
    REDEFINE METHOD CreateStatListCG (NT: StatementList): CStatListCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateStatListCG; 
      
    REDEFINE METHOD CreateIntLiteralCG (NT: IntegerLiteral): CIntLiteralCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateIntLiteralCG; 
      
    REDEFINE METHOD CreateBooleanLiteralCG (NT: BooleanLiteral): CBooleanLiteralCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateBooleanLiteralCG; 
      
    REDEFINE METHOD CreateRealLiteralCG (NT: RealLiteral): CRealLiteralCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateRealLiteralCG; 
      
    REDEFINE METHOD CreateStringLiteralCG (NT: StringLiteral): CStringLiteralCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateStringLiteralCG; 
      
    REDEFINE METHOD CreateVoidLitCG (NT: Void): CVoidLitCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateVoidLitCG; 
      
    REDEFINE METHOD CreateExpressionCG (NT: Expression): CExpressionCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateExpressionCG; 
      
    REDEFINE METHOD CreateActualCG (NT: Actual): CActualCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateActualCG; 
      
    REDEFINE METHOD CreateInstTypeCG (NT: InstType): CInstTypeCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateInstTypeCG; 
      
    REDEFINE METHOD CreateInstClassDefCG (NT: InstClassDefinition): CInstClassDefCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateInstClassDefCG; 
      
    REDEFINE METHOD CreateDesigElementCG (NT: DesigElement): CDesigElementCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateDesigElementCG; 
      
    REDEFINE METHOD CreateDesigCG (NT: Desig): CDesigCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateDesigCG; 

    REDEFINE METHOD CreateQuantifierCG (NT: Quantifier): CQuantifierCodeGenerator;
      BEGIN
      RESULT.CREATE(NT);
      END CreateQuantifierCG; 

    REDEFINE METHOD CreateSetSpecCG (NT: SetSpecification)
                       : CSetSpecCodeGenerator;
	  BEGIN
      RESULT.CREATE(NT);
      END CreateSetSpecCG;
      
    REDEFINE METHOD WhatAmI: ARRAY OF CHAR;
       BEGIN
       RESULT := "C code generation";
       END WhatAmI;

  END CCodeGeneratorCreator;

END CGCode;
