Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
HklValue* hklr_op_bitwise_and(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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
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);
}
Exemplo n.º 7
0
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;
}