コード例 #1
0
ファイル: control.c プロジェクト: cyisfor/ponyc
bool expr_while(pass_opt_t* opt, ast_t* ast)
{
  AST_GET_CHILDREN(ast, cond, body, else_clause);

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

  if(is_typecheck_error(cond_type))
    return false;

  if(!is_bool(cond_type))
  {
    ast_error(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.
  if(!ast_all_consumes_in_scope(body, body))
    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. Nothing from outside the
  // loop body can be consumed, and definitions in the body may not occur.
  if(!is_control_type(body_type))
    type = control_type_add_branch(type, body);

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

    // 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_WHILE);

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

  // Push our symbol status to our parent scope.
  ast_inheritstatus(ast_parent(ast), ast);
  return true;
}
コード例 #2
0
ファイル: postfix.c プロジェクト: fydot/ponyc
static bool member_access(typecheck_t* t, ast_t* ast, bool partial)
{
  // Left is a postfix expression, right is an id.
  AST_GET_CHILDREN(ast, left, right);
  assert(ast_id(right) == TK_ID);
  ast_t* type = ast_type(left);

  if(is_typecheck_error(type))
    return false;

  ast_t* find = lookup(t, ast, type, ast_name(right));

  if(find == NULL)
    return false;

  bool ret = true;

  switch(ast_id(find))
  {
    case TK_TYPEPARAM:
      ast_error(right, "can't look up a typeparam on an expression");
      ret = false;
      break;

    case TK_FVAR:
      if(!expr_fieldref(t, ast, find, TK_FVARREF))
        return false;
      break;

    case TK_FLET:
      if(!expr_fieldref(t, ast, find, TK_FLETREF))
        return false;
      break;

    case TK_NEW:
    case TK_BE:
    case TK_FUN:
      ret = method_access(ast, find);
      break;

    default:
      assert(0);
      ret = false;
      break;
  }

  ast_free_unattached(find);

  if(!partial)
    ast_inheritflags(ast);

  return ret;
}
コード例 #3
0
ファイル: traits.c プロジェクト: jonas-l/ponyc
// Process the method provided to the given entity.
// Stage 2.
static bool provided_methods(ast_t* entity)
{
  assert(entity != NULL);

  ast_t* provides = ast_childidx(entity, 3);
  ast_t* entity_members = ast_childidx(entity, 4);
  ast_t* last_member = ast_childlast(entity_members);
  bool r = true;

  // Run through our provides list
  for(ast_t* p = ast_child(provides); p != NULL; p = ast_sibling(p))
  {
    ast_t* trait_def = (ast_t*)ast_data(p);
    assert(trait_def != NULL);

    ast_t* type_args = ast_childidx(p, 2);
    ast_t* type_params = ast_childidx(trait_def, 1);
    ast_t* members = ast_childidx(trait_def, 4);

    // Run through the methods of each provided type
    for(ast_t* m = ast_child(members); m != NULL; m = ast_sibling(m))
    {
      // Check behaviour compatability
      if(ast_id(m) == TK_BE)
      {
        if(ast_id(entity) == TK_PRIMITIVE || ast_id(entity) == TK_CLASS)
        {
          ast_error(entity, "%s can't provide traits that have behaviours",
            (ast_id(entity) == TK_CLASS) ? "classes" : "primitives");

          r = false;
          continue;
        }
      }

      if(is_method(m))
      {
        // We have a provided method
        // Reify the method with the type parameters from trait definition and type
        // arguments from trait reference
        ast_t* reified = reify(type_args, m, type_params, type_args);

        if(reified == NULL) // Reification error, already reported
          return false;

        if(!provided_method(entity, reified, m, &last_member))
          r = false;
      }
    }
  }

  return r;
}
コード例 #4
0
ファイル: syntax.c プロジェクト: andymcn/ponyc
static ast_result_t syntax_thistype(typecheck_t* t, ast_t* ast)
{
  assert(ast != NULL);
  ast_t* parent = ast_parent(ast);
  assert(parent != NULL);
  ast_result_t r = AST_OK;

  if(ast_id(parent) != TK_ARROW)
  {
    ast_error(ast, "in a type, 'this' can only be used as a viewpoint");
    r = AST_ERROR;
  }

  if(t->frame->method == NULL)
  {
    ast_error(ast, "can only use 'this' for a viewpoint in a method");
    r = AST_ERROR;
  }

  return r;
}
コード例 #5
0
ファイル: reference.c プロジェクト: Preetam/ponyc
static bool check_fields_defined(ast_t* ast)
{
  assert(ast_id(ast) == TK_NEW);

  ast_t* members = ast_parent(ast);
  ast_t* member = ast_child(members);
  bool result = true;

  while(member != NULL)
  {
    switch(ast_id(member))
    {
      case TK_FVAR:
      case TK_FLET:
      case TK_EMBED:
      {
        sym_status_t status;
        ast_t* id = ast_child(member);
        ast_t* def = ast_get(ast, ast_name(id), &status);

        if((def != member) || (status != SYM_DEFINED))
        {
          ast_error(def, "field left undefined in constructor");
          result = false;
        }

        break;
      }

      default: {}
    }

    member = ast_sibling(member);
  }

  if(!result)
    ast_error(ast, "constructor with undefined fields is here");

  return result;
}
コード例 #6
0
ファイル: reference.c プロジェクト: tmmcguire/ponyc
static bool check_finaliser(pass_opt_t* opt, ast_t* ast)
{
  AST_GET_CHILDREN(ast, cap, id, typeparams, params, result, can_error, body);

  if(strcmp(ast_name(id), "_final"))
    return true;

  bool ok = true;

  if((ast_id(opt->check.frame->type) == TK_PRIMITIVE) &&
    (ast_id(ast_childidx(opt->check.frame->type, 1)) != TK_NONE))
  {
    ast_error(opt->check.errors, ast,
      "a primitive with type parameters cannot have a _final");
    ok = false;
  }

  if(ast_id(ast) != TK_FUN)
  {
    ast_error(opt->check.errors, ast, "_final must be a function");
    ok = false;
  }

  if(ast_id(cap) != TK_BOX)
  {
    ast_error(opt->check.errors, cap, "_final must be box");
    ok = false;
  }

  if(ast_id(typeparams) != TK_NONE)
  {
    ast_error(opt->check.errors, typeparams, "_final must not be polymorphic");
    ok = false;
  }

  if(ast_childcount(params) != 0)
  {
    ast_error(opt->check.errors, params, "_final must not have parameters");
    ok = false;
  }

  if(!is_none(result))
  {
    ast_error(opt->check.errors, result, "_final must return None");
    ok = false;
  }

  if(ast_id(can_error) != TK_NONE)
  {
    ast_error(opt->check.errors, can_error, "_final cannot raise an error");
    ok = false;
  }

  return ok;
}
コード例 #7
0
ファイル: traits.c プロジェクト: lzpfmh/ponyc
// Resolve the default body to use for the given method, if any.
// Return the body to use, NULL if none found or BODY_ERROR on error.
static ast_t* resolve_default_body(ast_t* entity, ast_t* method,
  method_t* info, const char* name, bool concrete)
{
  assert(entity != NULL);
  assert(method != NULL);
  assert(info != NULL);
  assert(name != NULL);

  if(info->default_body_src_2 != NULL)
  {
    // Ambiguous body, store info for use by any types that provide this one
    assert(info->default_body_src_1 != NULL);

    ast_t* err = ast_childidx(method, 5);
    ast_t* body = ast_childidx(method, 6);

    // Ditch whatever body we have, if any
    ast_erase(body);

    ast_setdata(body, info->default_body_src_1);
    ast_setdata(err, info->default_body_src_2);

    if(!concrete)
      return NULL;

    ast_error(entity, "multiple possible bodies for method %s, local "
      "disambiguation required", name);
    ast_error(info->default_body_src_1, "one possible body here");
    ast_error(info->default_body_src_2, "another possible body here");
    return BODY_ERROR;
  }

  if(info->default_body_src_1 == NULL)  // No default body found
    return NULL;

  // We have a default body, use it
  assert(info->reified_default != NULL);
  info->body_donor = (ast_t*)ast_data(info->default_body_src_1);
  return ast_childidx(info->reified_default, 6);
}
コード例 #8
0
ファイル: call.c プロジェクト: Perelandric/ponyc
static bool check_nonsendable_recover(pass_opt_t* opt, ast_t* ast)
{
  if(opt->check.frame->recover != NULL)
  {
    AST_GET_CHILDREN(ast, positional, namedargs, question, lhs);

    ast_t* type = ast_type(lhs);

    AST_GET_CHILDREN(type, cap, typeparams, params, result);

    // If the method is tag, the call is always safe.
    if(ast_id(cap) == TK_TAG)
      return true;

    ast_t* receiver = ast_child(lhs);

    // Dig through function qualification.
    if((ast_id(receiver) == TK_FUNREF) || (ast_id(receiver) == TK_FUNAPP) ||
       (ast_id(receiver) == TK_FUNCHAIN))
      receiver = ast_child(receiver);

    if(!is_receiver_safe(&opt->check, receiver))
    {
      ast_t* arg = ast_child(positional);
      bool args_sendable = true;
      while(arg != NULL)
      {
        if(ast_id(arg) != TK_NONE)
        {
          // Don't typecheck arg_type, this was already done in
          // auto_recover_call.
          ast_t* arg_type = ast_type(arg);
          if(!sendable(arg_type))
          {
            args_sendable = false;
            break;
          }
        }
        arg = ast_sibling(arg);
      }
      if(!args_sendable || !sendable(result))
      {
        ast_error(opt->check.errors, ast, "can't call method on non-sendable "
          "object inside of a recover expression");
        ast_error_continue(opt->check.errors, ast, "this would be possible if "
          "the arguments and return value were all sendable");
        return false;
      }
    }
  }
  return true;
}
コード例 #9
0
ファイル: syntax.c プロジェクト: federicosan/ponyc
static ast_result_t syntax_compile_intrinsic(pass_opt_t* opt, ast_t* ast)
{
  ast_t* parent = ast_parent(ast);
  assert(ast_id(parent) == TK_SEQ);

  ast_t* method = ast_parent(parent);

  switch(ast_id(method))
  {
    case TK_NEW:
    case TK_BE:
    case TK_FUN:
      // OK
      break;

    default:
      ast_error(opt->check.errors, ast,
        "a compile intrinsic must be a method body");
      return AST_ERROR;
  }

  ast_t* child = ast_child(parent);

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

  // Compile intrinsic has a value child, but it must be empty
  ast_t* value = ast_child(ast);

  if(child != ast || ast_sibling(child) != NULL || ast_id(value) != TK_NONE)
  {
    ast_error(opt->check.errors, ast,
      "a compile intrinsic must be the entire body");
    return AST_ERROR;
  }

  return AST_OK;
}
コード例 #10
0
ファイル: syntax.c プロジェクト: Preetam/ponyc
static ast_result_t syntax_ellipsis(ast_t* ast)
{
  assert(ast != NULL);
  ast_result_t r = AST_OK;

  ast_t* fn = ast_parent(ast_parent(ast));
  assert(fn != NULL);

  if(ast_id(fn) != TK_FFIDECL)
  {
    ast_error(ast, "... may only appear in FFI declarations");
    r = AST_ERROR;
  }

  if(ast_sibling(ast) != NULL)
  {
    ast_error(ast, "... must be the last parameter");
    r = AST_ERROR;
  }

  return r;
}
コード例 #11
0
ファイル: assemble.c プロジェクト: jonas-l/ponyc
ast_t* type_builtin(pass_opt_t* opt, ast_t* from, const char* name)
{
  ast_t* ast = type_base(from, NULL, name);

  if(!names_nominal(opt, from, &ast, false))
  {
    ast_error(from, "unable to validate '%s'", name);
    ast_free(ast);
    return NULL;
  }

  return ast;
}
コード例 #12
0
ファイル: syntax.c プロジェクト: federicosan/ponyc
static ast_result_t syntax_lambda_capture(pass_opt_t* opt, ast_t* ast)
{
  AST_GET_CHILDREN(ast, name, type, value);

  if(ast_id(type) != TK_NONE && ast_id(value) == TK_NONE)
  {
    ast_error(opt->check.errors, ast, "value missing for lambda expression "
      "capture (cannot specify type without value)");
    return AST_ERROR;
  }

  return AST_OK;
}
コード例 #13
0
ファイル: reference.c プロジェクト: Potpourri/ponyc
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);
  assert(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;
}
コード例 #14
0
ファイル: syntax.c プロジェクト: Preetam/ponyc
static ast_result_t syntax_ffi(ast_t* ast, bool return_optional)
{
  assert(ast != NULL);
  AST_GET_CHILDREN(ast, id, typeargs, args, named_args);
  ast_result_t r = AST_OK;

  // We don't check FFI names are legal, if the lexer allows it so do we

  if((ast_child(typeargs) == NULL && !return_optional) ||
    ast_childidx(typeargs, 1) != NULL)
  {
    ast_error(typeargs, "FFIs must specify a single return type");
    r = AST_ERROR;
  }

  for(ast_t* p = ast_child(args); p != NULL; p = ast_sibling(p))
  {
    if(ast_id(p) == TK_PARAM)
    {
      ast_t* def_val = ast_childidx(p, 2);
      assert(def_val != NULL);

      if(ast_id(def_val) != TK_NONE)
      {
        ast_error(def_val, "FFIs parameters cannot have default values");
        r = AST_ERROR;
      }
    }
  }

  if(ast_id(named_args) != TK_NONE)
  {
    ast_error(typeargs, "FFIs cannot take named arguments");
    r = AST_ERROR;
  }

  return r;
}
コード例 #15
0
ファイル: flatten.c プロジェクト: aturley/ponyc
ast_result_t flatten_typeparamref(pass_opt_t* opt, ast_t* ast)
{
  ast_t* cap_ast = cap_fetch(ast);
  token_id cap = ast_id(cap_ast);

  typeparam_set_cap(ast);

  token_id set_cap = ast_id(cap_ast);

  if((cap != TK_NONE) && (cap != set_cap))
  {
    ast_t* def = (ast_t*)ast_data(ast);
    ast_t* constraint = typeparam_constraint(ast);

    if(constraint != NULL)
    {
      ast_error(opt->check.errors, cap_ast, "can't specify a capability on a "
        "type parameter that differs from the constraint");
      ast_error_continue(opt->check.errors, constraint,
        "constraint definition is here");

      if(ast_parent(constraint) != def)
      {
        ast_error_continue(opt->check.errors, def,
          "type parameter definition is here");
      }
    } else {
      ast_error(opt->check.errors, cap_ast, "a type parameter with no "
        "constraint can only have #any as its capability");
      ast_error_continue(opt->check.errors, def,
        "type parameter definition is here");
    }

    return AST_ERROR;
  }

  return AST_OK;
}
コード例 #16
0
ファイル: gencall.c プロジェクト: cyisfor/ponyc
static LLVMValueRef dispatch_function(compile_t* c, ast_t* from, gentype_t* g,
  LLVMValueRef l_value, const char* method_name, ast_t* typeargs)
{
  LLVMValueRef func;

  if(g->use_type == c->object_ptr)
  {
    // Virtual, get the function by selector colour.
    uint32_t index = genfun_vtable_index(c, g, method_name, typeargs);
    assert(index != (uint32_t)-1);

    // Get the function from the vtable.
    func = gendesc_vtable(c, l_value, index);

    // Cast to the right function type.
    LLVMTypeRef f_type = genfun_sig(c, g, method_name, typeargs);

    if(f_type == NULL)
    {
      ast_error(from, "couldn't create a signature for '%s'", method_name);
      return NULL;
    }

    f_type = LLVMPointerType(f_type, 0);
    func = LLVMBuildBitCast(c->builder, func, f_type, "method");
  } else {
    // Static, get the actual function.
    func = genfun_proto(c, g, method_name, typeargs);

    if(func == NULL)
    {
      ast_error(from, "couldn't locate '%s'", method_name);
      return NULL;
    }
  }

  return func;
}
コード例 #17
0
ファイル: ffi.c プロジェクト: Sendence/ponyc
bool expr_ffi(pass_opt_t* opt, ast_t* ast)
{
  AST_GET_CHILDREN(ast, name, return_typeargs, args, namedargs, question);
  assert(name != NULL);

  ast_t* decl;
  if(!ffi_get_decl(&opt->check, ast, &decl, opt))
    return false;

  if(decl != NULL)  // We have a declaration
    return declared_ffi(opt, ast, decl);

  // We do not have a declaration
  for(ast_t* arg = ast_child(args); arg != NULL; arg = ast_sibling(arg))
  {
    ast_t* a_type = ast_type(arg);

    if((a_type != NULL) && is_type_literal(a_type))
    {
      ast_error(opt->check.errors, arg,
        "Cannot pass number literals as unchecked FFI arguments");
      return false;
    }
  }

  ast_t* return_type = ast_child(return_typeargs);

  if(return_type == NULL)
  {
    ast_error(opt->check.errors, name,
      "FFIs without declarations must specify return type");
    return false;
  }

  ast_settype(ast, return_type);

  return true;
}
コード例 #18
0
ファイル: postfix.c プロジェクト: JamesLinus/ponyc
static bool package_access(pass_opt_t* opt, ast_t** astp)
{
  ast_t* ast = *astp;

  // Left is a packageref, right is an id.
  ast_t* left = ast_child(ast);
  ast_t* right = ast_sibling(left);

  assert(ast_id(left) == TK_PACKAGEREF);
  assert(ast_id(right) == TK_ID);

  // Must be a type in a package.
  const char* package_name = ast_name(ast_child(left));
  ast_t* package = ast_get(left, package_name, NULL);

  if(package == NULL)
  {
    ast_error(opt->check.errors, right, "can't access package '%s'",
      package_name);
    return false;
  }

  assert(ast_id(package) == TK_PACKAGE);
  const char* type_name = ast_name(right);
  ast_t* type = ast_get(package, type_name, NULL);

  if(type == NULL)
  {
    ast_error(opt->check.errors, right, "can't find type '%s' in package '%s'",
      type_name, package_name);
    return false;
  }

  ast_settype(ast, type_sugar(ast, package_name, type_name));
  ast_setid(ast, TK_TYPEREF);

  return expr_typeref(opt, astp);
}
コード例 #19
0
ファイル: names.c プロジェクト: dailypips/ponyc
static bool names_applycap(ast_t* ast, ast_t* cap, ast_t* ephemeral)
{
  switch(ast_id(ast))
  {
    case TK_UNIONTYPE:
    case TK_ISECTTYPE:
    case TK_TUPLETYPE:
    {
      if(ast_id(cap) != TK_NONE)
      {
        ast_error(cap,
          "can't specify a capability for an alias to a type expression");
        return false;
      }

      if(ast_id(ephemeral) != TK_NONE)
      {
        ast_error(ephemeral,
          "can't specify ephemerality for an alias to a type expression");
        return false;
      }

      return true;
    }

    case TK_NOMINAL:
      names_applycap_index(ast, cap, ephemeral, 3);
      return true;

    case TK_ARROW:
      return names_applycap(ast_childidx(ast, 1), cap, ephemeral);

    default: {}
  }

  assert(0);
  return false;
}
コード例 #20
0
ファイル: gencall.c プロジェクト: killerswan/ponyc
static LLVMValueRef special_case_platform(compile_t* c, ast_t* ast)
{
  AST_GET_CHILDREN(ast, positional, named, postfix);
  AST_GET_CHILDREN(postfix, receiver, method);

  const char* method_name = ast_name(method);
  bool is_target;

  if(os_is_target(method_name, c->opt->release, &is_target, c->opt))
    return LLVMConstInt(c->ibool, is_target ? 1 : 0, false);

  ast_error(c->opt->check.errors, ast, "unknown Platform setting");
  return NULL;
}
コード例 #21
0
ファイル: syntax.c プロジェクト: federicosan/ponyc
static ast_result_t syntax_semi(pass_opt_t* opt, ast_t* ast)
{
  assert(ast_parent(ast) != NULL);
  assert(ast_id(ast_parent(ast)) == TK_SEQ);

  if(ast_checkflag(ast, AST_FLAG_BAD_SEMI))
  {
    ast_error(opt->check.errors, ast, "Unexpected semicolon, only use to "
      "separate expressions on the same line");
    return AST_ERROR;
  }

  return AST_OK;
}
コード例 #22
0
ファイル: reference.c プロジェクト: Potpourri/ponyc
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;
}
コード例 #23
0
ファイル: reference.c プロジェクト: pap/ponyc
static bool check_return_type(ast_t* ast)
{
  assert(ast_id(ast) == TK_FUN);
  AST_GET_CHILDREN(ast, cap, id, typeparams, params, type, can_error, body);
  ast_t* body_type = ast_type(body);

  if(is_typecheck_error(body_type))
    return false;

  // The last statement is an error, and we've already checked any return
  // expressions in the method.
  if(is_control_type(body_type))
    return true;

  // If it's a compiler intrinsic, ignore it.
  if(ast_id(body_type) == TK_COMPILER_INTRINSIC)
    return true;

  // The body type must match the return type, without subsumption, or an alias
  // of the body type must be a subtype of the return type.
  ast_t* a_type = alias(type);
  ast_t* a_body_type = alias(body_type);
  bool ok = true;

  if(!is_subtype(body_type, type) || !is_subtype(a_body_type, a_type))
  {
    ast_t* last = ast_childlast(body);
    ast_error(last, "function body isn't the result type");
    ast_error(type, "function return type: %s", ast_print_type(type));
    ast_error(body_type, "function body type: %s", ast_print_type(body_type));
    ok = false;
  }

  ast_free_unattached(a_type);
  ast_free_unattached(a_body_type);
  return ok;
}
コード例 #24
0
ファイル: syntax.c プロジェクト: federicosan/ponyc
static ast_result_t syntax_thistype(pass_opt_t* opt, ast_t* ast)
{
  assert(ast != NULL);
  ast_t* parent = ast_parent(ast);
  assert(parent != NULL);
  ast_result_t r = AST_OK;

  if(ast_id(parent) != TK_ARROW)
  {
    ast_error(opt->check.errors, ast,
      "in a type, 'this' can only be used as a viewpoint");
    r = AST_ERROR;
  }

  if(opt->check.frame->method == NULL)
  {
    ast_error(opt->check.errors, ast,
      "can only use 'this' for a viewpoint in a method");
    r = AST_ERROR;
  } else {
    ast_t* cap = ast_child(opt->check.frame->method);

    switch(ast_id(cap))
    {
      case TK_BOX:
      case TK_NONE:
        break;

      default:
        ast_error(opt->check.errors, ast,
          "can only use 'this' for a viewpoint in a box function");
        r = AST_ERROR;
    }
  }

  return r;
}
コード例 #25
0
ファイル: match.c プロジェクト: mgist/ponyc
// Infer the types of any literals in the pattern of the given case
static bool infer_pattern_type(ast_t* pattern, ast_t* match_expr_type,
  pass_opt_t* opt)
{
  assert(pattern != NULL);
  assert(match_expr_type != NULL);

  if(is_type_literal(match_expr_type))
  {
    ast_error(match_expr_type,
      "cannot infer type for literal match expression");
    return false;
  }

  return coerce_literals(&pattern, match_expr_type, opt);
}
コード例 #26
0
ファイル: reference.c プロジェクト: tmmcguire/ponyc
/**
 * Make sure the definition of something occurs before its use. This is for
 * both fields and local variable.
 */
bool def_before_use(pass_opt_t* opt, ast_t* def, ast_t* use, const char* name)
{
  if((ast_line(def) > ast_line(use)) ||
     ((ast_line(def) == ast_line(use)) &&
      (ast_pos(def) > ast_pos(use))))
  {
    ast_error(opt->check.errors, use,
      "declaration of '%s' appears after use", name);
    ast_error_continue(opt->check.errors, def,
      "declaration of '%s' appears here", name);
    return false;
  }

  return true;
}
コード例 #27
0
ファイル: sugar.c プロジェクト: shepheb/ponyc
static ast_result_t sugar_module(ast_t* ast)
{
  ast_t* docstring = ast_child(ast);

  ast_t* package = ast_parent(ast);
  assert(ast_id(package) == TK_PACKAGE);

  if(strcmp(package_name(package), "$0") != 0)
  {
    // Every module not in builtin has an implicit use builtin command.
    // Since builtin is always the first package processed it is $0.
    BUILD(builtin, ast,
      NODE(TK_USE,
      NONE
      STRING(stringtab("builtin"))
      NONE));

    ast_add(ast, builtin);
  }

  if((docstring == NULL) || (ast_id(docstring) != TK_STRING))
    return AST_OK;

  ast_t* package_docstring = ast_childlast(package);

  if(ast_id(package_docstring) == TK_STRING)
  {
    ast_error(docstring, "the package already has a docstring");
    ast_error(package_docstring, "the existing docstring is here");
    return AST_ERROR;
  }

  ast_append(package, docstring);
  ast_remove(docstring);
  return AST_OK;
}
コード例 #28
0
ファイル: traits.c プロジェクト: abingham/ponyc
// Check that all the methods in the given list are compatible with the given
// method
static bool methods_compatible(ast_t* list, ast_t* method, const char* name,
  ast_t* entity)
{
  assert(list != NULL);
  assert(method != NULL);
  assert(name != NULL);
  assert(entity != NULL);

  bool r = true;

  for(ast_t* p = ast_child(list); p != NULL; p = ast_sibling(p))
  {
    if(!is_subtype(method, p))
    {
      ast_error(method,
        "Clashing type for method %s provided by trait to %s %s",
        name, ast_get_print(entity), ast_name(ast_child(entity)));
      ast_error(p, "clashing method here");
      r = false;
    }
  }

  return r;
}
コード例 #29
0
ファイル: control.c プロジェクト: ozra/ponyc
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;

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

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

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

    // Push our symbol status to our parent scope.
    ast_inheritstatus(ast_parent(ast), ast);
    return true;
}
コード例 #30
0
ファイル: flatten.c プロジェクト: Potpourri/ponyc
static ast_result_t flatten_noconstraint(typecheck_t* t, ast_t* ast)
{
  if(t->frame->constraint != NULL)
  {
    switch(ast_id(ast))
    {
      case TK_TUPLETYPE:
        ast_error(ast, "tuple types can't be used as constraints");
        return AST_ERROR;

      case TK_ARROW:
        if(t->frame->method == NULL)
        {
          ast_error(ast, "arrow types can't be used as type constraints");
          return AST_ERROR;
        }
        break;

      default: {}
    }
  }

  return AST_OK;
}