summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/bio/bio.myr4
-rw-r--r--lib/bio/geti.myr24
-rw-r--r--lib/bio/puti.myr16
-rw-r--r--lib/crypto/rand.myr4
-rw-r--r--lib/date/parse.myr5
-rw-r--r--lib/std/bigint.myr38
-rw-r--r--lib/std/bitset.myr6
-rw-r--r--lib/std/chartype.myr12
-rw-r--r--lib/std/endian.myr12
-rw-r--r--lib/std/extremum.myr12
-rw-r--r--lib/std/fltbits.myr2
-rw-r--r--lib/std/fmt.myr4
-rw-r--r--lib/std/fndup.myr12
-rw-r--r--lib/std/getint.myr114
-rw-r--r--lib/std/hashfuncs.myr4
-rw-r--r--lib/std/intparse.myr10
-rw-r--r--lib/std/ipparse.myr4
-rw-r--r--lib/std/putint.myr26
-rw-r--r--lib/std/rand.myr12
-rw-r--r--lib/std/search.myr4
-rw-r--r--lib/std/syswrap+posixy.myr2
-rw-r--r--lib/std/units.myr16
-rw-r--r--lib/thread/atomic.myr2
-rw-r--r--parse/gram.y204
-rw-r--r--parse/infer.c20
-rw-r--r--parse/parse.h15
-rw-r--r--parse/type.c2
-rw-r--r--test/emptytrait.myr2
-rw-r--r--test/generictype.myr4
-rw-r--r--test/genericval.myr2
-rw-r--r--test/gtrait.myr2
-rw-r--r--test/recgeneric.myr2
-rw-r--r--test/trait-builtin.myr4
-rw-r--r--test/traitimpl.myr2
34 files changed, 358 insertions, 246 deletions
diff --git a/lib/bio/bio.myr b/lib/bio/bio.myr
index 4db8ec9..1f44bf8 100644
--- a/lib/bio/bio.myr
+++ b/lib/bio/bio.myr
@@ -283,7 +283,7 @@ const ensurecodepoint = {f
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 @@ generic putle = {f, v : @a::(numeric,integral)
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))
;;
diff --git a/lib/bio/geti.myr b/lib/bio/geti.myr
index ee9a631..4e9faca 100644
--- a/lib/bio/geti.myr
+++ b/lib/bio/geti.myr
@@ -5,23 +5,23 @@ use "types"
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
;;
/*
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 @@ generic getle = {f, n -> std.result(@a::(numeric,integral), err)
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 @@ generic getle = {f, n -> std.result(@a::(numeric,integral), err)
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 @@ generic getbe = {f, n -> std.result(@a::(numeric,integral), err)
v <<= 8
v |= (f.rbuf[f.rstart++] : uint64)
;;
- -> `std.Ok (v : @a::(numeric,integral))
+ -> `std.Ok (v : @a)
;;
}
diff --git a/lib/bio/puti.myr b/lib/bio/puti.myr
index 2f07414..38fddcd 100644
--- a/lib/bio/puti.myr
+++ b/lib/bio/puti.myr
@@ -5,16 +5,16 @@ use "types"
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)}
diff --git a/lib/crypto/rand.myr b/lib/crypto/rand.myr
index 21c3844..2cc6832 100644
--- a/lib/crypto/rand.myr
+++ b/lib/crypto/rand.myr
@@ -8,8 +8,8 @@ use "chacha20"
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
diff --git a/lib/date/parse.myr b/lib/date/parse.myr
index 6c6d0d7..398dbae 100644
--- a/lib/date/parse.myr
+++ b/lib/date/parse.myr
@@ -239,9 +239,8 @@ const matchampm = {d, s, am, err
-> 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
diff --git a/lib/std/bigint.myr b/lib/std/bigint.myr
index 129890c..bdc040c 100644
--- a/lib/std/bigint.myr
+++ b/lib/std/bigint.myr
@@ -22,7 +22,7 @@ pkg std =
;;
/* 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 @@ pkg std =
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 @@ pkg std =
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 @@ pkg std =
/* 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 @@ extern const put : (fmt : byte[:], args : ... -> size)
const Base = 0x100000000ul
-generic mkbigint = {v : @a::(integral,numeric)
+generic mkbigint = {v : @a :: integral,numeric @a
var a
var val
@@ -771,7 +771,7 @@ generic bigaddi = {a, b
-> 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 @@ generic bigmodi = {a, b
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
diff --git a/lib/std/bitset.myr b/lib/std/bitset.myr
index ce750db..3d8c2ff 100644
--- a/lib/std/bitset.myr
+++ b/lib/std/bitset.myr
@@ -22,9 +22,9 @@ pkg std =
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)
diff --git a/lib/std/chartype.myr b/lib/std/chartype.myr
index bf01d9a..9832fc5 100644
--- a/lib/std/chartype.myr
+++ b/lib/std/chartype.myr
@@ -25,7 +25,7 @@ pkg std =
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 @@ const totitle = {c
-> 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
diff --git a/lib/std/endian.myr b/lib/std/endian.myr
index 874ab71..c896dd8 100644
--- 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 @@ generic hosttonet = {v : @a::(integral,numeric)
-> 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
diff --git a/lib/std/extremum.myr b/lib/std/extremum.myr
index b8afc01..2c46ae1 100644
--- 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 clamp = {a, min, max
;;
}
-generic abs = {a : @a::numeric
- if a < (0 : @a::numeric)
+generic abs = {a : @a :: numeric @a
+ if a < (0 : @a)
-> -a
else
-> a
diff --git a/lib/std/fltbits.myr b/lib/std/fltbits.myr
index 0d7169b..765ce04 100644
--- a/lib/std/fltbits.myr
+++ b/lib/std/fltbits.myr
@@ -6,7 +6,7 @@ pkg std =
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))
diff --git a/lib/std/fmt.myr b/lib/std/fmt.myr
index 5c94542..005d1d3 100644
--- a/lib/std/fmt.myr
+++ b/lib/std/fmt.myr
@@ -537,7 +537,7 @@ const digitchars = [
'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 @@ generic intfmt = {sb, opts, signed, bits : @a::(integral,numeric)
;;
else
val = (bits : uint64)
- val &= ~0 >> (8*(sizeof(uint64)-sizeof(@a::(integral,numeric))))
+ val &= ~0 >> (8*(sizeof(uint64)-sizeof(@a)))
isneg = false
;;
diff --git a/lib/std/fndup.myr b/lib/std/fndup.myr
index 4bbed61..b4799e0 100644
--- a/lib/std/fndup.myr
+++ b/lib/std/fndup.myr
@@ -5,10 +5,10 @@ use "slcp"
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 @@ generic fnenvsz = {fn
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 @@ generic fnbdup = {fn, buf
env = envslice(repr[0])
slcp(buf[:env.len], env)
repr[0] = (buf : intptr)
- -> (&repr : @fn::function#)#
+ -> (&repr : @fn#)#
}
generic fnfree = {fn
diff --git a/lib/std/getint.myr b/lib/std/getint.myr
index 4445c4a..3499c4d 100644
--- a/lib/std/getint.myr
+++ b/lib/std/getint.myr
@@ -2,95 +2,95 @@ use "die"
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
}
diff --git a/lib/std/hashfuncs.myr b/lib/std/hashfuncs.myr
index 5ad1180..a7d61c4 100644
--- a/lib/std/hashfuncs.myr
+++ b/lib/std/hashfuncs.myr
@@ -23,13 +23,13 @@ pkg std =
}
;;
- 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)
}
diff --git a/lib/std/intparse.myr b/lib/std/intparse.myr
index 18cc478..446abc8 100644
--- a/lib/std/intparse.myr
+++ b/lib/std/intparse.myr
@@ -7,8 +7,8 @@ use "types"
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 @@ generic intparsebase = {s, base
-> 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 @@ generic doparse = {s, isneg, base -> option(@a::(integral,numeric))
;;
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
;;
diff --git a/lib/std/ipparse.myr b/lib/std/ipparse.myr
index 78cb619..16da94e 100644
--- a/lib/std/ipparse.myr
+++ b/lib/std/ipparse.myr
@@ -116,7 +116,7 @@ const delim = {ip, sep, ok
;;
}
-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 @@ generic num = {ip, lo, hi, base, sep, ok -> (@a::(numeric,integral), byte[:], bo
if v < lo || v > hi
-> (0, "", false)
;;
- -> ((v : @a::(numeric,integral)), ip[len:], true)
+ -> ((v : @a), ip[len:], true)
| `std.None:
-> (0, "", false)
;;
diff --git a/lib/std/putint.myr b/lib/std/putint.myr
index c6e48e9..c05ee7a 100644
--- a/lib/std/putint.myr
+++ b/lib/std/putint.myr
@@ -3,21 +3,21 @@ use "memops"
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)
diff --git a/lib/std/rand.myr b/lib/std/rand.myr
index c2a03fd..9cea564 100644
--- a/lib/std/rand.myr
+++ b/lib/std/rand.myr
@@ -13,12 +13,12 @@ pkg std =
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 @@ designed by David Blackman and Sebastiano Vigna.
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 @@ generic rngrandnum = {rng -> @a::(numeric,integral)
rng.s0 = (s0 << 55 | s0 >> 9) ^ s1 ^ (s1 << 14)
rng.s1 = (s1 << 36 | s1 >> 28)
- -> (r : @a::(numeric,integral))
+ -> (r : @a)
}
diff --git a/lib/std/search.myr b/lib/std/search.myr
index 8ae364f..5e3865b 100644
--- a/lib/std/search.myr
+++ b/lib/std/search.myr
@@ -3,8 +3,8 @@ use "option"
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 */
diff --git a/lib/std/syswrap+posixy.myr b/lib/std/syswrap+posixy.myr
index f49f9b8..4dd97fd 100644
--- a/lib/std/syswrap+posixy.myr
+++ b/lib/std/syswrap+posixy.myr
@@ -179,7 +179,7 @@ const fsize = {path
;;
}
-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
diff --git a/lib/std/units.myr b/lib/std/units.myr
index 67eab81..76d9e5a 100644
--- a/lib/std/units.myr
+++ b/lib/std/units.myr
@@ -2,14 +2,14 @@ use "types"
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
diff --git a/lib/thread/atomic.myr b/lib/thread/atomic.myr
index b9678c7..c3c8124 100644
--- 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)
diff --git a/parse/gram.y b/parse/gram.y
index dc17314..c3db284 100644
--- 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 Op binop(int toktype);
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 @@ static void setupinit(Node *n);
%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 @@ but warnings suck.
Type **params;
size_t nparams;
} tydef;
+ struct {
+ Traitspec **spec;
+ size_t nspec;
+ } traitspecs;
+ Traitspec *traitspec;
Trait *trait;
Node *node;
Tok *tok;
@@ -254,14 +263,14 @@ toplev : package
| /* empty */
;
-decl : attrs Tvar decllist {
+decl : attrs Tvar decllist traitspec {
size_t i;
for (i = 0; i < $3.nn; i++)
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 @@ decl : attrs Tvar decllist {
}
$$ = $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 @@ attrs : /* empty */ {$$.nstr = 0; $$.str = NULL;}
}
;
+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);
+ $$->traits = $1.nl;
+ $$->ntraits = $1.nn;
+ $$->param = $2;
+ $$->aux = NULL;
+ }
+ | traitlist generictype Tret type {
+ $$ = calloc(sizeof(Traitspec), 1);
+ $$->traits = $1.nl;
+ $$->ntraits = $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 @@ name : Tident {$$ = mkname($1->loc, $1->id);}
;
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 @@ implbody
;
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 @@ traitbody
;
-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 @@ type : structdef
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 @@ obrace : Tobrace {
}
;
-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 @@ funclit : obrace params Tendln blkbody Tcbrace {
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];
@@ -1101,6 +1159,48 @@ static void setattrs(Node *dcl, char **attrs, size_t nattrs)
}
}
+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;
diff --git a/parse/infer.c b/parse/infer.c
index 55628a5..69419d3 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -66,7 +66,6 @@ static Node **specializations;
static size_t nspecializations;
static Stab **specializationscope;
static size_t nspecializationscope;
-static Htab *seqbase;
static Traitmap *traitmap;
static void
@@ -482,7 +481,7 @@ tyfreshen(Tysubst *subst, Type *orig)
static void
tyresolve(Type *t)
{
- size_t i;
+ size_t i, j;
Trait *tr;
if (t->resolved)
@@ -526,13 +525,15 @@ tyresolve(Type *t)
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]->ntraits; j++) {
+ tr = gettrait(curstab(), t->spec[i]->traits[j]);
+ if (!tr)
+ lfatal(t->loc, "trait %s does not exist", ctxstr(t->spec[i]->traits[j]));
+ if (!t->trneed)
+ t->trneed = mkbs();
+ bsput(t->trneed, tr->uid);
+ }
}
for (i = 0; i < t->nsub; i++) {
@@ -2898,7 +2899,6 @@ void
infer(void)
{
delayed = mkht(tyhash, tyeq);
- seqbase = mkht(tyhash, tyeq);
loaduses();
initimpl();
diff --git a/parse/parse.h b/parse/parse.h
index 0bae957..c8db0f5 100644
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -2,6 +2,7 @@
typedef struct Srcloc Srcloc;
typedef struct Tysubst Tysubst;
+typedef struct Traitspec Traitspec;
typedef struct Tok Tok;
typedef struct Node Node;
@@ -118,6 +119,13 @@ struct Tyenv {
Htab *tab;
};
+struct Traitspec {
+ Node **traits;
+ size_t ntraits;
+ Type *param;
+ Type *aux;
+};
+
struct Type {
Ty type;
uint32_t tid;
@@ -125,8 +133,10 @@ struct Type {
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 */
@@ -350,6 +360,7 @@ struct Node {
};
/* globals */
+extern Htab *seqbase;
extern Srcloc curloc;
extern char *filename;
extern Tok *curtok; /* the last token we tokenized */
diff --git a/parse/type.c b/parse/type.c
index c31fbbe..ab033cb 100644
--- a/parse/type.c
+++ b/parse/type.c
@@ -24,6 +24,7 @@ size_t ntraittab;
Node **impltab;
size_t nimpltab;
Htab *eqcache;
+Htab *seqbase;
struct Typair {
uint32_t atid;
@@ -1083,6 +1084,7 @@ tyinit(Stab *st)
Type *ty;
Trait *tr;
+ seqbase = mkht(tyhash, tyeq);
eqcache = mkht(typairhash, typaireq);
tydeduptab = mkht(tyhash, tystricteq);
/* this must be done after all the types are created, otherwise we will
diff --git a/test/emptytrait.myr b/test/emptytrait.myr
index e3c3c91..f4a1f38 100644
--- a/test/emptytrait.myr
+++ b/test/emptytrait.myr
@@ -6,7 +6,7 @@ trait fooable @a =
impl fooable int =
;;
-generic foo = {x : @a::fooable
+generic foo = {x : @a::fooable @a
-> x
}
diff --git a/test/generictype.myr b/test/generictype.myr
index 68a6508..3e62af4 100644
--- 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
;;
diff --git a/test/genericval.myr b/test/genericval.myr
index ca7a925..fbe2038 100644
--- 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)
diff --git a/test/gtrait.myr b/test/gtrait.myr
index 5131ccc..9d84b45 100644
--- a/test/gtrait.myr
+++ b/test/gtrait.myr
@@ -4,7 +4,7 @@ trait comparable @a =
cmp : (a : @a, b : @a -> std.order)
;;
-impl comparable @a::numeric =
+impl comparable @a :: numeric @a =
cmp = {a, b
-> std.numcmp(a, b)
}
diff --git a/test/recgeneric.myr b/test/recgeneric.myr
index 28b9fab..ac5f13b 100644
--- 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
;;
diff --git a/test/trait-builtin.myr b/test/trait-builtin.myr
index 93c5bda..cdb8735 100644
--- a/test/trait-builtin.myr
+++ b/test/trait-builtin.myr
@@ -7,7 +7,7 @@ comparing to 42 wouldn't work.
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 max = {a:@a::numeric, b:@a::numeric
;;
}
-generic intlike_is42 = {a : @a::(numeric,integral)
+generic intlike_is42 = {a : @a :: numeric,integral @a
-> a == 42
}
diff --git a/test/traitimpl.myr b/test/traitimpl.myr
index e0d1eca..c3293c1 100644
--- a/test/traitimpl.myr
+++ b/test/traitimpl.myr
@@ -22,7 +22,7 @@ impl frobable byte[:] =
}
;;
-generic foo = {x : @a::frobable
+generic foo = {x : @a :: frobable @a
-> frob(x)
}