kuroko-lang / kuroko

Dialect of Python with explicit variable declaration and block scoping, with a lightweight and easy-to-embed bytecode compiler and interpreter.
https://kuroko-lang.github.io/
MIT License
427 stars 25 forks source link

`dict` argument compatibility with Python #23

Closed notwa closed 2 years ago

notwa commented 2 years ago

compared to Python 3,

klange commented 2 years ago

Supporting the keyword arguments initializer is a straightforward change, as keyword arguments are already passed to C function implementations as a dictionary:

diff --git a/src/obj_dict.c b/src/obj_dict.c
index 2f6b9dd..1338a57 100644
--- a/src/obj_dict.c
+++ b/src/obj_dict.c
@@ -39,9 +39,13 @@ static void _dict_gcsweep(KrkInstance * self) {
 #define CURRENT_NAME  self

 KRK_METHOD(dict,__init__,{
-   METHOD_TAKES_NONE();
-   krk_initTable(&self->entries);
-   return argv[0];
+   if (hasKw) {
+       return argv[argc];
+   } else {
+       METHOD_TAKES_NONE();
+       krk_initTable(&self->entries);
+       return argv[0];
+   }
 })

 KRK_METHOD(dict,__getitem__,{

The iterable and mapping initializers are a bit less straightforward. iterable inputs should be doable, though mappings I think I'm missing plumbing for.

klange commented 2 years ago
>>> dict(((1,2),))
 => {1: 2}
>>> dict(((1,2),),a=42)
 => {1: 2, 'a': 42}
>>> dict(((1,2),(3,4),(5,6)),a=42)
 => {1: 2, 'a': 42, 3: 4, 5: 6}
>>> let keys = ("key", "this")
 => ('key', 'this')
>>> let values = ("value", "that")
 => ('value', 'that')
>>> print(dict(zip(keys, values)))
{'this': 'that', 'key': 'value'}
diff --git a/src/obj_dict.c b/src/obj_dict.c
index 8fb4182..a1156f0 100644
--- a/src/obj_dict.c
+++ b/src/obj_dict.c
@@ -38,14 +38,45 @@ static void _dict_gcsweep(KrkInstance * self) {
 #define CURRENT_CTYPE KrkDict *
 #define CURRENT_NAME  self

+#define unpackArray(counter, indexer) do { \
+       for (size_t i = 0; i < counter; ++i) { \
+           if (keyOrValue == 0) { keyOrValue = 1; key = indexer; } \
+           else if (keyOrValue == 1) { keyOrValue = 0; krk_tableSet(&self->entries, key, indexer); } \
+           if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return 1; \
+       } \
+   } while (0)
+static int unpackKeyValuePair(KrkDict * self, KrkValue pair) {
+   KrkValue key;
+   int keyOrValue = 0;
+   unpackIterableFast(pair);
+   return 0;
+}
+#undef unpackArray
+
+#define unpackArray(counter, indexer) do { \
+       for (size_t i = 0; i < counter; ++i) { \
+           if (unpackKeyValuePair(self, indexer) || (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) \
+               return 1; \
+       } \
+   } while (0)
+static int unpackKeyValueSequence(KrkDict * self, KrkValue array) {
+   unpackIterableFast(array);
+   return 0;
+}
+#undef unpackArray
+
 KRK_METHOD(dict,__init__,{
+   METHOD_TAKES_AT_MOST(1);
+   krk_initTable(&self->entries);
+
+   if (argc > 1) {
+       if (unpackKeyValueSequence(self, argv[1])) return NONE_VAL();
+   }
+
    if (hasKw) {
-       return argv[argc];
-   } else {
-       METHOD_TAKES_NONE();
-       krk_initTable(&self->entries);
-       return argv[0];
+       krk_tableAddAll(AS_DICT(argv[argc]), &self->entries);
    }
+   return argv[0];
 })

 KRK_METHOD(dict,__getitem__,{