From 4f0f55a84b197911811223832c9c74a2457a28ec Mon Sep 17 00:00:00 2001 From: Seng-Jik <853974536@qq.com> Date: Fri, 12 Jun 2020 13:01:08 +0800 Subject: [PATCH] =?UTF-8?q?add=20Jisp=E7=BC=96=E7=A8=8B=E8=AF=AD=E8=A8=80?= =?UTF-8?q?=E7=9A=84=E8=A7=A3=E9=87=8A=E5=99=A8.fs.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...04\350\247\243\351\207\212\345\231\250.fs" | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 "Jisp\347\274\226\347\250\213\350\257\255\350\250\200\347\232\204\350\247\243\351\207\212\345\231\250.fs" diff --git "a/Jisp\347\274\226\347\250\213\350\257\255\350\250\200\347\232\204\350\247\243\351\207\212\345\231\250.fs" "b/Jisp\347\274\226\347\250\213\350\257\255\350\250\200\347\232\204\350\247\243\351\207\212\345\231\250.fs" new file mode 100644 index 0000000..82a0631 --- /dev/null +++ "b/Jisp\347\274\226\347\250\213\350\257\255\350\250\200\347\232\204\350\247\243\351\207\212\345\231\250.fs" @@ -0,0 +1,109 @@ +// github.com/Seng-Jik/Jisp + +module rec Jisp.Evalution + +open AST + +exception IdenifierNotFound of string +exception CanNotCallTheValue +exception InvalidArguments of string + +let bindValues (binds:Map) nameValueSeq = + Seq.fold (fun local (name,value) -> Map.add name value local) binds nameValueSeq + + +let getValueFromContext (context:Context) (id:string) : Result = + match Map.tryFind id context.Local with + | Some x -> Ok x + | None -> + match Map.tryFind id context.Global with + | Some x -> Ok x + | None -> Error (IdenifierNotFound id) + +let evalParams context : JispExpr list -> Result = function +| a :: tail -> + eval context a + |> Result.bind (fun a -> + evalParams context tail + |> Result.bind (fun t -> + Ok (a::t))) +| [] -> Ok [] + +let eval (context:Context) (ast:JispExpr) : Result = + match ast with + | Value v -> + match v with + | Lambda (CustumFunc x) -> + { x with + FunctionContext = context.Local } + |> CustumFunc + |> Lambda + | x -> x + |> Ok + | Identifier id -> getValueFromContext context id + | Apply { Function = f; Arguments = param } -> + eval context f + |> Result.bind (fun target -> + match target with + | Lambda x -> Ok x + | _ -> Error CanNotCallTheValue) + |> Result.bind (fun f -> + match f with + | RuntimeFunc func -> func { context with Level = context.Level + 1UL } param + | CustumFunc func -> + evalParams context param + |> Result.bind (fun arguments -> + let argCount = List.length arguments + let paramCount = List.length func.Parameters + if argCount > paramCount then + Error (InvalidArguments "Too much arguments passed.") + else + { func with + Parameters = List.skip argCount func.Parameters + FunctionContext = + bindValues + func.FunctionContext + (List.zip (List.take argCount func.Parameters) arguments) } + |> fun f -> + if (List.length f.Parameters) > 0 then + f |> CustumFunc |> Lambda |> Ok + else + eval { + context with + Local = f.FunctionContext + Level = context.Level + 1UL } f.Expression)) + + +let rec printResult = function +| Number x -> printf "%M" x +| Tuple [] -> () +| Tuple x -> + printf "(tuple" + List.iter (fun x -> + printf " " + printResult x) + x + printf ")" +| Lambda x -> + match x with + | RuntimeFunc f -> printf "(λ ??? (%A))" f + | CustumFunc f -> + printf "(λ " + for i in f.Parameters do printf "%s " i + printf "(...))" + + +let run context expr = + let threadFunction () = + eval context expr + |> function + | Ok result -> + printResult result + | Error e -> + printfn "Error:%A" e + + let stackSize = 1024 * 1024 * 256 + let thread = System.Threading.Thread (threadFunction,stackSize) + thread.Start () + thread.Join () + -- Gitee