blob: 0fad4c35fe33cf6ff6b0788c0a9ad915e83e8296 [file] [log] [blame]
Alan Donovan312d1a52017-10-02 10:10:28 -04001// Copyright 2017 The Bazel Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Alan Donovane3deafe2018-10-23 11:05:09 -04005// The starlark command interprets a Starlark file.
Alan Donovan312d1a52017-10-02 10:10:28 -04006// With no arguments, it starts a read-eval-print loop (REPL).
Alan Donovan551f3002018-11-01 09:44:00 -04007package main // import "go.starlark.net/cmd/starlark"
Alan Donovan312d1a52017-10-02 10:10:28 -04008
9import (
Alan Donovan312d1a52017-10-02 10:10:28 -040010 "flag"
11 "fmt"
12 "log"
13 "os"
14 "runtime/pprof"
15 "sort"
16 "strings"
17
Alan Donovan6beab7e2018-10-31 17:53:09 -040018 "go.starlark.net/repl"
19 "go.starlark.net/resolve"
Alan Donovan551f3002018-11-01 09:44:00 -040020 "go.starlark.net/starlark"
Alan Donovan312d1a52017-10-02 10:10:28 -040021)
22
23// flags
24var (
25 cpuprofile = flag.String("cpuprofile", "", "gather CPU profile in this file")
26 showenv = flag.Bool("showenv", false, "on success, print final global environment")
Josh Bleecher Snyderd1cdecf2018-12-07 14:21:37 -080027 execprog = flag.String("c", "", "execute program `prog`")
Alan Donovan312d1a52017-10-02 10:10:28 -040028)
29
30// non-standard dialect flags
31func init() {
32 flag.BoolVar(&resolve.AllowFloat, "fp", resolve.AllowFloat, "allow floating-point numbers")
Alan Donovan312d1a52017-10-02 10:10:28 -040033 flag.BoolVar(&resolve.AllowSet, "set", resolve.AllowSet, "allow set data type")
34 flag.BoolVar(&resolve.AllowLambda, "lambda", resolve.AllowLambda, "allow lambda expressions")
35 flag.BoolVar(&resolve.AllowNestedDef, "nesteddef", resolve.AllowNestedDef, "allow nested def statements")
Hittorp0a5e39a2018-08-09 15:02:30 +030036 flag.BoolVar(&resolve.AllowBitwise, "bitwise", resolve.AllowBitwise, "allow bitwise operations (&, |, ^, ~, <<, and >>)")
Alessandro Arzilli678bafe2018-12-07 17:28:35 +010037 flag.BoolVar(&resolve.AllowRecursion, "recursion", resolve.AllowRecursion, "allow while statements and recursive functions")
Alan Donovan312d1a52017-10-02 10:10:28 -040038}
39
40func main() {
Alan Donovane3deafe2018-10-23 11:05:09 -040041 log.SetPrefix("starlark: ")
Alan Donovan312d1a52017-10-02 10:10:28 -040042 log.SetFlags(0)
43 flag.Parse()
44
45 if *cpuprofile != "" {
46 f, err := os.Create(*cpuprofile)
47 if err != nil {
48 log.Fatal(err)
49 }
50 if err := pprof.StartCPUProfile(f); err != nil {
51 log.Fatal(err)
52 }
53 defer pprof.StopCPUProfile()
54 }
55
Alan Donovane3deafe2018-10-23 11:05:09 -040056 thread := &starlark.Thread{Load: repl.MakeLoad()}
57 globals := make(starlark.StringDict)
alandonovan55968252017-12-22 15:50:31 -050058
Josh Bleecher Snyderd1cdecf2018-12-07 14:21:37 -080059 switch {
60 case flag.NArg() == 1 || *execprog != "":
61 var (
62 filename string
63 src interface{}
64 err error
65 )
66 if *execprog != "" {
67 // Execute provided program.
68 filename = "cmdline"
69 src = *execprog
70 } else {
71 // Execute specified file.
72 filename = flag.Arg(0)
73 }
alandonovan2c1f3622018-12-17 13:10:16 -050074 thread.Name = "exec " + filename
Josh Bleecher Snyderd1cdecf2018-12-07 14:21:37 -080075 globals, err = starlark.ExecFile(thread, filename, src, nil)
alandonovana1b28d82018-03-13 10:59:24 -040076 if err != nil {
alandonovan55968252017-12-22 15:50:31 -050077 repl.PrintError(err)
78 os.Exit(1)
79 }
Josh Bleecher Snyderd1cdecf2018-12-07 14:21:37 -080080 case flag.NArg() == 0:
81 fmt.Println("Welcome to Starlark (go.starlark.net)")
alandonovan2c1f3622018-12-17 13:10:16 -050082 thread.Name = "REPL"
Josh Bleecher Snyderd1cdecf2018-12-07 14:21:37 -080083 repl.REPL(thread, globals)
Alan Donovan312d1a52017-10-02 10:10:28 -040084 default:
Alan Donovane3deafe2018-10-23 11:05:09 -040085 log.Fatal("want at most one Starlark file name")
Alan Donovan312d1a52017-10-02 10:10:28 -040086 }
Alan Donovan312d1a52017-10-02 10:10:28 -040087
88 // Print the global environment.
89 if *showenv {
90 var names []string
91 for name := range globals {
92 if !strings.HasPrefix(name, "_") {
93 names = append(names, name)
94 }
95 }
96 sort.Strings(names)
97 for _, name := range names {
98 fmt.Fprintf(os.Stderr, "%s = %s\n", name, globals[name])
99 }
100 }
101}