Răsfoiți Sursa

assign strings to ARRAY OF CHAR

Vladislav Folts 12 ani în urmă
părinte
comite
693a373473
9 a modificat fișierele cu 86 adăugiri și 18 ștergeri
  1. 21 7
      src/context.js
  2. 14 2
      src/rtl.js
  3. 3 2
      src/type.js
  4. 1 2
      test/expected/array.js
  5. 30 0
      test/expected/string.js
  6. 1 2
      test/expected/var_parameter.js
  7. 5 1
      test/input/string.ob
  8. 0 2
      test/test.cmd
  9. 11 0
      test/test_unit.js

+ 21 - 7
src/context.js

@@ -195,9 +195,9 @@ exports.Designator = ChainedContext.extend({
 		var type = this.__currentType;
 		if (!(type instanceof Type.Array))
 			throw new Errors.Error("ARRAY expected, got '" + type.name() + "'");
-		if (value !== undefined && value >= type.arraySize())
+		if (value !== undefined && value >= type.length())
 			throw new Errors.Error("index out of bounds: maximum possible index is "
-								 + (type.arraySize() - 1)
+								 + (type.length() - 1)
 								 + ", got " + value );
 		this.__currentType = type.elementsType();
 		this.__info = new Type.Variable(this.__currentType, false, this.__info.isReadOnly());
@@ -1222,7 +1222,9 @@ exports.Assignment = ChainedContext.extend({
 		this.__designator = undefined;
 		this.__leftOp = undefined;
 		this.__type = undefined;
+		this.__code = new Code.SimpleGenerator();
 	},
+	codeGenerator: function(){return this.__code;},
 	setDesignator: function(d){
 		this.__designator = d;
 	},
@@ -1233,19 +1235,31 @@ exports.Assignment = ChainedContext.extend({
 			throw new Errors.Error("cannot assign to " + d_info.idType());
 		this.__leftOp = d.code();
 		this.__type = d.type();
-		this.codeGenerator().write(this.__leftOp + (d_info.isVar() ? ".set(" : " = "));
+		if (!(this.__type instanceof Type.Array))
+			this.__code.write(this.__leftOp + (d_info.isVar() ? ".set(" : " = "));
 	},
 	handleExpression: function(type, value, designator){
-		if (!Cast.implicit(type, this.__type))
+		if (type instanceof Type.String
+			&& this.__type instanceof Type.Array
+			&& this.__type.elementsType() == basicTypes.char){
+			if (type.length() > this.__type.length())
+				throw new Errors.Error(
+					this.__type.length() + "-character ARRAY is too small for " 
+					+ type.length() + "-character string");
+			this.__code = new Code.SimpleGenerator(
+				this.rtl().assignArrayFromString(this.__leftOp, this.__code.result()));
+		}
+		else if (!Cast.implicit(type, this.__type))
 			throw new Errors.Error("type mismatch: '" + this.__leftOp
 								 + "' is '" + this.__type.description()
 								 + "' and cannot be assigned to '" + type.description() + "' expression");
-		if (designator)
-			writeDerefDesignatorCode(designator, this.codeGenerator());
+		else if (designator)
+			writeDerefDesignatorCode(designator, this.__code);
 	},
 	endParse: function(){
 		if (this.__designator.info().isVar())
-			this.codeGenerator().write(")");
+			this.__code.write(")");
+		this.parent().codeGenerator().write(this.__code.result());
 	}
 });
 

+ 14 - 2
src/rtl.js

@@ -31,10 +31,9 @@ function RTLMakeArray(/*dimensions, initializer*/){
 				result[i] = init;
 	}
 	else
-		for(i = 0; i < result.length; ++i){
+		for(i = 0; i < result.length; ++i)
 			result[i] = RTLMakeArray.apply(this, forward);
 	return result;
-	}
 }
 
 function RTLMakeSet(/*...*/){
@@ -79,6 +78,14 @@ function RTLSetInclR(l, r){
 	return l & r == r;
 }
 
+function RTLAssignArrayFromString(a, s){
+	var i;
+	for(i = 0; i < s.length; ++i)
+		a[i] = s.charCodeAt(i);
+	for(i = s.length; i < a.length; ++i)
+		a[i] = 0;
+}
+
 exports.Class = Class;
 exports.RTL = Class.extend({
 	init: function RTL(){
@@ -122,6 +129,11 @@ exports.RTL = Class.extend({
 			this.__entries.setInclR = RTLSetInclR;
 		return "RTL$.setInclR(" + args + ")";
 	},
+	assignArrayFromString: function(a, s){
+		if (!this.__entries.assignArrayFromString)
+			this.__entries.assignArrayFromString = RTLAssignArrayFromString;
+		return "RTL$.assignArrayFromString(" + a + ", " + s + ")";
+	},
 	generate: function(){
 		var result = "var RTL$ = {\n";
 		var firstEntry = true;

+ 3 - 2
src/type.js

@@ -23,7 +23,8 @@ exports.String = Type.extend({
 	idType: function(){return "string";},
 	description: function(){return (this.__s.length == 1 ? "single-" : "multi-") + "character string";},
 	value: function(){return this.__s;},
-	asChar: function (){return this.__s.length == 1 ? this.__s.charCodeAt(0) : undefined;}
+	asChar: function(){return this.__s.length == 1 ? this.__s.charCodeAt(0) : undefined;},
+	length: function(){return this.__s.length;}
 });
 
 var BasicType = Type.extend({
@@ -46,7 +47,7 @@ exports.Array = BasicType.extend({
 		this.__size = size;
 	},
 	elementsType: function(){return this.__elementsType;},
-	arraySize: function(){return this.__size;}
+	length: function(){return this.__size;}
 });
 
 exports.Pointer = BasicType.extend({

+ 1 - 2
test/expected/array.js

@@ -13,10 +13,9 @@ var RTL$ = {
 					result[i] = init;
 		}
 		else
-			for(i = 0; i < result.length; ++i){
+			for(i = 0; i < result.length; ++i)
 				result[i] = RTLMakeArray.apply(this, forward);
 		return result;
-		}
 	},
 	extend: function extend(methods){
 		methods.__proto__ = this.prototype; // make instanceof work

+ 30 - 0
test/expected/string.js

@@ -1,5 +1,35 @@
+var RTL$ = {
+	makeArray: function RTLMakeArray(/*dimensions, initializer*/){
+		var forward = Array.prototype.slice.call(arguments);
+		var result = new Array(forward.shift());
+		var i;
+		if (forward.length == 1){
+			var init = forward[0];
+			if (typeof init == "function")
+				for(i = 0; i < result.length; ++i)
+					result[i] = init();
+			else
+				for(i = 0; i < result.length; ++i)
+					result[i] = init;
+		}
+		else
+			for(i = 0; i < result.length; ++i)
+				result[i] = RTLMakeArray.apply(this, forward);
+		return result;
+	},
+	assignArrayFromString: function RTLAssignArrayFromString(a, s){
+		var i;
+		for(i = 0; i < s.length; ++i)
+			a[i] = s.charCodeAt(i);
+		for(i = s.length; i < a.length; ++i)
+			a[i] = 0;
+	}
+};
 var m = function (){
 var s1 = "\"";
 var s2 = "ABC";
 var s3 = "with space";
+var a2 = RTL$.makeArray(3, 0);
+RTL$.assignArrayFromString(a2, "\"");
+RTL$.assignArrayFromString(a2, "ABC");
 }();

+ 1 - 2
test/expected/var_parameter.js

@@ -24,10 +24,9 @@ var RTL$ = {
 					result[i] = init;
 		}
 		else
-			for(i = 0; i < result.length; ++i){
+			for(i = 0; i < result.length; ++i)
 				result[i] = RTLMakeArray.apply(this, forward);
 		return result;
-		}
 	},
 	makeRef: function RTLMakeRef(obj, prop){
 	    return {set: function(v){ obj[prop] = v; },

+ 5 - 1
test/input/string.ob

@@ -4,5 +4,9 @@ CONST
 	s1 = 22X;
 	s2 = "ABC";
 	s3 = "with space";
-
+VAR
+	a2: ARRAY 3 OF CHAR;
+BEGIN
+	a2 := s1;
+	a2 := s2
 END m.

+ 0 - 2
test/test.cmd

@@ -1,2 +0,0 @@
-SET NODE_PATH=%~dp0../src
-"C:\Program Files\nodejs\node.exe" test.js

+ 11 - 0
test/test_unit.js

@@ -754,6 +754,17 @@ procedure: function(){
 	test.expectError("v10 := v11", "type mismatch: 'v10' is 'ProcType6' and cannot be assigned to 'ProcType7' expression" );
 	test.expectError("v8 := v8VAR", "type mismatch: 'v8' is 'ProcType4' and cannot be assigned to 'ProcType4VAR' expression" );
 },
+"string assignment": function(){
+	var test = setupWithContext(
+		  Grammar.statement
+		, "VAR a1: ARRAY 3 OF CHAR;"
+		);
+	test.parse("a1 := \"abc\"");
+	test.parse("a1 := \"ab\"");
+	test.parse("a1 := \"a\"");
+	test.parse("a1 := 22X");
+	test.expectError("a1 := \"abcd\"", "3-character ARRAY is too small for 4-character string");
+},
 "scope": function(){
 	var test = setup(Grammar.declarationSequence);
 	test.parse("PROCEDURE p1(a1: INTEGER); END p1; PROCEDURE p2(a1: BOOLEAN); END p2;");