Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (*
- * SharpSolver - Progetto di Programmazione e Calcolo a.a. 2018-19
- * Main.fs: console e codice main
- * (C) 2018 Alvise Spano' @ Universita' Ca' Foscari di Venezia
- *)
- module SharpSolver.Main
- open Microsoft.FSharp.Text.Lexing
- open Absyn
- open System
- open Prelude
- open Microsoft.FSharp.Text
- // funzioni di logging e printing
- //
- let hout hd fmt =
- if not <| String.IsNullOrWhiteSpace hd then
- printf "[%s]%s" hd (new String (' ', max 1 (Config.prefix_max_len - String.length hd)))
- stdout.Flush ()
- printfn fmt
- let chout col hd fmt =
- let c = Console.ForegroundColor
- Console.ForegroundColor <- col
- Printf.kprintf (fun s -> hout hd "%s" s; Console.ForegroundColor <- c) fmt
- let out fmt = hout "" fmt
- let cout col fmt = chout col "" fmt
- let norm fmt = chout ConsoleColor.Yellow "norm" fmt
- let redux fmt = chout ConsoleColor.Magenta "redux" fmt
- let sol fmt = chout ConsoleColor.Green "sol" fmt
- let ident fmt = chout ConsoleColor.Green "ident" fmt
- let error fmt = chout ConsoleColor.Red "error" fmt
- // interprete dei comandi e delle espressioni
- //
- let interpreter_loop () =
- while true do
- printf "\n%s" Config.prompt_prefix // stampa il prompt
- stdout.Flush () // per sicurezza flusha lo stdout per vedere la stampa del prompt senza end-of-line
- let input = Console.ReadLine () // leggi l'input scritto dall'utente
- let lexbuf = LexBuffer<_>.FromString input // crea un lexbuffer sulla stringa di input
- // funzione locale per il pretty-printing degli errori
- let localized_error msg =
- let tabs = new string (' ', Config.prompt_prefix.Length + lexbuf.StartPos.Column)
- let cuts = new string ('^', let n = lexbuf.EndPos.Column - lexbuf.StartPos.Column in if n > 0 then n else 1)
- cout ConsoleColor.Yellow "%s%s\n" tabs cuts
- error "error at %d-%d: %s" lexbuf.StartPos.Column lexbuf.EndPos.Column msg
- // blocco con trapping delle eccezioni
- try
- let line = Parser.line Lexer.tokenize lexbuf // invoca il parser sul lexbuffer usando il lexer come tokenizzatore
- #if DEBUG
- hout "absyn" "%+A" line
- hout "pretty" "%O" line
- #endif
- // interpreta la linea in base al valore di tipo line prodotto dal parsing
- match line with
- | Cmd "help" ->
- out "%s" Config.help_text
- | Cmd ("quit" | "exit") ->
- out "%s" Config.exit_text
- exit 0
- // TODO: se volete supportare altri comandi, fatelo qui (opzionale)
- | Cmd s -> error "unknown command: %s" s // i comandi non conosciuti cadono in questo caso
- // TODO: aggiungere qui sotto i pattern per i casi Expr ed Equ con relativo codice per, rispettivamente, normalizzare espressioni e risolvere equazioni
- // se ho in input un tipo expr quindi un polinomio NON posto uguale a qualcosa, il match entrerà in questo caso
- | Expr e -> chout ConsoleColor.Magenta "redux" "%O" ((Impl.reduce(e))) // stampo il polinomio se in input viene inserito un polinomio , altrimenti stampo la sua derivata se viene inserita la lettera D prima del polinomio
- chout ConsoleColor.Yellow "norm" "%O" (Impl.normalize(Impl.reduce(e))) // stampo il polinomio normalizzato del polinomio dato in input (tipo normalized_polynomial) avvalendomi delle funzioni normalize / reduce
- hout "degree" "%i" (Impl.normalized_polynomial_degree(Impl.normalize( Impl.reduce(e)))) // stampo il grado del polinomio normalizzato( tipo int) avvalendomi delle funzioni normalized_polynomial_degree / normalize /reduce
- // se ho in input un tipo equ quindi due equazioni poste uguali, il match entrerà in questo caso
- |Equ(e1,e2) -> let reduce1=Impl.reduce e1 //riduco il polinomio se viene inserita la derivata del polinomio ,altrimenti ritorna il polinomio inserito
- let reduce2raw= Impl.reduce e2 // polinomio al di là del uguale
- let reduce2=Impl.polynomial_negate (Impl.reduce e2) //riduco il polinomio se viene inserita la derivata del polinomio ,altrimenti ritorna il polinomio inserito, successivamente il polinomio viene negato per concatenarlo al polinomio diciamo a "sinistra dell'uguale"
- match reduce1,reduce2 with
- Polynomial(x),Polynomial(y)-> let pol = Polynomial(x@y) in let norm =Impl.normalize pol // concateno i due polinomi ottenendo quindi un unico polinomio, successivamente lo normalizzo
- match (Impl.normalized_polynomial_degree norm) with // attraverso il grado del polinomio scelgo il procedimento di risoluzione
- 0->chout ConsoleColor.Magenta "redux" "%O = %O" reduce1 reduce2raw // stampa il polinomio
- chout ConsoleColor.Yellow "norm" "%O = 0" norm // stampa il polinomio normalizzato
- hout "degree" "%i" (Impl.normalized_polynomial_degree norm) // se il polinomio ha grado 0 entrerà in questo caso, stamperà il suo grado che è 0
- chout ConsoleColor.Green "identity" "%b" (Impl.solve0 norm) // se il polinomio è identico a 0 stampo true altrimenti false
- |1->chout ConsoleColor.Magenta "redux" "%O = %O" reduce1 reduce2raw // stampa il polinomio
- chout ConsoleColor.Yellow "norm" "%O = 0" norm // stampa il polinomio normalizzato
- hout "degree" "%i" (Impl.normalized_polynomial_degree norm) // se il polinomio ha grado 1 entrerà in questo caso, stamperà il suo grado che è 1
- chout ConsoleColor.Green "sol" "x=%O" (Impl.solve1 norm) // invoco la funzione per risolvere i polinomi di grado 1 che ritorna l'unica radice del polinomio (x1)
- |2->chout ConsoleColor.Magenta "redux" "%O = %O" reduce1 reduce2raw // stampa il polinomio
- chout ConsoleColor.Yellow "norm" "%O = 0" norm // stampa il polinomio normalizzato
- hout "degree" "%i" (Impl.normalized_polynomial_degree norm) // se il polinomio ha grado 2 entrerà in questo caso, stamperà il suo grado che è 2
- match (Impl.solve2 norm) with // in questo caso dovrò vedere tramite pattern matching se la funzione solve2 ritorna 2 soluzioni , 1 soluzione o nessuna
- Some(x1,Some x2)-> chout ConsoleColor.Green "sol" "x1= %f vel x2=%f" x1 x2 //se la funzione solve2 ritorna 2 soluzioni le stampa
- |Some(x1,None)-> chout ConsoleColor.Green "sol" "x1= %f" x1 //se la funzione solve2 ritorna 1 soluzione la stampa
- |None-> chout ConsoleColor.Green "sol" "%s" "no solution" //se la funzione solve2 ritorna nessuna soluzione avremo un messaggio di errore
- |3->chout ConsoleColor.Magenta "redux" "%O = %O" reduce1 reduce2raw // stampa il polinomio
- chout ConsoleColor.Yellow "norm" "%O = 0" norm // stampa il polinomio normalizzato
- hout "degree" "%i" (Impl.normalized_polynomial_degree norm) // se il polinomio ha grado 3 entrerà in questo caso, stamperà il suo grado che è 3
- match (Impl.solve3 norm) with // in questo caso dovrò vedere tramite pattern matching se la funzione solve3 ritorna 3 soluzioni (1 reale e 2 complesse che non vengono visualizzate) o nessuna soluzione o 3 soluzioni coincidenti.
- Some(x1,Some x2,Some x3)->chout ConsoleColor.Green "sol" "x1= %O vel x2=%O vel x3=%O" x1 x2 x3 //se la funzione solve3 ritorna 3 soluzioni, le stampa
- |Some(x1,None,None) -> chout ConsoleColor.Green "sol" "x1= %O" x1 //Una soluzione e viene stampata.
- |None -> chout ConsoleColor.Red "solve3" "%s" "no solution" //Non ha soluzioni
- |_-> chout ConsoleColor.Red "error" "%s" "Soluzioni per grado superiore al terzo non disponibile."
- | _ -> raise (NotImplementedException (sprintf "unknown command or expression: %O" line))
- // gestione delle eccezioni
- with LexYacc.ParseErrorContextException ctx ->
- let ctx = ctx :?> Parsing.ParseErrorContext<Parser.token>
- localized_error (sprintf "syntax error%s" (match ctx.CurrentToken with Some t -> sprintf " at token <%O>" t | None -> ""))
- | Lexer.LexerError msg -> localized_error msg
- | :? NotImplementedException as e -> error "%O" e
- | e -> localized_error e.Message
- // funzione main: il programma comincia da qui
- //
- [<EntryPoint>]
- let main _ =
- let code =
- try
- interpreter_loop () // chiama l'interprete
- 0 // ritorna il codice di errore 0 (nessun errore) al sistema operativo se tutto è andato liscio
- with e -> error "fatal error: %O" e; 1 // in caso di eccezione esce con codice di errore 1
- #if DEBUG
- Console.ReadKey () |> ignore // aspetta la pressione di un tasto prima di chiudere la finestra del terminare
- #endif
- code
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement