예제 #1
0
파일: subtype.c 프로젝트: jersey99/ponyc
static bool push_assume(ast_t* sub, ast_t* super)
{
  // Returns true if we have already assumed sub is a subtype of super.
  if(subtype_assume != NULL)
  {
    ast_t* assumption = ast_child(subtype_assume);

    while(assumption != NULL)
    {
      AST_GET_CHILDREN(assumption, assume_sub, assume_super);

      if(exact_nominal(sub, assume_sub) &&
        exact_nominal(super, assume_super))
        return true;

      assumption = ast_sibling(assumption);
    }
  } else {
    subtype_assume = ast_from(sub, TK_NONE);
  }

  BUILD(assume, sub, NODE(TK_NONE, TREE(ast_dup(sub)) TREE(ast_dup(super))));
  ast_add(subtype_assume, assume);
  return false;
}
예제 #2
0
파일: sugar.c 프로젝트: shepheb/ponyc
static ast_result_t sugar_update(ast_t** astp)
{
  ast_t* ast = *astp;
  assert(ast_id(ast) == TK_ASSIGN);

  AST_GET_CHILDREN(ast, value, call);

  if(ast_id(call) != TK_CALL)
    return AST_OK;

  // We are of the form:  x(y) = z
  // Replace us with:     x.update(y where value = z)
  AST_EXTRACT_CHILDREN(call, positional, named, expr);

  // If there are no named arguments yet, named will be a TK_NONE.
  ast_setid(named, TK_NAMEDARGS);

  // Build a new namedarg.
  BUILD_NO_DEBUG(namedarg, ast,
    NODE(TK_UPDATEARG,
      ID("value")
      NODE(TK_SEQ, TREE(value))));

  // Append the named arg to our existing list.
  ast_append(named, namedarg);

  // Replace with the update call.
  REPLACE(astp,
    NODE(TK_CALL,
      TREE(positional)
      TREE(named)
      NODE(TK_DOT, TREE(expr) ID("update"))));

  return AST_OK;
}
예제 #3
0
파일: lambda.c 프로젝트: Perelandric/ponyc
static void add_field_to_object(pass_opt_t* opt, ast_t* field,
  ast_t* class_members, ast_t* create_params, ast_t* create_body,
  ast_t* call_args)
{
  AST_GET_CHILDREN(field, id, type, init);
  ast_t* p_id = ast_from_string(id, package_hygienic_id(&opt->check));

  // The param is: $0: type
  BUILD(param, field,
    NODE(TK_PARAM,
      TREE(p_id)
      TREE(type)
      NONE));

  // The arg is: $seq init
  BUILD(arg, init,
    NODE(TK_SEQ,
      TREE(init)));

  // The body of create contains: id = consume $0
  BUILD(assign, init,
    NODE(TK_ASSIGN,
      NODE(TK_CONSUME, NODE(TK_NONE) NODE(TK_REFERENCE, TREE(p_id)))
      NODE(TK_REFERENCE, TREE(id))));

  // Remove the initialiser from the field
  ast_replace(&init, ast_from(init, TK_NONE));

  ast_add(class_members, field);
  ast_append(create_params, param);
  ast_append(create_body, assign);
  ast_append(call_args, arg);
}
예제 #4
0
파일: sugar.c 프로젝트: shepheb/ponyc
static ast_result_t sugar_binop(ast_t** astp, const char* fn_name)
{
  AST_GET_CHILDREN(*astp, left, right);

  ast_t* positional = ast_from(right, TK_POSITIONALARGS);

  if(ast_id(right) == TK_TUPLE)
  {
    ast_t* value = ast_child(right);

    while(value != NULL)
    {
      BUILD(arg, right, NODE(TK_SEQ, TREE(value)));
      ast_append(positional, arg);
      value = ast_sibling(value);
    }
  } else {
    BUILD(arg, right, NODE(TK_SEQ, TREE(right)));
    ast_add(positional, arg);
  }

  REPLACE(astp,
    NODE(TK_CALL,
      TREE(positional)
      NONE
      NODE(TK_DOT, TREE(left) ID(fn_name))
      ));

  return AST_OK;
}
예제 #5
0
파일: call.c 프로젝트: abingham/ponyc
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;
}
예제 #6
0
파일: assemble.c 프로젝트: jonas-l/ponyc
ast_t* type_isect_fun(ast_t* a, ast_t* b)
{
  token_id ta = ast_id(a);
  token_id tb = ast_id(b);

  if(((ta == TK_NEW) || (tb == TK_NEW)) && (ta != tb))
    return NULL;

  AST_GET_CHILDREN(a, a_cap, a_id, a_typeparams, a_params, a_result, a_throw);
  AST_GET_CHILDREN(b, b_cap, b_id, b_typeparams, b_params, b_result, b_throw);

  // Must have the same name.
  if(ast_name(a_id) != ast_name(b_id))
    return NULL;

  // Must have the same number of type parameters and parameters.
  if((ast_childcount(a_typeparams) != ast_childcount(b_typeparams)) ||
    (ast_childcount(a_params) != ast_childcount(b_params)))
    return NULL;

  // Contravariant receiver cap.
  token_id tcap;
  token_id a_tcap = ast_id(a_cap);
  token_id b_tcap = ast_id(b_cap);

  if(is_cap_sub_cap(b_tcap, TK_NONE, a_tcap, TK_NONE))
    tcap = a_tcap;
  else if(is_cap_sub_cap(a_tcap, TK_NONE, b_tcap, TK_NONE))
    tcap = b_tcap;
  else
    tcap = TK_BOX;

  // Result is the intersection of the results.
  ast_t* result = type_isect(a_result, b_result);

  // Covariant throws.
  token_id throws;

  if((ast_id(a_throw) == TK_NONE) || (ast_id(b_throw) == TK_NONE))
    throws = TK_NONE;
  else
    throws = TK_QUESTION;

  BUILD(fun, a,
    NODE(tcap)
    TREE(a_id)
    NODE(TK_TYPEPARAMS)
    NODE(TK_PARAMS)
    TREE(result)
    NODE(throws)
    );

  // TODO: union typeparams and params
  // handling typeparam names is tricky
  return fun;
}
예제 #7
0
파일: main.c 프로젝트: Alecs94/DSA-lab
void TREE(nodeT * root, int level){
    //int i;
    if (root!=NULL){
        /*for(i=0;i<=level;i++){
            printf(" ");
        }*/
        printf("%s ",root->data);
        TREE(root->left,level+1);
        TREE(root->right,level+1);
    }
}
예제 #8
0
static gboolean
del_tree (TreeNode **ptop,
          guint      v)
{
  TreeNode *found;
  GSK_RBTREE_LOOKUP_COMPARATOR (TREE(ptop), v, COMPARE_INT_WITH_TREE_NODE, found);
  if (found == NULL)
    return FALSE;
  GSK_RBTREE_REMOVE (TREE(ptop), found);
  gsk_mem_pool_fixed_free (&tree_node_pool, found);
  return TRUE;
}
예제 #9
0
파일: sugar.c 프로젝트: shepheb/ponyc
static ast_result_t sugar_with(typecheck_t* t, ast_t** astp)
{
  AST_EXTRACT_CHILDREN(*astp, withexpr, body, else_clause);
  token_id try_token;

  if(ast_id(else_clause) == TK_NONE)
    try_token = TK_TRY_NO_CHECK;
  else
    try_token = TK_TRY;

  expand_none(else_clause, false);

  // First build a skeleton try block without the "with" variables
  BUILD(replace, *astp,
    NODE(TK_SEQ,
      NODE(try_token,
        NODE(TK_SEQ, AST_SCOPE
          TREE(body))
        NODE(TK_SEQ, AST_SCOPE
          TREE(else_clause))
        NODE(TK_SEQ, AST_SCOPE))));

  ast_t* tryexpr = ast_child(replace);
  AST_GET_CHILDREN(tryexpr, try_body, try_else, try_then);

  // Add the "with" variables from each with element
  for(ast_t* p = ast_child(withexpr); p != NULL; p = ast_sibling(p))
  {
    assert(ast_id(p) == TK_SEQ);
    AST_GET_CHILDREN(p, idseq, init);
    const char* init_name = package_hygienic_id(t);

    BUILD(assign, idseq,
      NODE(TK_ASSIGN, AST_NODEBUG
        TREE(init)
        NODE(TK_LET, ID(init_name) NONE)));

    BUILD(local, idseq,
      NODE(TK_ASSIGN, AST_NODEBUG
        NODE(TK_REFERENCE, ID(init_name))
        TREE(idseq)));

    ast_add(replace, assign);
    ast_add(try_body, local);
    ast_add(try_else, local);
    build_with_dispose(try_then, idseq);
    ast_add(try_then, local);
  }

  ast_replace(astp, replace);
  return AST_OK;
}
예제 #10
0
int CreateThreadsParams(threaded_subDivide_parms **th_parms, threaded_subDivide_parms *model)
{
    subDivide_parms *parms =&model->parms;
    int npoints = parms->npoints;
    BBTreeNode *node[npoints];
    int i,nparms;
    
    nparms=0;
    for (i=0;i<npoints;i++)
	node[i]=&TREE(i)->node[TREE(i)->npart];

    CreateThreadsParams_recursive(th_parms,model,&nparms,node,0,glob_NThreads);
    
    return nparms;
}
예제 #11
0
파일: sugar.c 프로젝트: shepheb/ponyc
static void build_with_dispose(ast_t* dispose_clause, ast_t* idseq)
{
  assert(dispose_clause != NULL);
  assert(idseq != NULL);

  if(ast_id(idseq) == TK_LET)
  {
    // Just a single variable
    ast_t* id = ast_child(idseq);
    assert(id != NULL);

    // Don't call dispose() on don't cares
    if(ast_id(id) == TK_DONTCARE)
      return;

    assert(ast_id(id) == TK_ID);
    BUILD(dispose, idseq,
      NODE(TK_CALL,
        NONE NONE
        NODE(TK_DOT, NODE(TK_REFERENCE, TREE(id)) ID("dispose"))));

    ast_add(dispose_clause, dispose);
    return;
  }

  // We have a list of variables
  assert(ast_id(idseq) == TK_TUPLE);

  for(ast_t* p = ast_child(idseq); p != NULL; p = ast_sibling(p))
    build_with_dispose(dispose_clause, p);
}
예제 #12
0
파일: casemethod.c 프로젝트: DevL/ponyc
// Handle the given case method parameter, which does not have a type
// specified.
// Check the case parameter and generate the pattern element.
// Returns: true on success, false on error.
static bool param_without_type(ast_t* case_param, ast_t* pattern)
{
  assert(case_param != NULL);
  assert(pattern != NULL);

  AST_GET_CHILDREN(case_param, value, type, def_arg);
  assert(ast_id(type) == TK_NONE);

  if(ast_id(def_arg) != TK_NONE)
  {
    ast_error(type,
      "cannot specify default argument for match value parameter");
    return false;
  }

  // Add value to match pattern. Pop it first to avoid pointless copy.
  ast_t* popped_value = ast_pop(case_param);

  if(ast_id(popped_value) == TK_DONTCARE)
  {
    // Value is just `don't care`.
    ast_append(pattern, popped_value);
  }
  else
  {
    // Value in an expression, need a containing sequence.
    BUILD(value_ast, value, NODE(TK_SEQ, TREE(popped_value)));
    ast_append(pattern, value_ast);
  }

  return true;
}
예제 #13
0
파일: sugar.c 프로젝트: shepheb/ponyc
static ast_result_t sugar_ifdef(typecheck_t* t, ast_t* ast)
{
  assert(t != NULL);
  assert(ast != NULL);

  AST_GET_CHILDREN(ast, cond, then_block, else_block, else_cond);

  // Combine parent ifdef condition with ours.
  ast_t* parent_ifdef_cond = t->frame->ifdef_cond;

  if(parent_ifdef_cond != NULL)
  {
    // We have a parent ifdef, combine its condition with ours.
    assert(ast_id(ast_parent(parent_ifdef_cond)) == TK_IFDEF);

    REPLACE(&else_cond,
      NODE(TK_AND,
        TREE(parent_ifdef_cond)
        NODE(TK_NOT, TREE(cond))));

    REPLACE(&cond,
      NODE(TK_AND,
        TREE(parent_ifdef_cond)
        TREE(cond)));
  }
  else
  {
    // Make else condition for our children to use.
    REPLACE(&else_cond, NODE(TK_NOT, TREE(cond)));
  }

  // Normalise condition so and, or and not nodes aren't sugared to function
  // calls.
  if(!ifdef_cond_normalise(&cond))
  {
    ast_error(ast, "ifdef condition will never be true");
    return AST_ERROR;
  }

  if(!ifdef_cond_normalise(&else_cond))
  {
    ast_error(ast, "ifdef condition is always true");
    return AST_ERROR;
  }

  return sugar_else(ast);
}
예제 #14
0
static gboolean
test_tree (TreeNode **ptop,
           guint      v)
{
  TreeNode *found;
  GSK_RBTREE_LOOKUP_COMPARATOR (TREE(ptop), v, COMPARE_INT_WITH_TREE_NODE, found);
  return found != NULL;
}
예제 #15
0
파일: assemble.c 프로젝트: jonas-l/ponyc
ast_t* type_for_this(typecheck_t* t, ast_t* ast, token_id cap,
  token_id ephemeral)
{
  bool make_arrow = false;

  if(cap == TK_BOX)
  {
    cap = TK_REF;
    make_arrow = true;
  }

  AST_GET_CHILDREN(t->frame->type, id, typeparams);

  BUILD(typeargs, ast, NODE(TK_NONE));

  BUILD(type, ast,
    NODE(TK_NOMINAL,
      NODE(TK_NONE)
      TREE(id)
      TREE(typeargs)
      NODE(cap)
      NODE(ephemeral)));

  if(ast_id(typeparams) == TK_TYPEPARAMS)
  {
    ast_setid(typeargs, TK_TYPEARGS);
    ast_t* typeparam = ast_child(typeparams);

    while(typeparam != NULL)
    {
      ast_t* typeparam_id = ast_child(typeparam);
      ast_t* typearg = type_sugar(ast, NULL, ast_name(typeparam_id));
      ast_append(typeargs, typearg);

      typeparam = ast_sibling(typeparam);
    }
  }

  if(make_arrow)
  {
    BUILD(arrow, ast, NODE(TK_ARROW, NODE(TK_THISTYPE) TREE(type)));
    return arrow;
  }

  return type;
}
예제 #16
0
파일: sugar.c 프로젝트: shepheb/ponyc
static void add_as_type(typecheck_t* t, ast_t* type, ast_t* pattern,
  ast_t* body)
{
  assert(type != NULL);

  switch(ast_id(type))
  {
    case TK_TUPLETYPE:
    {
      BUILD(tuple_pattern, pattern, NODE(TK_SEQ, NODE(TK_TUPLE)));
      ast_append(pattern, tuple_pattern);
      ast_t* pattern_child = ast_child(tuple_pattern);

      BUILD(tuple_body, body, NODE(TK_SEQ, NODE(TK_TUPLE)));
      ast_t* body_child = ast_child(tuple_body);

      for(ast_t* p = ast_child(type); p != NULL; p = ast_sibling(p))
        add_as_type(t, p, pattern_child, body_child);

      if(ast_childcount(body_child) == 1)
      {
        // Only one child, not actually a tuple
        ast_t* t = ast_pop(body_child);
        ast_free(tuple_body);
        tuple_body = t;
      }

      ast_append(body, tuple_body);
      break;
    }

    case TK_DONTCARE:
      ast_append(pattern, type);
      break;

    default:
    {
      const char* name = package_hygienic_id(t);
      ast_t* a_type = alias(type);

      BUILD(pattern_elem, pattern,
        NODE(TK_SEQ,
          NODE(TK_LET, ID(name) TREE(a_type))));

      BUILD(body_elem, body,
        NODE(TK_SEQ,
          NODE(TK_CONSUME, NODE(TK_BORROWED) NODE(TK_REFERENCE, ID(name)))));

      ast_append(pattern, pattern_elem);
      ast_append(body, body_elem);
      break;
    }
  }
}
예제 #17
0
파일: traits.c 프로젝트: awaidmann/ponyc
// Convert the given method into a delegation indirection to the specified
// field.
static void make_delegation(ast_t* method, ast_t* field, ast_t* delegate_ref,
  ast_t* body_donor)
{
  assert(method != NULL);
  assert(field != NULL);
  assert(delegate_ref != NULL);

  // Make a redirection method body.
  ast_t* args = ast_from(delegate_ref, TK_NONE);
  ast_t* last_arg = NULL;

  AST_GET_CHILDREN(method, cap, id, t_params, params, result, error, old_body);

  for(ast_t* p = ast_child(params); p != NULL; p = ast_sibling(p))
  {
    const char* param_name = ast_name(ast_child(p));

    BUILD(arg, delegate_ref,
      NODE(TK_SEQ,
        NODE(TK_CONSUME,
          NONE
          NODE(TK_REFERENCE, ID(param_name)))));

    ast_list_append(args, &last_arg, arg);
    ast_setid(args, TK_POSITIONALARGS);
  }

  BUILD(body, delegate_ref,
    NODE(TK_SEQ,
      NODE(TK_CALL,
        TREE(args)    // Positional args.
        NODE(TK_NONE) // Named args.
        NODE(TK_DOT,  // Receiver.
          NODE(TK_REFERENCE, ID(ast_name(ast_child(field))))
          ID(ast_name(ast_childidx(method, 1)))))));

  if(is_none(result))
  {
    // Add None to end of body. Whilst the call generated above will return
    // None anyway in this case, without this extra None testing is very hard
    // since a directly written version of this body will have the None.
    BUILD(none, delegate_ref, NODE(TK_REFERENCE, ID("None")));
    ast_append(body, none);
  }

  ast_replace(&old_body, body);

  // Setup method info.
  method_t* info = (method_t*)ast_data(method);
  assert(info != NULL);
  info->body_donor = body_donor;
  info->delegated_field = field;
}
예제 #18
0
파일: lambda.c 프로젝트: jonas-l/ponyc
bool expr_lambda(pass_opt_t* opt, ast_t** astp)
{
  assert(astp != NULL);
  ast_t* ast = *astp;
  assert(ast != NULL);

  AST_GET_CHILDREN(ast, cap, t_params, params, captures, ret_type, raises,
    body);

  ast_t* members = ast_from(ast, TK_MEMBERS);
  ast_t* last_member = NULL;
  bool failed = false;

  // Process captures
  for(ast_t* p = ast_child(captures); p != NULL; p = ast_sibling(p))
  {
    ast_t* field = make_capture_field(p);

    if(field != NULL)
      ast_list_append(members, &last_member, field);
    else  // An error occurred, just keep going to potentially find more errors
      failed = true;
  }

  if(failed)
  {
    ast_free(members);
    return false;
  }

  // Stop the various elements being marked as preserve
  ast_clearflag(t_params, AST_FLAG_PRESERVE);
  ast_clearflag(params, AST_FLAG_PRESERVE);
  ast_clearflag(ret_type, AST_FLAG_PRESERVE);
  ast_clearflag(body, AST_FLAG_PRESERVE);

  // Make the apply function
  BUILD(apply, ast,
    NODE(TK_FUN, AST_SCOPE
      NONE  // Capability
      ID("apply")
      TREE(t_params)
      TREE(params)
      TREE(ret_type)
      TREE(raises)
      TREE(body)
      NONE));  // Doc string

  ast_list_append(members, &last_member, apply);

  // Replace lambda with object literal
  REPLACE(astp,
    NODE(TK_OBJECT,
      TREE(cap);
      NONE  // Provides list
      TREE(members)));

  // Catch up passes
  return ast_passes_subtree(astp, opt, PASS_EXPR);
}
예제 #19
0
파일: sugar.c 프로젝트: shepheb/ponyc
static ast_result_t sugar_for(typecheck_t* t, ast_t** astp)
{
  AST_EXTRACT_CHILDREN(*astp, for_idseq, for_iter, for_body, for_else);

  expand_none(for_else, true);
  const char* iter_name = package_hygienic_id(t);

  BUILD(try_next, for_iter,
    NODE(TK_TRY_NO_CHECK,
      NODE(TK_SEQ, AST_SCOPE
        NODE(TK_CALL,
          NONE
          NONE
          NODE(TK_DOT, NODE(TK_REFERENCE, ID(iter_name)) ID("next"))))
      NODE(TK_SEQ, AST_SCOPE
        NODE(TK_CONTINUE, NONE))
      NONE));

  sugar_try(try_next);

  REPLACE(astp,
    NODE(TK_SEQ,
      NODE(TK_ASSIGN, AST_NODEBUG
        TREE(for_iter)
        NODE(TK_LET, NICE_ID(iter_name, "for loop iterator") NONE))
      NODE(TK_WHILE, AST_SCOPE
        NODE(TK_SEQ,
          NODE_ERROR_AT(TK_CALL, for_iter,
            NONE
            NONE
            NODE(TK_DOT, NODE(TK_REFERENCE, ID(iter_name)) ID("has_next"))))
        NODE(TK_SEQ, AST_SCOPE
          NODE_ERROR_AT(TK_ASSIGN, for_idseq, AST_NODEBUG
            TREE(try_next)
            TREE(for_idseq))
          TREE(for_body))
        TREE(for_else))));

  return AST_OK;
}
예제 #20
0
파일: main.c 프로젝트: Alecs94/DSA-lab
int main()

