      (if (empty? code)
        (assoc err-map i "Empty input is not allowed.")
        (try
-         (let [code-form (binding [*read-eval* false]
-                           (read-string (.replace test "__" code)))
+         (let [user-forms (str/join " " (map pr-str (read-code code)))
+               [code-form] (read-code (.replace test "__" user-forms))
                found-restricted (clojure.walk/postwalk
                                  (fn [f]
                                    (if (sequential? f)

(ns org.bytopia.foreclojure.logic
  (:require clojure.walk)
  (:import [java.util.concurrent FutureTask TimeUnit TimeoutException]))

(def ^:const timeout 3000)

(def ^:private forbidden-symbols
  #{'eval 'resolve 'read 'read-string 'throw 'ns 'in-ns 'require 'use 'refer})

(defn read-code
  "Safely read Clojure code from a string. Returns a sequence of read forms.
  Taken from 4clojure.com source."
  [^String code]
  (binding [*read-eval* false]
    (with-in-str code
      (let [end (Object.)]
        (doall (take-while (complement #{end})
                           (repeatedly #(read *in* false end))))))))

(defn check-suggested-solution
  "Evaluates user code against problem tests. Returns a map of test numbers to
  the errors (map is empty if all tests passed correctly). `restricted` is a set
