From 12e3a9baa7ced5bae73be1bc39fd6a0e6564c04e Mon Sep 17 00:00:00 2001 From: ik Date: Tue, 20 Oct 2015 12:56:05 -0700 Subject: [PATCH 1/7] Char base type changed to Number. --- .../Core/Classes/JSIL.StringEnumerator.js | 73 ++++++++ .../Bootstrap/Core/Classes/System.Char.js | 2 +- .../Core/Helpers/JSIL.GetEnumerator.js | 17 +- .../Includes/Bootstrap/Core/Main.js | 1 + .../Bootstrap/Text/Classes/System.Char.js | 30 ++-- .../Bootstrap/Text/Classes/System.String.js | 13 +- .../Text/Classes/System.Text.StringBuilder.js | 16 +- .../Text/Helpers/JSIL.ConcatString.js | 2 + .../Text/Helpers/JSIL.SplitString.js | 12 +- .../Text/Helpers/JSIL.StringFromCharArray.js | 11 +- JSIL.Libraries/JSIL.Libraries.csproj | 1 + JSIL.Libraries/Sources/JSIL.Core.js | 13 +- JSIL/FunctionTransformPipeline.cs | 12 -- JSIL/ILBlockTranslator.cs | 7 +- JSIL/JSIL.csproj | 1 - JSIL/JavascriptAstEmitter.cs | 4 +- JSIL/Transforms/ExpandCastExpressions.cs | 14 -- JSIL/Transforms/IntroduceCharCasts.cs | 137 --------------- Proxies/Char.cs | 11 +- Proxies/Console.cs | 162 +++++++++++++++++- Proxies/String.cs | 16 +- .../Issue118_1.fs | 0 .../Int64CharArithmetic_Issue867.cs | 11 ++ Tests/SimpleTests.csproj | 2 +- Tests/Tests.csproj | 1 + 25 files changed, 331 insertions(+), 238 deletions(-) create mode 100644 JSIL.Libraries/Includes/Bootstrap/Core/Classes/JSIL.StringEnumerator.js delete mode 100644 JSIL/Transforms/IntroduceCharCasts.cs rename Tests/{SimpleTestCases => FailingTestCases}/Issue118_1.fs (100%) create mode 100644 Tests/SimpleTestCases/Int64CharArithmetic_Issue867.cs diff --git a/JSIL.Libraries/Includes/Bootstrap/Core/Classes/JSIL.StringEnumerator.js b/JSIL.Libraries/Includes/Bootstrap/Core/Classes/JSIL.StringEnumerator.js new file mode 100644 index 000000000..1ee9f7e3f --- /dev/null +++ b/JSIL.Libraries/Includes/Bootstrap/Core/Classes/JSIL.StringEnumerator.js @@ -0,0 +1,73 @@ +JSIL.MakeClass("System.Object", "JSIL.StringEnumerator", true, ["T"], function ($) { + var T = new JSIL.GenericParameter("T", "JSIL.StringEnumerator"); + + $.RawMethod(false, "__CopyMembers__", + function ArrayEnumerator_CopyMembers(source, target) { + target._array = source._array; + target._length = source._length; + target._index = source._index; + } + ); + + $.Method({ Public: true, Static: false }, ".ctor", + new JSIL.MethodSignature(null, [$jsilcore.TypeRef("System.Array", ["!!0"]), $.Int32]), + function (array, startPosition) { + this._array = array; + this._length = array.length; + if (typeof (startPosition) !== "number") + JSIL.RuntimeError("ArrayEnumerator ctor second argument must be number"); + + this._index = startPosition; + } + ); + + $.Method({ Public: true, Static: false }, "Reset", + new JSIL.MethodSignature(null, []), + function () { + if (this._array === null) + JSIL.RuntimeError("Enumerator is disposed or not initialized"); + + this._index = -1; + } + ); + + $.Method({ Public: true, Static: false }, "MoveNext", + new JSIL.MethodSignature(System.Boolean, []), + function () { + return (++this._index < this._length); + } + ); + + $.Method({ Public: true, Static: false }, "Dispose", + new JSIL.MethodSignature(null, []), + function () { + this._array = null; + this._index = 0; + this._length = -1; + } + ); + + $.Method({ Public: false, Static: false }, null, + new JSIL.MethodSignature(System.Object, []), + function () { + return this._array.charCodeAt(this._index); + } + ) + .Overrides("System.Collections.IEnumerator", "get_Current"); + + $.Method({ Public: true, Static: false }, "get_Current", + new JSIL.MethodSignature(T, []), + function () { + return this._array.charCodeAt(this._index); + } + ) + .Overrides("System.Collections.Generic.IEnumerator`1", "get_Current"); + + $.Property({ Public: true, Static: false, Virtual: true }, "Current"); + + $.ImplementInterfaces( + /* 0 */ System.IDisposable, + /* 1 */ System.Collections.IEnumerator, + /* 2 */ $jsilcore.TypeRef("System.Collections.Generic.IEnumerator`1", [new JSIL.GenericParameter("T", "JSIL.StringEnumerator")]) + ); +}); \ No newline at end of file diff --git a/JSIL.Libraries/Includes/Bootstrap/Core/Classes/System.Char.js b/JSIL.Libraries/Includes/Bootstrap/Core/Classes/System.Char.js index da9ebd30f..0c0a1b236 100644 --- a/JSIL.Libraries/Includes/Bootstrap/Core/Classes/System.Char.js +++ b/JSIL.Libraries/Includes/Bootstrap/Core/Classes/System.Char.js @@ -1,7 +1,7 @@ JSIL.ImplementExternals( "System.Char", function ($) { $.RawMethod(true, "CheckType", function (value) { - return ((typeof (value) === "string") && (value.length == 1)) || JSIL.Box.IsBoxedOfType(value, $.Type); + return (typeof (value) === "number") || JSIL.Box.IsBoxedOfType(value, $.Type); }); $.Constant({ Public: true, Static: true }, "MaxValue", "\uffff"); diff --git a/JSIL.Libraries/Includes/Bootstrap/Core/Helpers/JSIL.GetEnumerator.js b/JSIL.Libraries/Includes/Bootstrap/Core/Helpers/JSIL.GetEnumerator.js index c7101162d..4f324f3f1 100644 --- a/JSIL.Libraries/Includes/Bootstrap/Core/Helpers/JSIL.GetEnumerator.js +++ b/JSIL.Libraries/Includes/Bootstrap/Core/Helpers/JSIL.GetEnumerator.js @@ -15,6 +15,21 @@ JSIL.MakeArrayEnumerator = function (array, elementType) { return new tArrayEnumerator(array, -1); }; +JSIL.MakeStringEnumerator = function (array, elementType) { + var tArrayEnumerator; + + if (!elementType) { + if ($jsilcore.$tArrayEnumerator === null) + $jsilcore.$tArrayEnumerator = JSIL.StringEnumerator.Of(System.Object); + + tArrayEnumerator = $jsilcore.$tArrayEnumerator; + } else { + tArrayEnumerator = JSIL.StringEnumerator.Of(elementType); + } + + return new tArrayEnumerator(array, -1); +}; + JSIL.GetEnumerator = function (enumerable, elementType, fallbackMethodInvoke) { if ((typeof (enumerable) === "undefined") || (enumerable === null)) JSIL.RuntimeError("Enumerable is null or undefined"); @@ -33,7 +48,7 @@ JSIL.GetEnumerator = function (enumerable, elementType, fallbackMethodInvoke) { else if (enumerable.__IsArray__) result = JSIL.MakeArrayEnumerator(enumerable.Items, elementType); else if (typeof (enumerable) === "string") - result = JSIL.MakeArrayEnumerator(enumerable, elementType); + result = JSIL.MakeStringEnumerator(enumerable, elementType); else if ((fallbackMethodInvoke !== true) && tIEnumerable$b1 && tIEnumerable$b1.$Is(enumerable)) result = tIEnumerable$b1.GetEnumerator.Call(enumerable); else if ((fallbackMethodInvoke !== true) && tIEnumerable.$Is(enumerable)) diff --git a/JSIL.Libraries/Includes/Bootstrap/Core/Main.js b/JSIL.Libraries/Includes/Bootstrap/Core/Main.js index 65f519cd5..5d0b80d81 100644 --- a/JSIL.Libraries/Includes/Bootstrap/Core/Main.js +++ b/JSIL.Libraries/Includes/Bootstrap/Core/Main.js @@ -23,6 +23,7 @@ JSIL.DeclareNamespace("System.Runtime.InteropServices"); //? include("Helpers/JSIL.MakeIConvertibleMethods.js"); writeln(); //? include("Classes/JSIL.ArrayEnumerator.js"); writeln(); +//? include("Classes/JSIL.StringEnumerator.js"); writeln(); //? include("Classes/System.Boolean.js"); writeln(); //? include("Classes/System.Char.js"); writeln(); diff --git a/JSIL.Libraries/Includes/Bootstrap/Text/Classes/System.Char.js b/JSIL.Libraries/Includes/Bootstrap/Text/Classes/System.Char.js index 36c4b4ee1..e9ba7ef4a 100644 --- a/JSIL.Libraries/Includes/Bootstrap/Text/Classes/System.Char.js +++ b/JSIL.Libraries/Includes/Bootstrap/Text/Classes/System.Char.js @@ -3,8 +3,7 @@ JSIL.ImplementExternals("System.Char", function ($) { new JSIL.MethodSignature($.Boolean, [$.Char], []), function IsControl(c) { // FIXME: Unicode - var charCode = c.charCodeAt(0); - return (charCode <= 0x1F) || (charCode === 0x7F); + return (c <= 0x1F) || (c === 0x7F); } ); @@ -12,8 +11,7 @@ JSIL.ImplementExternals("System.Char", function ($) { new JSIL.MethodSignature($.Boolean, [$.Char], []), function IsDigit(c) { // FIXME: Unicode - var charCode = c.charCodeAt(0); - return (charCode >= 48) && (charCode <= 57); + return (c >= 48) && (c <= 57); } ); @@ -21,10 +19,9 @@ JSIL.ImplementExternals("System.Char", function ($) { new JSIL.MethodSignature($.Boolean, [$.Char], []), function IsLetter(c) { // FIXME: Unicode - var charCode = c.charCodeAt(0); return ( - ((charCode >= 65) && (charCode <= 90)) || - ((charCode >= 97) && (charCode <= 122))); + ((c >= 65) && (c <= 90)) || + ((c >= 97) && (c <= 122))); } ); @@ -32,8 +29,7 @@ JSIL.ImplementExternals("System.Char", function ($) { new JSIL.MethodSignature($.Boolean, [$.Char], []), function IsNumeric(c) { // FIXME: Unicode - var charCode = c.charCodeAt(0); - return (charCode >= 48) && (charCode <= 57); + return (c >= 48) && (c <= 57); } ); @@ -47,8 +43,7 @@ JSIL.ImplementExternals("System.Char", function ($) { $.Method({ Static: true, Public: true }, "IsSurrogate", new JSIL.MethodSignature($.Boolean, [$.Char], []), function IsSurrogate(c) { - var charCode = c.charCodeAt(0); - return (charCode >= 0xD800) && (charCode <= 0xDFFF); + return (c >= 0xD800) && (c <= 0xDFFF); } ); @@ -56,26 +51,25 @@ JSIL.ImplementExternals("System.Char", function ($) { new JSIL.MethodSignature($.Boolean, [$.Char], []), function IsWhiteSpace(c) { // FIXME: Unicode - var charCode = c.charCodeAt(0); return ( - ((charCode >= 0x09) && (charCode <= 0x13)) || - (charCode === 0x20) || - (charCode === 0xA0) || - (charCode === 0x85)); + ((c >= 0x09) && (c <= 0x13)) || + (c === 0x20) || + (c === 0xA0) || + (c === 0x85)); } ); $.Method({ Static: true, Public: true }, "ToLowerInvariant", new JSIL.MethodSignature($.Char, [$.Char], []), function ToLowerInvariant(c) { - return c.toLowerCase(); + return String.fromCharCode(c).toLowerCase().charCodeAt(0); } ); $.Method({ Static: true, Public: true }, "ToUpperInvariant", new JSIL.MethodSignature($.Char, [$.Char], []), function ToLowerInvariant(c) { - return c.toUpperCase(); + return String.fromCharCode(c).toUpperCase().charCodeAt(0); } ); diff --git a/JSIL.Libraries/Includes/Bootstrap/Text/Classes/System.String.js b/JSIL.Libraries/Includes/Bootstrap/Text/Classes/System.String.js index a05577df8..151d3b0c3 100644 --- a/JSIL.Libraries/Includes/Bootstrap/Text/Classes/System.String.js +++ b/JSIL.Libraries/Includes/Bootstrap/Text/Classes/System.String.js @@ -36,9 +36,10 @@ JSIL.ImplementExternals( $.Method({ Static: false, Public: true }, ".ctor", new JSIL.MethodSignature(null, ["System.Char", "System.Int32"], [], $jsilcore), function (ch, length) { + var symbol = String.fromCharCode(ch); var arr = new Array(length); for (var i = 0; i < length; i++) - arr[i] = ch; + arr[i] = symbol; return new String(arr.join("")); } @@ -151,7 +152,7 @@ JSIL.ImplementExternals( function (str, chars, startIndex) { var result = null; for (var i = startIndex || 0; i < chars.length; i++) { - var index = str.indexOf(chars[i]); + var index = str.indexOf(String.fromCharCode(chars[i])); if ((result === null) || (index < result)) result = index; } @@ -198,7 +199,7 @@ JSIL.ImplementExternals( function (str, chars) { var result = null; for (var i = 0; i < chars.length; i++) { - var index = str.lastIndexOf(chars[i]); + var index = str.lastIndexOf(String.fromCharCode(chars[i])); if ((result === null) || (index > result)) result = index; } @@ -247,7 +248,7 @@ JSIL.ImplementExternals( if (extraChars <= 0) return str; - return makePadding(ch, extraChars) + str; + return makePadding(String.fromCharCode(ch), extraChars) + str; } ); @@ -258,7 +259,7 @@ JSIL.ImplementExternals( if (extraChars <= 0) return str; - return str + makePadding(ch, extraChars); + return str + makePadding(String.fromCharCode(ch), extraChars); } ); @@ -267,7 +268,7 @@ JSIL.ImplementExternals( function (str, sourceIndex, destination, destinationIndex, count) { if (count > 0) { for (var i = 0; i < count; i++) - destination[destinationIndex + i] = str[sourceIndex + i]; + destination[destinationIndex + i] = str.charCodeAt(sourceIndex + i); } } ); diff --git a/JSIL.Libraries/Includes/Bootstrap/Text/Classes/System.Text.StringBuilder.js b/JSIL.Libraries/Includes/Bootstrap/Text/Classes/System.Text.StringBuilder.js index 7584d3d9f..5b930f7df 100644 --- a/JSIL.Libraries/Includes/Bootstrap/Text/Classes/System.Text.StringBuilder.js +++ b/JSIL.Libraries/Includes/Bootstrap/Text/Classes/System.Text.StringBuilder.js @@ -63,7 +63,7 @@ JSIL.ImplementExternals("System.Text.StringBuilder", function ($) { $.Method({ Static: false, Public: true }, "Append", (new JSIL.MethodSignature($.Type, [$.Char, $.Int32], [])), function Append(value, repeatCount) { - appendString(this, value, 0, value.length, repeatCount); + appendString(this, String.fromCharCode(value), 0, 1, repeatCount); } ); @@ -74,7 +74,7 @@ JSIL.ImplementExternals("System.Text.StringBuilder", function ($) { ], [])), function Append(value, startIndex, charCount) { for (var i = 0; i < charCount; i++) - this._str += value[startIndex + i]; + this._str += String.fromCharCode(value[startIndex + i]); this._capacity = Math.max(this._capacity, this._str.length); } @@ -130,7 +130,7 @@ JSIL.ImplementExternals("System.Text.StringBuilder", function ($) { $.Method({ Static: false, Public: true }, "Append", (new JSIL.MethodSignature($.Type, [$.Char], [])), function Append(value) { - appendString(this, value, 0, value.length, 1); + appendString(this, String.fromCharCode(value), 0, 1, 1); } ); @@ -194,7 +194,7 @@ JSIL.ImplementExternals("System.Text.StringBuilder", function ($) { (new JSIL.MethodSignature($.Type, [$jsilcore.TypeRef("System.Array", [$.Char])], [])), function Append(value) { for (var i = 0; i < value.length; i++) - this._str += value[i]; + this._str += String.fromCharCode(value[i]); this._capacity = Math.max(this._capacity, this._str.length); } @@ -322,7 +322,7 @@ JSIL.ImplementExternals("System.Text.StringBuilder", function ($) { $.Method({ Static: false, Public: true }, "Replace", (new JSIL.MethodSignature($.Type, [$.Char, $.Char], [])), function Replace(oldChar, newChar) { - return replace(this, oldChar, newChar, 0, this._str.length); + return replace(this, String.fromCharCode(oldChar), String.fromCharCode(newChar), 0, this._str.length); } ); @@ -332,7 +332,7 @@ JSIL.ImplementExternals("System.Text.StringBuilder", function ($) { $.Int32, $.Int32 ], [])), function Replace(oldChar, newChar, startIndex, count) { - return replace(this, oldChar, newChar, startIndex, count); + return replace(this, String.fromCharCode(oldChar), String.fromCharCode(newChar), startIndex, count); } ); @@ -385,7 +385,7 @@ JSIL.ImplementExternals("System.Text.StringBuilder", function ($) { $.Method({ Static: false, Public: true }, "get_Chars", (new JSIL.MethodSignature($.Char, [$.Int32], [])), function get_Chars(i) { - return this._str[i]; + return this._str.charCodeAt(i); } ); @@ -397,7 +397,7 @@ JSIL.ImplementExternals("System.Text.StringBuilder", function ($) { } this._str = this._str.substr(0, i) + - value + + String.fromCharCode(value) + this._str.substr(i + 1); } ); diff --git a/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.ConcatString.js b/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.ConcatString.js index 1af3232ad..f081a92aa 100644 --- a/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.ConcatString.js +++ b/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.ConcatString.js @@ -10,6 +10,8 @@ JSIL.ConcatString = function (/* ...values */) { ; else if (typeof (arg) === "string") result += arg; + else if ($jsilcore.System.Char.$Is(arg)) + result += String.fromCharCode(arg.valueOf()); else result += String(arg); } diff --git a/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.SplitString.js b/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.SplitString.js index 99cb54ba9..a4400c9f8 100644 --- a/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.SplitString.js +++ b/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.SplitString.js @@ -5,22 +5,22 @@ JSIL.SplitString = function (str, separators, options) { if (!separators) { // Whitespace characters from Unicode 6.0 separators = [ - "\u0009", "\u000A", "\u000B", "\u000C", "\u000D", "\u0020", "\u0085", "\u00A0", - "\u1680", "\u180E", "\u2000", "\u2001", "\u2002", "\u2003", "\u2004", "\u2005", - "\u2006", "\u2007", "\u2008", "\u2009", "\u200A", "\u2028", "\u2029", "\u202F", - "\u205F", "\u3000" + 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x0020, 0x0085, 0x00A0, + 0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, + 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x2028, 0x2029, 0x202F, + 0x205F, 0x3000 ]; } if (separators.length === 1) { - return str.split(separators[0]); + return str.split(String.fromCharCode(separators[0])); } else { var regexText = ""; for (var i = 0; i < separators.length; i++) { if (i > 0) regexText += "|" - regexText += JSIL.EscapeJSRegex(separators[i]); + regexText += JSIL.EscapeJSRegex(String.fromCharCode(separators[i])); } var regex = new RegExp(regexText, "g"); diff --git a/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.StringFromCharArray.js b/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.StringFromCharArray.js index a6f942d34..9adefbec4 100644 --- a/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.StringFromCharArray.js +++ b/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.StringFromCharArray.js @@ -1,13 +1,14 @@ JSIL.StringFromCharArray = function (chars, startIndex, length) { + var result = ""; + if (arguments.length < 2) startIndex = 0; if (arguments.length < 3) length = chars.length; - if (arguments.length > 1) { - var arr = chars.slice(startIndex, startIndex + length); - return arr.join(""); - } else { - return chars.join(""); + for (var i = startIndex; i < length - startIndex; i++) { + result += String.fromCharCode(chars[i]); } + + return result; }; \ No newline at end of file diff --git a/JSIL.Libraries/JSIL.Libraries.csproj b/JSIL.Libraries/JSIL.Libraries.csproj index 6677acd65..f96cd5edd 100644 --- a/JSIL.Libraries/JSIL.Libraries.csproj +++ b/JSIL.Libraries/JSIL.Libraries.csproj @@ -36,6 +36,7 @@ 4 + diff --git a/JSIL.Libraries/Sources/JSIL.Core.js b/JSIL.Libraries/Sources/JSIL.Core.js index 86e871ce9..1602d7d61 100644 --- a/JSIL.Libraries/Sources/JSIL.Core.js +++ b/JSIL.Libraries/Sources/JSIL.Core.js @@ -9225,9 +9225,7 @@ JSIL.ApplyCollectionInitializer = function (target, values) { JSIL.DefaultValueInternal = function (typeObject, typePublicInterface) { var fullName = typeObject.__FullName__; - if (fullName === "System.Char") { - return "\0"; - } else if (fullName === "System.Boolean") { + if (fullName === "System.Boolean") { return false; } else if (typeObject.__IsReferenceType__) { return null; @@ -9604,7 +9602,7 @@ JSIL.StringToCharArray = function (text) { var result = JSIL.Array.New(System.Char, text.length); for (var i = 0, l = text.length; i < l; i++) - result[i] = text[i]; + result[i] = text.charCodeAt(i); return result; }; @@ -10734,14 +10732,15 @@ JSIL.$FormatStringImpl = function (format, values) { if (alignment || valueFormat) { return JSIL.NumberToFormattedString(value.valueOf(), alignment, valueFormat); - } else { - - if (JSIL.GetType(value) === $jsilcore.System.Boolean.__Type__) { + var type = JSIL.GetType(value); + if (type === $jsilcore.System.Boolean.__Type__) { if (value.valueOf()) return "True"; else return "False"; + } else if (type === $jsilcore.System.Char.__Type__) { + return String.fromCharCode(value.valueOf()); } else if (value === null) { return ""; } else { diff --git a/JSIL/FunctionTransformPipeline.cs b/JSIL/FunctionTransformPipeline.cs index 83c651dad..c51c12023 100644 --- a/JSIL/FunctionTransformPipeline.cs +++ b/JSIL/FunctionTransformPipeline.cs @@ -218,8 +218,6 @@ private void FillPipeline () { Enqueue(HandleBooleanAsInteger); - Enqueue(IntroduceCharCasts); - Enqueue(IntroduceEnumCasts); Enqueue(ExpandCastExpressions); @@ -402,16 +400,6 @@ private bool IntroduceEnumCasts () { return true; } - private bool IntroduceCharCasts () { - if (Configuration.CodeGenerator.IntroduceCharCasts.GetValueOrDefault(true)) { - new IntroduceCharCasts( - TypeSystem, SpecialIdentifiers.JS - ).Visit(Function); - } - - return true; - } - private bool HandleBooleanAsInteger () { new HandleBooleanAsInteger( TypeSystem, SpecialIdentifiers.JS diff --git a/JSIL/ILBlockTranslator.cs b/JSIL/ILBlockTranslator.cs index 1afa71240..9ebf76c87 100644 --- a/JSIL/ILBlockTranslator.cs +++ b/JSIL/ILBlockTranslator.cs @@ -3022,12 +3022,7 @@ protected JSExpression Translate_Conv (ILExpression node, TypeReference targetTy var valueType = value.GetActualType(TypeSystem); if ( - !TypeUtil.TypesAreAssignable(TypeInfo, targetType, valueType) || - // HACK: Compensate for char not being assignable to int - ( - (targetType.FullName == "System.Char") || - (valueType.FullName == "System.Char") - ) + !TypeUtil.TypesAreAssignable(TypeInfo, targetType, valueType) ) value = Translate_Conv(value, targetType); diff --git a/JSIL/JSIL.csproj b/JSIL/JSIL.csproj index 0be506ef6..4a4ac0f56 100644 --- a/JSIL/JSIL.csproj +++ b/JSIL/JSIL.csproj @@ -105,7 +105,6 @@ - diff --git a/JSIL/JavascriptAstEmitter.cs b/JSIL/JavascriptAstEmitter.cs index b1550c48e..8666b6c72 100644 --- a/JSIL/JavascriptAstEmitter.cs +++ b/JSIL/JavascriptAstEmitter.cs @@ -913,7 +913,7 @@ public void VisitNode (JSRawOutputIdentifier identifier) { } public void VisitNode (JSCharLiteral ch) { - Output.Value(ch.Value); + Output.Value((ushort)(ch.Value)); } public void VisitNode (JSStringLiteral str) { @@ -1148,7 +1148,7 @@ public void VisitNode (JSDefaultValueLiteral defaultValue) { Output.Value(0.0); break; case "System.Char": - Output.Value("\0"); + Output.Value(0); break; case "System.Boolean": Output.WriteRaw("false"); diff --git a/JSIL/Transforms/ExpandCastExpressions.cs b/JSIL/Transforms/ExpandCastExpressions.cs index 8cdf33f9f..7f9435477 100644 --- a/JSIL/Transforms/ExpandCastExpressions.cs +++ b/JSIL/Transforms/ExpandCastExpressions.cs @@ -42,20 +42,6 @@ public void VisitNode (JSCastExpression ce) { ParentNode.ReplaceChild(ce, replacement); VisitReplacement(replacement); return; - } else if ( - TypeUtil.IsIntegralOrEnum(currentType) && - (targetType.MetadataType == MetadataType.Char) - ) { - newExpression = JSInvocationExpression.InvokeStatic( - JS.fromCharCode, new[] { ce.Expression }, true - ); - } else if ( - (currentType.MetadataType == MetadataType.Char) && - TypeUtil.IsIntegral(targetType) - ) { - newExpression = JSInvocationExpression.InvokeMethod( - JS.charCodeAt, ce.Expression, new[] { JSLiteral.New(0) }, true - ); } else if ( IntroduceEnumCasts.IsEnumOrNullableEnum(currentType) ) { diff --git a/JSIL/Transforms/IntroduceCharCasts.cs b/JSIL/Transforms/IntroduceCharCasts.cs deleted file mode 100644 index 4a4d44b00..000000000 --- a/JSIL/Transforms/IntroduceCharCasts.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using ICSharpCode.Decompiler.ILAst; -using JSIL.Ast; -using JSIL.Internal; -using Mono.Cecil; - -namespace JSIL.Transforms { - public class IntroduceCharCasts : JSAstVisitor { - public readonly TypeSystem TypeSystem; - public readonly JSSpecialIdentifiers JS; - - public IntroduceCharCasts (TypeSystem typeSystem, JSSpecialIdentifiers js) { - TypeSystem = typeSystem; - JS = js; - } - - protected JSInvocationExpression CastToChar (JSExpression integerExpression) { - return JSInvocationExpression.InvokeStatic( - JS.fromCharCode, new[] { integerExpression }, true - ); - } - - protected JSInvocationExpression CastToInteger (JSExpression charExpression) { - return JSInvocationExpression.InvokeMethod( - JS.charCodeAt, charExpression, new[] { JSLiteral.New(0) }, true - ); - } - - public void VisitNode (JSBinaryOperatorExpression boe) { - var leftType = boe.Left.GetActualType(TypeSystem); - var rightType = boe.Right.GetActualType(TypeSystem); - - bool isArithmetic = !(boe.Operator is JSAssignmentOperator); - - if (!isArithmetic && boe.Operator != JSOperator.Assignment && leftType.FullName == "System.Char") - { - JSBinaryOperator newOperator; - if (boe.Operator == JSOperator.AddAssignment) - { - newOperator = JSOperator.Add; - } - else if (boe.Operator == JSOperator.BitwiseAndAssignment) - { - newOperator = JSOperator.BitwiseAnd; - } - else if (boe.Operator == JSOperator.BitwiseOrAssignment) - { - newOperator = JSOperator.BitwiseOr; - } - else if (boe.Operator == JSOperator.BitwiseXorAssignment) - { - newOperator = JSOperator.BitwiseXor; - } - else if (boe.Operator == JSOperator.DivideAssignment) - { - newOperator = JSOperator.Divide; - } - else if (boe.Operator == JSOperator.MultiplyAssignment) - { - newOperator = JSOperator.Multiply; - } - else if (boe.Operator == JSOperator.RemainderAssignment) - { - newOperator = JSOperator.Remainder; - } - else if (boe.Operator == JSOperator.ShiftLeftAssignment) - { - newOperator = JSOperator.ShiftLeft; - } - else if (boe.Operator == JSOperator.ShiftRightAssignment) - { - newOperator = JSOperator.ShiftRight; - } - else if (boe.Operator == JSOperator.ShiftRightUnsignedAssignment) - { - newOperator = JSOperator.ShiftRightUnsigned; - } - else if (boe.Operator == JSOperator.SubtractAssignment) - { - newOperator = JSOperator.Subtract; - } - else - { - throw new InvalidOperationException("Unknown assigment operator"); - } - - var newBoe = new JSBinaryOperatorExpression(JSOperator.Assignment, boe.Left, - new JSBinaryOperatorExpression(newOperator, boe.Left, boe.Right, boe.ActualType), boe.ActualType); - ParentNode.ReplaceChild(boe, newBoe); - VisitReplacement(newBoe); - return; - } - - if (boe.Operator == JSOperator.Assignment && (leftType.FullName == "System.Char") && (rightType.FullName != "System.Char")) - { - boe.ReplaceChild(boe.Right, CastToChar(boe.Right)); - } - if (boe.Operator == JSOperator.Assignment && (leftType.FullName != "System.Char") && (rightType.FullName == "System.Char")) - { - boe.ReplaceChild(boe.Right, CastToInteger(boe.Right)); - } - - if ((leftType.FullName == "System.Char") && isArithmetic) - boe.ReplaceChild(boe.Left, CastToInteger(boe.Left)); - - if ((rightType.FullName == "System.Char") && isArithmetic) - boe.ReplaceChild(boe.Right, CastToInteger(boe.Right)); - - var parentInvocation = ParentNode as JSInvocationExpression; - JSDotExpressionBase parentInvocationDot = (parentInvocation != null) ? parentInvocation.Method as JSDotExpressionBase : null; - - if ( - isArithmetic && - (boe.GetActualType(TypeSystem).FullName == "System.Char") && - !( - (parentInvocation != null) && - (parentInvocationDot != null) && - (parentInvocationDot.Target is JSStringIdentifier) && - (((JSStringIdentifier)parentInvocationDot.Target).Identifier == "String") && - (parentInvocationDot.Member is JSFakeMethod) && - (((JSFakeMethod)parentInvocationDot.Member).Name == "fromCharCode") - ) - ) { - var castBoe = CastToChar(boe); - ParentNode.ReplaceChild(boe, castBoe); - - VisitReplacement(castBoe); - } else { - VisitChildren(boe); - } - } - } -} diff --git a/Proxies/Char.cs b/Proxies/Char.cs index ea8bcff7d..b0fed50d1 100644 --- a/Proxies/Char.cs +++ b/Proxies/Char.cs @@ -12,30 +12,33 @@ namespace JSIL.Proxies { JSProxyMemberPolicy.ReplaceDeclared )] public abstract class CharProxy { - [JSReplacement("$c.toLowerCase()")] + [JSReplacement("String.fromCharCode($c).toLowerCase().charCodeAt(0)")] [JSIsPure] public static char ToLower (char c) { throw new InvalidOperationException(); } // FIXME: Are ECMAScript strings always normalized? - [JSReplacement("$c.toLowerCase()")] + [JSReplacement("String.fromCharCode($c).toLowerCase().charCodeAt(0)")] [JSIsPure] public static char ToLowerInvariant (char c) { throw new InvalidOperationException(); } - [JSReplacement("$c.toUpperCase()")] + [JSReplacement("String.fromCharCode($c).toUpperCase().charCodeAt(0)")] [JSIsPure] public static char ToUpper (char c) { throw new InvalidOperationException(); } // FIXME: Are ECMAScript strings always normalized? - [JSReplacement("$c.toUpperCase()")] + [JSReplacement("String.fromCharCode($c).toUpperCase().charCodeAt(0)")] [JSIsPure] public static char ToUpperInvariant (char c) { throw new InvalidOperationException(); } + + [JSReplacement("String.fromCharCode($this)")] + new abstract public string ToString(); } } diff --git a/Proxies/Console.cs b/Proxies/Console.cs index c5aa650a7..4509312d1 100644 --- a/Proxies/Console.cs +++ b/Proxies/Console.cs @@ -8,11 +8,171 @@ namespace JSIL.Proxies { memberPolicy: JSProxyMemberPolicy.ReplaceDeclared )] public abstract class ConsoleProxy { + [JSReplacement("$typeof(this).__PublicInterface__.WriteLine(String.fromCharCode($arg))")] + public static void WriteLine(char arg) + { + throw new InvalidOperationException(); + } + + [JSRuntimeDispatch] + [JSExternal] + [JSMutatedArguments()] + [JSEscapingArguments()] + public static void WriteLine() + { + throw new InvalidOperationException(); + } + + [JSRuntimeDispatch] + [JSExternal] + [JSMutatedArguments()] + [JSEscapingArguments()] + public static void WriteLine(bool value) + { + throw new InvalidOperationException(); + } + + [JSRuntimeDispatch] + [JSExternal] + [JSMutatedArguments()] + [JSEscapingArguments()] + public static void WriteLine(char[] value) + { + throw new InvalidOperationException(); + } + + [JSRuntimeDispatch] + [JSExternal] + [JSMutatedArguments()] + [JSEscapingArguments()] + public static void WriteLine(char[] buffer, int index, int count) + { + throw new InvalidOperationException(); + } + + [JSRuntimeDispatch] + [JSExternal] + [JSMutatedArguments()] + [JSEscapingArguments()] + public static void WriteLine(decimal value) + { + throw new InvalidOperationException(); + } + + [JSRuntimeDispatch] + [JSExternal] + [JSMutatedArguments()] + [JSEscapingArguments()] + public static void WriteLine(double value) + { + throw new InvalidOperationException(); + } + + [JSRuntimeDispatch] + [JSExternal] + [JSMutatedArguments()] + [JSEscapingArguments()] + public static void WriteLine(float value) + { + throw new InvalidOperationException(); + } + + [JSRuntimeDispatch] + [JSExternal] + [JSMutatedArguments()] + [JSEscapingArguments()] + public static void WriteLine(int value) + { + throw new InvalidOperationException(); + } + + [JSRuntimeDispatch] + [JSExternal] + [JSMutatedArguments()] + [JSEscapingArguments()] + public static void WriteLine(uint value) + { + throw new InvalidOperationException(); + } + + [JSRuntimeDispatch] + [JSExternal] + [JSMutatedArguments()] + [JSEscapingArguments()] + public static void WriteLine(long value) + { + throw new InvalidOperationException(); + } + + [JSRuntimeDispatch] + [JSExternal] + [JSMutatedArguments()] + [JSEscapingArguments()] + public static void WriteLine(ulong value) + { + throw new InvalidOperationException(); + } + + [JSRuntimeDispatch] + [JSExternal] + [JSMutatedArguments()] + [JSEscapingArguments()] + public static void WriteLine(object value) + { + throw new InvalidOperationException(); + } + + [JSRuntimeDispatch] + [JSExternal] + [JSMutatedArguments()] + [JSEscapingArguments()] + public static void WriteLine(string value) + { + throw new InvalidOperationException(); + } + + [JSRuntimeDispatch] + [JSExternal] + [JSMutatedArguments()] + [JSEscapingArguments()] + public static void WriteLine(string format, object arg0) + { + throw new InvalidOperationException(); + } + + [JSRuntimeDispatch] + [JSExternal] + [JSMutatedArguments()] + [JSEscapingArguments()] + public static void WriteLine(string format, object arg0, object arg1) + { + throw new InvalidOperationException(); + } + + [JSRuntimeDispatch] + [JSExternal] + [JSMutatedArguments()] + [JSEscapingArguments()] + public static void WriteLine(string format, object arg0, object arg1, object arg2) + { + throw new InvalidOperationException(); + } + + [JSRuntimeDispatch] + [JSExternal] + [JSMutatedArguments()] + [JSEscapingArguments()] + public static void WriteLine(string format, object arg0, object arg1, object arg2, object arg3, __arglist) + { + throw new InvalidOperationException(); + } + [JSRuntimeDispatch] [JSExternal] [JSMutatedArguments()] [JSEscapingArguments()] - public static void WriteLine (params AnyType[] arguments) { + public static void WriteLine(string format, params object[] arg) + { throw new InvalidOperationException(); } diff --git a/Proxies/String.cs b/Proxies/String.cs index 70618e258..13b003c9e 100644 --- a/Proxies/String.cs +++ b/Proxies/String.cs @@ -73,7 +73,7 @@ public static string Concat (string a, string b, string c, string d) { throw new InvalidOperationException(); } - [JSReplacement("$lhs + $ch")] + [JSReplacement("$lhs + String.fromCharCode($ch)")] [JSIsPure] public static string Concat (string lhs, char ch) { throw new InvalidOperationException(); @@ -104,7 +104,7 @@ public static string Join (string separator, params string[] values) { [JSNeverReplace] abstract public int Length { get; } - [JSReplacement("$this[$index]")] + [JSReplacement("$this.charCodeAt($index)")] [JSIsPure] abstract public char get_Chars (int index); @@ -183,13 +183,13 @@ public int CompareTo (string rhs) { throw new InvalidOperationException(); } - [JSReplacement("$this.indexOf($value)")] + [JSReplacement("$this.indexOf(String.fromCharCode($value))")] [JSIsPure] public int IndexOf (char value) { throw new InvalidOperationException(); } - [JSReplacement("$this.indexOf($value, $startIndex)")] + [JSReplacement("$this.indexOf(String.fromCharCode($value), $startIndex)")] [JSIsPure] public int IndexOf (char value, int startIndex) { throw new InvalidOperationException(); @@ -207,7 +207,7 @@ public int IndexOf (string value, int startIndex) { throw new InvalidOperationException(); } - [JSReplacement("$this.lastIndexOf($value)")] + [JSReplacement("$this.lastIndexOf(String.fromCharCode($value))")] [JSIsPure] public int LastIndexOf (char value) { throw new InvalidOperationException(); @@ -271,7 +271,7 @@ public string Replace (string oldText, string newText) { throw new InvalidOperationException(); } - [JSReplacement("System.String.Replace($this, $oldChar, $newChar)")] + [JSReplacement("System.String.Replace($this, String.fromCharCode($oldChar), String.fromCharCode($newChar))")] [JSIsPure] public string Replace (char oldChar, char newChar) { throw new InvalidOperationException(); @@ -288,13 +288,13 @@ public bool Contains (string p) { throw new InvalidOperationException(); } - [JSReplacement("System.String.PadLeft($this, $length, ' ')")] + [JSReplacement("System.String.PadLeft($this, $length, 32)")] [JSIsPure] public string PadLeft (int length) { throw new InvalidOperationException(); } - [JSReplacement("System.String.PadRight($this, $length, ' ')")] + [JSReplacement("System.String.PadRight($this, $length, 32)")] [JSIsPure] public string PadRight (int length) { throw new InvalidOperationException(); diff --git a/Tests/SimpleTestCases/Issue118_1.fs b/Tests/FailingTestCases/Issue118_1.fs similarity index 100% rename from Tests/SimpleTestCases/Issue118_1.fs rename to Tests/FailingTestCases/Issue118_1.fs diff --git a/Tests/SimpleTestCases/Int64CharArithmetic_Issue867.cs b/Tests/SimpleTestCases/Int64CharArithmetic_Issue867.cs new file mode 100644 index 000000000..20f630538 --- /dev/null +++ b/Tests/SimpleTestCases/Int64CharArithmetic_Issue867.cs @@ -0,0 +1,11 @@ +using System; + +public static class Program +{ + public static void Main() + { + int l = 48; + string s = "2"; + Console.WriteLine(s[0] + l); + } +} \ No newline at end of file diff --git a/Tests/SimpleTests.csproj b/Tests/SimpleTests.csproj index f09458115..5a085b3bf 100644 --- a/Tests/SimpleTests.csproj +++ b/Tests/SimpleTests.csproj @@ -137,6 +137,7 @@ + @@ -338,7 +339,6 @@ - diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 233363e14..67498fc24 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -272,6 +272,7 @@ + From c1a2caa9974448205a60335d55bc69ed67bee988 Mon Sep 17 00:00:00 2001 From: ik Date: Tue, 20 Oct 2015 19:02:35 -0700 Subject: [PATCH 2/7] JSIL.ConcatString fixed. --- .../Includes/Bootstrap/Text/Helpers/JSIL.ConcatString.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.ConcatString.js b/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.ConcatString.js index f081a92aa..232bf90cf 100644 --- a/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.ConcatString.js +++ b/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.ConcatString.js @@ -10,7 +10,7 @@ JSIL.ConcatString = function (/* ...values */) { ; else if (typeof (arg) === "string") result += arg; - else if ($jsilcore.System.Char.$Is(arg)) + else if ($jsilcore.JSIL.Box.IsBoxedOfType(arg, $jsilcore.System.Char)) result += String.fromCharCode(arg.valueOf()); else result += String(arg); From 6b15238face589befc4815ce3ecb706106d9d4ae Mon Sep 17 00:00:00 2001 From: ik Date: Tue, 20 Oct 2015 19:19:18 -0700 Subject: [PATCH 3/7] JSIL.StringFromCharArray fixed. --- .../Bootstrap/Text/Helpers/JSIL.StringFromCharArray.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.StringFromCharArray.js b/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.StringFromCharArray.js index 9adefbec4..cad5ac67e 100644 --- a/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.StringFromCharArray.js +++ b/JSIL.Libraries/Includes/Bootstrap/Text/Helpers/JSIL.StringFromCharArray.js @@ -6,8 +6,8 @@ JSIL.StringFromCharArray = function (chars, startIndex, length) { if (arguments.length < 3) length = chars.length; - for (var i = startIndex; i < length - startIndex; i++) { - result += String.fromCharCode(chars[i]); + for (var i = 0; i < length; i++) { + result += String.fromCharCode(chars[startIndex + i]); } return result; From ed1cfb7633d713b7106015cb46f8896ffd16c8fc Mon Sep 17 00:00:00 2001 From: ik Date: Thu, 22 Oct 2015 17:26:02 -0700 Subject: [PATCH 4/7] Int64 -> Char cast. --- JSIL/Transforms/ExpandCastExpressions.cs | 5 +++-- JSIL/TypeUtil.cs | 5 +++++ Tests/SimpleTestCases/Int64CharCast.cs | 18 ++++++++++++++++++ Tests/SimpleTests.csproj | 1 + 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 Tests/SimpleTestCases/Int64CharCast.cs diff --git a/JSIL/Transforms/ExpandCastExpressions.cs b/JSIL/Transforms/ExpandCastExpressions.cs index 7f9435477..b9486aaf0 100644 --- a/JSIL/Transforms/ExpandCastExpressions.cs +++ b/JSIL/Transforms/ExpandCastExpressions.cs @@ -231,7 +231,7 @@ private JSExpression[] GetInt64ConversionArgs(TypeReference targetType) if (targetType == TypeSystem.Byte || targetType == TypeSystem.SByte) mask = 0xff; - if (targetType == TypeSystem.Int16 || targetType == TypeSystem.UInt16) + if (targetType == TypeSystem.Int16 || targetType == TypeSystem.UInt16 || targetType == TypeSystem.Char) mask = 0xffff; if (targetType == TypeSystem.Int32 || targetType == TypeSystem.UInt32) @@ -240,7 +240,8 @@ private JSExpression[] GetInt64ConversionArgs(TypeReference targetType) var signed = targetType == TypeSystem.SByte || targetType == TypeSystem.Int16 || - targetType == TypeSystem.Int32; + targetType == TypeSystem.Int32 || + targetType == TypeSystem.Char; return new[] { new JSNumberLiteral(mask ?? -1, typeof(double)) as JSExpression, diff --git a/JSIL/TypeUtil.cs b/JSIL/TypeUtil.cs index c9f82be5e..e856de5b3 100644 --- a/JSIL/TypeUtil.cs +++ b/JSIL/TypeUtil.cs @@ -142,6 +142,7 @@ public static bool IsNumeric (TypeReference type) { type = DereferenceType(type); switch (type.MetadataType) { + case MetadataType.Char: case MetadataType.Byte: case MetadataType.SByte: case MetadataType.Double: @@ -180,6 +181,7 @@ public static bool IsNumeric (TypeReference type) { case MetadataType.UInt32: case MetadataType.UInt64: case MetadataType.UIntPtr: + case MetadataType.Char: return false; default: { @@ -196,6 +198,7 @@ public static bool IsIntegral (TypeReference type) { type = DereferenceType(type); switch (type.MetadataType) { + case MetadataType.Char: case MetadataType.Byte: case MetadataType.SByte: case MetadataType.Int16: @@ -224,6 +227,7 @@ public static bool Is32BitIntegral (TypeReference type) { case MetadataType.Int16: case MetadataType.UInt32: case MetadataType.Int32: + case MetadataType.Char: return true; default: return IsNativeInteger(type); @@ -243,6 +247,7 @@ public static int SizeOfType (TypeReference type) { case MetadataType.UInt16: case MetadataType.Int16: + case MetadataType.Char: return 2; case MetadataType.UInt32: diff --git a/Tests/SimpleTestCases/Int64CharCast.cs b/Tests/SimpleTestCases/Int64CharCast.cs new file mode 100644 index 000000000..e9edf82d7 --- /dev/null +++ b/Tests/SimpleTestCases/Int64CharCast.cs @@ -0,0 +1,18 @@ +using System; + +public static class Program { + public static void Main (string[] args) + { + DoIt((char)(GetIt() + 5)); + } + + public static void DoIt(char input) + { + Console.WriteLine(input); + } + + public static long GetIt() + { + return 10; + } +} \ No newline at end of file diff --git a/Tests/SimpleTests.csproj b/Tests/SimpleTests.csproj index 5a085b3bf..7f2866b75 100644 --- a/Tests/SimpleTests.csproj +++ b/Tests/SimpleTests.csproj @@ -138,6 +138,7 @@ + From d44cb010913cf12a1c2eb7cb03740c0bb31ec176 Mon Sep 17 00:00:00 2001 From: Igor Kiselev Date: Wed, 16 Dec 2015 11:53:34 -0800 Subject: [PATCH 5/7] Fixed rebase problems with char. --- JSIL.Libraries/Includes/Bootstrap/Core/Classes/System.Char.js | 2 +- JSIL.Libraries/Includes/Bootstrap/Text/Classes/System.Char.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/JSIL.Libraries/Includes/Bootstrap/Core/Classes/System.Char.js b/JSIL.Libraries/Includes/Bootstrap/Core/Classes/System.Char.js index 0c0a1b236..d392193c4 100644 --- a/JSIL.Libraries/Includes/Bootstrap/Core/Classes/System.Char.js +++ b/JSIL.Libraries/Includes/Bootstrap/Core/Classes/System.Char.js @@ -8,4 +8,4 @@ $.Constant({ Public: true, Static: true }, "MinValue", "\0"); } ); -JSIL.MakeNumericType(String, "System.Char", true, null, JSIL.MakeIConvertibleMethods); \ No newline at end of file +JSIL.MakeNumericType(Number, "System.Char", true, null, JSIL.MakeIConvertibleMethods); \ No newline at end of file diff --git a/JSIL.Libraries/Includes/Bootstrap/Text/Classes/System.Char.js b/JSIL.Libraries/Includes/Bootstrap/Text/Classes/System.Char.js index e9ba7ef4a..614de7f50 100644 --- a/JSIL.Libraries/Includes/Bootstrap/Text/Classes/System.Char.js +++ b/JSIL.Libraries/Includes/Bootstrap/Text/Classes/System.Char.js @@ -76,7 +76,7 @@ JSIL.ImplementExternals("System.Char", function ($) { $.Method({ Static: true, Public: true }, "ToString", new JSIL.MethodSignature($.String, [$.Char], []), function ToString(c) { - return c; + return String.fromCharCode(c); } ); }); \ No newline at end of file From 7a8a2ccfc7539bccdb9368bf137e80fee293f551 Mon Sep 17 00:00:00 2001 From: Igor Kiselev Date: Thu, 17 Dec 2015 13:26:02 -0800 Subject: [PATCH 6/7] Implemented special processing for ToString. --- JSIL.Libraries/Sources/JSIL.Core.js | 7 +++++++ Proxies/Object.cs | 1 + Tests/{FailingTestCases => SimpleTestCases}/Issue118_1.fs | 0 Tests/SimpleTests.csproj | 1 + Tests/Tests.csproj | 1 - 5 files changed, 9 insertions(+), 1 deletion(-) rename Tests/{FailingTestCases => SimpleTestCases}/Issue118_1.fs (100%) diff --git a/JSIL.Libraries/Sources/JSIL.Core.js b/JSIL.Libraries/Sources/JSIL.Core.js index 1602d7d61..2e365b79c 100644 --- a/JSIL.Libraries/Sources/JSIL.Core.js +++ b/JSIL.Libraries/Sources/JSIL.Core.js @@ -6320,6 +6320,13 @@ JSIL.GetTypeName = function (type, dotNetTypeToString) { return result; }; +JSIL.ToString = function(value, type) { + if (typeof (value) == "number" && type.__TypeId__ === $jsilcore.System.Char.__TypeId__) { + return String.fromCharCode(value); + } + return value.toString(); +} + JSIL.Coalesce = function (lhs, rhs) { if (lhs == null) return rhs; diff --git a/Proxies/Object.cs b/Proxies/Object.cs index fd3925e73..d6f5c77f9 100644 --- a/Proxies/Object.cs +++ b/Proxies/Object.cs @@ -21,6 +21,7 @@ public abstract class ObjectProxy new abstract public AnyType MemberwiseClone (); [JSChangeName("toString")] + [JSReplacement("JSIL.ToString($this, $typeof(this))")] [JSNeverReplace] [JSRuntimeDispatch] new abstract public string ToString (); diff --git a/Tests/FailingTestCases/Issue118_1.fs b/Tests/SimpleTestCases/Issue118_1.fs similarity index 100% rename from Tests/FailingTestCases/Issue118_1.fs rename to Tests/SimpleTestCases/Issue118_1.fs diff --git a/Tests/SimpleTests.csproj b/Tests/SimpleTests.csproj index 7f2866b75..6893aa659 100644 --- a/Tests/SimpleTests.csproj +++ b/Tests/SimpleTests.csproj @@ -340,6 +340,7 @@ + diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 67498fc24..233363e14 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -272,7 +272,6 @@ - From 842573b2369ac3f8bf1e77f0ea8752d79363c0d6 Mon Sep 17 00:00:00 2001 From: Igor Kiselev Date: Tue, 22 Dec 2015 14:08:42 -0800 Subject: [PATCH 7/7] JSReplacement doesn't affect output translation. JSSuppressOutput introduced. --- JSIL/AssemblyTranslator.cs | 34 ++++++++----------- JSIL/JavascriptAssemblyEmitter.cs | 4 +-- JSIL/TypeInformation.cs | 15 +++++++- Meta | 2 +- Tests/MetadataTests.cs | 21 ++++++++++++ .../SpecialTestCases/SuppressOutputMethod.cs | 26 ++++++++++++++ Tests/Tests.csproj | 1 + 7 files changed, 80 insertions(+), 23 deletions(-) create mode 100644 Tests/SpecialTestCases/SuppressOutputMethod.cs diff --git a/JSIL/AssemblyTranslator.cs b/JSIL/AssemblyTranslator.cs index 39d571053..80104e387 100644 --- a/JSIL/AssemblyTranslator.cs +++ b/JSIL/AssemblyTranslator.cs @@ -1225,9 +1225,9 @@ ref int nextDisambiguatedId foreach (var method in methodsToTranslate) { var mi = TypeInfoProvider.GetMemberInformation(method); - bool isExternal, b, c; + bool isExternal, c; if (!ShouldTranslateMethodBody( - method, mi, stubbed, out isExternal, out b, out c + method, mi, stubbed, out isExternal, out c )) continue; @@ -1357,6 +1357,7 @@ internal JSFunctionExpression TranslateMethodExpression ( bool skip = ShouldSkipMember(method) || methodInfo.IsExternal || + methodInfo.IsSuppressOutput || methodInfo.IsAbstract; if (skip) { @@ -1597,7 +1598,7 @@ protected JSExpression TranslateField ( return null; var fieldInfo = TypeInfoProvider.GetMemberInformation(field); - if ((fieldInfo == null) || fieldInfo.IsIgnored || fieldInfo.IsExternal) + if ((fieldInfo == null) || fieldInfo.IsIgnored || fieldInfo.IsExternal || fieldInfo.IsSuppressOutput) return null; var dollarIdentifier = new JSRawOutputIdentifier(field.DeclaringType, dollar.Format, dollar.Arguments); @@ -1724,12 +1725,12 @@ where f.IsStatic (from f in staticFields where NeedsStaticConstructor(f.FieldType) let fi = TypeInfoProvider.GetField(f) - where ((fi != null) && (!fi.IsExternal && !fi.IsIgnored)) || (fi == null) + where ((fi != null) && (!fi.IsExternal && !fi.IsIgnored && !fi.IsSuppressOutput)) || (fi == null) select f).ToArray(); var fieldsToStrip = new HashSet(from f in staticFields let fi = TypeInfoProvider.GetField(f) - where (fi != null) && (fi.IsExternal || fi.IsIgnored) + where (fi != null) && (fi.IsExternal || fi.IsIgnored || fi.IsSuppressOutput) select f); // For fields with values assigned non-dynamically by the static constructor, we want to pull those values @@ -1926,7 +1927,7 @@ where NeedsStaticConstructor(f.FieldType) foreach (var f in typedef.Fields) { var fi = TypeInfoProvider.GetField(f); - if ((fi != null) && (fi.IsIgnored || fi.IsExternal)) + if ((fi != null) && (fi.IsIgnored || fi.IsExternal || fi.IsSuppressOutput)) continue; doTranslateField(f); @@ -2000,38 +2001,33 @@ where NeedsStaticConstructor(f.FieldType) protected void CreateMethodInformation ( MethodInfo methodInfo, bool stubbed, - out bool isExternal, out bool isJSReplaced, - out bool methodIsProxied + out bool isExternal, out bool methodIsProxied ) { - isJSReplaced = methodInfo.Metadata.HasAttribute("JSIL.Meta.JSReplacement"); methodIsProxied = (methodInfo.IsFromProxy && methodInfo.Member.HasBody) && - !methodInfo.IsExternal && !isJSReplaced; + !methodInfo.IsExternal && !methodInfo.IsMarkedWithJSReplacement && !methodInfo.IsSuppressOutput; isExternal = methodInfo.IsExternal || (stubbed && !methodInfo.IsUnstubbable); } internal bool ShouldTranslateMethodBody ( MethodDefinition method, MethodInfo methodInfo, bool stubbed, - out bool isExternal, out bool isJSReplaced, + out bool isExternal, out bool methodIsProxied ) { if (methodInfo == null) { - isExternal = isJSReplaced = methodIsProxied = false; + isExternal = methodIsProxied = false; return false; } CreateMethodInformation( methodInfo, stubbed, - out isExternal, out isJSReplaced, out methodIsProxied + out isExternal, out methodIsProxied ); if (ShouldSkipMember(method)) return false; if (isExternal) { - if (isJSReplaced) - return false; - var isProperty = methodInfo.DeclaringProperty != null; if (isProperty && methodInfo.DeclaringProperty.IsExternal) @@ -2043,7 +2039,7 @@ out bool methodIsProxied } } - if (methodInfo.IsIgnored) + if (methodInfo.IsIgnored || methodInfo.IsSuppressOutput) return false; if (!method.HasBody && !isExternal && !methodIsProxied) return false; @@ -2088,11 +2084,11 @@ protected void EmitMethodBody ( if (methodInfo == null) methodInfo = TypeInfoProvider.GetMemberInformation(method); - bool isExternal, isReplaced, methodIsProxied; + bool isExternal, methodIsProxied; if (!ShouldTranslateMethodBody( method, methodInfo, stubbed, - out isExternal, out isReplaced, out methodIsProxied + out isExternal, out methodIsProxied )) return; diff --git a/JSIL/JavascriptAssemblyEmitter.cs b/JSIL/JavascriptAssemblyEmitter.cs index 469f47463..707d2bb3a 100644 --- a/JSIL/JavascriptAssemblyEmitter.cs +++ b/JSIL/JavascriptAssemblyEmitter.cs @@ -404,11 +404,11 @@ public void EmitMethodDefinition ( if (methodInfo == null) methodInfo = TypeInfo.GetMemberInformation(method); - bool isExternal, isReplaced, methodIsProxied; + bool isExternal, methodIsProxied; if (!Translator.ShouldTranslateMethodBody( method, methodInfo, stubbed, - out isExternal, out isReplaced, out methodIsProxied + out isExternal, out methodIsProxied )) return; diff --git a/JSIL/TypeInformation.cs b/JSIL/TypeInformation.cs index f04376965..4d9af5023 100644 --- a/JSIL/TypeInformation.cs +++ b/JSIL/TypeInformation.cs @@ -1531,8 +1531,10 @@ public abstract class MemberInfo : IMemberInfo public readonly ProxyInfo SourceProxy; public readonly T Member; public readonly MetadataCollection Metadata; + public readonly bool IsMarkedWithJSReplacement; public readonly bool IsExternal; public readonly bool IsFromProxy; + protected readonly bool _IsSuppressOutput; protected readonly bool _IsIgnored; protected readonly bool _IsUnstubbable; protected readonly JSReadPolicy _ReadPolicy; @@ -1576,9 +1578,15 @@ protected MemberInfo ( if (Metadata.HasAttribute("JSIL.Meta.JSIgnore")) _IsIgnored = true; - if (Metadata.HasAttribute("JSIL.Meta.JSExternal") || Metadata.HasAttribute("JSIL.Meta.JSReplacement")) + if (Metadata.HasAttribute("JSIL.Meta.JSExternal")) IsExternal = true; + if (Metadata.HasAttribute("JSIL.Meta.JSSuppressOutput")) + _IsSuppressOutput = true; + + if (Metadata.HasAttribute("JSIL.Meta.JSReplacement")) + IsMarkedWithJSReplacement = true; + if (Metadata.HasAttribute("JSIL.Meta.JSNeverStub")) { _IsUnstubbable = true; IsExternal = false; @@ -1679,6 +1687,11 @@ public virtual bool IsIgnored { } } + public virtual bool IsSuppressOutput + { + get { return IsIgnored || _IsSuppressOutput; } + } + public virtual string ChangedName { get { var parms = Metadata.GetAttributeParameters("JSIL.Meta.JSChangeName"); diff --git a/Meta b/Meta index 7ab12f0b0..aa219ace8 160000 --- a/Meta +++ b/Meta @@ -1 +1 @@ -Subproject commit 7ab12f0b00b837f7e71ddec7b578225bd4b680db +Subproject commit aa219ace825ca9448c4d5494293ad210655a6584 diff --git a/Tests/MetadataTests.cs b/Tests/MetadataTests.cs index 09b13bd98..6e9c99a73 100644 --- a/Tests/MetadataTests.cs +++ b/Tests/MetadataTests.cs @@ -212,6 +212,27 @@ public void StubbedAssembliesDoNotGenerateMethodBodies () { } } + [Test] + public void JSSuppressOutputMethod() + { + var generatedJs = GenericTest( + @"SpecialTestCases\SuppressOutputMethod.cs", + "Foo", + "Excpetion in instance.Foo()" + ); + + try + { + Assert.IsTrue(generatedJs.Contains("instance.Foo()")); + Assert.IsFalse(generatedJs.Contains("\"Foo\"")); + } + catch + { + Console.WriteLine(generatedJs); + throw; + } + } + [Test] public void RenameMethod () { var generatedJs = GenericTest( diff --git a/Tests/SpecialTestCases/SuppressOutputMethod.cs b/Tests/SpecialTestCases/SuppressOutputMethod.cs new file mode 100644 index 000000000..9acd4a027 --- /dev/null +++ b/Tests/SpecialTestCases/SuppressOutputMethod.cs @@ -0,0 +1,26 @@ +using System; +using JSIL.Meta; + +public static class Program +{ + public static void Main(string[] args) + { + var instance = new Test(); + try + { + instance.Foo(); + } + catch (Exception e) + { + Console.WriteLine("Excpetion in instance.Foo()"); + } + + } +} + +public class Test { + [JSSuppressOutput] + public void Foo () { + Console.WriteLine("Foo"); + } +} \ No newline at end of file diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 233363e14..e3681f7b0 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -293,6 +293,7 @@ +