change printing
[lambda.git] / lambda.y
index 4d47f9b..9155a8a 100644 (file)
--- a/lambda.y
+++ b/lambda.y
@@ -1,9 +1,13 @@
+%define parse.error verbose
 %{
 #include "lambda.h"
 #include "lambda.tab.h"
+#include "lambda.yy.h"
 #include "mem.h"
+#include "print.h"
+#include "reduce.h"
 
-struct lambda *result;
+struct decllist *decls = NULL;
 extern int yylex();
 
 int yydebug=1;
@@ -14,6 +18,14 @@ void yyerror(const char *str)
 
 int yywrap()
 {
+       struct decllist *t;
+       while(decls != NULL){
+               free(decls->ident);
+               lambda_free(decls->value);
+               t = decls->next;
+               free(decls);
+               decls = t;
+       }
        return 1;
 }
 
@@ -26,16 +38,36 @@ struct lambda *make_ident(char *i)
 {
        struct lambda *r = make_lambda();
        r->which = lambda_ident;
-       r->data.identifier = strdup(i);
+       r->data.identifier.ident = strdup(i);
+       r->data.identifier.binding = NULL;
        return r;
 }
 
-struct lambda *make_abstraction(char *i, struct lambda *t)
+void lambda_bind(struct lambda *tob, struct lambda *binding, char *ident)
+{
+       switch(tob->which){
+       case lambda_ident:
+               if(strcmp(ident, tob->data.identifier.ident) == 0 && tob->data.identifier.binding == NULL)
+                       tob->data.identifier.binding = binding;
+               break;
+       case lambda_abs:
+               lambda_bind(tob->data.abstraction.expr, binding, ident);
+               break;
+       case lambda_app:
+               lambda_bind(tob->data.application.expr1, binding, ident);
+               lambda_bind(tob->data.application.expr2, binding, ident);
+               break;
+       }
+}
+
+struct lambda *make_abstraction(char *i, bool strict, struct lambda *t)
 {
        struct lambda *r = make_lambda();
        r->which = lambda_abs;
        r->data.abstraction.ident = strdup(i);
+       r->data.abstraction.strict = strict;
        r->data.abstraction.expr = t;
+       lambda_bind(t, r, i);
        return r;
 }
 
@@ -48,45 +80,113 @@ struct lambda *make_application(struct lambda *t1, struct lambda *t2)
        return r;
 }
 
+struct lambda *make_numeral(unsigned int i)
+{
+       struct lambda *body = make_ident("x");
+       while(i-- > 0)
+               body = make_application(make_ident("f"), body);
+       return make_abstraction("f", false, make_abstraction("x", false, body));
+}
+
+struct lambda *make_bool(bool b)
+{
+       return make_abstraction("a", false,
+               make_abstraction("b", false, make_ident(b ? "a" : "b")));
+}
+
+void decls_prepend(char *ident, struct lambda *value)
+{
+       struct decllist *head = malloc(sizeof (struct decllist));
+       head->next = decls;
+       head->ident = strdup(ident);
+       head->value = value;
+       decls = head;
+}
+
+struct lambda *decls_lookup(char *ident)
+{
+       for(struct decllist *c = decls; c != NULL; c = c->next)
+               if(strcmp(c->ident, ident) == 0)
+                       return copy(c->value);
+       return make_ident(ident);
+}
+
+int main()
+{
+       int r = yyparse();
+       yylex_destroy();
+       return r;
+}
+
 %}
 
-%token LAMBDA DOT OBRACE CBRACE IDENT I K S T F
+%token LAMBDA DOT OBRACE CBRACE IDENT FUNC SEMICOLON ASSIGN LITERAL BANG
 
 %%
 
+program
+       :
+       | lambda SEMICOLON program
 lambda
-       : term
-               { result = $$; }
-term
-       : term appterm
+       : FUNC func
                {
-                       $$ = make_application($1, $2);
+                       decls_prepend($1->data.identifier.ident, $2);
+                       printf("%s = ", $1->data.identifier.ident);
+                       lambda_print($2, NULL);
+                       lambda_free($1);
                }
+       | term
+               {
+                       struct lambda *t = $1;
+                       printf("     ");
+                       for(unsigned int i = 0; i<999; i++)
+                               if(!lambda_reduce(&t, &t, false))
+                                       break;
+                       lambda_print(t, NULL);
+                       lambda_free(t);
+               }
+func
+       : ASSIGN term
+               { $$ = $2; }
+       | BANG IDENT func
+               {
+                       $$ = make_abstraction($2->data.identifier.ident, true, $3);
+                       lambda_free($2);
+               }
+       | IDENT func
+               {
+                       $$ = make_abstraction($1->data.identifier.ident, false, $2);
+                       lambda_free($1);
+               }
+term
+       : term appterm
+               { $$ = make_application($1, $2); }
        | appterm
                { $$ = $1; }
 appterm
-       : IDENT
+       : LITERAL
+               { $$ = $1; }
+       | FUNC
                {
-                       $$ = make_ident($1->data.identifier);
+                       $$ = decls_lookup($1->data.identifier.ident);
                        lambda_free($1);
                }
-       | LAMBDA IDENT DOT term
+       | IDENT
+               { $$ = $1; }
+       | LAMBDA abstraction
+               { $$ = $2; }
+       | OBRACE term CBRACE
+               { $$ = $2; }
+abstraction
+       : BANG IDENT abstraction
                {
-                       $$ = make_abstraction($2->data.identifier, $4);
+                       $$ = make_abstraction($2->data.identifier.ident, true, $3);
                        lambda_free($2);
                }
-       | OBRACE term CBRACE
-               { $$ = $2; }
-       | I
-               { $$ = make_abstraction("x", make_ident("x")); }
-       | K
-               { $$ = make_abstraction("x", make_abstraction("y", make_ident("x"))); }
-       | S
-               { $$ = make_abstraction("x", make_abstraction("y", make_abstraction("z",
-                       make_application(make_application(make_ident("x"), make_ident("y")),
-                               make_application(make_ident("y"), make_ident("z"))))));
+       | IDENT abstraction
+               {
+                       $$ = make_abstraction($1->data.identifier.ident, false, $2);
+                       lambda_free($1);
                }
-       | T
-               { $$ = make_abstraction("x", make_abstraction("y", make_ident("x"))); }
-       | F
-               { $$ = make_abstraction("x", make_abstraction("y", make_ident("y"))); }
+       | DOT term
+               { $$ = $2; }