Advertisement
Guest User

Untitled

a guest
May 29th, 2014
251
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 4.52 KB | None | 0 0
  1. type LispValue =
  2.     Int of int
  3.     | Str of string
  4.     | Lst of (LispValue list)
  5.     | Lam of (string list) * LispValue
  6.     | Def of string * LispValue
  7.  
  8. let expr = Lst [Str "+"; Int 1; Lst [Str "*"; Lst[Str "if"; Lst [Str "-"; Int 2; Int 2]; Int 2; Int 3]; Int 3]]
  9.  
  10. let getFunc = function
  11.     | "+" -> Some (+)
  12.     | "*" -> Some (*)
  13.     | "-" -> Some (-)
  14.     | _ -> None
  15.  
  16. let nativeFunc = function
  17.     | "=" -> Some (=)
  18.     | _ -> None
  19.  
  20. let rec findUserFunc f = function
  21.     | [] -> None
  22.     | (name, value)::rest -> if name = f then Some value else findUserFunc f rest
  23.  
  24. let substitute args = function
  25.     | Int i -> if List.length args = 0 then Int i else failwith "Incorrect substitute"
  26.     | Str s -> failwith "Incorrect substitute"
  27.     | Lst l -> Lst l
  28.     | Lam (argnames, body) ->
  29.         let rec replaceOne name value = function
  30.             | Str s -> if name = s then value else Str s
  31.             | Lst l -> Lst <| List.map (replaceOne name value) l
  32.             | Lam (argnames, body) ->
  33.                 if List.exists ((=) name) argnames
  34.                 then Lam (argnames, body)
  35.                 else Lam (argnames, replaceOne name value body)
  36.             | body -> body
  37.         let rec replace body argnamesAndArgs =
  38.             if List.length argnames <> List.length args
  39.             then failwith "Incorrect argument count"
  40.             else match argnamesAndArgs with
  41.                 | [] -> body
  42.                 | (name, value)::rest -> replace (replaceOne name value body) rest
  43.         in replace body (List.zip argnames args)
  44.  
  45. let rec eval userFuncs = function
  46.     | Str s -> failwith "Incorrect expression"
  47.     | Int i -> Int i
  48.     | Lst [] -> Lst []
  49.     | Lst ((Str "define")::(Str name)::value::[]) -> Def (name, eval userFuncs value)
  50.     | Lst ((Str "if")::p::a::b::[]) ->
  51.         match (eval userFuncs p) with
  52.             | Int 0 -> eval userFuncs b
  53.             | _ -> eval userFuncs a
  54.     | Lst ((Str "lambda")::(Lst args)::body::[]) ->
  55.         let extractStr = function
  56.             | Str s -> s
  57.         in Lam (List.map extractStr args, body)
  58.     | Lst (Str f::args) ->
  59.         let extractInt = function
  60.             | Int i -> i
  61.         in match getFunc f with
  62.             | Some f -> Int <| List.reduce f (List.map (extractInt << eval userFuncs) args)
  63.             | None -> match nativeFunc f with
  64.                 | Some f -> Int <| if f (extractInt <| (eval userFuncs <| List.nth args 0)) (extractInt <| (eval userFuncs <| List.nth args 1)) then 1 else 0
  65.                 | None -> match findUserFunc f userFuncs with
  66.                     | Some value -> eval userFuncs <| substitute args value
  67.                     | None -> failwith "Unknown function"
  68.  
  69. let evalExprs =
  70.     let rec eval' acc userFuncs = function
  71.    | [] -> acc
  72.    | expr::rest -> match eval userFuncs expr with
  73.        | Def (name, value) -> eval' acc ((name, value)::userFuncs) rest
  74.         | value -> eval' (value::acc) userFuncs rest
  75.    in eval' [] []
  76.  
  77. let parse str =
  78.     let rec parse' = function
  79.        | [] -> (Lst [], [])
  80.        | (' '::rest) -> parse' rest
  81.         | (')'::_) -> failwith "Incorrect bracket"
  82.         | ('('::rest) ->
  83.             let rec parseList acc = function
  84.                 | [] -> failwith "No bracket"
  85.                 | (' '::rest) -> parseList acc rest
  86.                 | (')'::rest) -> (acc, rest)
  87.                 | str ->
  88.                     let expr = parse' str
  89.                    in parseList (fst expr::acc) (snd expr)
  90.            let subExpr = parseList [] rest
  91.            in (Lst <| List.rev (fst subExpr), snd subExpr)
  92.        | str ->
  93.            let rec parseToken acc = function
  94.                | [] -> (List.rev acc, [])
  95.                | (head::rest) ->
  96.                    if System.Char.IsWhiteSpace head or head = '(' or head = ')' then (List.rev acc, head::rest)
  97.                    else parseToken (head::acc) rest
  98.            let subExpr = parseToken [] str
  99.            let token str = match System.Int32.TryParse str with
  100.                | (true, i) -> Int i
  101.                | (false, _) -> Str str
  102.            in (token <| (System.String.Concat (Array.ofList (fst subExpr))), snd subExpr)
  103.    in parse' (Seq.toList str)
  104.  
  105. let parseExprs str =
  106.     let rec parseExprs' str =
  107.        match parse str with
  108.            | (expr, []) -> [expr]
  109.            | (expr, rest) -> expr::(parseExprs' rest)
  110.     in parseExprs' (Seq.toList str)
  111.  
  112. let evalProgram str = evalExprs (parseExprs str)
  113.  
  114. evalProgram "(define fact (lambda (n) (if (= n 0) 1 (* n (fact (- n 1)))))) (fact 5)"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement