Skip to content

Commit 2e03f71

Browse files
committed
---
yaml --- r: 669 b: refs/heads/master c: 77beffc h: refs/heads/master i: 667: 110b49c v: v3
1 parent 5d099ca commit 2e03f71

File tree

3 files changed

+170
-11
lines changed

3 files changed

+170
-11
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: c61d021f6d97c101ff9d201e5bf8e78eda8c8a1b
2+
refs/heads/master: 77beffc889effe6f77248568a684d8b942610c85

trunk/src/boot/fe/ast.ml

Lines changed: 86 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -114,22 +114,22 @@ and ty_tag = { tag_id: opaque_id;
114114
(* In closed type terms a constraint may refer to components of the term by
115115
* anchoring off the "formal symbol" '*', which represents "the term this
116116
* constraint is attached to".
117-
*
118-
*
117+
*
118+
*
119119
* For example, if I have a tuple type tup(int,int), I may wish to enforce the
120120
* lt predicate on it; I can write this as a constrained type term like:
121-
*
121+
*
122122
* tup(int,int) : lt( *._0, *._1 )
123-
*
123+
*
124124
* In fact all tuple types are converted to this form for purpose of
125125
* type-compatibility testing; the argument tuple in a function
126-
*
126+
*
127127
* fn (int x, int y) : lt(x, y) -> int
128-
*
128+
*
129129
* desugars to
130-
*
130+
*
131131
* fn (tup(int, int) : lt( *._1, *._2 )) -> int
132-
*
132+
*
133133
*)
134134

135135
and carg_base =
@@ -353,7 +353,7 @@ and plval =
353353
| PLVAL_ext_pexp of (pexp * pexp)
354354
| PLVAL_ext_deref of pexp
355355

356-
and pexp = pexp' Common.identified
356+
and pexp = pexp' identified
357357

358358
and lit =
359359
| LIT_nil
@@ -481,6 +481,9 @@ and crate' =
481481
and crate = crate' identified
482482
;;
483483

484+
485+
(* Utility values and functions. *)
486+
484487
let empty_crate' =
485488
{ crate_items = ({ view_imports = Hashtbl.create 0;
486489
view_exports = Hashtbl.create 0 },
@@ -511,9 +514,82 @@ let sane_name (n:name) : bool =
511514
| NAME_ext (prefix, _) -> sane_prefix prefix
512515
;;
513516

517+
(*
518+
* We have multiple subset-categories of expression:
519+
*
520+
* - Atomic expressions are just atomic-lvals and literals.
521+
*
522+
* - Primitive expressions are 1-level, machine-level operations on atomic
523+
* expressions (so: 1-level binops and unops on atomics)
524+
* - Constant expressions are those that can be evaluated at compile time,
525+
* without calling user code or accessing the communication subsystem. So
526+
* all expressions aside from call, port, chan or spawn, applied to all
527+
* lvals that are themselves constant.
528+
529+
*
530+
* We similarly have multiple subset-categories of lval:
531+
*
532+
* - Name lvals are those that contain no dynamic indices.
533+
*
534+
* - Atomic lvals are those indexed by atomic expressions.
535+
*
536+
* - Constant lvals are those that are only indexed by constant expressions.
537+
*
538+
* Rationales:
539+
*
540+
* - The primitives are those that can be evaluated without adjusting
541+
* reference counts or otherwise perturbing the lifecycle of anything
542+
* dynamically allocated.
543+
*
544+
* - The atomics exist to define the sub-structure of the primitives.
545+
*
546+
* - The constants are those we'll compile to read-only memory, either
547+
* immediates in the code-stream or frags in the .rodata section.
548+
*
549+
* Note:
550+
*
551+
* - Constant-expression-ness is defined in semant, and can only be judged
552+
* after resolve has run and connected idents with bindings.
553+
*)
554+
555+
let rec plval_is_atomic (plval:plval) : bool =
556+
match plval with
557+
PLVAL_ident _
558+
| PLVAL_app _ -> true
559+
560+
| PLVAL_ext_name (p, _) ->
561+
pexp_is_atomic p
562+
563+
| PLVAL_ext_pexp (a, b) ->
564+
(pexp_is_atomic a) &&
565+
(pexp_is_atomic b)
566+
567+
| PLVAL_ext_deref p ->
568+
pexp_is_atomic p
569+
570+
and pexp_is_atomic (pexp:pexp) : bool =
571+
match pexp.node with
572+
PEXP_lval pl -> plval_is_atomic pl
573+
| PEXP_lit _ -> true
574+
| _ -> false
575+
;;
576+
577+
578+
let pexp_is_primitive (pexp:pexp) : bool =
579+
match pexp.node with
580+
PEXP_binop (_, a, b) ->
581+
(pexp_is_atomic a) &&
582+
(pexp_is_atomic b)
583+
| PEXP_unop (_, p) ->
584+
pexp_is_atomic p
585+
| PEXP_lval pl ->
586+
plval_is_atomic pl
587+
| PEXP_lit _ -> true
588+
| _ -> false
589+
;;
514590

515-
(***********************************************************************)
516591

592+
(* Pretty-printing. *)
517593

518594
let fmt_ident (ff:Format.formatter) (i:ident) : unit =
519595
fmt ff "%s" i

trunk/src/boot/me/semant.ml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ type ctxt =
9898
ctxt_slot_keys: (node_id,Ast.slot_key) Hashtbl.t;
9999
ctxt_node_referenced: (node_id, unit) Hashtbl.t;
100100
ctxt_auto_deref_lval: (node_id, bool) Hashtbl.t;
101+
ctxt_plval_const: (node_id,bool) Hashtbl.t;
101102
ctxt_all_item_names: (node_id,Ast.name) Hashtbl.t;
102103
ctxt_all_item_types: (node_id,Ast.ty) Hashtbl.t;
103104
ctxt_all_lval_types: (node_id,Ast.ty) Hashtbl.t;
@@ -185,6 +186,7 @@ let new_ctxt sess abi crate =
185186
ctxt_slot_keys = Hashtbl.create 0;
186187
ctxt_node_referenced = Hashtbl.create 0;
187188
ctxt_auto_deref_lval = Hashtbl.create 0;
189+
ctxt_plval_const = Hashtbl.create 0;
188190
ctxt_all_item_names = Hashtbl.create 0;
189191
ctxt_all_item_types = Hashtbl.create 0;
190192
ctxt_all_lval_types = Hashtbl.create 0;
@@ -1340,6 +1342,87 @@ let expr_type (cx:ctxt) (e:Ast.expr) : Ast.ty =
13401342
| Ast.EXPR_atom a -> atom_type cx a
13411343
;;
13421344

1345+
1346+
let rec pexp_is_const (cx:ctxt) (pexp:Ast.pexp) : bool =
1347+
let check_opt po =
1348+
match po with
1349+
None -> true
1350+
| Some x -> pexp_is_const cx x
1351+
in
1352+
1353+
let check_mut_pexp mut p =
1354+
mut = Ast.MUT_immutable && pexp_is_const cx p
1355+
in
1356+
1357+
match pexp.node with
1358+
Ast.PEXP_call _
1359+
| Ast.PEXP_spawn _
1360+
| Ast.PEXP_port
1361+
| Ast.PEXP_chan _
1362+
| Ast.PEXP_custom _ -> false
1363+
1364+
| Ast.PEXP_bind (fn, args) ->
1365+
(pexp_is_const cx fn) &&
1366+
(arr_for_all
1367+
(fun _ a -> check_opt a)
1368+
args)
1369+
1370+
| Ast.PEXP_rec (elts, base) ->
1371+
(check_opt base) &&
1372+
(arr_for_all
1373+
(fun _ (_, mut, p) ->
1374+
check_mut_pexp mut p)
1375+
elts)
1376+
1377+
| Ast.PEXP_tup elts ->
1378+
arr_for_all
1379+
(fun _ (mut, p) ->
1380+
check_mut_pexp mut p)
1381+
elts
1382+
1383+
| Ast.PEXP_vec (mut, elts) ->
1384+
(arr_for_all
1385+
(fun _ p ->
1386+
check_mut_pexp mut p)
1387+
elts)
1388+
1389+
| Ast.PEXP_binop (_, a, b)
1390+
| Ast.PEXP_lazy_and (a, b)
1391+
| Ast.PEXP_lazy_or (a, b) ->
1392+
(pexp_is_const cx a) &&
1393+
(pexp_is_const cx b)
1394+
1395+
| Ast.PEXP_unop (_, p) -> pexp_is_const cx p
1396+
| Ast.PEXP_lval p ->
1397+
begin
1398+
match htab_search cx.ctxt_plval_const pexp.id with
1399+
None -> plval_is_const cx p
1400+
| Some b -> b
1401+
end
1402+
1403+
| Ast.PEXP_lit _
1404+
| Ast.PEXP_str _ -> true
1405+
1406+
| Ast.PEXP_box (mut, p) ->
1407+
check_mut_pexp mut p
1408+
1409+
and plval_is_const (cx:ctxt) (plval:Ast.plval) : bool =
1410+
match plval with
1411+
Ast.PLVAL_ident _
1412+
| Ast.PLVAL_app _ ->
1413+
bug () "Semant.plval_is_const on plval base"
1414+
1415+
| Ast.PLVAL_ext_name (pexp, _) ->
1416+
pexp_is_const cx pexp
1417+
1418+
| Ast.PLVAL_ext_pexp (a, b) ->
1419+
(pexp_is_const cx a) &&
1420+
(pexp_is_const cx b)
1421+
1422+
| Ast.PLVAL_ext_deref p ->
1423+
pexp_is_const cx p
1424+
;;
1425+
13431426
(* Mappings between mod items and their respective types. *)
13441427

13451428
let arg_slots (slots:Ast.header_slots) : Ast.slot array =

0 commit comments

Comments
 (0)