summaryrefslogtreecommitdiffstats
path: root/parser.y
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2011-11-28 09:22:38 -0800
committerKaz Kylheku <kaz@kylheku.com>2011-11-28 09:22:38 -0800
commit8104a2598204df75a485bcb27bd35a2d1c79dc31 (patch)
treefe15a667e4d28af3bd030661c4c1ba71b8a55af7 /parser.y
parent92514021697a83be8332457b3dcc437f029ee786 (diff)
downloadtxr-8104a2598204df75a485bcb27bd35a2d1c79dc31.tar.gz
txr-8104a2598204df75a485bcb27bd35a2d1c79dc31.tar.bz2
txr-8104a2598204df75a485bcb27bd35a2d1c79dc31.zip
Added evaluation support for quote and quasiquote with unquotes.
New functions list, append and eval. Code walking framework for expanding quasiquotes. quotes right now. * eval.c (let_s, lambda_s, call_s, cond_s, if_s, and_s, or_s defvar_s, defun_s, list_s, append_s): New symbol variables. (eval_intrinsic, op_quote, expand_forms, expand_cond_pairs, expand_place, expand_qquote): New static functions. (expand): New external function. (eval_init): Initialize new symbol variables. Use newly defined symbol variables to register functions. Also, new functions: quote, append, list and eval. * eval.h (expand): Declared. * lib.c (appendv): New function. (obj_init): quote and splice operator symbols moved into system package. (obj_print, obj_pprint): Support for printing quotes and splices. * lib.h (appendv): Declared. * match.c (do_s): New symbol variable. (syms_init): New variable initialized. (dir_tales_init): New variable used instead of intern. * match.h (do_s): Declared. * parser.y (elem): @(do) form recognized and its argument passed through the new expander. (o_elem, quasi_item): Pass list through expander. (list): Use choose_quote to decide whether to put regular quote or quasiquote on quoted list. (meta_expr): Fixed abstract syntax so the expression is a single argument of the sys:expr, rather than multiple arguments. (unquotes_occur, choose_quote): New static function.
Diffstat (limited to 'parser.y')
-rw-r--r--parser.y42
1 files changed, 36 insertions, 6 deletions
diff --git a/parser.y b/parser.y
index 37d6af35..6aa4d2e0 100644
--- a/parser.y
+++ b/parser.y
@@ -38,6 +38,7 @@
#include "utf8.h"
#include "match.h"
#include "hash.h"
+#include "eval.h"
#include "parser.h"
int yylex(void);
@@ -48,6 +49,7 @@ static val o_elems_transform(val output_form);
static val define_transform(val define_form);
static val lit_char_helper(val litchars);
static val optimize_text(val text_form);
+static val choose_quote(val quoted_form);
static wchar_t char_from_name(wchar_t *name);
static val parsed_spec;
@@ -290,7 +292,15 @@ texts : text %prec LOW { $$ = rlcp(cons($1, nil), $1); }
elem : texts { $$ = rlcp(cons(text_s, $1), $1);
$$ = rlcp(optimize_text($$), $$); }
| var { $$ = rl($1, num(lineno)); }
- | list { $$ = $1; }
+ | list { if (first($1) == do_s)
+ { val form = second($1);
+ val form_ex = expand(form);
+
+ if (form == form_ex)
+ $$ = $1;
+ else
+ $$ = rlcp(cons(do_s, cons(form_ex, nil)),
+ $1); }}
| COLL exprs_opt ')' elems END { $$ = list(coll_s, $4, nil, $2, nao);
rl($$, num($1)); }
| COLL exprs_opt ')' elems
@@ -515,7 +525,7 @@ o_elem : TEXT { $$ = string_own($1);
| SPACE { $$ = string_own($1);
rl($$, num(lineno)); }
| o_var { $$ = $1; }
- | list { $$ = rlcp(cons(expr_s, $1), $1); }
+ | list { $$ = rlcp(cons(expr_s, expand($1)), $1); }
| rep_elem { $$ = $1; }
;
@@ -603,14 +613,15 @@ var_op : '*' { $$ = list(t, nao); }
list : '(' exprs ')' { $$ = rl($2, num($1)); }
| '(' ')' { $$ = nil; }
| ',' expr { $$ = rlcp(list(unquote_s, $2, nao), $2); }
- | '\'' expr { $$ = rlcp(list(qquote_s, $2, nao), $2); }
+ | '\'' expr { $$ = rlcp(list(choose_quote($2),
+ $2, nao), $2); }
| SPLICE expr { $$ = rlcp(list(splice_s, $2, nao), $2); }
| '(' error { $$ = nil;
yybadtoken(yychar, lit("list expression")); }
;
-meta_expr : METAPAR exprs ')' { $$ = cons(expr_s, $2); }
- | METAPAR ')' { $$ = cons(expr_s, nil); }
+meta_expr : METAPAR exprs ')' { $$ = rlcp(cons(expr_s, expand($2)), $2); }
+ | METAPAR ')' { $$ = rl(cons(expr_s, nil), num(lineno)); }
| METAPAR error { $$ = nil;
yybadtoken(yychar, lit("meta expression")); }
;
@@ -752,7 +763,7 @@ quasi_items : quasi_item { $$ = cons($1, nil); }
quasi_item : litchars { $$ = lit_char_helper($1); }
| TEXT { $$ = string_own($1); }
| var { $$ = $1; }
- | list { $$ = rlcp(cons(expr_s, $1), $1); }
+ | list { $$ = rlcp(cons(expr_s, expand($1)), $1); }
;
litchars : LITCHAR { $$ = cons(chr($1), nil); }
@@ -879,6 +890,25 @@ static val optimize_text(val text_form)
return text_form;
}
+static val unquotes_occur(val quoted_form)
+{
+ if (atom(quoted_form)) {
+ return nil;
+ } else {
+ val sym = car(quoted_form);
+ if (sym == unquote_s || sym == splice_s)
+ return t;
+ if (sym == quote_s)
+ return nil;
+ return or2(unquotes_occur(sym), unquotes_occur(cdr(quoted_form)));
+ }
+}
+
+static val choose_quote(val quoted_form)
+{
+ return unquotes_occur(quoted_form) ? qquote_s : quote_s;
+}
+
val rl(val form, val lineno)
{
sethash(form_to_ln_hash, form, lineno);