forked from parrot/lisp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patheval.pir
191 lines (143 loc) · 5.37 KB
/
eval.pir
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# $Id$
=head1 NAME
eval.pir - evaluate forms
=cut
.sub _eval
.param pmc args
.ASSERT_LENGTH(args, 1, ERROR_NARGS)
.local string symname
.local string type
.local pmc symbol
.local int found
.local pmc body
.local pmc retv
# switch based on the type of the first arg
.local pmc form
.CAR(form, args)
type = typeof form
if type == "LispSymbol" goto SYMBOL
if type == "LispCons" goto FUNCTION_FORM
if type == "LispInteger" goto SELF_EVALUATING_OBJECT
if type == "LispString" goto SELF_EVALUATING_OBJECT
if type == "LispFloat" goto SELF_EVALUATING_OBJECT
.ERROR_1("internal", "Unknown object type in eval: %s", type)
FUNCTION_FORM:
.local pmc function
.local pmc funcargs
.local pmc funcptr
.local pmc funcarg
.local pmc test
.CAR(symbol, form)
.CDR(body, form)
.ASSERT_TYPE_AND_BRANCH(symbol, "symbol", FUNCTION_NOT_FOUND)
# Retrieve the function from the symbol.
function = symbol.'_get_function'()
# If the function wasn't set for the symbol, throw an error.
defined found, function
unless found goto FUNCTION_NOT_FOUND
# Check to see if the function is a special form (which aren't subject to
# normal function evaluation rules).
type = typeof function
if type == "LispSpecialForm" goto SPECIAL_FORMS
if type == "LispMacro" goto MACRO_FORM
# Normal function - evaluate all arguments being passed into the function.
.NIL(funcargs)
funcptr = body
FUNCTION_LOOP:
.NULL(funcptr, FUNCTION_CALL) # Call the function if no args left.
.CAR(funcarg, funcptr) # Pop the next arg off the list.
.local pmc evalarg # Evaluate the argument.
.LIST_1(evalarg, funcarg)
funcarg = _eval(evalarg)
.APPEND(funcargs,funcargs,funcarg) # Add the result to the args list.
.CDR(funcptr,funcptr) # Move to the next arg in the list.
goto FUNCTION_LOOP
FUNCTION_CALL:
.tailcall _FUNCTION_CALL(function,funcargs)
# VALID_IN_PARROT_0_2_0 goto DONE
FUNCTION_NOT_FOUND:
.ERROR_1("undefined-function", "%s is not a function name", symbol)
# VALID_IN_PARROT_0_2_0 goto DONE
.return(retv)
ERROR_NARGS:
.ERROR_0("program-error", "wrong number of arguments to EVAL")
# VALID_IN_PARROT_0_2_0 goto DONE
.return(retv)
SPECIAL_FORMS:
# Special forms aren't subject to normal evaluation rules - keep the
# arguments as is and call the function.
funcargs = body
goto FUNCTION_CALL
MACRO_FORM:
.local pmc macroexp
.local pmc macrosym
.local pmc macroenv
.local pmc macroarg
macrosym = _LOOKUP_SYMBOL("*MACROEXPAND-HOOK*")
if_null macrosym, MACRO_NOT_INITIALIZED
macroexp = macrosym.'_get_value'() # Get the expander function
.ASSERT_TYPE_AND_BRANCH(macroexp, "function", MACRO_NOT_INITIALIZED)
# VALID_IN_PARROT_0_2_0 peek_pad macroenv # Get current lexical scope
.LIST_3(funcargs, symbol, body, macroenv)
retv = _FUNCTION_CALL(macroexp, funcargs) # Call the macroexpand hook
.LIST_1(macroarg, retv)
_eval(macroarg)
# VALID_IN_PARROT_0_2_0 goto DONE
.return(retv)
SYMBOL:
symbol = form
symname = symbol.'_get_name_as_string'()
.local int is_special
is_special = _IS_SPECIAL(symbol) # Check if we're a dynamic
unless is_special goto LEXICAL_SYMBOL # variable
goto DYNAMIC_SYMBOL
DYNAMIC_SYMBOL:
.local pmc package
.local string pkgname
package = symbol.'_get_package'()
pkgname = package.'_get_name_as_string'()
symbol = _LOOKUP_GLOBAL(pkgname, symname)
goto CHECK_VALUE
LEXICAL_SYMBOL:
retv = _LOOKUP_LEXICAL(symname) # Check for a lexical shadow
if_null retv, CHECK_VALUE # If not found, assume global
symbol = retv # Use the lexical value
goto CHECK_VALUE
CHECK_VALUE:
retv = symbol.'_get_value'() # Check for symbol's value
defined found, retv
unless found goto SYMBOL_NOT_FOUND
DONE_SYMBOL:
# VALID_IN_PARROT_0_2_0 argcP = 1 # One value returned
# VALID_IN_PARROT_0_2_0 P5 = retv # Return value
# VALID_IN_PARROT_0_2_0
# VALID_IN_PARROT_0_2_0 goto DONE
.return(retv)
SYMBOL_NOT_FOUND:
.ERROR_1("unbound-variable", "variable %s has no value", form)
# VALID_IN_PARROT_0_2_0 goto DONE
.return(retv)
SELF_EVALUATING_OBJECT:
# Object is a primitive type (ie. a string, integer or float).
# VALID_IN_PARROT_0_2_0 argcP = 1 # One value returned
# VALID_IN_PARROT_0_2_0 P5 = retv # Return value
# VALID_IN_PARROT_0_2_0 goto DONE
.return(form)
MACRO_NOT_INITIALIZED:
.ERROR_0("internal","the macro system has not been initialized")
# VALID_IN_PARROT_0_2_0 goto DONE
# VALID_IN_PARROT_0_2_0
# VALID_IN_PARROT_0_2_0 DONE:
# VALID_IN_PARROT_0_2_0 is_prototyped = 0 # Nonprototyped return
# VALID_IN_PARROT_0_2_0 argcI = 0 # No integer values returned
# VALID_IN_PARROT_0_2_0 argcN = 0 # No float values returned
# VALID_IN_PARROT_0_2_0 argcS = 0 # No string values returned
# VALID_IN_PARROT_0_2_0
# VALID_IN_PARROT_0_2_0 returncc # Call the return continuation
.return()
.end
# Local Variables:
# mode: pir
# fill-column: 100
# End:
# vim: expandtab shiftwidth=4 ft=pir: