todo: object genericgetattr is wrong. should be looking up bases, not types. dummy make a type-name-getting function, rather than obj.tp$name so that number works (and it'd be a good error checking place too) genexpr with free vars test generator func repr test __builtin__ needs work test for __bases__ and __mro__ of list/str/dict/etc IfExp: a if a < b else b why aren't the methods in .js's actually method? (have to pass 'self' to loadIdentity) final mode: make a build mode that compiles all py removes all goog.exportSymbol then compiles all resulting .js for final dist type builds generated code will make closure v unhappy right now though add line/col numbers to all error messages change .tp$name to ['$n'] so external module tpnames work ide: - load shaders - switch btwn files and set defaulttext - perspective matrix - matrix lib - basic procedural objects ------------------- notes: both the type object's slots, and the tp_dict elements of a CPython typeobject are handled by the prototype object in js. ob$type, tp$xyz, sq$xyz, etc. correspond to slots, and non-$-containing ones are entries in tp$dict (that is methods, etc defined on the class). there is still a __dict__ object on instances (corresponding to dict at tp_dictoffset in CPython) which holds the attributes for the instance. these are not stored in the "object" js storage because objects in js are only string->obj, not obj->obj mappings. we might want to revisit that at some point, depending on whether anything other than strings really goes on the lhs. the __dict__ is accessible as inst.inst$dict on instances. having the prototype be the type object is slightly not good. when we want to get the type of a list, we do: listinst = [] listinst.ob$type == list.prototype; // <- great listinst.ob$type.ob$type == list.prototype; // <- bad! we want the second one to be type.prototype because the type of the type of a list instance is infact 'type'. this is just a silly artifact of how javascript inheritance works: by copying that prototype object. so, if we make a new thing based on the object that's using that as its prototype, we can't tell the difference between the copy and the prototype itself. what if we made the type object for a list instance be a "new list()" i.e. based on the prototype, but then with its ob$type set? todo;;; prototype should contain pyfunction objects, not just typeof x === 'function'. in lookup, the 'descr' from type lookup should be a function object so that it can get its ob$type (which would be the function type) would have a descriptor on it, so it can wrap (or not) the function into a bound method. ??? how does cpython work? they're obviously just regular c functions in the slots. -- ah. tp_methods is a list of the methods which is some data that gets wrapped into appropriate method objects on startup to build the type up. descriptor lookup: looking up 'name' on obj get obj.ob_type, pass to type_lookup (e.g. Sk.builtin.list.ob$type, which is basically the prototype obj of list) descr = obj.ob_type[name] (a builtin.func object) f = descr.ob_type.tp_descr_get result = f(descr, obj, obj.ob_type) so, the functions on list (say, 'extend') are actually descriptors SO! - for the builtin types, the 'slot' functions tp$stuff are just js functions. but, the accessible functions like list.extend are builtin.func's. that way they have the various methods, they have an ob$type, and they have a tp$descr_get which does appropriate binding. oh, ffs I hate JS. klass = new Object(); klass.prototype.x = function(){}; new klass(); assigning keyword arguments: - place all positional into array - for each keyword, figure out what it's position would be - if there's nothing there, then insert - otherwise, throw TypeError multiple values Oh wait, no, that's dumb. We don't know the target we're calling so the binding has to be in the call not at the call site (though it could look in the function object that's being called.) So, just build up a list of name/value for keywords, and .call has to put them in the right place by looking at something. code obj? func obj? ------------ closure binding: 1. need to handle converting from skulpt objects to js objects (for number, bool, string) maybe only handle those 3 and use something manual for others? 2. need to handle getting the return value to be an object that has a tp$getattr, so getting something out of it works 3. need to handle binding methods to their objects (creating something like a Sk.builtin.method) e.g. for g.drawRect 4. need to handle calling @constructor functions with 'new' because closure doesn't do return this; in its ctors. first 3 can do dynamically. there's no tag on ctors though, except in the comment annotations. - fork closure-compiler and generate a full set of wrappers offline? they could even be simple python seems like jsdoc-toolkit can handle parsing comments pretty well, seems like a reasonable approach. at least we could build a list of ctors. maybe do 1-3 dynamically, and just put ctors in a table and change .call to handle the 'new' stupid magic? can't quite build a useful table because all type objects won't be defined. could use string, but constructor.name is only the last and is non-standard anyway. here's a disgusting idea: after every goog.require() do if (goog && goog.ui && goog.ui.QueryData) goog.ui.QueryData.$isctor = true; for every one. blech. ----------- ffi pretty simple with a helper .js file? - remap from dict <-> obj with helper - remap from long/number -> number and back - functions/methods can't just pass in the raw code object to js because they'll not have access to their globals. wrap a closure that calls tp$call around them. todo; more helpers for ffi verify that numbers are numbers, not longs (and maybe a compile mode to disable longs entirely?) ---------------- bases and mro type(name, bases, dict) things are wrong with the ob$type vs. the actual JS type (i.e. Sk.builtin.object) vs the prototype. object is the name of a type. you can also call it, but that's pretty useless. trying to make the ctor function the type object means that the sneaky thing of putting the functions into the prototype so that they can be looked up as A.__init__ or a = A(); a.__init__() doesn't work because they would only be in one place. ------------------ bespin: - python plugin for syntax hl doesn't work - can it do autoindent? i.e. indent after :? - home-home is wrong - ctrl-home/ctrl-end don't work - ctrl-arrow is wrong - pageup/down are wrong ===> Code Mirror is much better ----------------- importing: - import is a statement, the load a create of a module has to happen synchronously so that it's available to the next line of code - xhrio is async, and without webworkers, can't be faked to be synchronous. - so, we have to pull all builtins/lib ahead of time, or otherwise pull from other sources, and then have all local code via a simple read that returns a string. since std lib is small this is ok for now. might have to subdivide it a bit eventually ----------------- ah, damnit. closure is kind of a pain in the ass - trying to model type/object, so instances are types but types are also types, and type itself is also a type. but closure flattens everything that isn't a prototype. so Sk.builtin.object.inst$dict is getting flattened to just 'Sa', which means of course that when some generic code tries to look up something in an instance, or class, or the type type, there's no inst$dict. - maybe putting a non-function (i.e. inst$dict) in the .prototype, and then removing it from actual instances with a delete in the constructor? - or, switch to using ["$d"] or something instead of inst$dict. kind of sucks, but probably the easiest way. - blurgh. same for tp$repr, tp$name, ob$type just because of 'type' object. shit-tay. ['$r'] ['$n'] ['$t'] :( ----------------- Test edit for review. ----------------- # vim: set tw=72 formatoptions=croqln: