Skip to content

Commit

Permalink
Make behaviour calls return None (RFC 28) (#1460)
Browse files Browse the repository at this point in the history
Closes #1455.
  • Loading branch information
Benoit Vey authored and jemc committed Dec 8, 2016
1 parent 034ce60 commit a9827e7
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 21 deletions.
14 changes: 7 additions & 7 deletions examples/yield/main.pony
Original file line number Diff line number Diff line change
Expand Up @@ -220,20 +220,20 @@ actor Main
match punk
| true =>
PunkDemo(env)
.loop()
.inc().inc().inc()
.dec().dec().dec()
.inc().dec()
.kill()
.>loop()
.>inc().>inc().>inc()
.>dec().>dec().>dec()
.>inc().>dec()
.>kill()
else
match perf > 0
| true =>
InterruptiblePony(env,debug,perf).perf()
LonelyPony(env,debug,perf).perf()
else
match lonely
| false => InterruptiblePony(env,debug).forever().kill()
| true => LonelyPony(env,debug).forever().kill()
| false => InterruptiblePony(env,debug).>forever().>kill()
| true => LonelyPony(env,debug).>forever().>kill()
end
end
end
Expand Down
3 changes: 3 additions & 0 deletions src/libponyc/codegen/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,9 @@ static bool init_module(compile_t* c, ast_t* program, pass_opt_t* opt)
c->reach = reach_new();
c->tbaa_mds = tbaa_metadatas_new();

// This gets a real value once the instance of None has been generated.
c->none_instance = NULL;

return true;
}

Expand Down
1 change: 1 addition & 0 deletions src/libponyc/codegen/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ typedef struct compile_t
LLVMValueRef tbaa_root;
LLVMValueRef tbaa_descriptor;
LLVMValueRef tbaa_descptr;
LLVMValueRef none_instance;

LLVMTypeRef void_type;
LLVMTypeRef ibool;
Expand Down
12 changes: 11 additions & 1 deletion src/libponyc/codegen/gencall.c
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,17 @@ LLVMValueRef gen_call(compile_t* c, ast_t* ast)
codegen_debugloc(c, ast);
gen_send_message(c, m, args, positional);
codegen_debugloc(c, NULL);
r = args[0];
switch(ast_id(postfix))
{
case TK_NEWREF:
case TK_NEWBEREF:
r = args[0];
break;

default:
r = c->none_instance;
break;
}
} else {
while(arg != NULL)
{
Expand Down
4 changes: 2 additions & 2 deletions src/libponyc/codegen/genfun.c
Original file line number Diff line number Diff line change
Expand Up @@ -359,8 +359,8 @@ static bool genfun_be(compile_t* c, reach_type_t* t, reach_method_t* m)
// Send the arguments in a message to 'this'.
gen_send_message(c, m, param_vals, params);

// Return 'this'.
LLVMBuildRet(c->builder, param_vals[0]);
// Return None.
LLVMBuildRet(c->builder, c->none_instance);
codegen_finishfun(c);

ponyint_pool_free_size(buf_size, param_vals);
Expand Down
6 changes: 6 additions & 0 deletions src/libponyc/codegen/gentype.c
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,12 @@ bool gentypes(compile_t* c)
make_global_instance(c, t);
}

// Cache the instance of None, which is used as the return value for
// behaviour calls.
t = reach_type_name(c->reach, "None");
assert(t != NULL);
c->none_instance = t->instance;

if(c->opt->verbosity >= VERBOSITY_INFO)
fprintf(stderr, " Function prototypes\n");

Expand Down
5 changes: 3 additions & 2 deletions src/libponyc/pass/sugar.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,8 +378,9 @@ static ast_result_t sugar_be(pass_opt_t* opt, ast_t* ast)

if(ast_id(result) == TK_NONE)
{
// Return type is This tag
ast_replace(&result, type_for_this(opt, ast, TK_TAG, TK_NONE, false));
// Return type is None.
ast_t* type = type_sugar(ast, NULL, "None");
ast_replace(&result, type);
}

sugar_docstring(ast);
Expand Down
10 changes: 5 additions & 5 deletions test/libponyc/sugar.cc
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ TEST_F(SugarTest, ActorWithCreateBehaviour)
const char* full_form =
"use \"builtin\"\n"
"actor tag Foo\n"
" be tag create():Foo tag => 3";
" be tag create():None => 3";

TEST_EQUIV(short_form, full_form);
}
Expand Down Expand Up @@ -345,7 +345,7 @@ TEST_F(SugarTest, BehaviourReturnType)
"use \"builtin\"\n"
"actor tag Foo\n"
" var create: U32\n"
" be tag foo():Foo tag => 3";
" be tag foo():None => 3";

