github.com/dfcfw/lua@v0.0.0-20230325031207-0cc7ffb7b8b9/luar/type.go (about)

     1  package luar
     2  
     3  import (
     4  	"reflect"
     5  
     6  	"github.com/dfcfw/lua"
     7  )
     8  
     9  func checkType(L *lua.LState, idx int) reflect.Type {
    10  	ud := L.CheckUserData(idx)
    11  	return ud.Value.(reflect.Type)
    12  }
    13  
    14  func typeCall(L *lua.LState) int {
    15  	ref := checkType(L, 1)
    16  
    17  	var value reflect.Value
    18  	switch ref.Kind() {
    19  	case reflect.Chan:
    20  		buffer := L.OptInt(2, 0)
    21  
    22  		if buffer < 0 {
    23  			L.ArgError(2, "negative buffer size")
    24  		}
    25  		if ref.ChanDir() != reflect.BothDir {
    26  			L.RaiseError("unidirectional channel type")
    27  		}
    28  
    29  		value = reflect.MakeChan(ref, buffer)
    30  	case reflect.Map:
    31  		value = reflect.MakeMap(ref)
    32  	case reflect.Slice:
    33  		length := L.OptInt(2, 0)
    34  		capacity := L.OptInt(3, length)
    35  
    36  		if length < 0 {
    37  			L.ArgError(2, "negative length")
    38  		}
    39  		if capacity < 0 {
    40  			L.ArgError(3, "negative capacity")
    41  		}
    42  		if length > capacity {
    43  			L.RaiseError("length > capacity")
    44  		}
    45  
    46  		value = reflect.MakeSlice(ref, length, capacity)
    47  	default:
    48  		value = reflect.New(ref)
    49  	}
    50  	L.Push(New(L, value.Interface()))
    51  	return 1
    52  }
    53  
    54  func typeEq(L *lua.LState) int {
    55  	type1 := checkType(L, 1)
    56  	type2 := checkType(L, 2)
    57  	L.Push(lua.LBool(type1 == type2))
    58  	return 1
    59  }