Browse Source

Added support for explicitly ignoring the return value of procedure calls by prefixing them with the new IGNORE keyword

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@8484 8c9fc860-2736-0410-a75d-ab315db34111
negelef 6 năm trước cách đây
mục cha
commit
41669785ad

+ 5 - 5
source/FoxCSharpParser.Mod

@@ -1426,7 +1426,7 @@ KernelLog.Ln();
             expressionList.AddExpression(right);
             designator := SyntaxTree.NewIdentifierDesignator(position, lynxAsop);
             designator := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
-            RETURN SyntaxTree.NewProcedureCallStatement(designator.position, designator, outer);
+            RETURN SyntaxTree.NewProcedureCallStatement(designator.position, FALSE, designator, outer);
         END NewAsopStatement;
 
 (* ACHTUNG: LYNX 15-MAY-2013 *)
@@ -1495,7 +1495,7 @@ KernelLog.Ln();
             expressionList.AddExpression(right);
             designator := SyntaxTree.NewIdentifierDesignator(position, name);
             designator := SyntaxTree.NewParameterDesignator(position, designator, expressionList);
-            RETURN SyntaxTree.NewProcedureCallStatement(designator.position, designator, outer);
+            RETURN SyntaxTree.NewProcedureCallStatement(designator.position, FALSE, designator, outer);
         END NewPortStatement; 
 
         PROCEDURE StatementExpression(
@@ -1608,7 +1608,7 @@ KernelLog.Ln();
                     expression := PatchPortReference(expression);
                     statement := NewPortStatement(position, lynxDelegate, designator, expression, outer);
                 ELSIF designator IS SyntaxTree.ParameterDesignator THEN
-                    statement := SyntaxTree.NewProcedureCallStatement(designator.position, designator, outer);
+                    statement := SyntaxTree.NewProcedureCallStatement(designator.position, FALSE, designator, outer);
                 ELSE
                     Error(position, Basic.InvalidCode, "Invalid expression statement");
                 END;
@@ -1839,7 +1839,7 @@ KernelLog.Ln();
             parameters := SyntaxTree.NewExpressionList();
             designator := SyntaxTree.NewIdentifierDesignator(position, lynxNewsel);
             designator := SyntaxTree.NewParameterDesignator(position, designator, parameters);
-            RETURN SyntaxTree.NewProcedureCallStatement(position, designator, outer);
+            RETURN SyntaxTree.NewProcedureCallStatement(position, FALSE, designator, outer);
         END NewLynxNewsel;
 
         PROCEDURE NewLynxAddsel(
@@ -1862,7 +1862,7 @@ KernelLog.Ln();
             parameters.AddExpression(channel);
             designator := SyntaxTree.NewIdentifierDesignator(position, lynxAddsel);
             designator := SyntaxTree.NewParameterDesignator(position, designator, parameters);
-            RETURN SyntaxTree.NewProcedureCallStatement(position, designator, outer);
+            RETURN SyntaxTree.NewProcedureCallStatement(position, FALSE, designator, outer);
         END NewLynxAddsel;
 
         PROCEDURE NewLynxSelect(position: Position): SyntaxTree.Expression;

+ 1 - 1
source/FoxIntermediateBackend.Mod

@@ -10956,7 +10956,7 @@ TYPE
 		BEGIN
 			IF Trace THEN TraceEnter("VisitProcedureCallStatement") END;
 			Expression(x.call);
-			IF (x.call.type # NIL) THEN (* WINAPI call: procedure returning unused value *)
+			IF (x.call.type # NIL) THEN (* procedure returning ignored value *)
 				ReleaseOperand(result)
 			END;
 			IF Trace THEN TraceExit("VisitProcedureCallStatement") END;

+ 9 - 1
source/FoxParser.Mod

@@ -1129,7 +1129,7 @@ TYPE
 						statement := SyntaxTree.NewCommunicationStatement(position, commToken, designator, expression, outer);
 						CommentStatement(statement);
 					ELSE
-						caller := SyntaxTree.NewProcedureCallStatement(designator.position, designator,outer);
+						caller := SyntaxTree.NewProcedureCallStatement(designator.position, FALSE, designator,outer);
 						statement := caller;
 						CommentStatement(statement);
 					END;
@@ -1303,6 +1303,14 @@ TYPE
 					returnStatement.End(symbol.position);
 					statements.AddStatement( returnStatement );
 					result := TRUE;
+			| Scanner.Ignore:
+					position := symbol.position;
+					CommentStatement(statement);
+					NextSymbol;
+					designator := Designator();
+					caller := SyntaxTree.NewProcedureCallStatement(designator.position, TRUE, designator,outer);
+					statements.AddStatement( caller );
+					result := TRUE;
 			| Scanner.Begin:
 					NextSymbol;  statement := StatementBlock(outer);  statements.AddStatement( statement );  Check( Scanner.End );
 					statement.End(symbol.position);

+ 4 - 1
source/FoxPrintout.Mod

@@ -1497,7 +1497,10 @@ TYPE
 		END VisitStatement;
 
 		PROCEDURE VisitProcedureCallStatement*(x: SyntaxTree.ProcedureCallStatement);
-		BEGIN Expression(x.call) END VisitProcedureCallStatement;
+		BEGIN
+			IF x.ignore THEN Keyword("IGNORE " ) END;
+			Expression(x.call);
+		END VisitProcedureCallStatement;
 
 		PROCEDURE VisitAssignment*(x: SyntaxTree.Assignment);
 		BEGIN

+ 17 - 15
source/FoxScanner.Mod

@@ -45,7 +45,7 @@ CONST
     	(* expressions may start with Plus ... Identifier *)
 		LeftParenthesis LeftBracket LeftBrace Number Character String Nil Imag True False Self Result New Identifier
 		(* statementy may start with Self ... Begin *)
-		If Case While Repeat For Loop With Exit Await Return Begin
+		If Case While Repeat For Loop With Exit Await Return Ignore Begin
 		(* symbols, expressions and statements cannot start with *)
 		Semicolon Transpose RightBrace RightBracket RightParenthesis 
 		Questionmark ExclamationMark
@@ -80,25 +80,25 @@ CONST
 	New*= 45; Identifier*= 46; 
 	(* statementy may start with Self ... Begin *)
 	If*= 47; Case*= 48; While*= 49; Repeat*= 50; For*= 51; Loop*= 52; 
-	With*= 53; Exit*= 54; Await*= 55; Return*= 56; Begin*= 57; 
+	With*= 53; Exit*= 54; Await*= 55; Return*= 56; Ignore*= 57; Begin*= 58; 
 	(* symbols, expressions and statements cannot start with *)
-	Semicolon*= 58; Transpose*= 59; RightBrace*= 60; RightBracket*= 61; RightParenthesis*= 62; Questionmark*= 63; 
-	ExclamationMark*= 64; LessLess*= 65; GreaterGreater*= 66; Upto*= 67; Arrow*= 68; Period*= 69; 
-	Comma*= 70; Colon*= 71; Of*= 72; Then*= 73; Do*= 74; To*= 75; 
-	By*= 76; Becomes*= 77; Bar*= 78; End*= 79; Else*= 80; Elsif*= 81; 
-	Until*= 82; Finally*= 83; 
+	Semicolon*= 59; Transpose*= 60; RightBrace*= 61; RightBracket*= 62; RightParenthesis*= 63; Questionmark*= 64; 
+	ExclamationMark*= 65; LessLess*= 66; GreaterGreater*= 67; Upto*= 68; Arrow*= 69; Period*= 70; 
+	Comma*= 71; Colon*= 72; Of*= 73; Then*= 74; Do*= 75; To*= 76; 
+	By*= 77; Becomes*= 78; Bar*= 79; End*= 80; Else*= 81; Elsif*= 82; 
+	Until*= 83; Finally*= 84; 
 	(* declaration elements *)
-	Code*= 84; Const*= 85; Type*= 86; Var*= 87; Out*= 88; Procedure*= 89; 
-	Operator*= 90; Import*= 91; Definition*= 92; Module*= 93; Cell*= 94; CellNet*= 95; 
-	Extern*= 96; 
+	Code*= 85; Const*= 86; Type*= 87; Var*= 88; Out*= 89; Procedure*= 90; 
+	Operator*= 91; Import*= 92; Definition*= 93; Module*= 94; Cell*= 95; CellNet*= 96; 
+	Extern*= 97; 
 	(* composite type symbols *)
-	Array*= 97; Object*= 98; Record*= 99; Pointer*= 100; Enum*= 101; Port*= 102; 
-	Address*= 103; Size*= 104; Alias*= 105; 
+	Array*= 98; Object*= 99; Record*= 100; Pointer*= 101; Enum*= 102; Port*= 103; 
+	Address*= 104; Size*= 105; Alias*= 106; 
 	(* assembler constants *)
-	Ln*= 106; PC*= 107; PCOffset*= 108; 
+	Ln*= 107; PC*= 108; PCOffset*= 109; 
 	(* number types *)
-	Shortint*= 109; Integer*= 110; Longint*= 111; Hugeint*= 112; Real*= 113; Longreal*= 114; 
-	Comment*= 115; EndOfText*= 116; Escape*= 117; 
+	Shortint*= 110; Integer*= 111; Longint*= 112; Hugeint*= 113; Real*= 114; Longreal*= 115; 
+	Comment*= 116; EndOfText*= 117; Escape*= 118; 
 
 	SingleQuote = 27X;  DoubleQuote* = 22X;
 	Ellipsis = 7FX;   (* used in Scanner.GetNumber to return with ".." when reading an interval like 3..5 *)
@@ -1310,6 +1310,7 @@ TYPE
 		tokens[Exit] := "Exit";
 		tokens[Await] := "Await";
 		tokens[Return] := "Return";
+		tokens[Ignore] := "Ignore";
 		tokens[Begin] := "Begin";
 		tokens[Semicolon] := "Semicolon";
 		tokens[Transpose] := "Transpose";
@@ -1435,6 +1436,7 @@ TYPE
 		Enter( "for" , For);
 		Enter( "finally" , Finally);
 		Enter( "if" , If);
+		Enter( "ignore" , Ignore);
 		Enter( "imag" , Imag);
 		Enter( "in" , In);
 		Enter( "is" , Is);

+ 7 - 4
source/FoxSemanticChecker.Mod

@@ -7030,6 +7030,7 @@ TYPE
 			IF Trace THEN D.Str("VisitProcedureCallStatement"); D.Ln; END;
 			call := procedureCall.call;
 			IF (call # NIL) &  ~(call IS SyntaxTree.ParameterDesignator) & ~(call IS SyntaxTree.ProcedureCallDesignator) & ~(call IS SyntaxTree.BuiltinCallDesignator)  THEN
+				IF procedureCall.ignore THEN Error(procedureCall.position, "ignoring non-procedure call") END;
 				call := SyntaxTree.NewParameterDesignator(call.position,call,SyntaxTree.NewExpressionList());
 			END;
 
@@ -7045,10 +7046,12 @@ TYPE
 			ELSIF (call.type # NIL) &  (call.left # NIL) THEN
 				IF call.left.type.resolved(SyntaxTree.ProcedureType).callingConvention = SyntaxTree.WinAPICallingConvention THEN
 					Warning(procedureCall.position,"ignoring return value of procedure call");
-				ELSE
+				ELSIF ~procedureCall.ignore THEN
 					Error(procedureCall.position,"calling procedure with non-void return type");
 					IF VerboseErrorMessage THEN Printout.Info("call ",call) END;
 				END;
+			ELSIF procedureCall.ignore THEN
+				Error(procedureCall.position,"ignoring procedure call without return value");
 			END;
 			procedureCall.SetCall(call);
 
@@ -7091,12 +7094,12 @@ TYPE
 			ELSIF IsIndexOperator(left) & left.assignable THEN
 				(* LHS is index write operator call *)
 				procedureCallDesignator :=  left(SyntaxTree.ProcedureCallDesignator);
-				resolvedStatement := SyntaxTree.NewProcedureCallStatement(assignment.position, procedureCallDesignator, assignment.outer);
+				resolvedStatement := SyntaxTree.NewProcedureCallStatement(assignment.position, FALSE, procedureCallDesignator, assignment.outer);
 			ELSIF CheckVariable(left) THEN
 				expression := NewOperatorCall(assignment.position, Scanner.Becomes, left, right, NIL);
 				IF (expression # NIL) & (expression IS SyntaxTree.ProcedureCallDesignator) THEN
 					procedureCallDesignator := expression(SyntaxTree.ProcedureCallDesignator);
-					resolvedStatement := SyntaxTree.NewProcedureCallStatement(assignment.position, procedureCallDesignator, assignment.outer);
+					resolvedStatement := SyntaxTree.NewProcedureCallStatement(assignment.position, FALSE, procedureCallDesignator, assignment.outer);
 				ELSIF (expression # NIL) & (expression IS SyntaxTree.StatementDesignator) THEN
 					resolvedStatement := expression(SyntaxTree.StatementDesignator).statement;
 				ELSIF AssignmentCompatible(left, right) THEN
@@ -7124,7 +7127,7 @@ TYPE
 			expression := NewOperatorCall(communication.position, communication.op, left, right, NIL);
 			IF (expression # NIL) & (expression IS SyntaxTree.ProcedureCallDesignator) THEN
 				procedureCallDesignator := expression(SyntaxTree.ProcedureCallDesignator);
-				resolvedStatement := SyntaxTree.NewProcedureCallStatement(communication.position, procedureCallDesignator, communication.outer);
+				resolvedStatement := SyntaxTree.NewProcedureCallStatement(communication.position, FALSE, procedureCallDesignator, communication.outer);
 			ELSE
 
 				IF ~cellsAreObjects THEN ImportModule(Global.NameChannelModule,communication.position) END;

+ 10 - 5
source/FoxSyntaxTree.Mod

@@ -3481,12 +3481,17 @@ TYPE
 
 	(** << call(...) >> **)
 	ProcedureCallStatement*= OBJECT(Statement)
+		VAR ignore-: BOOLEAN;
 		VAR call-: Designator;
 
-		PROCEDURE & InitProcedureCallStatement(position: Position; call: Designator; outer: Statement);
-		BEGIN	InitStatement(position,outer); SELF.call := call;
+		PROCEDURE & InitProcedureCallStatement(position: Position; ignore: BOOLEAN; call: Designator; outer: Statement);
+		BEGIN	InitStatement(position,outer); SELF.ignore := ignore; SELF.call := call;
 		END InitProcedureCallStatement;
 
+		PROCEDURE SetIgnore*(ignore: BOOLEAN);
+		BEGIN	SELF.ignore := ignore;
+		END SetIgnore;
+
 		PROCEDURE SetCall*(call: Designator);
 		BEGIN	SELF.call := call;
 		END SetCall;
@@ -3494,7 +3499,7 @@ TYPE
 		PROCEDURE Clone(): Statement;
 		VAR copy: ProcedureCallStatement;
 		BEGIN
-			NEW(copy, position, CloneDesignator(call), outer);
+			NEW(copy, position, ignore, CloneDesignator(call), outer);
 			RETURN copy
 		END Clone;
 
@@ -5647,10 +5652,10 @@ VAR
 		NEW( communication, position, op, left, right,outer );  RETURN communication
 	END NewCommunicationStatement;
 
-	PROCEDURE NewProcedureCallStatement*(position: Position; call: Designator; outer: Statement): ProcedureCallStatement;
+	PROCEDURE NewProcedureCallStatement*(position: Position; ignore: BOOLEAN; call: Designator; outer: Statement): ProcedureCallStatement;
 	VAR caller: ProcedureCallStatement;
 	BEGIN
-		NEW(caller,position,call,outer); RETURN caller
+		NEW(caller,position,ignore,call,outer); RETURN caller
 	END NewProcedureCallStatement;
 
 	PROCEDURE NewCaseStatement*( position: Position ; outer: Statement): CaseStatement;

+ 122 - 24
source/Oberon.Compilation.Test

@@ -17001,84 +17001,182 @@ negative: calling procedure returning boolean
 
 	MODULE Test;
 	PROCEDURE Procedure (): BOOLEAN; END Procedure;
-	BEGIN Procedure
+	BEGIN Procedure ()
+	END Test.
+
+positive: ignoring procedure call returning boolean
+
+	MODULE Test;
+	PROCEDURE Procedure (): BOOLEAN; END Procedure;
+	BEGIN IGNORE Procedure ()
 	END Test.
 
 negative: calling procedure returning character
 
 	MODULE Test;
 	PROCEDURE Procedure (): CHAR; END Procedure;
-	BEGIN Procedure
+	BEGIN Procedure ()
+	END Test.
+
+positive: ignoring procedure call returning character
+
+	MODULE Test;
+	PROCEDURE Procedure (): CHAR; END Procedure;
+	BEGIN IGNORE Procedure ()
 	END Test.
 
 negative: calling procedure returning integer
 
 	MODULE Test;
 	PROCEDURE Procedure (): INTEGER; END Procedure;
-	BEGIN Procedure
+	BEGIN Procedure ()
+	END Test.
+
+positive: ignoring procedure call returning integer
+
+	MODULE Test;
+	PROCEDURE Procedure (): INTEGER; END Procedure;
+	BEGIN IGNORE Procedure ()
 	END Test.
 
 negative: calling procedure returning real
 
 	MODULE Test;
 	PROCEDURE Procedure (): REAL; END Procedure;
-	BEGIN Procedure
+	BEGIN Procedure ()
+	END Test.
+
+positive: ignoring procedure call returning real
+
+	MODULE Test;
+	PROCEDURE Procedure (): REAL; END Procedure;
+	BEGIN IGNORE Procedure ()
 	END Test.
 
 negative: calling procedure returning set
 
 	MODULE Test;
 	PROCEDURE Procedure (): SET; END Procedure;
-	BEGIN Procedure
+	BEGIN Procedure ()
+	END Test.
+
+positive: ignoring procedure call returning set
+
+	MODULE Test;
+	PROCEDURE Procedure (): SET; END Procedure;
+	BEGIN IGNORE Procedure ()
 	END Test.
 
 negative: calling procedure returning array
 
 	MODULE Test;
 	PROCEDURE Procedure (): ARRAY 10 OF CHAR; END Procedure;
-	BEGIN Procedure
+	BEGIN Procedure ()
+	END Test.
+
+positive: ignoring procedure call returning array
+
+	MODULE Test;
+	PROCEDURE Procedure (): ARRAY 10 OF CHAR; END Procedure;
+	BEGIN IGNORE Procedure ()
 	END Test.
 
 negative: calling procedure returning record
 
 	MODULE Test;
 	PROCEDURE Procedure (): RECORD END; END Procedure;
-	BEGIN Procedure
+	BEGIN Procedure ()
+	END Test.
+
+positive: ignoring procedure call returning record
+
+	MODULE Test;
+	PROCEDURE Procedure (): RECORD END; END Procedure;
+	BEGIN IGNORE Procedure ()
 	END Test.
 
 negative: calling procedure returning object
 
 	MODULE Test;
 	PROCEDURE Procedure (): OBJECT END; END Procedure;
-	BEGIN Procedure
+	BEGIN Procedure ()
+	END Test.
+
+positive: ignoring procedure call returning object
+
+	MODULE Test;
+	PROCEDURE Procedure (): OBJECT END; END Procedure;
+	BEGIN IGNORE Procedure ()
 	END Test.
 
 negative: calling procedure returning base object
 
 	MODULE Test;
 	PROCEDURE Procedure (): OBJECT; END Procedure;
-	BEGIN Procedure
+	BEGIN Procedure ()
+	END Test.
+
+positive: ignoring procedure call returning base object
+
+	MODULE Test;
+	PROCEDURE Procedure (): OBJECT; END Procedure;
+	BEGIN IGNORE Procedure ()
 	END Test.
 
 negative: calling procedure returning pointer to array
 
 	MODULE Test;
 	PROCEDURE Procedure (): POINTER TO ARRAY 10 OF CHAR; END Procedure;
-	BEGIN Procedure
+	BEGIN Procedure ()
+	END Test.
+
+positive: ignoring procedure call returning pointer to array
+
+	MODULE Test;
+	PROCEDURE Procedure (): POINTER TO ARRAY 10 OF CHAR; END Procedure;
+	BEGIN IGNORE Procedure ()
 	END Test.
 
 negative: calling procedure returning pointer to record
 
 	MODULE Test;
 	PROCEDURE Procedure (): POINTER TO ARRAY 10 OF RECORD END; END Procedure;
-	BEGIN Procedure
+	BEGIN Procedure ()
+	END Test.
+
+positive: ignoring procedure call returning pointer to record
+
+	MODULE Test;
+	PROCEDURE Procedure (): POINTER TO ARRAY 10 OF RECORD END; END Procedure;
+	BEGIN IGNORE Procedure ()
 	END Test.
 
 negative: calling procedure returning procedure
 
 	MODULE Test;
 	PROCEDURE Procedure (): PROCEDURE; END Procedure;
-	BEGIN Procedure
+	BEGIN Procedure ()
+	END Test.
+
+positive: ignoring procedure call returning procedure
+
+	MODULE Test;
+	PROCEDURE Procedure (): PROCEDURE; END Procedure;
+	BEGIN IGNORE Procedure ()
+	END Test.
+
+positive: calling procedure returning nothing
+
+	MODULE Test;
+	PROCEDURE Procedure (); END Procedure;
+	BEGIN Procedure; Procedure ()
+	END Test.
+
+negative: ignoring procedure call returning nothing
+
+	MODULE Test;
+	PROCEDURE Procedure (); END Procedure;
+	BEGIN IGNORE Procedure ()
 	END Test.
 
 
@@ -29615,84 +29713,84 @@ negative: calling variable procedure returning boolean
 
 	MODULE Test;
 	VAR procedure: PROCEDURE (): BOOLEAN;
-	BEGIN procedure
+	BEGIN procedure ()
 	END Test.
 
 negative: calling variable procedure returning character
 
 	MODULE Test;
 	VAR procedure: PROCEDURE (): CHAR;
-	BEGIN procedure
+	BEGIN procedure ()
 	END Test.
 
 negative: calling variable procedure returning integer
 
 	MODULE Test;
 	VAR procedure: PROCEDURE (): INTEGER;
-	BEGIN procedure
+	BEGIN procedure ()
 	END Test.
 
 negative: calling variable procedure returning real
 
 	MODULE Test;
 	VAR procedure: PROCEDURE (): REAL;
-	BEGIN procedure
+	BEGIN procedure ()
 	END Test.
 
 negative: calling variable procedure returning set
 
 	MODULE Test;
 	VAR procedure: PROCEDURE (): SET;
-	BEGIN procedure
+	BEGIN procedure ()
 	END Test.
 
 negative: calling variable procedure returning array
 
 	MODULE Test;
 	VAR procedure: PROCEDURE (): ARRAY 10 OF CHAR;
-	BEGIN procedure
+	BEGIN procedure ()
 	END Test.
 
 negative: calling variable procedure returning record
 
 	MODULE Test;
 	VAR procedure: PROCEDURE (): RECORD END;
-	BEGIN procedure
+	BEGIN procedure ()
 	END Test.
 
 negative: calling variable procedure returning object
 
 	MODULE Test;
 	VAR procedure: PROCEDURE (): OBJECT END;
-	BEGIN procedure
+	BEGIN procedure ()
 	END Test.
 
 negative: calling variable procedure returning base object
 
 	MODULE Test;
 	VAR procedure: PROCEDURE (): OBJECT;
-	BEGIN procedure
+	BEGIN procedure ()
 	END Test.
 
 negative: calling variable procedure returning pointer to array
 
 	MODULE Test;
 	VAR procedure: PROCEDURE (): POINTER TO ARRAY 10 OF CHAR;
-	BEGIN procedure
+	BEGIN procedure ()
 	END Test.
 
 negative: calling variable procedure returning pointer to record
 
 	MODULE Test;
 	VAR procedure: PROCEDURE (): POINTER TO ARRAY 10 OF RECORD END;
-	BEGIN procedure
+	BEGIN procedure ()
 	END Test.
 
 negative: calling variable procedure returning procedure
 
 	MODULE Test;
 	VAR procedure: PROCEDURE (): PROCEDURE;
-	BEGIN procedure
+	BEGIN procedure ()
 	END Test.