Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2916382
iteration.h
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
iteration.h
View Options
#ifndef SV_ITERATION_H
#define SV_ITERATION_H
#include
"ant.h"
#include
"async.h"
#include
"utf8.h"
#include
"silver/engine.h"
#include
"modules/symbol.h"
#include
"modules/collections.h"
#define SV_ITER_GENERIC 0
#define SV_ITER_ARRAY 1
#define SV_ITER_MAP 2
#define SV_ITER_SET 3
#define SV_ITER_STRING 4
static
inline
jsval_t
sv_op_for_in
(
sv_vm_t
*
vm
,
ant_t
*
js
)
{
jsval_t
obj
=
vm
->
stack
[
--
vm
->
sp
];
jsval_t
keys
=
js_for_in_keys
(
js
,
obj
);
if
(
is_err
(
keys
))
return
keys
;
vm
->
stack
[
vm
->
sp
++
]
=
keys
;
return
tov
(
0
);
}
static
inline
bool
sv_is_map_iter
(
ant_t
*
js
,
jsval_t
obj
,
map_iterator_state_t
**
out_state
,
iter_type_t
*
out_type
)
{
if
(
vtype
(
obj
)
!=
T_OBJ
)
return
false
;
jsval_t
state_val
=
js_get_slot
(
js
,
obj
,
SLOT_ITER_STATE
);
if
(
vtype
(
state_val
)
==
T_UNDEF
)
return
false
;
map_iterator_state_t
*
st
=
(
map_iterator_state_t
*
)(
uintptr_t
)
js_getnum
(
state_val
);
if
(
!
st
)
return
false
;
if
(
st
->
type
>
ITER_TYPE_MAP_ENTRIES
)
return
false
;
*
out_state
=
st
;
*
out_type
=
st
->
type
;
return
true
;
}
static
inline
bool
sv_is_set_iter
(
ant_t
*
js
,
jsval_t
obj
,
set_iterator_state_t
**
out_state
,
iter_type_t
*
out_type
)
{
if
(
vtype
(
obj
)
!=
T_OBJ
)
return
false
;
jsval_t
state_val
=
js_get_slot
(
js
,
obj
,
SLOT_ITER_STATE
);
if
(
vtype
(
state_val
)
==
T_UNDEF
)
return
false
;
set_iterator_state_t
*
st
=
(
set_iterator_state_t
*
)(
uintptr_t
)
js_getnum
(
state_val
);
if
(
!
st
)
return
false
;
if
(
st
->
type
!=
ITER_TYPE_SET_VALUES
&&
st
->
type
!=
ITER_TYPE_SET_ENTRIES
)
return
false
;
*
out_state
=
st
;
*
out_type
=
st
->
type
;
return
true
;
}
static
inline
jsval_t
sv_op_for_of
(
sv_vm_t
*
vm
,
ant_t
*
js
)
{
jsval_t
iterable
=
vm
->
stack
[
--
vm
->
sp
];
if
(
vtype
(
iterable
)
==
T_ARR
)
{
vm
->
stack
[
vm
->
sp
++
]
=
iterable
;
vm
->
stack
[
vm
->
sp
++
]
=
tov
(
0
);
vm
->
stack
[
vm
->
sp
++
]
=
tov
(
SV_ITER_ARRAY
);
return
tov
(
0
);
}
if
(
vtype
(
iterable
)
==
T_STR
)
{
if
(
is_rope
(
js
,
iterable
))
{
iterable
=
rope_flatten
(
js
,
iterable
);
if
(
is_err
(
iterable
))
return
iterable
;
}
vm
->
stack
[
vm
->
sp
++
]
=
iterable
;
vm
->
stack
[
vm
->
sp
++
]
=
tov
(
0
);
vm
->
stack
[
vm
->
sp
++
]
=
tov
(
SV_ITER_STRING
);
return
tov
(
0
);
}
jsval_t
iter_fn
=
js_get_sym
(
js
,
iterable
,
get_iterator_sym
());
uint8_t
ft
=
vtype
(
iter_fn
);
if
(
ft
!=
T_FUNC
&&
ft
!=
T_CFUNC
)
return
js_mkerr
(
js
,
"not iterable"
);
jsval_t
iterator
=
sv_vm_call
(
vm
,
js
,
iter_fn
,
iterable
,
NULL
,
0
,
NULL
,
false
);
if
(
is_err
(
iterator
))
return
iterator
;
map_iterator_state_t
*
map_st
;
iter_type_t
map_type
;
if
(
sv_is_map_iter
(
js
,
iterator
,
&
map_st
,
&
map_type
))
{
vm
->
stack
[
vm
->
sp
++
]
=
ANT_PTR
(
map_st
);
vm
->
stack
[
vm
->
sp
++
]
=
tov
((
double
)
map_type
);
vm
->
stack
[
vm
->
sp
++
]
=
tov
(
SV_ITER_MAP
);
return
tov
(
0
);
}
set_iterator_state_t
*
set_st
;
iter_type_t
set_type
;
if
(
sv_is_set_iter
(
js
,
iterator
,
&
set_st
,
&
set_type
))
{
vm
->
stack
[
vm
->
sp
++
]
=
ANT_PTR
(
set_st
);
vm
->
stack
[
vm
->
sp
++
]
=
tov
((
double
)
set_type
);
vm
->
stack
[
vm
->
sp
++
]
=
tov
(
SV_ITER_SET
);
return
tov
(
0
);
}
jsval_t
next_method
=
js_getprop_fallback
(
js
,
iterator
,
"next"
);
vm
->
stack
[
vm
->
sp
++
]
=
iterator
;
vm
->
stack
[
vm
->
sp
++
]
=
next_method
;
vm
->
stack
[
vm
->
sp
++
]
=
tov
(
SV_ITER_GENERIC
);
return
tov
(
0
);
}
static
inline
jsval_t
sv_op_for_await_of
(
sv_vm_t
*
vm
,
ant_t
*
js
)
{
jsval_t
iterable
=
vm
->
stack
[
--
vm
->
sp
];
jsval_t
iter_fn
=
js_get_sym
(
js
,
iterable
,
get_asyncIterator_sym
());
uint8_t
ft
=
vtype
(
iter_fn
);
if
(
ft
!=
T_FUNC
&&
ft
!=
T_CFUNC
)
{
iter_fn
=
js_get_sym
(
js
,
iterable
,
get_iterator_sym
());
ft
=
vtype
(
iter_fn
);
if
(
ft
!=
T_FUNC
&&
ft
!=
T_CFUNC
)
return
js_mkerr
(
js
,
"not iterable"
);
}
jsval_t
iterator
=
sv_vm_call
(
vm
,
js
,
iter_fn
,
iterable
,
NULL
,
0
,
NULL
,
false
);
if
(
is_err
(
iterator
))
return
iterator
;
jsval_t
next_method
=
js_getprop_fallback
(
js
,
iterator
,
"next"
);
vm
->
stack
[
vm
->
sp
++
]
=
iterator
;
vm
->
stack
[
vm
->
sp
++
]
=
next_method
;
vm
->
stack
[
vm
->
sp
++
]
=
tov
(
SV_ITER_GENERIC
);
return
tov
(
0
);
}
static
inline
jsval_t
sv_op_iter_next
(
sv_vm_t
*
vm
,
ant_t
*
js
)
{
int
tag
=
(
int
)
js_getnum
(
vm
->
stack
[
vm
->
sp
-
1
]);
switch
(
tag
)
{
case
SV_ITER_ARRAY
:
{
jsval_t
arr
=
vm
->
stack
[
vm
->
sp
-
3
];
int
idx
=
(
int
)
js_getnum
(
vm
->
stack
[
vm
->
sp
-
2
]);
jsoff_t
len
=
js_arr_len
(
js
,
arr
);
if
(
idx
>=
(
int
)
len
)
{
vm
->
stack
[
vm
->
sp
++
]
=
js_mkundef
();
vm
->
stack
[
vm
->
sp
++
]
=
js_true
;
}
else
{
vm
->
stack
[
vm
->
sp
++
]
=
js_arr_get
(
js
,
arr
,
(
jsoff_t
)
idx
);
vm
->
stack
[
vm
->
sp
++
]
=
js_false
;
vm
->
stack
[
vm
->
sp
-
4
]
=
tov
(
idx
+
1
);
}
return
tov
(
0
);
}
case
SV_ITER_MAP
:
{
map_iterator_state_t
*
st
=
(
map_iterator_state_t
*
)(
uintptr_t
)
js_getnum
(
vm
->
stack
[
vm
->
sp
-
3
]);
if
(
!
st
->
current
)
{
vm
->
stack
[
vm
->
sp
++
]
=
js_mkundef
();
vm
->
stack
[
vm
->
sp
++
]
=
js_true
;
}
else
{
map_entry_t
*
entry
=
st
->
current
;
jsval_t
value
;
switch
(
st
->
type
)
{
case
ITER_TYPE_MAP_VALUES
:
value
=
entry
->
value
;
break
;
case
ITER_TYPE_MAP_KEYS
:
value
=
js_mkstr
(
js
,
entry
->
key
,
strlen
(
entry
->
key
));
break
;
case
ITER_TYPE_MAP_ENTRIES
:
{
jsval_t
pair
=
js_mkarr
(
js
);
js_arr_push
(
js
,
pair
,
js_mkstr
(
js
,
entry
->
key
,
strlen
(
entry
->
key
)));
js_arr_push
(
js
,
pair
,
entry
->
value
);
value
=
pair
;
break
;
}
default
:
value
=
js_mkundef
();
}
st
->
current
=
entry
->
hh
.
next
;
vm
->
stack
[
vm
->
sp
++
]
=
value
;
vm
->
stack
[
vm
->
sp
++
]
=
js_false
;
}
return
tov
(
0
);
}
case
SV_ITER_SET
:
{
set_iterator_state_t
*
st
=
(
set_iterator_state_t
*
)(
uintptr_t
)
js_getnum
(
vm
->
stack
[
vm
->
sp
-
3
]);
if
(
!
st
->
current
)
{
vm
->
stack
[
vm
->
sp
++
]
=
js_mkundef
();
vm
->
stack
[
vm
->
sp
++
]
=
js_true
;
}
else
{
set_entry_t
*
entry
=
st
->
current
;
jsval_t
value
;
if
(
st
->
type
==
ITER_TYPE_SET_ENTRIES
)
{
jsval_t
pair
=
js_mkarr
(
js
);
js_arr_push
(
js
,
pair
,
entry
->
value
);
js_arr_push
(
js
,
pair
,
entry
->
value
);
value
=
pair
;
}
else
{
value
=
entry
->
value
;
}
st
->
current
=
entry
->
hh
.
next
;
vm
->
stack
[
vm
->
sp
++
]
=
value
;
vm
->
stack
[
vm
->
sp
++
]
=
js_false
;
}
return
tov
(
0
);
}
case
SV_ITER_STRING
:
{
jsval_t
str
=
vm
->
stack
[
vm
->
sp
-
3
];
int
idx
=
(
int
)
js_getnum
(
vm
->
stack
[
vm
->
sp
-
2
]);
jsoff_t
slen
=
str_len_fast
(
js
,
str
);
if
(
idx
>=
(
int
)
slen
)
{
vm
->
stack
[
vm
->
sp
++
]
=
js_mkundef
();
vm
->
stack
[
vm
->
sp
++
]
=
js_true
;
}
else
{
jsoff_t
off
=
vstr
(
js
,
str
,
NULL
);
utf8proc_int32_t
cp
;
jsoff_t
cb_len
=
(
jsoff_t
)
utf8_next
((
const
utf8proc_uint8_t
*
)
&
js
->
mem
[
off
+
idx
],
(
utf8proc_ssize_t
)(
slen
-
idx
),
&
cp
);
vm
->
stack
[
vm
->
sp
++
]
=
js_mkstr
(
js
,
(
char
*
)
&
js
->
mem
[
off
+
idx
],
cb_len
);
vm
->
stack
[
vm
->
sp
++
]
=
js_false
;
vm
->
stack
[
vm
->
sp
-
4
]
=
tov
(
idx
+
(
int
)
cb_len
);
}
return
tov
(
0
);
}
default
:
{
jsval_t
next_method
=
vm
->
stack
[
vm
->
sp
-
2
];
jsval_t
iterator
=
vm
->
stack
[
vm
->
sp
-
3
];
uint8_t
ft
=
vtype
(
next_method
);
if
(
ft
!=
T_FUNC
&&
ft
!=
T_CFUNC
)
return
js_mkerr
(
js
,
"iterator.next is not a function"
);
jsval_t
result
=
sv_vm_call
(
vm
,
js
,
next_method
,
iterator
,
NULL
,
0
,
NULL
,
false
);
if
(
is_err
(
result
))
return
result
;
if
(
!
is_object_type
(
result
))
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Iterator result is not an object"
);
jsval_t
done
=
js_getprop_fallback
(
js
,
result
,
"done"
);
jsval_t
value
=
js_getprop_fallback
(
js
,
result
,
"value"
);
vm
->
stack
[
vm
->
sp
++
]
=
value
;
vm
->
stack
[
vm
->
sp
++
]
=
mkval
(
T_BOOL
,
js_truthy
(
js
,
done
));
return
tov
(
0
);
}}
}
static
inline
void
sv_op_iter_get_value
(
sv_vm_t
*
vm
,
ant_t
*
js
)
{
jsval_t
obj
=
vm
->
stack
[
--
vm
->
sp
];
jsval_t
done
=
js_getprop_fallback
(
js
,
obj
,
"done"
);
jsval_t
value
=
js_getprop_fallback
(
js
,
obj
,
"value"
);
vm
->
stack
[
vm
->
sp
++
]
=
value
;
vm
->
stack
[
vm
->
sp
++
]
=
mkval
(
T_BOOL
,
js_truthy
(
js
,
done
));
}
static
inline
void
sv_op_iter_close
(
sv_vm_t
*
vm
,
ant_t
*
js
)
{
int
tag
=
(
int
)
js_getnum
(
vm
->
stack
[
vm
->
sp
-
1
]);
if
(
tag
==
SV_ITER_GENERIC
)
{
jsval_t
iterator
=
vm
->
stack
[
vm
->
sp
-
3
];
jsval_t
return_fn
=
js_getprop_fallback
(
js
,
iterator
,
"return"
);
uint8_t
ft
=
vtype
(
return_fn
);
if
(
ft
==
T_FUNC
||
ft
==
T_CFUNC
)
sv_vm_call
(
vm
,
js
,
return_fn
,
iterator
,
NULL
,
0
,
NULL
,
false
);
}
vm
->
sp
-=
3
;
}
static
inline
jsval_t
sv_op_iter_call
(
sv_vm_t
*
vm
,
ant_t
*
js
,
uint8_t
*
ip
)
{
jsval_t
method
=
vm
->
stack
[
vm
->
sp
-
1
];
jsval_t
iterator
=
vm
->
stack
[
vm
->
sp
-
4
];
uint8_t
ft
=
vtype
(
method
);
if
(
ft
!=
T_FUNC
&&
ft
!=
T_CFUNC
)
return
js_mkerr
(
js
,
"iterator method is not callable"
);
jsval_t
result
=
sv_vm_call
(
vm
,
js
,
method
,
iterator
,
NULL
,
0
,
NULL
,
false
);
if
(
is_err
(
result
))
return
result
;
vm
->
stack
[
vm
->
sp
++
]
=
result
;
return
tov
(
0
);
}
static
inline
jsval_t
sv_op_await_iter_next
(
sv_vm_t
*
vm
,
ant_t
*
js
)
{
jsval_t
next_method
=
vm
->
stack
[
vm
->
sp
-
2
];
jsval_t
iterator
=
vm
->
stack
[
vm
->
sp
-
3
];
uint8_t
ft
=
vtype
(
next_method
);
if
(
ft
!=
T_FUNC
&&
ft
!=
T_CFUNC
)
return
js_mkerr
(
js
,
"iterator.next is not a function"
);
jsval_t
result
=
sv_vm_call
(
vm
,
js
,
next_method
,
iterator
,
NULL
,
0
,
NULL
,
false
);
if
(
is_err
(
result
))
return
result
;
if
(
vtype
(
result
)
==
T_PROMISE
)
{
jsval_t
awaited
=
sv_await_value
(
js
,
result
);
if
(
is_err
(
awaited
))
return
awaited
;
result
=
awaited
;
}
jsval_t
done
=
js_getprop_fallback
(
js
,
result
,
"done"
);
jsval_t
value
=
js_getprop_fallback
(
js
,
result
,
"value"
);
if
(
vtype
(
value
)
==
T_PROMISE
)
{
jsval_t
awaited_val
=
sv_await_value
(
js
,
value
);
if
(
is_err
(
awaited_val
))
return
awaited_val
;
value
=
awaited_val
;
}
vm
->
stack
[
vm
->
sp
++
]
=
value
;
vm
->
stack
[
vm
->
sp
++
]
=
mkval
(
T_BOOL
,
js_truthy
(
js
,
done
));
return
tov
(
0
);
}
#endif
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Thu, Mar 26, 4:48 PM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
512016
Default Alt Text
iteration.h (9 KB)
Attached To
Mode
rANT Ant
Attached
Detach File
Event Timeline
Log In to Comment