google / grumpy

Grumpy is a Python to Go source code transcompiler and runtime.
Apache License 2.0
10.55k stars 646 forks source link

__builtins__ not defined #50

Open selik opened 7 years ago

selik commented 7 years ago

I'm aware that not all builtins have been written yet. I tried to take a look at what has been written so far:

$ echo 'dir(__builtins__)' | make run
NameError: name '__builtins__' is not defined
exit status 1
make: *** [run] Error 1

I think there's some low-hanging fruit in writing plain Python implementations for a few builtins like sum, map, etc. Where's the right place to write those?

trotterdylan commented 7 years ago

Check out builtin_types.go

meadori commented 7 years ago

I am working through several of these now starting with abs #28. I plan to go after all next. Not sure if it is worth it to open an issue per builtin, or just use this one as catch all.

selik commented 7 years ago

Would it be reasonable to add plain Python implementations to builtin.py instead?

For example:

from itertools import izip

def map(function, *sequences):
    if len(sequences) == 1: # avoid infinite recursion from izip calling map
        return [function(arg) for arg in sequences[0]]
    return [function(*args) for args in izip(*sequences)]
trotterdylan commented 7 years ago

Yeah, I'm OK with that.

meadori commented 7 years ago

I can see two reason for doing it in the Go runtime:

  1. Efficiency - depending on the state of the transpiler and the host Go compiler, writing hand-tuned code in the runtime might lead to a faster implementation (especially for heavily used builtins).
  2. Circularity - in some cases you might have to implement builtins with builtins, thus precluding a pure Python implementaiton (like the use of len above).

We should probably review builtins on a case-by-case basis to determine whether Python or the Go-based runtime is more suitable.

trotterdylan commented 7 years ago

Yep, I think that's a good summary. Long term I expect we'll want all builtins to be written in Go for reason #1 but short term I think it's fine to write some in Python.

selik commented 7 years ago

I defined a map and all in lib\__builtin__.py but it didn't appear in my __main__ global namespace. I expected some magic to make anything in that module available everywhere.

trotterdylan commented 7 years ago

Oh that's right. The way things work right now there's a grumpy.Builtins *Dict that contains all the builtins. The __builtin__ module just copies stuff out of there into its own namespace. When doing a builtin name lookup, grumpy.Builtins is used rather than the __builtin__ module's own dict. That should change so that the __builtin__ dict is the canonical namespace for lookups otherwise code that adds stuff to __builtin__ won't work correctly.

selik commented 7 years ago

Ideally there should be a __builtins__ variable in every module's globals(), that references the __builtin__ module.

>>> __builtins__
<module '__builtin__' (built-in)>
meadori commented 7 years ago

I added a Go implementation of all in #54. any will follow next. It is very similar.