From 1d433cb5e4b31cc2f0882876cb947420a19f38b2 Mon Sep 17 00:00:00 2001 From: kscarlett Date: Mon, 1 Jan 2018 20:55:54 +0100 Subject: [PATCH] Added running from files --- examples/fibonacci.km | 22 ++++++++++ main.go | 95 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 examples/fibonacci.km diff --git a/examples/fibonacci.km b/examples/fibonacci.km new file mode 100644 index 0000000..70bd628 --- /dev/null +++ b/examples/fibonacci.km @@ -0,0 +1,22 @@ +let fib = fn(x) { + if (x == 0) { + return 0; + } + + if (x == 1) { + return 1; + } + + return fib(x-1) + fib(x-2); +}; + +let main = fn() { + let fibTest = fib(10); + if (fibTest != 55) { + return false; + } else { + return true; + } +}; + +main(); diff --git a/main.go b/main.go index 445d62b..2e3381c 100644 --- a/main.go +++ b/main.go @@ -1,4 +1,4 @@ -package main +/*package main import ( "fmt" @@ -18,3 +18,96 @@ func main() { fmt.Printf("Feel free to type commands!\n") repl.Start(os.Stdin, os.Stdout) } +*/ +package main + +import ( + "fmt" + "io" + "io/ioutil" + "os" + + "github.com/kscarlett/kmonkey/evaluator" + "github.com/kscarlett/kmonkey/lexer" + "github.com/kscarlett/kmonkey/object" + "github.com/kscarlett/kmonkey/parser" + "github.com/kscarlett/kmonkey/repl" + + log "github.com/sirupsen/logrus" + "github.com/ttacon/chalk" + "gopkg.in/alecthomas/kingpin.v2" +) + +var ( + app = kingpin.New("kmonkey", "The kmonkey interpreter") + verbose = app.Flag("verbose", "Enable verbose logging.").Short('v').Bool() + + interactive = app.Command("interactive", "Interactive REPL") + + run = app.Command("run", "Run kmonkey code") + runFile = run.Flag("file", "Code to run").Required().Short('f').ExistingFile() +) + +func init() { + log.SetFormatter(&log.TextFormatter{FullTimestamp: true}) + log.SetOutput(os.Stdout) +} + +func main() { + app.Version("0.1.0") + args, err := app.Parse(os.Args[1:]) + + if *verbose { + log.SetLevel(log.DebugLevel) + } else { + log.SetLevel(log.WarnLevel) + } + + switch kingpin.MustParse(args, err) { + case run.FullCommand(): + log.WithFields(log.Fields{ + "File": *runFile, + "Verbose": *verbose, + }).Debug("Received run command") + + runFromFile() + case interactive.FullCommand(): + startRepl() + } +} + +func runFromFile() { + file, err := ioutil.ReadFile(*runFile) + if err != nil { + log.Fatal(err) + } + + l := lexer.New(string(file)) + p := parser.New(l) + program := p.ParseProgram() + + if len(p.Errors()) != 0 { + printParserErrors(os.Stdout, p.Errors()) + os.Exit(21) + } + + env := object.NewEnvironment() + eval := evaluator.Eval(program, env) + if eval.Inspect() != "NULL" { + fmt.Println(eval.Inspect()) + } +} + +func startRepl() { + fmt.Printf("Starting kmonkey interactive interpreter v%s\n", "0.2.0") // Find a way to get this from app.version + repl.Start(os.Stdin, os.Stdout) +} + +func printParserErrors(out io.Writer, errors []string) { + errColor := chalk.Red.NewStyle().WithTextStyle(chalk.Bold).Style + + io.WriteString(out, errColor("PARSER ERROR!\n")) + for _, msg := range errors { + io.WriteString(out, errColor(" [!] ")+msg+"\n") + } +}