forked from jesperkha/Fizz
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrun.go
120 lines (100 loc) · 2.45 KB
/
run.go
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
package main
import (
"bufio"
"errors"
"fmt"
"os"
"strings"
"github.com/jesperkha/Fizz/env"
"github.com/jesperkha/Fizz/interp"
"github.com/jesperkha/Fizz/lib"
"github.com/jesperkha/Fizz/stmt"
"github.com/jesperkha/Fizz/term"
"github.com/jesperkha/Fizz/util"
)
var (
ErrOneArgOnly = errors.New("expected a single argument, got %d")
validArgs = []string{"--help", "--version", "-f", "-e"}
)
func RunInterpreter() {
parser, err := term.Parse(validArgs)
if err != nil {
util.ErrorAndExit(err)
}
args := parser.Args()
if len(args) > 1 {
util.ErrorAndExit(fmt.Errorf(ErrOneArgOnly.Error(), len(args)))
}
// Early exit options
if parser.HasOption("help") {
fmt.Println(term.HELP)
return
} else if parser.HasOption("version") {
fmt.Printf("Fizz %s\n", VERSION)
return
}
// Subcommands
if parser.SubCommand() == "docs" {
if err := lib.PrintDocs(args[0]); err != nil {
util.ErrorAndExit(err)
}
return
}
// Run terminal mode if no other args are given
if len(args) == 0 {
RunTerminal()
return
}
// Goto directory of file specified
split := strings.Split(args[0], "/")
path := strings.Join(split[:len(split)-1], "/")
name := split[len(split)-1]
os.Chdir(path)
// Run file
e, err := interp.RunFile(name)
// Print global environment if flag is set first
if parser.HasFlag("e") {
fmt.Println(util.FormatPrintValue(e))
}
// Handle error
if err != nil && err != stmt.ErrProgramExit {
util.PrintError(err)
if c := env.GetCallstack(); parser.HasFlag("f") && len(c) > 0 {
util.PrintError(fmt.Errorf(c))
}
os.Exit(1)
}
}
// Leaves the interpreter running as the user inputs code to the terminal.
// Prints out errors but does not terminate until ^C or 'exit'.
func RunTerminal() {
fmt.Println("type 'exit' to terminate session")
scanner := bufio.NewScanner(os.Stdin)
numBlocks, line := 0, 1
totalString, space := "", " "
env.ThrowEnvironment = false
for {
fmt.Printf("%d%s : %s", line, space, strings.Repeat(" ", numBlocks))
scanner.Scan()
input := scanner.Text()
if input == "exit" {
break
}
// Continue with indent after braces
numBlocks += strings.Count(input, "{") - strings.Count(input, "}")
totalString += input + "\n" // Better error handling
if numBlocks <= 0 {
if _, err := interp.Interperate("", totalString); err != nil {
util.PrintError(err)
line--
}
totalString = ""
numBlocks = 0
}
line++
if line == 10 {
space = ""
}
}
fmt.Println("session ended")
}