1 REM Step 6 of mal in BBC BASIC
11 repl_env% = FNalloc_environment(FNnil)
12 PROCcore_ns : REM This sets the data pointer
16 PROCenv_set(repl_env%, FNalloc_symbol(sym$), FNalloc_corefn(i%))
20 REM Initial forms to evaluate
22 DATA (def! not (fn* (a) (if a false true)))
23 DATA (def! load-file (fn* (f) (eval (read-string (str "(do " (slurp f) ")")))))
27 IF form$ <> "" THEN val$ = FNrep(form$)
32 IF FNis_empty(argv%) THEN
33 PROCenv_set(repl_env%, FNalloc_symbol("*ARGV*"), FNempty)
35 PROCenv_set(repl_env%, FNalloc_symbol("*ARGV*"), FNrest(argv%))
36 val$ = FNrep("(load-file " + FNpr_str(FNfirst(argv%), TRUE) + ")")
41 REM Catch all errors apart from "Escape".
42 ON ERROR LOCAL PRINT REPORT$:IF ERR = 17 THEN END ELSE PROCgc_restore(sav%)
55 DEF FNEVAL(ast%, env%)
57 =FNgc_exit(FNEVAL_(ast%, env%))
59 DEF FNEVAL_(ast%, env%)
60 LOCAL car%, specialform%, val%, bindings%
62 PROCgc_keep_only2(ast%, env%)
63 IF NOT FNis_list(ast%) THEN =FNeval_ast(ast%, env%)
64 IF FNis_empty(ast%) THEN =ast%
67 IF FNis_symbol(car%) THEN
69 CASE FNunbox_symbol(car%) OF
72 val% = FNEVAL(FNnth(ast%, 2), env%)
73 PROCenv_set(env%, FNnth(ast%, 1), val%)
76 env% = FNalloc_environment(env%)
77 bindings% = FNnth(ast%, 1)
78 WHILE NOT FNis_empty(bindings%)
79 PROCenv_set(env%, FNfirst(bindings%), FNEVAL(FNnth(bindings%, 1), env%))
80 bindings% = FNrest(FNrest(bindings%))
83 REM Loop round for tail-call optimisation.
85 REM The guide has us call FNeval_ast on the sub-list that excludes
86 REM the last element of ast%, but that's a bit painful without
87 REM native list slicing, so it's easier to just re-implement the
88 REM bit of FNeval_ast that we need.
90 WHILE NOT FNis_empty(FNrest(ast%))
91 val% = FNEVAL(FNfirst(ast%), env%)
96 IF FNis_truish(FNEVAL(FNnth(ast%, 1), env%)) THEN
99 IF FNcount(ast%) = 3 THEN =FNnil ELSE ast% = FNnth(ast%, 3)
101 REM Loop round for tail-call optimisation.
103 =FNalloc_fn(FNnth(ast%, 2), FNnth(ast%, 1), env%)
108 IF NOT specialform% THEN
109 REM This is the "apply" part.
110 ast% = FNeval_ast(ast%, env%)
112 IF FNis_corefn(car%) THEN
113 =FNcore_call(FNunbox_corefn(car%), FNrest(ast%))
115 IF FNis_fn(car%) THEN
116 env% = FNnew_env(FNfn_env(car%), FNfn_params(car%), FNrest(ast%))
117 ast% = FNfn_ast(car%)
118 REM Loop round for tail-call optimisation.
120 ERROR &40E80918, "Not a function"
129 =FNPRINT(FNEVAL(FNREAD(a$), repl_env%))
131 DEF FNeval_ast(ast%, env%)
132 LOCAL val%, car%, cdr%
133 IF FNis_symbol(ast%) THEN =FNenv_get(env%, ast%)
134 IF FNis_seq(ast%) THEN
135 IF FNis_empty(ast%) THEN =ast%
136 car% = FNEVAL(FNfirst(ast%), env%)
137 cdr% = FNeval_ast(FNrest(ast%), env%)
138 IF FNis_vector(ast%) THEN =FNalloc_vector_pair(car%, cdr%)
139 =FNalloc_pair(car%, cdr%)
145 LOCAL argv%, rargv%, cmdptr%, arg$, len%
147 IF !PAGE = &D7C1C7C5 THEN
148 REM Running under Brandy, so ARGC and ARGV$ are usable.
150 FOR i% = ARGC TO 1 STEP -1
151 argv% = FNalloc_pair(FNalloc_string(ARGV$(i%)), argv%)
155 IF (INKEY(-256) AND &F0) = &A0 THEN
157 REM Running under RISC OS
158 REM Vexingly, we can only get the command line that was passed to
159 REM the BASIC interpreter. This means that we need to extract
160 REM the arguments from that. Typically, we will have been started
161 REM with "BASIC -quit <filename> <args>".
164 SYS "OS_GetEnv" TO cmdptr%
166 SYS "OS_GSTrans", cmdptr%, q%, &20000000 + 256 TO cmdptr%, , len%
168 rargv% = FNalloc_pair(FNalloc_string($q%), rargv%)
170 REM Put argv back into the right order.
171 WHILE NOT FNis_empty(rargv%)
172 argv% = FNalloc_pair(FNfirst(rargv%), argv%)
173 rargv% = FNrest(rargv%)
175 IF FNis_empty(argv%) THEN =FNgc_exit(argv%)
176 argv% = FNrest(argv%) : REM skip "BASIC"
177 IF FNis_empty(argv%) THEN =FNgc_exit(argv%)
178 IF FNunbox_string(FNfirst(argv%)) <> "-quit" THEN =FNgc_exit(argv%)
179 argv% = FNrest(argv%) : REM skip "-quit"
180 IF FNis_empty(argv%) THEN =FNgc_exit(argv%)
181 argv% = FNrest(argv%) : REM skip filename
188 REM indent-tabs-mode: nil