예제 #1
0
TEST(plankton, env_resolution) {
  CREATE_RUNTIME();

  test_resolver_data_t data;
  data.i0 = new_heap_instance(runtime, ROOT(runtime, empty_instance_species));
  data.i1 = new_heap_instance(runtime, ROOT(runtime, empty_instance_species));
  value_t i2 = new_heap_instance(runtime, ROOT(runtime, empty_instance_species));

  value_mapping_t resolver;
  value_mapping_init(&resolver, value_to_int, &data);
  value_mapping_t access;
  value_mapping_init(&access, int_to_value, &data);

  value_t d0 = transcode_plankton(runtime, &resolver, &access, data.i0);
  ASSERT_TRUE(value_identity_compare(data.i0, d0));
  value_t d1 = transcode_plankton(runtime, &resolver, &access, data.i1);
  ASSERT_TRUE(value_identity_compare(data.i1, d1));
  value_t d2 = transcode_plankton(runtime, &resolver, &access, i2);
  ASSERT_FALSE(value_identity_compare(i2, d2));

  value_t a0 = new_heap_array(runtime, 4);
  set_array_at(a0, 0, data.i0);
  set_array_at(a0, 1, data.i1);
  set_array_at(a0, 2, i2);
  set_array_at(a0, 3, data.i0);
  value_t da0 = transcode_plankton(runtime, &resolver, &access, a0);
  ASSERT_TRUE(value_identity_compare(data.i0, get_array_at(da0, 0)));
  ASSERT_TRUE(value_identity_compare(data.i1, get_array_at(da0, 1)));
  ASSERT_FALSE(value_identity_compare(i2, get_array_at(da0, 2)));
  ASSERT_TRUE(value_identity_compare(data.i0, get_array_at(da0, 3)));

  DISPOSE_RUNTIME();
}
예제 #2
0
파일: codegen.c 프로젝트: plesner/neutrino
value_t assembler_flush(assembler_t *assm) {
  // Copy the bytecode into a blob object.
  blob_t code_blob;
  short_buffer_flush(&assm->code, &code_blob);
  TRY_DEF(bytecode, new_heap_blob_with_data(assm->runtime, &code_blob));
  // Invert the constant pool map into an array.
  value_t value_pool_map = assm->value_pool;
  size_t value_pool_size = get_id_hash_map_size(value_pool_map);
  TRY_DEF(value_pool, new_heap_array(assm->runtime, value_pool_size));
  id_hash_map_iter_t iter;
  id_hash_map_iter_init(&iter, value_pool_map);
  size_t entries_seen = 0;
  while (id_hash_map_iter_advance(&iter)) {
    value_t key;
    value_t value;
    id_hash_map_iter_get_current(&iter, &key, &value);
    size_t index = get_integer_value(value);
    // Check that the entry hasn't been set already.
    CHECK_PHYLUM(tpNull, get_array_at(value_pool, index));
    set_array_at(value_pool, index, key);
    entries_seen++;
  }
  CHECK_EQ("wrong number of entries", entries_seen, value_pool_size);
  return new_heap_code_block(assm->runtime, bytecode, value_pool,
      assm->high_water_mark);
}
예제 #3
0
파일: bind.c 프로젝트: plesner/neutrino
// Executes a method declaration on the given fragment.
static value_t apply_method_declaration(value_t ambience, value_t decl,
    value_t fragment) {
  CHECK_FAMILY(ofMethodDeclarationAst, decl);
  CHECK_FAMILY(ofModuleFragment, fragment);
  runtime_t *runtime = get_ambience_runtime(ambience);
  // Look for the :builtin annotation on this method.
  value_t annots = get_method_declaration_ast_annotations(decl);
  value_t builtin_name = new_not_found_condition();
  for (size_t i = 0; i < get_array_length(annots); i++) {
    value_t annot = get_array_at(annots, i);
    TRY_DEF(value, run_expression_until_condition(ambience, fragment, annot));
    if (in_family(ofBuiltinMarker, value))
      builtin_name = get_builtin_marker_name(value);
  }
  // Compile the method whether it's a builtin or not. This way we can reuse
  // the compilation code for both cases and just patch up the result after
  // the fact if it's a builtin.
  value_t method_ast = get_method_declaration_ast_method(decl);
  TRY_DEF(method, compile_method_ast_to_method(runtime, method_ast, fragment));
  if (!in_condition_cause(ccNotFound, builtin_name)) {
    // This is a builtin so patch the method with the builtin implementation.
    TRY_DEF(impl, runtime_get_builtin_implementation(runtime, builtin_name));
    value_t impl_code = get_builtin_implementation_code(impl);
    TRY(validate_builtin_method_binding(method, impl));
    set_method_code(method, impl_code);
    value_t impl_flags = get_builtin_implementation_method_flags(impl);
    set_method_flags(method, impl_flags);
  }
  value_t methodspace = get_module_fragment_methodspace(fragment);
  TRY(add_methodspace_method(runtime, methodspace, method));
  return success();
}
예제 #4
0
파일: bind.c 프로젝트: plesner/neutrino
// Iteratively apply the elements of the unbound fragment to the partially
// initialized bound fragment.
static value_t apply_module_fragment_elements(binding_context_t *context,
    value_t unbound_fragment, value_t bound_fragment) {
  value_t elements = get_unbound_module_fragment_elements(unbound_fragment);
  for (size_t i = 0; i < get_array_length(elements); i++) {
    value_t element = get_array_at(elements, i);
    TRY(apply_unbound_fragment_element(context->ambience, element, bound_fragment));
  }
  return success();
}
예제 #5
0
파일: bind.c 프로젝트: plesner/neutrino
value_t module_loader_process_options(runtime_t *runtime, value_t self,
    value_t options) {
  CHECK_FAMILY(ofIdHashMap, options);
  value_t libraries = get_id_hash_map_at_with_default(options, RSTR(runtime, libraries),
      ROOT(runtime, empty_array));
  for (size_t i = 0; i < get_array_length(libraries); i++) {
    value_t library_path = get_array_at(libraries, i);
    TRY(module_loader_read_library(runtime, self, library_path));
  }
  return success();
}
예제 #6
0
TEST(plankton, references) {
  CREATE_RUNTIME();

  value_t i0 = new_heap_instance(runtime, ROOT(runtime, empty_instance_species));
  value_t i1 = new_heap_instance(runtime, ROOT(runtime, empty_instance_species));
  value_t i2 = new_heap_instance(runtime, ROOT(runtime, empty_instance_species));
  value_t array = new_heap_array(runtime, 6);
  set_array_at(array, 0, i0);
  set_array_at(array, 1, i2);
  set_array_at(array, 2, i0);
  set_array_at(array, 3, i1);
  set_array_at(array, 4, i2);
  set_array_at(array, 5, i1);
  value_t decoded = check_plankton(runtime, array);
  ASSERT_SAME(get_array_at(decoded, 0), get_array_at(decoded, 2));
  ASSERT_NSAME(get_array_at(decoded, 0), get_array_at(decoded, 1));
  ASSERT_SAME(get_array_at(decoded, 1), get_array_at(decoded, 4));
  ASSERT_NSAME(get_array_at(decoded, 1), get_array_at(decoded, 3));
  ASSERT_SAME(get_array_at(decoded, 3), get_array_at(decoded, 5));

  DISPOSE_RUNTIME();
}
예제 #7
0
파일: method.c 프로젝트: tundra/neutrino
value_t build_call_tags_entries(runtime_t *runtime, value_t tags) {
  int64_t tag_count = get_array_length(tags);
  TRY_DEF(result, new_heap_pair_array(runtime, tag_count));
  for (int64_t i = 0; i < tag_count; i++) {
    set_pair_array_first_at(result, i, get_array_at(tags, i));
    // The offset is counted backwards because the argument evaluated last will
    // be at the top of the stack, that is, offset 0, and the first will be at
    // the bottom so has the highest offset.
    int64_t offset = tag_count - i - 1;
    set_pair_array_second_at(result, i, new_integer(offset));
  }
  TRY(co_sort_pair_array(result));
  IF_EXPENSIVE_CHECKS_ENABLED(check_call_tags_entries_unique(result));
  return result;
}
예제 #8
0
파일: bind.c 프로젝트: plesner/neutrino
// Given an array of modules map builds a two-level map from paths to stages to
// fragment entries.
static value_t build_real_fragment_entries(binding_context_t *context,
    value_t modules) {
  runtime_t *runtime = get_ambience_runtime(context->ambience);
  for (size_t mi = 0; mi < get_array_buffer_length(modules); mi++) {
    value_t module = get_array_buffer_at(modules, mi);
    value_t path = get_unbound_module_path(module);
    value_t fragments = get_unbound_module_fragments(module);
    for (size_t fi = 0; fi < get_array_length(fragments); fi++) {
      value_t fragment = get_array_at(fragments, fi);
      value_t stage = get_unbound_module_fragment_stage(fragment);
      bool dummy = false;
      TRY_DEF(entry, binding_context_ensure_fragment_entry(context, stage,
          path, fragment, &dummy));
      value_t imports = get_fragment_entry_imports(entry);
      value_t fragment_imports = get_unbound_module_fragment_imports(fragment);
      for (size_t ii = 0; ii < get_array_length(fragment_imports); ii++) {
        value_t import = get_array_at(fragment_imports, ii);
        TRY_DEF(ident, new_heap_identifier(runtime, present_stage(), import));
        TRY(ensure_array_buffer_contains(runtime, imports, ident));
      }
    }
  }
  return success();
}
예제 #9
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();
}
예제 #10
0
파일: method.c 프로젝트: tundra/neutrino
value_t get_call_data_value_at(value_t self, int64_t param_index) {
  value_t tags = get_call_data_tags(self);
  int64_t offset = get_call_tags_offset_at(tags, param_index);
  value_t values = get_call_data_values(self);
  return get_array_at(values, offset);
}
예제 #11
0
파일: interp.c 프로젝트: plesner/neutrino
// Returns the value at the given offset from the current pc.
static value_t read_value(code_cache_t *cache, frame_t *frame, size_t offset) {
    size_t index = read_short(cache, frame, offset);
    return get_array_at(cache->value_pool, index);
}