Pārlūkot izejas kodu

...

...

...

...

...

...

...

...

...
blueloveTH 1 gadu atpakaļ
vecāks
revīzija
9ecfc0196f

+ 9 - 1
.github/workflows/main.yml

@@ -92,10 +92,18 @@ jobs:
         uses: jirutka/setup-alpine@v1
         with:
           arch: x86
-          packages: gcc g++ make cmake libc-dev linux-headers python3
+          packages: gcc g++ make cmake libc-dev linux-headers python3 gdb
       - name: Build and Test
         run: |
           uname -m
+
+          python cmake_build.py Debug
+          # gdb_commands.txt
+          echo "run" > gdb_commands.txt
+          echo "backtrace" >> gdb_commands.txt
+          echo "quit" >> gdb_commands.txt
+          gdb -batch -x gdb_commands.txt --args ./main tests/77_builtin_func_1.py
+
           python cmake_build.py
           python scripts/run_tests.py
           python scripts/run_tests.py benchmark

+ 5 - 2
scripts/run_tests.py

@@ -8,9 +8,12 @@ def test_file(filepath, cpython=False):
     if cpython:
         return os.system("python " + filepath) == 0
     if sys.platform == 'win32':
-        return os.system("main.exe " + filepath) == 0
+        code = os.system("main.exe " + filepath)
     else:
-        return os.system("./main " + filepath) == 0
+        code = os.system("./main " + filepath)
+    if code != 0:
+        print('Return code:', code)
+    return code == 0
 
 def test_dir(path):
     print("Testing directory:", path)

+ 4 - 0
src/interpreter/ceval.c

@@ -90,6 +90,10 @@ FrameResult VM__run_top_frame(VM* self) {
             py_exception(tp_RecursionError, "maximum recursion depth exceeded");
             goto __ERROR;
         }
+        if(self->stack.sp >= self->stack.end) {
+            c11__abort(
+                "Stack overflow! Please increase PK_VM_STACK_SIZE or reduce the max recursion limit.");
+        }
 
         codes = frame->co->codes.data;
         frame->ip++;

+ 17 - 301
tests/77_builtin_func.py → tests/77_builtin_func_1.py

@@ -57,14 +57,14 @@ class TestSuperNoBaseMethod(TestSuperBase):
 try:
     t = TestSuperNoParent()
     print('未能拦截错误')
-    exit(1)
+    exit(2)
 except:
     pass
 
 try:
     t = TestSuperNoBaseMethod()
     print('未能拦截错误')
-    exit(1)
+    exit(3)
 except:
     pass
 
@@ -83,7 +83,7 @@ try:
     c = C()
     c.method()
     print('未能拦截错误')
-    exit(1)
+    exit(4)
 except:
     pass
 
@@ -91,7 +91,7 @@ try:
     d = D()
     d.method()
     print('未能拦截错误')
-    exit(1)
+    exit(5)
 except:
     pass
 
@@ -134,14 +134,14 @@ assert type(hash(a)) is int
 try:
     hash({1:1})
     print('未能拦截错误')
-    exit(1)
+    exit(6)
 except:
     pass
 
 try:
     hash([1])
     print('未能拦截错误')
-    exit(1)
+    exit(7)
 except:
     pass
 
@@ -166,7 +166,7 @@ repr(A())
 try:
     range(1,2,3,4)
     print('未能拦截错误, 在测试 range')
-    exit(1)
+    exit(8)
 except:
     pass
 
@@ -174,14 +174,14 @@ except:
 try:
     int('asad')
     print('未能拦截错误, 在测试 int')
-    exit(1)
+    exit(9)
 except:
     pass
 
 try:
     int(123, 16)
     print('未能拦截错误, 在测试 int')
-    exit(1)
+    exit(10)
 except:
     pass
 
@@ -192,14 +192,14 @@ assert type(11%2) is int
 try:
     float('asad')
     print('未能拦截错误, 在测试 float')
