| 1 | #!/usr/bin/env bash
|
| 2 | #
|
| 3 | # Usage:
|
| 4 | # ./run.sh <function name>
|
| 5 |
|
| 6 | set -o nounset
|
| 7 | set -o pipefail
|
| 8 | set -o errexit
|
| 9 |
|
| 10 | source common.sh
|
| 11 | source compare.sh
|
| 12 |
|
| 13 | readonly PY=$PY36
|
| 14 |
|
| 15 | _parse-one() {
|
| 16 | #PYTHONPATH=. ./opy_main.py 2to3.grammar parse "$@"
|
| 17 | opyg parse "$@"
|
| 18 | }
|
| 19 |
|
| 20 | parse-test() {
|
| 21 | _parse-one testdata/hello_py3.py # Python 3 print syntax
|
| 22 | echo ---
|
| 23 | _parse-one testdata/hello_py2.py
|
| 24 | }
|
| 25 |
|
| 26 | # It has problems without EOL!
|
| 27 | parser-bug() {
|
| 28 | local out=_tmp/opy_parser_bug.py
|
| 29 | echo -n 'foo = {}' > $out
|
| 30 | _parse-one $out
|
| 31 | }
|
| 32 |
|
| 33 | _compile-and-run() {
|
| 34 | local path=$1
|
| 35 | local basename=$(basename $path .py)
|
| 36 |
|
| 37 | mkdir -p _tmp
|
| 38 | local out=_tmp/${basename}.pyc
|
| 39 |
|
| 40 | #_parse-one $path
|
| 41 |
|
| 42 | # new opy compile
|
| 43 | _compile-one $path $out
|
| 44 | # unmodified pgen2
|
| 45 | #_compile2-one $path $out
|
| 46 |
|
| 47 | ls -l $out
|
| 48 | xxd $out
|
| 49 |
|
| 50 | python $out
|
| 51 | }
|
| 52 |
|
| 53 | _stdlib-compile-and-run() {
|
| 54 | local path=$1
|
| 55 | local basename=$(basename $path .py)
|
| 56 |
|
| 57 | mkdir -p _tmp
|
| 58 | local out=_tmp/${basename}.pyc_stdlib
|
| 59 | misc/stdlib_compile.py $path $out
|
| 60 |
|
| 61 | ls -l $out
|
| 62 | xxd $out
|
| 63 |
|
| 64 | python $out
|
| 65 | }
|
| 66 |
|
| 67 | stdlib-compile-test() {
|
| 68 | _stdlib-compile-and-run testdata/hello_py2.py
|
| 69 | }
|
| 70 |
|
| 71 | # Bad code object because it only has 14 fields. Gah!
|
| 72 | # We have to marshal the old one I guess.
|
| 73 | compile-hello2() {
|
| 74 | local out=_tmp/hello_py2.pyc27
|
| 75 | _compile-and-run testdata/hello_py2.py $out
|
| 76 | }
|
| 77 |
|
| 78 | # This compiles Python 3 to Python 2 bytecode, and runs it.
|
| 79 | compile-hello3() {
|
| 80 | _compile-and-run testdata/hello_py3.py
|
| 81 | }
|
| 82 |
|
| 83 | stdlib-determinism() {
|
| 84 | mkdir -p _tmp/det
|
| 85 | local file=./opy_main.py
|
| 86 |
|
| 87 | # 1 in 10 times we get a diff! And sometimes same diff! wtf!
|
| 88 | #
|
| 89 | # Code is definitely reordered. Basic block. But then there are tiny byte
|
| 90 | # differences too!
|
| 91 |
|
| 92 | #local file=./pytree.py
|
| 93 | _stdlib-compile-one $file _tmp/det/$file.1
|
| 94 | _stdlib-compile-one $file _tmp/det/$file.2
|
| 95 |
|
| 96 | compare-files _tmp/det/$file.{1,2}
|
| 97 | }
|
| 98 |
|
| 99 | stdlib-determinism-loop() {
|
| 100 | determinism-loop _stdlib-compile-one
|
| 101 | }
|
| 102 |
|
| 103 | # We want to fix the bug here. Hm not able to hit it?
|
| 104 | compile2-determinism() {
|
| 105 | mkdir -p _tmp/det
|
| 106 | local file=./opy_main.py
|
| 107 |
|
| 108 | #local file=./pytree.py
|
| 109 | _compile2-one $file _tmp/det/$file.1
|
| 110 | _compile2-one $file _tmp/det/$file.2
|
| 111 |
|
| 112 | compare-files _tmp/det/$file.{1,2}
|
| 113 | }
|
| 114 |
|
| 115 | # Compare stdlib and compile2. They differ every time! Is it because somehow
|
| 116 | # the Python interpreter is in a different state? TODO: Could force iteration
|
| 117 | # order.
|
| 118 |
|
| 119 | stdlib-compile2() {
|
| 120 | mkdir -p _tmp/det
|
| 121 | local file=./opy_main.py
|
| 122 |
|
| 123 | #local file=./pytree.py
|
| 124 | _stdlib-compile-one $file _tmp/det/$file.stdlib
|
| 125 | _compile2-one $file _tmp/det/$file.compile2
|
| 126 |
|
| 127 | compare-files _tmp/det/$file.{stdlib,compile2}
|
| 128 | }
|
| 129 |
|
| 130 | export PYTHONHASHSEED=0
|
| 131 | #export PYTHONHASHSEED=random
|
| 132 |
|
| 133 | compare-opy-tree() {
|
| 134 | diff -u _tmp/opy-{stdlib,stdlib2}/SIZES.txt || true
|
| 135 | #diff -u _tmp/opy-{stdlib,stdlib2}/MD5.txt || true
|
| 136 |
|
| 137 | # Hm even two stdlib runs are different!
|
| 138 | # TODO: find the smallest ones that are different
|
| 139 |
|
| 140 | # Same strings output
|
| 141 | compare-files _tmp/opy-{stdlib,stdlib2}/pytree.pyc
|
| 142 | return
|
| 143 | compare-files _tmp/opy-{stdlib,stdlib2}/opy_main.pyc
|
| 144 | compare-files _tmp/opy-{stdlib,stdlib2}/compiler2/pyassem.pyc
|
| 145 | compare-files _tmp/opy-{stdlib,stdlib2}/compiler2/pycodegen.pyc
|
| 146 | compare-files _tmp/opy-{stdlib,stdlib2}/compiler2/symbols.pyc
|
| 147 | compare-files _tmp/opy-{stdlib,stdlib2}/compiler2/transformer.pyc
|
| 148 | return
|
| 149 |
|
| 150 | #diff -u _tmp/opy-{stdlib,compile2}/MANIFEST.txt
|
| 151 |
|
| 152 | compare-files _tmp/opy-{stdlib,compile2}/util.pyc
|
| 153 | compare-files _tmp/opy-{stdlib,compile2}/pgen2/driver.pyc
|
| 154 | compare-files _tmp/opy-{stdlib,compile2}/opy_main.pyc
|
| 155 | }
|
| 156 |
|
| 157 | compare-osh-tree() {
|
| 158 | #diff -u _tmp/opy-{stdlib,stdlib2}/SIZES.txt || true
|
| 159 | #compare-files _tmp/osh-{ccompile,compile2}/core/id_kind_test.pyc
|
| 160 | compare-files _tmp/osh-{ccompile,compile2}/core/testdbg.pyc
|
| 161 | }
|
| 162 |
|
| 163 | unit-osh() {
|
| 164 | local dir=${1:-_tmp/osh-stdlib}
|
| 165 | local vm=${2:-byterun} # or cpython
|
| 166 | shift 2
|
| 167 | pushd $dir
|
| 168 | if test $vm = byterun; then
|
| 169 | PYTHONPATH=. byterun -c "$@"
|
| 170 | else
|
| 171 | PYTHONPATH=. python "$@"
|
| 172 | fi
|
| 173 | popd
|
| 174 | }
|
| 175 |
|
| 176 | # Combinations of {ccompile, compiler2} x {cpython, byterun}
|
| 177 | compile-run-one() {
|
| 178 | local compiler=${1:-ccompile} # or compile2
|
| 179 | local vm=${2:-byterun} # or cpython
|
| 180 | local py=$3
|
| 181 | shift 3
|
| 182 |
|
| 183 | if ! { test $compiler = ccompile || test $compiler = compile2; } then
|
| 184 | die "Invalid compiler $compiler"
|
| 185 | fi
|
| 186 |
|
| 187 | local dir="_tmp/osh-$compiler"
|
| 188 | local pyc="$dir/$(basename $py)c"
|
| 189 | _$compiler-one $py $pyc
|
| 190 |
|
| 191 | export PYTHONPATH=$dir
|
| 192 | if test $vm = cpython; then
|
| 193 | python $pyc "$@"
|
| 194 | elif test $vm = byterun; then
|
| 195 | #byterun -v -c $pyc "$@"
|
| 196 | byterun -c $pyc "$@"
|
| 197 | else
|
| 198 | die $vm
|
| 199 | fi
|
| 200 | }
|
| 201 |
|
| 202 | compare-sizes() {
|
| 203 | local left=$1
|
| 204 | local right=$2
|
| 205 | find $left -name '*.pyc' -a -printf '%s %P\n' | sort -n
|
| 206 | echo ---
|
| 207 | # Wow, opyc files are bigger! Code is not as optimal or what?
|
| 208 | # Order is roughly the same.
|
| 209 | find $right -name '*.opyc' -a -printf '%s %P\n' | sort -n
|
| 210 | }
|
| 211 |
|
| 212 | compare-opy-sizes() {
|
| 213 | compare-sizes .. _tmp/opy
|
| 214 | }
|
| 215 |
|
| 216 | compare-osh-sizes() {
|
| 217 | # TODO: filter opy out of the left
|
| 218 | compare-sizes .. _tmp/osh
|
| 219 | }
|
| 220 |
|
| 221 | # Doesn't work because of compileFile.
|
| 222 | old-compile-test() {
|
| 223 | PYTHONPATH=. tools/compile.py testdata/hello_py3.py
|
| 224 | }
|
| 225 |
|
| 226 | #
|
| 227 | # Parsing tests subsummed by compiling
|
| 228 | #
|
| 229 |
|
| 230 | # 2to3.grammar is from Python-3.6.1/ Lib/lib2to3/Grammar.txt
|
| 231 | parse-with-pgen2() {
|
| 232 | set +o errexit
|
| 233 | for py in "$@"; do
|
| 234 | _parse-one $py >/dev/null #2>&1
|
| 235 | echo $? $py
|
| 236 | done
|
| 237 | }
|
| 238 |
|
| 239 | # This fails due to some files not using __future__ print_function.
|
| 240 | parse-oil() {
|
| 241 | parse-with-pgen2 *.py ../*.py ../osh/*.py ../core/*.py ../asdl/*.py
|
| 242 | }
|
| 243 |
|
| 244 | # Parse the old Python2 code
|
| 245 | parse-pycompiler2() {
|
| 246 | # parse print statement
|
| 247 | parse-with-pgen2 ~/src/Python-2.7.6/Lib/compiler/*.py
|
| 248 | }
|
| 249 |
|
| 250 | # After lib2to3
|
| 251 | parse-pycompiler() {
|
| 252 | # parse print statement
|
| 253 | parse-with-pgen2 compiler/*.py tools/*.py
|
| 254 | }
|
| 255 |
|
| 256 | #
|
| 257 | # File Management
|
| 258 | #
|
| 259 |
|
| 260 | clear-tokens() {
|
| 261 | rm token.py tokenize.py
|
| 262 | rm -rf --verbose __pycache ../__pycache__
|
| 263 | }
|
| 264 |
|
| 265 | copy-lib2to3() {
|
| 266 | #cp -v $PY/Lib/{token,tokenize}.py .
|
| 267 | #return
|
| 268 |
|
| 269 | # For comparison
|
| 270 | mkdir -p pgen2
|
| 271 |
|
| 272 | cp -v $PY/Lib/lib2to3/{pytree,pygram}.py .
|
| 273 | cp -v $PY/Lib/lib2to3/pgen2/{__init__,driver,grammar,parse,token,tokenize,pgen}.py pgen2
|
| 274 | # The 2to3 grammar supports both Python 2 and Python 3.
|
| 275 | # - it has the old print statement. Well I guess you still want that! Gah.
|
| 276 | cp -v $PY/Lib/lib2to3/Grammar.txt .
|
| 277 | return
|
| 278 |
|
| 279 | cp -v $PY/Parser/Python.asdl .
|
| 280 |
|
| 281 | }
|
| 282 |
|
| 283 | # For compatibility with the compiler package.
|
| 284 | # I kind of want the static type syntax though?
|
| 285 | copy-old-grammar() {
|
| 286 | cp -v $PY27/Grammar/Grammar py27.grammar
|
| 287 | }
|
| 288 |
|
| 289 | copy-pycompiler() {
|
| 290 | # The last version of the pure Python compile package.
|
| 291 | mkdir -p compiler2
|
| 292 | cp -v ~/src/Python-2.7.6/Lib/compiler/*.py compiler2
|
| 293 | }
|
| 294 |
|
| 295 | copy-pycompiler-tools() {
|
| 296 | cp -v ~/src/Python-2.7.6/Tools/compiler/{ast.txt,ACKS,README,*.py} tools/
|
| 297 | }
|
| 298 |
|
| 299 | # Features from Python 3 used? Static types? I guess Python 3.6 has locals with
|
| 300 | # foo: str = 1
|
| 301 | #
|
| 302 | # Do I want that?
|
| 303 | #
|
| 304 | # Main things I ran into were:
|
| 305 | # - print statement
|
| 306 | # - next() is now __next__
|
| 307 | # - io.StringIO vs. cStringIO.cstringIO()
|
| 308 | #
|
| 309 | # And occasional exceptions about encoding. Had to add .encode('utf-8') in a
|
| 310 | # few places.
|
| 311 | #
|
| 312 | # So mostly cosmetic issues.
|
| 313 |
|
| 314 | "$@"
|