mirror of
https://github.com/zekexiao/pocketlang.git
synced 2025-02-11 07:00:58 +08:00
pk_core: implement list addition
This commit implements list addition. A new list is allocated, and the contents of l1 and l2 are concatenated onto the list. This is done by extending the buffer template macro to support a `concat` operation, which given an `other` buffer, appends all elements of the `other` buffer to the end of the `self` buffer. Allocations are done as needed. We implement this additional operation, since the alternative would be to call `reserve()` for each `write()` operation, which doesn't seem ideal. Issue: #55
This commit is contained in:
parent
5f6f66517f
commit
59333177cd
@ -37,13 +37,17 @@
|
||||
/* Fill the buffer at the end of it with provided data if the capacity */ \
|
||||
/* isn't enough using VM's realloc function. */ \
|
||||
void pk##m_name##BufferFill(pk##m_name##Buffer* self, PKVM* vm, \
|
||||
m_type data, int count); \
|
||||
m_type data, int count); \
|
||||
\
|
||||
/* Write to the buffer with provided data at the end of the buffer.*/ \
|
||||
void pk##m_name##BufferWrite(pk##m_name##Buffer* self, \
|
||||
PKVM* vm, m_type data); \
|
||||
PKVM* vm, m_type data); \
|
||||
\
|
||||
/* Concatenate the contents of another buffer at the end of this buffer.*/ \
|
||||
void pk##m_name##BufferConcat(pk##m_name##Buffer* self, PKVM* vm, \
|
||||
pk##m_name##Buffer* other); \
|
||||
|
||||
// The buffer "template" implementation of diferent types.
|
||||
// The buffer "template" implementation of different types.
|
||||
#define DEFINE_BUFFER(m_name, m_type) \
|
||||
void pk##m_name##BufferInit(pk##m_name##Buffer* self) { \
|
||||
self->data = NULL; \
|
||||
@ -71,7 +75,7 @@
|
||||
} \
|
||||
\
|
||||
void pk##m_name##BufferFill(pk##m_name##Buffer* self, PKVM* vm, \
|
||||
m_type data, int count) { \
|
||||
m_type data, int count) { \
|
||||
\
|
||||
pk##m_name##BufferReserve(self, vm, self->count + count); \
|
||||
\
|
||||
@ -81,8 +85,18 @@
|
||||
} \
|
||||
\
|
||||
void pk##m_name##BufferWrite(pk##m_name##Buffer* self, \
|
||||
PKVM* vm, m_type data) { \
|
||||
PKVM* vm, m_type data) { \
|
||||
pk##m_name##BufferFill(self, vm, data, 1); \
|
||||
} \
|
||||
\
|
||||
void pk##m_name##BufferConcat(pk##m_name##Buffer* self, PKVM* vm, \
|
||||
pk##m_name##Buffer* other) { \
|
||||
pk##m_name##BufferReserve(self, vm, self->count + other->count); \
|
||||
\
|
||||
memcpy(self->data + self->count, \
|
||||
other->data, \
|
||||
other->count * sizeof(m_type)); \
|
||||
self->count += other->count; \
|
||||
}
|
||||
|
||||
#endif // BUFFERS_TEMPLATE_H
|
||||
|
@ -1068,8 +1068,7 @@ Var varAdd(PKVM* vm, Var v1, Var v2) {
|
||||
case OBJ_LIST:
|
||||
{
|
||||
if (o2->type == OBJ_LIST) {
|
||||
List* l1 = (List*)o1, * l2 = (List*)o2;
|
||||
TODO;
|
||||
return VAR_OBJ(listJoin(vm, (List*)o1, (List*)o2));
|
||||
}
|
||||
} break;
|
||||
|
||||
|
17
src/pk_var.c
17
src/pk_var.c
@ -1272,6 +1272,23 @@ String* stringJoin(PKVM* vm, String* str1, String* str2) {
|
||||
return string;
|
||||
}
|
||||
|
||||
List* listJoin(PKVM* vm, List* l1, List* l2) {
|
||||
|
||||
// Optimize end case.
|
||||
if (l1->elements.count == 0) return l2;
|
||||
if (l2->elements.count == 0) return l1;
|
||||
|
||||
size_t size = (size_t)l1->elements.count + (size_t)l2->elements.count;
|
||||
List* list = newList(vm, size);
|
||||
|
||||
vmPushTempRef(vm, &list->_super);
|
||||
pkVarBufferConcat(&list->elements, vm, &l1->elements);
|
||||
pkVarBufferConcat(&list->elements, vm, &l2->elements);
|
||||
vmPopTempRef(vm);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
uint32_t scriptAddName(Script* self, PKVM* vm, const char* name,
|
||||
uint32_t length) {
|
||||
|
||||
|
@ -548,6 +548,9 @@ String* stringFormat(PKVM* vm, const char* fmt, ...);
|
||||
// Which would be faster than using "@@" format.
|
||||
String* stringJoin(PKVM* vm, String* str1, String* str2);
|
||||
|
||||
// Create a new list by joining the 2 given list and return the result.
|
||||
List* listJoin(PKVM* vm, List* l1, List* l2);
|
||||
|
||||
// Add the name (string literal) to the string buffer if not already exists and
|
||||
// return it's index in the buffer.
|
||||
uint32_t scriptAddName(Script* self, PKVM* vm, const char* name,
|
||||
|
@ -21,6 +21,11 @@ assert(0xffffffffffffffff == 18446744073709551615)
|
||||
l1 = [1, false, null, func print('hello') end]
|
||||
assert(is_null(l1[2]))
|
||||
l1[1] = true; assert(l1[1])
|
||||
l1 = [] + [] ; assert(l1.length == 0)
|
||||
l1 = [] + [1]; assert(l1.length == 1); assert(l1[0] == 1)
|
||||
l1 = [1] + []; assert(l1.length == 1); assert(l1[0] == 1)
|
||||
l2 = l1 + [1,2,3]; assert(l2.length == 4); assert(l2 == [1,1,2,3])
|
||||
l3 = l2 + l1 + l2; assert(l3 == [1,1,2,3,1,1,1,2,3])
|
||||
|
||||
## Builtin functions tests.
|
||||
assert(to_string(42) == '42')
|
||||
|
Loading…
Reference in New Issue
Block a user