-    exit(1)
+    exit(11)
 except:
     pass
 
 try:
     float([])
     print('未能拦截错误, 在测试 float')
-    exit(1)
+    exit(12)
 except:
     pass
 
@@ -213,7 +213,7 @@ assert type('25363546'.index('63')) is int
 try:
     '25363546'.index('err')
     print('未能拦截错误, 在测试 str.index')
-    exit(1)
+    exit(13)
 except:
     pass
 
@@ -228,7 +228,7 @@ assert '25363546'.find('err') == -1
 try:
     list(1,2)
     print('未能拦截错误, 在测试 list')
-    exit(1)
+    exit(14)
 except:
     pass
 
@@ -238,7 +238,7 @@ assert type([1,2,3,4,5].index(4)) is int
 try:
     [1,2,3,4,5].index(6)
     print('未能拦截错误, 在测试 list.index')
-    exit(1)
+    exit(15)
 except:
     pass
 
@@ -249,7 +249,7 @@ except:
 try:
     [1,2,3,4,5].remove(6)
     print('未能拦截错误, 在测试 list.remove')
-    exit(1)
+    exit(16)
 except:
     pass
 
@@ -259,7 +259,7 @@ except:
 try:
     [1,2,3,4,5].pop(1,2,3,4)
     print('未能拦截错误, 在测试 list.pop')
-    exit(1)
+    exit(17)
 except:
     pass
 
@@ -275,7 +275,7 @@ assert type(12 * [12]) is list
 try:
     tuple(1,2)
     print('未能拦截错误, 在测试 tuple')
-    exit(1)
+    exit(18)
 except:
     pass
 
@@ -305,287 +305,3 @@ assert type(repr(bytes([0x41, 0x42, 0x43]))) is str
 
 # /************ slice ************/
 assert type(slice(0.1, 0.2, 0.3)) is slice
