Example #1
0
// Note that, within this function, the the conversion's type
// is equivalent to the destination type.
//
// FIXME: Factor out the "conformance checking" code.
Expr*
admit_binary_conv(Context& cxt, Conversion_cons& c, Binary_expr& e)
{
  // Determine if the operands can be converted to the
  // declared type of the required expressin.
  Binary_expr& a = cast<Binary_expr>(c.expression());
  Type& t1 = declared_type(a.left());
  Type& t2 = declared_type(a.right());
  try {
    copy_initialize(cxt, t1, e.left());
    copy_initialize(cxt, t2, e.right());
  } catch(Translation_error&) {
    return nullptr;
  }

  // Adjust the type of the expression under test to that of
  // the required expression.
  //
  // FIXME: It's possible that we need to preserve the original
  // conversions in order to sort candidates. Consider:
  //
  //    requires (T a, T const b) {
  //      f(a) -> T;        // #1
  //      f(b) -> T const;  // #2
  //    }
  //
  // In an algorithm that uses a f(x) where x is const, we would
  // prefer #1. Perhaps we should collect viable conversion
  // and then sort at the end. Note that this is true for simple
  // typings also.
  //
  // FIXME: Add constructors to the builder. This is just plain dumb.
  return new Dependent_conv(c.type(), e);
}
Example #2
0
Expr*
admit_call_expr(Context& cxt, Usage& c, Call_expr& e)
{
  Call_expr& a = cast<Call_expr>(c.expression());

  // Build the list of parameter types from the declared types
  // of operands in the constraint.
  Type_list ts {&declared_type(a.function())};
  for (Expr& e0 : a.arguments())
    ts.push_back(declared_type(e0));

  // Build the list of arguments from e. Note that the first
  // argument is actually the function.
  Expr_list es {&e.function()};
  for (Expr& e0 : e.arguments())
    es.push_back(e0);

  // If conversion fails, this is not accessible.
  try {
    initialize_parameters(cxt, ts, es);
  } catch (Translation_error&) {
    return nullptr;
  }

  // Adjust the type and admit the expression.
  e.type_ = &a.type();
  return &e;
}
Example #3
0
Type* specializeType_div(Term* term)
{
    Type* left = declared_type(term->input(0));
    Type* right = declared_type(term->input(1));

    if ((left == TYPES.int_type || left == TYPES.float_type)
            && (right == TYPES.int_type || right == TYPES.float_type))
        return TYPES.float_type;

    return TYPES.any;
}
Example #4
0
Type* output_placeholder_specializeType(Term* caller)
{
    // Don't specialize if the type was explicitly declared
    if (caller->boolProp(s_ExplicitType, false))
        return declared_type(caller);

    // Special case: if we're an accumulatingOutput then the output type is List.
    if (caller->boolProp(s_AccumulatingOutput, false))
        return TYPES.list;

    if (caller->input(0) == NULL)
        return NULL;

    return declared_type(caller->input(0));
}
Example #5
0
// Direct initialzie `d` by a brace-enclosed list of expressions
// `es`.
Expr&
Parser::on_brace_initialization(Decl& d, Expr_list& es)
{
  Expr& i = list_initialize(cxt, declared_type(d), es);
  initialize_declaration(d, i);
  return i;
}
Example #6
0
void branch_update_state_type(Branch* branch)
{
    if (branch_state_type_is_out_of_date(branch)) {

        // TODO: Handle the case where the stateType should go from non-NULL to NULL

        // Recreate the state type
        Type* type = create_compound_type();

        // TODO: give this new type a nice name

        for (int i=0; i < branch->length(); i++) {
            Term* term = branch->get(i);
            if (term == NULL)
                continue;

            if (term->function != FUNCS.unpack_state || FUNCS.unpack_state == NULL)
                continue;

            Term* identifyingTerm = term->input(1);

            compound_type_append_field(type, declared_type(term), unique_name(identifyingTerm));
        }

        branch->stateType = type;

        // Might need to update any existing pack_state calls.
        branch_update_existing_pack_state_calls(branch);
    }
}
Example #7
0
void block_update_state_type(Block* block)
{
    if (!block_state_type_is_out_of_date(block))
        return;

    // Recreate the state type
    Type* type = create_compound_type();

    // TODO: give this new type a nice name

    for (int i=0; i < block->length(); i++) {
        Term* term = block->get(i);
        if (term == NULL)
            continue;

        if (term->function != FUNCS.unpack_state || FUNCS.unpack_state == NULL)
            continue;

        Term* identifyingTerm = term->input(1);

        caValue* fieldName = get_unique_name(identifyingTerm);
        ca_assert(is_string(fieldName));
        ca_assert(!string_eq(fieldName, ""));

        compound_type_append_field(type, declared_type(term), as_cstring(fieldName));
    }

    block->stateType = type;
    block_remove_property(block, sym_DirtyStateType);

    // Might need to update any existing pack_state calls.
    block_update_pack_state_calls(block);
}
ciType* Local::exact_type() const {
  ciType* type = declared_type();

  // for primitive arrays, the declared type is the exact type
  if (type->is_type_array_klass()) {
    return type;
  } else if (type->is_instance_klass()) {
    ciInstanceKlass* ik = (ciInstanceKlass*)type;
    if (ik->is_loaded() && ik->is_final() && !ik->is_interface()) {
      return type;
    }
  } else if (type->is_obj_array_klass()) {
    ciObjArrayKlass* oak = (ciObjArrayKlass*)type;
    ciType* base = oak->base_element_type();
    if (base->is_instance_klass()) {
      ciInstanceKlass* ik = base->as_instance_klass();
      if (ik->is_loaded() && ik->is_final()) {
        return type;
      }
    } else if (base->is_primitive_type()) {
      return type;
    }
  }
  return NULL;
}
Example #9
0
// Copy initialize the declaration `d` with `e`.
Expr&
Parser::on_equal_initialization(Decl& d, Expr& e)
{
  Expr& i = copy_initialize(cxt, declared_type(d), e);
  initialize_declaration(d, i);
  return i;
}
Example #10
0
// Select a default initializer for `d`.
//
// FIXME: This relies on the construction of placeholder nodes
// in the initialization branch. That seems wrong. We should be
// able to convey syntax via flags.
Expr&
Parser::on_default_initialization(Decl& d)
{
  Type& t = declared_type(d);
  Expr& i = default_initialize(cxt, t);
  initialize_declaration(d, i);
  return i;
}
Example #11
0
 void staticTypeQuery(Type* type, StaticTypeQuery* query)
 {
     Type* subjectType = declared_type(query->subject);
     if (subjectType->getIndex != NULL
             && subjectType->numElements != NULL)
         query->succeed();
     else
         query->fail();
 }
