8 typedef struct Sym Sym;
9 typedef struct Node Node;
34 #pragma varargck type "N" Node*
40 Node* new(int, Node*, Node*);
53 void diag(Node*, char*, ...);
55 void fcom(Node*,Node*,Node*);
57 #pragma varargck argpos cprint 1
58 #pragma varargck argpos diag 2
69 %type <node> name num args expr bool block elif stmnt stmnts
82 %token <lval> MOD IF ELSE WHILE BREAK
83 %token <sval> NAME NUM
110 $$ = new(NAME,nil,nil);
116 $$ = new(NUM,nil,nil);
121 ELSE IF '(' bool ')' stmnt
123 $$ = new('?', $4, new(':', $6, nil));
125 | ELSE IF '(' bool ')' stmnt elif
127 $$ = new('?', $4, new(':', $6, $7));
141 $$ = new('=', $1, $3);
145 $$ = new('m', $2, $3);
147 | IF '(' bool ')' stmnt
149 $$ = new('?', $3, new(':', $5, nil));
151 | IF '(' bool ')' stmnt elif
153 $$ = new('?', $3, new(':', $5, $6));
155 | WHILE '(' bool ')' stmnt
157 $$ = new('@', new('?', $3, new(':', $5, new('b', nil, nil))), nil);
161 $$ = new('b', nil, nil);
166 $$ = new('e', $1, nil);
181 $$ = new('\n', $1, $2);
200 $$ = new(NUM, nil, nil);
203 $$ = new('-', $$, $2);
207 $$ = new(',', $1, $3);
211 $$ = new('^', $1, $3);
215 $$ = new('*', $1, $3);
219 $$ = new('/', $1, $3);
223 $$ = new('%', $1, $3);
227 $$ = new('+', $1, $3);
231 $$ = new('-', $1, $3);
233 | bool '?' expr ':' expr
235 $$ = new('?', $1, new(':', $3, $5));
239 $$ = new('e', $1, $2);
243 $$ = new(LSH, $1, $3);
247 $$ = new(RSH, $1, $3);
257 $$ = new('!', $2, nil);
261 $$ = new(EQ, $1, $3);
265 $$ = new('!', new(EQ, $1, $3), nil);
269 $$ = new('>', $1, $3);
273 $$ = new('<', $1, $3);
281 static char buf[200];
295 while((c = getch()) > 0)
311 if(getch() == '<') return LSH;
315 if(getch() == '>') return RSH;
319 if(getch() == '=') return EQ;
323 if(getch() == '=') return NEQ;
334 || (c >= 'a' && c <= 'z')
335 || (c >= 'A' && c <= 'Z')
336 || (c >= '0' && c <= '9')){
345 if(strcmp(buf, "mod") == 0)
347 if(strcmp(buf, "if") == 0)
349 if(strcmp(buf, "else") == 0)
351 if(strcmp(buf, "while") == 0)
353 if(strcmp(buf, "break") == 0)
356 yylval.sval = sym(buf);
358 return (buf[0] >= '0' && buf[0] <= '9') ? NUM : NAME;
384 new(int c, Node *l, Node *r)
388 n = malloc(sizeof(Node));
400 static Sym *tab[128];
406 for(i=0; n[i] != '\0'; i++){
413 for(s = tab[h]; s != nil; s = s->l)
414 if(strcmp(s->n, n) == 0)
416 s = malloc(sizeof(Sym)+i+1);
417 memmove(s->n, n, i+1);
427 fprint(2, "%s:%d: %s\n", filename, lineno, s);
431 cprint(char *fmt, ...)
433 static char buf[1024], tabs[] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
438 vsnprint(buf, sizeof(buf), fmt, a);
442 while((x = strchr(p, '\n')) != nil){
445 p = &tabs[sizeof(tabs)-1 - clevel];
447 write(1, p, strlen(p));
451 write(1, p, strlen(p));
465 snprint(n, sizeof(n), "tmp%d", ++ntmp);
466 t = new(NAME, nil, nil);
471 cprint("%N = mpnew(0);\n", t);
472 t->s->f &= ~(FSET|FUSE);
484 return n->s == sym("mpzero") ||
485 n->s == sym("mpone") ||
486 n->s == sym("mptwo");
497 for(l = atmps; l != nil; l = l->l){
522 for(l = atmps; l != nil; l = l->l){
524 cprint("mpfree(%N);\n", t);
535 symref(Node *n, Sym *s)
539 if(n->c == NAME && n->s == s)
541 return symref(n->l, s) || symref(n->r, s);
564 if(n->c == NUM && strlen(n->s->n) == 1 && atoi(n->s->n) < 3)
570 bcom(Node *n, Node *t);
573 ecom(Node *f, Node *t)
582 m = strtomp(f->s->n, nil, 10, nil);
583 if(mpcmp(m, mpzero) == 0){
585 f->s = sym("mpzero");
589 if(mpcmp(m, mpone) == 0){
595 if(mpcmp(m, mptwo) == 0){
606 diag(f, "cannot assign list to %N", t);
607 f->l = ecom(f->l, nil);
608 f->r = ecom(f->r, nil);
614 if((f->s->f & FSET) == 0)
615 diag(f, "name used but not set");
620 cprint("mpassign(%N, %N);\n", f, t);
635 cprint("%N(%N);\n", f->l, t);
637 cprint("%N(%N, %N);\n", f->l, r, t);
642 diag(f, "destination %N not a name", t);
646 m = strtomp(f->s->n, nil, 10, nil);
647 if(mpsignif(m) <= 32)
648 cprint("uitomp(%udUL, %N);\n", mptoui(m), t);
649 else if(mpsignif(m) <= 64)
650 cprint("uvtomp(%lludULL, %N);\n", mptouv(m), t);
652 cprint("strtomp(\"%.16B\", nil, 16, %N);\n", m, t);
656 l = f->l->c == NAME ? f->l : ecom(f->l, t);
657 cprint("mpleft(%N, %N, %N);\n", l, f->r, t);
660 l = f->l->c == NAME ? f->l : ecom(f->l, t);
661 cprint("mpright(%N, %N, %N);\n", l, f->r, t);
669 l = ecom(f->l, complex(f->l) && !symref(f->r, t->s) ? t : nil);
670 r = ecom(f->r, complex(f->r) && l->s != t->s ? t : nil);
678 cprint("mpmodadd(%N, %N, %N, %N);\n", l, r, modulo, t);
681 cprint("mpmodsub(%N, %N, %N, %N);\n", l, r, modulo, t);
685 if(l->s == sym("mptwo") || r->s == sym("mptwo"))
686 cprint("mpmodadd(%N, %N, %N, %N); // 2*%N\n",
687 r->s == sym("mptwo") ? l : r,
688 r->s == sym("mptwo") ? l : r,
692 cprint("mpmodmul(%N, %N, %N, %N);\n", l, r, modulo, t);
695 if(l->s == sym("mpone")){
696 cprint("mpinvert(%N, %N, %N);\n", r, modulo, t);
700 cprint("mpinvert(%N, %N, %N);\n", r, modulo, t2);
701 cprint("mpmodmul(%N, %N, %N, %N);\n", l, t2, modulo, t);
705 if(r->s == sym("mptwo")){
709 cprint("mpexp(%N, %N, %N, %N);\n", l, r, modulo, t);
716 cprint("mpadd(%N, %N, %N);\n", l, r, t);
719 if(l->s == sym("mpzero")){
721 cprint("%N->sign = -%N->sign;\n", t, t);
723 cprint("mpsub(%N, %N, %N);\n", l, r, t);
727 if(l->s == sym("mptwo") || r->s == sym("mptwo"))
728 cprint("mpleft(%N, 1, %N);\n", r->s == sym("mptwo") ? l : r, t);
730 cprint("mpmul(%N, %N, %N);\n", l, r, t);
733 cprint("mpdiv(%N, %N, %N, %N);\n", l, r, t, nil);
736 cprint("mpmod(%N, %N, %N);\n", l, r, t);
739 if(r->s == sym("mptwo")){
743 cprint("mpexp(%N, %N, nil, %N);\n", l, r, t);
746 diag(f, "unknown operation");
759 bcom(Node *n, Node *t)
780 b1 = ecom(n->r->l, nil);
781 b2 = ecom(n->r->r, nil);
789 cprint("mpcmp(%N, %N)", l, r);
794 cprint(" >> (sizeof(int)*8-1)");
796 cprint(", %N, %N, %N);\n", neg ? b2 : b1, neg ? b1 : b2, t);
805 cprint("mpcmp(%N, %N)", l, r);
807 cprint(neg ? " != 0" : " == 0");
809 cprint(neg ? " <= 0" : " > 0");
811 cprint(neg ? " >= 0" : " < 0");
818 diag(n, "saw %N in boolean expression", f);
840 for(l = atmps; l != nil; l = l->l)
841 cprint("mpfree(%N);\n", l);
867 modulo = ecom(n->l, nil);
874 cprint("%N();\n", n->l);
877 cprint("%N(%N);\n", n->l, r);
888 flocs(Node *n, Node *r)
901 diag(n, "lhs is nil");
910 if(n->c == NAME && (n->s->f & (FARG|FLOC)) == 0){
912 return new(',', n, r);
920 fcom(Node *f, Node *a, Node *b)
925 ftmps = atmps = modulo = nil;
927 cprint("void %N(", f);
932 l = a->c == NAME ? a : a->l;
934 cprint("mpint *%N", l);
939 for(a = l0; a != nil; a = a->r)
940 cprint("mpint *%N = mpnew(0);\n", a->l);
942 for(a = l0; a != nil; a = a->r)
943 cprint("mpfree(%N);\n", a->l);
949 diag(Node *n, char *fmt, ...)
951 static char buf[1024];
955 vsnprint(buf, sizeof(buf), fmt, a);
958 fprint(2, "%s:%d: for %N; %s\n", filename, n->n, n, buf);
965 Node *n = va_arg(f->args, Node*);
968 return fmtprint(f, "nil");
971 return fmtprint(f, "%N, %N", n->l, n->r);
976 return fmtprint(f, "%s", n->s->n);
978 return fmtprint(f, "==");
980 return fmtprint(f, "if");
982 return fmtprint(f, "else");
984 return fmtprint(f, "mod");
986 return fmtprint(f, "%c", (char)n->c);
991 parse(int fd, char *file)
993 Binit(&bin, fd, OREAD);
1006 fprint(2, "%s [file ...]\n", argv0);
1011 main(int argc, char *argv[])
1013 fmtinstall('N', Nfmt);
1014 fmtinstall('B', mpfmt);
1022 parse(0, "<stdin>");
1025 while(*argv != nil){
1028 if((fd = open(*argv, OREAD)) < 0){
1029 fprint(2, "%s: %r\n", *argv);