You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
2.5 KiB
Forth
100 lines
2.5 KiB
Forth
type aexp =
|
|
AEint of int
|
|
| AEplus of (aexp * aexp)
|
|
| AEminus of (aexp * aexp)
|
|
| AEtimes of (aexp * aexp)
|
|
|
|
// funzione di interpretazione
|
|
let rec aexp_to_string : aexp -> string =
|
|
fun e ->
|
|
match e with
|
|
AEint i -> sprintf "%d" i
|
|
| AEplus (e,f) -> sprintf "(%s + %s)" (aexp_to_string e) (aexp_to_string f)
|
|
| AEminus (e,f) -> sprintf "(%s - %s)" (aexp_to_string e) (aexp_to_string f)
|
|
| AEtimes (e,f) -> sprintf "(%s * %s)" (aexp_to_string e) (aexp_to_string f)
|
|
|
|
(* printfn "%s" (aexp_to_string (AEplus ((AEint 10),(AEint 6)))) *)
|
|
|
|
// semantic domain
|
|
type eval = int
|
|
|
|
// error handling
|
|
let negativeError () = failwith "natural numbers should be positive or zero"
|
|
|
|
// denotational semantics
|
|
let rec sem : aexp -> eval =
|
|
fun ae ->
|
|
match ae with
|
|
AEint i ->
|
|
if i < 0 then negativeError () else i
|
|
| AEplus (e,f) ->
|
|
sem e + sem f
|
|
| AEminus (e,f) ->
|
|
sem e - sem f
|
|
| AEtimes (e,f) ->
|
|
sem e * sem f
|
|
|
|
(* printfn "%d" (sem (AEplus ((AEint 10),(AEint 6)))) *)
|
|
|
|
let eval_to_string : eval -> string =
|
|
fun e -> Printf.sprintf "%d" e
|
|
|
|
let eval : aexp -> unit =
|
|
fun ae ->
|
|
printfn "%s ==> " (aexp_to_string ae);
|
|
try
|
|
printfn "%s\n" (eval_to_string (sem ae))
|
|
with
|
|
Failure message ->
|
|
printfn "error: %s\n" message
|
|
|
|
printfn "%A" (eval (AEplus ((AEint 10),(AEint 6))))
|
|
|
|
// parallel computation
|
|
open System.Threading
|
|
open System.Threading.Tasks
|
|
|
|
// esempio di funzioni parallele
|
|
let runTasks () =
|
|
let rnd = System.Random()
|
|
|
|
for i = 1 to 10 do
|
|
let t = new Task(fun () ->
|
|
let time = rnd.Next(3000)
|
|
Thread.Sleep time
|
|
printfn "Thread %d waited for %d milliseconds" i time
|
|
)
|
|
t.Start()
|
|
|
|
// il risultato non è deterministico
|
|
let parallelIncrement () =
|
|
let a = [| 0 |]
|
|
for i = 1 to 100 do
|
|
let t = new Task(fun () ->
|
|
Thread.Sleep 100
|
|
a[0] <- a[0] + 1
|
|
printfn "Thread %d done" i
|
|
)
|
|
t.Start()
|
|
a
|
|
|
|
// usiamo lock per fixare il problema della lettura concorrente
|
|
// di una cella di memoria da parte di più "thread"
|
|
let parIncr2 () =
|
|
let rnd = System.Random()
|
|
let a = [| 0 |]
|
|
|
|
Array.Parallel.iter (fun i ->
|
|
lock a (fun () ->
|
|
let x = a[0]
|
|
Thread.Sleep (rnd.Next 10)
|
|
a[0] <- x + 1
|
|
printfn "Thread %d done" i
|
|
)
|
|
) [| 1 .. 1000 |]
|
|
a
|
|
|
|
printfn "%A" (parIncr2 ())
|
|
|
|
// però, la lock non risolve problemi con più risorse (i.e. dining philosophers problem)
|