SVM in Fsharp

01/12/2014

Obbiettivo di questo progetto è realizzare una macchina virtuale che esegua una serie di operazioni tra lista e registri stampandoci un output a video. Daremo le operazioni in input attraverso un file txt aggiunto al opportunamente al progetto (aggiungi nuovo elemento nel menu di destra su Visual Studio) . Un esempio di file di operazioni può essere questo (test.txt nel codice del programma) :


# first line
mov [0] 0
mov [1] 1
mov [2] 0
mov [3] 0
mov [4] 1

# second line
mov [10] 1
mov [11] 1
mov [12] 0
mov [13] 0
mov [14] 0

#xor on the first element
mov reg1 [4]
mov reg2 [14]
not reg3 reg1
not reg4 reg2
and reg1 reg4
and reg2 reg3
or reg1 reg2
mov [24] reg1

#xor on the second element
mov reg1 [3]
mov reg2 [13]
not reg3 reg1
not reg4 reg2
and reg1 reg4
and reg2 reg3
or reg1 reg2
mov [23] reg1

#xor on the third element
mov reg1 [2]
mov reg2 [12]
not reg3 reg1
not reg4 reg2
and reg1 reg4
and reg2 reg3
or reg1 reg2
mov [22] reg1

#xor on the fourth element
mov reg1 [1]
mov reg2 [11]
not reg3 reg1
not reg4 reg2
and reg1 reg4
and reg2 reg3
or reg1 reg2
mov [21] reg1

#xor on the fifth element
mov reg1 [0]
mov reg2 [10]
not reg3 reg1
not reg4 reg2
and reg1 reg4
and reg2 reg3
or reg1 reg2
mov [20] reg1

#end of program
end

Il nostro programma deve prendere ogni singola istruzione ed analizzarla come lista di caratteri. Dunque definiremo un codice capace di capire qual'è la funzione chiamata sulla base dei primi 3 caratteri letti:
Per esempio se la lista di caratteri è ['M'; 'O'; 'V'; ecc] noi andremo a chiamare la funzione MOV alla quale passiamo poi la restante parte della lista.

Queste è la tabella che ci spiega quali istruzioni è in grado di eseguire il nostro programma:
upload

Ed ecco di seguito il codice completo del programma:


open SVMLibrary

type Record = { REG1 : float; REG2: float; REG3: float; REG4: float; lista: int list; contatore : int; }

//run the program on the SVM -- call your functions in here.
let run_svm (program : string list) : string =


