-
Notifications
You must be signed in to change notification settings - Fork 0
/
vm.pl
132 lines (108 loc) · 5.44 KB
/
vm.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
:- consult(compiler).
simplify(X, Y) :-
compound(X), !,
term_to_atom(X, Y).
simplify([], "[]") :- !.
simplify(X, X).
lookup(_, [], 0) :- !.
lookup(X, [(X, V)|_], V) :- !.
lookup(X, [_|M], V) :-
lookup(X, M, V).
assign(K, V, [], [(K, V)]) :- !.
assign(K, V, [(K, _)|M], [(K, V)|M]) :- !.
assign(K, V, [KV|M], [KV|M1]) :-
assign(K, V, M, M1).
get_head(T, T, T).
% encode_int(X, [B1, B2, B3, B4]) :-
% integer(X), !,
% B4 is X mod (1 << 8),
% B3 is (X >> 8) mod (1 << 8),
% B2 is (X >> 16) mod (1 << 8),
% B1 is X >> 24.
% encode_int(X, [B1, B2, B3, B4]) :-
% integer(B1), integer(B2), integer(B3), integer(B4),
% X is (B1 << 24) + (B2 << 16) + (B3 << 8) + B4.
decomp(0x1, load_int) :- !.
decomp(0x2, load) :- !.
decomp(0x3, store) :- !.
decomp(0x4, add) :- !.
decomp(0x5, sub) :- !.
decomp(0x6, mult) :- !.
decomp(0x7, div) :- !.
decomp(0x8, mod) :- !.
decomp(0x9, and) :- !.
decomp(0xA, or) :- !.
decomp(0xB, not) :- !.
decomp(0x10, jump) :- !.
decomp(0x11, jz) :- !.
decomp(0x12, jgtz) :- !.
decomp(0xC, equal) :- !.
decomp(0xD, lt) :- !.
decomp(0xE, leq) :- !.
decomp(X, X).
% vm(_, (S, M), _) --> get_head(H), { decompile(H, [Val|_]), maplist(simplify, [Val, S, M], Text), format('~w ~21| ~20w ~60| ~w\n', Text), fail }.
% load_int(X) 0x1 load(X) 0x2 store(X) 0x3 add 0x4 sub 0x5 mult 0x6 div 0x7 mod 0x8 and 0x9 or 0xA not 0xB jump(LabelOffset) 0x10 jz(LabelOffset) 0x11 jgtz(LabelOffset) 0x12 equal 0xC lt 0xDleq 0xE
:- dynamic(jump_table/1).
% load_int(X) - load X on stack
vm((S, M), Out) --> [0x1, B1, B2, B3, B4], { encode_int(X, [B1, B2, B3, B4]) }, !, vm(([X|S], M), Out).
% load(X) - load variable X's value on stack
vm((S, M), Out) --> [0x2, B1, B2, B3, B4], { encode_int(X, [B1, B2, B3, B4]) }, !, { lookup(X, M, V) }, vm(([V|S], M), Out).
% store(X) - pop value from stack and store it in variable X
vm(([V|S], M), Out) --> [0x3, B1, B2, B3, B4], { encode_int(X, [B1, B2, B3, B4]) }, !, { assign(X, V, M, M1) }, vm((S, M1), Out).
% add, sub, mult, div, mod - pop top values from stack, perform proper operation and put result on stack
vm(([Arg1, Arg2|S], M), Out) --> [0x4], !, { Ret is Arg1 + Arg2 }, vm(([Ret|S], M), Out).
vm(([Arg1, Arg2|S], M), Out) --> [0x5], !, { Ret is Arg1 - Arg2 }, vm(([Ret|S], M), Out).
vm(([Arg1, Arg2|S], M), Out) --> [0x6], !, { Ret is Arg1 * Arg2 }, vm(([Ret|S], M), Out).
vm(([Arg1, Arg2|S], M), Out) --> [0x7], !, { Ret is Arg1 div Arg2 }, vm(([Ret|S], M), Out).
vm(([Arg1, Arg2|S], M), Out) --> [0x8], !, { Ret is Arg1 mod Arg2 }, vm(([Ret|S], M), Out).
% and, or - pop two values from stack, perform proper operation and put result on stack
vm(([1, 1|S], M), Out) --> [0x9], !, vm(([1|S], M), Out).
vm(([_, _|S], M), Out) --> [0x9], !, vm(([0|S], M), Out).
vm(([0, 0|S], M), Out) --> [0xA], !, vm(([0|S], M), Out).
vm(([_, _|S], M), Out) --> [0xA], !, vm(([1|S], M), Out).
% not - pop top value from stack and put negated on stack
vm(([1|S], M), Out) --> [0xB], !, vm(([0|S], M), Out).
vm(([0|S], M), Out) --> [0xB], !, vm(([1|S], M), Out).
% jump(label) - jump to given label
vm(In, Out) --> [0x10, B1, B2, B3, B4], { encode_int(Offset, [B1, B2, B3, B4]) }, !, { jump_table(Inits), arg(Offset, Inits, Bytecode), vm(In, Out, Bytecode, _) }.
% jz(label) - pop value from stack and if it was zero jump to given label
vm(([0|S], M), Out) --> [0x11, B1, B2, B3, B4], { encode_int(Offset, [B1, B2, B3, B4]) }, !, { jump_table(Inits), arg(Offset, Inits, Bytecode), vm((S, M), Out, Bytecode, _) }.
vm(([_|S], M), Out) --> [0x11, B1, B2, B3, B4], { encode_int(_, [B1, B2, B3, B4]) }, !, vm((S, M), Out).
% jgtz(label) - pop value from stack and if it was greater or equal zero jump to given label
vm(([V|S], M), Out) --> [0x12, B1, B2, B3, B4], { encode_int(Offset, [B1, B2, B3, B4]) }, { V >= 0}, !, { jump_table(Inits), arg(Offset, Inits, Bytecode), vm((S, M), Out, Bytecode, _) }.
vm(([_|S], M), Out) --> [0x12, B1, B2, B3, B4], { encode_int(_, [B1, B2, B3, B4]) }, !, vm((S, M), Out).
% equal - pop two values from stack and push 1 if values were equal (otherwise 0)
vm(([X, X|S], M), Out) --> [0xC], !, vm(([1|S], M), Out).
vm(([_, _|S], M), Out) --> [0xC], !, vm(([0|S], M), Out).
% lt - pop two values from stack and push 1 if top was less than second (otherwise 0)
vm(([X, Y|S], M), Out) --> [0xD], { X < Y }, !, vm(([1|S], M), Out).
vm(([_, _|S], M), Out) --> [0xD], !, vm(([0|S], M), Out).
% leq - pop two values from stack and push 1 if top was less than or eqaul to second (otherwise 0)
vm(([X, Y|S], M), Out) --> [0xE], { X =< Y }, !, vm(([1|S], M), Out).
vm(([_, _|S], M), Out) --> [0xE], !, vm(([0|S], M), Out).
vm(Memory, Memory) --> [].
% prefixes([X|Xs], [[X|Xs]|Prefixes]) :-
% prefixes(Xs, Prefixes).
% prefixes([], [[]]).
make_jump_table(Xs, JumpMapping, Inits) :-
make_jump_table(0, Xs, JumpMapping, Inits).
make_jump_table(N, [X|Xs], [N|JM], [[X|Xs]|Inits]) :-
!,
N1 is N + 1,
make_jump_table(N1, Xs, JM, Inits).
make_jump_table(N, [_|Xs], JM, Inits) :-
!,
N1 is N + 1,
make_jump_table(N1, Xs, JM, Inits).
make_jump_table(N, [], [N], [[]]) :- !.
make_jump_table(_, _, [], []).
run((Bytecode, JumpMapping), (S, M)) :-
make_jump_table(Bytecode, JumpMapping, Inits),
Faster =.. [array|Inits],
asserta(jump_table(Faster)),
!,
phrase(vm(([], []), (S, M)), Bytecode, _),
retract(jump_table(Faster)).
applyVMVarNames([], [], []).
applyVMVarNames([(Idx, Value)|Idxs], [Name|Names], [(Name, Value)|Tail]) :-
applyVMVarNames(Idxs, Names, Tail).