[RFC PATCH 1/2] Add impl(type, name) to retrieve a particular implementation of a trait decl
[Thread Prev] | [Thread Next]
[Date Prev] | [Date Next]
- Subject: [RFC PATCH 1/2] Add impl(type, name) to retrieve a particular implementation of a trait decl
- From: Michael Forney <mforney@xxxxxxxxxxx>
- Date: Sat, 1 Jul 2017 14:43:21 -0700
- To: myrddin-dev@xxxxxxxxxxxxxx
This avoids having to create a temporary variable when you know what implementation your want for a generic constant or function with generic return value. Re-use the impl keyword for this expression to avoid invalidating existing programs. --- doc/lang.txt | 10 ++++++++-- parse/gram.y | 6 +++++- parse/infer.c | 24 ++++++++++++++++++------ test/implexpr.myr | 18 ++++++++++++++++++ test/tests | 2 +- 5 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 test/implexpr.myr diff --git a/doc/lang.txt b/doc/lang.txt index 0f143224..3be5500f 100644 --- a/doc/lang.txt +++ b/doc/lang.txt @@ -1239,7 +1239,8 @@ TABLE OF CONTENTS: 5.2.3. Atomic Expressions: atomicexpr: ident | gap | literal | "(" expr ")" | - "sizeof" "(" type ")" | castexpr + "sizeof" "(" type ")" | castexpr | + "impl" "(" name "," type ")" castexpr: "(" expr ":" type ")" gap: "_" @@ -1265,6 +1266,10 @@ TABLE OF CONTENTS: match, again, given that it is never read from in the body of the match. + An impl expression chooses the implementation of the given trait + declaration for the given type. It is useful for refering to trait + declarations in a generic context. + 5.2.4. Cast Expressions: Cast expressions convert a value from one type to another. Some @@ -2012,7 +2017,8 @@ TABLE OF CONTENTS: postepxr "#" | atomicexpr - atomicexpr: ident | literal | "(" expr ")" | "sizeof" "(" type ")" + atomicexpr: ident | literal | "(" expr ")" | "sizeof" "(" type ")" | + "(" expr ":" type ")" | "impl" "(" name "," type ")" /* literals */ literal: funclit | seqlit | tuplit | simplelit diff --git a/parse/gram.y b/parse/gram.y index 3839a92c..bcf9713f 100644 --- a/parse/gram.y +++ b/parse/gram.y @@ -380,7 +380,7 @@ typedeclcore name : Tident {$$ = mkname($1->loc, $1->id);} | Tident Tdot Tident { - $$ = mkname($3->loc, $3->id); setns($$, $1->id); + $$ = mknsname($3->loc, $1->id, $3->id); } ; @@ -755,6 +755,10 @@ atomicexpr } | Tsizeof Toparen type Tcparen {$$ = mkexpr($1->loc, Osize, mkpseudodecl($1->loc, $3), NULL);} + | Timpl Toparen name Tcomma type Tcparen { + $$ = mkexpr($1->loc, Ovar, $3, NULL); + $$->expr.param = $5; + } ; tupbody : tuphead tuprest diff --git a/parse/infer.c b/parse/infer.c index dcaf1c40..445b34b4 100644 --- a/parse/infer.c +++ b/parse/infer.c @@ -1199,13 +1199,16 @@ static Type *initvar(Inferstate *st, Node *n, Node *s) if (s->decl.ishidden) fatal(n, "attempting to refer to hidden decl %s", ctxstr(st, n)); - param = NULL; + param = n->expr.param; if (s->decl.isgeneric) { subst = mksubst(); + if (param) + substput(subst, s->decl.trait->param, param); t = tysubstmap(st, subst, tf(st, s->decl.type), s->decl.type); - if (s->decl.trait) { + if (s->decl.trait && !param) { param = substget(subst, s->decl.trait->param); - delayedcheck(st, n, curstab()); + if (!param) + fatal(n, "ambiguous trait decl %s", ctxstr(st, s)); } substfree(subst); } else { @@ -1213,7 +1216,10 @@ static Type *initvar(Inferstate *st, Node *n, Node *s) } n->expr.did = s->decl.did; n->expr.isconst = s->decl.isconst; - n->expr.param = param; + if (param) { + n->expr.param = param; + delayedcheck(st, n, curstab()); + } if (s->decl.isgeneric && !st->ingeneric) { t = tyfreshen(st, NULL, t); addspecialization(st, n, curstab()); @@ -1484,6 +1490,7 @@ static void inferexpr(Inferstate *st, Node **np, Type *ret, int *sawret) Node *s, *n; Type *t, *b; int isconst; + Stab *ns; n = *np; assert(n->type == Nexpr); @@ -1650,9 +1657,14 @@ static void inferexpr(Inferstate *st, Node **np, Type *ret, int *sawret) * already done with this node, we can just return. */ if (n->expr.type) return; - s = getdcl(curstab(), args[0]); + ns = curstab(); + if (args[0]->name.ns) + ns = getns(file, args[0]->name.ns); + s = getdcl(ns, args[0]); if (!s) fatal(n, "undeclared var %s", ctxstr(st, args[0])); + if (n->expr.param && !s->decl.trait) + fatal(n, "var %s must refer to a trait decl", ctxstr(st, args[0])); initvar(st, n, s); break; case Ogap: /* _ -> @a */ @@ -1812,7 +1824,7 @@ static void specializeimpl(Inferstate *st, Node *n) putdcl(file->file.globls, dcl); htput(proto->decl.impls, n->impl.type, dcl); dcl->decl.isconst = 1; - if (n->impl.type->type == Tygeneric || hasparams(n->impl.type)) { + if (ty->type == Tygeneric || hasparams(ty)) { dcl->decl.isgeneric = 1; lappend(&proto->decl.gimpl, &proto->decl.ngimpl, dcl); lappend(&proto->decl.gtype, &proto->decl.ngtype, ty); diff --git a/test/implexpr.myr b/test/implexpr.myr new file mode 100644 index 00000000..d449a2af --- /dev/null +++ b/test/implexpr.myr @@ -0,0 +1,18 @@ +use std + +trait favorite @a = + Fav : @a +;; +impl favorite int = + Fav = 12 +;; +impl favorite char = + Fav = 'z' +;; +impl favorite byte[:] = + Fav = "hello" +;; + +const main = { + std.put("{},{},{}\n", impl(Fav, int), impl(Fav, char), impl(Fav, byte[:])) +} diff --git a/test/tests b/test/tests index ba4e0750..937828be 100644 --- a/test/tests +++ b/test/tests @@ -164,4 +164,4 @@ B destructuretup E 0 B nestedgoto E 0 B initializer E 0 B fmtalign E 0 - +B implexpr P 12,z,hello -- 2.13.2
Re: [RFC PATCH 1/2] Add impl(type, name) to retrieve a particular implementation of a trait decl | Ori Bernstein <ori@xxxxxxxxxxxxxx> |
[RFC PATCH 0/2] impl specialization and lookup changes | Michael Forney <mforney@xxxxxxxxxxx> |
- Next by Date: [RFC PATCH 0/2] impl specialization and lookup changes
- Previous by thread: [RFC PATCH 0/2] impl specialization and lookup changes
- Next by thread: Re: [RFC PATCH 1/2] Add impl(type, name) to retrieve a particular implementation of a trait decl
- Index(es):