Esempio n. 1
0
File: control.c Progetto: ozra/ponyc
bool expr_break(typecheck_t* t, ast_t* ast)
{
    if(t->frame->loop_body == NULL)
    {
        ast_error(ast, "must be in a loop");
        return false;
    }

    if(!ast_all_consumes_in_scope(t->frame->loop_body, ast))
        return false;

    // break is always the last expression in a sequence
    assert(ast_sibling(ast) == NULL);

    ast_settype(ast, ast_from(ast, TK_BREAK));
    ast_inheritflags(ast);

    // Add type to loop.
    ast_t* body = ast_child(ast);

    if(is_control_type(ast_type(body)))
    {
        ast_error(body, "break value cannot be a control statement");
        return false;
    }

    ast_t* loop_type = ast_type(t->frame->loop);

    loop_type = control_type_add_branch(loop_type, body);
    ast_settype(t->frame->loop, loop_type);

    return true;
}
Esempio n. 2
0
static bool method_chain(pass_opt_t* opt, ast_t* ast)
{
  if(!method_application(opt, ast, false))
    return false;

  // We check the receiver cap now instead of in method_application because
  // we need to know whether the receiver was recovered.
  ast_t* lhs = ast_childidx(ast, 2);
  ast_t* r_type = method_receiver_type(lhs);
  if(ast_id(lhs) == TK_FUNCHAIN)
  {
    bool recovered;
    if(!check_receiver_cap(opt, ast, &recovered))
      return false;

    if(!check_nonsendable_recover(opt, ast))
      return false;

    ast_t* f_type = ast_type(lhs);
    token_id f_cap = ast_id(ast_child(f_type));

    ast_t* c_type = chain_type(r_type, f_cap, recovered);
    ast_settype(ast, c_type);
  } else {
    ast_settype(ast, r_type);
  }

  return true;
}
Esempio n. 3
0
ast_t* control_type_add_branch(ast_t* control_type, ast_t* branch)
{
  assert(branch != NULL);

  ast_t* branch_type = ast_type(branch);

  if(is_typecheck_error(branch_type))
    return branch_type;

  if(is_type_literal(branch_type))
  {
    // The new branch is a literal
    if(control_type == NULL)
      control_type = ast_from(branch, TK_LITERAL);

    if(ast_id(control_type) != TK_LITERAL)
    {
      // The current control type is not a literal, fix that
      ast_t* old_control = control_type;
      control_type = ast_from(branch, TK_LITERAL);
      ast_settype(control_type, old_control);
    }

    assert(ast_id(control_type) == TK_LITERAL);

    // Add a literal branch reference to the new branch
    ast_t* member = ast_from(branch, TK_LITERALBRANCH);
    ast_setdata(member, (void*)branch);
    ast_append(control_type, member);

    ast_t* branch_non_lit = ast_type(branch_type);

    if(branch_non_lit != NULL)
    {
      // The branch's literal type has a non-literal component
      ast_t* non_literal_type = ast_type(control_type);
      ast_settype(control_type, type_union(non_literal_type, branch_non_lit));
    }

    return control_type;
  }

  if(control_type != NULL && ast_id(control_type) == TK_LITERAL)
  {
    // New branch is not literal, but the control structure is
    // Add new branch type to the control structure's non-literal aspect
    ast_t* non_literal_type = ast_type(control_type);
    non_literal_type = type_union(non_literal_type, branch_type);
    ast_settype(control_type, non_literal_type);
    return control_type;
  }

  // No literals here, just union the types
  return type_union(control_type, branch_type);
}
Esempio n. 4
0
bool expr_dontcare(ast_t* ast)
{
    // We are a tuple element. That tuple must either be a pattern or the LHS
    // of an assignment. It can be embedded in other tuples, which may appear
    // in sequences.
    ast_t* tuple = ast_parent(ast);

    if(ast_id(tuple) == TK_TUPLE)
    {
        ast_t* parent = ast_parent(tuple);

        while((ast_id(parent) == TK_TUPLE) || (ast_id(parent) == TK_SEQ))
        {
            tuple = parent;
            parent = ast_parent(tuple);
        }

        switch(ast_id(parent))
        {
        case TK_ASSIGN:
        {
            AST_GET_CHILDREN(parent, right, left);

            if(tuple == left)
            {
                ast_settype(ast, ast);
                return true;
            }

            break;
        }

        case TK_CASE:
        {
            AST_GET_CHILDREN(parent, pattern, guard, body);

            if(tuple == pattern)
            {
                ast_settype(ast, ast);
                return true;
            }

            break;
        }

        default:
        {}
        }
    }

    ast_error(ast, "the don't care token can only appear in a tuple, either on "
              "the LHS of an assignment or in a pattern");
    return false;
}
Esempio n. 5
0
bool expr_match_capture(pass_opt_t* opt, ast_t* ast)
{
  (void)opt;
  assert(ast != NULL);

  ast_t* type = ast_childidx(ast, 1);
  assert(type != NULL);

  // Capture type is as specified.
  ast_settype(ast, type);
  ast_settype(ast_child(ast), type);
  return true;
}
Esempio n. 6
0
// Setup the type, or lack thereof, for local variable declarations.
// This is not really anything to do with traits, but must be done before the
// expr pass (to allow initialisation references to the variable type) but
// after the name pass (to get temporal capabilities).
static void local_types(ast_t* ast)
{
  assert(ast != NULL);

  // Setup type or mark as inferred now to allow calling create on a
  // non-inferred local to initialise itself
  AST_GET_CHILDREN(ast, id, type);
  assert(type != NULL);

  if(ast_id(type) == TK_NONE)
    type = ast_from(id, TK_INFERTYPE);

  ast_settype(id, type);
  ast_settype(ast, type);
}
Esempio n. 7
0
bool expr_fieldref(pass_opt_t* opt, ast_t* ast, ast_t* find, token_id tid)
{
  AST_GET_CHILDREN(ast, left, right);
  ast_t* l_type = ast_type(left);

  if(is_typecheck_error(l_type))
    return false;

  AST_GET_CHILDREN(find, id, f_type, init);

  // Viewpoint adapted type of the field.
  ast_t* type = viewpoint_type(l_type, f_type);

  if(ast_id(type) == TK_ARROW)
  {
    ast_t* upper = viewpoint_upper(type);

    if(upper == NULL)
    {
      ast_error(ast, "can't read a field through %s", ast_print_type(l_type));
      return false;
    }

    ast_free_unattached(upper);
  }

  // Set the unadapted field type.
  ast_settype(right, f_type);

  // Set the type so that it isn't free'd as unattached.
  ast_setid(ast, tid);
  ast_settype(ast, type);

  if(ast_id(left) == TK_THIS)
  {
    // Handle symbol status if the left side is 'this'.
    ast_t* id = ast_child(find);
    const char* name = ast_name(id);

    sym_status_t status;
    ast_get(ast, name, &status);

    if(!valid_reference(opt, ast, type, status))
      return false;
  }

  return true;
}
Esempio n. 8
0
bool expr_recover(ast_t* ast)
{
  AST_GET_CHILDREN(ast, cap, expr);
  ast_t* type = ast_type(expr);

  if(is_typecheck_error(type))
    return false;

  if(is_type_literal(type))
  {
    make_literal_type(ast);
    return true;
  }

  ast_t* r_type = recover_type(type, ast_id(cap));

  if(r_type == NULL)
  {
    errorframe_t frame = NULL;
    ast_error_frame(&frame, ast, "can't recover to this capability");
    ast_error_frame(&frame, expr, "expression type is %s",
      ast_print_type(type));
    errorframe_report(&frame);
    return false;
  }

  ast_settype(ast, r_type);
  ast_inheritflags(ast);

  // Push our symbol status to our parent scope.
  ast_inheritstatus(ast_parent(ast), expr);
  return true;
}
Esempio n. 9
0
static bool tuple_access(ast_t* ast)
{
  // Left is a postfix expression, right is a lookup name.
  ast_t* left = ast_child(ast);
  ast_t* right = ast_sibling(left);
  ast_t* type = ast_type(left);

  if(is_typecheck_error(type))
    return false;

  // Change the lookup name to an integer index.
  if(!make_tuple_index(&right))
  {
    ast_error(right,
      "lookup on a tuple must take the form _X, where X is an integer");
    return false;
  }

  // Make sure our index is in bounds.
  type = ast_childidx(type, (size_t)ast_int(right));

  if(type == NULL)
  {
    ast_error(right, "tuple index is out of bounds");
    return false;
  }

  ast_setid(ast, TK_FLETREF);
  ast_settype(ast, type);
  ast_inheritflags(ast);
  return true;
}
Esempio n. 10
0
bool expr_recover(pass_opt_t* opt, ast_t* ast)
{
  AST_GET_CHILDREN(ast, cap, expr);
  ast_t* type = ast_type(expr);

  if(is_typecheck_error(type))
    return false;

  if(is_type_literal(type))
  {
    make_literal_type(ast);
    return true;
  }

  ast_t* r_type = recover_type(type, ast_id(cap));

  if(r_type == NULL)
  {
    ast_error(opt->check.errors, ast, "can't recover to this capability");
    ast_error_continue(opt->check.errors, expr, "expression type is %s",
      ast_print_type(type));
    return false;
  }

  ast_settype(ast, r_type);

  // Push our symbol status to our parent scope.
  ast_inheritstatus(ast_parent(ast), expr);
  return true;
}
Esempio n. 11
0
bool expr_identityof(pass_opt_t* opt, ast_t* ast)
{
  ast_t* expr = ast_child(ast);

  switch(ast_id(expr))
  {
    case TK_FVARREF:
    case TK_FLETREF:
    case TK_EMBEDREF:
    case TK_VARREF:
    case TK_LETREF:
    case TK_PARAMREF:
    case TK_THIS:
      break;

    default:
      ast_error(ast, "identity must be for a field, local, parameter or this");
      return false;
  }

  // Set the type to U64.
  ast_t* type = type_builtin(opt, expr, "U64");
  ast_settype(ast, type);
  return true;
}
Esempio n. 12
0
bool expr_param(pass_opt_t* opt, ast_t* ast)
{
  AST_GET_CHILDREN(ast, id, type, init);
  ast_settype(ast, type);
  bool ok = true;

  if(ast_id(init) != TK_NONE)
  {
    // Initialiser type must match declared type.
    if(!coerce_literals(&init, type, opt))
      return false;

    ast_t* init_type = ast_type(init);

    if(is_typecheck_error(init_type))
      return false;

    init_type = alias(init_type);
    errorframe_t err = NULL;

    if(!is_subtype(init_type, type, &err, opt))
    {
      errorframe_t err2 = NULL;
      ast_error_frame(&err2, init,
        "default argument is not a subtype of the parameter type");
      errorframe_append(&err2, &err);
      errorframe_report(&err2, opt->check.errors);
      ok = false;
    }

    ast_free_unattached(init_type);
  }

  return ok;
}
Esempio n. 13
0
bool expr_compiler_intrinsic(typecheck_t* t, ast_t* ast)
{
  if(t->frame->method_body == NULL)
  {
    ast_error(ast, "a compiler intrinsic must be a method body");
    return false;
  }

  ast_t* child = ast_child(t->frame->method_body);

  // Allow a docstring before the compiler_instrinsic.
  if(ast_id(child) == TK_STRING)
    child = ast_sibling(child);

  if((child != ast) || (ast_sibling(child) != NULL))
  {
    ast_error(ast, "a compiler intrinsic must be the entire body");
    return false;
  }

  // Disable debuglocs on calls to this method.
  ast_setdebug(t->frame->method, false);

  ast_settype(ast, ast_from(ast, TK_COMPILER_INTRINSIC));
  return true;
}
Esempio n. 14
0
static bool method_call(pass_opt_t* opt, ast_t* ast)
{
  if(!method_application(opt, ast, false))
    return false;

  AST_GET_CHILDREN(ast, positional, namedargs, lhs);
  ast_t* type = ast_type(lhs);

  if(is_typecheck_error(type))
    return false;

  AST_GET_CHILDREN(type, cap, typeparams, params, result);
  ast_settype(ast, result);
  ast_inheritflags(ast);

  switch(ast_id(lhs))
  {
    case TK_NEWBEREF:
    case TK_BEREF:
      ast_setsend(ast);
      return true;

    case TK_NEWREF:
    case TK_FUNREF:
      ast_setmightsend(ast);
      return true;

    default: {}
  }

  assert(0);
  return false;
}
Esempio n. 15
0
ast_t* builder_add_type(builder_t* builder, const char* type_of,
  const char* description)
{
  assert(type_of != NULL);
  assert(description != NULL);

  if(builder == NULL)
    return NULL;

  ast_t* type_parent = builder_find_sub_tree(builder, type_of);

  if(type_parent == NULL)
  {
    error(NULL, 0, 0, "Node with attribute {def %s} not found", type_of);
    return NULL;
  }

  assert(ast_type(type_parent) == NULL);
  ast_t* ast = builder_add_ast(builder, description);

  if(ast == NULL)
    return NULL;

  // Success, add new type to builder
  ast_settype(type_parent, ast);
  return ast;
}
Esempio n. 16
0
bool expr_digestof(pass_opt_t* opt, ast_t* ast)
{
  ast_t* expr = ast_child(ast);

  switch(ast_id(expr))
  {
    case TK_FVARREF:
    case TK_FLETREF:
    case TK_EMBEDREF:
    case TK_VARREF:
    case TK_LETREF:
    case TK_PARAMREF:
    case TK_THIS:
      break;

    default:
      ast_error(opt->check.errors, ast,
        "can only get the digest of a field, local, parameter or this");
      return false;
  }

  // Set the type to U64.
  ast_t* type = type_builtin(opt, expr, "U64");
  ast_settype(ast, type);
  return true;
}
Esempio n. 17
0
static bool expr_addressof_ffi(pass_opt_t* opt, ast_t* ast)
{
  ast_t* expr = ast_child(ast);

  switch(ast_id(expr))
  {
    case TK_FVARREF:
    case TK_VARREF:
    case TK_FLETREF:
    case TK_LETREF:
      break;

    case TK_PARAMREF:
      ast_error(ast, "can't take the address of a function parameter");
      return false;

    default:
      ast_error(ast, "can only take the address of a field or local variable");
      return false;
  }

  // Set the type to Pointer[ast_type(expr)].
  ast_t* expr_type = ast_type(expr);

  if(is_typecheck_error(expr_type))
    return false;

  ast_t* type = type_pointer_to(opt, expr_type);
  ast_settype(ast, type);
  return true;
}
Esempio n. 18
0
bool expr_field(pass_opt_t* opt, ast_t* ast)
{
  AST_GET_CHILDREN(ast, id, type, init);

  if(ast_id(init) != TK_NONE)
  {
    // Initialiser type must match declared type.
    if(!coerce_literals(&init, type, opt))
      return false;

    ast_t* init_type = ast_type(init);

    if(is_typecheck_error(init_type))
      return false;

    init_type = alias(init_type);

    if(!is_subtype(init_type, type))
    {
      ast_error(init,
        "field/param initialiser is not a subtype of the field/param type");
      ast_error(type, "field/param type: %s", ast_print_type(type));
      ast_error(init, "initialiser type: %s", ast_print_type(init_type));
      ast_free_unattached(init_type);
      return false;
    }

    ast_free_unattached(init_type);
  }

  ast_settype(ast, type);
  return true;
}
Esempio n. 19
0
static bool check_type_params(ast_t** astp)
{
  ast_t* lhs = *astp;
  ast_t* type = ast_type(lhs);

  if(is_typecheck_error(type))
    return false;

  ast_t* typeparams = ast_childidx(type, 1);
  assert(ast_id(type) == TK_FUNTYPE);

  if(ast_id(typeparams) == TK_NONE)
    return true;

  BUILD(typeargs, typeparams, NODE(TK_TYPEARGS));

  if(!check_constraints(typeparams, typeargs, true))
  {
    ast_free_unattached(typeargs);
    return false;
  }

  type = reify(type, typeparams, typeargs);
  typeparams = ast_childidx(type, 1);
  ast_replace(&typeparams, ast_from(typeparams, TK_NONE));

  REPLACE(astp, NODE(ast_id(lhs), TREE(lhs) TREE(typeargs)));
  ast_settype(*astp, type);

  return true;
}
Esempio n. 20
0
bool expr_compile_error(ast_t* ast)
{
  // compile_error is always the last expression in a sequence
  assert(ast_sibling(ast) == NULL);

  ast_settype(ast, ast_from(ast, TK_COMPILE_ERROR));
  return true;
}
Esempio n. 21
0
bool expr_consume(pass_opt_t* opt, ast_t* ast)
{
  AST_GET_CHILDREN(ast, cap, term);
  ast_t* type = ast_type(term);

  if(is_typecheck_error(type))
    return false;

  const char* name = NULL;

  switch(ast_id(term))
  {
    case TK_VARREF:
    case TK_LETREF:
    case TK_PARAMREF:
    {
      ast_t* id = ast_child(term);
      name = ast_name(id);
      break;
    }

    case TK_THIS:
    {
      name = stringtab("this");
      break;
    }

    default:
      ast_error(opt->check.errors, ast,
        "consume must take 'this', a local, or a parameter");
      return false;
  }

  // Can't consume from an outer scope while in a loop condition.
  if((opt->check.frame->loop_cond != NULL) &&
    !ast_within_scope(opt->check.frame->loop_cond, ast, name))
  {
    ast_error(opt->check.errors, ast,
      "can't consume from an outer scope in a loop condition");
    return false;
  }

  ast_setstatus(ast, name, SYM_CONSUMED);

  token_id tcap = ast_id(cap);
  ast_t* c_type = consume_type(type, tcap);

  if(c_type == NULL)
  {
    ast_error(opt->check.errors, ast, "can't consume to this capability");
    ast_error_continue(opt->check.errors, term, "expression type is %s",
      ast_print_type(type));
    return false;
  }

  ast_settype(ast, c_type);
  return true;
}
Esempio n. 22
0
bool expr_error(pass_opt_t* opt, ast_t* ast)
{
  (void)opt;
  // error is always the last expression in a sequence
  assert(ast_sibling(ast) == NULL);

  ast_settype(ast, ast_from(ast, TK_ERROR));
  return true;
}
Esempio n. 23
0
bool expr_break(pass_opt_t* opt, ast_t* ast)
{
  typecheck_t* t = &opt->check;

  if(t->frame->loop_body == NULL)
  {
    ast_error(opt->check.errors, ast, "must be in a loop");
    return false;
  }

  errorframe_t errorf = NULL;
  if(!ast_all_consumes_in_scope(t->frame->loop_body, ast, &errorf))
  {
    errorframe_report(&errorf, opt->check.errors);
    return false;
  }

  // break is always the last expression in a sequence
  assert(ast_sibling(ast) == NULL);

  ast_settype(ast, ast_from(ast, TK_BREAK));

  // Add type to loop.
  ast_t* body = ast_child(ast);

  if(ast_id(body) != TK_NONE)
  {
    if(is_control_type(ast_type(body)))
    {
      ast_error(opt->check.errors, body,
        "break value cannot be a control statement");
      return false;
    }

    ast_t* loop_type = ast_type(t->frame->loop);

    // If there is no body the break will jump to the else branch, whose type
    // has already been added to the loop type.
    loop_type = control_type_add_branch(opt, loop_type, body);
    ast_settype(t->frame->loop, loop_type);
  }

  return true;
}
Esempio n. 24
0
bool expr_repeat(pass_opt_t* opt, ast_t* ast)
{
  AST_GET_CHILDREN(ast, body, cond, else_clause);

  ast_t* body_type = ast_type(body);
  ast_t* cond_type = ast_type(cond);
  ast_t* else_type = ast_type(else_clause);

  if(is_typecheck_error(cond_type))
    return false;

  if(!is_bool(cond_type))
  {
    ast_error(opt->check.errors, cond, "condition must be a Bool");
    return false;
  }

  if(is_typecheck_error(body_type) || is_typecheck_error(else_type))
    return false;

  // All consumes have to be in scope when the loop body finishes.
  errorframe_t errorf = NULL;
  if(!ast_all_consumes_in_scope(body, body, &errorf))
  {
    errorframe_report(&errorf, opt->check.errors);
    return false;
  }

  // Union with any existing type due to a break expression.
  ast_t* type = ast_type(ast);

  // No symbol status is inherited from the loop body or condition. Nothing
  // from outside can be consumed, and definitions inside may not occur.
  if(!is_control_type(body_type))
    type = control_type_add_branch(opt, type, body);

  if(!is_control_type(else_type))
  {
    type = control_type_add_branch(opt, type, else_clause);
    ast_inheritbranch(ast, else_clause);

    // Use a branch count of two instead of one. This means we will pick up any
    // consumes, but not any definitions, since definitions may not occur.
    ast_consolidate_branches(ast, 2);
  }

  if(type == NULL)
    type = ast_from(ast, TK_REPEAT);

  ast_settype(ast, type);
  literal_unify_control(ast, opt);

  // Push our symbol status to our parent scope.
  ast_inheritstatus(ast_parent(ast), ast);
  return true;
}
Esempio n. 25
0
File: control.c Progetto: ozra/ponyc
bool expr_if(pass_opt_t* opt, ast_t* ast)
{
    ast_t* cond = ast_child(ast);
    ast_t* left = ast_sibling(cond);
    ast_t* right = ast_sibling(left);
    ast_t* cond_type = ast_type(cond);

    if(is_typecheck_error(cond_type))
        return false;

    if(!is_bool(cond_type))
    {
        ast_error(cond, "condition must be a Bool");
        return false;
    }

    ast_t* l_type = ast_type(left);
    ast_t* r_type = ast_type(right);

    ast_t* type = NULL;
    size_t branch_count = 0;

    if(!is_control_type(l_type))
    {
        type = control_type_add_branch(type, left);
        ast_inheritbranch(ast, left);
        branch_count++;
    }

    if(!is_control_type(r_type))
    {
        type = control_type_add_branch(type, right);
        ast_inheritbranch(ast, right);
        branch_count++;
    }

    if(type == NULL)
    {
        if(ast_sibling(ast) != NULL)
        {
            ast_error(ast_sibling(ast), "unreachable code");
            return false;
        }

        type = ast_from(ast, TK_IF);
    }

    ast_settype(ast, type);
    ast_inheritflags(ast);
    ast_consolidate_branches(ast, branch_count);
    literal_unify_control(ast, opt);

    // Push our symbol status to our parent scope.
    ast_inheritstatus(ast_parent(ast), ast);
    return true;
}
Esempio n. 26
0
bool expr_literal(pass_opt_t* opt, ast_t* ast, const char* name)
{
  ast_t* type = type_builtin(opt, ast, name);

  if(is_typecheck_error(type))
    return false;

  ast_settype(ast, type);
  return true;
}
Esempio n. 27
0
bool expr_try(pass_opt_t* opt, ast_t* ast)
{
  AST_GET_CHILDREN(ast, body, else_clause, then_clause);

  ast_t* body_type = ast_type(body);
  ast_t* else_type = ast_type(else_clause);
  ast_t* then_type = ast_type(then_clause);

  if(is_typecheck_error(body_type) ||
    is_typecheck_error(else_type) ||
    is_typecheck_error(then_type))
    return false;

  ast_t* type = NULL;

  if(!is_control_type(body_type))
    type = control_type_add_branch(opt, type, body);

  if(!is_control_type(else_type))
    type = control_type_add_branch(opt, type, else_clause);

  if(type == NULL)
  {
    if(ast_sibling(ast) != NULL)
    {
      ast_error(opt->check.errors, ast_sibling(ast), "unreachable code");
      return false;
    }

    type = ast_from(ast, TK_TRY);
  }

  // The then clause does not affect the type of the expression.
  if(is_control_type(then_type))
  {
    ast_error(opt->check.errors, then_clause,
      "then clause always terminates the function");
    return false;
  }

  if(is_type_literal(then_type))
  {
    ast_error(opt->check.errors, then_clause,
      "Cannot infer type of unused literal");
    return false;
  }

  ast_settype(ast, type);

  literal_unify_control(ast, opt);

  // Push the symbol status from the then clause to our parent scope.
  ast_inheritstatus(ast_parent(ast), then_clause);
  return true;
}
Esempio n. 28
0
bool expr_field(pass_opt_t* opt, ast_t* ast)
{
  AST_GET_CHILDREN(ast, id, type, init);

  // An embedded field must have a known, non-actor type.
  if(ast_id(ast) == TK_EMBED)
  {
    if(!is_known(type) || is_actor(type))
    {
      ast_error(ast, "embedded fields must always be primitives or classes");
      return false;
    }
  }

  if(ast_id(init) != TK_NONE)
  {
    // Initialiser type must match declared type.
    if(!coerce_literals(&init, type, opt))
      return false;

    ast_t* init_type = ast_type(init);

    if(is_typecheck_error(init_type))
      return false;

    init_type = alias(init_type);

    if(!is_subtype(init_type, type))
    {
      ast_error(init,
        "field/param initialiser is not a subtype of the field/param type");
      ast_error(type, "field/param type: %s", ast_print_type(type));
      ast_error(init, "initialiser type: %s", ast_print_type(init_type));
      ast_free_unattached(init_type);
      return false;
    }

    // If it's an embedded field, check for a constructor result.
    if(ast_id(ast) == TK_EMBED)
    {
      if((ast_id(init) != TK_CALL) ||
        (ast_id(ast_childidx(init, 2)) != TK_NEWREF))
      {
        ast_error(ast,
          "an embedded field must be initialised using a constructor");
        return false;
      }
    }

    ast_free_unattached(init_type);
  }

  ast_settype(ast, type);
  return true;
}
Esempio n. 29
0
static bool method_chain(pass_opt_t* opt, ast_t* ast)
{
  if(!method_application(opt, ast, false))
    return false;

  AST_GET_CHILDREN(ast, positional, namedargs, question, lhs);

  ast_t* type = ast_type(lhs);
  if(ast_id(ast_child(type)) == TK_AT)
  {
    ast_error(opt->check.errors, ast, "a bare method cannot be chained");
    return false;
  }

  // We check the receiver cap now instead of in method_application because
  // we need to know whether the receiver was recovered.
  ast_t* r_type = method_receiver_type(lhs);
  if(ast_id(lhs) == TK_FUNCHAIN)
  {
    bool recovered;
    if(!check_receiver_cap(opt, ast, &recovered))
      return false;

    if(!check_nonsendable_recover(opt, ast))
      return false;

    ast_t* f_type = ast_type(lhs);
    token_id f_cap = ast_id(ast_child(f_type));

    ast_t* c_type = chain_type(r_type, f_cap, recovered);
    ast_settype(ast, c_type);
  } else {
    ast_settype(ast, r_type);
  }

  return true;
}
Esempio n. 30
0
bool expr_local(typecheck_t* t, ast_t* ast)
{
  assert(t != NULL);
  assert(ast != NULL);

  AST_GET_CHILDREN(ast, id, type);
  assert(type != NULL);

  if(ast_id(type) == TK_NONE)
  {
    // No type specified, check we can infer
    if(!is_assigned_to(ast, false))
    {
      if(t->frame->pattern != NULL)
        ast_error(ast, "cannot infer type of capture variables");
      else
        ast_error(ast, "locals must specify a type or be assigned a value");

      return false;
    }

    type = ast_from(id, TK_INFERTYPE);
  }
  else if(ast_id(ast) == TK_LET && t->frame->pattern == NULL)
  {
    // Let, check we have a value assigned
    if(!is_assigned_to(ast, false))
    {
      ast_error(ast, "can't declare a let local without assigning to it");
      return false;
    }
  }

  ast_settype(id, type);
  ast_settype(ast, type);
  return true;
}