(* 
    fatto: Funzioni: AND ; OR; NOP; END; NOT ; MOD; ADD; SUB; MUL; DIV; MOV; CUT   ->>> ATTENZIONE

*)


        //CREO LISTA da 100 caratteri tutti 0
        let rec lista (n : int) (counter : int) =
            match counter with
            |0 -> []
            |_ -> [n]@lista n (counter-1) 
        

        let lista2 = lista 0 100

        //definisco registri
        let myrecord = { REG1 = 0.0; REG2 = 0.0; REG3 = 0.0; REG4 = 0.0; contatore = 0; lista = lista2; }

        //funzione che aggiorna i registri
        let cambia_record ( p : Record) ( reg_aggiornato1 : float ) ( reg_aggiornato2 : float ) ( reg_aggiornato3 : float )  ( reg_aggiornato4 : float ) ( contatore_aggiornato : int ) ( lista_aggiornata : int list ) : Record = { myrecord with REG1 = ( reg_aggiornato1 ); REG2 = ( reg_aggiornato2 ); REG3 = ( reg_aggiornato3 ); REG4 = ( reg_aggiornato4 ); contatore = ( contatore_aggiornato ); lista = ( lista_aggiornata ); }

        //Funzioni di aiuto
        let analisi_reg stringa myrecord =
            match stringa with
            |[y; z; w] -> if y='E' && z='G' && w='1' then myrecord.REG1
                          elif y='E' && z='G' && w='2' then myrecord.REG2
                          elif y='E' && z='G' && w='3' then myrecord.REG3
                          elif y='E' && z='G' && w='4' then myrecord.REG4
                          else failwith "Istruzione sbagliata. 0.1"
            |_ -> failwith "Istruzione sbagliata. 0.2"

        let analisi_lista lista myrecord =
            match lista with
            |[y; z] -> if z=']' then char_to_int y
                       else failwith "Istruzione sbagliata. 0.3"
            |[y; z; w] -> if w=']' then ((char_to_int y)*10) + (char_to_int z)
                          else failwith "Istruzione sbagliata. 0.4"
            |[y; z; w; t] -> if t=']' then ((char_to_int y)*100) + ((char_to_int z)*10) + (char_to_int w)
                             else failwith "Istruzione sbagliata. 0.5"
            |_ -> failwith "Istruzione sbagliata. 0.6"
            (* la lista è composta da massimo 100 elementi *)

        let rec prendi_dalla_lista (numero : int) contatore lista myrecord =
            match lista, contatore with
            |[], _ -> failwith "Errore nella lista." 
            |x::xs, contatore -> if (contatore) < numero then  prendi_dalla_lista numero (contatore+1) xs myrecord
                                 else float (x)
            |_ -> failwith "C'è qualche errore 0"

        let rec analisi_int lista myrecord = (string_to_float (list_to_string lista))
        
        let rec trova lista counter =
            match lista, counter with
            |[], counter -> counter
            |[x], counter -> counter+1
            |x::xs, counter -> if x = ']' then counter+1 else trova xs (counter+1)

        let rec elimina_parte_in_piu lista conta numero = //conta 0 and numero da trova - 1
            match lista, conta with
            |[], conta -> []
            |[x], conta -> if conta = numero then [x] else []
            |x::xs, conta -> if conta = numero then [x] else [x]@elimina_parte_in_piu xs (conta+1) numero
                  
        let rec determino_contatore lista myrecord =
            match elimina_parte_in_piu (lista) 0 ((trova lista 0)-1) with
            |[x] -> if x=']' then [] else [x]
            |x::xs -> if x=']' then [] else [x]@determino_contatore (xs) myrecord
            |_ -> failwith "Errore nella dichiarazione di un indirizzo."

        let rec seconda_parte_lista lista myrecord =
            match lista with
            |x::xs -> if x=']' then xs else seconda_parte_lista xs myrecord
            |_ -> failwith "Istruzione sbagliata. 0.7"
            (* la lista è composta da massimo 3 cifre *)

        let capiscoprimapartereg lista myrecord = 
            match lista with
            |x::y::z::w::xs ->
            if x='R' && y='E' && z='G' && w='1' then myrecord.REG1
            elif x='R' && y='E' && z='G' && w='2' then myrecord.REG2
            elif x='R' && y='E' && z='G' && w='3' then myrecord.REG3
            elif x='R' && y='E' && z='G' && w='4' then myrecord.REG4
            else failwith "Hai specificato in modo errato qualche comando. 0.1"
            |_ -> failwith "Hai specificato in modo errato qualche comando. 0.2"

        let prendosecondapartereg lista myrecord = 
            match lista with
            |[x;y;z;w] -> []
            |x::y::z::w::xs -> xs
            |_ -> failwith "Hai specificato in modo errato qualche comando. 0.3"

        let capiscosecondapartereg lista myrecord = 
            match lista with
            |[x] -> float (char_to_int x)
            |x::xs -> if x='R' then analisi_reg xs myrecord
                      elif x='[' then prendi_dalla_lista (analisi_lista xs myrecord) 0 myrecord.lista myrecord
                      else analisi_int ([x]@xs) myrecord
            |_ -> failwith "Hai specificato in modo errato qualche comando. 0.4"

        //funzione elimina spazi vuoti su xs
        let rec pulisci stringa = 
            match stringa with
            |[] -> []
            |[x] -> if x = ' ' then [] else [x]
            |x::xs -> if x = ' ' then pulisci xs else [x]@pulisci xs

        //funzione che aggiorna la lista di interi finale
        let rec aggiorna_lista (lista : char list) myrecord ( posizione : int ) ( contatore : int ) ( lista2 : int list )=
            match lista2, contatore with
            |[], contatore -> failwith "C'è qualche errore 1"
            |[x], contatore -> if contatore = posizione then [(int (capiscosecondapartereg (seconda_parte_lista lista myrecord) myrecord))]
                               else [x]
            |x::xs, contatore -> if contatore < 100 then
                                    if contatore = posizione then [(int (capiscosecondapartereg (seconda_parte_lista lista myrecord) myrecord))]@aggiorna_lista lista myrecord posizione (contatore+1) xs
                                    else [x]@aggiorna_lista lista myrecord posizione (contatore+1) xs
                                 else
                                    if contatore = posizione then [(int (capiscosecondapartereg (seconda_parte_lista lista myrecord) myrecord))]
                                    else [x]

        let rec aggiorna_lista_2 myrecord ( posizione : int ) ( contatore : int ) ( lista2 : int list )=
            match lista2, contatore with
            |[], contatore -> failwith "C'è qualche errore 2"
            |[x], contatore -> if contatore = posizione then [0]
                               else [x]
            |x::xs, contatore -> if contatore < 100 then
                                    if contatore = posizione then [0]@aggiorna_lista_2 myrecord posizione (contatore+1) xs
                                    else [x]@aggiorna_lista_2 myrecord posizione (contatore+1) xs
                                 else
                                    if contatore = posizione then [0]
                                    else [x]

        let mov_con_reg lista myrecord =
            match lista with
            |y::z::w::xs -> // <<<>>> va analizzato xs perchè deve essere azzerato
                        if y='E' && z='G' && w='1' then 
                           cambia_record myrecord ((capiscosecondapartereg (xs) myrecord)) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif y='E' && z='G' && w='2' then
                             cambia_record myrecord (myrecord.REG1) ((capiscosecondapartereg (xs) myrecord)) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif y='E' && z='G' && w='3' then
                             cambia_record myrecord  (myrecord.REG1) (myrecord.REG2) ((capiscosecondapartereg (xs) myrecord)) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif y='E' && z='G' && w='4' then
                             cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) ((capiscosecondapartereg (xs) myrecord)) (myrecord.contatore+1) (myrecord.lista)
                        else failwith "Verifica MOV"
             |_ -> failwith "Verifica MOV"
        
        let mov_lista xs myrecord = cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (aggiorna_lista xs myrecord (int(analisi_int (determino_contatore (xs) myrecord) myrecord )) 0 myrecord.lista)

        //Funzioni della SVM
        let funzione_end myrecord = cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)

        let funzione_nop myrecord = cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)

        (* <<<---ATTENZIONE: la funzione cut ha bisogno di molti più casi rispetto alle altre. Nella prima parte concesso anche un registro di memoria.
        Poi nella seconda parte va azzerata e copiato il contenuto nella prima. Quindi devo capire se si tratta di:
        Registro - registro
        Registro - lista
        Registro - costante
        Lista - registro
        Lista - costante
        Lista - lista
         --->>> *)

        (*  <<<<---!!!! ATTENZIONE:_ Questa è la funzione sposta (CUT) che non è richiesta e copiato il valore da arg2 ad arg1 azzera arg2 !!!!--->>>> *)

        let funzione_cut (listacaratteri: char list) myrecord =
                match pulisci (listacaratteri) with
                |x::xs ->
                if x='R' then 
                    match prendosecondapartereg (pulisci (listacaratteri)) myrecord with
                    |[x] -> mov_con_reg xs myrecord
                    |[x; y] -> mov_con_reg xs myrecord
                    |[x; y; z] -> if x='[' && z =']' then cambia_record (mov_con_reg xs myrecord) ((mov_con_reg xs myrecord).REG1) ((mov_con_reg xs myrecord).REG2) ((mov_con_reg xs myrecord).REG3) ((mov_con_reg xs myrecord).REG4) ((mov_con_reg xs myrecord).contatore) (aggiorna_lista_2 myrecord (int(analisi_int [y] (mov_con_reg xs myrecord))) 0 (mov_con_reg xs myrecord).lista)
                                  else mov_con_reg xs myrecord
                    |[x;y;z;w] -> if x='[' && w =']' then cambia_record (mov_con_reg xs myrecord) ((mov_con_reg xs myrecord).REG1) ((mov_con_reg xs myrecord).REG2) ((mov_con_reg xs myrecord).REG3) ((mov_con_reg xs myrecord).REG4) ((mov_con_reg xs myrecord).contatore) (aggiorna_lista_2 myrecord (int(analisi_int [y; z] (mov_con_reg xs myrecord))) 0 (mov_con_reg xs myrecord).lista)
                                  elif x='R' && y='E' && z ='G' && w='1' then cambia_record (mov_con_reg xs myrecord) (0.0) ((mov_con_reg xs myrecord).REG2) ((mov_con_reg xs myrecord).REG3) ((mov_con_reg xs myrecord).REG4) ((mov_con_reg xs myrecord).contatore) ((mov_con_reg xs myrecord).lista)
                                  elif x='R' && y='E' && z ='G' && w='2' then cambia_record (mov_con_reg xs myrecord) ((mov_con_reg xs myrecord).REG1) (0.0) ((mov_con_reg xs myrecord).REG3) ((mov_con_reg xs myrecord).REG4) ((mov_con_reg xs myrecord).contatore) ((mov_con_reg xs myrecord).lista)
                                  elif x='R' && y='E' && z ='G' && w='3' then cambia_record (mov_con_reg xs myrecord) ((mov_con_reg xs myrecord).REG1) ((mov_con_reg xs myrecord).REG2) (0.0) ((mov_con_reg xs myrecord).REG4) ((mov_con_reg xs myrecord).contatore) ((mov_con_reg xs myrecord).lista)
                                  elif x='R' && y='E' && z ='G' && w='4' then cambia_record (mov_con_reg xs myrecord) ((mov_con_reg xs myrecord).REG1) ((mov_con_reg xs myrecord).REG2) ((mov_con_reg xs myrecord).REG3) (0.0) ((mov_con_reg xs myrecord).contatore) ((mov_con_reg xs myrecord).lista)
                                  else mov_con_reg xs myrecord
                    |_ -> failwith "Errore nella funzione MOV. 0.0"
                elif x='[' then 
                    match seconda_parte_lista (pulisci (listacaratteri)) myrecord with
                    |[x] -> cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (aggiorna_lista xs myrecord (int(analisi_int (determino_contatore (xs) myrecord) myrecord )) 0 myrecord.lista)
                    |[x; y] -> cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (aggiorna_lista xs myrecord (int(analisi_int (determino_contatore (xs) myrecord) myrecord )) 0 myrecord.lista)
                    |[x; y; z] -> if x='[' && z =']' then cambia_record (mov_lista xs myrecord) ((mov_lista xs myrecord).REG1) ((mov_lista xs myrecord).REG2) ((mov_lista xs myrecord).REG3) ((mov_lista xs myrecord).REG4) ((mov_lista xs myrecord).contatore) (aggiorna_lista_2 myrecord (int(analisi_int [y] (mov_lista xs myrecord))) 0 (mov_lista xs myrecord).lista)
                                  else cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (aggiorna_lista xs myrecord (int(analisi_int (determino_contatore (xs) myrecord) myrecord )) 0 myrecord.lista)
                    |[x;y;z;w] -> if x='[' && w =']' then cambia_record (mov_lista xs myrecord) ((mov_lista xs myrecord).REG1) ((mov_lista xs myrecord).REG2) ((mov_lista xs myrecord).REG3) ((mov_lista xs myrecord).REG4) ((mov_lista xs myrecord).contatore) (aggiorna_lista_2 myrecord (int(analisi_int [y; z] (mov_lista xs myrecord))) 0 (mov_lista xs myrecord).lista)
                                  elif x='R' && y='E' && z ='G' && w='1' then cambia_record (mov_lista xs myrecord) (0.0) ((mov_lista xs myrecord).REG2) ((mov_lista xs myrecord).REG3) ((mov_lista xs myrecord).REG4) ((mov_lista xs myrecord).contatore) ((mov_lista xs myrecord).lista)
                                  elif x='R' && y='E' && z ='G' && w='2' then cambia_record (mov_lista xs myrecord) ((mov_lista xs myrecord).REG1) (0.0) ((mov_lista xs myrecord).REG3) ((mov_lista xs myrecord).REG4) ((mov_lista xs myrecord).contatore) ((mov_lista xs myrecord).lista)
                                  elif x='R' && y='E' && z ='G' && w='3' then cambia_record (mov_lista xs myrecord) ((mov_lista xs myrecord).REG1) ((mov_lista xs myrecord).REG2) (0.0) ((mov_lista xs myrecord).REG4) ((mov_lista xs myrecord).contatore) ((mov_lista xs myrecord).lista)
                                  elif x='R' && y='E' && z ='G' && w='4' then cambia_record (mov_lista xs myrecord) ((mov_lista xs myrecord).REG1) ((mov_lista xs myrecord).REG2) ((mov_lista xs myrecord).REG3) (0.0) ((mov_lista xs myrecord).contatore) ((mov_lista xs myrecord).lista)
                                  else mov_con_reg xs myrecord
                    |_ -> failwith "Errore nella funzione MOV. 0.0"
                //cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (aggiorna_lista xs myrecord (int(analisi_int (determino_contatore (xs) myrecord) myrecord )) 0 myrecord.lista)
                else failwith "Errore nella funzione MOV. 0.1"
                |_ -> failwith "Errore nella funzione MOV. 0.2"


        let funzione_mov (listacaratteri: char list) myrecord =
                match pulisci (listacaratteri) with
                |x::xs ->
                if x='R' then mov_con_reg xs myrecord
                elif x='[' then mov_lista xs myrecord
                else failwith "Errore nella funzione MOV. 0.1"
                |_ -> failwith "Errore nella funzione MOV. 0.2"

        let funzione_and (listacaratteri: char list) myrecord =
            match pulisci (listacaratteri) with
                |x::y::z::w::xs ->
                 if int (capiscoprimapartereg (pulisci listacaratteri) myrecord) > 1 || int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) > 1 || int (capiscoprimapartereg (pulisci listacaratteri) myrecord) < 0 || int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) < 0 then failwith "Valori non concessi nella funzione AND. Accetto solo 0 o 1."
                 else
                        if x='R' && y='E' && z='G' && w='1' then 
                            if int (capiscoprimapartereg (pulisci listacaratteri) myrecord) = 1 && int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) = 1 then cambia_record myrecord (1.0) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                            else cambia_record myrecord (0.0) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='2' then
                            if int (capiscoprimapartereg (pulisci listacaratteri) myrecord) = 1 && int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) = 1 then cambia_record myrecord (myrecord.REG1) (1.0) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                            else cambia_record myrecord (myrecord.REG1) (0.0) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='3' then
                            if int (capiscoprimapartereg (pulisci listacaratteri) myrecord) = 1 && int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) = 1 then cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (1.0) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                            else cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (0.0) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='4' then
                            if int (capiscoprimapartereg (pulisci listacaratteri) myrecord) = 1 && int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) = 1 then cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (1.0) (myrecord.contatore+1) (myrecord.lista)
                            else cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (0.0) (myrecord.contatore+1) (myrecord.lista)
                        else failwith "Verifica AND."
                |_ -> failwith "Errore nella funzione AND."
        

        let funzione_or (listacaratteri: char list) myrecord =
            match pulisci (listacaratteri) with
                |x::y::z::w::xs ->
                if int (capiscoprimapartereg (pulisci listacaratteri) myrecord) > 1 || int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) > 1 || int (capiscoprimapartereg (pulisci listacaratteri) myrecord) < 0 || int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) < 0 then failwith "Valori non concessi nella funzione OR. Accetto solo 0 o 1."
                else
                        if x='R' && y='E' && z='G' && w='1' then 
                            if int (capiscoprimapartereg (pulisci listacaratteri) myrecord) = 0 && int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) = 0 then cambia_record myrecord (0.0) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                            else cambia_record myrecord (1.0) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='2' then
                            if int (capiscoprimapartereg (pulisci listacaratteri) myrecord) = 0 && int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) = 0 then cambia_record myrecord (myrecord.REG1) (0.0) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                            else cambia_record myrecord (myrecord.REG1) (1.0) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='3' then
                            if int (capiscoprimapartereg (pulisci listacaratteri) myrecord) = 0 && int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) = 0 then cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (0.0) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                            else cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (1.0) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='4' then
                            if int (capiscoprimapartereg (pulisci listacaratteri) myrecord) = 0 && int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) = 0 then cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (0.0) (myrecord.contatore+1) (myrecord.lista)
                            else cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (1.0) (myrecord.contatore+1) (myrecord.lista)
                        else failwith "Verifica OR."
                |_ -> failwith "Errore nella funzione OR."
        

        let funzione_not (listacaratteri: char list) myrecord =
                match pulisci (listacaratteri) with
                |x::y::z::w::xs ->
                if int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) > 1 || int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) < 0 then failwith "Valori non concessi nella funzione OR. Accetto solo 0 o 1 per ARG2."
                else
                        if x='R' && y='E' && z='G' && w='1' then 
                            if int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) = 0 then cambia_record myrecord (1.0) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                            else cambia_record myrecord (0.0) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='2' then
                            if int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) = 0 then cambia_record myrecord (myrecord.REG1) (1.0) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                            else cambia_record myrecord (myrecord.REG1) (0.0) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='3' then
                            if int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) = 0 then cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (1.0) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                            else cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (0.0) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='4' then
                            if int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) = 0 then cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (1.0) (myrecord.contatore+1) (myrecord.lista)
                            else cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (0.0) (myrecord.contatore+1) (myrecord.lista)
                        else failwith "Verifica NOT."
                |_ -> failwith "Errore nella funzione NOT."

        let funzione_mod (listacaratteri: char list) myrecord =
                match pulisci (listacaratteri) with
                |x::y::z::w::xs ->
                        if x='R' && y='E' && z='G' && w='1' then 
                            cambia_record myrecord (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))%(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='2' then
                            cambia_record myrecord (myrecord.REG1) (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))%(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='3' then
                            cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))%(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='4' then
                            cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))%(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.contatore+1) (myrecord.lista)
                        else failwith "Verifica MOD."
                |_ -> failwith "Errore nella funzione MOD."

        let funzione_add (listacaratteri: char list) myrecord =
                match pulisci (listacaratteri) with
                |x::y::z::w::xs ->
                        if x='R' && y='E' && z='G' && w='1' then 
                            cambia_record myrecord (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))+(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='2' then
                            cambia_record myrecord (myrecord.REG1) (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))+(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='3' then
                            cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))+(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='4' then
                            cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))+(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.contatore+1) (myrecord.lista)
                        else failwith "Verifica ADD."
                |_ -> failwith "Errore nella funzione ADD."

        let funzione_sub (listacaratteri: char list) myrecord = 
                match pulisci (listacaratteri) with
                |x::y::z::w::xs ->
                        if x='R' && y='E' && z='G' && w='1' then 
                            cambia_record myrecord (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))-(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='2' then
                            cambia_record myrecord (myrecord.REG1) (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))-(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='3' then
                            cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))-(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='4' then
                            cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))-(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.contatore+1) (myrecord.lista)
                        else failwith "Verifica SUB."
                |_ -> failwith "Errore nella funzione SUB."

        let funzione_mul (listacaratteri: char list) myrecord =
                match pulisci (listacaratteri) with
                |x::y::z::w::xs ->
                        if x='R' && y='E' && z='G' && w='1' then 
                            cambia_record myrecord (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))*(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='2' then
                            cambia_record myrecord (myrecord.REG1) (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))*(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='3' then
                            cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))*(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='4' then
                            cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))*(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.contatore+1) (myrecord.lista)
                        else failwith "Verifica MUL."
                |_ -> failwith "Errore nella funzione MUL."

        let funzione_div (listacaratteri: char list) myrecord =
                match pulisci (listacaratteri) with
                |x::y::z::w::xs ->
                if int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord) = 0 then failwith "Valori non concessi nella funzione DIV. Non posso dividere per 0."
                else
                        if x='R' && y='E' && z='G' && w='1' then 
                            cambia_record myrecord (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))/(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.REG2) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='2' then
                            cambia_record myrecord (myrecord.REG1) (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))/(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.REG3) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='3' then
                            cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))/(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.REG4) (myrecord.contatore+1) (myrecord.lista)
                        elif x='R' && y='E' && z='G' && w='4' then
                            cambia_record myrecord (myrecord.REG1) (myrecord.REG2) (myrecord.REG3) (float((int (capiscoprimapartereg (pulisci listacaratteri) myrecord))/(int (capiscosecondapartereg (prendosecondapartereg (pulisci listacaratteri) myrecord) myrecord)))) (myrecord.contatore+1) (myrecord.lista)
                        else failwith "Verifica DIV."
                |_ -> failwith "Errore nella funzione DIV."

        //funzione che analizza la stringa per capire l'istruzione comandata
        let analizza ( stringa : string ) myrecord = 
            match string_to_list stringa with
            |[] -> failwith "Nessun comando dato"
            |[x;y;z] -> if x='E' && y='N' && z='D' then funzione_end myrecord
                        elif x='N' && y='O' && z='P' then funzione_nop myrecord
                        else failwith "Il comando dato risulta non corretto 0"
            |x::y::z::xs -> if x='M' && y='O' && z='V' then funzione_mov xs myrecord
                            elif x='O' && y='R' && z=' ' then funzione_or xs myrecord
                            elif x='A' && y='N' && z='D' then funzione_and xs myrecord
                            elif x='N' && y='O' && z='T' then funzione_not xs myrecord
                            elif x='M' && y='O' && z='D' then funzione_mod xs myrecord
                            elif x='A' && y='D' && z='D' then funzione_add xs myrecord
                            elif x='S' && y='U' && z='B' then funzione_sub xs myrecord
                            elif x='M' && y='U' && z='L' then funzione_mul xs myrecord
                            elif x='D' && y='I' && z='V' then funzione_div xs myrecord
                            elif x='C' && y='U' && z='T' then funzione_div xs myrecord
                            else failwith "Il comando dato risulta non corretto 1"
            |_ -> failwith "Il comando dato risulta non corretto 2" 
        

        //funzione per leggere le varie stringhe
        let rec leggi_istruzioni stringa myrecord = 
            match stringa with
            |[] -> failwith "La lista di istruzioni risulta essere vuota"
            |[x] -> analizza x myrecord
            |x::xs -> if x = "END" then analizza x myrecord else let myrecord = analizza x myrecord in leggi_istruzioni xs myrecord

        //risultato

        let risultato myrecord = leggi_istruzioni program myrecord

        let rec stringhiamo_bene lista counter =
            match lista, counter with
            |[], counter -> ""
            |[x], counter -> if counter%10 = 0 then "\n"+string x+"\t" else string x+"\t"
            |x::xs, counter -> if counter%10 = 0 then "\n"+string x+"\t" + stringhiamo_bene xs (counter+1) else string x+"\t" + stringhiamo_bene xs (counter+1)

        let stampa myrecord = stringhiamo_bene (myrecord.lista) 0 + "\n\nRegistri:" + "\t" + string (myrecord.REG1) + "\t" + string (myrecord.REG2) + "\t" + string (myrecord.REG3) + "\t" + string (myrecord.REG4) + "\n\nContatore: " + string (myrecord.contatore)

        stampa (risultato myrecord)