{
    nodeT *t=createTreeRoot();
    nodeL *l=createListFromTree(t);
    free(t);
    l=s->first;
    LIST(l);// prints the list
    printf("\n");
    t=createTreeFromList(l);
    TREE(t,0);//the tree
    return 0;
}
예제 #21
0
파일: assemble.c 프로젝트: jonas-l/ponyc
ast_t* type_for_fun(ast_t* ast)
{
  AST_GET_CHILDREN(ast, cap, name, typeparams, params, result);
  token_id fcap = ast_id(cap);

  if(fcap == TK_NONE)
    fcap = TK_TAG;

  // The params may already have types attached. If we build the function type
  // directly from those we'll get nested types which can mess things up. To
  // avoid this make a clean version of the params without types.
  ast_t* clean_params = ast_dup(params);

  for(ast_t* p = ast_child(clean_params); p != NULL; p = ast_sibling(p))
    ast_settype(p, NULL);

  BUILD(fun, ast,
    NODE(TK_FUNTYPE,
      NODE(fcap) TREE(typeparams) TREE(clean_params) TREE(result)));

  return fun;
}
예제 #22
0
static gboolean
add_tree (TreeNode **ptop,
          guint      v)
{
  TreeNode *node = gsk_mem_pool_fixed_alloc (&tree_node_pool);
  TreeNode *extant;
  node->value = v;
  GSK_RBTREE_INSERT (TREE(ptop), node, extant);
  if (extant == NULL)
    return FALSE;
  gsk_mem_pool_fixed_free (&tree_node_pool, node);
  return TRUE;
}
예제 #23
0
파일: sugar.c 프로젝트: shepheb/ponyc
static ast_result_t sugar_unop(ast_t** astp, const char* fn_name)
{
  AST_GET_CHILDREN(*astp, expr);

  REPLACE(astp,
    NODE(TK_CALL,
      NONE
      NONE
      NODE(TK_DOT, TREE(expr) ID(fn_name))
      ));

  return AST_OK;
}
예제 #24
0
파일: names.c 프로젝트: dailypips/ponyc
static bool names_typeparam(ast_t** astp, ast_t* def)
{
  ast_t* ast = *astp;
  AST_GET_CHILDREN(ast, package, type, typeargs, cap, ephemeral);
  assert(ast_id(package) == TK_NONE);

  if(ast_id(typeargs) != TK_NONE)
  {
    ast_error(typeargs, "can't qualify a type parameter with type arguments");
    return false;
  }

  // Change to a typeparamref.
  REPLACE(astp,
    NODE(TK_TYPEPARAMREF,
      TREE(type)
      TREE(cap)
      TREE(ephemeral)));

  ast_setdata(*astp, def);
  return true;
}
예제 #25
0
파일: sugar.c 프로젝트: shepheb/ponyc
static ast_result_t sugar_as(pass_opt_t* opt, ast_t** astp)
{
  typecheck_t* t = &opt->check;
  ast_t* ast = *astp;
  AST_GET_CHILDREN(ast, expr, type);

  ast_t* pattern_root = ast_from(type, TK_LEX_ERROR);
  ast_t* body_root = ast_from(type, TK_LEX_ERROR);
  add_as_type(t, type, pattern_root, body_root);

  ast_t* body = ast_pop(body_root);
  ast_free(body_root);

  if(body == NULL)
  {
    // No body implies all types are "don't care"
    ast_error(ast, "Cannot treat value as \"don't care\"");
    ast_free(pattern_root);
    return AST_ERROR;
  }

  // Don't need top sequence in pattern
  assert(ast_id(ast_child(pattern_root)) == TK_SEQ);
  ast_t* pattern = ast_pop(ast_child(pattern_root));
  ast_free(pattern_root);

  REPLACE(astp,
    NODE(TK_MATCH, AST_SCOPE
      NODE(TK_SEQ, TREE(expr))
      NODE(TK_CASES, AST_SCOPE
        NODE(TK_CASE, AST_SCOPE
          TREE(pattern)
          NONE
          TREE(body)))
      NODE(TK_SEQ, AST_SCOPE NODE(TK_ERROR, NONE))));

  return ast_visit(astp, pass_sugar, NULL, opt, PASS_SUGAR);
}
예제 #26
0
파일: casemethod.c 프로젝트: DevL/ponyc
// Check type parameters and build the all type parameter structures for a
// complete set of case methods with the given name.
// Generate type parameter list for worker call.
static void build_t_params(ast_t* match_t_params,
  ast_t* worker_t_params)
{
  assert(match_t_params != NULL);
  assert(worker_t_params != NULL);

  for(ast_t* p = ast_child(match_t_params); p != NULL; p = ast_sibling(p))
  {
    AST_GET_CHILDREN(p, id, constraint, def_type);
    assert(ast_id(id) == TK_ID);

    // Add type parameter name to worker call list.
    BUILD(type, p, NODE(TK_NOMINAL, NONE TREE(id) NONE NONE NONE));
    ast_append(worker_t_params, type);
    ast_setid(worker_t_params, TK_TYPEARGS);
  }
}
예제 #27
0
파일: sugar.c 프로젝트: shepheb/ponyc
static ast_result_t sugar_typeparam(ast_t* ast)
{
  AST_GET_CHILDREN(ast, id, constraint);

  if(ast_id(constraint) == TK_NONE)
  {
    REPLACE(&constraint,
      NODE(TK_NOMINAL,
        NONE
        TREE(id)
        NONE
        NONE
        NONE));
  }

  return AST_OK;
}
예제 #28
0
파일: assemble.c 프로젝트: jonas-l/ponyc
ast_t* type_pointer_to(pass_opt_t* opt, ast_t* to)
{
  BUILD(pointer, to,
    NODE(TK_NOMINAL,
      NONE // Package
      ID("Pointer")
      NODE(TK_TYPEARGS,
        TREE(to)
        )
      NONE // Capability
      NONE // Ephemeral
      ));

  if(!names_nominal(opt, to, &pointer, false))
  {
    ast_error(to, "unable to create Pointer[%s]", ast_print_type(to));
    ast_free(pointer);
    return NULL;
  }

  return pointer;
}
예제 #29
0
// Collect the given type parameter
static void collect_type_param(ast_t* orig_param, ast_t* params, ast_t* args)
{
  assert(orig_param != NULL);

  // Get original type parameter info
  AST_GET_CHILDREN(orig_param, id, constraint, deflt);
  const char* name = ast_name(id);

  constraint = sanitise_type(constraint);
  assert(constraint != NULL);

  // New type parameter has the same constraint as the old one (sanitised)
  if(params != NULL)
  {
    BUILD(new_param, orig_param,
      NODE(TK_TYPEPARAM,
        ID(name)
        TREE(constraint)
        NONE));

    ast_append(params, new_param);
    ast_setid(params, TK_TYPEPARAMS);
  }

  // New type arguments binds to old type parameter
  if(args != NULL)
  {
    BUILD(new_arg, orig_param,
      NODE(TK_NOMINAL,
        NONE  // Package
        ID(name)
        NONE  // Type args
        NONE  // cap
        NONE)); // ephemeral

    ast_append(args, new_arg);
    ast_setid(args, TK_TYPEARGS);
  }
}
예제 #30
0
파일: sanitise.c 프로젝트: FedeOmoto/ponyc
// Collect the given type parameter
static void collect_type_param(ast_t* orig_param, ast_t* params, ast_t* args)
{
  assert(orig_param != NULL);
  assert(params != NULL);
  assert(args != NULL);

  // Get original type parameter info
  AST_GET_CHILDREN(orig_param, id, constraint, deflt);
  const char* name = ast_name(id);

  constraint = sanitise_type(constraint);
  assert(constraint != NULL);

  // New type parameter has the same constraint as the old one (sanitised)
  BUILD(new_param, orig_param,
    NODE(TK_TYPEPARAM,
      ID(name)
      TREE(constraint)
      NONE));

  ast_append(params, new_param);

  // New type arguments binds to old type parameter
  BUILD(new_arg, orig_param,
    NODE(TK_TYPEPARAMREF, DATA(orig_param)  
      ID(name)
      NONE  // cap
      NONE)); // ephemeral

  ast_append(args, new_arg);

  // Since we have a type parameter the params and args node should not be
  // TK_NONE
  ast_setid(params, TK_TYPEPARAMS);
  ast_setid(args, TK_TYPEARGS);
}