runFunction :: Function -> [Value] -> Handles -> IState -> EvalExprFn -> IO RetVal
runFunction (UserDefined (FuncDef _ params body))
            args handles state evalExpr = do
  -- new stack frame, with args TODO: copy the "globals"
  let st = foldr (\((FunctionParameter param), arg)
                   table
                   -> Map.insert param arg table)
                   Map.empty
                   (zip params args)
  let newState = state { frame_ = Frame st handles }

  val <- State.evalStateT (mapM evalExpr body) newState
  return $ b2rv . isTruthy $ (last val)
runFunction :: Function -> [Value] -> Handles -> IState -> EvalExprFn -> IO RetVal
runFunction (UserDefined (FuncDef _ params body))
            args handles state evalExpr = do
  -- new stack frame, with args TODO: copy the "globals"
  let st = foldr (\((FunctionParameter param), arg)
                   table
                   -> Map.insert param arg table)
                   Map.empty
                   (zip params args)
  let newState = state { frame_ = Frame st handles }

  val <- State.evalStateT (mapM evalExpr body) newState
  return $ b2rv . isTruthy $ (last val)
runFunction (UserDefined (FuncDef _ params body))
            args handles state evalExpr = do
  -- new stack frame, with args TODO: copy the "globals"
  let st = foldr (\((FunctionParameter param), arg)
                   table
                   -> Map.insert param arg table)
                   Map.empty
                   (zip params args)
  let newState = state { frame_ = Frame st handles }

  val <- State.evalStateT (mapM evalExpr body) newState
  return $ b2rv . isTruthy $ (last val)