Skip to content

Commit 97f5100

Browse files
GeoffreyHuckSebastienTainon
authored andcommitted
Apply Geoffrey Huck updates: skulpt/skulpt@1.3.0...GeoffreyHuck:master onto Skulpt 1.3
1 parent 6c99c21 commit 97f5100

21 files changed

+6240
-58
lines changed

README.md

+49
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,52 @@
1+
# Modified version of Skulpt for FranceIOI
2+
3+
The file *src/internalpython.js* should be created automatically when building the sources. If that's not the case, you should create it with the following content :
4+
5+
Sk.internalPy={"files":{"src/classmethod.py":"class classmethod(object):\n \"Emulate PyClassMethod_Type() in Objects/funcobject.c\"\n\n def __init__(self, f):\n self.f = f\n\n def __get__(self, obj, klass=None):\n if klass is None:\n klass = type(obj)\n def newfunc(*args):\n return self.f(klass, *args)\n return newfunc\n","src/property.py":"class property(object):\n \"Emulate PyProperty_Type() in Objects/descrobject.c\"\n\n def __init__(self, fget=None, fset=None, fdel=None, doc=None):\n self.fget = fget\n self.fset = fset\n self.fdel = fdel\n if doc is None and fget is not None:\n if hasattr(fget, '__doc__'):\n doc = fget.__doc__\n else:\n doc = None\n self.__doc__ = doc\n\n def __get__(self, obj, objtype=None):\n if obj is None:\n return self\n if self.fget is None:\n raise AttributeError(\"unreadable attribute\")\n return self.fget(obj)\n\n def __set__(self, obj, value):\n if self.fset is None:\n raise AttributeError(\"can't set attribute\")\n self.fset(obj, value)\n\n def __delete__(self, obj):\n if self.fdel is None:\n raise AttributeError(\"can't delete attribute\")\n self.fdel(obj)\n\n def getter(self, fget):\n return type(self)(fget, self.fset, self.fdel, self.__doc__)\n\n def setter(self, fset):\n return type(self)(self.fget, fset, self.fdel, self.__doc__)\n\n def deleter(self, fdel):\n return type(self)(self.fget, self.fset, fdel, self.__doc__)\n","src/staticmethod.py":"class staticmethod(object):\n \"Emulate PyStaticMethod_Type() in Objects/funcobject.c\"\n\n def __init__(self, f):\n self.f = f\n\n def __get__(self, obj, objtype=None):\n return self.f\n"}}
6+
7+
In this modified version, each modification of a variable
8+
9+
v = X
10+
11+
is transformed to
12+
13+
v = window.currentPythonRunner.reportValue(X, 'v');
14+
15+
Objects, lists and dicts contains a unique *__uuid* field. Every time an object method is called, a list is modified, a dict is modified, a new reference is created with the same *__uuid*. These objects also contain a *_parents* which contains the _uuid of the parents. This allows to create a new reference for the parent objects. For example :
16+
17+
a = [1, 2, 3]
18+
b = [..., a, ...] # A list containing a
19+
c = { ..., 'element': a , ... } # A dict containing a
20+
21+
*a._parents* will contain the _uuid of *b* and *c*. This allows to create a new reference for *b* and *c* whenever *a* changes.
22+
23+
Note : An object has an internal variable *$d* (dollar sign + d) that is a dict and that contains all the object's variable memebers.
24+
25+
The code related to the references update is in *src/persistent.js*.
26+
27+
Most of the modifications are in *src/compile.js* and their aim is to call the rights functions of *src/persistent.js* within the javascript code generated from the python one.
28+
29+
The generated javascript code is visible in Codecast's console when you hit "Compile". It is also possible to add a "debugger;" instruction within the generated code if you add
30+
31+
out("debugger;");
32+
33+
at the place you want in *src/compile.js*/
34+
35+
36+
# Development
37+
38+
npm run watch
39+
40+
It updates dist/skulpt.js every time there is a modification in the source.
41+
42+
43+
# Build
44+
45+
npm run dist
46+
47+
You can then get the file *dist/skulpt.min.js* and replace Codecast's skulpt file.
48+
49+
150
# Welcome to Skulpt
251

