summaryrefslogtreecommitdiff
path: root/src/cmd/gotest/gotry
blob: 52c5d2d5867529bd2dc74ebaf9c1afa454c64d21 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#!/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