HklValue* hklr_op_bitwise_xor(HklValue* left_value, HklValue* right_value) { HklValue* result = NULL; bool left_updated = false, right_updated = false; // Dereference left and right sides if (left_value->type == HKL_TYPE_REF) { left_updated = true; left_value = hklr_object_dereference(left_value->as.object); } if (right_value->type == HKL_TYPE_REF) { right_updated = true; right_value = hklr_object_dereference(right_value->as.object); } switch (left_value->type) { case HKL_TYPE_INT: switch(right_value->type) { case HKL_TYPE_INT: result = hkl_value_new(HKL_TYPE_INT, left_value->as.integer ^ right_value->as.integer); break; case HKL_TYPE_REAL: case HKL_TYPE_STRING: default: assert(false); break; } break; // HKL_TYPE_INT default: assert(false); break; } if (left_updated) { hkl_value_free(left_value); } if (right_updated) { hkl_value_free(right_value); } return result; }
HklValue* hklr_op_typeof(HklValue* value) { bool temporary = true; // Dereference if (value->type == HKL_TYPE_REF) { HklValue* temp = value; value = hklr_object_dereference(value->as.object); // Don't free the deque or hash since it can't be a temporary if (value->type == HKL_TYPE_ARRAY || value->type == HKL_TYPE_HASH || value->type == HKL_TYPE_FUNCTION) { temporary = false; // simply spoof the value temp->type = HKL_TYPE_NIL; } hkl_value_free(temp); } HklType type = value->type; // Spoof the value if it not temporary if (temporary == false) value->type = HKL_TYPE_NIL; hkl_value_free(value); value = hkl_value_new(HKL_TYPE_TYPE, type); value->type = HKL_TYPE_TYPE; return value; }
HklValue* hklr_op_size(HklValue* value) { // Dereference if (value->type == HKL_TYPE_REF) { HklValue* temp = value; value = hklr_object_dereference(value->as.object); hkl_value_free(temp); } switch (value->type) { case HKL_TYPE_STRING: { HklString* string = value->as.string; value->type = HKL_TYPE_INT; value->as.integer = string->length; hkl_string_free(string); } break; default: assert(false); break; } return value; }
HklValue* hklr_op_multiply(HklValue* left_value, HklValue* right_value) { HklValue* result = NULL; bool left_updated = false, right_updated = false; // Dereference left and right sides if (left_value->type == HKL_TYPE_REF) { left_updated = true; left_value = hklr_object_dereference(left_value->as.object); } if (right_value->type == HKL_TYPE_REF) { right_updated = true; right_value = hklr_object_dereference(right_value->as.object); } switch (left_value->type) { case HKL_TYPE_INT: switch(right_value->type) { case HKL_TYPE_INT: result = hkl_value_new(HKL_TYPE_INT, left_value->as.integer * right_value->as.integer); break; case HKL_TYPE_REAL: result = hkl_value_new(HKL_TYPE_REAL, left_value->as.integer * right_value->as.real); break; case HKL_TYPE_STRING: result = hkl_value_new(HKL_TYPE_STRING, hkl_string_new()); int i; for (i=0; i < (int)left_value->as.integer; i ++) { hkl_string_cat(result->as.string, right_value->as.string); } break; default: assert(false); break; } break; // HKL_TYPE_INT case HKL_TYPE_REAL: switch(right_value->type) { case HKL_TYPE_INT: result = hkl_value_new(HKL_TYPE_REAL, left_value->as.real * right_value->as.integer); break; case HKL_TYPE_REAL: result = hkl_value_new(HKL_TYPE_REAL, left_value->as.real * right_value->as.real); break; default: assert(false); break; } break; // HKL_TYPE_REAL case HKL_TYPE_STRING: switch(right_value->type) { case HKL_TYPE_INT: { result = hkl_value_new(HKL_TYPE_STRING, hkl_string_new()); int i; for (i=0; i < (int)right_value->as.integer; i ++) { hkl_string_cat(result->as.string, left_value->as.string); } } break; default: assert(false); break; } break; // HKL_TYPE_STRING default: assert(false); break; } if (left_updated) { hkl_value_free(left_value); } if (right_updated) { hkl_value_free(right_value); } return result; }
void hklr_statement_assign(HklrExpression* lhs, HklrExpression* rhs) { // Evaluate the left hand side and then discard the value object HklValue* vobj = hklr_expression_eval(lhs); HklrObject* object = vobj->as.object; hkl_value_free(vobj); HklValue* value = hklr_expression_eval(rhs); assert(object != NULL); assert(value != NULL); // dereference the objcet if (value->type == HKL_TYPE_REF) { HklValue* temp = value; value = hklr_object_dereference(value->as.object); hkl_value_free(temp); } // wipe out the original value // Composite objects will // create new objects to replace the variable // and decrease the ref count of the original switch (object->type) { case HKL_TYPE_STRING: hkl_string_free(object->as.string); break; default: break; } switch (value->type) { case HKL_TYPE_NIL: object->type = HKL_TYPE_NIL; break; case HKL_TYPE_INT: object->type = HKL_TYPE_INT; object->as.integer = value->as.integer; break; case HKL_TYPE_REAL: object->type = HKL_TYPE_REAL; object->as.real = value->as.real; break; case HKL_TYPE_STRING: object->type = HKL_TYPE_STRING; object->as.string = hkl_string_new_from_string(value->as.string); break; default: break; } hkl_value_free(value); }
HklValue* hklr_op_size(HklValue* value) { bool temporary = true; // Dereference if (value->type == HKL_TYPE_REF) { HklValue* temp = value; value = hklr_object_dereference(value->as.object); // Don't free the deque or hash since it can't be a temporary if (value->type == HKL_TYPE_ARRAY || value->type == HKL_TYPE_HASH || value->type == HKL_TYPE_FUNCTION) { temporary = false; // simply spoof the value temp->type = HKL_TYPE_NIL; } hkl_value_free(temp); } switch (value->type) { case HKL_TYPE_STRING: { HklString* string = value->as.string; value->type = HKL_TYPE_INT; value->as.integer = string->length; hkl_string_free(string); } break; case HKL_TYPE_ARRAY: { HklDeque* deque = value->as.deque; value->type = HKL_TYPE_INT; value->as.integer = deque->size; if (temporary) { // Free the deque hkl_value_free(hkl_value_new(HKL_TYPE_ARRAY, deque)); } } break; case HKL_TYPE_HASH: { HklHash* hash = value->as.hash; value->type = HKL_TYPE_INT; value->as.integer = hash->length; if (temporary) { // Free the hash hkl_value_free(hkl_value_new(HKL_TYPE_HASH, hash)); } } break; case HKL_TYPE_FUNCTION: { HklrFunction* function = value->as.function; value->type = HKL_TYPE_INT; value->as.integer = function->stmt_list->size; if (temporary) { // Free the function hklr_function_free(function); } } break; default: assert(false); break; } return value; }