352
[![Join the chat at https://gitter.im/skulpt/skulpt](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/skulpt/skulpt?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

debugger/debugger.js

+125-38
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,45 @@
44

55
var Sk = Sk || {}; //jshint ignore:line
66

7-
function hasOwnProperty(obj, prop) {
7+
/**
8+
* Changes :
9+
*
10+
* - Suspension.colno -> Suspension.$colno
11+
* - Suspension.lineno -> Suspension.$lineno
12+
* - Suspension.filename -> Suspension.$filename
13+
*
14+
* Modification on hasOwnProperty (or skulpt crash).
15+
* Internal call to hasOwnProperty here moved to debuggerHasOwnProperty (origninal of hasOwnProperty).
16+
*
17+
* goog.exportSymbol -> Sk.exportSymbol
18+
*
19+
* Add :
20+
* - this.output_callback._onStepError(e);
21+
* - this.output_callback._onStepSuccess(e);
22+
*/
23+
24+
var DEBUG_DEBUGGER = false;
25+
var debuggerLog = function() {
26+
if (DEBUG_DEBUGGER) {
27+
// 1. Convert args to a normal array
28+
var args = Array.prototype.slice.call(arguments);
29+
30+
// 2. Prepend log prefix log string
31+
args.unshift("[debugger.js] ");
32+
33+
// 3. Pass along arguments to console.log
34+
console.log.apply(console, args);
35+
}
36+
};
37+
38+
function hasOwnProperty(prop) {
39+
var obj = this;
40+
var proto = obj.constructor.prototype;
41+
return (prop in obj) &&
42+
(!(prop in proto) || proto[prop] !== obj[prop]);
43+
}
44+
45+
function debuggerHasOwnProperty(obj, prop) {
846
var proto = obj.constructor.prototype;
947
return (prop in obj) &&
1048
(!(prop in proto) || proto[prop] !== obj[prop]);
@@ -32,15 +70,15 @@ Sk.Debugger = function(filename, output_callback) {
3270

3371
Sk.Debugger.prototype.print = function(txt) {
3472
if (this.output_callback != null) {
35-
this.output_callback.print(txt);
73+
this.output_callback.print(txt + "\n");
3674
}
3775
};
3876

3977
Sk.Debugger.prototype.get_source_line = function(lineno) {
4078
if (this.output_callback != null) {
4179
return this.output_callback.get_source_line(lineno);
4280
}
43-
81+
4482
return "";
4583
};
4684

@@ -78,25 +116,27 @@ Sk.Debugger.prototype.generate_breakpoint_key = function(filename, lineno, colno
78116
};
79117

80118
Sk.Debugger.prototype.check_breakpoints = function(filename, lineno, colno, globals, locals) {
119+
// debuggerLog('check_breakpoints', filename, lineno, colno, globals, locals);
120+
81121
// If Step mode is enabled then ignore breakpoints since we will just break
82122
// at every line.
83123
if (this.step_mode === true) {
84124
return true;
85125
}
86-
126+
87127
var key = this.generate_breakpoint_key(filename, lineno, colno);
88-
if (hasOwnProperty(this.dbg_breakpoints, key) &&
128+
if (debuggerHasOwnProperty(this.dbg_breakpoints, key) &&
89129
this.dbg_breakpoints[key].enabled === true) {
90130
var bp = null;
91-
if (hasOwnProperty(this.tmp_breakpoints, key)) {
131+
if (debuggerHasOwnProperty(this.tmp_breakpoints, key)) {
92132
delete this.dbg_breakpoints[key];
93133
delete this.tmp_breakpoints[key];
94134
return true;
95135
}
96-
136+
97137
this.dbg_breakpoints[key].ignore_count -= 1;
98138
this.dbg_breakpoints[key].ignore_count = Math.max(0, this.dbg_breakpoints[key].ignore_count);
99-
139+
100140
bp = this.dbg_breakpoints[key];
101141
if (bp.ignore_count === 0) {
102142
return true;
@@ -113,23 +153,23 @@ Sk.Debugger.prototype.get_breakpoints_list = function() {
113153

114154
Sk.Debugger.prototype.disable_breakpoint = function(filename, lineno, colno) {
115155
var key = this.generate_breakpoint_key(filename, lineno, colno);
116-
117-
if (hasOwnProperty(this.dbg_breakpoints, key)) {
156+
157+
if (debuggerHasOwnProperty(this.dbg_breakpoints, key)) {
118158
this.dbg_breakpoints[key].enabled = false;
119159
}
120160
};
121161

122162
Sk.Debugger.prototype.enable_breakpoint = function(filename, lineno, colno) {
123163
var key = this.generate_breakpoint_key(filename, lineno, colno);
124-
125-
if (hasOwnProperty(this.dbg_breakpoints, key)) {
164+
165+
if (debuggerHasOwnProperty(this.dbg_breakpoints, key)) {
126166
this.dbg_breakpoints[key].enabled = true;
127167
}
128168
};
129169

130170
Sk.Debugger.prototype.clear_breakpoint = function(filename, lineno, colno) {
131171
var key = this.generate_breakpoint_key(filename, lineno, colno);
132-
if (hasOwnProperty(this.dbg_breakpoints, key)) {
172+
if (debuggerHasOwnProperty(this.dbg_breakpoints, key)) {
133173
delete this.dbg_breakpoints[key];
134174
return null;
135175
} else {
@@ -144,7 +184,7 @@ Sk.Debugger.prototype.clear_all_breakpoints = function() {
144184

145185
Sk.Debugger.prototype.set_ignore_count = function(filename, lineno, colno, count) {
146186
var key = this.generate_breakpoint_key(filename, lineno, colno);
147-
if (hasOwnProperty(this.dbg_breakpoints, key)) {
187+
if (debuggerHasOwnProperty(this.dbg_breakpoints, key)) {
148188
var bp = this.dbg_breakpoints[key];
149189
bp.ignore_count = count;
150190
}
@@ -153,39 +193,44 @@ Sk.Debugger.prototype.set_ignore_count = function(filename, lineno, colno, count
153193
Sk.Debugger.prototype.set_condition = function(filename, lineno, colno, lhs, cond, rhs) {
154194
var key = this.generate_breakpoint_key(filename, lineno, colno);
155195
var bp;
156-
if (hasOwnProperty(this.dbg_breakpoints, key)) {
196+
if (debuggerHasOwnProperty(this.dbg_breakpoints, key)) {
157197
// Set a new condition
158198
bp = this.dbg_breakpoints[key];
159199
} else {
160200
bp = new Sk.Breakpoint(filename, lineno, colno);
161201
}
162-
202+
163203
bp.condition = new Sk.Condition(lhs, cond, rhs);
164204
this.dbg_breakpoints[key] = bp;
165205
};
166206

167207
Sk.Debugger.prototype.print_suspension_info = function(suspension) {
168-
var filename = suspension.filename;
169-
var lineno = suspension.lineno;
170-
var colno = suspension.colno;
171-
this.print("Hit Breakpoint at <" + filename + "> at line: " + lineno + " column: " + colno + "\n");
172-
this.print("----------------------------------------------------------------------------------\n");
173-
this.print(" ==> " + this.get_source_line(lineno - 1) + "\n");
174-
this.print("----------------------------------------------------------------------------------\n");
208+
var filename = suspension.$filename;
209+
var lineno = suspension.$lineno;
210+
var colno = suspension.$colno;
211+
if (DEBUG_DEBUGGER) {
212+
console.log("Hit Breakpoint at <" + filename + "> at line: " + lineno + " column: " + colno + "\n");
213+
console.log("----------------------------------------------------------------------------------\n");
214+
console.log(" ==> " + this.get_source_line(lineno - 1) + "\n");
215+
console.log("----------------------------------------------------------------------------------\n");
216+
console.log(suspension);
217+
}
175218
};
176219

177220
Sk.Debugger.prototype.set_suspension = function(suspension) {
221+
debuggerLog('set_suspension', suspension);
222+
178223
var parent = null;
179-
if (!hasOwnProperty(suspension, "filename") && suspension.child instanceof Sk.misceval.Suspension) {
224+
if (!debuggerHasOwnProperty(suspension, "$filename") && suspension.child instanceof Sk.misceval.Suspension) {
180225
suspension = suspension.child;
181226
}
182-
227+
183228
// Pop the last suspension of the stack if there is more than 0
184229
if (this.suspension_stack.length > 0) {
185230
this.suspension_stack.pop();
186231
this.current_suspension -= 1;
187232
}
188-
233+
189234
// Unroll the stack to get each suspension.
190235
while (suspension instanceof Sk.misceval.Suspension) {
191236
parent = suspension;
@@ -195,7 +240,7 @@ Sk.Debugger.prototype.set_suspension = function(suspension) {
195240
}
196241

197242
suspension = parent;
198-
243+
199244
this.print_suspension_info(suspension);
200245
};
201246

@@ -217,15 +262,26 @@ Sk.Debugger.prototype.suspension_handler = function(susp) {
217262
});
218263
};
219264

220-
Sk.Debugger.prototype.resume = function() {
265+
Sk.Debugger.prototype.resume = function(resolve, reject) {
266+
debuggerLog('resume');
267+
221268
// Reset the suspension stack to the topmost
222269
this.current_suspension = this.suspension_stack.length - 1;
223-
270+
224271
if (this.suspension_stack.length === 0) {
225272
this.print("No running program");
273+
274+
if (typeof resolve === 'function') {
275+
resolve();
276+
}
226277
} else {
227278
var promise = this.suspension_handler(this.get_active_suspension());
228-
promise.then(this.success.bind(this), this.error.bind(this));
279+
var self = this;
280+
promise.then(function(value) {
281+
self.success(value, resolve, reject);
282+
}, function(error) {
283+
self.error(error, reject);
284+
});
229285
}
230286
};
231287

@@ -234,33 +290,60 @@ Sk.Debugger.prototype.pop_suspension_stack = function() {
234290
this.current_suspension -= 1;
235291
};
236292

237-
Sk.Debugger.prototype.success = function(r) {
293+
Sk.Debugger.prototype.success = function(r, resolve, reject) {
294+
debuggerLog('success', r, resolve);
295+
238296
if (r instanceof Sk.misceval.Suspension) {
297+
debuggerLog('success suspension');
239298
this.set_suspension(r);
299+
if (this.output_callback != null) {
300+
this.output_callback._onStepSuccess(resolve);
301+
}
240302
} else {
241303
if (this.suspension_stack.length > 0) {
242304
// Current suspension needs to be popped of the stack
243305
this.pop_suspension_stack();
244-
306+
245307
if (this.suspension_stack.length === 0) {
308+
debuggerLog('success complete');
309+
246310
this.print("Program execution complete");
311+
312+
if (typeof resolve === 'function') {
313+
resolve();
314+
}
315+
247316
return;
248317
}
249-
318+
319+
debuggerLog('here we are');
320+
250321
var parent_suspension = this.get_active_suspension();
251322
// The child has completed the execution. So override the child's resume
252323
// so we can continue the execution.
253324
parent_suspension.child.resume = function() {
254325
return r;
255326
};
256-
this.resume();
327+
328+
this.resume(resolve, reject);
257329
} else {
330+
debuggerLog('success complete 2');
331+
258332
this.print("Program execution complete");
333+
334+
if (typeof resolve === 'function') {
335+
resolve();
336+
}
259337
}
260338
}
261339
};
262340

263-
Sk.Debugger.prototype.error = function(e) {
341+
Sk.Debugger.prototype.error = function(e, reject) {
342+
debuggerLog('error', e);
343+
344+
if (this.output_callback != null) {
345+
this.output_callback._onStepError(e, reject);
346+
}
264347
this.print("Traceback (most recent call last):");
265348
for (var idx = 0; idx < e.traceback.length; ++idx) {
266349
this.print(" File \"" + e.traceback[idx].filename + "\", line " + e.traceback[idx].lineno + ", in <module>");
@@ -269,11 +352,15 @@ Sk.Debugger.prototype.error = function(e) {
269352
code = " " + code;
270353
this.print(code);
271354
}
272-
355+
273356
var err_ty = e.constructor.tp$name;
274357
for (idx = 0; idx < e.args.v.length; ++idx) {
275358
this.print(err_ty + ": " + e.args.v[idx].v);
276359
}
360+
361+
if (typeof reject === 'function') {
362+
reject();
363+
}
277364
};
278365

279366
Sk.Debugger.prototype.asyncToPromise = function(suspendablefn, suspHandlers, debugger_obj) {
@@ -302,11 +389,11 @@ Sk.Debugger.prototype.asyncToPromise = function(suspendablefn, suspHandlers, deb
302389

303390
Sk.Debugger.prototype.execute = function(suspendablefn, suspHandlers) {
304391
var r = suspendablefn();
305-
392+
306393
if (r instanceof Sk.misceval.Suspension) {
307394
this.suspensions.concat(r);
308395
this.eval_callback(r);
309396
}
310397
};
311398

312-
goog.exportSymbol("Sk.Debugger", Sk.Debugger);
399+
Sk.exportSymbol("Sk.Debugger", Sk.Debugger);

0 commit comments

Comments
 (0)