Example #12
0
Block* statically_resolve_dynamic_method(Term* term)
{
    ca_assert(term->function == FUNCS.dynamic_method);

    Value nameLocation;
    nameLocation.set_list(2);
    nameLocation.index(0)->set(term->getProp(s_method_name));
    nameLocation.index(1)->set_term(term);

    return find_method_on_type(declared_type(term), &nameLocation);
}
Example #13
0
ciType* LoadField::exact_type() const {
  ciType* type = declared_type();
  // for primitive arrays, the declared type is the exact type
  if (type->is_type_array_klass()) {
    return type;
  }
  if (type->is_instance_klass()) {
    ciInstanceKlass* ik = (ciInstanceKlass*)type;
    if (ik->is_loaded() && ik->is_final()) {
      return type;
    }
  }
  return NULL;
}
Example #14
0
// Allocate space for an object of type `t`. No value initialization
// procedure is invoked.
//
// This currently works by prototyping an object of the approppriate
// shape and storing that for the declaration.
//
// TODO: It would be better if we could just emplace the approiately
// shaped object directly into the store.
Value&
Evaluator::alloca(Decl const& d)
{
  struct fn
  {
    Value operator()(Type const& t) { banjo_unhandled_case(t); }
    Value operator()(Boolean_type const&) { return 0; }
    Value operator()(Integer_type const&) { return 0; }
    Value operator()(Float_type const&)   { return 0.0; }
    Value operator()(Function_type const&) { return Function_value(nullptr); }
    Value operator()(Reference_type const&) { return Reference_value(nullptr); }
  };
  return store(d, apply(declared_type(d), fn{}));
}
Example #15
0
Expr*
admit_binary_expr(Context& cxt, Usage& c, Binary_expr& e)
{
  // Determine if the operands can be converted to the
  // declared type of the required expressin.
  Binary_expr& a = cast<Binary_expr>(c.expression());
  Type& t1 = declared_type(a.left());
  Type& t2 = declared_type(a.right());
  try {
    copy_initialize(cxt, t1, e.left());
    copy_initialize(cxt, t2, e.right());
  } catch(Translation_error&) {
    return nullptr;
  }

  // Adjust the type of the expression under test to that of
  // the required expression.
  //
  // FIXME: See the notes on admit_binary_conv. We may want
  // to preserve the conversions for the purpose of ordering.
  e.type_ = &a.type();
  return &e;
}
Example #16
0
    void hosted_get_index(caStack* stack)
    {
        caValue* list = circa_input(stack, 0);
        int index = circa_int_input(stack, 1);

        if (index < 0) {
            char indexStr[40];
            sprintf(indexStr, "Negative index: %d", index);
            return circa_output_error(stack, indexStr);
        } else if (index >= list_length(list)) {
            char indexStr[40];
            sprintf(indexStr, "Index out of range: %d", index);
            return circa_output_error(stack, indexStr);
        }

        caValue* result = get_index(list, index);

        copy(result, circa_output(stack, 0));
        cast(circa_output(stack, 0), declared_type((Term*) circa_caller_term(stack)));
    }
