Mercurial > urweb
comparison lib/js/urweb.js @ 970:8371d12ae63f
Hopefully complete refactoring of Jscomp to output ASTs; partial implementation of interpreter in runtime system (demo/alert works)
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Tue, 22 Sep 2009 12:23:21 -0400 |
parents | 001edfbe2561 |
children | c22e524a6dd3 |
comparison
equal
deleted
inserted
replaced
969:001edfbe2561 | 970:8371d12ae63f |
---|---|
1 // Function versions of operators | |
2 | |
3 function not(x) { return !x; } | |
4 function neg(x) { return -x; } | |
5 | |
6 function eq(x, y) { return x == y; } | |
7 function plus(x, y) { return x + y; } | |
8 function minus(x, y) { return x - y; } | |
9 function times(x, y) { return x * y; } | |
10 function div(x, y) { return x / y; } | |
11 function mod(x, y) { return x % y; } | |
12 function lt(x, y) { return x < y; } | |
13 function le(x, y) { return x <= y; } | |
14 | |
1 // Lists | 15 // Lists |
2 | 16 |
3 function cons(v, ls) { | 17 function cons(v, ls) { |
4 return { next : ls, data : v }; | 18 return { next : ls, data : v }; |
5 } | 19 } |
763 } | 777 } |
764 | 778 |
765 | 779 |
766 // Key events | 780 // Key events |
767 | 781 |
768 function kc(e) { | 782 var uw_event = null; |
769 return window.event ? e.keyCode : e.which; | 783 |
784 function kc() { | |
785 return window.event ? uw_event.keyCode : uw_event.which; | |
786 } | |
787 | |
788 | |
789 // The Ur interpreter | |
790 | |
791 var urfuncs = []; | |
792 | |
793 function lookup(env, n) { | |
794 while (env != null) { | |
795 if (n == 0) | |
796 return env.data; | |
797 else { | |
798 --n; | |
799 env = env.next; | |
800 } | |
801 } | |
802 | |
803 throw "Out-of-bounds Ur variable reference"; | |
804 } | |
805 | |
806 function exec0(env, e) { | |
807 var stack = null; | |
808 | |
809 while (true) { | |
810 switch (e.c) { | |
811 case "c": | |
812 var v = e.v; | |
813 if (stack == null) | |
814 return v; | |
815 var fr = stack.data; | |
816 | |
817 switch (fr.c) { | |
818 case "s": | |
819 e = {c: "c", v: {v: v}}; | |
820 stack = stack.next; | |
821 break; | |
822 case "1": | |
823 e = {c: "c", v: {n: fr.n, v: v}}; | |
824 stack = stack.next; | |
825 break; | |
826 case "f": | |
827 fr.args[fr.pos++] = v; | |
828 if (fr.a == null) { | |
829 e = {c: "c", v: fr.f.apply(null, fr.args)}; | |
830 stack = stack.next; | |
831 } else { | |
832 e = fr.a.data; | |
833 fr.a = fr.a.next; | |
834 } | |
835 break; | |
836 case "a1": | |
837 if (v == null || !v.body) | |
838 throw "Ur: applying non-function"; | |
839 stack = cons({c: "a2", env: v.env, body: v.body}, stack.next); | |
840 e = fr.x; | |
841 break; | |
842 case "a2": | |
843 stack = cons({c: "a3", env: env}, stack.next); | |
844 env = cons(v, fr.env); | |
845 e = fr.body; | |
846 break; | |
847 case "a3": | |
848 env = fr.env; | |
849 stack = stack.next; | |
850 break; | |
851 case "r": | |
852 fr.fs["_" + fr.n] = v; | |
853 if (fr.l == null) { | |
854 e = {c: "c", v: fr.fs}; | |
855 stack = stack.next; | |
856 } else { | |
857 fr.n = fr.l.data.n; | |
858 e = fr.l.data.v; | |
859 fr.l = fr.l.next; | |
860 } | |
861 break; | |
862 case ".": | |
863 e = {c: "c", v: v["_" + fr.f]}; | |
864 stack = stack.next; | |
865 break; | |
866 case ";": | |
867 e = fr.e2; | |
868 stack = stack.next; | |
869 break; | |
870 case "=1": | |
871 env = cons(v, env); | |
872 e = fr.e2; | |
873 stack = stack.next; | |
874 break; | |
875 case "=": | |
876 env = cons(v, env); | |
877 e = fr.e2; | |
878 stack = cons({c: "a3", env: env}, stack.next); | |
879 break; | |
880 default: | |
881 throw "Unknown Ur continuation kind"; | |
882 } | |
883 | |
884 break; | |
885 case "v": | |
886 e = {c: "c", v: lookup(env, e.n)}; | |
887 break; | |
888 case "n": | |
889 e = {c: "c", v: urfuncs[e.n]}; | |
890 break; | |
891 case "s": | |
892 stack = cons({c: "s"}, stack); | |
893 e = e.v; | |
894 break; | |
895 case "1": | |
896 stack = cons({c: "1", n: e.n}, stack); | |
897 e = e.v; | |
898 break; | |
899 case "f": | |
900 if (e.a == null) | |
901 e = {c: "c", v: e.f()}; | |
902 else { | |
903 var args = []; | |
904 stack = cons({c: "f", f: e.f, args: args, pos: 0, a: e.a.next}, stack); | |
905 e = e.a.data; | |
906 } | |
907 break; | |
908 case "l": | |
909 e = {c: "c", v: {env: env, body: e.b}}; | |
910 break; | |
911 case "a": | |
912 stack = cons({c: "a1", x: e.x}, stack); | |
913 e = e.f; | |
914 break; | |
915 case "r": | |
916 if (e.l == null) | |
917 throw "Empty Ur record in interpretation"; | |
918 var fs = {}; | |
919 stack = cons({c: "r", n: e.l.data.n, fs: fs, l: e.l.next}, stack); | |
920 e = e.l.data; | |
921 break; | |
922 case ".": | |
923 stack = cons({c: ".", f: e.f}, stack); | |
924 e = e.r; | |
925 break; | |
926 case ";": | |
927 stack = cons({c: ";", e2: e.e2}, stack); | |
928 e = e.e1; | |
929 break; | |
930 case "=": | |
931 stack = cons({c: "=", e2: e.e2}, stack); | |
932 e = e.e1; | |
933 break; | |
934 case "e": | |
935 var env0 = env; | |
936 var e0 = e.e; | |
937 e = {c: "c", v: cs(function() { return exec0(env0, e0); })}; | |
938 break; | |
939 default: | |
940 throw "Unknown Ur expression kind"; | |
941 } | |
942 } | |
943 } | |
944 | |
945 function exec(e) { | |
946 var r = exec0(null, e); | |
947 | |
948 if (r != null && r.body) | |
949 return function(v) { return exec0(cons(v, r.env), r.body); }; | |
950 else | |
951 return r; | |
770 } | 952 } |
771 | 953 |
772 | 954 |
773 // App-specific code | 955 // App-specific code |
774 | 956 |