ref: ca10a1ec838b7d468a2b43894af659c111a0e9b1
parent: ddb327c92ebe3f96c5c816ec61996440551de401
author: Michael Forney <mforney@mforney.org>
date: Sat Jul 1 10:43:21 EDT 2017
Add impl(type, name) to retrieve a particular implementation of a trait decl 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.
--- a/doc/lang.txt
+++ b/doc/lang.txt
@@ -1239,7 +1239,8 @@
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 @@
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 @@
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
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -380,7 +380,7 @@
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 @@
}
| 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
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1199,13 +1199,16 @@
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 @@
}
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 @@
Node *s, *n;
Type *t, *b;
int isconst;
+ Stab *ns;
n = *np;
assert(n->type == Nexpr);
@@ -1650,9 +1657,14 @@
* 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 @@
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);
--- /dev/null
+++ b/test/implexpr.myr
@@ -1,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[:]))
+}
--- a/test/tests
+++ b/test/tests
@@ -164,4 +164,4 @@
B nestedgoto E 0
B initializer E 0
B fmtalign E 0
-
+B implexpr P 12,z,hello