Ejemplo n.º 1
0
// Works exactly as Eval with exception that it writes the result of executed
// code into `out`.
func (ir *Interpreter) EvalAs(out interface{}, format string, args ...interface{}) error {
	// interpreter thread
	if C.Tcl_GetCurrentThread() == ir.ir.thread {
		ir.ir.cmdbuf.Reset()
		err := sprintf(&ir.ir.cmdbuf, format, args...)
		if err != nil {
			return ir.ir.filt(err)
		}
		err = ir.ir.eval_as(out, ir.ir.cmdbuf.Bytes())
		return ir.ir.filt(err)
	}

	// foreign thread
	buf := buffer_pool.get()
	err := sprintf(&buf, format, args...)
	if err != nil {
		buffer_pool.put(buf)
		return ir.ir.filt(err)
	}
	script := buf.Bytes()
	err = ir.ir.run_and_wait(func() error {
		return ir.ir.filt(ir.ir.eval_as(out, script))
	})
	buffer_pool.put(buf)
	return err
}
Ejemplo n.º 2
0
// Unregisters (deletes) previously registered command set within the `name`
// namespace.
func (ir *Interpreter) UnregisterCommands(name string) error {
	if C.Tcl_GetCurrentThread() == ir.ir.thread {
		return ir.ir.filt(ir.ir.unregister_commands(name))
	}
	return ir.ir.run_and_wait(func() error {
		return ir.ir.filt(ir.ir.unregister_commands(name))
	})
}
Ejemplo n.º 3
0
// Register multiple TCL command within the `name` namespace. The method uses
// runtime reflection and registers only those methods of the `val` which have
// one of the following prefixes: "TCL" or "TCL_". The name of the resulting
// command doesn't include the prefix.
func (ir *Interpreter) RegisterCommands(name string, val interface{}) error {
	if C.Tcl_GetCurrentThread() == ir.ir.thread {
		return ir.ir.filt(ir.ir.register_commands(name, val))
	}
	return ir.ir.run_and_wait(func() error {
		return ir.ir.filt(ir.ir.register_commands(name, val))
	})
}
Ejemplo n.º 4
0
func (ir *Interpreter) UploadImage(name string, img image.Image) error {
	if C.Tcl_GetCurrentThread() == ir.ir.thread {
		return ir.ir.filt(ir.ir.upload_image(name, img))
	}
	return ir.ir.run_and_wait(func() error {
		return ir.ir.filt(ir.ir.upload_image(name, img))
	})
}
Ejemplo n.º 5
0
// Works the same way as Eval("%{}", byte_slice), but avoids unnecessary
// buffering.
func (ir *Interpreter) EvalBytes(s []byte) error {
	if C.Tcl_GetCurrentThread() == ir.ir.thread {
		return ir.ir.filt(ir.ir.eval(s))
	}
	return ir.ir.run_and_wait(func() error {
		return ir.ir.filt(ir.ir.eval(s))
	})
}
Ejemplo n.º 6
0
func (ir *Interpreter) Eval(args ...interface{}) error {
	if C.Tcl_GetCurrentThread() == ir.ir.thread {
		return ir.ir.filt(ir.ir.eval(args...))
	}
	return ir.ir.run_and_wait(func() error {
		return ir.ir.filt(ir.ir.eval(args...))
	})
}
Ejemplo n.º 7
0
// Every TCL error goes through the filter passed to this function. If you pass
// nil, then no error filter is set.
func (ir *Interpreter) ErrorFilter(filt func(error) error) {
	if C.Tcl_GetCurrentThread() == ir.ir.thread {
		ir.ir.errfilt = filt
	}
	ir.ir.run_and_wait(func() error {
		ir.ir.errfilt = filt
		return nil
	})
}
Ejemplo n.º 8
0
func new_interpreter(init interface{}) (*interpreter, error) {
	ir := &interpreter{
		C:              C.Tcl_CreateInterp(),
		errfilt:        func(err error) error { return err },
		commands:       make(map[string]interface{}),
		methods:        make(map[string]interface{}),
		method_handles: make(map[string][]int),
		valuesbuf:      make([]reflect.Value, 0, 10),
		queue:          make(chan async_action, 50),
		thread:         C.Tcl_GetCurrentThread(),
	}

	C.Tcl_FindExecutable(C.CString(os.Args[0]))

	switch realinit := init.(type) {
	case string:
		err := ir.eval([]byte(realinit))
		if err != nil {
			panic(err)
		}
	case func(*interpreter):
		realinit(ir)
	}

	status := C.Tcl_Init(ir.C)
	if status != C.TCL_OK {
		return nil, errors.New(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}

	status = C.Tk_Init(ir.C)
	if status != C.TCL_OK {
		return nil, errors.New(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}

	ir.id = global_handles.get_handle_for_value(ir)
	runtime.SetFinalizer(ir, release_interpreter)
	return ir, nil
}
Ejemplo n.º 9
0
func new_interpreter() (*interpreter, error) {
	ir := &interpreter{
		C:         C.Tcl_CreateInterp(),
		errfilt:   func(err error) error { return err },
		commands:  make(map[string]interface{}),
		channels:  make(map[string]interface{}),
		valuesbuf: make([]reflect.Value, 0, 10),
		queue:     make(chan async_action, 50),
		thread:    C.Tcl_GetCurrentThread(),
	}

	status := C.Tcl_Init(ir.C)
	if status != C.TCL_OK {
		return nil, errors.New(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}

	status = C.Tk_Init(ir.C)
	if status != C.TCL_OK {
		return nil, errors.New(C.GoString(C.Tcl_GetStringResult(ir.C)))
	}

	return ir, nil
}
Ejemplo n.º 10
0
func (ir *Interpreter) MainLoop() {
	ir.thread = C.Tcl_GetCurrentThread()
	C.Tk_MainLoop()
}