1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
(****************************************
primitives.mli - ... les primitives
[o'rly ?]
****************************************)
open Mips
open Mipshelpers
open Ast
module Sset = Set.Make(String)
module Smap = Map.Make(String)
(* Les codes des primitives *)
let print_int_code =
[Move (A0, A1) ;
Li (V0, 1) ; (* print_int *)
Syscall ;
Jr RA]
let print_string_code =
[Move (A0, A1) ;
Li (V0, 4) ; (* print_string *)
Syscall ;
Jr RA]
let print_newline_code =
[Li (A0, 10) ;
Li (V0, 11) ; (* print_char *)
Syscall ;
Jr RA]
let read_int_code =
[Li (V0, 5) ; (* read_int *)
Syscall ;
Jr RA]
let read_line_code =
(malloc 1024)
@
[Move (A0, V0) ;
Li (A1, 1024) ; (* on alloue ici un (gros) buffer
une version plus propre aurait été de faire
une boucle, accumulant les chars sur la pile
jusqu'à trouver un \n, allouant la bonne quantité
de mémoire et dépilant les chars ; mais TODO pour
l'instant *)
Li (V0, 8) ; (* read_string *)
Syscall ;
Move (V0, A0) ;
Jr RA]
(* Le petit helper qui génère le code "d'enregistrement" d'une primitive,
code qui sera exécuté au début du main *)
let primitive_register_code fname =
[La (T1, fname)]
@
(malloc 4)
@
[Sw (T1, (0, V0))]
(* Petits helpers utiles pour la détermination des primitives utilisées
et la génération du code (pour l'assignation de labels non utilisés) *)
let primitives = [("print_int", print_int_code) ;
("print_string", print_string_code) ;
("print_newline", print_newline_code) ;
("read_int", read_int_code) ;
("read_line", read_line_code)]
let primitives_map, primitives_set =
let rec aux = function
| [] -> Smap.empty, Sset.empty
| (id, code)::l ->
let map, set = aux l
in
Smap.add id code map, Sset.add id set
in
aux primitives
let in_use_primitives idents =
Sset.elements (Sset.inter idents primitives_set)
|