Skip to content

Commit 4f5e936

Browse files
committed
Weak continued.
1 parent 9f69cce commit 4f5e936

File tree

13 files changed

+167
-40
lines changed

13 files changed

+167
-40
lines changed

.pylintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ disable=print-statement,
168168
redefined-outer-name,
169169
unspecified-encoding,
170170
unsubscriptable-object,
171-
wrong-import-position
171+
wrong-import-position,
172+
too-many-branches
172173

173174
# Enable the message, report, category or checker with the given id(s). You can
174175
# either give multiple identifier separated by comma (,) or put this option

docs/language-reference/types.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ See also :ref:`dict-comprehensions`.
324324
|(self, other: {TK: TV}) # Create a dict of self and other.
325325
get(self, # Get value for key. Return default
326326
key: TK, # if missing. Inserts default if missing
327-
default: TV = None, # and insert is True
327+
default: TV? = None, # and insert is True
328328
insert: bool = False) -> TV?
329329
__in__(self, key: TK) -> bool # Contains given key.
330330

mys/lib/mys/memory.hpp

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,21 @@ class shared_ptr final
8080
void decrement()
8181
{
8282
INCREMENT_NUMBER_OF_OBJECT_DECREMENTS;
83-
count() -= 1;
8483

8584
if (object_count() > 0) {
8685
object_count() -= 1;
8786

8887
if (object_count() == 0) {
8988
std::destroy_at(get());
90-
DECREMENT_NUMBER_OF_ALLOCATED_OBJECTS;
91-
INCREMENT_NUMBER_OF_OBJECT_FREES;
9289
}
9390
}
9491

92+
count() -= 1;
93+
9594
if (count() == 0) {
9695
std::free(m_buf_p);
96+
DECREMENT_NUMBER_OF_ALLOCATED_OBJECTS;
97+
INCREMENT_NUMBER_OF_OBJECT_FREES;
9798
}
9899
}
99100

@@ -212,18 +213,25 @@ class weak_ptr final
212213
public:
213214
mys::shared_ptr<T> m_shared;
214215

216+
weak_ptr(void) noexcept
217+
: m_shared(nullptr)
218+
{
219+
}
220+
215221
weak_ptr(const mys::shared_ptr<T> &shared) noexcept
216222
: m_shared(shared)
217223
{
218224
if (m_shared) {
219-
m_shared.object_count()--;
225+
m_shared.object_count() -= 1;
220226
}
221227
}
222228

223229
~weak_ptr()
224230
{
225-
if (m_shared && m_shared.object_count() > 0) {
226-
m_shared.object_count()++;
231+
if (m_shared) {
232+
if (m_shared.object_count() > 0) {
233+
m_shared.object_count() += 1;
234+
}
227235
}
228236
}
229237

@@ -233,19 +241,21 @@ class weak_ptr final
233241

234242
if (other) {
235243
m_shared = other;
236-
other.object_count()--;
244+
other.object_count() -= 1;
237245
}
238246

239247
return *this;
240248
}
241249

242250
weak_ptr& operator=(std::nullptr_t)
243251
{
244-
if (m_shared && m_shared.object_count() > 0) {
245-
m_shared.object_count()++;
246-
}
252+
if (m_shared) {
253+
if (m_shared.object_count() > 0) {
254+
m_shared.object_count() += 1;
255+
}
247256

248-
m_shared = nullptr;
257+
m_shared = nullptr;
258+
}
249259

250260
return *this;
251261
}
@@ -257,11 +267,7 @@ class weak_ptr final
257267

