 definitial "#t", true
 definitial "#f", the_false_value
 definitial "nil", nil
-definitial "foo"
-definitial "bar"
-definitial "fib"
-definitial "fact"
+for i in [
+  "x", "y", "z", "a", "b", "c", "foo", "bar", "hux",
+  "fib", "fact", "visit", "primes", "length"]
+  definitial i
+
 
 defpredicate = (name, nativ, arity) ->
   defprimitive name, ((a, b) -> if nativ.call(null, a, b) then true else the_false_value), arity

    @f(v)
    
class Primitive extends Value
  constructor: (@name, @address) ->
    




evaluate = (e, env, kont) ->
  [type, exp] = [(ntype e), (nvalu e)]
  if type == "symbol"
    return variables.evaluate exp, env, kont

  if type in ["number", "string", "boolean", "vector"]
    return exp

  if type == "list"
    head = car exp
    if (ntype head) == 'symbol'
      switch (nvalu head)
        when "quote" then resume (cdr exp), kont
        when "if" then evaluateIf (cdr exp), env, kont

          evaluate (cadr e), env, new Ifs((-> (caddr e)), (->(cadddr e)), env, kont)
        when "begin" then eprogn (cdr exp), env
        when "set!" then update (nvalu cadr exp), env, (evaluate (caddr exp), env)
        when "lambda" then make_function (astSymbolsToLispSymbols cadr exp), (cddr exp), env
        else invoke (evaluate (car exp), env), (evlis (cdr exp), env)
    else
      invoke (evaluate (car exp), env), (evlis (cdr exp), env)
  else
    throw new Error("Can't handle a #{type}")

class Ifs:
  evaluate: (cond, pass, alt, env, kont) ->
    if cond then 

  resume: (

env_init = nil
env_global = env_init

ntype = (node) -> car node
nvalu = (node) -> cadr node

definitial = (name, value = nil) ->
  env_global = (cons (cons name, value), env_global)
  name

defprimitive = (name, nativ, arity) ->
  definitial name, ((args) ->
    vmargs = listToVector(args)
    if (vmargs.length == arity)
      nativ.apply null, vmargs
    else
      throw "Incorrect arity")


{inspect} = require "util"
print = require "./print"

ntype = (node) -> car node
nvalu = (node) -> cadr node

class Value

class Continuation
  constructor: (@k) ->
  invoke: (v, env, kont) ->
    if nilp cdr v
      resume @k, (car v)
    else
      throw "Continuations expect one argument", [v, env, kont]

# Abstract class representing the environment

class Environment
  lookup: -> throw "Nonspecific invocation"
  update: -> throw "Nonspecific invocation"

# Base of the environment stack.  If you hit this, your variable was
# never found for lookup/update.  Note that at this time in the
# class, you have not 

class NullEnv extends Environment
  lookup: -> throw "Unknown variable"
  update: -> throw "Unknown variable"

# This appears to be an easy and vaguely abstract handle to the
# environment.  The book is not clear on the distinction between the
# FullEnv and the VariableEnv.
            
class FullEnv extends Environment
  constructor: (@others, @name) ->
  lookup: (name, kont) ->
    @others.lookup name, kont
  update: (name, kont, value) ->
    @others.update name, kont, value

# This is the classic environment pair; either it's *this*
# environment, or it's a parent environment, until you hit the
# NullEnv.

class VariableEnv extends FullEnv
  constructor: (@others, @name, @value) ->
