HklrObject* hklr_object_new(HklType type, HklFlag flags, ...) { assert(type != HKL_TYPE_NONE); HklrObject* object = hkl_alloc_object(HklrObject); object->prev = NULL; object->next = NULL; object->rc = 0; object->is_buffered = false; object->color = HKL_COLOR_BLACK; object->type = type; object->flags = flags; HKLR.gc_created++; object->flags = flags; object->type = type; hklr_gc_inc(object); va_list argp; va_start(argp, flags); //void* pointer = NULL; switch (type) { case HKL_TYPE_NIL: break; case HKL_TYPE_INT: object->as.integer = va_arg(argp, int); break; case HKL_TYPE_REAL: object->as.real = va_arg(argp, double); break; case HKL_TYPE_STRING: object->as.string = va_arg(argp, HklString*); break; default: assert(false); break; } va_end(argp); return object; }
static bool process_closures(HklPair* pair, void* data) { // Search in our scope for the closed variables. HklrObject* object = hklr_exists(pair->key); if (object != NULL) { // increment the rc of the closed variable // we'll dec it when the function is destroyed hklr_gc_inc(object); pair->value = object; } else { pair->value = NULL; } return false; }
HklValue* hklr_expression_eval(HklrExpression* expr) { assert(expr != NULL); switch (expr->type) { case HKL_EXPR_NIL: return hkl_value_new(HKL_TYPE_NIL); break; case HKL_EXPR_MAYBE: return hkl_value_new(HKL_TYPE_INT, rand() % 2 == 1); break; case HKL_EXPR_INT: return hkl_value_new(HKL_TYPE_INT, expr->arg[0].integer); break; case HKL_EXPR_TYPE: return hkl_value_new(HKL_TYPE_TYPE, expr->arg[0].type); break; case HKL_EXPR_REAL: return hkl_value_new(HKL_TYPE_REAL, expr->arg[0].real); break; case HKL_EXPR_STRING: { HklString* string = hkl_string_new_from_string(expr->arg[0].string); assert(string != NULL); return hkl_value_new(HKL_TYPE_STRING, string); } break; case HKL_EXPR_VAR: { HklrObject* object = hklr_search(expr->arg[0].string); // apply more list items to the object to fetch deeper ones HklList* list = expr->arg[1].list; if (list->size && object->type != HKL_TYPE_REF) assert(false); HklListNode* node = list->head; while (node && object->type == HKL_TYPE_REF) { HklVariable* var = node->data; if (object->type == HKL_TYPE_REF && object->as.object->type == HKL_TYPE_FUNCTION) { HKLR.reg_return = NULL; // Try a function call HklrFunction* function = object->as.object->as.function; assert(var->type == HKL_VAR_CALL); HklList* args = var->as.list; struct scope_carier carrier; carrier.locals = hkl_hash_new(); carrier.upvals = hkl_hash_new(); carrier.arg = args->head; // Create the closure variables hkl_tree_traverse(function->closure_list, make_closures, &carrier); // Make the args in the function signature local variables hkl_list_traverse(function->args_list, make_locals, &carrier); hklr_scope_push_full(true, carrier.locals, carrier.upvals); // execute the statements within hkl_list_traverse(function->stmt_list, hklr_statement_exec_list, NULL); // the post_object is the function return value if (HKLR.reg_return == NULL) HKLR.reg_return = hkl_value_new(HKL_TYPE_NIL); // if the return value is an object be sure to increase the ref count // Though, this count needs to be decced afterwards if (HKLR.reg_return->type == HKL_TYPE_REF) hklr_gc_inc(HKLR.reg_return->as.object); hklr_scope_pop(); return HKLR.reg_return; } else if (object->type == HKL_TYPE_REF && object->as.object->type == HKL_TYPE_HASH) { HklPair* pair = hkl_hash_search(object->as.object->as.hash, var->as.string); // This key doesnt exist just create it if (pair == NULL) { HklrObject* post_object = hklr_object_new(HKL_TYPE_NIL, HKL_FLAG_NONE); hkl_hash_insert(object->as.object->as.hash, var->as.string, post_object); return hkl_value_new(HKL_TYPE_REF, post_object); } if (node->next == NULL) return hkl_value_new(HKL_TYPE_REF, pair->value); object = pair->value; } node = node->next; } return hkl_value_new(HKL_TYPE_REF, object); } break; case HKL_EXPR_GETS: { HklString* string = hkl_string_new_from_stream(stdin); assert(string != NULL); return hkl_value_new(HKL_TYPE_STRING, string); } break; case HKL_EXPR_ARRAY: { // allocate space ahead of time HklDeque* deque = hkl_deque_new();//_sized(list->size); hkl_list_traverse(expr->arg[0].list, hklr_array_add_list, deque); return hkl_value_new(HKL_TYPE_ARRAY, deque); } break; case HKL_EXPR_HASH: { HklHash* hash = hkl_hash_new(); struct hash_index hash_index; hash_index.index = 0; hash_index.hash = hash; hkl_list_traverse(expr->arg[0].list, hklr_hash_add_list, &hash_index); return hkl_value_new(HKL_TYPE_HASH, hash); } break; case HKL_EXPR_FUNCTION: { return hkl_value_new(HKL_TYPE_FUNCTION, hklr_function_new(expr->arg[0].list, expr->arg[1].tree, expr->arg[2].list)); } break; case HKL_EXPR_UNARY: { HklValue* value = hklr_expression_eval(expr->arg[1].expression); assert(value != NULL); switch (expr->arg[0].op) { case HKL_OP_UNARY_MINUS: switch (value->type) { case HKL_TYPE_INT: value->as.integer = -value->as.integer; return value; break; case HKL_TYPE_REAL: value->as.real = -value->as.real; return value; break; default: assert(false); break; } break; // HKL_OP_UNARY_MINUS case HKL_OP_SIZE: return hklr_op_size(value); break; // HKL_OP_SIZE case HKL_OP_TYPEOF: return hklr_op_typeof(value); break; // HKL_OP_TYPE case HKL_OP_BITWISE_NOT: switch (value->type) { case HKL_TYPE_INT: value->as.integer = ~value->as.integer; return value; break; default: assert(false); break; } default: assert(false); break; } } break; // HKL_EXPR_UNARY case HKL_EXPR_BINARY: { HklValue *left_value = hklr_expression_eval(expr->arg[0].expression); HklValue *right_value = hklr_expression_eval(expr->arg[2].expression); HklValue *result = NULL; assert(left_value != NULL); assert(right_value != NULL); switch (expr->arg[1].op) { case HKL_OP_PLUS: result = hklr_op_plus(left_value, right_value); break; case HKL_OP_MINUS: result = hklr_op_minus(left_value, right_value); break; case HKL_OP_LESS: result = hklr_op_less(left_value, right_value); break; case HKL_OP_LESS_EQUAL: result = hklr_op_less_equal(left_value, right_value); break; case HKL_OP_GREATER: result = hklr_op_greater(left_value, right_value); break; case HKL_OP_GREATER_EQUAL: result = hklr_op_greater_equal(left_value, right_value); break; case HKL_OP_ASTERISK: result = hklr_op_multiply(left_value, right_value); break; case HKL_OP_DIVIDE: result = hklr_op_divide(left_value, right_value); break; case HKL_OP_MOD: result = hklr_op_mod(left_value, right_value); break; case HKL_OP_EQUAL: result = hklr_op_equal(left_value, right_value); break; case HKL_OP_COALESCE: result = hklr_op_coalesce(left_value, right_value); if (result == left_value) { result = hkl_value_new(left_value->type); result->as = left_value->as; left_value->type = HKL_TYPE_NIL; } else if (result == right_value) { result = hkl_value_new(right_value->type); result->as = right_value->as; right_value->type = HKL_TYPE_NIL; } break; case HKL_OP_BITWISE_AND: result = hklr_op_bitwise_and(left_value, right_value); break; case HKL_OP_BITWISE_OR: result = hklr_op_bitwise_or(left_value, right_value); break; case HKL_OP_BITWISE_XOR: result = hklr_op_bitwise_xor(left_value, right_value); break; case HKL_OP_AS: { assert(right_value->type == HKL_TYPE_TYPE); switch (right_value->as.type) { case HKL_TYPE_INT: result = hklr_as_integer(left_value); break; case HKL_TYPE_REAL: result = hklr_as_real(left_value); break; case HKL_TYPE_STRING: result = hklr_as_string(left_value); break; default: assert(false); break; } } break; default: assert(false); break; } hkl_value_free(left_value); hkl_value_free(right_value); return result; } break; // HKL_EXPR_BINARY default: assert(false); break; } assert(false); return NULL; }