-
Notifications
You must be signed in to change notification settings - Fork 60
/
Copy pathlookup.coffee
119 lines (118 loc) · 3.52 KB
/
lookup.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# now this might be a little confusing, so a
# clarification is in order.
# First off, at the scripting level most things
# as they are handled get evalled.
# That means that they are recursively "calculated"
# as much as possible, i.e. variables are recursively
# looked up for their values, operators are applied,
# functions are ivoked, etc.
# I.e. while scripting, most things are
# evalled all the times.
# e.g. if I type
# x = 1+1
# then x is actually assigned 2, not 1+1
# Something that helps a little is "quote", e.g.
# If I assign
# x = quote(1+1)
# then x actually contains 1+1, not 2.
# But then x is evaluated as soon as I type
# x // gives "2" as x is evaluated
#
# Evaluation is great, but sometimes one wants
# to look at the actual structure of an expression
# or a content of a variable, without those
# being evaluated first.
#
# for example I might type
# x = a + b
# a = 1
# b = 2
# and from this point on printing the actual
# structure of x is impossible, because from
# now on any evaluation of x will give "3"
# You might say "but you have x defined up there,
# what's the point of printing it out?", to which
# the answer is that one might do further
# substitutions or transformations of special kind
# to x. One might want to look at the structure
# and it might be complex or impossible.
#
# So this function does that.
# If it's passed a variable, then it
# DOES NOT eval the variable, RATHER
# it prints the content of the variable without
# evaluating it.
# In the other cases it works like "quote" e.g.
# it just gives the argument as is, again without
# evaluating it.
#
# In the following examples, for brevity, I just
# use
# x = quote(1+2)
# instead of this:
# x = a + b
# a = 1
# b = 2
# to put a structure in x that is easy to see whether
# it's avaulated or not.
#
# So lookup allows this:
# x = quote(1+2)
# print(lookup(x)) # gives 1+2
#
# Note that there would be potentially a way
# to achieve a similar result, you could do:
# x = quote(quote(1+2))
# print(x)
# but you can't always control x to contain
# two quotes like that...
# note how two "quotes" are needed because
# if you just put one, then
# x would indeed contain 1+2 instead of 3,
# but then print would evaluate that to 3:
# x = quote(1+2) # now x contains 1+2, not 3
# print(x) # but x evaluated here to 3
#
# Other workarounds would not work:
# x = quote(1+2)
# print(quote(x))
# would not work because quote(x) literally means 'x'
# so 'x' is printed instead of its content.
#
# Note also that lookup allows you to copy
# the structure of a variable to another:
# x = a + b
# a = 1
# b = 2
# now:
# y = x # y contains the number 3 and prints to 3
# y = lookup(x) # y contains "a+b" and prints to 3
# y = quote(x) # y contains "x" and prints to 3
# note that in the first and second case y is
# independent from x, i.e. changing x doesn't change y
# while in the last case it is.
#
# Another similar simple example is when doing something
# like this:
# x = y
# y = z
# x
# => gives z
# lookup(x)
# => gives y
# i.e. lookup allows you to see the immediate
# content of x, rather than the evaluation which
# would end up in x -> y -> z
# Note that if you invert the order of the assignments i.e.
# y = z
# x = y
# Then at this point x immediately contains z, since the
# assignment x = y is not quoted, hence y is evaluated to z
# when assigned to x.
# lookup(x)
# => gives z
Eval_lookup = ->
p1 = cadr(p1)
if !iscons(p1) and cadr(p1).k == SYM
p1 = get_binding(p1)
push p1