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
|
||||
(Types.to_string other));
|
||||
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 ->
|
||||
let target = resolve_name ctx.env ~seen:[] loc name in
|
||||
let a = check ctx (List.hd args) in
|
||||
|
||||
@ -62,6 +62,30 @@
|
||||
{:where (copyable? $t)}
|
||||
(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 [] ()
|
||||
(println (ident 3))
|
||||
(println (ident 4.5))
|
||||
@ -98,8 +122,15 @@
|
||||
(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 (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)
|
||||
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 (at (as-slice one) 0))
|
||||
(free one)
|
||||
(free keep)
|
||||
(free-all a))))
|
||||
|
||||
@ -1323,7 +1323,10 @@ let () =
|
||||
(* Generics end to end: one written body per family, several emitted, and
|
||||
the collapsed prelude running underneath it. Every line of the expected
|
||||
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 ~opt:"-O0" "generics, -O0" "programs/generics.flan" generics_out;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user