public static ObjBoundMethod newBoundMethod(Value_t receiver, ObjClosure method) { ObjBoundMethod bound = (ObjBoundMethod)ALLOCATE_OBJ(ObjType.OBJ_BOUND_METHOD); bound.receiver = receiver; bound.method = method; return(bound); }
private static bool callValue(Value_t callee, int argCount) { if (Value.IS_OBJ(callee)) { switch (Object.OBJ_TYPE(callee)) { case ObjType.OBJ_BOUND_METHOD: { ObjBoundMethod bound = Object.AS_BOUND_METHOD(callee); vm.stack[vm.stackTop - argCount - 1] = bound.receiver; return(call(bound.method, argCount)); } case ObjType.OBJ_CLASS: { ObjClass klass = Object.AS_CLASS(callee); vm.stack[vm.stackTop - argCount - 1] = Value.OBJ_VAL(Object.newInstance(klass)); Value_t initializer = new Value_t(); if (Table.tableGet(ref klass.methods, vm.initString, ref initializer)) { return(call(Object.AS_CLOSURE(initializer), argCount)); } else if (argCount != 0) { runtimeError("Expected 0 arguments but got {0}.", argCount.ToString()); return(false); } vm.frames[vm.frameCount - 1]._ip_index += 2; // HACK FIX return(true); } case ObjType.OBJ_CLOSURE: return(call(Object.AS_CLOSURE(callee), argCount)); case ObjType.OBJ_NATIVE: { NativeFn native = Object.AS_NATIVE(callee); Value_t result = native(argCount, vm.stackTop - argCount); vm.stackTop -= argCount + 1; push(result); vm.frames[vm.frameCount - 1]._ip_index += 2; // HACK FIX return(true); } default: // Non-callable object type. break; } } runtimeError("Can only call functions and classes."); return(false); }
// Generics, <T>, doesn't seem to work with classes? static Obj allocateObject(int size, ObjType type) { Obj object_ = null; switch (type) { case ObjType.OBJ_STRING: object_ = new ObjString(); break; case ObjType.OBJ_FUNCTION: object_ = new ObjFunction(); break; case ObjType.OBJ_INSTANCE: object_ = new ObjInstance(); break; case ObjType.OBJ_NATIVE: object_ = new ObjNative(); break; case ObjType.OBJ_CLOSURE: object_ = new ObjClosure(); break; case ObjType.OBJ_UPVALUE: object_ = new ObjUpvalue(); break; case ObjType.OBJ_CLASS: object_ = new ObjClass(); break; case ObjType.OBJ_BOUND_METHOD: object_ = new ObjBoundMethod(); break; default: object_ = null; // clox: (Obj*)reallocate(NULL, 0, size); break; } object_.type = type; object_.isMarked = false; object_.next = VM.vm.objects; VM.vm.objects = object_; #if DEBUG_LOG_GC System.Console.WriteLine("{0} allocate {1} for {2}", object_._mem_id.ToString(), size.ToString(), type.ToString()); #endif return(object_); }
private static bool bindMethod(ObjClass klass, ObjString name) { Value_t method = new Value_t(); if (!Table.tableGet(ref klass.methods, name, ref method)) { runtimeError("Undefined property '{0}'.", new string(name.chars, 0, name.chars.Length - 1)); return(false); } ObjBoundMethod bound = Object.newBoundMethod(peek(0), Object.AS_CLOSURE(method)); pop(); push(Value.OBJ_VAL(bound)); return(true); }
private static void blackenObject(Obj object_) { #if DEBUG_LOG_GC System.Console.Write("{0} blacken ", object_._mem_id.ToString()); Value.printValue(Value.OBJ_VAL(object_)); System.Console.WriteLine(); #endif switch (object_.type) { case ObjType.OBJ_BOUND_METHOD: { ObjBoundMethod bound = (ObjBoundMethod)object_; markValue(ref bound.receiver); markObject((Obj)bound.method); break; } case ObjType.OBJ_CLASS: { ObjClass klass = (ObjClass)object_; markObject((Obj)klass.name); Table.markTable(ref klass.methods); break; } case ObjType.OBJ_CLOSURE: { ObjClosure closure = (ObjClosure)object_; markObject((Obj)closure.function); for (int i = 0; i < closure.upvalueCount; i++) { markObject((Obj)closure.upvalues[i]); } break; } case ObjType.OBJ_FUNCTION: { ObjFunction function = (ObjFunction)object_; markObject((Obj)function.name); markArray(ref function.chunk.constants); break; } case ObjType.OBJ_INSTANCE: { ObjInstance instance = (ObjInstance)object_; markObject((Obj)(instance.klass)); Table.markTable(ref instance.fields); break; } case ObjType.OBJ_UPVALUE: markValue(ref ((ObjUpvalue)object_).closed); break; case ObjType.OBJ_NATIVE: case ObjType.OBJ_STRING: break; } }