IMPLEMENTATION MODULE YaflAsGC;

FROM YaflType          IMPORT TypedNonTerminal;
FROM YaflPreconditions IMPORT OldExpression;
FROM YaflGC            IMPORT YaflGC;
FROM YaflPredefined    IMPORT PredefItems,
                              PredefClass;
FROM CGMethods         IMPORT CMethDecl;
FROM CGClass           IMPORT CClassDecl;
FROM Streams           IMPORT StdOut;
FROM YaflClasses       IMPORT ClassDeclaration;
FROM YaflGMethods      IMPORT MethDeclCodeGenerator;
FROM CGMethods         IMPORT CMethImplCodeGenerator;
FROM Conversions       IMPORT IntConversions;

  ONCE CLASS AssertionGC;
    VAR
      LocalResultString: ONCE ARRAY OF CHAR;
      
    REDEFINE METHOD CREATE;
      BEGIN
      LocalResultString := "lresult";
      END CREATE;

    METHOD LocalResult: ARRAY OF CHAR;
      BEGIN
      RESULT := LocalResultString;
      END LocalResult;  

    METHOD CallToCheckPreConditions (Output: YaflGC; 
                                     Method: MethodDeclaration);
      VAR
        Meth: MethodDeclaration;
      BEGIN
      --DEBUG
      --  Output.WriteString("printf(");
      --  Output.QuotedString("ctc prec: " +
      --                     Method.Class.Module.Id.Data + "." +
      --                     Method.Class.Id.Data + "." +
      --                     Method.Id.Data + "(" +
      --                     IntConversions.IntToString(Method.LineNr,0) + "," +
      --                     IntConversions.IntToString(Method.ColNr,0) + ")\n", FALSE);
      --  Output.WriteLine(");");
      --  END;
      Output.CheckPreCondition;
      Output.LeftParent;
      Output.This;
      Output.Comma;
      Output.DbxMethodReference(Method.Class.Module.Id.Data,
                                Method.Class.Id.Data,
                                Method.Id.Data);
      Output.RightParent;
      Output.SemiColon;
      END CallToCheckPreConditions;   

    METHOD CallToCheckPostConditions   (Output: YaflGC; 
                                        Method: MethodDeclaration);
      VAR
        Class: ClassDeclaration;
      BEGIN
      --DEBUG
      --  Output.WriteString("printf(");
      --  Output.QuotedString("ctc post: " +
      --                     Method.Class.Module.Id.Data + "." +
      --                     Method.Class.Id.Data + "." +
      --                     Method.Id.Data + "(" +
      --                     IntConversions.IntToString(Method.LineNr,0) + "," +
      --                     IntConversions.IntToString(Method.ColNr,0) + ")\n", FALSE);
      --  Output.WriteLine(");");
      --  END;
      Output.CheckPostConditions;
      Output.LeftParent;
      Output.This;
      Output.Comma;
      Output.DbxMethodReference(Method.Class.Module.Id.Data,
                                Method.Class.Id.Data,
                                Method.Id.Data);
      Output.RightParent;
      Output.SemiColon;
      END CallToCheckPostConditions;
                               
      
    METHOD CallToComputeOldExpressions (Output: YaflGC; 
                                        Method: MethodDeclaration);
      VAR
        Class: ClassDeclaration;
      BEGIN
      --DEBUG
      --  Output.WriteString("printf(");
      --  Output.QuotedString("ctc old: " +
      --                     Method.Class.Module.Id.Data + "." +
      --                     Method.Class.Id.Data + "." +
      --                     Method.Id.Data + "(" +
      --                     IntConversions.IntToString(Method.LineNr,0) + "," +
      --                     IntConversions.IntToString(Method.ColNr,0) + ")\n", FALSE);
      --  Output.WriteLine(");");
      --  END;
      Output.ComputeOldExpressions;
      Output.LeftParent;
      Output.This;
      Output.Comma;
      Output.DbxMethodReference(Method.Class.Module.Id.Data,
                                Method.Class.Id.Data,
                                Method.Id.Data);
      Output.RightParent;
      Output.SemiColon;
      END CallToComputeOldExpressions;
      
    METHOD MethAssertPushType (Output: YaflGC; ObjType: Type); 
      BEGIN
      WHAT ObjType.SimpleType OF
        IN PredefClass:
	      IF (ObjType.ArrayLevel > 0 ) THEN
	        Output.AssertionStackPushObj;
	      ELSIF (TAG = PredefItems.Integer)
             OR (TAG = PredefItems.Boolean) THEN
            Output.AssertionStackPushInt;
          ELSIF (TAG = PredefItems.Char) THEN
            Output.AssertionStackPushChar;
          ELSIF TAG = PredefItems.Real THEN
            Output.AssertionStackPushReal;
            END;
          END;
      ELSE  
        Output.AssertionStackPushObj;
        END;    
      END MethAssertPushType;

    METHOD MethAssertPushOldExpr (Output: YaflGC; Expr: TypedNonTerminal); 
      BEGIN
      MethAssertPushType (Output, Expr.GetType);
      Output.LeftParent;
      Output.Ampersand;
      Output.OldStackName;
      Output.Comma;
      --Expr.Gc.GenerateEvaluationCode;
      Expr.Gc.GenerateCode;
      Output.RightParent;
      Output.SemiColon;
      Output.WriteLn;
      END MethAssertPushOldExpr;

    METHOD MethAssertPushFormal (Output: YaflGC; Param: Formal); 
      BEGIN
      MethAssertPushType (Output, Param.GetType);
      Output.LeftParent;
      Output.Ampersand;
      Output.AssertionStackName;
      Output.Comma;
      Output.Yu(Param.Id.Data);
      Output.RightParent;
      Output.SemiColon;
      Output.WriteLn;
      END MethAssertPushFormal;

    METHOD MethAssertPushResult (Output: YaflGC;
                                 Gc: CMethImplCodeGenerator; 
                                 ReturnType: Type;
                                 InAnchor: BOOLEAN); 
      BEGIN
      MethAssertPushType (Output, ReturnType);
      Output.LeftParent;
      Output.Ampersand;
      Output.AssertionStackName;
      Output.Comma;
      IF InAnchor THEN
        Output.Result;
      ELSE
        IF Gc <> VOID THEN
          Gc.GenerateLocal(Gc.Obj.LocalResult);
        ELSE
          Output.Result;
          END;
        END;
      Output.RightParent;
      Output.SemiColon;
      Output.WriteLn;
      END MethAssertPushResult;

    METHOD GenerateGetOld (Output: YaflGC; 
                           OldType: Type);
      BEGIN
      GeneratePop(Output, OldType, FALSE);
      END GenerateGetOld;

    METHOD GenerateGetParam (Output: YaflGC; 
                             Offset: INTEGER; 
                             ParamType: Type);
      BEGIN
      GenerateGet(Output, Offset, ParamType, TRUE);
      END GenerateGetParam;

    METHOD GenerateGet (Output: YaflGC; 
                        Offset: INTEGER; 
                        ParamType: Type;
                        UseAssertStack: BOOLEAN);
      BEGIN
      ASSERT ParamType <> VOID;
      WHAT ParamType.SimpleType OF
        IN PredefClass:
	      IF ParamType.ArrayLevel > 0 THEN
	        Output.AssertionStackGetObj;
	      ELSIF (TAG = PredefItems.Integer) 
             OR (TAG = PredefItems.Boolean) THEN
            Output.AssertionStackGetInt;
          ELSIF (TAG = PredefItems.Char) THEN
            Output.AssertionStackGetChar;
          ELSIF TAG = PredefItems.Real THEN
            Output.AssertionStackGetReal;
            END;
          END;
      ELSE  
        Output.AssertionStackGetObj;
        END;    
      Output.LeftParent;
      Output.Ampersand;
      IF UseAssertStack THEN
        Output.AssertionStackName;
      ELSE
        Output.OldStackName;
        END;
      Output.Comma;
      Output.WriteInt(Offset, 0);
      Output.RightParent;
      END GenerateGet;
      
    METHOD GeneratePop (Output: YaflGC; 
                        ParamType: Type;
                        UseAssertStack: BOOLEAN);
      BEGIN
      ASSERT ParamType <> VOID;
      WHAT ParamType.SimpleType OF
        IN PredefClass:
	      IF ParamType.ArrayLevel > 0 THEN
	        Output.AssertionStackPopObj;
	      ELSIF (TAG = PredefItems.Integer) 
             OR (TAG = PredefItems.Boolean) THEN
            Output.AssertionStackPopInt;
          ELSIF (TAG = PredefItems.Char) THEN
            Output.AssertionStackPopChar;
          ELSIF TAG = PredefItems.Real THEN
            Output.AssertionStackPopReal;
            END;
          END;
      ELSE  
        Output.AssertionStackPopObj;
        END;    
      Output.LeftParent;
      Output.Ampersand;
      IF UseAssertStack THEN
        Output.AssertionStackName;
      ELSE
        Output.OldStackName;
        END;
      --Output.Comma;
      --Output.WriteInt(Offset, 0);
      Output.RightParent;
      END GeneratePop;
      
  END AssertionGC;
  
END YaflAsGC;

