char *test_print() { object = Object_new(); Object_print(object); Object_destroy(object); object = True_new(); Object_print(object); Object_destroy_immortal(object); object = False_new(); Object_print(object); Object_destroy_immortal(object); object = Nil_new(); Object_print(object); Object_destroy_immortal(object); object = Integer_new(123); Object_print(object); Object_destroy(object); bstring hello = bfromcstr("hello"); object = String_new(hello); Object_print(object); Object_destroy(object); return NULL; }
char *test_slots() { Object *parent_age = Integer_new(50); Object *parent_money = Integer_new(1000); Object *child_age = Integer_new(25); Object *parent = Object_new(); Object *child = Object_new_with_parent(parent); bstring money = bfromcstr("money"); bstring age = bfromcstr("age"); Object_register_slot(parent, bfromcstr("money"), parent_money); Object_register_slot(parent, bfromcstr("age"), parent_age); Object_register_slot(child, bfromcstr("age"), child_age); mu_assert(Object_lookup_slot(parent, age)->value.integer == 50, "Parent age is wrong"); mu_assert(Object_lookup_slot(child, age)->value.integer == 25, "Child age is wrong"); mu_assert(Object_lookup_slot(parent, money)->value.integer == 1000, "Parent money is wrong"); mu_assert(Object_lookup_slot(child, money)->value.integer == 1000, "Child money is wrong"); Object_destroy(child); bdestroy(money); bdestroy(age); return NULL; }
char *test_create_with_parent() { parent = Object_new(); object = Object_new_with_parent(parent); mu_assert(object->parent == parent, "Object didn't get assigned a parent."); return NULL; }
Object* net_init() { Socket_proto = Socket_createProto(); Object* net = Object_new(Object_proto); Object_setSlot(net, SYM(socket), FUNC(net_socket, 1)); Object_setSlot(net, SYM(Socket), Socket_proto); return net; }
Object * Function_native_new(native_fn function, short arity) { NativeMethod *method = NativeMethod_new(function, arity); Object *object = Object_new(); object->native = 1; object->type = tFunction; object->value.other = method; return object; }
Object* Function_new(Instruction **instructions, int instructions_count, short arity) { long *literals = calloc(10, sizeof(long)); VMMethod *method = VMMethod_new(instructions, instructions_count, literals, 10, arity); Object *object = Object_new(); object->type = tFunction; object->value.other = method; return object; }
char *test_create() { object = Object_new(); mu_assert(object != NULL, "Failed to create object."); mu_assert(object->type == tObject, "Object has an invalid type."); immortal = True_new(); mu_assert(object != NULL, "Failed to create immortal object."); return NULL; }
Object *String_new(bstring value) { check(value != NULL, "Cannot allocate string with empty value."); Object *object = Object_new(); object->type = tString; object->value.string = value; return object; error: return NULL; }
Object *Integer_new(int value) { Object *object = Object_new(); object->type = tInteger; object->value.integer = value; Object_define_native_method(object, bfromcstr("+"), Primitive_Integer_add, 1); Object_define_native_method(object, bfromcstr("-"), Primitive_Integer_sub, 1); Object_define_native_method(object, bfromcstr("*"), Primitive_Integer_mul, 1); Object_define_native_method(object, bfromcstr("/"), Primitive_Integer_div, 1); return object; }
Object* Array_new(Object **contents, int count) { DArray *array = DArray_create(sizeof(Object*), count || 1); int i=0; for(i=0; i < count; i++) { retain((Object*)contents[i]); DArray_push(array, contents[i]); } Object *object = Object_new(); object->type = tArray; object->value.other = array; Object_define_native_method(object, bfromcstr("[]"), Primitive_Array_at, 1); return object; }
int main(int argc, char *argv[]) { printf("\n"); // declare a variable int a = 1; char b = 'b'; // print the variable values printf("Value of 'a': %d\n", a); printf("Value of 'b': %c\n", b); // get the memory address of the variable printf("Memory address of 'a': %p\n", &a); printf("Memory address of 'b': %p\n", &b); // get the bytesize of the variable printf("Bytesize of 'a': %lu\n", sizeof(a)); printf("Bytesize of 'b': %lu\n", sizeof(b)); printf("---\n"); // declare two pointers and do the same thing int *c = &a; char *d = &b; printf("Value of '*c': %d\n", *c); printf("Value of '*d': %c\n", *d); printf("Memory address of '*c': %p\n", &c); printf("Memory address of '*d': %p\n", &d); printf("Bytesize of '*c': %lu\n", sizeof(*c)); printf("Bytesize of '*d': %lu\n", sizeof(*d)); // declaring and accessing an attribute of a struct // with an initialiser function struct Object *obj = Object_new(2, 2); obj->sum = sum(obj->number, obj->number2); printf("\nThe sum of the numbers stored in 'obj' is %d\n\n", obj->sum); free(obj); return 0; }
Object* Hash_new(Object *array_obj) { DArray *array = (DArray*)array_obj->value.other; int count = DArray_count(array); assert(count % 2 == 0 && "Hash element count must be even."); Hashmap *hash = Hashmap_create(String_compare, String_hash); int i=0; for(i=0; i < count; i += 2) { Object *key = retain((Object*)DArray_at(array, i)); Object *value = retain((Object*)DArray_at(array, i+1)); assert(key->type == tString && "All hash keys must be strings"); Hashmap_set(hash, key, value, value->type); } Object *object = Object_new(); object->type = tHash; object->value.other = hash; Object_define_native_method(object, bfromcstr("[]"), Primitive_Hash_get, 1); return object; }
Object *Object_new_with_parent(Object *parent) { Object *object = Object_new(); object->parent = retain(parent); return object; }
void run(void *literals[], byte instructions[]) { byte *ip = instructions; // instruction pointer Object *stack[STACK_MAX]; // the famous stack Object **sp = stack; // stack pointer Object *locals[STACK_MAX] = {}; // where we store our local variables // Setup the runtime Object *self = Object_new(); retain(self); // Start processing instructions while (1) { switch (*ip) { case CALL: { ip++; // moving to the 1st operand char *method = (char *)literals[*ip]; ip++; int argc = *ip; Object *argv[10]; int i; for(i = 0; i < argc; ++i) argv[i] = STACK_POP(); Object *receiver = STACK_POP(); Object *result = call(receiver, method, argv, argc); STACK_PUSH(result); // Releasing what was poped from the stack after we're done with it. for(i = 0; i < argc; ++i) release(argv[i]); release(receiver); break; } case PUSH_STRING: { ip++; STACK_PUSH(String_new((char *)literals[*ip])); break; } case PUSH_NUMBER: { ip++; STACK_PUSH(Number_new((long)literals[*ip])); break; } case PUSH_SELF: { STACK_PUSH(self); break; } case PUSH_NIL: { STACK_PUSH(NilObject); break; } case PUSH_BOOL: { ip++; if (*ip == 0) { STACK_PUSH(FalseObject); } else { STACK_PUSH(TrueObject); } break; } case GET_LOCAL: { ip++; // index of local in the locals table STACK_PUSH(locals[*ip]); break; } case SET_LOCAL: { ip++; locals[*ip] = STACK_POP(); break; } case ADD: { Object *a = STACK_POP(); Object *b = STACK_POP(); STACK_PUSH(Number_new(Number_value(a) + Number_value(b))); release(a); release(b); break; } case JUMP_UNLESS: { ip++; // number of bytes to more forward byte offset = *ip; Object *condition = STACK_POP(); if (!Object_is_true(condition)) ip += offset; release(condition); break; } case RETURN: { goto cleanup; break; } } ip++; } cleanup: release(self); int i; for(i = 0; i < STACK_MAX; ++i) if (locals[i]) release(locals[i]); while (sp > stack) release(STACK_POP()); }
void runtime_init() { Object_proto = Object_new(0); CFunction_proto = Object_new(Object_proto); Function_proto = Object_new(Object_proto); Hash_proto = Object_new(Object_proto); List_proto = Object_new(Object_proto); Symbol_proto = Object_new(Object_proto); Bool_proto = Object_new(Object_proto); Integer_proto = Object_new(Object_proto); Float_proto = Object_new(Object_proto); String_proto = Object_new(Object_proto); Exception_proto = Object_new(Object_proto); SymbolTable_init(); Object_initProto(); CFunction_initProto(); Function_initProto(); Hash_initProto(); List_initProto(); Symbol_initProto(); Bool_initProto(); Integer_initProto(); Float_initProto(); String_initProto(); Exception_initProto(); Qnil = Nil_new(); Qtrue = Bool_new(); Qfalse = Bool_new(); }