forked from APrioriInvestments/typed_python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbytes_wrapper.py
More file actions
102 lines (82 loc) · 3.71 KB
/
Copy pathbytes_wrapper.py
File metadata and controls
102 lines (82 loc) · 3.71 KB
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
# Copyright 2018 Braxton Mckee
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from nativepython.type_wrappers.refcounted_wrapper import RefcountedWrapper
import nativepython.type_wrappers.runtime_functions as runtime_functions
from typed_python import Bytes
import nativepython.native_ast as native_ast
import nativepython
from nativepython.native_ast import VoidPtr
typeWrapper = lambda t: nativepython.python_object_representation.typedPythonTypeToTypeWrapper(t)
class BytesWrapper(RefcountedWrapper):
is_pod = False
is_empty = False
is_pass_by_ref = True
def __init__(self):
super().__init__(Bytes)
self.layoutType = native_ast.Type.Struct(element_types=(
('refcount', native_ast.Int64),
('data', native_ast.UInt8)
), name='StringLayout').pointer()
def getNativeLayoutType(self):
return self.layoutType
def on_refcount_zero(self, context, instance):
assert instance.isReference
return runtime_functions.free.call(instance.nonref_expr.cast(native_ast.UInt8Ptr))
def convert_bin_op(self, context, left, op, right):
if right.expr_type == left.expr_type:
if op.matches.Add:
return context.push(
bytes,
lambda bytesRef: bytesRef.expr.store(
runtime_functions.bytes_concat.call(
left.nonref_expr.cast(VoidPtr),
right.nonref_expr.cast(VoidPtr)
).cast(self.layoutType)
)
)
return super().convert_bin_op(context, left, op, right)
def convert_getitem(self, context, expr, item):
item = item.toInt64()
len_expr = self.convert_len(context, expr)
with context.ifelse((item.nonref_expr.lt(len_expr.nonref_expr.negate())).bitor(item.nonref_expr.gte(len_expr.nonref_expr))) as (true, false):
with true:
context.pushException(IndexError, "index out of range")
return context.pushPod(
int,
expr.nonref_expr.ElementPtrIntegers(0, 1).elemPtr(
native_ast.Expression.Branch(
cond=item.nonref_expr.lt(native_ast.const_int_expr(0)),
false=item.nonref_expr,
true=item.nonref_expr.add(len_expr.nonref_expr)
).add(native_ast.const_int_expr(8))
).load().cast(native_ast.Int64)
)
def convert_len_native(self, expr):
return native_ast.Expression.Branch(
cond=expr,
false=native_ast.const_int_expr(0),
true=expr.ElementPtrIntegers(0, 1).ElementPtrIntegers(4).cast(native_ast.Int32.pointer()).load().cast(native_ast.Int64)
)
def convert_len(self, context, expr):
return context.pushPod(int, self.convert_len_native(expr.nonref_expr))
def constant(self, context, s):
return context.push(
bytes,
lambda bytesRef: bytesRef.expr.store(
runtime_functions.bytes_from_ptr_and_len.call(
native_ast.const_bytes_cstr(s),
native_ast.const_int_expr(len(s))
).cast(self.layoutType)
)
)