-
-
-# 未完全测试准确性-----------------------------------------------
-#       116: 1529:    bind_property(_t(tp_slice), "start", [](VM* vm, ArgsView args){
-#     #####: 1530:        return CAST(Slice&, args[0]).start;
-#         -: 1531:    });
-#       116: 1532:    bind_property(_t(tp_slice), "stop", [](VM* vm, ArgsView args){
-#     #####: 1533:        return CAST(Slice&, args[0]).stop;
-#         -: 1534:    });
-#       116: 1535:    bind_property(_t(tp_slice), "step", [](VM* vm, ArgsView args){
-#     #####: 1536:        return CAST(Slice&, args[0]).step;
-#         -: 1537:    });
-s = slice(1, 2, 3)
-assert type(s) is slice
-assert s.start == 1
-assert s.stop == 2
-assert s.step == 3
-
-# 未完全测试准确性-----------------------------------------------
-# test slice.__repr__
-assert type(repr(slice(1,1,1))) is str
-
-# /************ namedict ************/
-# # test namedict.keys:
-# class A():
-#     def __init__(self):
-#         self.a = 10
-#     def method(self):
-#         pass
-
-
-# my_namedict = A().__dict__
-# assert type(my_namedict.keys()) is list
-
-# # test namedict.values:
-# class A():
-#     def __init__(self):
-#         self.a = 10
-#     def method(self):
-#         pass
-
-
-# my_namedict = A().__dict__
-# assert type(my_namedict.values()) is list
-
-
-# class A():
-#     def __init__(self):
-#         self.a = 10
-#     def method(self):
-#         pass
-
-
-# my_namedict = A().__dict__
-# assert type(len(my_namedict)) is int
-
-
-class A():
-    def __init__(self):
-        self.a = 10
-    def method(self):
-        pass
-
-
-my_namedict = A().__dict__
-
-try:
-    hash(my_namedict)
-    print('未能拦截错误, 在测试 namedict.__hash__')
-    exit(1)
-except TypeError:
-    pass
-
-a = hash(object())  # object is hashable
-a = hash(A())       # A is hashable
-class B:
-    def __eq__(self, o): return True
-    def __ne__(self, o): return False
-
-try:
-    hash(B())
-    print('未能拦截错误, 在测试 B.__hash__')
-    exit(1)
-except TypeError:
-    pass
-
-# 未完全测试准确性-----------------------------------------------
-# test namedict.__repr__:
-class A():
-    def __init__(self):
-        self.a = 10
-    def method(self):
-        pass
-
-
-my_namedict = A().__dict__
-assert type(repr(my_namedict)) is str
-
-
-# /************ dict ************/
-# 未完全测试准确性-----------------------------------------------
-# test dict:
-assert type(dict([(1,2)])) is dict
-
-try:
-    dict([(1, 2, 3)])
-    print('未能拦截错误, 在测试 dict')
-    exit(1)
-except:
-    pass
-
-try:
-    dict([(1, 2)], 1)
-    print('未能拦截错误, 在测试 dict')
-    exit(1)
-except:
-    pass
-
-try:
-    hash(dict([(1,2)]))
-    print('未能拦截错误, 在测试 dict.__hash__')
-    exit(1)
-except:
-    pass
-
-# test dict.__iter__
-for k in {1:2, 2:3, 3:4}.keys():
-    assert k in [1,2,3]
-
-# 未完全测试准确性-----------------------------------------------
-# test dict.get
-
-assert {1:2, 3:4}.get(1) == 2
-assert {1:2, 3:4}.get(2) is None
-assert {1:2, 3:4}.get(20, 100) == 100
-
-try:
-    {1:2, 3:4}.get(1,1, 1)
-    print('未能拦截错误, 在测试 dict.get')
-    exit(1)
-except:
-    pass
-
-# 未完全测试准确性-----------------------------------------------
-# test dict.__repr__
-assert type(repr({1:2, 3:4})) is str
-
-# /************ property ************/
-class A():
-    def __init__(self):
-        self._name = '123'
-
-    @property
-    def value(self):
-        return 2
-
-    def get_name(self):
-        '''
-        doc string 1
-        '''
-        return self._name
-
-    def set_name(self, val):
-        '''
-        doc string 2
-        '''
-        self._name = val
-
-assert A().value == 2
-
-A.name = property(A.get_name, A.set_name)
-
-class Vector2:
-    def __init__(self) -> None:
-        self._x = 0
-
-    @property
-    def x(self):
-        return self._x
-    
-    @x.setter
-    def x(self, val):
-        self._x = val
-
-v = Vector2()
-assert v.x == 0
-v.x = 10
-assert v.x == 10
-
-# function.__doc__
-def aaa():
-    '12345'
-    pass
-assert aaa.__doc__ == '12345'
-
-# test callable
-assert callable(lambda: 1) is True          # function
-assert callable(1) is False                 # int
-assert callable(object) is True             # type
-assert callable(object()) is False
-assert callable([].append) is True      # bound method
-assert callable([].__getitem__) is True # bound method
-
-class A:
-    def __init__(self):
-        pass
-
-    def __call__(self):
-        pass
-
-assert callable(A) is True      # type
-assert callable(A()) is True    # instance with __call__
-assert callable(A.__call__) is True  # bound method
-assert callable(A.__init__) is True  # bound method
-assert callable(print) is True  # builtin function
-assert callable(isinstance) is True  # builtin function
-
-
-assert id(0) is None
-assert id(2**62) is None
-
-# test issubclass
-assert issubclass(int, int) is True
-assert issubclass(int, object) is True
-assert issubclass(object, int) is False
-assert issubclass(object, object) is True
-assert issubclass(int, type) is False
-assert issubclass(type, type) is True
-assert issubclass(float, int) is False
-
-
-def f(a, b):
-    c = a
-    del a
-    return sum([b, c])
-
-assert f(1, 2) == 3
-
-# /************ module time ************/
-import time
-# test time.time
-assert type(time.time()) is float
-
-local_t = time.localtime()
-assert type(local_t.tm_year) is int
-assert type(local_t.tm_mon) is int
-assert type(local_t.tm_mday) is int
-assert type(local_t.tm_hour) is int
-assert type(local_t.tm_min) is int
-assert type(local_t.tm_sec) is int
-assert type(local_t.tm_wday) is int
-assert type(local_t.tm_yday) is int
-assert type(local_t.tm_isdst) is int
-
-# test time.sleep
-time.sleep(0.1)
-# test time.localtime
-assert type(time.localtime()) is time.struct_time
-
-# test min/max
-assert min(1, 2) == 1
-assert min(1, 2, 3) == 1
-assert min([1, 2]) == 1
-assert min([1, 2], key=lambda x: -x) == 2
-
-assert max(1, 2) == 2
-assert max(1, 2, 3) == 3
-assert max([1, 2]) == 2
-assert max([1, 2, 3], key=lambda x: -x) == 1
-
-assert min([
-    (3, 1),
-    (1, 2),
-    (1, 3),
-    (1, 4),
-]) == (1, 2)
-
-assert min(1, 2) == 1
-assert max(1, 2) == 2
-
-exit()
-
-dir_int = dir(int)
-assert dir_int[:4] == ['__add__', '__and__', '__base__', '__eq__']

