func (g *Gentee) Compile(input, path string) (*Exec, int, error) {
	unitID, err := compiler.Compile(g.Workspace, input, path)
	if err != nil {
		return nil, 0, err
	}
	exec, err := compiler.Link(g.Workspace, unitID)
	return &Exec{Exec: exec}, unitID, err
}
Compile compiles the Gentee source code.
The function returns bytecode, id of the compiled unit and error code.
package gentee
import (
	"fmt"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"github.com/gentee/gentee/compiler"
	"github.com/gentee/gentee/core"
	"github.com/gentee/gentee/vm"
)
const (
	SysSuspend   = vm.SysSuspend
	SysResume    = vm.SysResume
	SysTerminate = vm.SysTerminate
)
type Exec struct {
	*core.Exec
}
type Unit struct {
	*core.Unit
}
type Settings struct {
	vm.Settings
}
type Gentee struct {
	*core.Workspace
}
type EmbedItem struct {
	Prototype string
	Object    interface{}
}
type Custom struct {
	Embedded []EmbedItem
}
type Progress = vm.Progress
type ProgressFunc = vm.ProgressFunc
func str2type(in string) (ret uint16) {
	switch in {
	case ``:
		ret = core.TYPENONE
	case `int`, `thread`:
		ret = core.TYPEINT
	case `bool`:
		ret = core.TYPEBOOL
	case `float`:
		ret = core.TYPEFLOAT
	case `char`:
		ret = core.TYPECHAR
	case `str`:
		ret = core.TYPESTR
	case `range`:
		ret = core.TYPERANGE
	case `buf`:
		ret = core.TYPEBUF
	case `file`:
		ret = core.TYPEFILE
	case `handle`:
		ret = core.TYPEHANDLE
	case `fn`:
		ret = core.TYPEFUNC
	case `error`:
		ret = core.TYPEERROR
	case `set`:
		ret = core.TYPESET
	case `obj`:
		ret = core.TYPEOBJ
	default:
		if in == `arr` || strings.HasPrefix(in, `arr.`) {
			ret = core.TYPEARR
		} else if in == `map` || strings.HasPrefix(in, `map.`) {
			ret = core.TYPEMAP
		} else {
			ret = core.TYPESTRUCT
		}
	}
	return
}
func str2pars(in string) (types []uint16) {
	if len(in) == 0 {
		return
	}
	for _, par := range strings.Split(in, `,`) {
		types = append(types, str2type(strings.TrimSpace(par)))
	}
	return
}
func Customize(custom *Custom) error {
	re, err := regexp.Compile(`^([\wº]+)\(([\w ,\.\*]*)\)\s*([\w\.\*]*)?`)
	if err != nil {
		return err
	}
	for _, v := range custom.Embedded {
		v.Prototype = strings.ReplaceAll(v.Prototype, ` `, ``)
		if len(v.Prototype) == 0 || v.Object == nil {
			return fmt.Errorf("%s %v", vm.ErrorText(vm.ErrCustom), v)
		}
		list := re.FindAllStringSubmatch(v.Prototype, -1)
		vals := list[0]
		if len(vals) < 4 {
			return fmt.Errorf("%s %v", vm.ErrorText(vm.ErrCustom), v)
		}
		t := reflect.TypeOf(v.Object)
		embed := core.Embed{
			Name:     vals[1],
			Pars:     vals[2],
			Ret:      vals[3],
			Code:     uint32(len(vm.EmbedFuncs)),
			Func:     v.Object,
			Return:   str2type(vals[3]),
			Params:   str2pars(vals[2]),
			Variadic: t.IsVariadic(),
			Runtime:  t.NumIn() > 0 && t.In(0) == reflect.TypeOf(&vm.Runtime{}),
			CanError: t.NumOut() >= 1 && t.Out(t.NumOut()-1).String() == `error`,
		}
		vm.EmbedFuncs = append(vm.EmbedFuncs, embed)
	}
	return nil
}
func New() *Gentee {
	g := Gentee{
		Workspace: core.NewVM(vm.EmbedFuncs),
	}
	compiler.InitStdlib(g.Workspace)
	return &g
}