示例#1
0
static value_t lambda_scope_lookup(lambda_scope_o *self, value_t symbol,
    binding_info_t *info_out) {
  size_t capture_count_before = get_array_buffer_length(self->captures);
  // See if we've captured this variable before.
  for (size_t i = 0; i < capture_count_before; i++) {
    value_t captured = get_array_buffer_at(self->captures, i);
    if (value_identity_compare(captured, symbol)) {
      // Found it. Record that we did if necessary and return success.
      if (info_out != NULL)
        binding_info_set(info_out, btLambdaCaptured, i, 0);
      return success();
    }
  }
  // We haven't seen this one before so look it up outside.
  value_t value = scope_lookup(self->outer, symbol, info_out);
  if (info_out != NULL && !in_condition_cause(ccNotFound, value)) {
    // We found something and this is a read. Add it to the list of captures.
    runtime_t *runtime = self->assembler->runtime;
    if (get_array_buffer_length(self->captures) == 0) {
      // The first time we add something we have to create a new array buffer
      // since all empty capture scopes share the singleton empty buffer.
      TRY_SET(self->captures, new_heap_array_buffer(runtime, 2));
    }
    TRY(add_to_array_buffer(runtime, self->captures, symbol));
    binding_info_set(info_out, btLambdaCaptured, capture_count_before, 0);
  }
  return value;
}
示例#2
0
文件: bind.c 项目: plesner/neutrino
value_t build_binding_schedule(binding_context_t *context) {
  runtime_t *runtime = get_ambience_runtime(context->ambience);
  TRY_DEF(schedule, new_heap_array_buffer(runtime, 16));
  TRY_DEF(all_fragments, build_fragment_identifier_array(context));
  loop: do {
    for (size_t i = 0; i < get_array_buffer_length(all_fragments); i++) {
      value_t ident = get_array_buffer_at(all_fragments, i);
      if (should_fragment_be_bound(context, schedule, ident)) {
        TRY(add_to_array_buffer(runtime, schedule, ident));
        goto loop;
      }
    }
  } while (false);
  return schedule;
}
示例#3
0
文件: method.c 项目: tundra/neutrino
value_t add_methodspace_inheritance(runtime_t *runtime, value_t self,
    value_t subtype, value_t supertype) {
  CHECK_FAMILY(ofMethodspace, self);
  CHECK_MUTABLE(self);
  CHECK_FAMILY(ofType, subtype);
  CHECK_FAMILY(ofType, supertype);
  value_t inheritance = get_methodspace_inheritance(self);
  value_t parents = get_id_hash_map_at(inheritance, subtype);
  if (in_condition_cause(ccNotFound, parents)) {
    // Make the parents buffer small since most types don't have many direct
    // parents. If this fails nothing has happened.
    TRY_SET(parents, new_heap_array_buffer(runtime, 4));
    // If this fails we've wasted some space allocating the parents array but
    // otherwise nothing has happened.
    TRY(set_id_hash_map_at(runtime, inheritance, subtype, parents));
  }
  // If this fails we may have set the parents array of the subtype to an empty
  // array which is awkward but okay.
  invalidate_methodspace_caches(self);
  return add_to_array_buffer(runtime, parents, supertype);
}
示例#4
0
文件: bind.c 项目: plesner/neutrino
// Uses the fragment entry map to create an array of identifiers for all the
// fragments, synthetic and real.
static value_t build_fragment_identifier_array(binding_context_t *context) {
  runtime_t *runtime = get_ambience_runtime(context->ambience);
  TRY_DEF(result, new_heap_array_buffer(runtime, 16));
  id_hash_map_iter_t module_iter;
  id_hash_map_iter_init(&module_iter, context->fragment_entry_map);
  while (id_hash_map_iter_advance(&module_iter)) {
    value_t module_path;
    value_t module_fragments;
    // Scan through the fragments.
    id_hash_map_iter_get_current(&module_iter, &module_path, &module_fragments);
    id_hash_map_iter_t fragment_iter;
    id_hash_map_iter_init(&fragment_iter, module_fragments);
    while (id_hash_map_iter_advance(&fragment_iter)) {
      value_t stage;
      value_t entry;
      id_hash_map_iter_get_current(&fragment_iter, &stage, &entry);
      value_t ident = get_fragment_entry_identifier(entry);
      TRY(add_to_array_buffer(runtime, result, ident));
    }
  }
  sort_array_buffer(result);
  return result;
}
示例#5
0
文件: bind.c 项目: plesner/neutrino
// Ensures that the given unbound module is in the given array buffer, as well
// as any other modules imported by the module.
static value_t ensure_module_in_array(runtime_t *runtime, value_t array,
    value_t unbound_module) {
  CHECK_FAMILY(ofUnboundModule, unbound_module);
  if (in_array_buffer(array, unbound_module))
    // If it's already there there's nothing to do.
    return success();
  // Add the module.
  TRY(add_to_array_buffer(runtime, array, unbound_module));
  // Scan through the imports and recursively add imported modules. Which
  // stage the module is imported into doesn't matter at this point, we just
  // have to enumerate them.
  value_t unbound_fragments = get_unbound_module_fragments(unbound_module);
  for (size_t fi = 0; fi < get_array_length(unbound_fragments); fi++) {
    value_t unbound_fragment = get_array_at(unbound_fragments, fi);
    value_t imports = get_unbound_module_fragment_imports(unbound_fragment);
    for (size_t ii = 0; ii < get_array_length(imports); ii++) {
      value_t import = get_array_at(imports, ii);
      TRY_DEF(imported_module, module_loader_lookup_module(
          deref(runtime->module_loader), import));
      TRY(ensure_module_in_array(runtime, array, imported_module));
    }
  }
  return success();
}
示例#6
0
文件: bind.c 项目: plesner/neutrino
// Add synthetic fragment entries corresponding to imported fragments where
// there is no real fragment to import the fragment into.
static value_t build_synthetic_fragment_entries(binding_context_t *context) {
  // Keep adding synthetic modules as long as changes are being made to the
  // map. We'll scan through the fragments currently in the map, then scan
  // through their imports, and for each check that the fragment that should
  // receive the import exists. If it doesn't it is created.
  loop: do {
    id_hash_map_iter_t module_iter;
    id_hash_map_iter_init(&module_iter, context->fragment_entry_map);
    while (id_hash_map_iter_advance(&module_iter)) {
      value_t module_path;
      value_t module_fragments;
      // Scan through the fragments.
      id_hash_map_iter_get_current(&module_iter, &module_path, &module_fragments);
      id_hash_map_iter_t fragment_iter;
      id_hash_map_iter_init(&fragment_iter, module_fragments);
      while (id_hash_map_iter_advance(&fragment_iter)) {
        value_t stage;
        value_t entry;
        id_hash_map_iter_get_current(&fragment_iter, &stage, &entry);
        value_t unbound_fragment = get_fragment_entry_fragment(entry);
        // If there is no fragment associated with this entry it is synthetic
        // and hence we're done.
        if (is_nothing(unbound_fragment))
          continue;
        // Scan through the fragment's imports and ensure that their import
        // targets have been created.
        value_t imports = get_fragment_entry_imports(entry);
        for (size_t i = 0; i < get_array_buffer_length(imports); i++) {
          value_t import = get_array_buffer_at(imports, i);
          value_t import_fragment_stage = get_identifier_stage(import);
          if (!value_identity_compare(import_fragment_stage, present_stage()))
            // We'll record past imports but ignore them for the purposes of
            // closing the import map since they're redundant.
            continue;
          value_t import_module_path = get_identifier_path(import);
          value_t import_module = get_id_hash_map_at(context->fragment_entry_map,
              import_module_path);
          // Scan through the fragments of the imported module.
          id_hash_map_iter_t imported_fragment_iter;
          id_hash_map_iter_init(&imported_fragment_iter, import_module);
          bool has_changed_anything = false;
          while (id_hash_map_iter_advance(&imported_fragment_iter)) {
            value_t import_stage;
            value_t import_entry;
            id_hash_map_iter_get_current(&imported_fragment_iter,
                &import_stage, &import_entry);
            value_t target_stage = add_stage_offsets(import_stage, stage);
            // Ensure that there is a target entry to add the import to. If it
            // already exists this is a no-op, if it doesn't a synthetic entry
            // is created.
            TRY_DEF(target_entry, binding_context_ensure_fragment_entry(
                context, target_stage, module_path, nothing(),
                &has_changed_anything));
           value_t target_imports = get_fragment_entry_imports(target_entry);
           value_t import_ident = get_fragment_entry_identifier(import_entry);
            if (!in_array_buffer(target_imports, import_ident)) {
              has_changed_anything = true;
              TRY(add_to_array_buffer(get_ambience_runtime(context->ambience),
                  target_imports, import_ident));
            }
          }
          // If any changes were made we have to start over.
          if (has_changed_anything)
            goto loop;
        }
      }
    }
  } while (false);
  return success();
}