Browse Source

procedure returning a result cannot be used as a statement.

Vladislav Folts 12 years ago
parent
commit
2b5bd5ba37
5 changed files with 81 additions and 97 deletions
  1. 4 1
      src/context.js
  2. 24 45
      src/procedure.js
  3. 3 2
      test/expected/len.js
  4. 3 2
      test/input/len.ob
  5. 47 47
      test/test_unit.js

+ 4 - 1
src/context.js

@@ -1442,7 +1442,10 @@ exports.StatementProcedureCall = ProcedureCall.extend({
     },
     endParse: function(){
         ProcedureCall.prototype.endParse.call(this);
-        this.parent().codeGenerator().write(this.callExpression().code());
+        var e = this.callExpression();
+        if  (e.type())
+            throw new Errors.Error("procedure returning a result cannot be used as a statement");
+        this.parent().codeGenerator().write(e.code());
     }
 });
 

+ 24 - 45
src/procedure.js

@@ -167,6 +167,28 @@ var TwoArgToOperatorProcCallGenerator = ProcCallGenerator.extend({
 	}
 });
 
+function setBitImpl(name, op){
+    var args = [new Arg(Type.basic.set, true),
+                new Arg(Type.basic.int, false)];
+    function operator(x, y){
+        var code = op(Code.adjustPrecedence(x, precedence.assignment),
+                      Code.adjustPrecedence(y, precedence.shift));
+        return new Code.Expression(
+            code, undefined, undefined, undefined, precedence.assignment);
+    }
+    var proc = new ProcType(
+        "predefined procedure " + name,
+        args,
+        undefined,
+        function(context, id, type){
+            return new TwoArgToOperatorProcCallGenerator(
+                context, id, type, operator);
+            });
+    var type = new Type.Procedure(proc);
+    var symbol = new Type.Symbol(name, type);
+    return symbol;
+}
+
 function bitShiftImpl(name, op){
     var CallGenerator = ProcCallGenerator.extend({
         init: function SgiftProcCallGenerator(context, id, type){
@@ -304,51 +326,8 @@ exports.predefined = [
 		var symbol = new Type.Symbol("ASSERT", type);
 		return symbol;
 	}(),
-	function(){
-		var args = [new Arg(Type.basic.set, true),
-					new Arg(Type.basic.int, false)];
-		function operator(x, y){
-            var code = Code.adjustPrecedence(x, precedence.assignment) +
-                       " |= 1 << " +
-                       Code.adjustPrecedence(y, precedence.shift);
-            return new Code.Expression(
-                code, Type.basic.set, undefined, undefined, precedence.assignment);
-        }
-		var proc = new ProcType(
-			"predefined procedure INCL",
-			args,
-			undefined,
-			function(context, id, type){
-				return new TwoArgToOperatorProcCallGenerator(
-					context, id, type, operator);
-				});
-		var type = new Type.Procedure(proc);
-		var symbol = new Type.Symbol("INCL", type);
-		return symbol;
-	}(),
-	function(){
-		var args = [new Arg(Type.basic.set, true),
-					new Arg(Type.basic.int, false)];
-		function operator(x, y){
-            var code = Code.adjustPrecedence(x, precedence.assignment) +
-                       " &= ~(1 << " +
-                       Code.adjustPrecedence(y, precedence.shift) +
-                       ")";
-            return new Code.Expression(
-                code, Type.basic.set, undefined, undefined, precedence.assignment);
-        }
-		var proc = new ProcType(
-			"predefined procedure EXCL",
-			args,
-			undefined,
-			function(context, id, type){
-				return new TwoArgToOperatorProcCallGenerator(
-					context, id, type, operator);
-				});
-		var type = new Type.Procedure(proc);
-		var symbol = new Type.Symbol("EXCL", type);
-		return symbol;
-	}(),
+    setBitImpl("INCL", function(x, y){return x + " |= 1 << " + y;}),
+    setBitImpl("EXCL", function(x, y){return x + " &= ~(1 << " + y + ")";}),
     function(){
         var CallGenerator = ProcCallGenerator.extend({
             init: function AbsProcCallGenerator(context, id, type){

+ 3 - 2
test/expected/len.js

@@ -28,6 +28,7 @@ var s1 = "\"";
 var a1 = RTL$.makeArray(10, 0);
 var a2 = RTL$.makeArray(15, false);
 var a3 = RTL$.makeArray(20, 0);
+var i = 0;
 
 function p1(a/*ARRAY OF INTEGER*/){
 	return a.length;
@@ -36,8 +37,8 @@ function p1(a/*ARRAY OF INTEGER*/){
 function p2(a/*VAR ARRAY OF BOOLEAN*/){
 	return a.length;
 }
-p1(a1);
-p2(a2);
+i = p1(a1);
+i = p2(a2);
 RTL$.assert(a3.length == 20);
 RTL$.assert(s1.length == 1);
 RTL$.assert("abc".length == 3);

+ 3 - 2
test/input/len.ob

@@ -7,6 +7,7 @@ VAR
     a1: ARRAY 10 OF INTEGER;
     a2: ARRAY 15 OF BOOLEAN;
     a3: ARRAY 20 OF CHAR;
+	i: INTEGER;
 
 PROCEDURE p1(a: ARRAY OF INTEGER): INTEGER;
     RETURN LEN(a)
@@ -17,8 +18,8 @@ PROCEDURE p2(VAR a: ARRAY OF BOOLEAN): INTEGER;
 END p2;
 
 BEGIN
-	p1(a1);
-	p2(a2);
+	i := p1(a1);
+	i := p2(a2);
 	ASSERT(LEN(a3) = 20);
     ASSERT(LEN(s1) = 1);
     ASSERT(LEN("abc") = 3)

+ 47 - 47
test/test_unit.js

@@ -425,31 +425,31 @@ identifier: function(){
          ["i := ROR(i)", "2 argument(s) expected, got 1"]
          )
     ),
-"ODD": function(){
-    var test = setup(Grammar.statement);
-
-    test.parse("ODD(1)");
-    test.parse("ASSERT(ODD(123))");
-    test.expectError("ODD(1.2)", "type mismatch for argument 1: 'REAL' cannot be converted to 'INTEGER'");
-    test.expectError("ODD(TRUE)", "type mismatch for argument 1: 'BOOLEAN' cannot be converted to 'INTEGER'");
-},
-"ORD": function(){
-    var test = setupWithContext(Grammar.statement, "VAR ch: CHAR;");
-
-    test.parse("ORD(ch)");
-    test.parse("ORD(TRUE)");
-    test.parse("ORD({1})");
-    test.parse("ORD(\"a\")");
-    test.parse("ASSERT(ORD(22X) = 022H)");
-    test.expectError("ORD(1.2)", "type mismatch for argument 1: 'REAL' cannot be converted to 'CHAR or BOOLEAN or SET'");
-    test.expectError("ORD(\"abc\")", "type mismatch for argument 1: 'multi-character string' cannot be converted to 'CHAR or BOOLEAN or SET'");
-},
-"CHR": function(){
-    var test = setupWithContext(Grammar.statement, "VAR i: INTEGER; ch: CHAR;");
-
-    test.parse("CHR(i)");
-    //test.expectError("CHR(ch)", "type mismatch for argument 1: 'CHAR' cannot be converted to 'INTEGER'");
-},
+"ODD": testWithContext(
+    context(Grammar.statement, "VAR b: BOOLEAN;"),
+    pass("b := ODD(1)",
+         "b := ODD(123)"
+         ),
+    fail(["b := ODD(1.2)", "type mismatch for argument 1: 'REAL' cannot be converted to 'INTEGER'"],
+         ["b := ODD(TRUE)", "type mismatch for argument 1: 'BOOLEAN' cannot be converted to 'INTEGER'"]
+         )
+),
+"ORD": testWithContext(
+    context(Grammar.statement, "VAR ch: CHAR; i: INTEGER; b: BOOLEAN;"),
+    pass("i := ORD(ch)",
+         "i := ORD(TRUE)",
+         "i := ORD({1})",
+         "i := ORD(\"a\")",
+         "b := ORD(22X) = 022H"),
+    fail(["i := ORD(1.2)", "type mismatch for argument 1: 'REAL' cannot be converted to 'CHAR or BOOLEAN or SET'"],
+         ["i := ORD(\"abc\")", "type mismatch for argument 1: 'multi-character string' cannot be converted to 'CHAR or BOOLEAN or SET'"]
+         )
+),
+"CHR": testWithContext(
+    context(Grammar.statement, "VAR i: INTEGER; ch: CHAR;"),
+    pass("ch := CHR(i)"),
+    fail(["ch := CHR(ch)", "type mismatch for argument 1: 'CHAR' cannot be converted to 'INTEGER'"])
+),
 "assignment statement": function(){
     var test = setupWithContext(
           Grammar.statement
@@ -783,7 +783,7 @@ procedure: function(){
             "VAR i: INTEGER; PROCEDURE int(): INTEGER; RETURN 1 END int;"),
     pass("PROCEDURE p(): BOOLEAN; RETURN TRUE END p",
          "PROCEDURE p(): BOOLEAN; RETURN int() = 1 END p",
-         "PROCEDURE p; BEGIN END p",
+         "PROCEDURE p; BEGIN END p" ,
          "PROCEDURE p(): INTEGER; BEGIN RETURN 0 END p"),
     fail(["PROCEDURE p; RETURN TRUE END p", "unexpected RETURN in PROCEDURE declared with no result type"],
          ["PROCEDURE p(): BOOLEAN; END p", "RETURN expected at the end of PROCEDURE declared with 'BOOLEAN' result type"],
@@ -852,27 +852,27 @@ procedure: function(){
     test.expectError("PROCEDURE p(a: ARRAY OF T); BEGIN varInteger(a[0].i) END p",
                      "read-only variable cannot be used as VAR parameter");
 },
-"procedure call": function(){
-    var test = setupWithContext(Grammar.statement
-                              , "TYPE ProcType = PROCEDURE;"
-                              + "VAR notProcedure: INTEGER;"
-                              + "PROCEDURE p; END p;"
-                              + "PROCEDURE p1(i: INTEGER); END p1;"
-                              + "PROCEDURE p2(i: INTEGER; b: BOOLEAN); END p2;"
-                              + "PROCEDURE p3(): ProcType; RETURN p END p3;"
-                               );
-    test.parse("p");
-    test.parse("p()");
-
-    test.parse("p1(1)");
-    test.parse("p1(1 + 2)");
-
-    test.parse("p2(1, TRUE)");
-    test.expectError("notProcedure", "PROCEDURE expected, got 'INTEGER'");
-    test.expectError("p2(TRUE, 1)", "type mismatch for argument 1: 'BOOLEAN' cannot be converted to 'INTEGER'");
-    test.expectError("p2(1, 1)", "type mismatch for argument 2: 'INTEGER' cannot be converted to 'BOOLEAN'");
-    test.expectError("p3()()", "not parsed");
-},
+"procedure call": testWithContext(
+    context(Grammar.statement,
+            "TYPE ProcType = PROCEDURE;" +
+            "VAR notProcedure: INTEGER;" +
+            "PROCEDURE p; END p;" +
+            "PROCEDURE p1(i: INTEGER); END p1;" +
+            "PROCEDURE p2(i: INTEGER; b: BOOLEAN); END p2;" +
+            "PROCEDURE p3(): ProcType; RETURN p END p3;"),
+    pass("p",
+         "p()",
+         "p1(1)",
+         "p1(1 + 2)",
+         "p2(1, TRUE)"),
+    fail(["notProcedure", "PROCEDURE expected, got 'INTEGER'"],
+         ["p2(TRUE, 1)", "type mismatch for argument 1: 'BOOLEAN' cannot be converted to 'INTEGER'"],
+         ["p2(1, 1)", "type mismatch for argument 2: 'INTEGER' cannot be converted to 'BOOLEAN'"],
+         ["p()()", "not parsed"],
+         ["p3", "procedure returning a result cannot be used as a statement"],
+         ["p3()", "procedure returning a result cannot be used as a statement"]
+         )
+),
 "procedure assignment": function(){
     var test = setupWithContext(
           Grammar.statement