Skip to content

Commit ad0cbd1

Browse files
committed
Merge branch 'master' of github.com:skulpt/skulpt
2 parents beac6c3 + c9e731a commit ad0cbd1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2192
-133
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ This is the contribute.md of our project. Great to have you here. Here are a few
1919
This section includes ways to get started with your open source project. Include links to documentation and to different communication channels:
2020

2121
* github: Lots of good discussion happens around pull requests and bug reports
22+
* [gitter discussion](https://gitter.im/skulpt/skulpt?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
2223
* [Mailing list](https://groups.google.com/forum/#!forum/skulpt)
2324
* IRC channel: [#skulpt](http://webchat.freenode.net/?channels=skulpt)
2425
* Blog: Some stuff about getting started is on [Brad's blog](http://reputablejournal.com)

HACKING.rst

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,62 @@ The Sk.builtin.func method creates a function. For module creation we typically
509509

510510
Well, I think this should be enough to get you going. Its worth repeating, if you made it this far, don't forget to call m docbi or m dist after you make changes in your module, its easy to get into the mode of thinking that the new javascript is automatically loaded. But skulpt-stdlib.js is not automatically rebuilt!
511511

512+
Importing/Using a module in another module
513+
------------------------------------------
514+
515+
While working on the namedtuple factory in the collections module I needed to add code to make
516+
sure that the fields named in the named tuple did not duplicate python keywords. while I was
517+
looking around for a list of keywords I discovered that there already was a list of keywords
518+
in the keyword module. Why not use that? A couple of problems:
519+
520+
* How do you import a module into another module? Especially under the condition
521+
where you are writing a module in javascript and the module you want to include is a python
522+
module?
523+
524+
* How do you call a function that was imported from a python module? Here is the snippet
525+
that demonstrates
526+
527+
.. code-block:: javascript
528+
529+
var keywds = Sk.importModule("keyword", false, false);
530+
531+
mod.namedtuple = function (name, fields) {
532+
var nm = Sk.ffi.remapToJs(name);
533+
// fields could be a string or a tuple or list of strings
534+
var flds = Sk.ffi.remapToJs(fields);
535+
536+
if (typeof(flds) === 'string') {
537+
flds = flds.split(/\s+/);
538+
}
539+
// use the keyword module function iskeyword
540+
for (i = 0; i < flds.length; i++) {
541+
if (Sk.ffi.remapToJs(Sk.misceval.callsim(keywds.$d['iskeyword'],Sk.ffi.remapToPy(flds[i])))) {
542+
throw new Sk.builtin.ValueError("Type names and field names cannot be a keyword: " + flds[i]);
543+
}
544+
}
545+
546+
The importing part is easy: ``Sk.importModule(name, dumpJS, canSuspend)``
547+
548+
The not-so-obvious part is the
549+
line: ``Sk.ffi.remapToJs(Sk.misceval.callsim(keywds.$d['iskeyword'],Sk.ffi.remapToPy(flds[i])))``
550+
551+
Working inside out: We use ``Sk.misceval.callsim`` to call the python function ``iskeyword`` which we
552+
retrieve from the module's dictionary of methods ``$d`` Because we are calling a Python function we need
553+
to remap the parameter from a javascript string to a Python string object. Hence the ``remapToPy`` call
554+
in the parameter. Since ``iskeyword`` will return a Python bool object we need to remap that back
555+
to javscript for our if statement.
556+
557+
You can use a similar strategy for creating an instance of a class:
558+
559+
.. code-block:: javascript
560+
561+
var io = Sk.importModule("io", false, false);
562+
var stdin = Sk.misceval.callsim(io.$d["TextIOWrapper"]);
563+
564+
565+
Seems like a lot of work to check for a keyword in an array. But knowing how to do this for much more
566+
complicated methods in other modules will pay off.
567+
512568
513569
Debugging
514570
---------

skulpt.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ def bowerProperty(name):
9191
'src/slice.js',
9292
'src/set.js',
9393
'src/module.js',
94+
'src/structseq.js',
9495
'src/generator.js',
9596
'src/file.js',
9697
'src/ffi.js',

src/abstract.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Sk.abstr.unop_type_error = function (v, name) {
2828
uop = {
2929
"UAdd" : "+",
3030
"USub" : "-",
31-
"Inver": "~"
31+
"Invert": "~"
3232
}[name];
3333

3434
throw new Sk.builtin.TypeError("bad operand type for unary " + uop + ": '" + vtypename + "'");
@@ -136,7 +136,6 @@ Sk.abstr.uoNameToSlotFunc_ = function (obj, name) {
136136
if (obj === null) {
137137
return undefined;
138138
}
139-
140139
switch (name) {
141140
case "USub":
142141
return obj.nb$negative ? obj.nb$negative : obj["__neg__"];
@@ -242,12 +241,6 @@ Sk.abstr.numOpAndPromote = function (a, b, opfn) {
242241
}
243242

244243
if (a.constructor === Sk.builtin.lng) {
245-
// if (b.constructor == Sk.builtin.nmber)
246-
// if (b.skType == Sk.builtin.nmber.float$) {
247-
// var tmp = new Sk.builtin.nmber(a.tp$str(), Sk.builtin.nmber.float$);
248-
// return [tmp, b];
249-
// } else
250-
// return [a, b.v];
251244
return [a, b];
252245
} else if (a.constructor === Sk.builtin.nmber) {
253246
return [a, b];

src/biginteger.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,6 @@ Sk.builtin.biginteger.prototype.bnIntValue = function () {
900900
else if (this.t === 0) {
901901
return 0;
902902
}
903-
// assumes 16 < DB < 32
904903
return ((this[1] & ((1 << (32 - this.DB)) - 1)) << this.DB) | this[0];
905904
};
906905

@@ -1439,7 +1438,6 @@ Sk.builtin.biginteger.prototype.bnpMultiplyUpperTo = function (a, n, r) {
14391438
* @extends Sk.builtin.biginteger
14401439
*/
14411440
Sk.builtin.biginteger.Barrett = function (m) {
1442-
// setup Barrett
14431441
this.r2 = Sk.builtin.biginteger.nbi();
14441442
this.q3 = Sk.builtin.biginteger.nbi();
14451443
Sk.builtin.biginteger.ONE.dlShiftTo(2 * m.t, this.r2);
@@ -1537,7 +1535,6 @@ Sk.builtin.biginteger.prototype.bnModPow = function (e, m) {
15371535
z = new Sk.builtin.biginteger.Montgomery(m);
15381536
}
15391537

1540-
// precomputation
15411538
g = [];
15421539
n = 3;
15431540
k1 = k - 1;

src/builtin.js

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ Sk.builtin.asnum$nofloat = function (a) {
128128
a = a.toString();
129129
}
130130

131-
// Sk.debugout("INITIAL: " + a);
131+
// Sk.debugout("INITIAL: " + a);
132132

133133
// If not a float, great, just return this
134134
if (a.indexOf(".") < 0 && a.indexOf("e") < 0 && a.indexOf("E") < 0) {
@@ -147,17 +147,10 @@ Sk.builtin.asnum$nofloat = function (a) {
147147
mantissa = a;
148148
}
149149

150-
// Sk.debugout("e:" + expon);
151-
152150
expon = parseInt(expon, 10);
153151

154-
// Sk.debugout("MANTISSA:" + mantissa);
155-
// Sk.debugout("EXPONENT:" + expon);
156-
157152
decimal = mantissa.indexOf(".");
158153

159-
// Sk.debugout("DECIMAL: " + decimal);
160-
161154
// Simplest case, no decimal
162155
if (decimal < 0) {
163156
if (expon >= 0) {
@@ -187,27 +180,17 @@ Sk.builtin.asnum$nofloat = function (a) {
187180
mantissa = mantissa.substr(0, decimal);
188181
}
189182

190-
// Sk.debugout("NO DECIMAL: " + mantissa);
191-
192183
decimal = decimal + expon;
193-
194-
// Sk.debugout("MOVE DECIM: " + decimal);
195-
196184
while (decimal > mantissa.length) {
197185
mantissa += "0";
198186
}
199187

200-
// Sk.debugout("PADDED : " + mantissa);
201-
202188
if (decimal <= 0) {
203189
mantissa = 0;
204190
} else {
205191
mantissa = mantissa.substr(0, decimal);
206192
}
207193

208-
// Sk.debugout("LENGTH: " + mantissa.length);
209-
// Sk.debugout("RETURN: " + mantissa);
210-
211194
return mantissa;
212195
};
213196
goog.exportSymbol("Sk.builtin.asnum$nofloat", Sk.builtin.asnum$nofloat);
@@ -750,6 +733,21 @@ Sk.builtin.getattr = function getattr (obj, name, default_) {
750733
return ret;
751734
};
752735

736+
Sk.builtin.setattr = function setattr (obj, name, value) {
737+
738+
Sk.builtin.pyCheckArgs("setattr", arguments, 3, 3);
739+
if (!Sk.builtin.checkString(name)) {
740+
throw new Sk.builtin.TypeError("attribute name must be string");
741+
}
742+
if (obj.tp$setattr) {
743+
obj.tp$setattr(Sk.ffi.remapToJs(name), value);
744+
} else {
745+
throw new Sk.builtin.AttributeError("object has no attribute " + Sk.ffi.remapToJs(name));
746+
}
747+
748+
return Sk.builtin.none.none$;
749+
};
750+
753751
Sk.builtin.raw_input = function (prompt) {
754752
var x, resolution, susp;
755753

src/builtindict.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,14 @@ Sk.builtins = {
6868
"type" : Sk.builtin.type,
6969
"input" : Sk.builtin.input,
7070
"raw_input" : Sk.builtin.raw_input,
71+
"setattr" : Sk.builtin.setattr,
7172
/*'read': Sk.builtin.read,*/
7273
"jseval" : Sk.builtin.jseval,
7374
"jsmillis" : Sk.builtin.jsmillis,
7475
"quit" : Sk.builtin.quit,
7576
"exit" : Sk.builtin.quit,
7677

77-
// Functions below are not implemented
78+
// Functions below are not implemented
7879
"bytearray" : Sk.builtin.bytearray,
7980
"callable" : Sk.builtin.callable,
8081
"complex" : Sk.builtin.complex,

src/dict.js

Lines changed: 64 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -386,83 +386,70 @@ Sk.builtin.dict.prototype["values"] = new Sk.builtin.func(function (self) {
386386
return new Sk.builtin.list(ret);
387387
});
388388

389+
Sk.builtin.dict.prototype["clear"] = new Sk.builtin.func(function (self) {
390+
var k;
391+
var iter;
392+
393+
for (iter = self.tp$iter(), k = iter.tp$iternext();
394+
k !== undefined;
395+
k = iter.tp$iternext()) {
396+
self.mp$del_subscript(k);
397+
}
398+
});
399+
400+
Sk.builtin.dict.prototype["setdefault"] = new Sk.builtin.func(function (self, key, default_) {
401+
try {
402+
return self.mp$subscript(key);
403+
}
404+
catch (e) {
405+
if (default_ === undefined) {
406+
default_ = Sk.builtin.none.none$;
407+
}
408+
self.mp$ass_subscript(key, default_);
409+
return default_;
410+
}
411+
});
412+
413+
Sk.builtin.dict.prototype["copy"] = new Sk.builtin.func(function (self) {
414+
throw new Sk.builtin.NotImplementedError("dict.copy is not yet implemented in Skulpt");
415+
});
416+
417+
Sk.builtin.dict.prototype["fromkeys"] = new Sk.builtin.func(function (seq, value) {
418+
throw new Sk.builtin.NotImplementedError("dict.fromkeys is not yet implemented in Skulpt");
419+
});
420+
421+
Sk.builtin.dict.prototype["iteritems"] = new Sk.builtin.func(function (self) {
422+
throw new Sk.builtin.NotImplementedError("dict.iteritems is not yet implemented in Skulpt");
423+
});
424+
425+
Sk.builtin.dict.prototype["iterkeys"] = new Sk.builtin.func(function (self) {
426+
throw new Sk.builtin.NotImplementedError("dict.iterkeys is not yet implemented in Skulpt");
427+
});
428+
429+
Sk.builtin.dict.prototype["itervalues"] = new Sk.builtin.func(function (self) {
430+
throw new Sk.builtin.NotImplementedError("dict.itervalues is not yet implemented in Skulpt");
431+
});
432+
433+
Sk.builtin.dict.prototype["popitem"] = new Sk.builtin.func(function (self) {
434+
throw new Sk.builtin.NotImplementedError("dict.popitem is not yet implemented in Skulpt");
435+
});
436+
437+
Sk.builtin.dict.prototype["update"] = new Sk.builtin.func(function (self, other) {
438+
throw new Sk.builtin.NotImplementedError("dict.update is not yet implemented in Skulpt");
439+
});
440+
441+
Sk.builtin.dict.prototype["viewitems"] = new Sk.builtin.func(function (self) {
442+
throw new Sk.builtin.NotImplementedError("dict.viewitems is not yet implemented in Skulpt");
443+
});
444+
445+
Sk.builtin.dict.prototype["viewkeys"] = new Sk.builtin.func(function (self) {
446+
throw new Sk.builtin.NotImplementedError("dict.viewkeys is not yet implemented in Skulpt");
447+
});
448+
449+
Sk.builtin.dict.prototype["viewvalues"] = new Sk.builtin.func(function (self) {
450+
throw new Sk.builtin.NotImplementedError("dict.viewvalues is not yet implemented in Skulpt");
451+
});
452+
389453
Sk.builtin.dict.prototype.tp$name = "dict";
390454

391455
goog.exportSymbol("Sk.builtin.dict", Sk.builtin.dict);
392-
393-
/*
394-
395-
$.prototype.clear = function() { throw "todo; dict.clear"; };
396-
$.prototype.copy = function() { throw "todo; dict.copy"; };
397-
$.prototype.fromkeys = function() { throw "todo; dict.fromkeys"; };
398-
$.prototype.get = function() { throw "todo; dict.get"; };
399-
400-
$.prototype.has_key = function(key)
401-
{
402-
return this.hasOwnProperty(kf(key));
403-
};
404-
405-
$.prototype.items = function() { throw "todo; dict.items"; };
406-
$.prototype.iteritems = function() { throw "todo; dict.iteritems"; };
407-
$.prototype.iterkeys = function() { throw "todo; dict.iterkeys"; };
408-
$.prototype.itervalues = function() { throw "todo; dict.itervalues"; };
409-
$.prototype.keys = function() { throw "todo; dict.keys"; };
410-
$.prototype.pop = function() { throw "todo; dict.pop"; };
411-
$.prototype.popitem = function() { throw "todo; dict.popitem"; };
412-
$.prototype.setdefault = function() { throw "todo; dict.setdefault"; };
413-
$.prototype.update = function() { throw "todo; dict.update"; };
414-
$.prototype.values = function() { throw "todo; dict.values"; };
415-
416-
$.prototype.__getitem__ = function(key)
417-
{
418-
var entry = this[kf(key)];
419-
return typeof entry === 'undefined' ? undefined : entry.rhs;
420-
};
421-
422-
$.prototype.__delitem__ = function(key)
423-
{
424-
var k = kf(key);
425-
426-
if (this.hasOwnProperty(k))
427-
{
428-
this.size -= 1;
429-
delete this[k];
430-
}
431-
432-
return this;
433-
};
434-
435-
$.prototype.__class__ = new Sk.builtin.type('dict', [Sk.types.object], {});
436-
437-
$.prototype.__iter__ = function()
438-
{
439-
var allkeys = [];
440-
for (var k in this)
441-
{
442-
if (this.hasOwnProperty(k))
443-
{
444-
var i = this[k];
445-
if (i && i.hasOwnProperty('lhs')) // skip internal stuff. todo; merge pyobj and this
446-
{
447-
allkeys.push(k);
448-
}
449-
}
450-
}
451-
//print(allkeys);
452-
453-
var ret =
454-
{
455-
__iter__: function() { return ret; },
456-
$obj: this,
457-
$index: 0,
458-
$keys: allkeys,
459-
next: function()
460-
{
461-
// todo; StopIteration
462-
if (ret.$index >= ret.$keys.length) return undefined;
463-
return ret.$obj[ret.$keys[ret.$index++]].lhs;
464-
}
465-
};
466-
return ret;
467-
};
468-
*/

0 commit comments

Comments
 (0)