[]
let main argv =
  try
    let parsed_program = parse_file "test.txt"
    let dump = run_svm parsed_program
    System.Console.WriteLine(dump)
    0
  with
    | Failure(msg) ->
        System.Console.WriteLine(msg)
        1
    | :? System.IO.FileNotFoundException as exc ->
        System.Console.WriteLine(exc.Message)
        1
    | :? System.IO.IOException as exc ->
        System.Console.WriteLine(exc.Message)
        1

ed ecco infine la SVMLibrary.fs che deve essere inclusa nel progetto perchè contine alcune funzioni richiamate nel programma:

module SVMLibrary

open System.IO

let string_to_list (s : string) = s.ToCharArray() |> Array.toList
let rec list_to_string (l : char list) =
  match l with
  | [] -> ""
  | c :: cs -> (string c) + (list_to_string cs)

let char_to_int (c : char) = (string c) |> int

let string_to_float (c : string) = (string c) |> float

//parse the input file returning a list of string for each line, converted to upper cases.
let parse_file (input : string) =
  let parsed_program = File.ReadAllLines(input) |> Array.toList
  [for line in parsed_program do
      yield line.ToUpper()] |> List.filter(fun x -> x <> "" && x.StartsWith("#") |> not)

Il mio consiglio personale è quello di partire da sotto per provare a capire il codice. Il codice è rilasciato come Open Source.