Пример #1
0
// Process the given provided method for the given entity.
// The method passed should be reified already and will be freed by this
// function.
static bool provided_method(ast_t* entity, ast_t* reified_method,
  ast_t* raw_method, ast_t** last_method)
{
  assert(entity != NULL);
  assert(reified_method != NULL);
  assert(last_method != NULL);

  const char* entity_name = ast_name(ast_child(entity));

  if(ast_id(reified_method) == TK_BE || ast_id(reified_method) == TK_NEW)
  {
    // Modify return type to the inheritting type
    ast_t* ret_type = ast_childidx(reified_method, 4);
    assert(ast_id(ret_type) == TK_NOMINAL);

    const char* pkg_name = package_name(ast_nearest(entity, TK_PACKAGE));
    ast_set_name(ast_childidx(ret_type, 0), pkg_name);
    ast_set_name(ast_childidx(ret_type, 1), entity_name);
  }

  // Ignore docstring
  ast_t* doc = ast_childidx(reified_method, 7);

  if(ast_id(doc) == TK_STRING)
  {
    ast_set_name(doc, "");
    ast_setid(doc, TK_NONE);
  }

  // Check for existing method of the same name
  const char* name = ast_name(ast_childidx(reified_method, 1));
  assert(name != NULL);

  ast_t* existing = ast_get(entity, name, NULL);

  if(existing != NULL && is_field(existing))
  {
    ast_error(existing, "field '%s' clashes with provided method", name);
    ast_error(raw_method, "method is defined here");
    ast_free_unattached(reified_method);
    return false;
  }

  existing = add_method(entity, existing, reified_method, last_method);

  if(existing == NULL)
  {
    ast_free_unattached(reified_method);
    return false;
  }

  method_t* info = (method_t*)ast_data(existing);
  assert(info != NULL);

  if(!record_default_body(reified_method, raw_method, info))
    ast_free_unattached(reified_method);

  return true;
}
Пример #2
0
// Process the given provided method for the given entity.
// The method passed should be reified already and will be freed by this
// function.
static bool provided_method(pass_opt_t* opt, ast_t* entity,
  ast_t* reified_method, ast_t* raw_method, ast_t** last_method)
{
  assert(entity != NULL);
  assert(reified_method != NULL);
  assert(last_method != NULL);

  AST_GET_CHILDREN(reified_method, cap, id, typeparams, params, result,
    can_error, body, doc);

  if(ast_id(reified_method) == TK_BE || ast_id(reified_method) == TK_NEW)
  {
    // Modify return type to the inheriting type
    ast_t* this_type = type_for_this(opt, entity, ast_id(cap),
      TK_EPHEMERAL, true);

    ast_replace(&result, this_type);
  }

  // Ignore docstring
  if(ast_id(doc) == TK_STRING)
  {
    ast_set_name(doc, "");
    ast_setid(doc, TK_NONE);
  }

  // Check for existing method of the same name
  const char* name = ast_name(id);
  assert(name != NULL);

  ast_t* existing = ast_get(entity, name, NULL);

  if(existing != NULL && is_field(existing))
  {
    ast_error(existing, "field '%s' clashes with provided method", name);
    ast_error(raw_method, "method is defined here");
    ast_free_unattached(reified_method);
    return false;
  }

  existing = add_method(entity, existing, reified_method, last_method);

  if(existing == NULL)
  {
    ast_free_unattached(reified_method);
    return false;
  }

  method_t* info = (method_t*)ast_data(existing);
  assert(info != NULL);

  if(!record_default_body(reified_method, raw_method, info))
    ast_free_unattached(reified_method);

  return true;
}
Пример #3
0
bool binspector_parser_t::is_named_statement()
{
    return is_invariant() ||
           is_constant()  ||
           is_skip()      ||
           is_slot()      ||
           is_signal()    ||
           is_field(); // field should be last because atoms only
                       // require an expression which most everything
                       // falls into; the more explicit stuff should 
                       // come first.
}
Пример #4
0
// Process the methods required for delegation to all the fields in the given
// entity.
static bool delegated_methods(ast_t* entity, pass_opt_t* opt)
{
  assert(entity != NULL);

  bool r = true;

  // Check all fields.
  for(ast_t* field = ast_child(ast_childidx(entity, 4)); field != NULL;
    field = ast_sibling(field))
  {
    if(is_field(field))
    {
      AST_GET_CHILDREN(field, id, f_type, value, delegates);

      // Check all delegates for field.
      for(ast_t* trait_ref = ast_child(delegates); trait_ref != NULL;
        trait_ref = ast_sibling(trait_ref))
      {
        ast_t* trait = (ast_t*)ast_data(trait_ref);
        assert(trait != NULL);

        if(!trait_entity(trait, opt))
          return false;

        // Run through the methods of each delegated type.
        for(ast_t* method = ast_child(ast_childidx(trait, 4));
          method != NULL; method = ast_sibling(method))
        {
          if(!delegated_method(entity, method, field, trait_ref, opt))
            r = false;
        }
      }
    }
  }

  return r;
}
Пример #5
0
// Process all field delegations in the given type.
// Stage 3.
static bool field_delegations(ast_t* entity)
{
  assert(entity != NULL);

  ast_t* members = ast_childidx(entity, 4);
  assert(members != NULL);

  bool r = true;

  // Check all fields
  for(ast_t* f = ast_child(members); f != NULL; f = ast_sibling(f))
  {
    if(is_field(f))
    {
      AST_GET_CHILDREN(f, id, f_type, value, delegates);

      // Check all delegates for field
      for(ast_t* d = ast_child(delegates); d != NULL; d = ast_sibling(d))
      {
        if(!check_delegate(entity, f_type, d))
        {
          r = false;
          continue;
        }

        // Mark all methods in delegate trait as targets for this field
        ast_t* trait = (ast_t*)ast_data(d);
        assert(trait != NULL);
        ast_t* t_members = ast_childidx(trait, 4);

        for(ast_t* m = ast_child(t_members); m != NULL; m = ast_sibling(m))
        {
          if(is_method(m))
          {
            // Mark method as delegate target for this field
            const char* method_name = ast_name(ast_childidx(m, 1));
            assert(method_name != NULL);

            ast_t* local_method = ast_get(entity, method_name, NULL);
            assert(local_method != NULL);

            method_t* info = (method_t*)ast_data(local_method);
            assert(info != NULL);

            if(info->delegate_field_1 == NULL)
            {
              // First delegate field for this method
              info->delegate_field_1 = f;
              info->delegate_target_1 = d;
            }
            else if(info->delegate_field_2 == NULL &&
              info->delegate_field_1 != f)
            {
              // We already have one delegate field, record second
              info->delegate_field_2 = f;
              info->delegate_target_2 = d;
            }
          }
        }
      }
    }
  }

  return r;
}
Пример #6
0
// Puts "field" from "section" from .ini file "f" into "s".
// If "section" does not exist or "field" does not exist in
// section then s="";
void ini_fgets(FILE *f, const char *section, const char *field, char *s)
{
   int i;
   long start_pos,string_start_pos;
   char ts[INI_STRING_SIZE*2];

   if (f!=current_file)
      reset_buffer(f);

   // Default to "Not found"
   s[0]=0;

   // See if section is in buffer
   for (i=0;i<NUM_SECTION_BUFFERS;i++)
      if (strnicmp(section_buffers[i].name,section,MAX_SECTION_WIDTH)==0)
         break;

   // If section is in buffer, seek to it if necessary
   if (i<NUM_SECTION_BUFFERS)
   {
      if (i!=current_section)
      {
         current_section=i;
         fseek(f,section_buffers[i].offset,SEEK_SET);
      }
   }
   // else look through .ini file for it.
   else
   {
      // Make sure we are not at eof or this will cause trouble.
      if (feof(f))
         rewind(f);
      start_pos=ftell(f);
      while (1)
      {
         stripped_fgets(ts,INI_STRING_SIZE*2,f);
         // If it is a section, add it to the section buffer
         if (is_section(ts,"*"))
            current_section=add_section(ts,ftell(f));
         // If it is the section we are looking for, break.
         if (is_section(ts,section))
            break;
         // If we reach the end of the file, rewind to the start.
         if (feof(f))
            rewind(f);
         if (ftell(f)==start_pos)
            return;
      }
   }

   // See if field is in buffer
   for (i=0;i<NUM_FIELD_BUFFERS;i++)
      if (field_buffers[i].section==current_section)
         if (strnicmp(field_buffers[i].name,field,MAX_FIELD_WIDTH)==0)
            break;

   // If field is in buffer, seek to it and read it
   if (i<NUM_FIELD_BUFFERS)
   {
      fseek(f,field_buffers[i].offset,SEEK_SET);
      stripped_fgets(ts,INI_STRING_SIZE*2,f);
      get_field_string(s,ts);
   }
   else
   // else search through section for field.
   {
      // Make sure we do not start at eof or this will cause problems.
      if (feof(f))
         fseek(f,section_buffers[current_section].offset,SEEK_SET);
      start_pos=ftell(f);
      while (1)
      {
         string_start_pos=ftell(f);
         stripped_fgets(ts,INI_STRING_SIZE*2,f);
         // If it is a field, add it to the buffer
         if (is_field(ts,"*"))
            add_field(ts,current_section,string_start_pos);
         // If it is the field we are looking for, save it
         if (is_field(ts,field))
         {
            get_field_string(s,ts);
            break;
         }
         // If we reach the end of the section, start over
         if (feof(f) || is_section(ts,"*"))
            fseek(f,section_buffers[current_section].offset,SEEK_SET);
         if (ftell(f)==start_pos)
            return;
      }
   }
}
Пример #7
0
static int release_parse_line(void *ptr, const char *line, uint mask)
{
    release_t *release = (release_t *) ptr;

    int ret = 0;
    unsigned int count = 0;
    char **list = 0;
    static int reading_md5sums = 0;
#ifdef HAVE_SHA256
    static int reading_sha256sums = 0;
#endif

    switch (*line) {
    case 'A':
        if (is_field("Architectures", line)) {
            release->architectures = parse_list(line, &release->architectures_count,
                    ' ', 0);
        }
        break;

    case 'C':
        if (is_field("Codename", line)) {
            release->name = parse_simple("Codename", line);
        } else if (is_field("Components", line)) {
            release->components = parse_list(line, &release->components_count,
                    ' ', 0);
        }
        break;

    case 'D':
        if (is_field("Date", line)) {
            release->datestring = parse_simple("Date", line);
        }
        break;

    case 'M':
        if (is_field("MD5sum", line)) {
            reading_md5sums = 1;
            if (release->md5sums == NULL) {
                release->md5sums = xcalloc(1, sizeof(cksum_list_t));
                cksum_list_init(release->md5sums);
            }
            goto dont_reset_flags;
        }
        break;

#ifdef HAVE_SHA256
    case 'S':
        if (is_field("SHA256", line)) {
            reading_sha256sums = 1;
            if (release->sha256sums == NULL) {
                release->sha256sums = xcalloc(1, sizeof(cksum_list_t));
                cksum_list_init(release->sha256sums);
            }
            goto dont_reset_flags;
        }
        break;
#endif

    case ' ':
        if (reading_md5sums) {
            list = parse_list(line, &count, ' ', 1);
            cksum_list_append(release->md5sums, list);
            goto dont_reset_flags;
        }
#ifdef HAVE_SHA256
        else if (reading_sha256sums) {
            list = parse_list(line, &count, ' ', 1);
            cksum_list_append(release->sha256sums, list);
            goto dont_reset_flags;
        }
#endif
        break;

    default:
        ret = 1;
    }

    reading_md5sums = 0;
#ifdef HAVE_SHA256
    reading_sha256sums = 0;
#endif

 dont_reset_flags:

    return ret;
}
Пример #8
0
// Add a new method to the given entity, based on the specified method from
// the specified type.
// The trait_ref is the entry in the provides / delegates list that causes this
// method inclusion. Needed for error reporting.
// The basis_method is the reified method in the trait to add.
// The adjective parameter is used for error reporting and should be "provided"
// or similar.
// Return the newly added method or NULL on error.
static ast_t* add_method(ast_t* entity, ast_t* trait_ref, ast_t* basis_method,
  const char* adjective, pass_opt_t* opt)
{
  assert(entity != NULL);
  assert(trait_ref != NULL);
  assert(basis_method != NULL);
  assert(adjective != NULL);

  const char* name = ast_name(ast_childidx(basis_method, 1));

  // Check behaviour compatability.
  if(ast_id(basis_method) == TK_BE)
  {
    switch(ast_id(entity))
    {
      case TK_PRIMITIVE:
        ast_error(opt->check.errors, trait_ref,
          "cannot add a behaviour (%s) to a primitive", name);
        return NULL;

      case TK_STRUCT:
        ast_error(opt->check.errors, trait_ref,
          "cannot add a behaviour (%s) to a struct", name);
        return NULL;

      case TK_CLASS:
        ast_error(opt->check.errors, trait_ref,
          "cannot add a behaviour (%s) to a class", name);
        return NULL;

      default:
        break;
    }
  }

  // Check for existing method of the same name.
  ast_t* existing = ast_get(entity, name, NULL);

  if(existing != NULL)
  {
    assert(is_field(existing)); // Should already have checked for methods.

    ast_error(opt->check.errors, trait_ref,
      "%s method '%s' clashes with field", adjective, name);
    ast_error_continue(opt->check.errors, basis_method,
      "method is defined here");
    return NULL;
  }

  // Check for clash with existing method.
  ast_t* case_clash = ast_get_case(entity, name, NULL);

  if(case_clash != NULL)
  {
    const char* clash_name = "";

    switch(ast_id(case_clash))
    {
      case TK_FUN:
      case TK_BE:
      case TK_NEW:
        clash_name = ast_name(ast_childidx(case_clash, 1));
        break;

      case TK_LET:
      case TK_VAR:
      case TK_EMBED:
        clash_name = ast_name(ast_child(case_clash));
        break;

      default:
        assert(0);
        break;
    }

    ast_error(opt->check.errors, trait_ref,
      "%s method '%s' differs only in case from '%s'",
      adjective, name, clash_name);
    ast_error_continue(opt->check.errors, basis_method,
      "clashing method is defined here");
    return NULL;
  }

  AST_GET_CHILDREN(basis_method, cap, id, typeparams, params, result,
    can_error, body, doc);

  // Ignore docstring.
  if(ast_id(doc) == TK_STRING)
  {
    ast_set_name(doc, "");
    ast_setid(doc, TK_NONE);
  }

  ast_t* local = ast_append(ast_childidx(entity, 4), basis_method);
  ast_set(entity, name, local, SYM_DEFINED, false);
  ast_t* body_donor = (ast_t*)ast_data(basis_method);
  method_t* info = attach_method_t(local);
  info->trait_ref = trait_ref;

  if(ast_id(body) != TK_NONE)
    info->body_donor = body_donor;

  return local;
}