| 1 | #!/usr/bin/env python2
 | 
| 2 | """
 | 
| 3 | four_var_kinds.py
 | 
| 4 | 
 | 
| 5 | From PyCodeObject in Include/code.h:
 | 
| 6 | 
 | 
| 7 |     PyObject *co_names;		/* list of strings (names used) */
 | 
| 8 |     PyObject *co_varnames;	/* tuple of strings (local variable names) */
 | 
| 9 |     PyObject *co_freevars;	/* tuple of strings (free variable names) */
 | 
| 10 |     PyObject *co_cellvars;      /* tuple of strings (cell variable names) */
 | 
| 11 | 
 | 
| 12 |     PyObject *co_consts;	/* list (constants used) */
 | 
| 13 | 
 | 
| 14 | I don't get what these are.
 | 
| 15 | """
 | 
| 16 | # names
 | 
| 17 | # varnames
 | 
| 18 | 
 | 
| 19 | def f(x):
 | 
| 20 |   y = x
 | 
| 21 |   return x
 | 
| 22 | 
 | 
| 23 | class C(object):
 | 
| 24 |   def __init__(self):
 | 
| 25 |     self.x = 1
 | 
| 26 |     y = 2
 | 
| 27 | 
 | 
| 28 | # In Add bytecode:
 | 
| 29 | # co_freevars:        ('left',)
 | 
| 30 | # It makes sense because it's "free" -- not in the frame.
 | 
| 31 | 
 | 
| 32 | # In Adder bytecode:
 | 
| 33 | # co_cellvars:        ('left',)
 | 
| 34 | 
 | 
| 35 | 
 | 
| 36 | # I generally use classes for this, but I do use it for generator expressions.
 | 
| 37 | 
 | 
| 38 | # However the usage is quite low.  If it's down at the CPython levels, then we
 | 
| 39 | # might be able to get rid of it.
 | 
| 40 | # In the case of generator expressions, we could just use dynamic scope?  Not
 | 
| 41 | # lexical scope?  They are equivalent in that case.
 | 
| 42 | 
 | 
| 43 | # Hm in CPython there are only 2 of my own usages!
 | 
| 44 | """
 | 
| 45 | > cpy$names %>% filter(kind == 'free')
 | 
| 46 |                                                             path   code_name
 | 
| 47 | 1                      /home/andy/git/oilshell/oil/core/args.pyc  ParseLikeEcho
 | 
| 48 | 2                   /home/andy/git/oilshell/oil/core/builtin.pyc _PrintDirStack
 | 
| 49 | 
 | 
| 50 | The first is all()
 | 
| 51 | # See ParseLikeEcho in core/args.py:
 | 
| 52 | # if not all(c in self.arity0 for c in arg[1:]):
 | 
| 53 | 
 | 
| 54 | The second is ' '.join()
 | 
| 55 | """
 | 
| 56 | # TODO: I want real closures to run JS on OVM (ES3 probably).  So maybe omit
 | 
| 57 | # cell and free vars?  There # are many ways to compile closures.
 | 
| 58 | #
 | 
| 59 | # Experiment: move everything to 'names' instead of 'varnames'?  What breaks?
 | 
| 60 | # Run unit tests.
 | 
| 61 | 
 | 
| 62 | """
 | 
| 63 | > Names(cpy$names)
 | 
| 64 | # A tibble: 4 x 2
 | 
| 65 |   kind      n
 | 
| 66 |   <chr> <int>
 | 
| 67 | 1 name  14342
 | 
| 68 | 2 var    5435
 | 
| 69 | 3 free     16
 | 
| 70 | 4 cell     14
 | 
| 71 | 
 | 
| 72 | > Names(opy$names)                                                                                                                               
 | 
| 73 | # A tibble: 4 x 2
 | 
| 74 |   kind      n
 | 
| 75 |   <chr> <int>
 | 
| 76 | 1 name  18926
 | 
| 77 | 2 var   16581
 | 
| 78 | 3 free     52
 | 
| 79 | 4 cell     49
 | 
| 80 | """
 | 
| 81 |      
 | 
| 82 | def Adder(left):
 | 
| 83 |   def Add(right):
 | 
| 84 |     return left + right
 | 
| 85 |   return Add
 | 
| 86 | 
 | 
| 87 | a = Adder(3)
 | 
| 88 | print(a(5))
 | 
| 89 | 
 | 
| 90 | 
 | 
| 91 | 
 | 
| 92 | 
 | 
| 93 | 
 |