-
Notifications
You must be signed in to change notification settings - Fork 0
/
parameter.py
155 lines (125 loc) · 4.76 KB
/
parameter.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
149
150
151
152
153
154
# (c) 2023 Hermann Paul von Borries
# MIT License
import builtins
# Verify what happens when a viper int is passed to a function
def some_function(s,x):
print(f"{s}: {x} 0x{x:.08x}")
return x
@micropython.viper
def viperfun():
x = 1
ret = some_function("viper int 1=", x)
assert ret == builtins.int(1)
y = uint(0xffffffff)
ret = some_function("viper uint 0xffffffff",y)
assert ret == builtins.int(0xffffffff)
z = int(-1)
ret = some_function("viper int -1=", z)
assert ret == builtins.int(-1)
ba = bytearray(10)
pba = ptr8(ba)
print("the pointer address is", uint(pba))
some_function("viper ptr8=", pba)
pmem = ptr8(0xffffffff)
ret = some_function("viper ptr8 to 0xffffffff", pmem)
assert ret == builtins.int(0xffffffff)
#print(f"{isinstance(pmem,int)}")
#NotImplementedError: conversion to object
# f gets converted to a builtins.int before isinstance does it's stuff
f = 0
assert isinstance(f, builtins.int)
# int gets converted to builtins.int before type() does it's stuff
#viper_type = type(int)
#assert viper_type == builtins.int
# a number with with nine hexadecimal "f" will be passed as builtins.int
ret = some_function("passing number > 4 bytes", 0xfffffffff)
print(f"passing number > 4 bytes return value: {ret} == {ret:08x}")
assert ret == builtins.int(0xfffffffff )
viperfun()
# Now call a viper function from a non-viper to verify the parameters are cast
# using int() or uint()
@micropython.viper
def viper_fun_int(s, x:int )->int:
print(s, f"check parameter cast int: argument {x} == {x:08x}")
return x
@micropython.viper
def viper_fun_uint(s, x:uint )->uint:
print(s, f"check parameter cast uint: argument {x} == {x:08x}")
return x
def check_parameter_cast():
# uint and int function produce the same result for positive numbers
for fun in (viper_fun_int, viper_fun_uint):
ret = fun("1", 1)
assert ret == 1
# Check maximum small int
ret = fun("0x3fffffff",0x3fffffff)
assert ret == 0x3fffffff
# Check maximum signed int
ret = fun("0x7fffffff", 0x7fffffff)
assert ret == 0x7fffffff
ret = fun("0xff7a55bb33", 0xff7a55bb33)
assert ret == 0x7a55bb33 # truncated to 4 bytes, but by chance positive
assert ret > 0
# Check with just 4 bytes of f
ret = viper_fun_int("0xffffffff", 0xffffffff)
print(f"0xffffffff return value {ret} == {ret:08x}")
assert ret == -1 # truncated to 4 bytes
# Check with just 4 bytes of f
ret = viper_fun_uint("0xffffffff", 0xffffffff)
print(f"0xffffffff return value {ret} == {ret:08x}")
assert ret == 0xffffffff # truncated to 4 bytes
# Check with number > 4 bytes
ret = viper_fun_int("0xffffffffff", 0xffffffffff)
print(f"0xffffffffff return value {ret} == {ret:08x}")
assert ret == -1 # truncated to 4 bytes
# Check with number > 4 bytes. Here uint is different than int
ret = viper_fun_uint("0xffffffffff", 0xffffffffff)
print(f"0xffffffffff return value {ret} == {ret:08x}")
assert ret == 0xffffffff # truncated to 4 bytes
check_parameter_cast()
# viper int does not convert string to int, unlike builtins.int
try:
viperfun("123")
except TypeError:
print("OK: can't cast string to viper int in a parameter")
print("test return object")
@micropython.viper
def function_returns_object(x)->object:
return x
h = function_returns_object("a string")
print("function_returns_object returns", h)
assert isinstance(h,str)
h = function_returns_object((1,2,3))
print("function_returns_object returns", h)
assert isinstance(h,tuple)
h = function_returns_object([1,2,3])
print("function_returns_object returns", h)
assert isinstance(h,list)
# See if return hint needed if function returns non-viper object
@micropython.viper
def function_returns_no_type(x):
return x
h = function_returns_no_type("a string")
print("function_returns_no_type returns", h)
assert isinstance(h,str)
h = function_returns_no_type((1,2,3))
print("function_returns_no_type returns", h)
assert isinstance(h,tuple)
h = function_returns_no_type([1,2,3])
print("function_returns_no_type returns", h)
assert isinstance(h,list)
# Any cannot be used
#from types import Any
#@micropython.viper
#def function_returns_any(x)->Any: # <-- will fail with ViperTypeError: unknown type 'Any'
# return x
@micropython.viper
def function_a(y)->int:
return int(function_b(y)) # <-- must cast, MP does not know what this returns
@micropython.viper
def function_b(x:int)->int:
return x+1
assert function_a(1) == 2
# the argument gets converted to a viper int somewhere in between
# So adding 1 to a positive number wraps around
assert function_a(0x7fffffff) < 0