Skip to content

Commit ce3ac98

Browse files
committed
added namespaces to vars, and protocols
1 parent 31018ca commit ce3ac98

11 files changed

Lines changed: 359 additions & 88 deletions

File tree

pixie/vm/code.py

Lines changed: 183 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,23 @@
1818
"SET_VAR",
1919
"POP",
2020
"DEREF_VAR",
21-
"INSTALL"]
21+
"INSTALL",
22+
"RECUR",
23+
"ARG",
24+
"PUSH_SELF"]
2225

2326
for x in range(len(BYTECODES)):
2427
globals()[BYTECODES[x]] = r_uint(x)
2528

26-
class TailCall(object.Object):
27-
_type = object.Type("TailCall")
28-
__immutable_fields_ = ["_f", "_args"]
29-
def __init__(self, f, args):
30-
self._f = f
31-
self._args = args
32-
33-
def run(self):
34-
return self._f._invoke(self._args)
29+
# class TailCall(object.Object):
30+
# _type = object.Type("TailCall")
31+
# __immutable_fields_ = ["_f", "_args"]
32+
# def __init__(self, f, args):
33+
# self._f = f
34+
# self._args = args
35+
#
36+
# def run(self):
37+
# return self._f._invoke(self._args)
3538

3639

3740
class BaseCode(object.Object):
@@ -49,8 +52,6 @@ def get_bytecode(self):
4952

5053
def invoke(self, args):
5154
result = self._invoke(args)
52-
while isinstance(result, TailCall):
53-
result = result.run()
5455
return result
5556

5657

@@ -145,9 +146,10 @@ def deref(self):
145146
return self.get_root(rev)
146147

147148

148-
class VarRegistry(__builtins__.object):
149-
def __init__(self):
149+
class Namespace(__builtins__.object):
150+
def __init__(self, name):
150151
self._registry = {}
152+
self._name = name
151153

152154
def intern_or_make(self, name):
153155
assert isinstance(name, str)
@@ -157,19 +159,176 @@ def intern_or_make(self, name):
157159
self._registry[name] = v
158160
return v
159161

160-
_var_registry = VarRegistry()
162+
def get(self, name, default):
163+
return self._registry.get(name, default)
161164

162-
def intern_var(name):
163-
return _var_registry.intern_or_make(name)
165+
class NamespaceRegistry(__builtins__.object):
166+
def __init__(self):
167+
self._registry = {}
164168

169+
def find_or_make(self, name):
170+
assert isinstance(name, str)
171+
v = self._registry.get(name, None)
172+
if v is None:
173+
v = Namespace(name)
174+
self._registry[name] = v
175+
return v
165176

166177

167-
def as_var(name):
168-
var = intern_var(name)
169-
def with_fn(fn):
170-
inst = type("W"+fn.__name__, (NativeFn,), {"inner_invoke": fn})()
171-
var.set_root(inst)
172-
return inst
173-
return with_fn
178+
def get(self, name, default):
179+
return self._registry.get(name, default)
180+
181+
_ns_registry = NamespaceRegistry()
182+
183+
def intern_var(ns, name=None):
184+
if name is None:
185+
name = ns
186+
ns = ""
187+
188+
return _ns_registry.find_or_make(ns).intern_or_make(name)
189+
190+
def get_var_if_defined(ns, name):
191+
w_ns = _ns_registry.get(ns, None)
192+
if w_ns is None:
193+
return None
194+
return w_ns.get(name, None)
195+
196+
197+
198+
199+
200+
201+
class Protocol(object.Object):
202+
_type = object.Type("Protocol")
203+
204+
def __init__(self, name):
205+
self._name = name
206+
self._polyfns = {}
207+
self._satisfies = {}
208+
209+
def add_method(self, pfn):
210+
self._polyfns[pfn] = pfn
211+
212+
def add_satisfies(self, tp):
213+
self._satisfies[tp] = tp
214+
215+
def satisfies(self, tp):
216+
return tp in self._satisfies
174217