TEST_EQUIV(short_form, full_form);
}
Expand Down Expand Up @@ -1549,7 +1549,7 @@ TEST_F(SugarTest, ObjectWithBehaviour)
" None\n"

"actor tag $T\n"
" be tag foo(): $T tag =>\n"
" be tag foo(): None =>\n"
" 4\n"
" new tag create(): $T tag^ => true";

Expand Down Expand Up @@ -1626,7 +1626,7 @@ TEST_F(SugarTest, ObjectTagWithBehaviour)
" None\n"

"actor tag $T\n"
" be tag foo(): $T tag =>\n"
" be tag foo(): None =>\n"
" 4\n"
" new tag create(): $T tag^ => true";

Expand Down Expand Up @@ -2498,7 +2498,7 @@ TEST_F(SugarTest, CaseBehaviour)
"use \"builtin\"\n"
"actor tag Foo\n"
" var create: U32\n"
" be tag fib(a: U64): Foo tag =>\n"
" be tag fib(a: U64): None =>\n"
" $1(consume a)\n"
" fun ref $1($2: U64): None =>\n"
" match consume $2\n"
Expand Down
2 changes: 1 addition & 1 deletion test/libponyc/sugar_expr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ TEST_F(SugarExprTest, PartialBehaviour)

"class Foo\n"
" fun f(x: T) =>\n"
" {box()($1 = x): T tag => $1.f() }";
" {box()($1 = x) => $1.f() }";

TEST_EQUIV(short_form, full_form);
}
Expand Down
46 changes: 46 additions & 0 deletions test/libponyc/type_check_subtype.cc
Original file line number Diff line number Diff line change
Expand Up @@ -987,3 +987,49 @@ TEST_F(SubTypeTest, IsSubTypeArrow)

pass_opt_init(&opt);
}


TEST_F(SubTypeTest, IsFunTagSubBe)
{
const char* src =
"trait tag T\n"
" be foo()\n"

"class tag C is T\n"
" fun tag foo() => None\n"

"interface Test\n"
" fun z(t: T, c: C)";

TEST_COMPILE(src);

pass_opt_t opt;
pass_opt_init(&opt);

ASSERT_TRUE(is_subtype(type_of("c"), type_of("t"), NULL, &opt));

pass_opt_init(&opt);
}


TEST_F(SubTypeTest, IsBeSubFunTag)
{
const char* src =
"trait tag T\n"
" fun tag foo()\n"

"actor A is T\n"
" be foo() => None\n"

"interface Test\n"
" fun z(t: T, a: A)";

TEST_COMPILE(src);

pass_opt_t opt;
pass_opt_init(&opt);

ASSERT_TRUE(is_subtype(type_of("a"), type_of("t"), NULL, &opt));

pass_opt_init(&opt);
}
5 changes: 2 additions & 3 deletions test/libponyc/verify.cc
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,9 @@ TEST_F(VerifyTest, ActorBeFinal)
" be _final() =>\n"
" None";

TEST_ERRORS_3(src,
TEST_ERRORS_2(src,
"a _final method must be a function",
"a _final method must use box as the receiver capability",
"a _final method must return None");
"a _final method must use box as the receiver capability");
}

TEST_F(VerifyTest, ClassFunRefFinal)
Expand Down

0 comments on commit a9827e7

Please sign in to comment.