func (w *World) Compile(fset *token.FileSet, text string) (Code, os.Error) {
	stmts, err := parser.ParseStmtList(fset, "input", text)
	if err == nil {
		return w.CompileStmtList(fset, stmts)
	}

	// Otherwise try as DeclList.
	decls, err1 := parser.ParseDeclList(fset, "input", text)
	if err1 == nil {
		return w.CompileDeclList(fset, decls)
	}

	// Have to pick an error.
	// Parsing as statement list admits more forms,
	// its error is more likely to be useful.
	return nil, err
}
Exemple #2
0
func main() {
	fmt.Println("Welcome to the Go REPL!")
	fmt.Println("Enter '?' for a list of commands.")

	w := new(World)
	w.pkgs = new(vector.StringVector)
	w.defs = new(vector.StringVector)
	w.code = new(vector.Vector)

	buf := bufio.NewReader(os.Stdin)
	unstable := false
	for {
		if unstable {
			fmt.Print("! ")
		}

		fmt.Print(strings.Join(w.pkgs.Data(), " ") + "> ")

		read, err := buf.ReadString('\n')
		if err != nil {
			println()
			break
		}

		line := read[0 : len(read)-1]
		if len(line) == 0 {
			continue
		}

		w.exec = ""

		switch line[0] {
		case '?':
			fmt.Println("Commands:")
			fmt.Println("\t?\thelp")
			fmt.Println("\t+ (pkg)\timport package")
			fmt.Println("\t- (pkg)\tremove package")
			fmt.Println("\t-[dpc]\tpop last (declaration|package|code)")
			fmt.Println("\t~\treset")
			fmt.Println("\t: (...)\tadd persistent code")
			fmt.Println("\t!\tinspect source")
		case '+':
			w.pkgs.Push(line[2:])
			unstable = true
		case '-':
			if len(line) > 1 && line[1] != ' ' {
				switch line[1] {
				case 'd':
					if w.defs.Len() > 0 {
						w.defs.Pop()
					}
				case 'p':
					if w.pkgs.Len() > 0 {
						w.pkgs.Pop()
					}
				case 'c':
					if w.code.Len() > 0 {
						w.code.Pop()
					}
				}
			} else {
				if len(line) > 2 && w.pkgs.Len() > 0 {
					for i, v := range w.pkgs.Data() {
						if v == line[2:] {
							w.pkgs.Delete(i)
							break
						}
					}
				} else {
					if w.code.Len() > 0 {
						w.code.Pop()
					}
				}
			}

			unstable = compile(w).Len() > 0
		case '~':
			w.pkgs.Resize(0, 0)
			w.defs.Resize(0, 0)
			w.code.Resize(0, 0)
			unstable = false
		case '!':
			fmt.Println(w.source())
		case ':':
			tree, err := parser.ParseStmtList("go-repl", line[2:], nil)
			if err != nil {
				fmt.Println("Parse error:", err)
				continue
			}

			w.code.Push(tree[0])

			unstable = compile(w).Len() > 0
		default:
			var tree interface{}
			tree, err := parser.ParseStmtList("go-repl", line[0:], nil)
			if err != nil {
				tree, err = parser.ParseDeclList("go-repl", line[0:], nil)
				if err != nil {
					fmt.Println("Parse error:", err)
					continue
				}
			}

			changed := false
			switch tree.(type) {
			case []ast.Stmt:
				for _, v := range tree.([]ast.Stmt) {
					str := new(bytes.Buffer)
					printer.Fprint(str, v)

					switch v.(type) {
					case *ast.AssignStmt:
						w.code.Push(v)
						changed = true
					default:
						w.exec = str.String()
					}
				}
			case []ast.Decl:
				for _, v := range tree.([]ast.Decl) {
					str := new(bytes.Buffer)
					printer.Fprint(str, v)

					w.defs.Push(str.String())
				}

				changed = true
			}

			if err := compile(w); err.Len() > 0 {
				fmt.Println("Compile error:", err)

				if changed {
					unstable = true
				}
			} else if out, err := run(); err.Len() > 0 {
				fmt.Println("Runtime error:\n", err)

				if changed {
					unstable = true
				}
			} else {
				fmt.Print(out)
			}
		}
	}
}
Exemple #3
0
func main() {
	fmt.Println("Welcome to the Go REPL!")
	fmt.Println("Enter '?' for a list of commands.")

	w := new(World)
	w.pkgs = &[]string{}
	w.code = &[]interface{}{}
	w.defs = &[]string{}
	w.files = token.NewFileSet()

	buf := bufio.NewReader(os.Stdin)
	unstable := false
	for {
		if unstable {
			fmt.Print("! ")
		}

		fmt.Print(strings.Join(*w.pkgs, " ") + "> ")

		read, err := buf.ReadString('\n')
		if err != nil {
			println()
			break
		}

		line := read[0 : len(read)-1]
		if len(line) == 0 {
			continue
		}

		w.exec = ""

		switch line[0] {
		case '?':
			fmt.Println("Commands:")
			fmt.Println("\t?\thelp")
			fmt.Println("\t+ (pkg)\timport package")
			fmt.Println("\t- (pkg)\tremove package")
			fmt.Println("\t-[dpc]\tpop last (declaration|package|code)")
			fmt.Println("\t~\treset")
			fmt.Println("\t: (...)\tadd persistent code")
			fmt.Println("\t!\tinspect source")
		case '+':
			*w.pkgs = append(*w.pkgs, strings.Trim(line[1:], " "))
			unstable = true
		case '-':
			if len(line) > 1 && line[1] != ' ' {
				switch line[1] {
				case 'd':
					if len(*w.defs) > 0 {
						*w.defs = (*w.defs)[:len(*w.defs)-1]
					}
				case 'p':
					if len(*w.pkgs) > 0 {
						*w.pkgs = (*w.pkgs)[:len(*w.pkgs)-1]
					}
				case 'c':
					if len(*w.code) > 0 {
						*w.code = (*w.code)[:len(*w.code)-1]
					}
				}
			} else {
				if len(line) > 2 && len(*w.pkgs) > 0 {
					for i, v := range *w.pkgs {
						if v == line[2:] {
							copy((*w.pkgs)[i:], (*w.pkgs)[i+1:])
							*w.pkgs = (*w.pkgs)[:len(*w.pkgs)-1]
							break
						}
					}
				} else {
					if len(*w.code) > 0 {
						*w.code = (*w.code)[:len(*w.code)-1]
					}
				}
			}

			unstable = compile(w).Len() > 0
		case '~':
			*w.pkgs = (*w.pkgs)[:0]
			*w.defs = (*w.pkgs)[:0]
			*w.code = (*w.code)[:0]
			unstable = false
		case '!':
			fmt.Println(w.source())
		case ':':
			line = line + ";"
			tree, err := parser.ParseStmtList(w.files, "go-repl", strings.Trim(line[1:], " "))
			if err != nil {
				fmt.Println("Parse error:", err)
				continue
			}

			*w.code = append(*w.code, tree[0])

			unstable = compile(w).Len() > 0
		default:
			line = line + ";"
			var tree interface{}
			tree, err := parser.ParseStmtList(w.files, "go-repl", line[0:])
			if err != nil {
				tree, err = parser.ParseDeclList(w.files, "go-repl", line[0:])
				if err != nil {
					fmt.Println("Parse error:", err)
					continue
				}
			}

			changed := false
			switch tree.(type) {
			case []ast.Stmt:
				for _, v := range tree.([]ast.Stmt) {
					str := new(bytes.Buffer)
					printer.Fprint(str, w.files, v)

					switch v.(type) {
					case *ast.AssignStmt:
						*w.code = append(*w.code, v)
						changed = true
					default:
						w.exec = str.String()
					}
				}
			case []ast.Decl:
				for _, v := range tree.([]ast.Decl) {
					str := new(bytes.Buffer)
					printer.Fprint(str, w.files, v)

					*w.defs = append(*w.defs, str.String())
				}

				changed = true
			}

			if err := compile(w); err.Len() > 0 {
				fmt.Println("Compile error:", err)

				if changed {
					unstable = true
				}
			} else if out, err := run(); err.Len() > 0 {
				fmt.Println("Runtime error:\n", err)

				if changed {
					unstable = true
				}
			} else {
				fmt.Print(out)
			}
		}
	}
}