Example #1
0
func NewRule(name string, r io.Reader) (*Rule, error) {
	data, err := ioutil.ReadAll(r)
	if err != nil {
		return nil, err
	}

	fset := twik.NewFileSet()
	scope := NewGlobalScope(fset)

	node, err := twik.Parse(fset, name, data)
	if err != nil {
		return nil, err
	}

	return &Rule{
		Name:    name,
		program: node,
		scope:   scope,
		lock:    &sync.Mutex{},
	}, nil
}
Example #2
0
func run() error {
	fset := twik.NewFileSet()
	scope := twik.NewDefaultScope(fset)
	scope.Create("printf", printfFn)
	scope.Create("list", listFn)

	if len(os.Args) > 1 {
		if strings.HasPrefix(os.Args[1], "-") {
			return fmt.Errorf("usage: twik [<source file>]")
		}
		f, err := os.Open(os.Args[1])
		if err != nil {
			return err
		}
		defer f.Close()
		data, err := ioutil.ReadAll(f)
		if err != nil {
			return err
		}
		node, err := twik.Parse(fset, os.Args[1], data)
		if err != nil {
			return err
		}

		_, err = scope.Eval(node)
		return err
	}

	state, err := terminal.MakeRaw(1)
	if err != nil {
		return err
	}
	defer terminal.Restore(1, state)

	t := terminal.NewTerminal(os.Stdout, "> ")
	unclosed := ""
	for {
		line, err := t.ReadLine()
		if err == io.EOF {
			break
		}
		if err != nil {
			return err
		}
		if unclosed != "" {
			line = unclosed + "\n" + line
		}
		unclosed = ""
		t.SetPrompt("> ")
		node, err := twik.ParseString(fset, "", line)
		if err != nil {
			if strings.HasSuffix(err.Error(), "missing )") {
				unclosed = line
				t.SetPrompt(". ")
				continue
			}
			fmt.Println(err)
			continue
		}
		value, err := scope.Eval(node)
		if err != nil {
			fmt.Println(err)
			continue
		}
		if value != nil {
			if reflect.TypeOf(value).Kind() == reflect.Func {
				fmt.Println("#func")
			} else if v, ok := value.([]interface{}); ok {
				if len(v) == 0 {
					fmt.Println("()")
				} else {
					fmt.Print("(list")
					for _, e := range v {
						fmt.Printf(" %#v", e)
					}
					fmt.Println(")")
				}
			} else {
				fmt.Printf("%#v\n", value)
			}
		}
	}
	fmt.Println()
	return nil
}