func (fb *functionBuilder) changePath(newPath string) {
	fb.path = newPath
}
changePath changes the current path. Note that the path is initially set at
the creation of the function builder; this method should be called only when
the path changes during the building of the same function, for example when
emitting a render expression.
package compiler
import (
	"fmt"
	"math"
	"reflect"
	"strconv"
	"github.com/open2b/scriggo/ast"
	"github.com/open2b/scriggo/internal/runtime"
)
const (
	maxRegistersCount        = 127
	maxNativeFunctionsCount  = 256
	maxScriggoFunctionsCount = 256
	maxFieldIndexesCount     = 256
	maxSelectCasesCount      = 65536
	maxTypesCount = 256
	maxIntValuesCount     = 1 << 14  
	maxFloatValuesCount   = 1 << 14  
	maxStringValuesCount  = 256
	maxGeneralValuesCount = 256
)
var intType = reflect.TypeOf(0)
var float64Type = reflect.TypeOf(0.0)
var float32Type = reflect.TypeOf(float32(0.0))
var complex128Type = reflect.TypeOf(0i)
var complex64Type = reflect.TypeOf(complex64(0))
var stringType = reflect.TypeOf("")
var emptyInterfaceType = reflect.TypeOf(&[]interface{}{interface{}(nil)}[0]).Elem()
type label runtime.Addr
func encodeRenderContext(ctx ast.Context, inURL, isURLSet bool) runtime.Context {
	c := runtime.Context(ctx)
	if inURL {
		if isURLSet {
			c |= 0b11000000
		} else {
			c |= 0b10000000
		}
	}
	return c
}
func decodeRenderContext(c runtime.Context) (ast.Context, bool, bool) {
	ctx := ast.Context(c & 0b00001111)
	inURL := c&0b10000000 != 0
	isURLSet := false
	if inURL {
		isURLSet = c&0b01000000 != 0
	}
	return ctx, inURL, isURLSet
}
func encodeInt16(v int16) (a, b int8) {
	a = int8(v >> 8)
	b = int8(v)
	return
}
func decodeInt16(a, b int8) int16 {
	return int16(int(a)<<8 | int(uint8(b)))
}
func encodeUint16(v uint16) (a, b int8) {
	a = int8(uint8(v >> 8))
	b = int8(uint8(v))
	return
}
func decodeUint16(a, b int8) uint16 {
	return uint16(uint8(a))<<8 | uint16(uint8(b))
}
func encodeUint24(v uint32) (a, b, c int8) {
	a = int8(uint8(v >> 16))
	b = int8(uint8(v >> 8))
	c = int8(uint8(v))
	return
}
func decodeUint24(a, b, c int8) uint32 {
	return uint32(uint8(a))<<16 | uint32(uint8(b))<<8 | uint32(uint8(c))
}
func encodeValueIndex(t registerType, i int) (a, b int8) {
	a, b = encodeInt16(int16(i))
	a |= int8(t << 6)
	return a, b
}
func decodeValueIndex(a, b int8) (t registerType, i int) {
	return registerType(uint8(a) >> 6), int(decodeUint16(a, b) &^ (3 << 14))
}
func newFunction(pkg, name string, typ reflect.Type, file string, pos *ast.Position) *runtime.Function {
	fn := runtime.Function{
		Pkg:  pkg,
		Name: name,
		Type: typ,
		File: file,
	}
	if pos != nil {
		fn.Pos = &runtime.Position{
			Line:   pos.Line,
			Column: pos.Column,
			Start:  pos.Start,
			End:    pos.End,
		}
	}
	return &fn
}
func newMacro(pkg, name string, typ reflect.Type, format ast.Format, file string, pos *ast.Position) *runtime.Function {
	fn := runtime.Function{
		Pkg:    pkg,
		Name:   name,
		Macro:  true,
		Format: format,
		Type:   typ,
		File:   file,
	}
	if pos != nil {
		fn.Pos = &runtime.Position{
			Line:   pos.Line,
			Column: pos.Column,
			Start:  pos.Start,
			End:    pos.End,
		}
	}
	return &fn
}
func newNativeFunction(pkg, name string, fn interface{}) *runtime.NativeFunction {
	return runtime.NewNativeFunction(pkg, name, fn)
}
type functionBuilder struct {
	fn                     *runtime.Function
	labelAddrs             []runtime.Addr  
	gotos                  map[runtime.Addr]label
	maxRegs                map[registerType]int8  
	numRegs                map[registerType]int8
	scopes                 []map[string]int8
	scopeShifts            []runtime.StackShift
	complexBinaryOpIndexes map[ast.OperatorType]int8  
	complexUnaryOpIndex    int8                       
	text struct {
		addr  runtime.Addr
		txt   [][]byte
		inURL bool
	}
	path string
}
func newBuilder(fn *runtime.Function, path string) *functionBuilder {
	fn.Body = nil
	builder := &functionBuilder{
		fn:                     fn,
		gotos:                  map[runtime.Addr]label{},
		maxRegs:                map[registerType]int8{},
		numRegs:                map[registerType]int8{},
		scopes:                 []map[string]int8{},
		complexBinaryOpIndexes: map[ast.OperatorType]int8{},
		complexUnaryOpIndex:    -1,
		path:                   path,
	}
	return builder
}
func (fb *functionBuilder) currentStackShift() runtime.StackShift {
	return runtime.StackShift{
		fb.numRegs[intRegister],
		fb.numRegs[floatRegister],
		fb.numRegs[stringRegister],
		fb.numRegs[generalRegister],
	}
}
func (fb *functionBuilder) enterScope() {
	fb.scopes = append(fb.scopes, map[string]int8{})
	fb.enterStack()
}
func (fb *functionBuilder) exitScope() {
	fb.scopes = fb.scopes[:len(fb.scopes)-1]
	fb.exitStack()
}
func (fb *functionBuilder) enterStack() {
	scopeShift := fb.currentStackShift()
	fb.scopeShifts = append(fb.scopeShifts, scopeShift)
}
func (fb *functionBuilder) exitStack() {
	shift := fb.scopeShifts[len(fb.scopeShifts)-1]
	fb.numRegs[intRegister] = shift[intRegister]
	fb.numRegs[floatRegister] = shift[floatRegister]
	fb.numRegs[stringRegister] = shift[stringRegister]
	fb.numRegs[generalRegister] = shift[generalRegister]
	fb.scopeShifts = fb.scopeShifts[:len(fb.scopeShifts)-1]
}
func (fb *functionBuilder) newRegister(kind reflect.Kind) int8 {
	t := kindToType(kind)
	num := fb.numRegs[t]
	if num == maxRegistersCount {
		panic(newLimitExceededError(fb.fn.Pos, fb.path, "%s registers count exceeded %d", t, maxRegistersCount))
	}
	fb.allocRegister(t, num+1)
	return num + 1
}
func (fb *functionBuilder) newIndirectRegister() int8 {
	return -fb.newRegister(reflect.Interface)
}
func (fb *functionBuilder) bindVarReg(name string, reg int8) {
	fb.scopes[len(fb.scopes)-1][name] = reg
}
func (fb *functionBuilder) declaredInCurrentScope(v string) (int8, bool) {
	reg, ok := fb.scopes[len(fb.scopes)-1][v]
	return reg, ok
}
func (fb *functionBuilder) declaredInFunc(v string) bool {
	for i := len(fb.scopes) - 1; i >= 0; i-- {
		_, ok := fb.scopes[i][v]
		if ok {
			return true
		}
	}
	return false
}
func (fb *functionBuilder) scopeLookup(n string) int8 {
	for i := len(fb.scopes) - 1; i >= 0; i-- {
		reg, ok := fb.scopes[i][n]
		if ok {
			return reg
		}
	}
	panic(fmt.Sprintf("bug: %s not found", n))
}
func (fb *functionBuilder) addPosAndPath(pos *ast.Position) {
	pc := runtime.Addr(len(fb.fn.Body))
	if fb.fn.DebugInfo == nil {
		fb.fn.DebugInfo = map[runtime.Addr]runtime.DebugInfo{}
	}
	debugInfo := fb.fn.DebugInfo[pc]
	if pos == nil {
		debugInfo.Position.Line = 1
		debugInfo.Position.Column = 1
	} else {
		debugInfo.Position.Line = pos.Line
		debugInfo.Position.Column = pos.Column
		debugInfo.Position.Start = pos.Start
		debugInfo.Position.End = pos.End
	}
	debugInfo.Path = fb.path
	fb.fn.DebugInfo[pc] = debugInfo
}
func (fb *functionBuilder) addOperandKinds(a, b, c reflect.Kind) {
	pc := runtime.Addr(len(fb.fn.Body))
	if fb.fn.DebugInfo == nil {
		fb.fn.DebugInfo = map[runtime.Addr]runtime.DebugInfo{}
	}
	debugInfo := fb.fn.DebugInfo[pc]
	debugInfo.OperandKind = [3]reflect.Kind{a, b, c}
	fb.fn.DebugInfo[pc] = debugInfo
}
func (fb *functionBuilder) addFunctionType(typ reflect.Type) {
	pc := runtime.Addr(len(fb.fn.Body))
	if fb.fn.DebugInfo == nil {
		fb.fn.DebugInfo = map[runtime.Addr]runtime.DebugInfo{}
	}
	debugInfo := fb.fn.DebugInfo[pc]
	debugInfo.FuncType = typ
	fb.fn.DebugInfo[pc] = debugInfo
}