forked from skulpt/skulpt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
notes.txt
232 lines (169 loc) · 7.94 KB
/
notes.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
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: