blob: 52c5d2d5867529bd2dc74ebaf9c1afa454c64d21 [file] [log] [blame]
#!/usr/bin/env bash
# Copyright 2010 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# Using all the non-test *.go files in the named directory, write
# out a file /tmp/$USER.try.go to evaluate the expressions on the
# command line, perhaps to discover a function or method that
# gives the desired results. See usage message.
# Compile the program and run it.
# Makes egrep,grep work better in general if we put them
# in ordinary C mode instead of what the current language is.
unset LANG
export LC_ALL=C
export LC_CTYPE=C
export GOROOT=${GOROOT:-"@@GOROOT@@"}
eval $(gomake -j1 --no-print-directory -f "$GOROOT"/src/Make.inc go-env)
if [ -z "$O" ]; then
echo 'missing $O - maybe no Make.$GOARCH?' 1>&2
exit 2
fi
# Allow overrides
GC="${_GC:-$GC} -I _test"
GL="${GL:-$LD} -L _test"
AS="$AS"
CC="$CC"
LD="$LD"
export GC GL O AS CC LD
# Macros for tab and quotes for easier readability.
T=' '
BQ='`'
SQ="'"
DQ='"'
SD="$SQ$DQ"
DS="$DQ$SQ"
usage="usage: gotry [packagedirectory] expression ...
Given one expression, gotry attempts to evaluate that expression.
Given multiple expressions, gotry treats them as a list of arguments
and result values and attempts to find a function in the package
that, given the first few expressions as arguments, evaluates to
the remaining expressions as results. If the first expression has
methods, it will also search for applicable methods.
If there are multiple expressions, a package directory must be
specified. If there is a package argument, the expressions are
evaluated in an environment that includes
import . ${DQ}packagedirectory${DQ}
Examples:
gotry 3+4
# evaluates to 7
gotry strings ${SD}abc${DS} ${SD}c${DS} 7-5
# finds strings.Index etc.
gotry regexp ${SQ}MustCompile(${DQ}^[0-9]+${DQ})${SQ} ${SD}12345${DS} true
# finds Regexp.MatchString
"
function fail() {
echo 2>&1 "$@"
exit 2
}
case $# in
0)
fail "$usage"
;;
*)
case "$1" in
-*help|-*'?'|'?')
fail "$usage"
esac
if test -d "$GOROOT/src/pkg/$1"
then
pkg=$(basename $1)
dir=$GOROOT/src/pkg/$1
importdir=$1
shift
case "$pkg" in
os|syscall)
fail "gotry: cannot try packages os or syscall; they are too dangerous"
esac
fi
;;
esac
spaces='[ ][ ]*'
function getFunctions() {
if [ "$pkg" = "" ]
then
return
fi
for file in $dir/*.go
do
case $file in
*_test*)
continue
esac
grep "func$spaces[A-Z]" $file | # TODO: should be Unicode upper case
sed "s/func$spaces//;s/(.*//"
done | sort -u
}
# Generate list of public functions.
functions=$(getFunctions)
# Write file to compile
rm -f /tmp/$USER.try.go
(
cat <<'!'
package main
import (
"os"
"try"
!
if [ "$pkg" != "" ]
then
echo "$T" . '"'$importdir'"'
fi
cat <<!
)
func main() {
try.Main("$pkg", firstArg, functions, args)
}
var functions = map[string] interface{}{
!
for i in $functions
do
echo "$T"'"'$i'": '$i','
done
echo "}"
echo 'var args = []interface{}{'
if [ $# = 1 ]
then
echo "${T}toSlice($1)",
else
for i
do
echo "$T$i",
done
fi
echo "}"
cat <<!
var firstArg = $BQ$1$BQ
var _ os.Error
func toSlice(a ...interface{}) []interface{} { return a }
!
)>/tmp/$USER.try.go
$GC -o /tmp/$USER.try.$O /tmp/$USER.try.go &&
$GL -o /tmp/$USER.try /tmp/$USER.try.$O &&
/tmp/$USER.try "_$@"
rm -f /tmp/$USER.try /tmp/$USER.try.go /tmp/$USER.try.$O