示例#1
0
HklrObject* hklr_search(HklString* key)
{
  assert(key != NULL);

  HklScope* scope = ((HklScope*) HKLR.scopes->tail->data);
  HklPair* pair = NULL;

  // check your scope first
  pair = hkl_hash_search(scope->locals, key);
  if (pair) return pair->value; 

  // now try upvals
  pair = hkl_hash_search(scope->upvals, key);
  if (pair) return pair->value;

  // Now try scopes above

  HklListNode* node = HKLR.scopes->tail;
  node = node->last;
  while(node != NULL)
  {
    scope = ((HklScope*) node->data);
    // check locals first then upvals
    pair = hkl_hash_search(scope->locals, key);
    if (!pair) pair = hkl_hash_search(scope->upvals, key);    

    // if you find the object 
    // make it an upval to my scope
    if (pair)
    {
      hklr_upval_insert(key, pair->value);
      return pair->value;
    }

    node = node->last;
  }

  // Finally try global scope
  pair = hkl_hash_search(HKLR.globals, key);
  if (pair)
  {
    hklr_upval_insert(key, pair->value);
    return pair->value;
  }

  // Didn't find it, make a nil object
  HklrObject* object = hklr_object_new(HKL_TYPE_NIL, HKL_FLAG_NONE);
  hklr_local_insert(key, object);
  return object;
}
示例#2
0
void hklr_init()
{
  // The first and last gc_root are dummy objects
  HKLR.gc_roots = hklr_object_new(HKL_TYPE_INT, HKL_FLAG_NONE, NULL);
  HKLR.gc_tail = hklr_object_new(HKL_TYPE_INT, HKL_FLAG_NONE, NULL);
  // Dont count them in the object count
  HKLR.gc_created-=2;

  HKLR.gc_roots->next = HKLR.gc_tail;
  HKLR.gc_tail->prev = HKLR.gc_roots;

  HKLR.gc_to_free = hkl_list_new();

  HKLR.gc_runs = 0;
  HKLR.gc_freed = 0;
  HKLR.gc_rootsize = 0;

  HKLR.globals = hkl_hash_new();
  HKLR.scopes = hkl_list_new();
  HKLR.scope_level = 0;

  hklr_scope_push();
}
示例#3
0
static bool hklr_hash_add_list(void* pair, void* hash_index)
{
  HklrObject* object = hklr_object_new(HKL_TYPE_NIL, HKL_FLAG_NONE);

  // If the user didnt give a value
  // Give them an integer corresponding to the index in the hash
  if (((HklPair*) pair)->value == NULL)
  {
    ((HklPair*) pair)->value = hklr_expression_new(HKL_EXPR_STRING, hkl_string_new_from_string(((HklPair*) pair)->key));
  }

  hklr_object_assign(object, (HklrExpression*) ((HklPair*) pair)->value);

  hkl_hash_insert(((struct hash_index*) hash_index)->hash, ((HklPair*) pair)->key, object);

  return false;
}
示例#4
0
static bool make_locals(void* string, void* carrier)
{
  HklrObject* object = hklr_object_new(HKL_TYPE_NIL, HKL_FLAG_NONE);

  //hklr_local_insert((HklString*) string, object);
  hkl_hash_insert(((struct scope_carier*) carrier)->locals, (HklString*) string, object);

  // If you have too few args then the rest are nil
  if (((struct scope_carier*) carrier)->arg == NULL)
    return true;

  // Some fancy pointer arithematic
  // This iterates the argument expression
  HklrExpression* assign = ((struct scope_carier*) carrier)->arg->data;
  ((struct scope_carier*) carrier)->arg = ((struct scope_carier*) carrier)->arg->next;

  hklr_object_assign(object, assign);

  return false;
}
示例#5
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;
}
示例#6
0
void hklr_statement_exec(HklrStatement* stmt)
{
  assert(stmt != NULL);

  switch (stmt->type)
  {

    case HKL_STMT_PUTS:
      hklr_statement_puts(stmt->arg[0].expression);
    break;

    case HKL_STMT_HKLR:

      // Print runtime information
      fprintf(stdout, "Ops:             %zu\n", HKLR.ops);
      fprintf(stdout, "Objects Created: %zu\n", HKLR.gc_created);
      fprintf(stdout, "Objects Freed:   %zu\n", HKLR.gc_freed);
      fprintf(stdout, "Object Cycles:   %zu\n", HKLR.gc_rootsize);
      fprintf(stdout, "GC Runs:         %zu\n", HKLR.gc_runs);
      fprintf(stdout, "Scope Level:     %zu\n", HKLR.scope_level);
      fprintf(stdout, "Globals:         %zu\n", HKLR.globals->length);
      fprintf(stdout, "Locals:          %zu\n", ((HklScope*) HKLR.scopes->tail->data)->locals->length);
      fprintf(stdout, "Upvals:          %zu\n", ((HklScope*) HKLR.scopes->tail->data)->upvals->length);
      fflush(stdout);
      break;

    case HKL_STMT_INIT:
    {
      // This is very much a hack and needs to be made ALOT better
      // this doesn't actually play nice with flags, but will
      // do for now to create globals and locals
      if (stmt->arg[0].flags & HKL_FLAG_GLOBAL)
        hklr_global_insert(stmt->arg[1].string, hklr_object_new(HKL_TYPE_NIL, stmt->arg[0].flags));
      else
        hklr_local_insert(stmt->arg[1].string, hklr_object_new(HKL_TYPE_NIL, stmt->arg[0].flags));

      HklrExpression* temp = hklr_expression_new(HKL_EXPR_ID, stmt->arg[1].string);
      hklr_statement_assign(temp, stmt->arg[2].expression);
      hklr_expression_free(temp);
    }
    break;

    case HKL_STMT_ASSIGN:
      hklr_statement_assign(stmt->arg[0].expression, stmt->arg[1].expression);
    break; // HKL_STMT_ASSIGN

    case HKL_STMT_IF:
      hklr_statement_if(stmt->arg[0].expression, stmt->arg[1].list);
      break;

    case HKL_STMT_WHILE:
      hklr_statement_while(stmt->arg[0].expression, stmt->arg[1].list);
      break;

    default:
      break;
  }

  // Increment numbers of completed operations
  HKLR.ops++;
}