func (l *State) ProtectedCall(argCount, resultCount, errorFunction int) error {
	return l.ProtectedCallWithContinuation(argCount, resultCount, errorFunction, 0, nil)
}
ProtectedCall calls a function in protected mode. Both argCount and
resultCount have the same meaning as in Call. If there are no errors
during the call, ProtectedCall behaves exactly like Call.

However, if there is any error, ProtectedCall catches it, pushes a single
value on the stack (the error message), and returns an error. Like Call,
ProtectedCall always removes the function and its arguments from the stack.

If errorFunction is 0, then the error message returned on the stack is
exactly the original error message. Otherwise, errorFunction is the stack
index of an error handler (in the Lua C, message handler). This cannot be
a pseudo-index in the current implementation. In case of runtime errors,
this function will be called with the error message and its return value
will be the message returned on the stack by ProtectedCall.

Typically, the error handler is used to add more debug information to the
error message, such as a stack traceback. Such information cannot be
gathered after the return of ProtectedCall, since by then, the stack has
unwound.

The possible errors are the following:

RuntimeError  a runtime error
MemoryError   allocating memory, the error handler is not called
ErrorError    running the error handler

http://www.lua.org/manual/5.2/manual.html#lua_pcall
package lua
import (
	"errors"
	"fmt"
	"io"
	"math"
	"strings"
)
const MultipleReturns = -1
const (
	HookCall, MaskCall = iota, 1 << iota
	HookReturn, MaskReturn
	HookLine, MaskLine
	HookCount, MaskCount
	HookTailCall, MaskTailCall
)
var (
	SyntaxError = errors.New("syntax error")
	MemoryError = errors.New("memory error")
	ErrorError  = errors.New("error within the error handler")
	FileError   = errors.New("file error")
)
type RuntimeError string
func (r RuntimeError) Error() string { return "runtime error: " + string(r) }
type Type int
const (
	TypeNil Type = iota
	TypeBoolean
	TypeLightUserData
	TypeNumber
	TypeString
	TypeTable
	TypeFunction
	TypeUserData
	TypeThread
	TypeCount
	TypeNone = TypeNil - 1
)
type Operator int
const (
	OpAdd        Operator = iota  
	OpSub                         
	OpMul                         
	OpDiv                         
	OpMod                         
	OpPow                         
	OpUnaryMinus                  
)
type ComparisonOperator int
const (
	OpEq ComparisonOperator = iota  
	OpLT                            
	OpLE                            
)
const (
	RegistryIndex = firstPseudoIndex
	RegistryIndexMainThread = iota
	RegistryIndexGlobals
)
const Signature = "\033Lua"
const MinStack = 20
const (
	VersionMajor  = 5
	VersionMinor  = 2
	VersionNumber = 502
	VersionString = "Lua " + string('0'+VersionMajor) + "." + string('0'+VersionMinor)
)
type RegistryFunction struct {
	Name     string
	Function Function
}
type Debug struct {
	Event int
	Name string
	NameKind string
	What string
	Source string
	ShortSource string
	CurrentLine int
	LineDefined int
	LastLineDefined int
	UpValueCount int
	ParameterCount int
	IsVarArg bool
	IsTailCall bool
	callInfo *callInfo
}
type Hook func(state *State, activationRecord Debug)
type Function func(state *State) int
type pc int
type callStatus byte
const (
	callStatusLua                callStatus = 1 << iota  
	callStatusHooked                                     
	callStatusReentry                                    
	callStatusYielded                                    
	callStatusYieldableProtected                         
	callStatusError                                      
	callStatusTail                                       
	callStatusHookYielded                                
)
type State struct {
	error                 error
	shouldYield           bool
	top                   int  
	global                *globalState
	callInfo              *callInfo  
	oldPC                 pc         
	stackLast             int        
	stack                 []value
	nonYieldableCallCount int
	nestedGoCallCount     int
	hookMask              byte
	allowHook             bool
	internalHook          bool
	baseHookCount         int
	hookCount             int
	hooker                Hook
	upValues              *openUpValue
	errorFunction         int       
	baseCallInfo          callInfo  
	protectFunction       func()
}
type globalState struct {
	mainThread         *State
	tagMethodNames     [tmCount]string
	metaTables         [TypeCount]*table  
	registry           *table
	panicFunction      Function  
	version            *float64  
	memoryErrorMessage string
}
func (g *globalState) metaTable(o value) *table {
	var t Type
	switch o.(type) {
	case nil:
		t = TypeNil
	case bool:
		t = TypeBoolean
	case float64:
		t = TypeNumber
	case string:
		t = TypeString
	case *table:
		t = TypeTable
	case *goFunction:
		t = TypeFunction
	case closure:
		t = TypeFunction
	case *userData:
		t = TypeUserData
	case *State:
		t = TypeThread
	default:
		return nil
	}
	return g.metaTables[t]
}
func (l *State) adjustResults(resultCount int) {
	if resultCount == MultipleReturns && l.callInfo.top < l.top {
		l.callInfo.setTop(l.top)
	}
}
func (l *State) apiIncrementTop() {
	l.top++
	if apiCheck && l.top > l.callInfo.top {
		panic("stack overflow")
	}
}
func (l *State) apiPush(v value) {
	l.push(v)
	if apiCheck && l.top > l.callInfo.top {
		panic("stack overflow")
	}
}
func (l *State) checkElementCount(n int) {
	if apiCheck && n >= l.top-l.callInfo.function {
		panic("not enough elements in the stack")
	}
}
func (l *State) checkResults(argCount, resultCount int) {
	if apiCheck && resultCount != MultipleReturns && l.callInfo.top-l.top < resultCount-argCount {
		panic("results from function overflow current stack size")
	}
}
func (l *State) Context() (int, bool, error) {
	if l.callInfo.isCallStatus(callStatusYielded) {
		return l.callInfo.context, l.callInfo.shouldYield, l.callInfo.error
	}
	return 0, false, nil
}
func (l *State) CallWithContinuation(argCount, resultCount, context int, continuation Function) {
	if apiCheck && continuation != nil && l.callInfo.isLua() {
		panic("cannot use continuations inside hooks")
	}
	l.checkElementCount(argCount + 1)
	if apiCheck && l.shouldYield {
		panic("cannot do calls on non-normal thread")
	}
	l.checkResults(argCount, resultCount)
	f := l.top - (argCount + 1)
	if continuation != nil && l.nonYieldableCallCount == 0 {  
		l.callInfo.continuation = continuation
		l.callInfo.context = context
		l.call(f, resultCount, true)  
	} else {  
		l.call(f, resultCount, false)  
	}
	l.adjustResults(resultCount)
}