Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

30178 clr.CompileModules fails for in-line dictionary initialization …

…that uses tuples as values

30165 cannot create weak reference to old class, generator, possibly others.
30153 set union of set union raises NullReferenceException
30130 IronPython doesn't deliver traceback frames with exception event when tracing is enabled
30129 sys.settrace throws an exception when called on non-top most frame
28223 ',' is now a valid float format specifier

Also fixing a broken test which isn't recognizing RC version number
And fixing regression on last checkin related to formatting hex numbers
  • Loading branch information...
commit ecacc53fb9574f18a999508437c99d00234e0790 1 parent c380579
DinoV authored
View
2  Languages/IronPython/IronPython/Compiler/Ast/ConstantExpression.cs
@@ -94,7 +94,7 @@ public class ConstantExpression : Expression, IInstructionProvider {
internal override string CheckAssign() {
if (_value == null) {
- return "assignment to None";
+ return "cannot assign to None";
}
return "can't assign to literal";
View
7 Languages/IronPython/IronPython/Compiler/Ast/TupleExpression.cs
@@ -18,7 +18,9 @@
using Microsoft.Scripting;
using Microsoft.Scripting.Runtime;
+using IronPython.Runtime;
using IronPython.Runtime.Binding;
+using IronPython.Runtime.Operations;
#if !CLR2
using MSAst = System.Linq.Expressions;
@@ -29,7 +31,6 @@
namespace IronPython.Compiler.Ast {
using Ast = MSAst.Expression;
- using IronPython.Runtime.Operations;
public class TupleExpression : SequenceExpression {
private bool _expandable;
@@ -108,6 +109,10 @@ public TupleExpression(bool expandable, params Expression[] items)
}
internal override object GetConstantValue() {
+ if (Items.Count == 0) {
+ return PythonTuple.EMPTY;
+ }
+
object[] items = new object[Items.Count];
for (int i = 0; i < items.Length; i++) {
items[i] = Items[i].GetConstantValue();
View
17 Languages/IronPython/IronPython/Runtime/Exceptions/TraceBack.cs
@@ -46,7 +46,7 @@ public class TraceBack {
}
}
- public object tb_frame {
+ public TraceBackFrame tb_frame {
get {
return _frame;
}
@@ -232,8 +232,12 @@ public class TraceBackFrame {
private void SetLineNumber(int newLineNum) {
var pyThread = PythonOps.GetFunctionStackNoCreate();
- if (!TracingThisFrame(pyThread)) {
- throw PythonOps.ValueError("f_lineno can only be set by a trace function");
+ if (!IsTopMostFrame(pyThread)) {
+ if (!TracingThisFrame(pyThread)) {
+ throw PythonOps.ValueError("f_lineno can only be set by a trace function");
+ } else {
+ return;
+ }
}
FunctionCode funcCode = _debugProperties.Code;
@@ -296,7 +300,12 @@ public class TraceBackFrame {
}
private bool TracingThisFrame(List<FunctionStack> pyThread) {
- return pyThread != null && pyThread.Count != 0 && Type.ReferenceEquals(this, pyThread[pyThread.Count - 1].Frame);
+ return pyThread != null &&
+ pyThread.FindIndex(x => x.Frame == this) != -1;
+ }
+
+ private bool IsTopMostFrame(List<FunctionStack> pyThread) {
+ return pyThread != null && pyThread.Count != 0 && Type.ReferenceEquals(this, pyThread[pyThread.Count - 1].Frame);
}
private static Exception BadForOrFinallyJump(int newLineNum, Dictionary<int, bool> jumpIntoLoopIds) {
View
20 Languages/IronPython/IronPython/Runtime/Generator.cs
@@ -30,7 +30,7 @@
namespace IronPython.Runtime {
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix"), PythonType("generator")]
[DontMapIDisposableToContextManager, DontMapIEnumerableToContains]
- public sealed class PythonGenerator : IEnumerator, IEnumerator<object>, ICodeFormattable, IEnumerable {
+ public sealed class PythonGenerator : IEnumerator, IEnumerator<object>, ICodeFormattable, IEnumerable, IWeakReferenceable {
private readonly Func<MutableTuple, object>/*!*/ _next; // The delegate which contains the user code to perform the iteration.
private readonly PythonFunction _function; // the function which created the generator
private readonly MutableTuple _data; // the closure data we need to pass into each iteration. Item000 is the index, Item001 is the current value
@@ -63,6 +63,7 @@ public sealed class PythonGenerator : IEnumerator, IEnumerator<object>, ICodeFor
/// Since send() could send an exception, we need to keep this different from throwable's value.
/// </summary>
private object _sendValue;
+ private WeakRefTracker _tracker;
internal PythonGenerator(PythonFunction function, Func<MutableTuple, object>/*!*/ next, MutableTuple data) {
_function = function;
@@ -620,5 +621,22 @@ class GeneratorFinalizer {
}
#endregion
+
+ #region IWeakReferenceable Members
+
+ WeakRefTracker IWeakReferenceable.GetWeakRef() {
+ return _tracker;
+ }
+
+ bool IWeakReferenceable.SetWeakRef(WeakRefTracker value) {
+ _tracker = value;
+ return true;
+ }
+
+ void IWeakReferenceable.SetFinalizer(WeakRefTracker value) {
+ _tracker = value;
+ }
+
+ #endregion
}
}
View
2  Languages/IronPython/IronPython/Runtime/Operations/FloatOps.cs
@@ -793,7 +793,7 @@ public static partial class DoubleOps {
return spec.AlignNumericText(digits, false, Double.IsNaN(self) || Sign(self) > 0);
} else {
// Always pass isZero=false so that -0.0 shows up
- return spec.AlignNumericText(digits, false, Sign(self) > 0);
+ return spec.AlignNumericText(digits, false, Double.IsNaN(self) ? true : Sign(self) > 0);
}
}
View
2  Languages/IronPython/IronPython/Runtime/Operations/ObjectOps.cs
@@ -253,6 +253,8 @@ public static class ObjectOps {
throw PythonOps.ValueError("Sign not allowed in string format specifier");
} else if (spec.Alignment == '=') {
throw PythonOps.ValueError("'=' alignment not allowed in string format specifier");
+ } else if (spec.ThousandsComma) {
+ throw PythonOps.ValueError("Cannot specify ',' with 's'.");
}
// apply precision to shorten the string first
View
5 Languages/IronPython/IronPython/Runtime/Operations/PythonOps.cs
@@ -2246,7 +2246,8 @@ public static partial class PythonOps {
context,
context.GlobalDict,
context.Dict,
- code);
+ code,
+ tb != null ? tb.tb_frame : null);
tb = new TraceBack(tb, tbf);
tb.SetLine(frame.GetFileLineNumber());
@@ -4375,7 +4376,7 @@ public static partial class PythonOps {
if (pyFrames == null) {
e.SetFrameList(pyFrames = new List<DynamicStackFrame>());
}
-
+
var frame = new PythonDynamicStackFrame(context, funcCode, line);
funcCode.LightThrowCompile(context);
pyFrames.Add(frame);
View
2  Languages/IronPython/IronPython/Runtime/PythonTracebackListener.cs
@@ -161,7 +161,7 @@ internal sealed class PythonTracebackListener : Debugging.ITraceCallback {
traceEvent = "exception";
object pyException = PythonExceptions.ToPython((Exception)payload);
object pyType = ((IPythonObject)pyException).PythonType;
- args = PythonTuple.MakeTuple(pyType, pyException, null);
+ args = PythonTuple.MakeTuple(pyType, pyException, new TraceBack(null, pyFrame));
break;
case Debugging.TraceEventKind.FrameExit:
traceEvent = "return";
View
30 Languages/IronPython/IronPython/Runtime/PythonTuple.cs
@@ -24,20 +24,28 @@
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Utils;
+using IronPython.Compiler.Ast;
+
using IronPython.Runtime.Exceptions;
using IronPython.Runtime.Operations;
using IronPython.Runtime.Types;
#if CLR2
using Microsoft.Scripting.Math;
+using MSAst = Microsoft.Scripting.Ast;
#else
using System.Numerics;
+using MSAst = System.Linq.Expressions;
#endif
+using Utils = Microsoft.Scripting.Ast.Utils;
+
namespace IronPython.Runtime {
+ using Ast = MSAst.Expression;
+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
[PythonType("tuple"), Serializable, DebuggerTypeProxy(typeof(CollectionDebugProxy)), DebuggerDisplay("tuple, {Count} items")]
- public class PythonTuple : ICollection, IEnumerable, IEnumerable<object>, IList, IList<object>, ICodeFormattable,
+ public class PythonTuple : ICollection, IEnumerable, IEnumerable<object>, IList, IList<object>, ICodeFormattable, IExpressionSerializable,
#if CLR2
IValueEquality,
#endif
@@ -640,6 +648,26 @@ public class PythonTuple : ICollection, IEnumerable, IEnumerable<object>, IList,
}
#endregion
+
+ #region IExpressionSerializable Members
+
+ public System.Linq.Expressions.Expression CreateExpression() {
+ Ast[] items = new Ast[Count];
+ for (int i = 0; i < items.Length; i++) {
+ items[i] = Utils.Constant(this[i]);
+ }
+
+ return Ast.Call(
+ AstMethods.MakeTuple,
+ Ast.NewArrayInit(
+ typeof(object),
+ items
+ )
+ );
+
+ }
+
+ #endregion
}
/// <summary>
View
7 Languages/IronPython/IronPython/Runtime/SetStorage.cs
@@ -248,10 +248,12 @@ internal sealed class SetStorage : IEnumerable, IEnumerable<object>
}
Bucket[] buckets = _buckets;
+ res._hashFunc = _hashFunc;
+ res._eqFunc = _eqFunc;
+ res._itemType = _itemType;
if (_count < _buckets.Length * MinLoad) {
// If the set is sparsely populated, create a cleaner copy
res.Initialize(_count);
- res.UpdateHelperFunctions(this);
for (int i = 0; i < buckets.Length; i++) {
Bucket bucket = buckets[i];
@@ -263,9 +265,6 @@ internal sealed class SetStorage : IEnumerable, IEnumerable<object>
// Otherwise, perform a faster copy
res._maxCount = (int)(buckets.Length * Load);
res._buckets = new Bucket[buckets.Length];
- res._hashFunc = _hashFunc;
- res._eqFunc = _eqFunc;
- res._itemType = _itemType;
for (int i = 0; i < buckets.Length; i++) {
Bucket bucket = buckets[i];
View
14 Languages/IronPython/IronPython/Runtime/StringFormatter.cs
@@ -812,9 +812,9 @@ public StringFormatter(CodeContext/*!*/ context, string str, object data)
StringBuilder str = new StringBuilder();
// use .NETs faster conversion if we can
if (radix == 16) {
- str.Append(Char.IsLower(format) ? val.ToString("x") : val.ToString("X"));
+ AppendNumberReversed(str, Char.IsLower(format) ? val.ToString("x") : val.ToString("X"));
} else if (radix == 10) {
- str.Append(val.ToString());
+ AppendNumberReversed(str, val.ToString());
} else {
if (val == 0) str.Append('0');
while (val != 0) {
@@ -878,6 +878,16 @@ public StringFormatter(CodeContext/*!*/ context, string str, object data)
}
}
+ private static void AppendNumberReversed(StringBuilder str, string res) {
+ int start = 0;
+ while (start < (res.Length - 1) && res[start] == '0') {
+ start++;
+ }
+ for (int i = res.Length - 1; i >= start; i--) {
+ str.Append(res[i]);
+ }
+ }
+
private void AppendHex(char format) {
AppendBase(format, 16);
}
View
21 Languages/IronPython/IronPython/Runtime/Types/OldClass.cs
@@ -63,7 +63,8 @@ public sealed class OldClass :
ICodeFormattable,
IMembersList,
IDynamicMetaObjectProvider,
- IPythonMembersList {
+ IPythonMembersList,
+ IWeakReferenceable {
[NonSerialized]
private List<OldClass> _bases;
@@ -75,6 +76,7 @@ public sealed class OldClass :
private int _optimizedInstanceNamesVersion;
private string[] _optimizedInstanceNames;
+ private WeakRefTracker _tracker;
public static string __doc__ = "classobj(name, bases, dict)";
@@ -629,5 +631,22 @@ internal class OldClassDebugView {
}
}
}
+
+ #region IWeakReferenceable Members
+
+ WeakRefTracker IWeakReferenceable.GetWeakRef() {
+ return _tracker;
+ }
+
+ bool IWeakReferenceable.SetWeakRef(WeakRefTracker value) {
+ _tracker = value;
+ return true;
+ }
+
+ void IWeakReferenceable.SetFinalizer(WeakRefTracker value) {
+ _tracker = value;
+ }
+
+ #endregion
}
}
View
69 Languages/IronPython/Tests/modules/system_related/sys_test.py
@@ -327,7 +327,7 @@ def test_getrefcount():
def test_version():
import re
#E.g., 2.5.0 (IronPython 2.0 Alpha (2.0.0.800) on .NET 2.0.50727.1433)
- regex = "^\d\.\d\.\d \(IronPython \d\.\d(\.\d)? ((Alpha \d+ )|(Beta \d+ )|())((DEBUG )|()|(\d?))\(\d\.\d\.\d{1,8}\.\d{1,8}\) on \.NET \d(\.\d{1,5}){3}\)$"
+ regex = "^\d\.\d\.\d \(IronPython \d\.\d(\.\d)? ((Alpha \d+ )|(Beta \d+ )|(RC \d+ )|())((DEBUG )|()|(\d?))\(\d\.\d\.\d{1,8}\.\d{1,8}\) on \.NET \d(\.\d{1,5}){3}\)$"
Assert(re.match(regex, sys.version) != None)
def test_winver():
@@ -423,6 +423,73 @@ def f():
None, 'line', None, 'call', None, 'line', None, 'return', None,
'return', None])
+def test_cp30129():
+ frames = []
+ def f(*args):
+ if args[1] == 'call':
+ frames.append(args[0])
+ if len(frames) == 3:
+ res.append('setting' + str(frames[1].f_lineno))
+ frames[1].f_lineno = 447
+ return f
+
+
+ import sys
+ sys.settrace(f)
+
+ res = []
+ def a():
+ res.append('foo')
+ res.append('bar')
+ res.append('baz')
+
+ def b():
+ a()
+ res.append('x')
+ res.append('y')
+ res.append('z')
+
+ def c():
+ b()
+ res.append('hello')
+ res.append('goodbye')
+ res.append('see ya')
+
+
+ c()
+
+ AreEqual(res, ['setting447', 'foo', 'bar', 'baz', 'x', 'y', 'z', 'hello', 'goodbye', 'see ya'])
+
+ sys.settrace(None)
+
+
+def test_cp30130():
+ def f(frame, event, arg):
+ if event == 'exception':
+ global ex
+ ex = arg
+ return f
+
+ sys.settrace(f)
+
+ def g():
+ raise Exception()
+
+ try:
+ g()
+ except:
+ pass
+
+ exc_type = ex[0]
+ exc_value = ex[1]
+ tb_value = ex[2]
+
+ print tb_value
+ import traceback
+ Assert(''.join(traceback.format_exception(exc_type, exc_value, tb_value)).find('line') != -1)
+
+ sys.settrace(None)
+
#--MAIN------------------------------------------------------------------------
testDelGetFrame = "Test_GetFrame" in sys.argv
View
5 Languages/IronPython/Tests/test_compiler.py
@@ -208,5 +208,10 @@ def test_system_core_cp20623():
AreEqual(cp20623.A, 35)
#TODO: need to also generate a standalone exe from cp20623 and try running it
+def test_cp30178():
+ compileCode("cp30178", 'mydict = { "a": ("Fail", "tuple") }')
+ import cp30178
+ AreEqual(cp30178.mydict, {'a' : ('Fail', 'tuple')})
+
#------------------------------------------------------------------------------
run_test(__name__)
View
26 Languages/IronPython/Tests/test_strformat.py
@@ -254,10 +254,8 @@ def test_object___format___errors():
# ensure only the s format type is recognized
for char in allChars:
if char != 's' and (char < '0' or char > '9'):
- if char==',' and is_cpython:
+ if char==',':
errors.append(('10' + char, "Cannot specify ',' with 's'."))
- elif char==',': #http://ironpython.codeplex.com/workitem/28377
- temp = object.__format__(",")
else:
errors.append(('10' + char, "Unknown format code '%s' for object of type 'str'" % char))
@@ -336,15 +334,15 @@ def test_float___format__():
(999999999999.9, '1.2', '1.0e+12'),
(999999999999.0, '', '999999999999.0'),
(-999999999999.0, '', '-999999999999.0'),
- (10e667, '+', '+1.0#INF'),
- (-10e667, '+', '-1.0#INF'),
- (10e667/10e667, '+', '-1.0#IND'),
- (10e667, '-', '1.0#INF'),
- (-10e667, '-', '-1.0#INF'),
- (10e667/10e667, '-', '-1.0#IND'),
- (10e667, ' ', ' 1.0#INF'),
- (-10e667, ' ', '-1.0#INF'),
- (10e667/10e667, ' ', '-1.0#IND'),
+ (10e667, '+', '+inf'),
+ (-10e667, '+', '-inf'),
+ (10e667/10e667, '+', '+nan'),
+ (10e667, '-', 'inf'),
+ (-10e667, '-', '-inf'),
+ (10e667/10e667, '-', 'nan'),
+ (10e667, ' ', ' inf'),
+ (-10e667, ' ', '-inf'),
+ (10e667/10e667, ' ', ' nan'),
]
tests+= [ (2.0, '', '2.0'),
@@ -575,9 +573,7 @@ def test_float___format__():
def test_float___format___errors():
errors = []
- okChars = set(['\0', '%', 'E', 'F', 'G', 'e', 'f', 'g', 'n'])
- if is_cpython: #http://ironpython.codeplex.com/workitem/28223
- okChars.add(',')
+ okChars = set(['\0', '%', 'E', 'F', 'G', 'e', 'f', 'g', 'n', ','])
# verify the okChars are actually ok
for char in okChars:
2.0.__format__('10' + char)
View
5 Languages/IronPython/Tests/test_syntax.py
@@ -228,10 +228,7 @@ def run_compile_test(code, msg, lineno, skipCpy):
#("'abc'.", "invalid syntax", 1),
]
-if is_ironpython or float(sys.winver) < 2.7: #http://ironpython.codeplex.com/workitem/28379
- compile_tests.append(("None = 2", "assignment to None", 1, False))
-else:
- compile_tests.append(("None = 2", "cannot assign to None", 1, False))
+compile_tests.append(("None = 2", "cannot assign to None", 1, False))
# different error messages, ok
for test in compile_tests:
View
23 Runtime/Microsoft.Dynamic/Generation/ToDiskRewriter.cs
@@ -74,11 +74,26 @@ internal sealed class ToDiskRewriter : ExpressionVisitor {
}
// Add the consant pool variable to the top lambda
- body = AstUtils.AddScopedVariable(
- body,
+ // We first create the array and then assign into it so that we can refer to the
+ // array and read values out that have already been created.
+ ReadOnlyCollectionBuilder<Expression> assigns = new ReadOnlyCollectionBuilder<Expression>(_constants.Count + 2);
+ assigns.Add(Expression.Assign(
_constantPool,
- Expression.NewArrayInit(typeof(object), _constants)
- );
+ Expression.NewArrayBounds(typeof(object), Expression.Constant(_constants.Count))
+ ));
+
+ // emit inner most constants first so they're available for outer most constants to consume
+ for (int i = _constants.Count - 1; i >= 0 ; i--) {
+ assigns.Add(
+ Expression.Assign(
+ Expression.ArrayAccess(_constantPool, Expression.Constant(i)),
+ _constants[i]
+ )
+ );
+ }
+ assigns.Add(body);
+
+ body = Expression.Block(new[] { _constantPool }, assigns);
}
// Rewrite the lambda
Please sign in to comment.
Something went wrong with that request. Please try again.