Skip to content

Put a timeout on executions #30

Description

@cartermp

The following code contains an infinite loop in it:

open System

type Ops = Add | Sub | Mul | Div | And | Or | Eor | Bic | Lsl | Lsr | Asr | Ror | Ldc of int
         | Dup | Drop | Swap | Over | Ld8 | St8 | Ld16 | St16 | Ld32 | St32 | Se8 | Se16
         | For of Exp | Next | If of Exp*Exp | Func of string*Exp | Ldl of string | Stl of string
and Exp = Ops list

type Sym = Var of int32 | Fun of Exp

let symbols = Map.empty

let isNumber (x:string) = fst (Int32.TryParse(x))


let getOps = function
    | "+" -> Add
    | "-" -> Sub
    | "*" -> Mul
    | "/" -> Div
    | "and" -> And
    | "or" -> Or
    | "eor" -> Eor
    | "bic" -> Bic
    | "lsl" -> Lsl
    | "lsr" -> Lsr
    | "asr" -> Asr
    | "ror" -> Ror
    | "dup" -> Dup
    | "drop" -> Drop
    | "swap" -> Swap
    | "over" -> Over
    | "ld8" -> Ld8
    | "st8" -> St8
    | "ld16" -> Ld16
    | "st16" -> St16
    | "ld32" -> Ld32
    | "st32" -> St32
    | "for" -> For []
    | "next" -> Next
    | x when isNumber x -> Ldc (int x)
    | x -> failwithf "Unknown word %A" x

let exec = function
    | (Add,x::y::xs) -> (x+y)::xs
    | (Sub,x::y::xs) -> (y-x)::xs
    | (Mul,x::y::xs) -> (x*y)::xs
    | (Div,x::y::xs) -> (y/x)::xs
    | (Ldc x,xs)     -> x::xs
    | (_,[]) -> failwith "Empty stack"
    | x      -> failwithf "Unknown Op %A" x

let infix = function
    | (Add,x::y::xs) -> ("("+x+" + "+y+")")::xs
    | (Sub,x::y::xs) -> ("("+y+" - "+x+")")::xs
    | (Mul,x::y::xs) -> ("("+x+" * "+y+")")::xs
    | (Div,x::y::xs) -> ("("+y+" / "+x+")")::xs
    | (Ldc x,xs)     -> (string x)::xs
    | (_,[]) -> failwith "Empty stack"
    | x      -> failwithf "Unknown Op %A" x

let run f = Array.fold (fun xs op -> f (op,xs)) []

//let source = "2 3 + 1 - 2 /"
let source = "1 4 for dup + next + -"
let code = source.Split() |> Array.filter ((<>)"") |> Array.map getOps

printfn "Source:  %A" source
printfn "Code:    %A" code

let rec combFor xs bb ys depth =
    match xs with
    | [] -> if bb <> [] then printfn "ERROR: bb not empty %A" bb
            (xs,[],List.rev (bb@ys))
    | Next::xs when depth = 0 -> printfn "ERROR: No For!"
                                 failwith ""
    | Next::xs when depth = 1 -> (xs,[],List.rev (bb@ys))//(xs,List.rev bb,ys)
    //| Next::xs when depth > 0 -> combFor xs bb ys (depth - 1)
    //| For [] :: xs -> combFor xs bb (For []::ys) (depth + 1)
    | For [] :: xs   -> let (xs,bb,ys) = combFor xs bb ys (depth + 1)
                        combFor xs [] (For bb :: ys) (depth + 1)
    | x::xs when depth > 0 -> combFor xs (x::bb) ys depth
    | x::xs -> combFor (x::xs) bb ys depth

let c = List.ofArray code
printfn "Code:    %A" c
let d = combFor c [] [] 0 
printfn "CFor:    %A" d

//printfn "Infix:   %A" (run infix code)
//let result = run exec code
//printfn "Result = %A" (List.rev result)

It's a lot, but this will run infinitely on a local machine as a console app.

In the browser, this will freeze the page until your browser eventually asks to quit. We should put a limit on execution time and stop executing code, then notify the user about that.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions