Browse Source

Preliminar implementation of instance.clone() method

Marco Bambini 6 năm trước cách đây
mục cha
commit
9ed38c610c
3 tập tin đã thay đổi với 40 bổ sung15 xóa
  1. 15 0
      src/runtime/gravity_core.c
  2. 6 15
      src/shared/gravity_value.c
  3. 19 0
      test/unittest/instance_clone.gravity

+ 15 - 0
src/runtime/gravity_core.c

@@ -788,6 +788,20 @@ static bool object_exec (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
     RETURN_ERROR("Forbidden Object execution.");
 }
 
+static bool object_clone (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
+    #pragma unused(nargs)
+    
+    if (VALUE_ISA_INSTANCE(GET_VALUE(0))) {
+        gravity_instance_t *instance = (gravity_instance_t *)(GET_VALUE(0).p);
+        gravity_instance_t *clone = gravity_instance_clone(vm, instance);
+        RETURN_VALUE(VALUE_FROM_OBJECT(clone), rindex);
+    }
+    
+    // more cases to add in the future
+    RETURN_ERROR("Unable to clone non instance object.");
+}
+
+
 //static bool object_methods (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 //    #pragma unused(vm, nargs)
 //    gravity_class_t *c = gravity_value_getclass(GET_VALUE(0));
@@ -2958,6 +2972,7 @@ void gravity_core_init (void) {
     gravity_class_bind(gravity_class_object, "bind", NEW_CLOSURE_VALUE(object_bind));
     gravity_class_bind(gravity_class_object, "unbind", NEW_CLOSURE_VALUE(object_unbind));
     gravity_class_bind(gravity_class_object, GRAVITY_INTERNAL_EXEC_NAME, NEW_CLOSURE_VALUE(object_exec));
+    gravity_class_bind(gravity_class_object, "clone", NEW_CLOSURE_VALUE(object_clone));
 
     // NULL CLASS
     // Meta

+ 6 - 15
src/shared/gravity_value.c

@@ -1319,20 +1319,6 @@ void gravity_fiber_free (gravity_vm *vm, gravity_fiber_t *fiber) {
     if (fiber->error) mem_free(fiber->error);
     mem_free(fiber->stack);
     mem_free(fiber->frames);
-    
-    // free upvalues
-    /*
-    if (fiber->upvalues) {
-        gravity_upvalue_t *upvalue = fiber->upvalues;
-        gravity_upvalue_t *tempvalue;
-        while (upvalue) {
-            tempvalue = upvalue;
-            upvalue = upvalue->next;
-            gravity_upvalue_free(vm, tempvalue);
-        }
-    }
-     */
-    
     mem_free(fiber);
 }
 
@@ -1603,7 +1589,12 @@ gravity_instance_t *gravity_instance_clone (gravity_vm *vm, gravity_instance_t *
   
     gravity_instance_t *instance = (gravity_instance_t *)mem_alloc(NULL, sizeof(gravity_instance_t));
     instance->isa = gravity_class_instance;
-    instance->objclass = c; // TODO: if gravity_class_is_anon(c) then c must be deeply copied
+    instance->objclass = c;
+    
+    // if c is an anonymous class then it must be deeply copied
+    if (gravity_class_is_anon(c)) {
+        // clone class c and all its closures
+    }
     
     gravity_delegate_t *delegate = gravity_vm_delegate(vm);
 

+ 19 - 0
test/unittest/instance_clone.gravity

@@ -0,0 +1,19 @@
+#unittest {
+	name: "Instance clone.";
+	error: NONE;
+	result: 300;
+};
+
+class Foo {
+    var a;
+}
+
+func main() {
+    var f = Foo();
+    f.a = 100;
+    
+    var f2 = f.clone();
+    f2.a = 200;
+    
+    return f.a + f2.a;
+}