added hawk_rtx_getarrvaltally().
All checks were successful
continuous-integration/drone/push Build is passing

Val methods being worked on
This commit is contained in:
2025-11-02 13:27:58 +09:00
parent 2fb423df1a
commit 7640fbe805
5 changed files with 248 additions and 35 deletions

View File

@ -9,7 +9,6 @@ import "weak"
type Instance struct {
c *C.hawk_t // c object
//g *Hawk // go object
g weak.Pointer[Hawk] // go object
}

81
hawk.go
View File

@ -86,8 +86,26 @@ type Val struct {
prev *Val
}
type ValType int
const (
VAL_NIL ValType = C.HAWK_VAL_NIL
VAL_CHAR ValType = C.HAWK_VAL_CHAR
VAL_BCHR ValType = C.HAWK_VAL_BCHR
VAL_INT ValType = C.HAWK_VAL_INT
VAL_FLT ValType = C.HAWK_VAL_FLT
VAL_STR ValType = C.HAWK_VAL_STR
VAL_MBS ValType = C.HAWK_VAL_MBS
VAL_FUN ValType = C.HAWK_VAL_FUN
VAL_MAP ValType = C.HAWK_VAL_MAP
VAL_ARR ValType = C.HAWK_VAL_ARR
VAL_REX ValType = C.HAWK_VAL_REX
VAL_REF ValType = C.HAWK_VAL_REF
VAL_BOB ValType = C.HAWK_VAL_BOB
)
type BitMask C.hawk_bitmask_t
func deregister_instance(h *Hawk) {
fmt.Printf ("DEREGISER INSTANCE %p\n", h)
for h.rtx_head != nil {
@ -269,6 +287,7 @@ func (hawk *Hawk) chain_rtx(rtx *Rtx) {
rtx.next = nil
hawk.rtx_tail = rtx
hawk.rtx_count++
fmt.Printf(">>>> %d\n", hawk.rtx_count)
hawk.rtx_mtx.Unlock()
}
@ -291,6 +310,7 @@ fmt.Printf("head %p tail %p\n", hawk.rtx_tail, hawk.rtx_tail)
rtx.next = nil
rtx.prev = nil
hawk.rtx_count--
fmt.Printf(">>>> %d\n", hawk.rtx_count)
hawk.rtx_mtx.Unlock()
}
@ -546,6 +566,12 @@ func (val *Val) Close() {
}
}
func (val *Val) Type() ValType {
var x C.int
x = C.hawk_rtx_getvaltype(val.rtx.c, val.c)
return ValType(x)
}
/*func (val *Val) ToByte() (byte, error) {
}
@ -605,6 +631,61 @@ func (val* Val) ToByteArr() ([]byte, error) {
return v, nil
}
func (val *Val) ArrayTally() int {
var v C.hawk_ooi_t
// TODO: if not array .. panic or return -1 or 0?
v = C.hawk_rtx_getarrvaltally(val.rtx.c, val.c)
return int(v)
}
// TODO: function get the first index and last index or the capacity
// function to traverse?
func (val *Val) ArrayField(index int) (*Val, error) {
var v *C.hawk_val_t
v = C.hawk_rtx_getarrvalfld(val.rtx.c, val.c, C.hawk_ooi_t(index))
if v == nil { return nil, val.rtx.make_errinfo() }
return val.rtx.make_val(func() *C.hawk_val_t { return v })
}
func (val *Val) MapField(key string) (*Val, error) {
var v *C.hawk_val_t
var uc []C.hawk_uch_t
uc = string_to_uchars(key)
v = C.hawk_rtx_getmapvalfld(val.rtx.c, val.c, &uc[0], C.hawk_oow_t(len(uc)))
if v == nil { return nil, val.rtx.make_errinfo() }
return val.rtx.make_val(func() *C.hawk_val_t { return v })
}
//func (val *Val) SetArrayField(index int, val *Val) error {
//
//}
// TODO: map traversal..
//func (val *Val) SetMapField(key string, val *Val) error {
//}
// -----------------------------------------------------------
var val_type []string = []string{
VAL_NIL: "NIL",
VAL_CHAR: "CHAR",
VAL_BCHR: "BCHR",
VAL_INT: "INT",
VAL_FLT: "FLT",
VAL_STR: "STR",
VAL_MBS: "MBS",
VAL_FUN: "FUN",
VAL_MAP: "MAP",
VAL_ARR: "ARR",
VAL_REX: "REX",
VAL_REF: "REF",
VAL_BOB: "BOB",
}
func (t ValType) String() string {
return val_type[t]
}
// -----------------------------------------------------------
func ucstr_to_rune_slice(str *C.hawk_uch_t) []rune {

View File

@ -14,53 +14,65 @@ func exit_with_error(msg string, err error) {
os.Exit(1)
}
func make_hawk() (*hawk.Hawk, error) {
func make_hawk(script string) (*hawk.Hawk, error) {
var h *hawk.Hawk
var err error
h, err = hawk.New()
if err != nil { return nil, err }
err = h.ParseText(`function x(a1, a2, a3) {
for (i = 0; i < 10; i++) {
printf("hello, world [%d] [%s] [%s]\n", a1, a2, a3);
##if (i == 3) sys::sleep(1);
err = h.ParseText(script)
if err != nil {
h.Close()
return nil, err
}
##return "welcome to the jungle 999";
return 1.9923;
}`)
if err != nil { return nil, err }
return h, nil
}
func run_hawk(h *hawk.Hawk, id int, wg *sync.WaitGroup) {
var r *hawk.Rtx
func run_hawk(h *hawk.Hawk, id int, t *testing.T, wg *sync.WaitGroup) {
var rtx *hawk.Rtx
var v *hawk.Val
//var ret string
var ret []byte //float64
var i int
var err error
defer wg.Done()
r, err = h.NewRtx(fmt.Sprintf("%d", id))
rtx, err = h.NewRtx(fmt.Sprintf("%d", id))
if err != nil {
t.Errorf("failed to create rtx id[%d] - %s", id, err.Error())
return
}
v, err = r.Call("x",
hawk.Must(r.NewVal/*FromInt*/(id + 10)),
hawk.Must(r.NewVal([]byte{'A',66,67,68,69})),
hawk.Must(r.NewVal/*FromStr*/("this is cool")))
if err != nil { exit_with_error("rtx call", err) }
v, err = rtx.Call("x",
hawk.Must(rtx.NewVal/*FromInt*/(id + 10)),
hawk.Must(rtx.NewVal([]byte{'A',66,67,68,69})),
hawk.Must(rtx.NewVal/*FromStr*/("this is cool")))
if err != nil {
t.Errorf("failed to invoke function 'x' for rtx id[%d] - %s", id, err.Error())
rtx.Close()
return
}
ret, err = v.ToByteArr()
if err != nil {
fmt.Printf("failed to get return value - %s\n", err.Error())
} else {
fmt.Printf("RET[%d] => [%v]\n", id, ret)
t.Errorf("failed to get return value for rtx id[%d] - %s", id, err.Error())
rtx.Close()
return
}
fmt.Printf("RET[%d] => [%v]\n", id, ret)
r.Close()
// check if ValCount() returns the right number of values created explicitly
i = rtx.ValCount()
if i != 3 { t.Errorf("the number of val objects for rtx id[%d] must be 3. but %d was returned", id, i) }
rtx.Close()
// it's safe to all ValCount() after Close() has been called.
i = rtx.ValCount()
if i != 0 { t.Errorf("the number of val objects for rtx id[%d] must be 0. but %d was returned", id, i) }
}
func Test1(t *testing.T) {
@ -71,22 +83,130 @@ func Test1(t *testing.T) {
debug.SetGCPercent(100) // enable normal GC
h, err = make_hawk()
if err != nil { exit_with_error("Failed to make hawk", err) }
h, err = make_hawk(`function x(a1, a2, a3) {
for (i = 0; i < 10; i++) {
printf("hello, world [%d] [%s] [%s]\n", a1, a2, a3);
##if (i == 3) sys::sleep(1);
}
##return "welcome to the jungle 999";
return 1.9923;
}`)
if err != nil {
t.Errorf("Failed to make hawk - %s", err.Error())
return
}
for i = 0; i < 10; i++ {
wg.Add(1)
go run_hawk(h, i, &wg)
go run_hawk(h, i, t, &wg)
}
wg.Wait()
fmt.Printf ("%d RTX objects\n", h.RtxCount())
h.Close()
h = nil
// when rtx objects are all closed, the counter must drop to 0
i = h.RtxCount()
if i != 0 { t.Errorf("the number of rtx objects must be 0. but %d was returned", i) }
h.Close()
h = nil
fmt.Printf ("== END of run ==\n")
runtime.GC()
runtime.Gosched()
time.Sleep(1000 * time.Millisecond) // give finalizer time to print
}
func Test2(t *testing.T) {
var h *hawk.Hawk
var rtx *hawk.Rtx
var err error
debug.SetGCPercent(100) // enable normal GC
h, err = make_hawk(`function get_map(s) {
@local x
x["hello"] = s
x[99] = "donkey is running"
x["what"] = "rankey gankey"
x[1.239] = @b"nice value"
return x
}
function get_arr(s) {
@local x;
x = hawk::array(s, (s %% s), 10, 20.99);
for (i in x) print i, x[i];
return x;
}`)
if err != nil {
t.Errorf("Failed to make hawk - %s", err.Error())
return
}
rtx, err = h.NewRtx("test2")
if err != nil {
t.Errorf("failed to create rtx - %s", err.Error())
} else {
var v *hawk.Val
v, err = rtx.Call("get_map", hawk.Must(rtx.NewValFromStr("hawk flies")))
if err != nil {
t.Errorf("failed to call get_map - %s", err.Error())
} else {
if v.Type() != hawk.VAL_MAP {
t.Errorf("the returned value must be %s. but it was %s", hawk.VAL_MAP.String(), v.Type().String())
} else {
var f *hawk.Val
f = hawk.Must(v.MapField("hello"))
if f.Type() != hawk.VAL_STR {
t.Errorf("the value at the hello field must be a string. but it was %s", f.Type().String())
} else {
var sv string
sv = hawk.Must(f.ToStr())
if sv != "hawk flies" {
t.Errorf("the value for the hello field must be 'hawk flies'. but it was %s", sv)
}
}
f, err = v.MapField("HELLO")
if err == nil {
t.Errorf("the value at the HELLO field must not be found. but it was %s", f.Type().String())
}
}
}
v, err = rtx.Call("get_arr", hawk.Must(rtx.NewValFromStr("hawk flies")))
if err != nil {
t.Errorf("failed to call get_arr - %s", err.Error())
} else {
if v.Type() != hawk.VAL_ARR {
t.Errorf("the returned value must be %s. but it was %s", hawk.VAL_ARR.String(), v.Type().String())
} else {
var sz int
var f *hawk.Val
sz = v.ArrayTally()
if sz != 4 {
t.Errorf("the returned value must have 4 elements. but it had %d elements", sz)
}
f = hawk.Must(v.ArrayField(2))
if f.Type() != hawk.VAL_STR {
t.Errorf("the value at the hello field must be a string. but it was %s", f.Type().String())
} else {
var sv string
sv = hawk.Must(f.ToStr())
if sv != "hawk flieshawk flies" {
t.Errorf("the value for the hello field must be 'hawk flieshawk flies'. but it was %s", sv)
}
}
}
}
}
h.Close()
runtime.GC()
runtime.Gosched()
time.Sleep(1000 * time.Millisecond) // give finalizer time to print
}

View File

@ -3373,6 +3373,11 @@ HAWK_EXPORT hawk_val_t* hawk_rtx_getarrvalfld (
hawk_ooi_t index
);
HAWK_EXPORT hawk_ooi_t hawk_rtx_getarrvaltally (
hawk_rtx_t* rtx,
hawk_val_t* arr
);
/**
* The hawk_rtx_makerefval() function creates a reference value.
* \return value on success, #HAWK_NULL on failure

View File

@ -1444,6 +1444,14 @@ hawk_val_t* hawk_rtx_getarrvalfld (hawk_rtx_t* rtx, hawk_val_t* arr, hawk_ooi_t
return HAWK_ARR_DPTR(_arr, index);
}
hawk_ooi_t hawk_rtx_getarrvaltally (hawk_rtx_t* rtx, hawk_val_t* arr)
{
hawk_arr_t* _arr;
HAWK_ASSERT (HAWK_RTX_GETVALTYPE(rtx, arr) == HAWK_VAL_ARR);
_arr = ((hawk_val_arr_t*)arr)->arr;
return HAWK_ARR_TALLY(_arr);
}
hawk_val_t* hawk_rtx_makerefval (hawk_rtx_t* rtx, int id, hawk_val_t** adr)
{
hawk_val_ref_t* val;