%{
#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 yywrap()
{
+ struct decllist *t;
+ while(decls != NULL){
+ free(decls->ident);
+ lambda_free(decls->value);
+ t = decls->next;
+ free(decls);
+ decls = t;
+ }
return 1;
}
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;
}
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));
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
| 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