         }
         return .List(res)
     }
-    env[Builtins.println.rawValue] = { params in
+    env[Builtins.println.rawValue] = { params,locals,values in
         guard case let .List(parameters) = params, parameters.count > 1 else {return .List([])}
     
-        print(parameters[1])
+        print(parameters[1].eval(with: locals,for: values)!)
         return .List([])
     }
-    env[Builtins.eval.rawValue] = { params in
+    env[Builtins.eval.rawValue] = { params,locals,values in
         guard case let .List(parameters) = params, parameters.count == 2 else {return .List([])}
         
-        return parameters[1].eval()!
+        return parameters[1].eval(with: locals,for: values)!
     }
     
     return env

        
        let lambda = parameters[3]
        
        let f: (SExpr)->SExpr = { params in
            guard case var .List(p) = params else {return .List([])}
            p = Array(p.dropFirst(1))
            
            // Replace parameters in the lambda with values
            if let result = lambda.replace(this:vars, with:p).eval(){
                return result
            }else{
                return .List([])

            // Evaluate all subexpressions
            if !skip {
                elements = elements.map{
                    return $0.eval(with:locals, for:values)!
                }
            }
            node = .List(elements)
            
            // Obtain a a reference to the function represented by the first atom and apply it, local definitions shadow global ones
            if elements.count > 0, case let .Atom(value) = elements[0], let f = localContext[value] ?? defaultEnvironment[value] {
                let r = f(node,locals,values)
                return r
            }
            