+ 243 - 0
tests/77_builtin_func_2.py

@@ -0,0 +1,243 @@
+# 未完全测试准确性-----------------------------------------------
+#       116: 1529:    bind_property(_t(tp_slice), "start", [](VM* vm, ArgsView args){
+#     #####: 1530:        return CAST(Slice&, args[0]).start;
+#         -: 1531:    });
+#       116: 1532:    bind_property(_t(tp_slice), "stop", [](VM* vm, ArgsView args){
+#     #####: 1533:        return CAST(Slice&, args[0]).stop;
+#         -: 1534:    });
+#       116: 1535:    bind_property(_t(tp_slice), "step", [](VM* vm, ArgsView args){
+#     #####: 1536:        return CAST(Slice&, args[0]).step;
+#         -: 1537:    });
+s = slice(1, 2, 3)
+assert type(s) is slice
+assert s.start == 1
+assert s.stop == 2
+assert s.step == 3
+
+# 未完全测试准确性-----------------------------------------------
+# test slice.__repr__
+assert type(repr(slice(1,1,1))) is str
+
+
+class A():
+    def __init__(self):
+        self.a = 10
+    def method(self):
+        pass
+
+
+my_namedict = A().__dict__
+
+try:
+    hash(my_namedict)
+    print('未能拦截错误, 在测试 namedict.__hash__')
+    exit(1)
+except TypeError:
+    pass
+
+a = hash(object())  # object is hashable
+a = hash(A())       # A is hashable
+class B:
+    def __eq__(self, o): return True
+    def __ne__(self, o): return False
+
+try:
+    hash(B())
+    print('未能拦截错误, 在测试 B.__hash__')
+    exit(1)
+except TypeError:
+    pass
+
+# 未完全测试准确性-----------------------------------------------
+# test namedict.__repr__:
+class A():
+    def __init__(self):
+        self.a = 10
+    def method(self):
+        pass
+
+
+my_namedict = A().__dict__
+assert type(repr(my_namedict)) is str
+
+
+# /************ dict ************/
+# 未完全测试准确性-----------------------------------------------
+# test dict:
+assert type(dict([(1,2)])) is dict
+
+try:
+    dict([(1, 2, 3)])
+    print('未能拦截错误, 在测试 dict')
+    exit(1)
+except:
+    pass
+
+try:
+    dict([(1, 2)], 1)
+    print('未能拦截错误, 在测试 dict')
+    exit(1)
+except:
+    pass
+
+try:
+    hash(dict([(1,2)]))
+    print('未能拦截错误, 在测试 dict.__hash__')
+    exit(1)
+except:
+    pass
+
+# test dict.__iter__
+for k in {1:2, 2:3, 3:4}.keys():
+    assert k in [1,2,3]
+
+# 未完全测试准确性-----------------------------------------------
+# test dict.get
+
+assert {1:2, 3:4}.get(1) == 2
+assert {1:2, 3:4}.get(2) is None
+assert {1:2, 3:4}.get(20, 100) == 100
+
+try:
+    {1:2, 3:4}.get(1,1, 1)
+    print('未能拦截错误, 在测试 dict.get')
+    exit(1)
+except:
+    pass
+
+# 未完全测试准确性-----------------------------------------------
+# test dict.__repr__
+assert type(repr({1:2, 3:4})) is str
+
+# /************ property ************/
+class A():
+    def __init__(self):
+        self._name = '123'
+
+    @property
+    def value(self):
+        return 2
+
+    def get_name(self):
+        '''
+        doc string 1
+        '''
+        return self._name
+
+    def set_name(self, val):
+        '''
+        doc string 2
+        '''
+        self._name = val
+
+assert A().value == 2
+
+A.name = property(A.get_name, A.set_name)
+
+class Vector2:
+    def __init__(self) -> None:
+        self._x = 0
+
+    @property
+    def x(self):
+        return self._x
+    
+    @x.setter
+    def x(self, val):
+        self._x = val
+
+v = Vector2()
+assert v.x == 0
+v.x = 10
+assert v.x == 10
+
+# function.__doc__
+def aaa():
+    '12345'
+    pass
+assert aaa.__doc__ == '12345'
+
+# test callable
+assert callable(lambda: 1) is True          # function
+assert callable(1) is False                 # int
+assert callable(object) is True             # type
+assert callable(object()) is False
+assert callable([].append) is True      # bound method
+assert callable([].__getitem__) is True # bound method
+
+class A:
+    def __init__(self):
+        pass
+
+    def __call__(self):
+        pass
+
+assert callable(A) is True      # type
+assert callable(A()) is True    # instance with __call__
+assert callable(A.__call__) is True  # bound method
+assert callable(A.__init__) is True  # bound method
+assert callable(print) is True  # builtin function
+assert callable(isinstance) is True  # builtin function
+
+
+assert id(0) is None
+assert id(2**62) is None
+
+# test issubclass
+assert issubclass(int, int) is True
+assert issubclass(int, object) is True
+assert issubclass(object, int) is False
+assert issubclass(object, object) is True
+assert issubclass(int, type) is False
+assert issubclass(type, type) is True
+assert issubclass(float, int) is False
+
+
+def f(a, b):
+    c = a
+    del a
+    return sum([b, c])
+
+assert f(1, 2) == 3
+
+# /************ module time ************/
+import time
+# test time.time
+assert type(time.time()) is float
+
+local_t = time.localtime()
+assert type(local_t.tm_year) is int
+assert type(local_t.tm_mon) is int
+assert type(local_t.tm_mday) is int
+assert type(local_t.tm_hour) is int
+assert type(local_t.tm_min) is int
+assert type(local_t.tm_sec) is int
+assert type(local_t.tm_wday) is int
+assert type(local_t.tm_yday) is int
+assert type(local_t.tm_isdst) is int
+
+# test time.sleep
+time.sleep(0.1)
+# test time.localtime
+assert type(time.localtime()) is time.struct_time
+
+# test min/max
+assert min(1, 2) == 1
+assert min(1, 2, 3) == 1
+assert min([1, 2]) == 1
+assert min([1, 2], key=lambda x: -x) == 2
+
+assert max(1, 2) == 2
+assert max(1, 2, 3) == 3
+assert max([1, 2]) == 2
+assert max([1, 2, 3], key=lambda x: -x) == 1
+
+assert min([
+    (3, 1),
+    (1, 2),
+    (1, 3),
+    (1, 4),
+]) == (1, 2)
+
+assert min(1, 2) == 1
+assert max(1, 2) == 2