change printing
[lambda.git] / lambda.y
index 040d834..9155a8a 100644 (file)
--- a/lambda.y
+++ b/lambda.y
@@ -2,10 +2,11 @@
 %{
 #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();
 
@@ -17,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;
 }
 
@@ -30,17 +39,35 @@ struct lambda *make_ident(char *i)
        struct lambda *r = make_lambda();
        r->which = lambda_ident;
        r->data.identifier.ident = strdup(i);
-       r->data.identifier.revision = 0;
+       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.revision = 0;
+       r->data.abstraction.strict = strict;
        r->data.abstraction.expr = t;
+       lambda_bind(t, r, i);
        return r;
 }
 
@@ -53,6 +80,20 @@ 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));
@@ -64,59 +105,57 @@ void decls_prepend(char *ident, struct lambda *value)
 
 struct lambda *decls_lookup(char *ident)
 {
-       struct decllist *c = decls;
-       while(c != NULL){
+       for(struct decllist *c = decls; c != NULL; c = c->next)
                if(strcmp(c->ident, ident) == 0)
                        return copy(c->value);
-               c = c->next;
-       }
        return make_ident(ident);
 }
 
-void decls_print()
-{
-       struct decllist *c = decls;
-       unsigned int maxlen = 0, len;
-       while(c != NULL){
-               len = strlen(c->ident);
-               maxlen = maxlen < len ? len : maxlen;
-               c = c->next;
-       }
-
-       c = decls;
-       while(c != NULL){
-               printf("% -*s = ", maxlen, c->ident);
-               lambda_print(c->value, NULL);
-               c = c->next;
-       }
-}
-
-void decls_free()
+int main()
 {
-       struct decllist *t;
-       while(decls != NULL){
-               free(decls->ident);
-               lambda_free(decls->value);
-               t = decls->next;
-               free(decls);
-               decls = t;
-       }
+       int r = yyparse();
+       yylex_destroy();
+       return r;
 }
 
 %}
 
-%token LAMBDA DOT OBRACE CBRACE IDENT FUNC SEMICOLON ASSIGN
+%token LAMBDA DOT OBRACE CBRACE IDENT FUNC SEMICOLON ASSIGN LITERAL BANG
 
 %%
 
+program
+       :
+       | lambda SEMICOLON program
 lambda
-       : decl lambda
+       : FUNC func
+               {
+                       decls_prepend($1->data.identifier.ident, $2);
+                       printf("%s = ", $1->data.identifier.ident);
+                       lambda_print($2, NULL);
+                       lambda_free($1);
+               }
        | term
-               { result = $$; }
-decl
-       : FUNC ASSIGN term SEMICOLON
                {
-                       decls_prepend($1->data.identifier.ident, $3);
+                       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
@@ -125,24 +164,28 @@ term
        | appterm
                { $$ = $1; }
 appterm
-       : FUNC
+       : LITERAL
+               { $$ = $1; }
+       | FUNC
                {
                        $$ = decls_lookup($1->data.identifier.ident);
                        lambda_free($1);
                }
        | IDENT
-               {
-                       $$ = make_ident($1->data.identifier.ident);
-                       lambda_free($1);
-               }
+               { $$ = $1; }
        | LAMBDA abstraction
                { $$ = $2; }
        | OBRACE term CBRACE
                { $$ = $2; }
 abstraction
-       : IDENT abstraction
+       : BANG IDENT abstraction
+               {
+                       $$ = make_abstraction($2->data.identifier.ident, true, $3);
+                       lambda_free($2);
+               }
+       | IDENT abstraction
                {
-                       $$ = make_abstraction($1->data.identifier.ident, $2);
+                       $$ = make_abstraction($1->data.identifier.ident, false, $2);
                        lambda_free($1);
                }
        | DOT term