lambda: lambda.tab.o lambda.yy.o print.o mem.o reduce.o
$(LINK.c) $(LDLIBS) $^ $(OUTPUT_OPTION)
-%.tab.c: %.y
+%.tab.c: %.y %.yy.c
$(YACC.y) -db $(basename $<) $<
%.yy.c: %.l
-program := declaration* term
-declaration := func '=' term ';'
+program := term ';' program
+ | declaration ';' program
+declaration := func strictident+ '=' term ';'
term := appterm term
| appterm
appterm := func
| ident
- | '\' ident+ '.' term
+ | '\' strictident+ '.' term
| '(' term ')'
+strictident := '!'? ident
func := 'A' | 'B' | ... | 'Z'
ident := 'a' | 'b' | ... | 'z'
struct {
char *ident;
unsigned int revision;
+ bool strict;
struct lambda *expr;
} abstraction;
struct {
};
struct lambda *make_ident(char *);
-struct lambda *make_abstraction(char *, struct lambda *);
+struct lambda *make_abstraction(char *, bool, struct lambda *);
struct lambda *make_application(struct lambda *, struct lambda *);
struct lambda *make_numeral(unsigned int i);
struct lambda *make_bool(bool b);
\. return DOT;
\( return OBRACE;
\) return CBRACE;
+\! return BANG;
true yylval = make_bool(true); return LITERAL;
false yylval = make_bool(false); return LITERAL;
[0-9]+ yylval = make_numeral(atoi(yytext)); return LITERAL;
return r;
}
-struct lambda *make_abstraction(char *i, struct lambda *t)
+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;
return r;
}
struct lambda *body = make_ident("x");
while(i-- > 0)
body = make_application(make_ident("f"), body);
- return make_abstraction("f", make_abstraction("x", body));
+ return make_abstraction("f", false, make_abstraction("x", false, body));
}
struct lambda *make_bool(bool b)
{
return b
- ? make_abstraction("a", make_abstraction("b", make_ident("a")))
- : make_abstraction("a", make_abstraction("b", make_ident("b")));
+ ? make_abstraction("a", false, make_abstraction("b", false, make_ident("a")))
+ : make_abstraction("a", false, make_abstraction("b", false, make_ident("b")));
}
void decls_prepend(char *ident, struct lambda *value)
%}
-%token LAMBDA DOT OBRACE CBRACE IDENT FUNC SEMICOLON ASSIGN LITERAL
+%token LAMBDA DOT OBRACE CBRACE IDENT FUNC SEMICOLON ASSIGN LITERAL BANG
%%
lambda_print($1, NULL);
lambda_free($1);
}
- | FUNC ASSIGN term
+ | FUNC func
{
- decls_prepend($1->data.identifier.ident, $3);
+ decls_prepend($1->data.identifier.ident, $2);
printf("%s = ", $1->data.identifier.ident);
- lambda_print($3, NULL);
+ lambda_print($2, NULL);
+ lambda_free($1);
+ }
+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
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
break;
case lambda_abs:
c->data.abstraction.ident = strdup(t->data.abstraction.ident);
+ c->data.abstraction.strict = t->data.abstraction.strict;
c->data.abstraction.expr = copy(t->data.abstraction.expr);
c->data.abstraction.revision = t->data.abstraction.revision;
break;
-I=\x.x;
-K=\x y.x;
-S=\x y z.x y(x z);
-B=\x y z.x (y z);
-C=\x y z.x z y;
-W=\x y.x y y;
-SOMEGA=\x.x x;
-OMEGA=SOMEGA SOMEGA;
-Y=\g.(\x.g (x x))(\x.g (x x));
+I x = x;
+K x y = x;
+S x y z = x y(x z);
+B x y z = x (y z);
+C x y z = x z y;
+W x y = x y y;
+SOMEGA x = x x;
+OMEGA = SOMEGA SOMEGA;
+Y g = (\x.g (x x))(\x.g (x x));
-ZERO=\f x.x;
-SUCC=\n f x.f(n f x);
-PLUS=\m n.m SUCC n;
-MULT=\m n.m (PLUS n) 0;
-EXP=\b e.e b;
+ZERO f !x = x;
+SUCC n f x = f (n f x);
+PLUS m n = m SUCC n;
+MULT m n = m (PLUS n) 0;
+EXP b e = e b;
-PRED=\n f x.n(\g h.h(g f))(\u.x)(\u.u);
-SUB=\m n.n PRED m;
+PRED n f x = n(\g h.h(g f))(\u.x)(\u.u);
+SUB m n = n PRED m;
-ISZERO=\n.n(\x.false)true;
-LEQ=\m n.ISZERO (MINUS m n);
-
-AND=\p q.p q p;
-OR=\p.p p;
+ISZERO n = n (\x.false) true;
+LEQ m n = ISZERO (MINUS m n);
+AND p q = p q p;
+OR p = p p;
#include <stdio.h>
#include "lambda.h"
+#define PRINT_ABS(t) {\
+ if(t->data.abstraction.strict)\
+ putchar('!');\
+ printf("%s", t->data.abstraction.ident);\
+ print_apos(t->data.abstraction.revision);\
+ }
+
+
void print_apos(unsigned int revision)
{
if(revision == 1)
}
}
-void print_ident(char *ident, unsigned int revision)
-{
- printf("%s", ident);
- while(revision > 2){
- putchar('\"');
- revision -= 2;
- }
- if(revision == 1)
- putchar('\'');
-}
-
void term_print(struct lambda *t, struct lambda *mark)
{
if(t == mark)
putchar('|');
switch(t->which){
case lambda_ident:
- print_ident(t->data.identifier.ident, t->data.identifier.revision);
+ printf("%s", t->data.identifier.ident);
+ print_apos(t->data.identifier.revision);
break;
case lambda_abs:
printf("λ");
- print_ident(t->data.abstraction.ident, t->data.abstraction.revision);
+ PRINT_ABS(t);
while((t = t->data.abstraction.expr)->which == lambda_abs){
putchar(' ');
- print_ident(t->data.abstraction.ident, t->data.abstraction.revision);
+ PRINT_ABS(t);
}
putchar('.');
term_print(t, mark);
void lambda_print(struct lambda *t, struct lambda *mark)
{
term_print(t, mark);
- putchar('\n');
+ printf(";\n");
}
t1 = t->data.application.expr1;
t2 = t->data.application.expr2;
lambda_reduce(t1, total, maxdepth);
- //For applicative order
- lambda_reduce(t2, total, maxdepth);
if(t1->which == lambda_abs){
+ if(t1->data.abstraction.strict)
+ lambda_reduce(t2, total, maxdepth);
lambda_print(total, t);
printf("β -> ");
lambda_beta(t1, t1->data.abstraction.expr, t2, total);
(*maxdepth)--;
lambda_reduce(t, total, maxdepth);
}
- //For applicative order
- } else if(t->which == lambda_abs) {
- lambda_reduce(t->data.abstraction.expr, total, maxdepth);
}
}