Guest User

Untitled

a guest
Jul 1st, 2018
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 13.18 KB | None | 0 0
  1. #open "syntaxe";;
  2. #open "envir";;
  3. #open "printf";;
  4.  
  5. let taille_du_mot = 4;;            (* un mot = quatre octets *)
  6.  
  7. let rec taille_du_type = function
  8.   | Integer | Boolean -> taille_du_mot
  9.   | Array(inf, sup, ty) -> (sup - inf + 1) * taille_du_type ty;;
  10. let val_const = function
  11.   | Entière n -> n
  12.   | Booléenne b -> if b then 1 else 0;;
  13. type info_variable =
  14.   { typ: expr_type;
  15.     emplacement: emplacement_variable }
  16. and emplacement_variable =
  17.   | Global_indirect of int
  18.   | Global_direct of int
  19.   | Local_indirect of int
  20.   | Local_direct of int;;
  21. let profondeur_pile = ref 0;;
  22.  
  23. let réserve_pile n =
  24.   printf "sub sp, %d, sp\n" (n*taille_du_mot);
  25.   profondeur_pile := !profondeur_pile + n*taille_du_mot
  26.  
  27. and libère_pile n =
  28.   printf "add sp, %d, sp\n" (n*taille_du_mot);
  29.   profondeur_pile := !profondeur_pile - n*taille_du_mot;;
  30. let rec type_de env = function
  31.   | Constante(Entière n) -> Integer
  32.   | Constante(Booléenne b) -> Boolean
  33.   | Variable nom -> (cherche_variable nom env).typ
  34.   | Application(fonc, args) ->
  35.       (cherche_fonction fonc env).fonc_type_résultat
  36.   | Op_unaire(op, arg) ->
  37.       let (type_arg, type_res) =
  38.         typage__type_op_unaire op
  39.       in type_res
  40.   | Op_binaire(op, arg1, arg2) ->
  41.       let (type_arg1, type_arg2, type_res) =
  42.         typage__type_op_binaire op
  43.       in type_res
  44.   | Accès_tableau(arg1, arg2) ->
  45.       match type_de env arg1 with
  46.       | Array(inf, sup, ty) -> ty
  47.       | _ -> failwith "type de tableau erroné";;
  48. let rec sans_interférences env = function
  49.   | Constante c -> true
  50.   | Variable nom ->
  51.       let var = cherche_variable nom env in
  52.       begin match var.emplacement with
  53.       | Global_indirect _ | Global_direct _ -> false
  54.       | Local_indirect _  | Local_direct _  -> true
  55.       end
  56.   | Application(fonc, args) -> false
  57.   | Op_unaire(op, arg) ->
  58.       sans_interférences env arg
  59.   | Op_binaire(op, arg1, arg2) ->
  60.       sans_interférences env arg1 & sans_interférences env arg2
  61.   | Accès_tableau(arg1, arg2)  ->
  62.       sans_interférences env arg1 & sans_interférences env arg2;;
  63. let dernier_registre = 24;;
  64.  
  65. let rec besoins env = function
  66.   | Constante c -> 0
  67.   | Variable nom -> 0
  68.   | Application(fonc, args) -> dernier_registre
  69.   | Op_unaire(op, arg) -> besoins env arg
  70.   | Op_binaire(op, arg1, arg2) -> besoins_op_binaire env arg1 arg2
  71.   | Accès_tableau(arg1, arg2)  -> besoins_op_binaire env arg1 arg2
  72.  
  73. and besoins_op_binaire env arg1 arg2 =
  74.   let b1 = besoins env arg1 and b2 = besoins env arg2 in
  75.   if b1 < b2
  76.    & (sans_interférences env arg1 or sans_interférences env arg2)
  77.   then max b2 (b1 + 1)
  78.   else max b1 (b2 + 1);;
  79. let instr_pour_op = function
  80.   | "+"   -> "add"     | "-"   -> "sub"
  81.   | "*"   -> "mult"    | "/"   -> "div"
  82.   | "="   -> "seq"     | "<>"  -> "sne"
  83.   | "<"   -> "slt"     | ">"   -> "sgt"
  84.   | "<="  -> "sle"     | ">="  -> "sge"
  85.   | "and" -> "and"     | "or"  -> "or"
  86.   | _ -> failwith "opérateur inconnu";;
  87.  
  88. let rec compile_expr env expr reg =
  89.   match expr with
  90.   | Constante cst ->
  91.       printf "add r 0, %d, r %d\n" (val_const cst) reg
  92.   | Variable nom ->
  93.       let var = cherche_variable nom env in
  94.       begin match var.emplacement with
  95.       | Global_indirect n ->
  96.           printf "load r 0, %d, r %d  # %s \n" n reg nom
  97.       | Global_direct n ->
  98.           printf "add r 0, %d, r %d  # %s \n" n reg nom
  99.       | Local_indirect n ->
  100.           printf "load sp, %d, r %d  # %s \n"
  101.                  (!profondeur_pile - n) reg nom
  102.       | Local_direct n ->
  103.           printf "add sp, %d, r %d  # %s \n"
  104.                  (!profondeur_pile - n) reg nom
  105.       end
  106.   | Application(fonc, arguments) ->
  107.       let nbr_args = list_length arguments in
  108.       réserve_pile nbr_args;
  109.       let position = ref 0 in
  110.       do_list (function arg ->
  111.                 compile_expr env arg 1;
  112.                 printf "store sp, %d, r 1\n" !position;
  113.                 position := !position + taille_du_mot)
  114.               arguments;
  115.       printf "jmp F%s, ra\n" fonc;
  116.       libère_pile nbr_args;
  117.       if reg <> 1 then printf "add r 1, r 0, r %d\n" reg
  118.   | Op_unaire(op, arg) ->
  119.       compile_expr env arg reg;
  120.       begin match op with
  121.       | "-"   -> printf "sub r 0, r %d, r %d\n" reg reg
  122.       | "not" -> printf "seq r 0, r %d, r %d\n"  reg reg
  123.       | _ -> failwith "opérateur uniaire inconnu"
  124.       end
  125.   | Op_binaire(op, arg1, Constante cst2) ->
  126.       compile_expr env arg1 reg;
  127.       printf "%s r %d, %d, r %d\n"
  128.              (instr_pour_op op) reg (val_const cst2) reg
  129.   | Op_binaire(("+" | "*" | "=" | "<>" | "and" | "or") as op,
  130.                Constante cst1, arg2) ->
  131.       compile_expr env arg2 reg;
  132.       printf "%s r %d, %d, r %d\n"
  133.              (instr_pour_op op) reg (val_const cst1) reg
  134.   | Op_binaire(op, arg1, arg2) ->
  135.       let (reg1, reg2) = compile_arguments env arg1 arg2 reg in      
  136.       printf "%s r %d, r %d, r %d\n" (instr_pour_op op) reg1 reg2 reg
  137.   | Accès_tableau(arg1, Constante cst) ->
  138.       begin match type_de env arg1 with
  139.       | Array(inf, sup, type_éléments) ->
  140.          compile_expr env arg1 reg;
  141.          begin match type_éléments with
  142.          | Integer | Boolean ->
  143.              printf "load r %d, %d, r %d\n" reg
  144.                     ((val_const cst - inf) * taille_du_mot) reg
  145.          | Array(_, _, _) ->
  146.              let taille = taille_du_type type_éléments in
  147.              printf "add r %d, %d, r %d\n"
  148.                     reg ((val_const cst - inf) * taille) reg
  149.          end
  150.       | _ -> failwith "Erreur dans le contrôleur de types" end
  151.   | Accès_tableau(arg1, arg2) ->
  152.       begin match type_de env arg1 with
  153.       | Array(inf, sup, type_éléments) ->
  154.          let (reg1, reg2) = compile_arguments env arg1 arg2 reg in
  155.          if inf <> 0 then printf "sub r %d, %d, r %d\n" reg2 inf reg2;
  156.          begin match type_éléments with
  157.          | Integer | Boolean ->
  158.              printf "mult r %d, %d, r %d\n" reg2 taille_du_mot reg2;
  159.              printf "load r %d, r %d, r %d\n" reg1 reg2 reg
  160.          | Array(_, _, typ) ->
  161.              let taille = taille_du_type type_éléments in
  162.              printf "mult r %d, %d, r %d\n" reg2 taille reg2;
  163.              printf "add r %d, r %d, r %d\n" reg1 reg2 reg
  164.          end
  165.       | _ -> failwith "Erreur dans le contrôleur de types" end
  166.  
  167. and compile_arguments env arg1 arg2 reg_libre =
  168.   let b1 = besoins env arg1 and b2 = besoins env arg2 in
  169.   if b1 < b2
  170.    & (sans_interférences env arg1 or sans_interférences env arg2)
  171.   then begin
  172.     let (reg2, reg1) = compile_arguments env arg2 arg1 reg_libre in
  173.     (reg1, reg2)
  174.   end else begin
  175.     compile_expr env arg1 reg_libre;
  176.     if b2 < dernier_registre - reg_libre then begin
  177.       compile_expr env arg2 (reg_libre + 1);
  178.       (reg_libre, reg_libre + 1)
  179.     end else begin
  180.       réserve_pile 1;
  181.       printf "store sp, 0, r %d\n" reg_libre;
  182.       compile_expr env arg2 reg_libre;
  183.       printf "load sp, 0, r 29\n";
  184.       libère_pile 1;
  185.       (29, reg_libre)
  186.     end
  187.   end;;
  188. let compteur_d'étiquettes = ref 0;;
  189.  
  190. let nouvelle_étiq () =
  191.   incr compteur_d'étiquettes; !compteur_d'étiquettes;;
  192.  
  193. let rec compile_instr env = function
  194.   | Affectation_var(nom_var,
  195.                     Constante(Entière 0 | Booléenne false)) ->
  196.       affecte_var env nom_var 0
  197.   | Affectation_var(nom_var, expr) ->
  198.       compile_expr env expr 1;
  199.       affecte_var env nom_var 1
  200.   | Affectation_tableau(expr1, Constante cst2, expr3) ->
  201.       begin match type_de env expr1 with
  202.       | Array(inf, sup, type_éléments) ->
  203.          let (reg3, reg1) = compile_arguments env expr3 expr1 1 in
  204.          printf "store r %d, %d, r %d\n"
  205.                 reg1 ((val_const cst2 - inf) * taille_du_mot) reg3
  206.       | _ -> failwith "Erreur dans le contrôleur de types" end
  207.   | Affectation_tableau(expr1, expr2, expr3) ->
  208.       begin match type_de env expr1 with
  209.       | Array(inf, sup, type_éléments) ->
  210.          compile_expr env expr3 1;
  211.          let (reg1, reg2) = compile_arguments env expr1 expr2 2 in
  212.          if inf <> 0 then printf "sub r %d, %d, r %d\n" reg2 inf reg2;
  213.          printf "mult r %d, %d, r %d\n" reg2 taille_du_mot reg2;
  214.          printf "store r %d, r %d, r %d\n" reg1 reg2 1
  215.       | _ -> failwith "Erreur dans le contrôleur de types" end
  216.   | Appel(proc, arguments) ->
  217.       let nbr_args = list_length arguments in
  218.       réserve_pile nbr_args;
  219.       let position = ref 0 in
  220.       do_list (function arg ->
  221.                 compile_expr env arg 1;
  222.                 printf "store sp, %d, r 1\n" !position;
  223.                 position := !position + taille_du_mot)
  224.               arguments;
  225.       printf "jmp P%s, ra\n" proc;
  226.       libère_pile nbr_args
  227.   | If(condition, branche_oui, Bloc []) ->
  228.       let étiq_fin = nouvelle_étiq() in
  229.       compile_expr env condition 1;
  230.       printf "braz r 1, L%d\n" étiq_fin;
  231.       compile_instr env branche_oui;
  232.       printf "L%d:\n" étiq_fin
  233.   | If(condition, Bloc [], branche_non) ->
  234.       let étiq_fin = nouvelle_étiq() in
  235.       compile_expr env condition 1;
  236.       printf "branz r 1, L%d\n" étiq_fin;
  237.       compile_instr env branche_non;
  238.       printf "L%d:\n" étiq_fin
  239.   | If(Op_unaire("not", condition), branche_oui, branche_non) ->
  240.       compile_instr env (If(condition, branche_non, branche_oui))
  241.   | If(condition, branche_oui, branche_non) ->
  242.       let étiq_non = nouvelle_étiq() and étiq_fin = nouvelle_étiq() in
  243.       compile_expr env condition 1;
  244.       printf "braz r 1, L%d\n" étiq_non;
  245.       compile_instr env branche_oui;
  246.       printf "braz r 0, L%d\n" étiq_fin;
  247.       printf "L%d:\n" étiq_non;
  248.       compile_instr env branche_non;
  249.       printf "L%d:\n" étiq_fin
  250.   | While(condition, corps) ->
  251.       let étiq_corps = nouvelle_étiq()
  252.       and étiq_test = nouvelle_étiq() in
  253.       printf "braz r 0, L%d\n" étiq_test;
  254.       printf "L%d:\n" étiq_corps;
  255.       compile_instr env corps;
  256.       printf "L%d:\n" étiq_test;
  257.       compile_expr env condition 1;
  258.       printf "branz r 1, L%d\n" étiq_corps
  259.   | Write expr ->
  260.       compile_expr env expr 1;
  261.       printf "write\n"
  262.   | Read nom_var ->
  263.       printf "read\n";
  264.       affecte_var env nom_var 1
  265.   | Bloc liste_instr ->
  266.       do_list (compile_instr env) liste_instr
  267.  
  268. and affecte_var env nom reg =
  269.   let var = cherche_variable nom env in
  270.   match var.emplacement with
  271.   | Global_indirect n ->
  272.       printf "store r 0, %d, r %d  # %s \n" n reg nom
  273.   | Local_indirect n ->
  274.       printf "store sp, %d, r %d  # %s \n"
  275.              (!profondeur_pile - n) reg nom
  276.   | _ -> failwith "mauvaise gestion des emplacements de varaibles";;
  277. let alloue_variable_locale (nom, typ) env =
  278.   profondeur_pile := !profondeur_pile + taille_du_type typ;
  279.   let emplacement =
  280.     match typ with
  281.     | Integer | Boolean ->
  282.         Local_indirect(!profondeur_pile)
  283.     | Array(_, _, _) ->
  284.         Local_direct(!profondeur_pile) in
  285.   ajoute_variable nom {typ=typ; emplacement=emplacement} env;;
  286.  
  287. let alloue_paramètres liste_des_paramètres environnement =
  288.   let prof = ref 0 in
  289.   let env = ref environnement in
  290.   do_list
  291.    (function (nom,typ) ->
  292.       env := ajoute_variable nom
  293.               {typ=typ;
  294.                emplacement = Local_indirect !prof}
  295.               !env;
  296.       prof := !prof - taille_du_mot)
  297.     liste_des_paramètres;
  298.   !env;;
  299.  
  300. let compile_procédure env (nom, décl) =
  301.   let env1 =
  302.     alloue_paramètres décl.proc_paramètres env in
  303.   profondeur_pile := taille_du_mot;
  304.   let env2 =
  305.     list_it alloue_variable_locale décl.proc_variables env1 in
  306.   printf "P%s:\n" nom;
  307.   printf "sub sp, %d, sp\n" !profondeur_pile;
  308.   printf "store sp, %d, ra\n" (!profondeur_pile - taille_du_mot);
  309.   compile_instr env2 décl.proc_corps;
  310.   printf "load sp, %d, ra\n" (!profondeur_pile - taille_du_mot);
  311.   printf "add sp, %d, sp\n" !profondeur_pile;
  312.   printf "jmp ra, r 0\n";;
  313.  
  314. let compile_fonction env (nom, décl) =
  315.   let env1 =
  316.     alloue_paramètres décl.fonc_paramètres env in
  317.   profondeur_pile := taille_du_mot;
  318.   let env2 =
  319.     list_it alloue_variable_locale décl.fonc_variables env1 in
  320.   let env3 =
  321.     alloue_variable_locale (nom, décl.fonc_type_résultat) env2 in
  322.   printf "F%s:\n" nom;
  323.   printf "sub sp, %d, sp\n" !profondeur_pile;
  324.   printf "store sp, %d, ra\n" (!profondeur_pile - taille_du_mot);
  325.   compile_instr env3 décl.fonc_corps;
  326.   printf "load sp, 0, r 1\n";
  327.   printf "load sp, %d, ra\n" (!profondeur_pile - taille_du_mot);
  328.   printf "add sp, %d, sp\n" !profondeur_pile;
  329.   printf "jmp ra, r 0\n";;
  330. let adresse_donnée = ref 0;;
  331.  
  332. let alloue_variable_globale (nom, typ) env =
  333.   let emplacement =
  334.     match typ with
  335.     | Integer | Boolean -> Global_indirect(!adresse_donnée)
  336.     | Array(_, _, _)    -> Global_direct(!adresse_donnée) in
  337.   adresse_donnée := !adresse_donnée + taille_du_type typ;
  338.   ajoute_variable nom {typ=typ; emplacement=emplacement} env;;
  339.  
  340. let compile_programme prog =
  341.   adresse_donnée := 0;
  342.   let env_global =
  343.     list_it alloue_variable_globale prog.prog_variables
  344.             (environnement_initial prog.prog_procédures
  345.                                    prog.prog_fonctions) in
  346.   compile_instr env_global prog.prog_corps;
  347.   printf "stop\n";
  348.   do_list (compile_procédure env_global) prog.prog_procédures;
  349.   do_list (compile_fonction env_global) prog.prog_fonctions;;
Add Comment
Please, Sign In to add comment