From 74579b9fa0239e529a0ed4154a63ccf0a00b06e1 Mon Sep 17 00:00:00 2001 From: "Elf M. Sternberg" Date: Mon, 1 Jun 2015 07:40:15 -0700 Subject: [PATCH] Added a lot of comments to the interpreter, clearing up a confusion in my mind. --- chapter3/interpreter.coffee | 47 ++++++++++++++++++++++++++++++------- chapter3/test.coffee | 4 ++-- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/chapter3/interpreter.coffee b/chapter3/interpreter.coffee index cd62c22..b793ceb 100644 --- a/chapter3/interpreter.coffee +++ b/chapter3/interpreter.coffee @@ -4,17 +4,23 @@ print = require "../chapter1/print" # Debugging tool. {inspect} = require "util" - env_init = nil env_global = env_init ntype = (node) -> car node nvalu = (node) -> cadr node +# Takes a name and a value and pushes those onto the global environment. + definitial = (name, value = nil) -> env_global = (cons (cons name, value), env_global) name +# Takes a name, a native function, and the expected arity of that +# function, and returns the global environment with new a (native) +# function perpared to unpack any (interpreter) variable pairs and +# apply the (native) function with them. + defprimitive = (name, nativ, arity) -> definitial name, ((args) -> vmargs = listToVector(args) @@ -33,12 +39,16 @@ definitial "bar" definitial "fib" definitial "fact" +# Wraps a native predicate in function to ensure the interpreter's +# notion of falsity is preserved. + defpredicate = (name, nativ, arity) -> defprimitive name, ((a, b) -> if nativ.call(null, a, b) then true else the_false_value), arity defprimitive "cons", cons, 2 defprimitive "car", car, 2 defprimitive "set-cdr!", setcdr, 2 +defprimitive "log", ((a) -> console.log a), 1 defprimitive "+", ((a, b) -> a + b), 2 defprimitive "*", ((a, b) -> a * b), 2 defprimitive "-", ((a, b) -> a - b), 2 @@ -46,6 +56,10 @@ defprimitive "/", ((a, b) -> a / b), 2 defpredicate "lt", ((a, b) -> a < b), 2 defpredicate "eq?", ((a, b) -> a == b), 2 +# Takes an environment, a list of names and a list of values, and for +# each name and value pair pushes that pair onto the list, adding them +# to the environment. + extend = (env, variables, values) -> if (pairp variables) if (pairp values) @@ -61,16 +75,24 @@ extend = (env, variables, values) -> else nil +# Takes a list of variable names, a function body, and an environment +# at the time of evaluation, and returns: +# a (native) function that takes a list of values, applies them to the +# environment, and evaluates the body, returning the resulting value. + make_function = (variables, body, env) -> (values) -> eprogn body, (extend env, variables, values) -invoke = (fn, args) -> - (fn args) +# Evaluates a (native) function with of one arg with the arg provided. +# Invoke runs the functions created by make_function, and is unrelated +# to the native functions of defprimitive() + +invoke = (fn, arg) -> (fn arg) # Takes a list of nodes and calls evaluate on each one, returning the # last one as the value of the total expression. In this example, we -# are hard-coding what ought to be a macro, namely the threading -# macros, "->" +# are hard-coding what ought to be a macro, namely the threading macro +# often named "->" eprogn = (exps, env) -> if (pairp exps) @@ -82,12 +104,17 @@ eprogn = (exps, env) -> else nil +# Evaluates a list of expressions and returns a list of resolved +# values. + evlis = (exps, env) -> if (pairp exps) (cons (evaluate (car exps), env), (evlis (cdr exps), env)) else nil - + +# Locates a named reference in the environment and returns its value. + lookup = (id, env) -> if (pairp env) if (caar env) == id @@ -97,6 +124,9 @@ lookup = (id, env) -> else nil +# Locates a named reference in the environment and replaces its value +# with a new value. + update = (id, env, value) -> if (pairp env) if (caar env) == id @@ -120,8 +150,9 @@ astSymbolsToLispSymbols = (node) -> handler(nvalu node) -# Takes an AST node and evaluates it and its contents. A node may be -# ("list" (... contents ...)) or ("number" 42) or ("symbol" x), etc. +# Takes an AST node and evaluates it and its contents, returning the +# final value of the calculation. A node may be ("list" (... contents +# ...)) or ("number" 42) or ("symbol" x), etc. cadddr = metacadr('cadddr') diff --git a/chapter3/test.coffee b/chapter3/test.coffee index 4e4dddd..5f8b941 100644 --- a/chapter3/test.coffee +++ b/chapter3/test.coffee @@ -2,7 +2,7 @@ lisp = require './interpreter.coffee' {read, readForms} = require '../chapter1/reader' {inspect} = require 'util' -ast = read("(begin (set! fact (lambda (x) (if (eq? x 0) 1 (* x (fact (- x 1)))))) (fact 5))") +ast = read("(log (begin (set! fact (lambda (x) (if (eq? x 0) 1 (* x (fact (- x 1)))))) (fact 5)))") # ast = read("(begin (if (lt 4 2) (+ 4 1) (+ 2 1)))") # ast = read("(begin (set! fact 4) fact)") @@ -11,4 +11,4 @@ ast = read("(begin (set! fact (lambda (x) (if (eq? x 0) 1 (* x (fact (- x 1))))) # ast = read("(begin (set! fact (lambda (x) (+ x x))) (fact 5))") # ast = read("(begin (set! fact (lambda (x) (- x 4))) (fact 5))") -console.log "Result:", (lisp ast) +(lisp ast)