Example #17
0
Term* rebind_possible_accessor(Branch* branch, Term* accessor, Term* result)
{
    // Check if this isn't a recognized accessor.
    if (!has_empty_name(accessor)) {
        // Just create a named copy of 'result'.
        return apply(branch, FUNCS.copy, TermList(result), accessor->nameSymbol);
    }

    TermList accessorChain;
    trace_accessor_chain(accessor, &accessorChain);

    Term* head = accessorChain[0];

    // Create the selector
    Term* selector = write_selector_for_accessor_chain(branch, &accessorChain);

    Term* set = apply(branch, FUNCS.set_with_selector,
            TermList(head, selector, result), head->nameSymbol);

    change_declared_type(set, declared_type(head));
    return set;
}
Example #18
0
bool branch_state_type_is_out_of_date(Branch* branch)
{
    // Alloc an array that tracks, for each field in the existing stateType,
    // whether we have found a corresponding term for that field.
    bool* typeFieldFound = NULL;
    int existingFieldCount = 0;

    if (branch->stateType != NULL) {
        existingFieldCount = compound_type_get_field_count(branch->stateType);
        size_t size = sizeof(bool) * existingFieldCount;
        typeFieldFound = (bool*) malloc(size);
        memset(typeFieldFound, 0, size);
    }
    
    // Walk through every term and check whether every unpack_state call is already
    // mentioned in the state type.
    for (int i=0; i < branch->length(); i++) {
        Term* term = branch->get(i);
        if (term == NULL)
            continue;

        if (term->function != FUNCS.unpack_state)
            continue;

        // Found an unpack_state call
        Term* identifyingTerm = term->input(1);

        // If the branch doesn't yet have a stateType then that's an update.
        if (branch->stateType == NULL)
            goto return_true;

        // Look for the field name
        int fieldIndex = list_find_field_index_by_name(branch->stateType,
            unique_name(identifyingTerm));

        // If the name isn't found then that's an update
        if (fieldIndex == -1)
            goto return_true;

        // If the type doesn't match then that's an update
        if (compound_type_get_field_type(branch->stateType, fieldIndex)
                != declared_type(term))
            goto return_true;

        // Record this field index as 'found'
        typeFieldFound[fieldIndex] = true;
    }

    // If there were any fields in the type that weren't found in the branch, then
    // that's an update.
    if (typeFieldFound != NULL) {
        for (int i=0; i < existingFieldCount; i++) {
            if (!typeFieldFound[i])
                goto return_true;
        }
    }

    // No reason to update, return false.
    free(typeFieldFound);
    return false;

return_true:
    free(typeFieldFound);
    return true;
}
Example #19
0
Synthetic_expr&
Builder::synthesize_expression(Decl& d)
{
  return make<Synthetic_expr>(declared_type(d), d);
}
Example #20
0
// Returns the declared type of an expression. In general, this is type of 
// the expression. However, for id-expressions, we actually use the declared 
// type of the referenced declaration.
Type const&
declared_type(Expr const& e)
{
  return declared_type(modify(e));
}