summaryrefslogtreecommitdiff
path: root/primitives.ml
blob: 2b50c0b43bdf27983b77fe165b628c0d87091099 (plain)
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)