-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmachine.py
148 lines (146 loc) · 5.2 KB
/
machine.py
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#coding=utf-8
from opcode import cmp_op
from TVar import *
class CheckError(Exception): pass
def error(msg):
raise CheckError(msg)
class Stack(object):
def __init__(self,ltenv,gtenv,ctenv,size=256):
self.s = [ None ] * size
self.top = 0
self.local_tenv = ltenv
self.global_tenv = gtenv
self.const_tenv = ctenv
def push(self,val):
self.s[self.top] = val
self.top += 1
return self.top
def pop(self): # RETURN_VALUE = POP
self.top -= 1
val = self.s[self.top]
self.s[self.top] = None
return val
def push_const(self,args):
val = self.const_tenv[args]
return self.push(val)
def push_fast(self,args): # LOAD_XXX = PUSH typ-val
val = self.local_tenv[args]
#print( 'load-fast:',val,self.s[0:10])
return self.push(val)
def store_fast(self,args):
val = self.pop ( )
self.local_tenv[args] = val
#print( 's_fast:',val,self.local_tenv)
return
def push_global(self,args):
val = self.global_tenv[args]
return self.push(val)
def store_global(self,args):
val = self.pop ( )
self.global_tenv[args] = val
return
def binop(self,name):
right_val = self.pop ()
left_val = self.pop ()
#print( 'binop:',left_val,right_val,self.s[0:10])
if left_val == right_val:
return self.push(left_val)
else:
error( "for {} type(s): {} and {}".format(name,repr(left_val),repr(right_val) ) )
def cmpop(self,args):
right_val = self.pop ()
left_val = self.pop ()
#print( 'binop:',left_val,right_val,self.s[0:10])
if left_val == right_val:
return self.push(bool)#self.push(left_val)
else:
error( "for {} type(s): {} and {}".format(cmp_op[args],repr(left_val),repr(right_val) ) )
def tup(self,args):
lst = list(reversed( [self.pop () for i in range(args)] ))
if lst == [ ]:
return self.push( Unit )
val = Tuple( *lst)
return self.push (val)
def lst(self,args):
val = list( reversed( [self.pop () for i in range(args)] ) )
if val == [ ]:
return self.push( List(Any) )
flag = val.pop()
for v in val:
if v != flag:
error( "for {} type(s): {} and {}".format("["+flag+"]",v,flag))
return self.push ( List(flag) )
def slice(self,args):
end = self.pop ()
start = self.pop ()
if (end == Unit or end == Int) and ( start == Int or start == Unit ):
return self.push( [Int] )
else:
error("for slice type(s): slice({},{})".format(start,end) )
def sub_scr(self,args):
index = self.pop ()
lst = self.pop ()
if isinstance(lst,List) or ( isinstance(lst,list) and len(lst) == 1):
if index == Int :
if isinstance(lst,List):
typ = lst.tvar[0]
else:
typ = lst[0]
return self.push(typ)
elif index == [Int]:
typ = List(Int)
return self.push(typ)
else:
error("for subscr type(s): {} and {}".format(Int,index) )
else:
error("for subscr type(s): {} and {}".format(lst,List) )
def If(self):
else_val = self.pop ()
then_val = self.pop ()
test = self.pop ()
#print( 'if:',test,then_val,else_val)
if then_val == else_val:
return self.push(then_val)
else:
error( "for if type(s): {} and {}".format(repr(then_val),repr(else_val)) )
def For(self):
iter_val = self.pop ()
#print( "iter_val:",iter_val,self.s[:10] )
if isinstance(iter_val,List) or ( isinstance(iter_val,list) and len(iter_val) == 1):
if isinstance(iter_val,List):
t_val = iter_val.tvar[0]
else:
t_val = iter_val[0]
top = self.push( t_val )
#print( "iter_val:",iter_val,self.s[:10] )
return top
else:
error("for iter type(s): {} and {}".format(iter_val,List) )
def call(self,args):
arglist = [i for i in reversed( [ self.pop () for z in range(args) ] ) ]
functyp = self.pop () # TVar TO
def arp(to,acc):
if not isinstance(to,To):
return acc + [to]
return arp(to.b,acc + [to.a] )
lst = arp(functyp,[ ])
ret = lst.pop()
#print( "arglist:",arglist,"functyp:",functyp , lst )
if len(arglist) != len(lst):
error("call function argcount type(s): {} and {}".format(len(arglist),len(lst)) )
for a,t in zip(arglist,lst):
#print( a,t ,a == t )
if a != t:
error("call function type(s): {} and {}".format(arglist,lst))
return self.push(ret)
def ret(self):
val = self.pop ()
typ = self.global_tenv["return"]
if val == typ:
return self.push(val)
else:
error( "for return type(s): {} and {}".format(repr(typ),repr(val) ) )
@property
def peek(self):
return self.s[self.top - 1]
__all__ = ["Stack"]