             case let x as Symbol:
                 return x
             default:
-                throw InterpreterError.SyntaxError("trying to evaluate invalid statement")
+                throw InterpreterError.SyntaxError("invalid constant literal")
             }
         } else if let x = x as? List, x.first as? Symbol == "if" { // conditional
-            var test = x[1]
-            let conseq = x[2]
-            let alt = x[3]
+            guard var test = x[safe: 1], let conseq = x[safe: 2], let alt = x[safe: 3] else {
+                throw InterpreterError.SyntaxError("invalid conditional statement")
+            }
 
             guard let bool = try eval(&test, withEnvironment: &env) as? Bool else {
                 throw InterpreterError.SyntaxError("invalid conditional statement")


/// A Scheme Env is implemented as a Swift `[String: Any]` dictionary.
public typealias Env = [Symbol: Any]

/**
 A simple Scheme interpreter written in Swift

            var exp = bool ? conseq : alt
            return try eval(&exp, withEnvironment: &env)
        } else if let x = x as? List, x.first as? Symbol == "define" { // definition
            guard let `var` = x[safe: 1] as? Symbol, var exp = x[safe: 2] else {
                throw InterpreterError.SyntaxError("invalid variable definition")
            }

            env[`var`] = try eval(&exp, withEnvironment: &env)
            return 0
        } else if let x = x as? List { // procedure call
            var args: [Any] = []
            guard var exp = x[safe: 0] else {
                throw InterpreterError.SyntaxError("invalid procedure call")
            }

            let proc = try eval(&exp, withEnvironment: &env)