258268
mys::shared_ptr<T> lock() const noexcept
259269
{
260-
if (!m_shared) {
261-
abort_is_none();
262-
}
263-
264-
if (m_shared.object_count() == 0) {
270+
if (m_shared && m_shared.object_count() == 0) {
265271
print_traceback();
266272
std::cerr
267273
<< "\nPanic(message=\"Cannot lock weak pointer with no object.\")\n";

mys/transpiler/base.py

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from .utils import CompileError
2626
from .utils import GenericType
2727
from .utils import InternalError
28+
from .utils import Weak
2829
from .utils import dedent
2930
from .utils import dot2ns
3031
from .utils import format_binop
@@ -87,6 +88,13 @@ def is_for_loop_func_call(node):
8788
return node.iter.func.id in FOR_LOOP_FUNCS
8889

8990

91+
def strip_lock(text):
92+
if text.endswith('.lock()'):
93+
return text[:-7]
94+
else:
95+
return text
96+
97+
9098
def mys_type_to_target_cpp_type(mys_type):
9199
if is_primitive_type(mys_type):
92100
return 'auto'
@@ -1169,6 +1177,18 @@ def visit_call_method(self, node):
11691177
raise CompileError('None has no methods', node.func)
11701178
elif isinstance(mys_type, GenericType):
11711179
value, args = self.visit_call_method_generic(name, mys_type, value, node)
1180+
elif isinstance(mys_type, Weak):
1181+
mys_type = mys_type.mys_type
1182+
1183+
if self.context.is_class_defined(mys_type):
1184+
op, value, args = self.visit_call_method_class(name,
1185+
mys_type,
1186+
value,
1187+
node)
1188+
elif self.context.is_trait_defined(mys_type):
1189+
args = self.visit_call_method_trait(name, mys_type, node)
1190+
else:
1191+
raise CompileError(f"'{mys_type}' not class or trait", node.func)
11721192
else:
11731193
mys_type = format_mys_type(mys_type)
11741194

@@ -1986,14 +2006,20 @@ def visit_For(self, node):
19862006

19872007
def visit_attribute_class(self, name, mys_type, value, node):
19882008
definitions = self.context.get_class_definitions(mys_type)
2009+
member = definitions.members.get(name)
19892010

1990-
if name in definitions.members:
1991-
self.context.mys_type = definitions.members[name].type
1992-
else:
2011+
if member is None:
19932012
raise CompileError(
19942013
f"class '{mys_type}' has no member '{name}'",
19952014
node)
19962015

2016+
if isinstance(member.type, Weak):
2017+
self.context.mys_type = member.type.mys_type
2018+
lock = '.lock()'
2019+
else:
2020+
self.context.mys_type = member.type
2021+
lock = ''
2022+
19972023
if value == 'self':
19982024
if self.context.is_macro:
19992025
value = '(__self__)'
@@ -2003,10 +2029,11 @@ def visit_attribute_class(self, name, mys_type, value, node):
20032029
raise CompileError(f"class '{mys_type}' member '{name}' is private",
20042030
node)
20052031

2006-
return value
2032+
return value, lock
20072033

20082034
def visit_Attribute(self, node):
20092035
name = node.attr
2036+
lock = ''
20102037

20112038
if isinstance(node.value, ast.Name):
20122039
value = node.value.id
@@ -2032,17 +2059,20 @@ def visit_Attribute(self, node):
20322059
value = self.visit(node.value)
20332060
mys_type = self.context.mys_type
20342061

2062+
if isinstance(mys_type, Weak):
2063+
mys_type = mys_type.mys_type
2064+
20352065
if isinstance(mys_type, GenericType):
20362066
mys_type = add_generic_class(mys_type.node, self.context)[1]
20372067

20382068
if self.context.is_class_defined(mys_type):
2039-
value = self.visit_attribute_class(name, mys_type, value, node)
2069+
value, lock = self.visit_attribute_class(name, mys_type, value, node)
20402070
else:
20412071
raise CompileError(f"'{mys_type}' has no member '{name}'", node)
20422072

20432073
value = wrap_not_none(value, mys_type)
20442074

2045-
return f'{value}->{make_name(node.attr)}'
2075+
return f'{value}->{make_name(name)}{lock}'
20462076

20472077
def create_constant(self, cpp_type, value):
20482078
if value == 'nullptr':
@@ -2503,7 +2533,7 @@ def visit_assign_subscript(self, node, target):
25032533
return self.visit_assign_other(node, target)
25042534

25052535
def visit_assign_other(self, node, target):
2506-
target = self.visit(target)
2536+
target = strip_lock(self.visit(target))
25072537
target_mys_type = self.context.mys_type
25082538
value = self.visit_check_type(node.value, target_mys_type)
25092539

mys/transpiler/class_transformer.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,18 @@ def add_init(self, node, members):
6262

6363
for member in members:
6464
member_name = member.target.id
65+
annotation = member.annotation
66+
67+
if isinstance(annotation, ast.Subscript):
68+
if isinstance(annotation.value, ast.Name):
69+
if annotation.value.id == 'weak':
70+
annotation = annotation.slice
6571

6672
if is_public(member_name):
67-
args.args.append(ast.arg(arg=member_name,
68-
annotation=member.annotation))
73+
args.args.append(ast.arg(arg=member_name, annotation=annotation))
6974
value = ast.Name(id=member_name)
7075
else:
71-
value = self.default_member_value(member.annotation)
76+
value = self.default_member_value(annotation)
7277

7378
body.append(
7479
ast.Assign(

mys/transpiler/context.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from .utils import CompileError
44
from .utils import Optional
5+
from .utils import Weak
56
from .utils import is_primitive_type
67
from .utils import is_snake_case
78
from .utils import split_dict_mys_type
@@ -292,6 +293,8 @@ def is_type_defined(self, mys_type):
292293
return False
293294
elif isinstance(mys_type, Optional):
294295
return self.is_type_defined(mys_type.mys_type)
296+
elif isinstance(mys_type, Weak):
297+
return self.is_type_defined(mys_type.mys_type)
295298
elif self.is_class_or_trait_defined(mys_type):
296299
return True
297300
elif self.is_enum_defined(mys_type):

mys/transpiler/definitions.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from .utils import CompileError
88
from .utils import GenericType
99
from .utils import Optional
10+
from .utils import Weak
1011
from .utils import format_mys_type
1112
from .utils import get_import_from_info
1213
from .utils import has_docstring
@@ -58,13 +59,12 @@ def visit_Subscript(self, node):
5859
if value == 'optional':
5960
return Optional(self.visit(node.slice), node)
6061
elif value == 'weak':
61-
# ToDo: Do not remove weak.
62-
return self.visit(node.slice)
63-
# return Weak(self.visit(node.slice), node)
62+
return Weak(self.visit(node.slice), node)
6463
else:
6564
types = self.visit(node.slice)
6665

67-
if isinstance(node.slice, ast.Name) or isinstance(types, Optional):
66+
if (isinstance(node.slice, ast.Name)
67+
or isinstance(types, (Optional, Weak))):
6868
types = [types]
6969
else:
7070
types = list(types)
@@ -941,6 +941,10 @@ def process_type(self, mys_type):
941941
return mys_type
942942
elif isinstance(mys_type, Optional):
943943
return self.process_type(mys_type.mys_type)
944+
elif isinstance(mys_type, Weak):
945+
mys_type.mys_type = self.process_type(mys_type.mys_type)
946+
947+
return mys_type
944948
elif mys_type in self.module_definitions.classes:
945949
return f'{self.module}.{mys_type}'
946950
elif mys_type in self.module_definitions.traits:

mys/transpiler/utils.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,20 @@ def __init__(self, mys_type, node):
2222
self.node = node
2323

2424
def __eq__(self, other):
25-
return self.mys_type == other.mys_type
25+
return isinstance(other, Optional) and self.mys_type == other.mys_type
26+
27+
28+
class Weak:
29+
30+
def __init__(self, mys_type, node):
31+
self.mys_type = mys_type
32+
self.node = node
33+
34+
def __eq__(self, other):
35+
if isinstance(other, Weak):
36+
return self.mys_type == other.mys_type
37+
else:
38+
return self.mys_type == other
2639

2740

2841
class CompileError(Exception):
@@ -408,7 +421,10 @@ def mys_to_cpp_type(mys_type, context):
408421
return shared_dict_type(key, value)
409422
elif isinstance(mys_type, set):
410423
item = mys_to_cpp_type(list(mys_type)[0], context)
424+
411425
return shared_set_type(item)
426+
elif isinstance(mys_type, Weak):
427+
return f'mys::weak_ptr<{dot2ns(mys_type.mys_type)}>'
412428
else:
413429
if mys_type == 'string':
414430
return 'mys::String'

mys/transpiler/value_type_visitor.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from .utils import CompileError
1818
from .utils import InternalError
1919
from .utils import Optional
20+
from .utils import Weak
2021
from .utils import is_primitive_type
2122
from .utils import is_snake_case
2223
from .utils import make_integer_literal
@@ -201,6 +202,10 @@ def intersection_of(type_1, type_2, node):
201202
return intersection_of(type_1.mys_type, type_2, node)
202203
elif isinstance(type_2, Optional):
203204
return intersection_of(type_1, type_2.mys_type, node)
205+
elif isinstance(type_1, Weak):
206+
return intersection_of(type_1.mys_type, type_2, node)
207+
elif isinstance(type_2, Weak):
208+
return intersection_of(type_1, type_2.mys_type, node)
204209
else:
205210
raise InternalError(f"specialize types {type_1}, {type_2}", node)
206211

@@ -228,6 +233,8 @@ def reduce_type(value_type):
228233
return {reduce_type(value_type.value_type)}
229234
elif value_type is None:
230235
return None
236+
elif isinstance(value_type, Weak):
237+
return reduce_type(value_type.mys_type)
231238
else:
232239
raise Exception(f"Bad reduce of value type {value_type}.")
233240

@@ -794,6 +801,15 @@ def visit_call_method(self, node):
794801
return self.visit_call_method_trait(name, value_type, node)
795802
elif isinstance(value_type, GenericType):
796803
return self.visit_call_method_generic(name, value_type, node)
804+
elif isinstance(value_type, Weak):
805+
value_type = value_type.mys_type
806+
807+
if self.context.is_class_defined(value_type):
808+
return self.visit_call_method_class(name, value_type, node)
809+
elif self.context.is_trait_defined(value_type):
810+
return self.visit_call_method_trait(name, value_type, node)
811+
else:
812+
raise CompileError(f"'{value_type}' not class or trait", node.func)
797813
else:
798814
raise CompileError("None has no methods", node.func)
799815

mys/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '0.414.0'
1+
__version__ = '0.415.0'

0 commit comments

Comments
 (0)