175218

219+
class PolymorphicFn(BaseCode):
220+
_type = object.Type("PolymorphicFn")
221+
222+
__immutable_fields__ = ["_rev?"]
223+
def __init__(self, name, protocol):
224+
self._name = name
225+
self._dict = {}
226+
self._rev = 0
227+
self._protocol = protocol
228+
protocol.add_method(self)
229+
230+
def extend(self, tp, fn):
231+
self._dict[tp] = fn
232+
self._rev += 1
233+
self._protocol.add_satisfies(tp)
234+
235+
def _invoke(self, args):
236+
a = args[0].type()
237+
return self._dict[a].invoke(args)
238+
239+
class DoublePolymorphicFn(BaseCode):
240+
_type = object.Type("DoublePolymorphicFn")
241+
242+
__immutable_fields__ = ["_rev?"]
243+
def __init__(self, name, protocol):
244+
BaseCode.__init__(self)
245+
self._name = name
246+
self._dict = {}
247+
self._rev = 0
248+
self._protocol = protocol
249+
protocol.add_method(self)
250+
251+
def extend2(self, tp1, tp2, fn):
252+
d1 = self._dict.get(tp1, None)
253+
if d1 is None:
254+
d1 = {}
255+
self._dict[tp1] = d1
256+
d1[tp2] = fn
257+
self._rev += 1
258+
self._protocol.add_satisfies(tp1)
259+
260+
261+
@elidable
262+
def get_fn(self, tp1, tp2, _rev):
263+
d1 = self._dict.get(tp1, None)
264+
assert d1
265+
fn = d1.get(tp2, None)
266+
return promote(fn)
267+
268+
def _invoke(self, args):
269+
assert len(args) >= 2
270+
a = args[0].type()
271+
b = args[1].type()
272+
fn = self.get_fn(a, b, self._rev)
273+
return fn.invoke(args)
274+
275+
def munge(s):
276+
return s.replace("-", "_")
277+
278+
import inspect
279+
def defprotocol(ns, name, methods):
280+
gbls = inspect.currentframe().f_back.f_globals
281+
proto = Protocol(name)
282+
intern_var(ns, name).set_root(proto)
283+
gbls[munge(name)] = proto
284+
for method in methods:
285+
poly = PolymorphicFn(method, proto)
286+
intern_var(ns, method).set_root(poly)
287+
gbls[munge(method)] = poly
288+
289+
290+
## PYTHON FLAGS
291+
CO_VARARGS = 0x4
292+
def wrap_fn(fn):
293+
def as_native_fn(f):
294+
return type("W"+fn.__name__, (NativeFn,), {"inner_invoke": f})()
295+
296+
code = fn.func_code
297+
if code.co_flags & CO_VARARGS:
298+
pass
299+
else:
300+
argc = code.co_argcount
301+
if argc == 0:
302+
return as_native_fn(lambda self, args: fn())
303+
if argc == 1:
304+
return as_native_fn(lambda self, args: fn(args[0]))
305+
if argc == 2:
306+
return as_native_fn(lambda self, args: fn(args[0], args[1]))
307+
if argc == 3:
308+
return as_native_fn(lambda self, args: fn(args[0], args[1]))
309+
310+
311+
def extend(pfn, tp1, tp2=None):
312+
def extend_inner(fn):
313+
if tp2 is None:
314+
pfn.extend(tp1, wrap_fn(fn))
315+
else:
316+
pfn.extend2(tp1, tp2, wrap_fn(fn))
317+
318+
return pfn
319+
320+
return extend_inner
321+
322+
323+
324+
def as_var(ns, name=None):
325+
if name is None:
326+
name = ns
327+
ns = "pixie.stdlib"
328+
var = intern_var(ns, name)
329+
def with_fn(fn):
330+
if not isinstance(fn, BaseCode):
331+
fn = wrap_fn(fn)
332+
var.set_root(fn)
333+
return fn
334+
return with_fn

0 commit comments

Comments
 (0)