ref: 7ec5af48e7c7fa40c494b5572fcfa04d3a998cba
parent: e2c679b435ce2e9a71a4247acaf0c9177cd33c0b
parent: ac6c06f906d356b0004ed450558dd890c7057fbf
author: Ori Bernstein <[email protected]>
date: Sun Jan 14 15:06:34 EST 2018
Merge branch 'trait-syntax'
--- a/6/gengas.c
+++ b/6/gengas.c
@@ -9,6 +9,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
+#include <errno.h>
#include "util.h"
#include "parse.h"
@@ -471,7 +472,8 @@
}
popstab();
- getcwd(dir, sizeof dir);
+ if (!getcwd(dir, sizeof dir))
+ die("could not get cwd: %s\n", strerror(errno));
for (i = 0; i < file->file.nfiles; i++) {
path = file->file.files[i];
fprintf(fd, ".file %zd \"%s/%s\"\n", i + 1, dir, path);
--- a/doc/lang.txt
+++ b/doc/lang.txt
@@ -190,7 +190,8 @@
3.3. Declarations:
- decl: attrs ("var" | "const" | "generic") decllist
+ decl: attrs declkind decllist [traitspec]
+ declkind: ("var" | "const" | "generic")
attrs: ("extern" | "pkglocal" | "$noret")*
decllist: declbody ("," declbody)*
declbody: declcore ["=" expr]
@@ -530,9 +531,7 @@
4.3. Generic types:
- typaram: "@" ident ["::" paramlist]
- paramlist: ident | "(" ident ("," ident)* ")"
-
+ typaram: "@" ident
A nametype refers to a (potentially parameterized) named type, as
defined in section 4.5.
@@ -591,7 +590,7 @@
4.4.2. Impls:
- implstmt: "impl" ident impltypes "=" implbody
+ implstmt: "impl" ident impltypes traitspec "=" implbody
impltypes: type ["->" type ("," type)*]
implbody: (name [":" type] "=" expr)*
@@ -637,8 +636,8 @@
specific type that represents them.
- Types are freshened. Freshening is the process of replacing
unbound type parameters with type variables, such that
- '@a::(integral,numeric)' is replaced with the type variable
- '$n::(integral,numeric)'.
+ '@a :: integral @a, numeric @a' is replaced with the type variable
+ '$n :: integral $n, numeric $n'.
- Union tags are registered for delayed unification, with the type
for unions being the declaration type of the variable.
@@ -782,8 +781,8 @@
a single pass suffices.
At this point, default types are applied. An unconstrained type
- with type $t::(numeric,integral) is replaced with int. An
- unconstrained type with $t::(numeric,floating) is replaced with
+ with type $t :: numeric $t, integral $t is replaced with int. An
+ unconstrained type with $t :: numeric $t, floating $t is replaced with
flt64.
4.6. Built In Traits:
@@ -950,7 +949,7 @@
e.g. 0x123_fff, 0b1111, 0o777, 1234
- They have the type `@a::(numeric,integral)
+ They have the type `@a :: numeric @a, integral @a
5.1.1.4: Boolean Literals:
@@ -980,7 +979,7 @@
e.g. 123.456, 10.0e7, 1_000.
- They have type `@a::(numeric,floating)`
+ They have type `@a :: numeric @a, floating @a`
5.1.2. Sequence and Tuple Literals:
@@ -1043,7 +1042,8 @@
5.1.3. Function Literals:
- funclit: "{" arglist ["->" rettype] "\n" blockbody "}"
+ funclit: "{" arglist ["->" rettype] [traitspec] "\n"
+ blockbody "}"
arglist: (ident [":" type])*
Function literals describe a function. They begin with a '{',
@@ -1461,8 +1461,7 @@
Type:
- ( e1 : @a OP e2 : @a ) : bool
- where @a :: numeric
+ ( e1 : @a OP e2 : @a ) : bool :: numeric @a
5.2.11. Union Constructors:
@@ -1488,8 +1487,7 @@
Type:
- (e1 : @a OP e2:@a) : @a
- where @a :: integral
+ (e1 : @a OP e2:@a) : @a :: integral @a
5.2.13. Addition:
@@ -1503,8 +1501,7 @@
Type:
- ( e1 : @a OP e2 : @a ) : bool
- where @a :: numeric
+ ( e1 : @a OP e2 : @a ) : bool :: numeric @a
5.2.14. Multiplication and Division
@@ -1516,8 +1513,7 @@
Type:
- ( e1 : @a OP e2 : @a ) : bool
- where @a :: numeric
+ ( e1 : @a OP e2 : @a ) : bool :: numeric @a
5.2.15. Modulo:
@@ -1528,8 +1524,7 @@
Type:
- ( e1 : @a OP e2 : @a ) : bool
- where @a :: (numeric,integral)
+ ( e1 : @a OP e2 : @a ) : bool :: numeric @a, integral @a
5.2.16. Shift:
@@ -1545,8 +1540,7 @@
Type:
- (e1 : @a OP e2:@a) : @a
- where @a :: integral
+ (e1 : @a OP e2:@a) : @a :: integral @a
5.2.17: Postincrement, Postdecrement:
@@ -1570,7 +1564,7 @@
(e1++ : @a) : @a
(e1-- : @a) : @a
- where @a :: integral
+ :: integral @a
5.2.18: Address:
@@ -1636,7 +1630,7 @@
(expr : <aggregate>).name : @a
(expr : <seq>).len : @idx
- where @idx :: (integral,numeric)
+ :: integral @a, numeric @a
5.2.22: Index:
@@ -1653,7 +1647,7 @@
(expr : @a[N])[(idx : @idx)] : @a
(expr : @a[:])[(idx : @idx)] : @a
- where @idx :: (integral,numeric)
+ :: integral, numeric @idx
5.2.23: Slice:
@@ -1675,8 +1669,7 @@
(expr : @a[N])[(lo : @lo) : (hi : @hi)] : @a[:]
(expr : @a[:])[(lo : @lo) : (hi : @hi)] : @a[:]
(expr : @#)[(lo : @lo) : (hi : @hi)] : @a[:]
- where @lo :: (integral,numeric)
- and @hi :: (integral,numeric)
+ :: integral, numeric @lo, integral, numeric @hi
5.2.24: Call:
@@ -1960,7 +1953,7 @@
pkgbody: (decl | attrs tydef | traitdef | impldef)*
/* declarations */
- decl: attrs ("var" | "const" | "generic") decllist
+ decl: attrs ("var" | "const" | "generic") decllist
attrs: ("$noret" | "extern" | "pkglocal")*
decllist: declbody ("," declbody)+
declbody: declcore ["=" expr]
@@ -1967,14 +1960,16 @@
declcore: ident [":" type]
/* traits */
- traitdef: "trait" ident typaram [auxtypes] ("\n" | "=" traitbody ";;")
+ traitdef: "trait" ident typaram [auxtypes] [traitspec] ("\n" | "=" traitbody ";;")
auxtypes: "->" type ("," type)*
traitbody: "\n"* (ident ":" type "\n"*)*
- impldef: "impl" ident type [auxtypes] ("\n" | "=" implbody ";;")
+ impldef: "impl" ident type [auxtypes] [traitspec] ("\n" | "=" implbody ";;")
implbody: "\n"* (ident [":" type] "=" expr "\n"*)*
/* types */
- tydef: "type" typeid "=" type
+ traitspec: "::" traitvar+
+ traitvar: name+ type ["->" type]
+ tydef: "type" typeid [traitspec] "=" type
typeid: ident | ident "(" typarams ")"
typarams: typaram ("," typaram)*
type: structdef | uniondef | tupledef |
@@ -1984,8 +1979,7 @@
uniondef: "union" unionbody ";;"
unionbody: ("`" ident [type])*
tupledef: "(" type ("," type)* ")"
- generic: typaram ["::" traitlist]
- traitlist: name | "(" name ("," name)
+ generic: typaram
constructed: functype | sicetype | arraytype | ptrtype | void | name
functype: "(" arglist "->" type ")"
arglist: [arg ("," arg)*]
@@ -2024,7 +2018,7 @@
/* literals */
literal: funclit | seqlit | tuplit | simplelit
- funclit: "{" [funcargs] ";" blockbody "}"
+ funclit: "{" [funcargs] [traitspec] "\n" blockbody "}"
funcargs: ident [ ":" type] ("," ident [ ":" type])*
seqlit: "[" structelts | [arrayelts] "]"
arrayelts: arrayelt ("," arrayelt)*
--- a/lib/bio/bio.myr
+++ b/lib/bio/bio.myr
@@ -283,7 +283,7 @@
writes a single integer-like value to the output stream, in
little endian format
*/
-generic putle = {f, v : @a::(numeric,integral)
+generic putle = {f, v : @a :: numeric,integral @a
for var i = 0; i < sizeof(@a); i++
putb(f, (v & 0xff : byte))
v >>= 8
@@ -295,7 +295,7 @@
writes a single integer-like value to the output stream, in
big endian format
*/
-generic putbe = {f, v : @a::(numeric,integral)
+generic putbe = {f, v : @a :: numeric,integral @a
for var i = sizeof(@a); i != 0; i--
putb(f, ((v >> ((i-1)*8)) & 0xff : byte))
;;
--- a/lib/bio/geti.myr
+++ b/lib/bio/geti.myr
@@ -5,16 +5,16 @@
pkg bio =
/* unsigned big endian */
- generic getbe8 : (f : file# -> std.result(@a::(numeric,integral), err))
- generic getbe16 : (f : file# -> std.result(@a::(numeric,integral), err))
- generic getbe32 : (f : file# -> std.result(@a::(numeric,integral), err))
- generic getbe64 : (f : file# -> std.result(@a::(numeric,integral), err))
+ generic getbe8 : (f : file# -> std.result(@a, err)) :: numeric,integral @a
+ generic getbe16 : (f : file# -> std.result(@a, err)) :: numeric,integral @a
+ generic getbe32 : (f : file# -> std.result(@a, err)) :: numeric,integral @a
+ generic getbe64 : (f : file# -> std.result(@a, err)) :: numeric,integral @a
/* signed big endian */
- generic getle8 : (f : file# -> std.result(@a::(numeric,integral), err))
- generic getle16 : (f : file# -> std.result(@a::(numeric,integral), err))
- generic getle32 : (f : file# -> std.result(@a::(numeric,integral), err))
- generic getle64 : (f : file# -> std.result(@a::(numeric,integral), err))
+ generic getle8 : (f : file# -> std.result(@a, err)) :: numeric,integral @a
+ generic getle16 : (f : file# -> std.result(@a, err)) :: numeric,integral @a
+ generic getle32 : (f : file# -> std.result(@a, err)) :: numeric,integral @a
+ generic getle64 : (f : file# -> std.result(@a, err)) :: numeric,integral @a
;;
/*
@@ -21,7 +21,7 @@
reads a single integer-like value to the output stream, in
little endian format
*/
-generic getle = {f, n -> std.result(@a::(numeric,integral), err)
+generic getle = {f, n -> std.result(@a, err) :: numeric,integral @a
match ensureread(f, n)
| `std.Err e : -> `std.Err e
| `std.Ok _:
@@ -29,7 +29,7 @@
for var i = 0; i < n; i++
v |= (f.rbuf[f.rstart++] : uint64) << (8*(i : uint64))
;;
- -> `std.Ok (v : @a::(numeric,integral))
+ -> `std.Ok (v : @a)
;;
}
@@ -37,7 +37,7 @@
reads a single integer-like value to the output stream, in
big endian format
*/
-generic getbe = {f, n -> std.result(@a::(numeric,integral), err)
+generic getbe = {f, n -> std.result(@a, err) :: numeric,integral @a
match ensureread(f, n)
| `std.Err e : -> `std.Err e
| `std.Ok _:
@@ -46,7 +46,7 @@
v <<= 8
v |= (f.rbuf[f.rstart++] : uint64)
;;
- -> `std.Ok (v : @a::(numeric,integral))
+ -> `std.Ok (v : @a)
;;
}
--- a/lib/bio/puti.myr
+++ b/lib/bio/puti.myr
@@ -5,16 +5,16 @@
pkg bio =
/* unsigned big endian */
- generic putbe8 : (f : file#, v : @a::(numeric,integral) -> std.result(std.size, err))
- generic putbe16 : (f : file#, v : @a::(numeric,integral) -> std.result(std.size, err))
- generic putbe32 : (f : file#, v : @a::(numeric,integral) -> std.result(std.size, err))
- generic putbe64 : (f : file#, v : @a::(numeric,integral) -> std.result(std.size, err))
+ generic putbe8 : (f : file#, v : @a -> std.result(std.size, err)) :: numeric,integral @a
+ generic putbe16 : (f : file#, v : @a -> std.result(std.size, err)) :: numeric,integral @a
+ generic putbe32 : (f : file#, v : @a -> std.result(std.size, err)) :: numeric,integral @a
+ generic putbe64 : (f : file#, v : @a -> std.result(std.size, err)) :: numeric,integral @a
/* unsigned little endian */
- generic putle8 : (f : file#, v : @a::(numeric,integral) -> std.result(std.size, err))
- generic putle16 : (f : file#, v : @a::(numeric,integral) -> std.result(std.size, err))
- generic putle32 : (f : file#, v : @a::(numeric,integral) -> std.result(std.size, err))
- generic putle64 : (f : file#, v : @a::(numeric,integral) -> std.result(std.size, err))
+ generic putle8 : (f : file#, v : @a -> std.result(std.size, err)) :: numeric,integral @a
+ generic putle16 : (f : file#, v : @a -> std.result(std.size, err)) :: numeric,integral @a
+ generic putle32 : (f : file#, v : @a -> std.result(std.size, err)) :: numeric,integral @a
+ generic putle64 : (f : file#, v : @a -> std.result(std.size, err)) :: numeric,integral @a
;;
generic putbe8 = {f, v; -> putbe(f, (v : uint64), 1)}
--- a/lib/crypto/rand.myr
+++ b/lib/crypto/rand.myr
@@ -8,8 +8,8 @@
pkg crypto =
/* designed to mirror std.rand() */
const randbytes : (buf : byte[:] -> void)
- generic rand : (lo : @a::(integral,numeric), hi : @a::(integral,numeric) -> @a::(numeric,integral))
- generic randnum : (-> @a::(numeric,integral))
+ generic rand : (lo : @a, hi : @a -> @a) ::numeric,integral @a
+ generic randnum : (-> @a) :: numeric,integral @a
;;
const Stirinterval = 16*std.MiB
--- a/lib/date/parse.myr
+++ b/lib/date/parse.myr
@@ -239,9 +239,8 @@
-> s
;;
}
-generic intval = {dst : @a::(numeric,integral)#, s : byte[:], \
- min : @a::(numeric,integral), max : @a::(numeric,integral), \
- err : std.option(parsefail)# -> byte[:]
+
+generic intval = {dst : @a#, s : byte[:], min : @a, max : @a, err : std.option(parsefail)# -> byte[:] :: numeric,integral @a
var i, c, num
num = s
--- a/lib/iter/bld.sub
+++ b/lib/iter/bld.sub
@@ -9,3 +9,9 @@
lib ../sys:sys
lib ../std:std
;;
+
+testdeps =
+ ../testr:testr
+ ../sys:sys
+ ../std:std
+;;
--- a/lib/std/bigint.myr
+++ b/lib/std/bigint.myr
@@ -22,7 +22,7 @@
;;
/* administrivia */
- generic mkbigint : (v : @a::(numeric,integral) -> bigint#)
+ generic mkbigint : (v : @a -> bigint#) :: numeric,integral @a
const bigfrombytes : (isneg : bool, v : byte[:] -> bigint#)
const bigfree : (a : bigint# -> void)
const bigdup : (a : bigint# -> bigint#)
@@ -40,7 +40,7 @@
const bigiszero : (a : bigint# -> bool)
const bigiseven : (a : bigint# -> bool)
const bigcmp : (a : bigint#, b : bigint# -> order)
- generic bigcmpi : (a : bigint#, b : @a::(numeric,integral) -> order)
+ generic bigcmpi : (a : bigint#, b : @a -> order) :: numeric,integral @a
/* shorthand for comparisons */
const bigeq : (a : bigint#, b : bigint# -> bool)
@@ -48,11 +48,11 @@
const bigle : (a : bigint#, b : bigint# -> bool)
const biggt : (a : bigint#, b : bigint# -> bool)
const bigge : (a : bigint#, b : bigint# -> bool)
- generic bigeqi : (a : bigint#, b : @a::(numeric,integral) -> bool)
- generic biglti : (a : bigint#, b : @a::(numeric,integral) -> bool)
- generic biglei : (a : bigint#, b : @a::(numeric,integral) -> bool)
- generic biggti : (a : bigint#, b : @a::(numeric,integral) -> bool)
- generic biggei : (a : bigint#, b : @a::(numeric,integral) -> bool)
+ generic bigeqi : (a : bigint#, b : @a -> bool) :: numeric,integral @a
+ generic biglti : (a : bigint#, b : @a -> bool) :: numeric,integral @a
+ generic biglei : (a : bigint#, b : @a -> bool) :: numeric,integral @a
+ generic biggti : (a : bigint#, b : @a -> bool) :: numeric,integral @a
+ generic biggei : (a : bigint#, b : @a -> bool) :: numeric,integral @a
/* bigint*bigint -> bigint ops */
const bigadd : (a : bigint#, b : bigint# -> bigint#)
@@ -71,15 +71,15 @@
/* bigint*int -> bigint ops */
- generic bigaddi : (a : bigint#, b : @a::(integral,numeric) -> bigint#)
- generic bigsubi : (a : bigint#, b : @a::(integral,numeric) -> bigint#)
- generic bigmuli : (a : bigint#, b : @a::(integral,numeric) -> bigint#)
- generic bigdivi : (a : bigint#, b : @a::(integral,numeric) -> bigint#)
- generic bigmodi : (a : bigint#, b : @a::(integral,numeric) -> bigint#)
- generic bigshli : (a : bigint#, b : @a::(integral,numeric) -> bigint#)
- generic bigshri : (a : bigint#, b : @a::(integral,numeric) -> bigint#)
- generic bigandi : (a : bigint#, b : @a::(integral,numeric) -> bigint#)
- generic bigori : (a : bigint#, b : @a::(integral,numeric) -> bigint#)
+ generic bigaddi : (a : bigint#, b : @a -> bigint#) :: integral,numeric @a
+ generic bigsubi : (a : bigint#, b : @a -> bigint#) :: integral,numeric @a
+ generic bigmuli : (a : bigint#, b : @a -> bigint#) :: integral,numeric @a
+ generic bigdivi : (a : bigint#, b : @a -> bigint#) :: integral,numeric @a
+ generic bigmodi : (a : bigint#, b : @a -> bigint#) :: integral,numeric @a
+ generic bigshli : (a : bigint#, b : @a -> bigint#) :: integral,numeric @a
+ generic bigshri : (a : bigint#, b : @a -> bigint#) :: integral,numeric @a
+ generic bigandi : (a : bigint#, b : @a -> bigint#) :: integral,numeric @a
+ generic bigori : (a : bigint#, b : @a -> bigint#) :: integral,numeric @a
//const bigpowi : (a : bigint#, b : uint64 -> bigint#)
//const bigmodpowi : (b : bigint#, e : bigint#, m : bigint# -> bigint#)
@@ -93,7 +93,7 @@
const Base = 0x100000000ul
-generic mkbigint = {v : @a::(integral,numeric)
+generic mkbigint = {v : @a :: integral,numeric @a
var a
var val
@@ -771,7 +771,7 @@
-> a
}
-generic bigsubi = {a, b : @a::(numeric,integral)
+generic bigsubi = {a, b : @a :: numeric,integral @a
var bigb : bigint
var dig : uint32[2]
@@ -811,7 +811,7 @@
a << s, with integer arg.
logical left shift. any other type would be illogical.
*/
-generic bigshli = {a, s : @a::(numeric,integral)
+generic bigshli = {a, s : @a :: numeric,integral @a
var off, shift
var t, carry
--- a/lib/std/bitset.myr
+++ b/lib/std/bitset.myr
@@ -22,9 +22,9 @@
const bsmax : (a : bitset# -> size)
const bscount : (a : bitset# -> size)
- generic bsput : (bs : bitset#, v : @a::(integral,numeric) -> bool)
- generic bsdel : (bs : bitset#, v : @a::(integral,numeric) -> bool)
- generic bshas : (bs : bitset#, v : @a::(integral,numeric) -> bool)
+ generic bsput : (bs : bitset#, v : @a -> bool) :: integral,numeric @a
+ generic bsdel : (bs : bitset#, v : @a -> bool) :: integral,numeric @a
+ generic bshas : (bs : bitset#, v : @a -> bool) :: integral,numeric @a
const bsdiff : (a : bitset#, b : bitset# -> void)
const bsintersect : (a : bitset#, b : bitset# -> void)
--- a/lib/std/chartype.myr
+++ b/lib/std/chartype.myr
@@ -25,7 +25,7 @@
const toupper : (c : char -> char)
const totitle : (c : char -> char)
- generic charval : (c : char, base : int -> @a::(integral,numeric))
+ generic charval : (c : char, base : int -> @a) :: integral,numeric @a
const cellwidth : (c : char -> int)
;;
@@ -1670,18 +1670,18 @@
-> c
}
-generic charval = {c, base -> @a::(numeric,integral)
+generic charval = {c, base -> @a :: numeric,integral @a
var v = -1
if c >= '0' && c <= '9'
- v = (c - '0' : @a::(integral,numeric))
+ v = (c - '0' : @a)
elif c >= 'a' && c <= 'z'
- v = (c - 'a' + 10 : @a::(integral,numeric))
+ v = (c - 'a' + 10 : @a)
elif c >= 'A' && c <= 'Z'
- v = (c - 'A' + 10 : @a::(integral,numeric))
+ v = (c - 'A' + 10 : @a)
;;
- if v < 0 || v >= (base : @a::(integral,numeric))
+ if v < 0 || v >= (base : @a)
-> -1
;;
-> v
--- a/lib/std/endian.myr
+++ b/lib/std/endian.myr
@@ -1,16 +1,16 @@
pkg std =
- generic hosttonet : (v : @a::(integral,numeric) -> @a::(integral,numeric))
- generic nettohost : (v : @a::(integral,numeric) -> @a::(integral,numeric))
+ generic hosttonet : (v : @a -> @a) :: integral,numeric @a
+ generic nettohost : (v : @a -> @a) :: integral,numeric @a
;;
/* FIXME: we only support little endian platforms right now,
so we assume a little endian machine. FIX THIS. */
-generic hosttonet = {v : @a::(integral,numeric)
+generic hosttonet = {v : @a :: integral,numeric @a
var i
var ret
ret = 0
- for i = 0; i < sizeof(@a::(integral,numeric)); i++
+ for i = 0; i < sizeof(@a); i++
ret <<= 8
ret |= v & 0xff
v >>= 8
@@ -18,12 +18,12 @@
-> ret
}
-generic nettohost = {v : @a::(integral,numeric)
+generic nettohost = {v : @a :: integral,numeric @a
var i
var ret
ret = 0
- for i = 0; i < sizeof(@a::(integral,numeric)); i++
+ for i = 0; i < sizeof(@a); i++
ret <<= 8
ret |= v & 0xff
v >>= 8
--- a/lib/std/extremum.myr
+++ b/lib/std/extremum.myr
@@ -1,8 +1,8 @@
pkg std =
- generic min : (a : @a::numeric, b : @a::numeric -> @a::numeric)
- generic max : (a : @a::numeric, b : @a::numeric -> @a::numeric)
- generic clamp : (a : @a::numeric, min : @a::numeric, max : @a::numeric -> @a::numeric)
- generic abs : (a : @a::numeric -> @a::numeric)
+ generic min : (a : @a, b : @a -> @a) :: numeric @a
+ generic max : (a : @a, b : @a -> @a) :: numeric @a
+ generic clamp : (a : @a, min : @a, max : @a -> @a) :: numeric @a
+ generic abs : (a : @a -> @a) :: numeric @a
;;
generic min = {a, b
@@ -31,8 +31,8 @@
;;
}
-generic abs = {a : @a::numeric
- if a < (0 : @a::numeric)
+generic abs = {a : @a :: numeric @a
+ if a < (0 : @a)
-> -a
else
-> a
--- a/lib/std/fltbits.myr
+++ b/lib/std/fltbits.myr
@@ -6,7 +6,7 @@
const flt32inf : (-> flt32)
const flt32nan : (-> flt32)
- generic isnan : (f : @a::floating -> bool)
+ generic isnan : (f : @a -> bool) ::floating @a
const flt64frombits : (bits : uint64 -> flt64)
const flt32frombits : (bits : uint32 -> flt32)
const flt64explode : (flt : flt64 -> (bool, int64, int64))
--- a/lib/std/fmt.myr
+++ b/lib/std/fmt.myr
@@ -537,7 +537,7 @@
'5','6','7','8','9',
'a','b','c','d','e','f'
]
-generic intfmt = {sb, opts, signed, bits : @a::(integral,numeric)
+generic intfmt = {sb, opts, signed, bits : @a :: integral,numeric @a
var isneg
var sval, val
var b : char[32]
@@ -557,7 +557,7 @@
;;
else
val = (bits : uint64)
- val &= ~0 >> (8*(sizeof(uint64)-sizeof(@a::(integral,numeric))))
+ val &= ~0 >> (8*(sizeof(uint64)-sizeof(@a)))
isneg = false
;;
--- a/lib/std/fndup.myr
+++ b/lib/std/fndup.myr
@@ -5,10 +5,10 @@
use "types"
pkg std =
- generic fnenvsz : (fn : @fn::function -> size)
- generic fndup : (fn : @fn::function -> @fn::function)
- generic fnbdup : (fn : @fn::function, buf : byte[:] -> @fn::function)
- generic fnfree : (fn : @fn::function -> void)
+ generic fnenvsz : (fn : @fn -> size) :: function @fn
+ generic fndup : (fn : @fn -> @fn) :: function @fn
+ generic fnbdup : (fn : @fn, buf : byte[:] -> @fn) :: function @fn
+ generic fnfree : (fn : @fn -> void) :: function @fn
;;
generic fndup = {fn
@@ -27,7 +27,7 @@
extern const put : (fmt : byte[:], args : ... -> int64)
-generic fnbdup = {fn, buf
+generic fnbdup = {fn : @fn, buf :: function @fn
var repr : intptr[2]
var env
@@ -35,7 +35,7 @@
env = envslice(repr[0])
slcp(buf[:env.len], env)
repr[0] = (buf : intptr)
- -> (&repr : @fn::function#)#
+ -> (&repr : @fn#)#
}
generic fnfree = {fn
--- a/lib/std/getint.myr
+++ b/lib/std/getint.myr
@@ -2,95 +2,95 @@
use "memops"
pkg std =
- generic gethost64 : (buf : byte[:] -> @a::(numeric,integral))
- generic getle64 : (buf : byte[:] -> @a::(numeric,integral))
- generic getbe64 : (buf : byte[:] -> @a::(numeric,integral))
- generic gethost32 : (buf : byte[:] -> @a::(numeric,integral))
- generic getle32 : (buf : byte[:] -> @a::(numeric,integral))
- generic getbe32 : (buf : byte[:] -> @a::(numeric,integral))
- generic gethost16 : (buf : byte[:] -> @a::(numeric,integral))
- generic getle16 : (buf : byte[:] -> @a::(numeric,integral))
- generic getbe16 : (buf : byte[:] -> @a::(numeric,integral))
- generic gethost8 : (buf : byte[:] -> @a::(numeric,integral))
- generic getle8 : (buf : byte[:] -> @a::(numeric,integral))
- generic getbe8 : (buf : byte[:] -> @a::(numeric,integral))
+ generic gethost64 : (buf : byte[:] -> @a) :: numeric,integral @a
+ generic getle64 : (buf : byte[:] -> @a) :: numeric,integral @a
+ generic getbe64 : (buf : byte[:] -> @a) :: numeric,integral @a
+ generic gethost32 : (buf : byte[:] -> @a) :: numeric,integral @a
+ generic getle32 : (buf : byte[:] -> @a) :: numeric,integral @a
+ generic getbe32 : (buf : byte[:] -> @a) :: numeric,integral @a
+ generic gethost16 : (buf : byte[:] -> @a) :: numeric,integral @a
+ generic getle16 : (buf : byte[:] -> @a) :: numeric,integral @a
+ generic getbe16 : (buf : byte[:] -> @a) :: numeric,integral @a
+ generic gethost8 : (buf : byte[:] -> @a) :: numeric,integral @a
+ generic getle8 : (buf : byte[:] -> @a) :: numeric,integral @a
+ generic getbe8 : (buf : byte[:] -> @a) :: numeric,integral @a
;;
-generic gethost64 = {buf -> @a::(numeric,integral)
+generic gethost64 = {buf -> @a :: numeric,integral @a
var val : int64
iassert(buf.len >= 8, "gethost64: index out of bounds")
memblit((&val : byte#), (buf : byte#), 8)
- -> (val : @a::(numeric,integral))
+ -> (val : @a)
}
-generic getbe64 = {buf -> @a::(numeric,integral)
- -> ((buf[0] : @a::(numeric,integral)) << 56) | \
- ((buf[1] : @a::(numeric,integral)) << 48) | \
- ((buf[2] : @a::(numeric,integral)) << 40) | \
- ((buf[3] : @a::(numeric,integral)) << 32) | \
- ((buf[4] : @a::(numeric,integral)) << 24) | \
- ((buf[5] : @a::(numeric,integral)) << 16) | \
- ((buf[6] : @a::(numeric,integral)) << 8) | \
- ((buf[7] : @a::(numeric,integral)) << 0)
+generic getbe64 = {buf -> @a :: numeric,integral @a
+ -> ((buf[0] : @a) << 56) | \
+ ((buf[1] : @a) << 48) | \
+ ((buf[2] : @a) << 40) | \
+ ((buf[3] : @a) << 32) | \
+ ((buf[4] : @a) << 24) | \
+ ((buf[5] : @a) << 16) | \
+ ((buf[6] : @a) << 8) | \
+ ((buf[7] : @a) << 0)
}
generic getle64 = {buf
- -> ((buf[0] : @a::(numeric,integral)) << 0) | \
- ((buf[1] : @a::(numeric,integral)) << 8) | \
- ((buf[2] : @a::(numeric,integral)) << 16) | \
- ((buf[3] : @a::(numeric,integral)) << 24) | \
- ((buf[4] : @a::(numeric,integral)) << 32) | \
- ((buf[5] : @a::(numeric,integral)) << 40) | \
- ((buf[6] : @a::(numeric,integral)) << 48) | \
- ((buf[7] : @a::(numeric,integral)) << 56)
+ -> ((buf[0] : @a) << 0) | \
+ ((buf[1] : @a) << 8) | \
+ ((buf[2] : @a) << 16) | \
+ ((buf[3] : @a) << 24) | \
+ ((buf[4] : @a) << 32) | \
+ ((buf[5] : @a) << 40) | \
+ ((buf[6] : @a) << 48) | \
+ ((buf[7] : @a) << 56)
}
-generic gethost32 = {buf -> @a::(numeric,integral)
+generic gethost32 = {buf -> @a :: numeric,integral @a
var val : int32
iassert(buf.len >= 4, "gethost32: index out of bounds")
memblit((&val : byte#), (buf : byte#), 4)
- -> (val : @a::(numeric,integral))
+ -> (val : @a)
}
-generic getbe32 = {buf
- -> ((buf[0] : @a::(numeric,integral)) << 24) | \
- ((buf[1] : @a::(numeric,integral)) << 16) | \
- ((buf[2] : @a::(numeric,integral)) << 8) | \
- ((buf[3] : @a::(numeric,integral)) << 0)
+generic getbe32 = {buf -> @a :: numeric, integral @a
+ -> ((buf[0] : @a) << 24) | \
+ ((buf[1] : @a) << 16) | \
+ ((buf[2] : @a) << 8) | \
+ ((buf[3] : @a) << 0)
}
-generic getle32 = {buf
- -> ((buf[0] : @a::(numeric,integral)) << 0) | \
- ((buf[1] : @a::(numeric,integral)) << 8) | \
- ((buf[2] : @a::(numeric,integral)) << 16) | \
- ((buf[3] : @a::(numeric,integral)) << 24)
+generic getle32 = {buf -> @a :: numeric, integral @a
+ -> ((buf[0] : @a) << 0) | \
+ ((buf[1] : @a) << 8) | \
+ ((buf[2] : @a) << 16) | \
+ ((buf[3] : @a) << 24)
}
-generic gethost16 = {buf -> @a::(numeric,integral)
+generic gethost16 = {buf -> @a :: numeric,integral @a
var val : int16
iassert(buf.len >= 2, "gethost16: index out of bounds")
memblit((&val : byte#), (buf : byte#), 4)
- -> (val : @a::(numeric,integral))
+ -> (val : @a)
}
-generic getbe16 = {buf
- -> ((buf[0] : @a::(numeric,integral)) << 8) | \
- ((buf[1] : @a::(numeric,integral)) << 0)
+generic getbe16 = {buf -> @a :: numeric,integral @a
+ -> ((buf[0] : @a) << 8) | \
+ ((buf[1] : @a) << 0)
}
-generic getle16 = {buf
- -> ((buf[0] : @a::(numeric,integral)) << 0) | \
- ((buf[1] : @a::(numeric,integral)) << 8)
+generic getle16 = {buf -> @a :: numeric,integral @a
+ -> ((buf[0] : @a) << 0) | \
+ ((buf[1] : @a) << 8)
}
-generic gethost8 = {buf
- -> (buf[0] : @a::(numeric,integral)) << 0
+generic gethost8 = {buf -> @a :: numeric,integral @a
+ -> (buf[0] : @a) << 0
}
-generic getbe8 = {buf
- -> (buf[0] : @a::(numeric,integral)) << 0
+generic getbe8 = {buf -> @a :: numeric,integral @a
+ -> (buf[0] : @a) << 0
}
-generic getle8 = {buf
- -> (buf[0] : @a::(numeric,integral)) << 0
+generic getle8 = {buf -> @a :: numeric,integral @a
+ -> (buf[0] : @a) << 0
}
--- a/lib/std/hashfuncs.myr
+++ b/lib/std/hashfuncs.myr
@@ -23,13 +23,13 @@
}
;;
- impl equatable @a::(integral,numeric) =
+ impl equatable @a :: integral,numeric @a =
eq = {a, b
-> a == b
}
;;
- impl hashable @a::(integral,numeric) =
+ impl hashable @a :: integral,numeric @a =
hash = {a
-> siphash24((&a : byte#)[:sizeof(@a)], Seed)
}
--- a/lib/std/intparse.myr
+++ b/lib/std/intparse.myr
@@ -7,8 +7,8 @@
use "utf"
pkg std =
- generic intparsebase : (s : byte[:], base : int -> option(@a::(integral,numeric)))
- generic intparse : (s : byte[:] -> option(@a::(integral,numeric)))
+ generic intparsebase : (s : byte[:], base : int -> option(@a)) :: integral,numeric @a
+ generic intparse : (s : byte[:] -> option(@a)) :: integral,numeric @a
;;
generic intparse = {s
@@ -47,7 +47,7 @@
-> doparse(s, isneg, base)
}
-generic doparse = {s, isneg, base -> option(@a::(integral,numeric))
+generic doparse = {s, isneg, base -> option(@a) :: integral,numeric @a
var v
var cv : int32
@@ -58,8 +58,8 @@
;;
cv = charval(c, base)
if cv >= 0
- v *= (base : @a::(integral,numeric))
- v += (cv : @a::(integral,numeric))
+ v *= (base : @a)
+ v += (cv : @a)
else
-> `None
;;
--- a/lib/std/ipparse.myr
+++ b/lib/std/ipparse.myr
@@ -116,7 +116,7 @@
;;
}
-generic num = {ip, lo, hi, base, sep, ok -> (@a::(numeric,integral), byte[:], bool)
+generic num = {ip, lo, hi, base, sep, ok -> (@a, byte[:], bool) :: numeric,integral @a
var len
if !ok
@@ -133,7 +133,7 @@
if v < lo || v > hi
-> (0, "", false)
;;
- -> ((v : @a::(numeric,integral)), ip[len:], true)
+ -> ((v : @a), ip[len:], true)
| `std.None:
-> (0, "", false)
;;
--- a/lib/std/putint.myr
+++ b/lib/std/putint.myr
@@ -3,21 +3,21 @@
use "types"
pkg std =
- generic puthost64 : (buf : byte[:], v : @a::(numeric,integral) -> size)
- generic putle64 : (buf : byte[:], v : @a::(numeric,integral) -> size)
- generic putbe64 : (buf : byte[:], v : @a::(numeric,integral) -> size)
- generic puthost32 : (buf : byte[:], v : @a::(numeric,integral) -> size)
- generic putle32 : (buf : byte[:], v : @a::(numeric,integral) -> size)
- generic putbe32 : (buf : byte[:], v : @a::(numeric,integral) -> size)
- generic puthost16 : (buf : byte[:], v : @a::(numeric,integral) -> size)
- generic putle16 : (buf : byte[:], v : @a::(numeric,integral) -> size)
- generic putbe16 : (buf : byte[:], v : @a::(numeric,integral) -> size)
- generic puthost8 : (buf : byte[:], v : @a::(numeric,integral) -> size)
- generic putle8 : (buf : byte[:], v : @a::(numeric,integral) -> size)
- generic putbe8 : (buf : byte[:], v : @a::(numeric,integral) -> size)
+ generic puthost64 : (buf : byte[:], v : @a -> size) :: numeric,integral @a
+ generic putle64 : (buf : byte[:], v : @a -> size) :: numeric,integral @a
+ generic putbe64 : (buf : byte[:], v : @a -> size) :: numeric,integral @a
+ generic puthost32 : (buf : byte[:], v : @a -> size) :: numeric,integral @a
+ generic putle32 : (buf : byte[:], v : @a -> size) :: numeric,integral @a
+ generic putbe32 : (buf : byte[:], v : @a -> size) :: numeric,integral @a
+ generic puthost16 : (buf : byte[:], v : @a -> size) :: numeric,integral @a
+ generic putle16 : (buf : byte[:], v : @a -> size) :: numeric,integral @a
+ generic putbe16 : (buf : byte[:], v : @a -> size) :: numeric,integral @a
+ generic puthost8 : (buf : byte[:], v : @a -> size) :: numeric,integral @a
+ generic putle8 : (buf : byte[:], v : @a -> size) :: numeric,integral @a
+ generic putbe8 : (buf : byte[:], v : @a -> size) :: numeric,integral @a
;;
-generic puthost = {buf, val : @a::(integral, numeric)
+generic puthost = {buf, val : @a :: integral, numeric @a
iassert(buf.len >= sizeof(@a), "buffer too small")
memblit((buf : byte#), (&val : byte#), sizeof(@a))
-> sizeof(@a)
--- a/lib/std/rand.myr
+++ b/lib/std/rand.myr
@@ -13,12 +13,12 @@
const mksrng : (seed : uint32 -> rng#)
const freerng : (rng : rng# -> void)
- generic rand : (lo : @a::(numeric,integral), hi : @a::(numeric,integral) -> @a::(numeric,integral))
- generic randnum : (-> @a::(numeric,integral))
+ generic rand : (lo : @a, hi : @a -> @a) :: numeric,integral @a
+ generic randnum : (-> @a) :: numeric,integral @a
const randbytes : (buf : byte[:] -> void)
- generic rngrand : (rng : rng#, lo : @a::(numeric,integral), hi : @a::(numeric,integral) -> @a::(numeric,integral))
- generic rngrandnum : (rng : rng# -> @a::(numeric,integral))
+ generic rngrand : (rng : rng#, lo : @a, hi : @a -> @a) ::numeric,integral @a
+ generic rngrandnum : (rng : rng# -> @a) :: numeric,integral @a
const rngrandbytes : (rng : rng#, buf : byte[:] -> void)
;;
@@ -90,7 +90,7 @@
See http://xoroshiro.di.unimi.it/ for details.
*/
-generic rngrandnum = {rng -> @a::(numeric,integral)
+generic rngrandnum = {rng -> @a :: numeric,integral @a
var s0, s1, r
s0 = rng.s0
@@ -101,5 +101,5 @@
rng.s0 = (s0 << 55 | s0 >> 9) ^ s1 ^ (s1 << 14)
rng.s1 = (s1 << 36 | s1 >> 28)
- -> (r : @a::(numeric,integral))
+ -> (r : @a)
}
--- a/lib/std/search.myr
+++ b/lib/std/search.myr
@@ -3,8 +3,8 @@
use "types"
pkg std =
- generic lsearch : (sl : @t[:], key : @k, cmp : (v : @t, k : @k -> order) -> option(@idx::(integral,numeric)))
- generic bsearch : (sl : @t[:], key : @k, cmp : (v : @t, k : @k -> order) -> option(@idx::(integral,numeric)))
+ generic lsearch : (sl : @t[:], key : @k, cmp : (v : @t, k : @k -> order) -> option(@idx)) :: integral,numeric @idx
+ generic bsearch : (sl : @t[:], key : @k, cmp : (v : @t, k : @k -> order) -> option(@idx)) :: integral,numeric @idx
;;
/* linear search over a list of values */
--- a/lib/std/syswrap+plan9.myr
+++ b/lib/std/syswrap+plan9.myr
@@ -261,7 +261,7 @@
}
*/
-generic check = {e : @a::(integral, numeric) -> result(@b, errno)
+generic check = {e : @a -> result(@b, errno) :: integral, numeric @a
if e < 0
-> `Err lasterr()
else
@@ -270,25 +270,25 @@
}
/* duplicated code to break dependency cycle */
-generic _getle16 = {buf -> @a::(numeric,integral)
- -> ((buf[0] : @a::(numeric,integral)) << 0) | \
- ((buf[1] : @a::(numeric,integral)) << 8)
+generic _getle16 = {buf -> @a :: numeric,integral @a
+ -> ((buf[0] : @a) << 0) | \
+ ((buf[1] : @a) << 8)
}
-generic _getle32 = {buf -> @a::(numeric,integral)
- -> ((buf[0] : @a::(numeric,integral)) << 0) | \
- ((buf[1] : @a::(numeric,integral)) << 8) | \
- ((buf[2] : @a::(numeric,integral)) << 16) | \
- ((buf[3] : @a::(numeric,integral)) << 24)
+generic _getle32 = {buf -> @a :: numeric,integral @a
+ -> ((buf[0] : @a) << 0) | \
+ ((buf[1] : @a) << 8) | \
+ ((buf[2] : @a) << 16) | \
+ ((buf[3] : @a) << 24)
}
-generic _getle64 = {buf -> @a::(numeric,integral)
- -> ((buf[0] : @a::(numeric,integral)) << 0) | \
- ((buf[1] : @a::(numeric,integral)) << 8) | \
- ((buf[2] : @a::(numeric,integral)) << 16) | \
- ((buf[3] : @a::(numeric,integral)) << 24) | \
- ((buf[4] : @a::(numeric,integral)) << 32) | \
- ((buf[5] : @a::(numeric,integral)) << 40) | \
- ((buf[6] : @a::(numeric,integral)) << 48) | \
- ((buf[7] : @a::(numeric,integral)) << 56)
+generic _getle64 = {buf -> @a :: numeric,integral @a
+ -> ((buf[0] : @a) << 0) | \
+ ((buf[1] : @a) << 8) | \
+ ((buf[2] : @a) << 16) | \
+ ((buf[3] : @a) << 24) | \
+ ((buf[4] : @a) << 32) | \
+ ((buf[5] : @a) << 40) | \
+ ((buf[6] : @a) << 48) | \
+ ((buf[7] : @a) << 56)
}
--- a/lib/std/syswrap+posixy.myr
+++ b/lib/std/syswrap+posixy.myr
@@ -179,7 +179,7 @@
;;
}
-generic check = {e : @a::(integral, numeric) -> result(@b, errno)
+generic check = {e : @a -> result(@b, errno) :: integral,numeric @a
if e < 0
-> `Err (e : errno)
else
--- a/lib/std/units.myr
+++ b/lib/std/units.myr
@@ -2,14 +2,14 @@
pkg std =
/* JEDEC 100B.1 memory sizes */
- generic KiB : @a::(integral,numeric) = 1024
- generic MiB : @a::(integral,numeric) = KiB*1024
- generic GiB : @a::(integral,numeric) = MiB*1024
- generic TiB : @a::(integral,numeric) = GiB*1024
- generic PiB : @a::(integral,numeric) = TiB*1024
- generic EiB : @a::(integral,numeric) = PiB*1024
- generic ZiB : @a::(integral,numeric) = EiB*1024
- generic YiB : @a::(integral,numeric) = ZiB*1024
+ generic KiB : @a = 1024 :: integral,numeric @a
+ generic MiB : @a = KiB*1024 :: integral,numeric @a
+ generic GiB : @a = MiB*1024 :: integral,numeric @a
+ generic TiB : @a = GiB*1024 :: integral,numeric @a
+ generic PiB : @a = TiB*1024 :: integral,numeric @a
+ generic EiB : @a = PiB*1024 :: integral,numeric @a
+ generic ZiB : @a = EiB*1024 :: integral,numeric @a
+ generic YiB : @a = ZiB*1024 :: integral,numeric @a
generic Sec : time = 1_000_000
generic Msec : time = 1_000
--- a/lib/thread/atomic.myr
+++ b/lib/thread/atomic.myr
@@ -1,7 +1,7 @@
use std
pkg thread =
- trait atomic @a::(integral,numeric) =
+ trait atomic @a :: integral,numeric @a =
xget : (p : @a# -> @a)
xset : (p : @a#, v : @a -> void)
xadd : (p : @a#, v : @a -> @a)
--- a/mbld/deps.myr
+++ b/mbld/deps.myr
@@ -19,8 +19,6 @@
`Ldep byte[:]
;;
-const Abiversion = 13
-
var usepat : regex.regex#
var cflagpat : regex.regex#
var clibpat : regex.regex#
--- a/mbld/libs.myr
+++ b/mbld/libs.myr
@@ -22,7 +22,7 @@
incs : byte[:][:] -> void)
;;
-const Abiversion = 14
+const Abiversion = 15
const builtlib = {b, mt, dep, dyndep
var ldep, l, u
--- a/parse/export.c
+++ b/parse/export.c
@@ -71,11 +71,15 @@
{
size_t i;
- if (t->vis != Visintern)
+ if (!t || t->vis != Visintern)
return;
t->vis = Vishidden;
for (i = 0; i < t->nsub; i++)
tagtype(st, t->sub[i], ingeneric, hidelocal);
+ for (i = 0; i < t->nspec; i++) {
+ tagtype(st, t->spec[i]->param, ingeneric, hidelocal);
+ tagtype(st, t->spec[i]->aux, ingeneric, hidelocal);
+ }
switch (t->type) {
case Tystruct:
for (i = 0; i < t->nmemb; i++)
@@ -259,7 +263,6 @@
free(k);
/* tag the traits */
- tr = NULL;
for (i = 0; i < ntraittab; i++) {
tr = traittab[i];
if (tr->vis != Visexport)
@@ -266,9 +269,12 @@
continue;
if (hidelocal && tr->ishidden)
tr->vis = Vishidden;
+ tagtype(st, tr->param, 0, hidelocal);
tr->param->vis = tr->vis;
- for (j = 0; j < tr->naux; j++)
+ for (j = 0; j < tr->naux; j++) {
+ tagtype(st, tr->aux[j], 0, hidelocal);
tr->aux[j]->vis = tr->vis;
+ }
for (j = 0; j < tr->nproto; j++) {
tr->proto[j]->decl.vis = tr->vis;
tagnode(st, tr->proto[j], 0, hidelocal);
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -18,10 +18,11 @@
#include "parse.h"
-Stab *curscope;
#define LBLSTKSZ 64
static Node **lbls[LBLSTKSZ];
static size_t nlbls[LBLSTKSZ];
+Stab *curscope;
+
/* the first time we see a label, we increment to 0 */
static int lbldepth = -1;
@@ -32,6 +33,7 @@
static Node *mkpseudodecl(Srcloc l, Type *t);
static void installucons(Stab *st, Type *t);
static void setattrs(Node *dcl, char **attrs, size_t nattrs);
+static void setwith(Type *ty, Traitspec **spec, size_t nspec);
static void setupinit(Node *n);
%}
@@ -132,7 +134,9 @@
%type <ty> type structdef uniondef tupledef compoundtype functype funcsig
%type <ty> generictype
%type <tylist> typelist typarams optauxtypes
-%type <nodelist> typaramlist
+%type <traitspecs> traitspec traits
+%type <traitspec> traitvar
+%type <nodelist> traitlist
%type <tok> asnop cmpop addop mulop shiftop optident obrace
@@ -207,6 +211,11 @@
Type **params;
size_t nparams;
} tydef;
+ struct {
+ Traitspec **spec;
+ size_t nspec;
+ } traitspecs;
+ Traitspec *traitspec;
Trait *trait;
Node *node;
Tok *tok;
@@ -254,7 +263,7 @@
| /* empty */
;
-decl : attrs Tvar decllist {
+decl : attrs Tvar decllist traitspec {
size_t i;
for (i = 0; i < $3.nn; i++)
@@ -261,7 +270,7 @@
setattrs($3.nl[i], $1.str, $1.nstr);
$$ = $3;
}
- | attrs Tconst decllist {
+ | attrs Tconst decllist traitspec {
size_t i;
for (i = 0; i < $3.nn; i++) {
setattrs($3.nl[i], $1.str, $1.nstr);
@@ -269,11 +278,12 @@
}
$$ = $3;
}
- | attrs Tgeneric decllist {
+ | attrs Tgeneric decllist traitspec {
size_t i;
for (i = 0; i < $3.nn; i++) {
setattrs($3.nl[i], $1.str, $1.nstr);
+ setwith($3.nl[i]->decl.type, $4.spec, $4.nspec);
$3.nl[i]->decl.isconst = 1;
$3.nl[i]->decl.isgeneric = 1;
}
@@ -288,6 +298,50 @@
}
;
+traitspec
+ : Twith traits {$$ = $2;}
+ | /* nothing */ {$$.nspec = 0;}
+ ;
+
+traits : traitvar {
+ $$.spec = NULL;
+ $$.nspec = 0;
+ lappend(&$$.spec, &$$.nspec, $1);
+ }
+ | traits listsep traitvar {
+ $$ = $1;
+ lappend(&$$.spec, &$$.nspec, $3);
+ }
+ ;
+
+traitvar
+ : traitlist generictype {
+ $$ = calloc(sizeof(Traitspec), 1);
+ $$->trait = $1.nl;
+ $$->ntrait = $1.nn;
+ $$->param = $2;
+ $$->aux = NULL;
+ }
+ | traitlist generictype Tret type {
+ $$ = calloc(sizeof(Traitspec), 1);
+ $$->trait = $1.nl;
+ $$->ntrait = $1.nn;
+ $$->param = $2;
+ $$->aux = $4;
+ }
+ ;
+
+traitlist
+ : name {
+ $$.nl = 0;
+ $$.nn = 0;
+ lappend(&$$.nl, &$$.nn, $1);
+ }
+ | traitlist listsep name {
+ lappend(&$$.nl, &$$.nn, $3);
+ }
+ ;
+
decllist: declbody {
$$.loc = $1->loc; $$.nl = NULL; $$.nn = 0;
lappend(&$$.nl, &$$.nn, $1);
@@ -388,12 +442,22 @@
;
implstmt
- : Timpl name type optauxtypes {
+ : Timpl name type optauxtypes traitspec {
+ size_t i;
+
$$ = mkimplstmt($1->loc, $2, $3, $4.types, $4.ntypes, NULL, 0);
$$->impl.isproto = 1;
+ setwith($3, $5.spec, $5.nspec);
+ for (i = 0; i < $4.ntypes; i++)
+ setwith($4.types[i], $5.spec, $5.nspec);
}
- | Timpl name type optauxtypes Tasn Tendln implbody Tendblk {
- $$ = mkimplstmt($1->loc, $2, $3, $4.types, $4.ntypes, $7.nl, $7.nn);
+ | Timpl name type optauxtypes traitspec Tasn Tendln implbody Tendblk {
+ size_t i;
+
+ $$ = mkimplstmt($1->loc, $2, $3, $4.types, $4.ntypes, $8.nl, $8.nn);
+ setwith($3, $5.spec, $5.nspec);
+ for (i = 0; i < $4.ntypes; i++)
+ setwith($4.types[i], $5.spec, $5.nspec);
}
;
@@ -411,25 +475,32 @@
;
traitdef
- : Ttrait Tident generictype optauxtypes { /* trait prototype */
+ : Ttrait Tident generictype optauxtypes traitspec { /* trait prototype */
+ size_t i;
$$ = mktrait($1->loc,
mkname($2->loc, $2->id), $3,
$4.types, $4.ntypes,
NULL, 0,
1);
+ setwith($3, $5.spec, $5.nspec);
+ for (i = 0; i < $4.ntypes; i++)
+ setwith($4.types[i], $5.spec, $5.nspec);
}
- | Ttrait Tident generictype optauxtypes Tasn traitbody Tendblk /* trait definition */ {
+ | Ttrait Tident generictype optauxtypes traitspec Tasn traitbody Tendblk /* trait definition */ {
size_t i;
$$ = mktrait($1->loc,
mkname($2->loc, $2->id), $3,
$4.types, $4.ntypes,
- $6.nl, $6.nn,
+ $7.nl, $7.nn,
0);
- for (i = 0; i < $6.nn; i++) {
- $6.nl[i]->decl.trait = $$;
- $6.nl[i]->decl.impls = mkht(tyhash, tyeq);
- $6.nl[i]->decl.isgeneric = 1;
+ for (i = 0; i < $7.nn; i++) {
+ $7.nl[i]->decl.trait = $$;
+ $7.nl[i]->decl.impls = mkht(tyhash, tyeq);
+ $7.nl[i]->decl.isgeneric = 1;
}
+ setwith($3, $5.spec, $5.nspec);
+ for (i = 0; i < $4.ntypes; i++)
+ setwith($4.types[i], $5.spec, $5.nspec);
}
;
@@ -452,14 +523,14 @@
;
-tydef : Ttype typeid {$$ = $2;}
- | Ttype typeid Tasn type {
+tydef : Ttype typeid traitspec {$$ = $2;}
+ | Ttype typeid traitspec Tasn type {
$$ = $2;
- if ($$.nparams == 0) {
- $$.type = mktyname($2.loc, mkname($2.loc, $2.name), $4);
- } else {
- $$.type = mktygeneric($2.loc, mkname($2.loc, $2.name), $2.params, $2.nparams, $4);
- }
+ if ($$.nparams == 0)
+ $$.type = mktyname($2.loc, mkname($2.loc, $2.name), $5);
+ else
+ $$.type = mktygeneric($2.loc, mkname($2.loc, $2.name), $2.params, $2.nparams, $5);
+ setwith($$.type, $3.spec, $3.nspec);
}
;
@@ -498,35 +569,17 @@
generictype
: Ttyparam {$$ = mktyparam($1->loc, $1->id);}
- | Ttyparam Twith name {
- $$ = mktyparam($1->loc, $1->id);
- lappend(&$$->traits, &$$->ntraits, $3);
- }
- | Ttyparam Twith Toparen typaramlist Tcparen {
- size_t i;
- $$ = mktyparam($1->loc, $1->id);
- for (i = 0; i < $4.nn; i++)
- lappend(&$$->traits, &$$->ntraits, $4.nl[i]);
- }
;
-typaramlist
- : name {
- $$.nl = NULL; $$.nn = 0;
- lappend(&$$.nl, &$$.nn, $1);
- }
- | typaramlist listsep name {lappend(&$$.nl, &$$.nn, $3);}
- ;
-
compoundtype
- : functype {$$ = $1;}
- | type Tosqbrac Tcolon Tcsqbrac {$$ = mktyslice($2->loc, $1);}
- | type Tosqbrac expr Tcsqbrac {$$ = mktyarray($2->loc, $1, $3);}
- | type Tosqbrac Tellipsis Tcsqbrac {$$ = mktyarray($2->loc, $1, NULL);}
- | name Toparen typelist Tcparen {$$ = mktyunres($1->loc, $1, $3.types, $3.ntypes);}
- | type Tderef {$$ = mktyptr($2->loc, $1);}
- | Tvoidlit {$$ = mktyunres($1->loc, mkname($1->loc, $1->id), NULL, 0);}
- | name {$$ = mktyunres($1->loc, $1, NULL, 0);}
+ : functype {$$ = $1;}
+ | type Tosqbrac Tcolon Tcsqbrac {$$ = mktyslice($2->loc, $1);}
+ | type Tosqbrac expr Tcsqbrac {$$ = mktyarray($2->loc, $1, $3);}
+ | type Tosqbrac Tellipsis Tcsqbrac {$$ = mktyarray($2->loc, $1, NULL);}
+ | name Toparen typelist Tcparen {$$ = mktyunres($1->loc, $1, $3.types, $3.ntypes);}
+ | type Tderef {$$ = mktyptr($2->loc, $1);}
+ | Tvoidlit {$$ = mktyunres($1->loc, mkname($1->loc, $1->id), NULL, 0);}
+ | name {$$ = mktyunres($1->loc, $1, NULL, 0);}
;
functype: Toparen funcsig Tcparen {$$ = $2;}
@@ -826,11 +879,13 @@
}
;
-funclit : obrace params Tendln blkbody Tcbrace {
+funclit : obrace params traitspec Tendln blkbody Tcbrace {
size_t i;
Node *fn, *lit;
- $$ = mkfunc($1->loc, $2.nl, $2.nn, mktyvar($3->loc), $4);
+ for (i = 0; i < $2.nn; i++)
+ setwith($2.nl[i]->decl.type, $3.spec, $3.nspec);
+ $$ = mkfunc($1->loc, $2.nl, $2.nn, mktyvar($4->loc), $5);
fn = $$->lit.fnval;
for (i = 0; i < nlbls[lbldepth]; i++) {
lit = lbls[lbldepth][i]->expr.args[0];
@@ -840,11 +895,14 @@
assert(lbldepth >= 0);
lbldepth--;
}
- | obrace params Tret type Tendln blkbody Tcbrace {
+ | obrace params Tret type traitspec Tendln blkbody Tcbrace {
size_t i;
Node *fn, *lit;
- $$ = mkfunc($1->loc, $2.nl, $2.nn, $4, $6);
+ setwith($4, $5.spec, $5.nspec);
+ for (i = 0; i < $2.nn; i++)
+ setwith($2.nl[i]->decl.type, $5.spec, $5.nspec);
+ $$ = mkfunc($1->loc, $2.nl, $2.nn, $4, $7);
fn = $$->lit.fnval;
for (i = 0; i < nlbls[lbldepth]; i++) {
lit = lbls[lbldepth][i]->expr.args[0];
@@ -1056,7 +1114,8 @@
%%
-static void setupinit(Node *n)
+static void
+setupinit(Node *n)
{
char name[1024];
char *p, *s;
@@ -1078,7 +1137,8 @@
n->decl.name->name.name = strdup(s);
}
-static Node *mkpseudodecl(Srcloc l, Type *t)
+static Node *
+mkpseudodecl(Srcloc l, Type *t)
{
static int nextpseudoid;
char buf[128];
@@ -1087,7 +1147,8 @@
return mkdecl(l, mkname(l, buf), t);
}
-static void setattrs(Node *dcl, char **attrs, size_t nattrs)
+static void
+setattrs(Node *dcl, char **attrs, size_t nattrs)
{
size_t i;
@@ -1101,8 +1162,52 @@
}
}
-static void installucons(Stab *st, Type *t)
+static void
+setwith(Type *ty, Traitspec **ts, size_t nts)
{
+ size_t i, j;
+
+ if (!ty)
+ return;
+ for (i = 0; i < nts; i++) {
+ switch (ty->type) {
+ case Typaram:
+ if (tyeq(ty, ts[i]->param))
+ lappend(&ty->spec, &ty->nspec, ts[i]);
+
+ break;
+ case Tyname:
+ case Tyunres:
+ for (j = 0; j < ty->ngparam; j++)
+ setwith(ty->gparam[j], ts, nts);
+ for (j = 0; j < ty->narg; j++)
+ setwith(ty->arg[j], ts, nts);
+ break;
+ case Tystruct:
+ for (j = 0; j < ty->nmemb; j++)
+ setwith(ty->sdecls[j]->decl.type, ts, nts);
+ break;
+ case Tyunion:
+ for (j = 0; j < ty->nmemb; j++)
+ setwith(ty->udecls[j]->etype, ts, nts);
+ break;
+ case Typtr:
+ case Tyarray:
+ case Tyslice:
+ case Tyfunc:
+ case Tytuple:
+ for (j = 0; j < ty->nsub; j++)
+ setwith(ty->sub[j], ts, nts);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void
+installucons(Stab *st, Type *t)
+{
Type *b;
size_t i;
@@ -1127,7 +1232,8 @@
}
-static Op binop(int tt)
+static Op
+binop(int tt)
{
Op o;
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -35,7 +35,9 @@
static void inferdecl(Node *n);
static int tryconstrain(Type *ty, Trait *tr, int update);
+static Type *tyfreshen(Tysubst *subst, Type *orig);
static Type *tf(Type *t);
+static Type *basetype(Type *a);
static Type *unify(Node *ctx, Type *a, Type *b);
static Type *tyfix(Node *ctx, Type *orig, int noerr);
@@ -66,7 +68,6 @@
static size_t nspecializations;
static Stab **specializationscope;
static size_t nspecializationscope;
-static Htab *seqbase;
static Traitmap *traitmap;
static void
@@ -279,6 +280,7 @@
ty = exprtype(n->iterstmt.seq);
if (ty->type == Tyslice || ty->type == Tyarray || ty->type == Typtr)
return;
+ ty = tyfreshen(NULL, ty);
for (i = 0; i < tr->nproto; i++) {
ty = exprtype(n->iterstmt.seq);
if (hthas(tr->proto[i]->decl.impls, ty))
@@ -462,7 +464,7 @@
static Type *
tyfreshen(Tysubst *subst, Type *orig)
{
- Type *t;
+ Type *ty, *base;
if (!needfreshen(orig))
return orig;
@@ -469,13 +471,18 @@
pushenv(orig->env);
if (!subst) {
subst = mksubst();
- t = tyspecialize(orig, subst, delayed, seqbase);
+ ty = tyspecialize(orig, subst, delayed, seqbase);
substfree(subst);
} else {
- t = tyspecialize(orig, subst, delayed, seqbase);
+ ty = tyspecialize(orig, subst, delayed, seqbase);
}
+ ty->spec = orig->spec;
+ ty->nspec = orig->nspec;
+ base = basetype(ty);
+ if (base)
+ htput(seqbase, ty, base);
popenv(orig->env);
- return t;
+ return ty;
}
/* Resolves a type and all its subtypes recursively. */
@@ -482,7 +489,7 @@
static void
tyresolve(Type *t)
{
- size_t i;
+ size_t i, j;
Trait *tr;
if (t->resolved)
@@ -526,13 +533,16 @@
break;
}
- for (i = 0; i < t->ntraits; i++) {
- tr = gettrait(curstab(), t->traits[i]);
- if (!tr)
- lfatal(t->loc, "trait %s does not exist", ctxstr(t->traits[i]));
- if (!t->trneed)
- t->trneed = mkbs();
- bsput(t->trneed, tr->uid);
+ for (i = 0; i < t->nspec; i++) {
+ for (j = 0; j < t->spec[i]->ntrait; j++) {
+ tr = gettrait(curstab(), t->spec[i]->trait[j]);
+ if (!tr)
+ lfatal(t->loc, "trait %s does not exist", ctxstr(t->spec[i]->trait[j]));
+ if (!t->trneed)
+ t->trneed = mkbs();
+ bsput(t->trneed, tr->uid);
+ htput(seqbase, t, t->spec[i]->aux);
+ }
}
for (i = 0; i < t->nsub; i++) {
@@ -597,9 +607,8 @@
{
size_t i;
- for (i = 0; i < t->ngparam; i++) {
+ for (i = 0; i < t->ngparam; i++)
substput(subst, t->gparam[i], tf(orig->arg[i]));
- }
t = tyfreshen(subst, t);
return t;
}
@@ -628,7 +637,9 @@
t = tylookup(orig);
isgeneric = t->type == Tygeneric;
ingeneric += isgeneric;
+ pushenv(orig->env);
tyresolve(t);
+ popenv(orig->env);
/* If this is an instantiation of a generic type, we want the params to
* match the instantiation */
if (orig->type == Tyunres && t->type == Tygeneric) {
@@ -1919,7 +1930,7 @@
fatal(n, "%s incompatibly specialized with %zd types instead of %zd types",
namestr(n->impl.traitname), n->impl.naux, tr->naux);
n->impl.type = tf(n->impl.type);
- pushenv(n->impl.type->env);
+ pushenv(n->impl.env);
for (i = 0; i < n->impl.naux; i++)
n->impl.aux[i] = tf(n->impl.aux[i]);
for (i = 0; i < n->impl.ndecls; i++) {
@@ -1986,7 +1997,7 @@
if (generic)
ingeneric--;
}
- popenv(n->impl.type->env);
+ popenv(n->impl.env);
}
static void
@@ -2049,7 +2060,7 @@
{
size_t i, nbound;
Node **bound, *n, *pat;
- Type *t, *b;
+ Type *t, *b, *e;
n = *np;
if (!n)
@@ -2115,12 +2126,15 @@
infernode(&n->iterstmt.seq, NULL, sawret);
infernode(&n->iterstmt.body, ret, sawret);
- b = mktyvar(n->loc);
- t = mktyvar(n->loc);
- htput(seqbase, t, b);
- constrain(n, type(n->iterstmt.seq), traittab[Tciter]);
- unify(n, type(n->iterstmt.seq), t);
- unify(n, type(n->iterstmt.elt), b);
+ e = type(n->iterstmt.elt);
+ t = type(n->iterstmt.seq);
+ constrain(n, t, traittab[Tciter]);
+ b = basetype(t);
+ if (b)
+ unify(n, e, b);
+ else
+ htput(seqbase, t, e);
+ delayedcheck(n, curstab());
break;
case Nmatchstmt:
infernode(&n->matchstmt.val, NULL, sawret);
@@ -2365,6 +2379,43 @@
}
static void
+fixiter(Node *n, Type *ty, Type *base)
+{
+ size_t i, bestidx;
+ int r, bestrank;
+ Type *b, *t, *orig;
+ Tysubst *ts;
+ Node *impl;
+
+ ty = tysearch(ty);
+ b = htget(seqbase, ty);
+ if (!b)
+ return;
+ bestrank = -1;
+ bestidx = 0;
+ for (i = 0; i < nimpltab; i++) {
+ if (impltab[i]->impl.trait != traittab[Tciter])
+ continue;
+ r = tymatchrank(impltab[i]->impl.type, ty);
+ if (r > bestrank) {
+ bestrank = r;
+ bestidx = i;
+ }
+ }
+ if (bestrank >= 0) {
+ impl = impltab[bestidx];
+ orig = impl->impl.type;
+ t = tf(impl->impl.aux[0]);
+ ts = mksubst();
+ for (i = 0; i < ty->narg; i++)
+ substput(ts, tf(orig->arg[i]), ty->arg[i]);
+ t = tyfreshen(ts, t);
+ substfree(ts);
+ unify(n, t, base);
+ }
+}
+
+static void
postcheckpass(Node ***rem, size_t *nrem, Stab ***remscope, size_t *nremscope)
{
size_t i;
@@ -2373,12 +2424,16 @@
for (i = 0; i < npostcheck; i++) {
n = postcheck[i];
pushstab(postcheckscope[i]);
- switch (exprop(n)) {
- case Omemb: infercompn(n, rem, nrem, remscope, nremscope); break;
- case Ocast: checkcast(n, rem, nrem, remscope, nremscope); break;
- case Ostruct: checkstruct(n, rem, nrem, remscope, nremscope); break;
- case Ovar: checkvar(n, rem, nrem, remscope, nremscope); break;
- default: die("should not see %s in postcheck\n", opstr[exprop(n)]);
+ if (n->type == Nexpr) {
+ switch (exprop(n)) {
+ case Omemb: infercompn(n, rem, nrem, remscope, nremscope); break;
+ case Ocast: checkcast(n, rem, nrem, remscope, nremscope); break;
+ case Ostruct: checkstruct(n, rem, nrem, remscope, nremscope); break;
+ case Ovar: checkvar(n, rem, nrem, remscope, nremscope); break;
+ default: die("should not see %s in postcheck\n", opstr[exprop(n)]);
+ }
+ } else if (n->type == Niterstmt) {
+ fixiter(n, type(n->iterstmt.seq), type(n->iterstmt.elt));
}
popstab();
}
@@ -2405,7 +2460,6 @@
postcheckscope = remscope;
npostcheckscope = nremscope;
}
- postcheckpass(NULL, NULL, NULL, NULL);
}
/* After inference, replace all
@@ -2588,7 +2642,8 @@
typesub(n->iterstmt.elt, noerr);
typesub(n->iterstmt.seq, noerr);
typesub(n->iterstmt.body, noerr);
- additerspecialization(n, curstab());
+ if (!ingeneric)
+ additerspecialization(n, curstab());
break;
case Nmatchstmt:
typesub(n->matchstmt.val, noerr);
@@ -2687,6 +2742,8 @@
tr = traittab[Tciter];
assert(tr->nproto == 2);
ty = exprtype(n->iterstmt.seq);
+ if (ty->type == Typaram)
+ continue;
it = itertype(n->iterstmt.seq, mktype(n->loc, Tybool));
d = specializedcl(tr->proto[0], ty, it, &name);
@@ -2782,10 +2839,10 @@
tr = gettrait(ns, n);
if (!tr)
fatal(impl, "trait %s does not exist near %s",
- namestr(impl->impl.traitname), ctxstr(impl));
+ namestr(impl->impl.traitname), ctxstr(impl));
if (tr->naux != impl->impl.naux)
fatal(impl, "incompatible implementation of %s: mismatched aux types",
- namestr(impl->impl.traitname), ctxstr(impl));
+ namestr(impl->impl.traitname), ctxstr(impl));
}
return tr;
}
@@ -2849,6 +2906,7 @@
Type *ty;
pushstab(file->file.globls);
+ seqbase = mkht(tyhash, tyeq);
traitmap = zalloc(sizeof(Traitmap));
builtintraits();
for (i = 0; i < nimpltab; i++) {
@@ -2898,7 +2956,6 @@
infer(void)
{
delayed = mkht(tyhash, tyeq);
- seqbase = mkht(tyhash, tyeq);
loaduses();
initimpl();
--- a/parse/node.c
+++ b/parse/node.c
@@ -264,6 +264,9 @@
n->impl.env = mkenv();
bindtype(n->impl.env, t);
}
+ for (i = 0; i < naux; i++)
+ if (hasparams(aux[i]))
+ bindtype(n->impl.env, aux[i]);
return n;
}
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -1,7 +1,8 @@
-#define Abiversion 14
+#define Abiversion 15
typedef struct Srcloc Srcloc;
typedef struct Tysubst Tysubst;
+typedef struct Traitspec Traitspec;
typedef struct Tok Tok;
typedef struct Node Node;
@@ -118,6 +119,13 @@
Htab *tab;
};
+struct Traitspec {
+ Node **trait;
+ size_t ntrait;
+ Type *param;
+ Type *aux;
+};
+
struct Type {
Ty type;
uint32_t tid;
@@ -125,8 +133,10 @@
Vis vis;
- Node **traits; /* trait list */
- size_t ntraits; /* trait list size */
+ Traitspec **spec;
+ size_t nspec;
+ //Node **traits; /* trait list */
+ //size_t ntraits; /* trait list size */
Type **gparam; /* Tygeneric: type parameters that match the type args */
size_t ngparam; /* Tygeneric: count of type parameters */
@@ -367,6 +377,7 @@
extern size_t ndecls;
extern Node **exportimpls;
extern size_t nexportimpls;
+extern Htab *seqbase;
/* property tables */
extern int opispure[];
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -14,6 +14,7 @@
#include "parse.h"
static Node *specializenode(Node *g, Tysubst *tsmap);
+static void fillsubst(Tysubst *tsmap, Type *to, Type *from);
static void
substpush(Tysubst *subst)
@@ -84,8 +85,9 @@
tyspecialize(Type *orig, Tysubst *tsmap, Htab *delayed, Htab *trbase)
{
Type *t, *ret, *tmp, *var, *base;
- Type **arg;
+ Traitspec *ts;
size_t i, narg;
+ Type **arg;
t = tysearch(orig);
tmp = substget(tsmap, t);
@@ -98,6 +100,20 @@
ret = mktyvar(t->loc);
ret->trneed = bsdup(t->trneed);
substput(tsmap, t, ret);
+ for (i = 0; i < t->nspec; i++) {
+ ts = zalloc(sizeof(Traitspec));
+ ts->trait = t->spec[i]->trait;
+ ts->ntrait = t->spec[i]->ntrait;
+ ts->param = tyspecialize(t->spec[i]->param, tsmap, delayed, trbase);
+ if (t->spec[i]->aux)
+ ts->aux = tyspecialize(t->spec[i]->aux, tsmap, delayed, trbase);
+ lappend(&ret->spec, &ret->nspec, ts);
+ }
+ tmp = htget(seqbase, t);
+ if (tmp) {
+ tmp = tyspecialize(tmp, tsmap, delayed, trbase);
+ htput(trbase, ret, tmp);
+ }
break;
case Tygeneric:
var = mktyvar(t->loc);
@@ -186,6 +202,26 @@
return t;
}
+static void
+substputspec(Tysubst *tsmap, Type *from, Type *to)
+{
+ size_t ai, aj, bi, bj;
+
+ for (ai = 0; ai < from->nspec; ai++) {
+ for (aj = 0; aj < from->spec[ai]->ntrait; aj++) {
+ for (bi = 0; bi < to->nspec; bi++) {
+ for (bj = 0; bj < to->spec[bi]->ntrait; bj++) {
+ if (nameeq(from->spec[ai]->trait[aj], to->spec[bi]->trait[bj]))
+ fillsubst(tsmap, to->spec[ai]->aux, from->spec[bi]->aux);
+ }
+ }
+ if (nameeq(from->spec[ai]->trait[aj], traittab[Tciter]->name))
+ if (to->type == Tyslice || to->type == Tyarray)
+ fillsubst(tsmap, to->sub[0], from->spec[ai]->aux);
+ }
+ }
+}
+
/*
* Fills the substitution map with a mapping from
* the type parameter 'from' to it's substititon 'to'
@@ -199,6 +235,7 @@
if (debugopt['S'])
printf("mapping %s => %s\n", tystr(from), tystr(to));
substput(tsmap, from, to);
+ substputspec(tsmap, from, to);
return;
}
assert(to->nsub == from->nsub);
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -671,6 +671,9 @@
tytab[t->tid] = tt;
else if (!boundtype(t))
htput(e->tab, t, t);
+ for (i = 0; i < t->nspec; i++)
+ if (t->spec[i]->aux)
+ bindtype_rec(e, t->spec[i]->aux, visited);
break;
case Tygeneric:
for (i = 0; i < t->ngparam; i++)
--- a/parse/type.c
+++ b/parse/type.c
@@ -24,6 +24,7 @@
Node **impltab;
size_t nimpltab;
Htab *eqcache;
+Htab *seqbase;
struct Typair {
uint32_t atid;
--- a/parse/use.c
+++ b/parse/use.c
@@ -218,7 +218,7 @@
static void
typickle(FILE *fd, Type *ty)
{
- size_t i;
+ size_t i, j;
if (!ty) {
die("trying to pickle null type\n");
@@ -226,6 +226,16 @@
}
wrbyte(fd, ty->type);
wrbyte(fd, ty->vis);
+ wrint(fd, ty->nspec);
+ for (i = 0; i < ty->nspec; i++) {
+ wrint(fd, ty->spec[i]->ntrait);
+ for (j = 0; j < ty->spec[i]->ntrait; j++)
+ pickle(fd, ty->spec[i]->trait[j]);
+ wrtype(fd, ty->spec[i]->param);
+ wrbool(fd, ty->spec[i]->aux != NULL);
+ if (ty->spec[i]->aux)
+ wrtype(fd, ty->spec[i]->aux);
+ }
wrint(fd, ty->nsub);
switch (ty->type) {
case Tyunres:
@@ -350,7 +360,7 @@
static Type *
tyunpickle(FILE *fd)
{
- size_t i, n;
+ size_t i, j, n;
Type *ty;
Ty t;
@@ -359,6 +369,19 @@
ty->isimport = 1;
if (rdbyte(fd) == Vishidden)
ty->ishidden = 1;
+ ty->nspec = rdint(fd);
+ ty->spec = malloc(ty->nspec * sizeof(Traitspec*));
+ for (i = 0; i < ty->nspec; i++) {
+ ty->spec[i] = zalloc(sizeof(Traitspec));
+ n = rdint(fd);
+ ty->spec[i]->ntrait = n;
+ ty->spec[i]->trait = malloc(n * sizeof(Node*));
+ for (j = 0; j < ty->spec[i]->ntrait; j++)
+ ty->spec[i]->trait[j] = unpickle(fd);
+ rdtype(fd, &ty->spec[i]->param);
+ if (rdbool(fd))
+ rdtype(fd, &ty->spec[i]->aux);
+ }
ty->nsub = rdint(fd);
if (ty->nsub > 0)
ty->sub = zalloc(ty->nsub * sizeof(Type *));
--- a/test/emptytrait.myr
+++ b/test/emptytrait.myr
@@ -6,7 +6,7 @@
impl fooable int =
;;
-generic foo = {x : @a::fooable
+generic foo = {x : @a::fooable @a
-> x
}
--- a/test/generictype.myr
+++ b/test/generictype.myr
@@ -1,8 +1,8 @@
use std
/* checks that parameterized types work. exits with 0. */
-type option(@a::(integral,numeric)) = union
- `Some @a::(integral,numeric)
+type option(@a) :: integral,numeric @a = union
+ `Some @a
`None
;;
--- a/test/genericval.myr
+++ b/test/genericval.myr
@@ -1,6 +1,6 @@
use std
-generic Foo : @a::(integral,numeric) = 42
+generic Foo : @a = 42 :: integral,numeric @a
const main = {
std.exit(Foo)
--- a/test/gtrait.myr
+++ b/test/gtrait.myr
@@ -4,7 +4,7 @@
cmp : (a : @a, b : @a -> std.order)
;;
-impl comparable @a::numeric =
+impl comparable @a :: numeric @a =
cmp = {a, b
-> std.numcmp(a, b)
}
--- a/test/recgeneric.myr
+++ b/test/recgeneric.myr
@@ -1,6 +1,6 @@
use std
-type o(@a::integral) = union
+type o(@a) :: integral @a = union
`S @a
;;
--- a/test/trait-builtin.myr
+++ b/test/trait-builtin.myr
@@ -7,7 +7,7 @@
exits with 42.
*/
-generic max = {a:@a::numeric, b:@a::numeric
+generic max = {a : @a, b : @a :: numeric @a
if a > b
-> a
else
@@ -15,7 +15,7 @@
;;
}
-generic intlike_is42 = {a : @a::(numeric,integral)
+generic intlike_is42 = {a : @a :: numeric,integral @a
-> a == 42
}
--- a/test/traitimpl.myr
+++ b/test/traitimpl.myr
@@ -22,7 +22,7 @@
}
;;
-generic foo = {x : @a::frobable
+generic foo = {x : @a :: frobable @a
-> frob(x)
}