A cast to a type variable, and the container builtins over one
(t x) is not a name is_cast knows - t is not a machine type - so it is its own arm, admitted by numeric? because a cast produces a number. vec-new, pool-new and map-new all reach the one list of what names a type, so the spike's line for vec-new had already covered the other two; zeroed takes its type from the position it is written in. All four are pinned in programs/generics.flan.
This commit is contained in:
parent
dad725afe4
commit
de93ffc89e
20
lib/check.ml
20
lib/check.ml
@ -4645,6 +4645,26 @@ and named_call ctx ~want loc name args =
|
|||||||
float goes through (i32 x) first" name
|
float goes through (i32 x) first" name
|
||||||
(Types.to_string other));
|
(Types.to_string other));
|
||||||
prim (Tast.Cast target) target [ a ]
|
prim (Tast.Cast target) target [ a ]
|
||||||
|
(* A cast to a *type variable*: [(t x)] inside a generic body. The name is
|
||||||
|
not one [is_cast] knows, because [is_cast] asks whether the name is a
|
||||||
|
machine type and [t] is not — so this is its own arm, above the ordinary
|
||||||
|
one and below the enums, and it reaches the same [Cast] prim.
|
||||||
|
|
||||||
|
Inside an instantiation [resolve_name] has already answered with the
|
||||||
|
concrete target, so the copy casts to a real type and the emitter sees
|
||||||
|
nothing unusual. During the abstract pass the target is [Var t] and the
|
||||||
|
[where] clause is what says the cast means anything at all: a cast
|
||||||
|
produces a number, so [numeric?] is what admits it. *)
|
||||||
|
| _ when (List.mem name ctx.env.tyvars || List.mem_assoc name ctx.env.subst)
|
||||||
|
&& List.length args = 1 ->
|
||||||
|
let target = resolve_name ctx.env ~seen:[] loc name in
|
||||||
|
unconstrained ctx.env loc ("a cast to " ^ name) ~needs:"numeric?" target;
|
||||||
|
let a = check ctx (List.hd args) in
|
||||||
|
(match a.Tast.ty with
|
||||||
|
| Types.Enum _ -> ()
|
||||||
|
| t when Types.is_numeric t || generic_ty t -> ()
|
||||||
|
| t -> fail loc "%s converts a number, found %s" name (Types.to_string t));
|
||||||
|
prim (Tast.Cast target) target [ a ]
|
||||||
| _ when is_cast name && List.length args = 1 ->
|
| _ when is_cast name && List.length args = 1 ->
|
||||||
let target = resolve_name ctx.env ~seen:[] loc name in
|
let target = resolve_name ctx.env ~seen:[] loc name in
|
||||||
let a = check ctx (List.hd args) in
|
let a = check ctx (List.hd args) in
|
||||||
|
|||||||
@ -62,6 +62,30 @@
|
|||||||
{:where (copyable? $t)}
|
{:where (copyable? $t)}
|
||||||
(println x))
|
(println x))
|
||||||
|
|
||||||
|
;; A cast to a type variable. [(t x)] is not a name [is_cast] knows — [t] is
|
||||||
|
;; not a machine type — so it is its own arm, and [numeric?] is what admits
|
||||||
|
;; it, because a cast produces a number. Inside the copy the target is
|
||||||
|
;; concrete and the emitter sees an ordinary cast.
|
||||||
|
(defn widen [x i32 d $t] $t
|
||||||
|
{:where (numeric? $t)}
|
||||||
|
(do d (t x)))
|
||||||
|
|
||||||
|
;; The builtins that take a *type name* as an argument, over a variable. Each
|
||||||
|
;; reaches the one list of what names a type, so all three came at once.
|
||||||
|
;; (pool-new t) and (map-new t i32) are the other two; a Pool of a variable
|
||||||
|
;; needs it not to be move-only, which [copyable?] is.
|
||||||
|
(defn one-of [x $t] (Vec $t)
|
||||||
|
{:where (copyable? $t)}
|
||||||
|
(let [v (vec-new t)]
|
||||||
|
(push v x)
|
||||||
|
v))
|
||||||
|
|
||||||
|
;; (zeroed) takes its type from the position it is written in, so a variable
|
||||||
|
;; in that position is answered by the instantiation like any other type.
|
||||||
|
(defn zero-of [x $t] $t
|
||||||
|
{:where (copyable? $t)}
|
||||||
|
(do x (zeroed)))
|
||||||
|
|
||||||
(defn main [] ()
|
(defn main [] ()
|
||||||
(println (ident 3))
|
(println (ident 3))
|
||||||
(println (ident 4.5))
|
(println (ident 4.5))
|
||||||
@ -98,8 +122,15 @@
|
|||||||
(match (min-of (slice ns 0 4)) (Some m) (println m) _ (println -1))
|
(match (min-of (slice ns 0 4)) (Some m) (println m) _ (println -1))
|
||||||
(match (max-of (slice fs 0 3)) (Some m) (println m) _ (println -1.0))
|
(match (max-of (slice fs 0 3)) (Some m) (println m) _ (println -1.0))
|
||||||
(match (index-of (slice ns 0 4) 18) (Some i) (println i) _ (println -1))
|
(match (index-of (slice ns 0 4) 18) (Some i) (println i) _ (println -1))
|
||||||
|
(println (widen 3 0.0))
|
||||||
|
(println (widen 3 (i64 0)))
|
||||||
|
(println (zero-of 9))
|
||||||
|
|
||||||
(let [a (arena-new 4096)
|
(let [a (arena-new 4096)
|
||||||
keep (filter (slice ns 0 4) (fn [x] (> x 5)))]
|
keep (filter (slice ns 0 4) (fn [x] (> x 5)))
|
||||||
|
one (one-of 4.5)]
|
||||||
(println (len (as-slice keep)))
|
(println (len (as-slice keep)))
|
||||||
|
(println (at (as-slice one) 0))
|
||||||
|
(free one)
|
||||||
(free keep)
|
(free keep)
|
||||||
(free-all a))))
|
(free-all a))))
|
||||||
|
|||||||
@ -1323,7 +1323,10 @@ let () =
|
|||||||
(* Generics end to end: one written body per family, several emitted, and
|
(* Generics end to end: one written body per family, several emitted, and
|
||||||
the collapsed prelude running underneath it. Every line of the expected
|
the collapsed prelude running underneath it. Every line of the expected
|
||||||
output is an answer a per-type copy used to give. *)
|
output is an answer a per-type copy used to give. *)
|
||||||
let generics_out = "3\n4.5\ntrue\n7\n5\n-1\n5\n42\n3\n1\n10\n1\n8\n3\n4.5\ntext\n1\n2.5\n9\n36\n2\n2.5\n0\n3\n" in
|
let generics_out =
|
||||||
|
"3\n4.5\ntrue\n7\n5\n-1\n5\n42\n3\n1\n10\n1\n8\n\
|
||||||
|
3\n4.5\ntext\n1\n2.5\n9\n36\n2\n2.5\n0\n3\n3\n0\n3\n4.5\n"
|
||||||
|
in
|
||||||
outputs "generics" "programs/generics.flan" generics_out;
|
outputs "generics" "programs/generics.flan" generics_out;
|
||||||
outputs ~opt:"-O0" "generics, -O0" "programs/generics.flan" generics_out;
|
outputs ~opt:"-O0" "generics, -O0" "programs/generics.flan" generics_out;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user