Skip to content

Commit 24dd200

Browse files
authored
Merge pull request GaijinEntertainment#2083 from GaijinEntertainment/more-tutorials
pointer tutorial
2 parents 2b3e30b + 48b5b87 commit 24dd200

10 files changed

Lines changed: 1114 additions & 7 deletions

File tree

.github/copilot-instructions.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ When editing RST files in `doc/source/reference/language/`:
178178
- All code blocks use `.. code-block:: das` with gen2 syntax
179179
- Include `// output:` comments showing expected output for runnable examples
180180
- Add `require` statements when examples need imports
181-
- Use `:ref:` cross-references to link between pages (labels: `_structs`, `_classes`, `_functions`, `_statements`, `_expressions`, `_arrays`, `_tables`, `_iterators`, `_generators`, `_lambdas`, `_blocks`, `_tuples`, `_variants`, `_bitfields`, `_aliases`, `_modules`, `_options`, `_unsafe`, `_enumerations`, `_generic_programming`, `_pattern-matching`, `_comprehensions`, `_string_builder`, `_macros`, `_reification`, `_finalizers`, `_clone`, `_temporary`, `_move_copy_clone`, `_annotations`, `_program_structure`, `_type_conversions`, `_contexts`, `_locks`, `_datatypes_and_values`)
181+
- Use `:ref:` cross-references to link between pages (labels: `_structs`, `_classes`, `_functions`, `_statements`, `_expressions`, `_arrays`, `_tables`, `_iterators`, `_generators`, `_lambdas`, `_blocks`, `_tuples`, `_variants`, `_bitfields`, `_aliases`, `_modules`, `_options`, `_unsafe`, `_enumerations`, `_generic_programming`, `_pattern-matching`, `_comprehensions`, `_string_builder`, `_macros`, `_reification`, `_finalizers`, `_clone`, `_temporary`, `_move_copy_clone`, `_annotations`, `_program_structure`, `_type_conversions`, `_contexts`, `_locks`, `_datatypes_and_values`, `_pointers`)
182182
- Verify examples compile: `bin/Release/daslang.exe example.das`
183183

184184
### RST table rules
@@ -247,7 +247,7 @@ C++ integration tutorial RST files live in `doc/source/reference/tutorials/` wit
247247
- Each tutorial is one self-contained `.cpp` file with embedded `main()` — no separate build infrastructure needed beyond CMake target
248248
- Tutorial CMake targets: `integration_cpp_01` through `integration_cpp_NN` (defined in `tutorials/integration/cpp/CMakeLists.txt`)
249249

250-
- Tutorial labels for cross-references: `tutorial_hello_world`, `tutorial_variables`, `tutorial_operators`, `tutorial_control_flow`, `tutorial_functions`, `tutorial_arrays`, `tutorial_strings`, `tutorial_structs`, `tutorial_enumerations`, `tutorial_tables`, `tutorial_tuples_and_variants`, `tutorial_function_pointers`, `tutorial_blocks`, `tutorial_lambdas`, `tutorial_iterators_and_generators`, `tutorial_modules`, `tutorial_move_copy_clone`, `tutorial_classes`, `tutorial_generics`, `tutorial_lifetime`, `tutorial_error_handling`, `tutorial_unsafe`, `tutorial_string_format`, `tutorial_pattern_matching`, `tutorial_annotations`, `tutorial_contracts`, `tutorial_testing`, `tutorial_linq`, `tutorial_functional`, `tutorial_json`, `tutorial_regex`, `tutorial_operator_overloading`
250+
- Tutorial labels for cross-references: `tutorial_hello_world`, `tutorial_variables`, `tutorial_operators`, `tutorial_control_flow`, `tutorial_functions`, `tutorial_arrays`, `tutorial_strings`, `tutorial_structs`, `tutorial_enumerations`, `tutorial_tables`, `tutorial_tuples_and_variants`, `tutorial_function_pointers`, `tutorial_blocks`, `tutorial_lambdas`, `tutorial_iterators_and_generators`, `tutorial_modules`, `tutorial_move_copy_clone`, `tutorial_classes`, `tutorial_generics`, `tutorial_lifetime`, `tutorial_error_handling`, `tutorial_unsafe`, `tutorial_string_format`, `tutorial_pattern_matching`, `tutorial_annotations`, `tutorial_contracts`, `tutorial_testing`, `tutorial_linq`, `tutorial_functional`, `tutorial_json`, `tutorial_regex`, `tutorial_operator_overloading`, `tutorial_pointers`
251251
- C++ integration tutorial labels: `tutorial_integration_cpp_hello_world`, `tutorial_integration_cpp_calling_functions`, `tutorial_integration_cpp_binding_functions`, `tutorial_integration_cpp_binding_types`, `tutorial_integration_cpp_binding_enums`, `tutorial_integration_cpp_interop`, `tutorial_integration_cpp_callbacks`, `tutorial_integration_cpp_methods`, `tutorial_integration_cpp_operators_and_properties`
252252
- C++ integration tutorial plan (remaining): 10 Custom Modules, 11 Context Variables, 12 Smart Pointers & GC, 13 AOT, 14 Serialization, 15 Custom Annotations, 16 Sandbox
253253

CLAUDE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ When editing RST files in `doc/source/reference/language/`:
178178
- All code blocks use `.. code-block:: das` with gen2 syntax
179179
- Include `// output:` comments showing expected output for runnable examples
180180
- Add `require` statements when examples need imports
181-
- Use `:ref:` cross-references to link between pages (labels: `_structs`, `_classes`, `_functions`, `_statements`, `_expressions`, `_arrays`, `_tables`, `_iterators`, `_generators`, `_lambdas`, `_blocks`, `_tuples`, `_variants`, `_bitfields`, `_aliases`, `_modules`, `_options`, `_unsafe`, `_enumerations`, `_generic_programming`, `_pattern-matching`, `_comprehensions`, `_string_builder`, `_macros`, `_reification`, `_finalizers`, `_clone`, `_temporary`, `_move_copy_clone`, `_annotations`, `_program_structure`, `_type_conversions`, `_contexts`, `_locks`, `_datatypes_and_values`)
181+
- Use `:ref:` cross-references to link between pages (labels: `_structs`, `_classes`, `_functions`, `_statements`, `_expressions`, `_arrays`, `_tables`, `_iterators`, `_generators`, `_lambdas`, `_blocks`, `_tuples`, `_variants`, `_bitfields`, `_aliases`, `_modules`, `_options`, `_unsafe`, `_enumerations`, `_generic_programming`, `_pattern-matching`, `_comprehensions`, `_string_builder`, `_macros`, `_reification`, `_finalizers`, `_clone`, `_temporary`, `_move_copy_clone`, `_annotations`, `_program_structure`, `_type_conversions`, `_contexts`, `_locks`, `_datatypes_and_values`, `_pointers`)
182182
- Verify examples compile: `bin/Release/daslang.exe example.das`
183183

184184
### RST table rules
@@ -247,7 +247,7 @@ C++ integration tutorial RST files live in `doc/source/reference/tutorials/` wit
247247
- Each tutorial is one self-contained `.cpp` file with embedded `main()` — no separate build infrastructure needed beyond CMake target
248248
- Tutorial CMake targets: `integration_cpp_01` through `integration_cpp_NN` (defined in `tutorials/integration/cpp/CMakeLists.txt`)
249249

250-
- Tutorial labels for cross-references: `tutorial_hello_world`, `tutorial_variables`, `tutorial_operators`, `tutorial_control_flow`, `tutorial_functions`, `tutorial_arrays`, `tutorial_strings`, `tutorial_structs`, `tutorial_enumerations`, `tutorial_tables`, `tutorial_tuples_and_variants`, `tutorial_function_pointers`, `tutorial_blocks`, `tutorial_lambdas`, `tutorial_iterators_and_generators`, `tutorial_modules`, `tutorial_move_copy_clone`, `tutorial_classes`, `tutorial_generics`, `tutorial_lifetime`, `tutorial_error_handling`, `tutorial_unsafe`, `tutorial_string_format`, `tutorial_pattern_matching`, `tutorial_annotations`, `tutorial_contracts`, `tutorial_testing`, `tutorial_linq`, `tutorial_functional`, `tutorial_json`, `tutorial_regex`, `tutorial_operator_overloading`
250+
- Tutorial labels for cross-references: `tutorial_hello_world`, `tutorial_variables`, `tutorial_operators`, `tutorial_control_flow`, `tutorial_functions`, `tutorial_arrays`, `tutorial_strings`, `tutorial_structs`, `tutorial_enumerations`, `tutorial_tables`, `tutorial_tuples_and_variants`, `tutorial_function_pointers`, `tutorial_blocks`, `tutorial_lambdas`, `tutorial_iterators_and_generators`, `tutorial_modules`, `tutorial_move_copy_clone`, `tutorial_classes`, `tutorial_generics`, `tutorial_lifetime`, `tutorial_error_handling`, `tutorial_unsafe`, `tutorial_string_format`, `tutorial_pattern_matching`, `tutorial_annotations`, `tutorial_contracts`, `tutorial_testing`, `tutorial_linq`, `tutorial_functional`, `tutorial_json`, `tutorial_regex`, `tutorial_operator_overloading`, `tutorial_pointers`
251251
- C++ integration tutorial labels: `tutorial_integration_cpp_hello_world`, `tutorial_integration_cpp_calling_functions`, `tutorial_integration_cpp_binding_functions`, `tutorial_integration_cpp_binding_types`, `tutorial_integration_cpp_binding_enums`, `tutorial_integration_cpp_interop`, `tutorial_integration_cpp_callbacks`, `tutorial_integration_cpp_methods`, `tutorial_integration_cpp_operators_and_properties`
252252
- C++ integration tutorial plan (remaining): 10 Custom Modules, 11 Context Variables, 12 Smart Pointers & GC, 13 AOT, 14 Serialization, 15 Custom Annotations, 16 Sandbox
253253

doc/source/reference/language.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
language/program_structure.rst
99
language/lexical_structure.rst
1010
language/datatypes.rst
11+
language/pointers.rst
1112
language/constants_and_enumerations.rst
1213
language/statements.rst
1314
language/expressions.rst
@@ -41,8 +42,8 @@
4142
language/builtin_functions.rst
4243

4344
*****************************
44-
The Runtime
45-
*****************************
45+
The Runtime
46+
*****************************
4647

4748
.. toctree::
4849
language/contexts.rst

doc/source/reference/language/datatypes.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ All structs are always passed to functions arguments as references.
293293
Pointers
294294
--------------
295295

296-
Pointers are types that 'reference' (point to) some other data, but can be null (point to nothing).
296+
Pointers are types that 'reference' (point to) some other data, but can be null (point to nothing)
297+
(see :ref:`Pointers <pointers>`).
297298
In order to work with actual value, one need to dereference it using the dereference or safe navigation operators.
298299
Dereferencing will panic if a null pointer is passed to it.
299300
Pointers can be created using the new operator, or with the C++ environment.
Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
.. _pointers:
2+
3+
========
4+
Pointers
5+
========
6+
7+
.. index::
8+
single: Pointers
9+
10+
Daslang provides nullable pointer types for heap-allocated data, optional
11+
references, and low-level memory access. Pointer operations split into
12+
two categories: **safe** operations that work without ``unsafe``, and
13+
**unsafe** operations that require an ``unsafe`` block.
14+
15+
.. _pointer_types:
16+
17+
--------------
18+
Pointer types
19+
--------------
20+
21+
============= =====================================================
22+
Type Description
23+
============= =====================================================
24+
``T?`` Nullable pointer to type ``T``
25+
``T? const`` Const pointer — cannot modify the pointed-to value
26+
``T?#`` Temporary pointer (from ``safe_addr``) — cannot escape scope
27+
``void?`` Untyped pointer — must ``reinterpret`` to use
28+
============= =====================================================
29+
30+
Pointer types are declared by appending ``?`` to any type::
31+
32+
var p : int? // pointer to int — null by default
33+
var ps : Point? // pointer to struct
34+
var vp : void? // void pointer
35+
36+
All pointers default to ``null`` when uninitialized.
37+
38+
.. _pointer_creation:
39+
40+
-----------------
41+
Creating pointers
42+
-----------------
43+
44+
new
45+
^^^
46+
47+
``new`` allocates on the heap and returns ``T?``::
48+
49+
var p = new Point(x = 3.0, y = 4.0) // p is Point?
50+
var q = new Point() // default field values
51+
52+
Heap pointers must be released with ``delete`` (see :ref:`pointer_delete`)
53+
or declared with ``var inscope`` for automatic cleanup::
54+
55+
var inscope pt = new Point(x = 1.0, y = 2.0)
56+
// pt is automatically deleted at scope exit
57+
58+
addr
59+
^^^^
60+
61+
``addr(x)`` returns a pointer to an existing variable. **Requires unsafe.**
62+
63+
::
64+
65+
var x = 42
66+
unsafe {
67+
var p = addr(x) // p is int?
68+
*p = 100 // modifies x
69+
}
70+
71+
The pointer is valid only while the variable is alive — using it after
72+
the variable goes out of scope is undefined behavior.
73+
74+
safe_addr
75+
^^^^^^^^^
76+
77+
``safe_addr`` from ``daslib/safe_addr`` returns a temporary pointer (``T?#``)
78+
without requiring ``unsafe``. The compiler validates that the argument is a
79+
local or global variable (not a field of a temporary)::
80+
81+
require daslib/safe_addr
82+
var a = 13
83+
var p = safe_addr(a) // p is int?# (temporary pointer)
84+
print("{*p}\n")
85+
86+
Temporary pointers cannot be stored in containers or returned from functions.
87+
88+
.. _pointer_deref:
89+
90+
--------------
91+
Dereferencing
92+
--------------
93+
94+
``*p`` or ``deref(p)`` follows the pointer to the value. Both panic if the
95+
pointer is null::
96+
97+
*p // dereference
98+
deref(p) // same thing
99+
100+
For struct pointers, ``.`` auto-dereferences — no ``->`` operator is needed::
101+
102+
var inscope pt = new Point(x = 5.0, y = 6.0)
103+
print("{pt.x}\n") // 5 — same as (*pt).x
104+
pt.x = 10.0 // modify through auto-deref
105+
106+
.. _pointer_null_safety:
107+
108+
-----------
109+
Null safety
110+
-----------
111+
112+
Null checks
113+
^^^^^^^^^^^
114+
115+
Pointers can be compared to ``null``::
116+
117+
if (p != null) {
118+
print("{*p}\n") // safe — we checked
119+
}
120+
121+
Null dereference panics at runtime and can be caught with ``try``/``recover``::
122+
123+
try {
124+
var np : int?
125+
print("{*np}\n")
126+
} recover {
127+
print("caught null dereference\n")
128+
}
129+
130+
Safe navigation ``?.``
131+
^^^^^^^^^^^^^^^^^^^^^^
132+
133+
``?.`` returns ``null`` instead of panicking when the pointer is null::
134+
135+
p?.x // returns x if p is non-null, null otherwise
136+
a?.b?.c // chains — short-circuits on first null
137+
138+
Safe navigation results are themselves nullable, so combine with ``??``
139+
for a concrete fallback::
140+
141+
let val = p?.x ?? -1 // -1 if p is null
142+
143+
Null coalescing ``??``
144+
^^^^^^^^^^^^^^^^^^^^^^
145+
146+
``??`` provides a default value when the left side is null::
147+
148+
let x = p ?? default_value
149+
150+
For pointer dereference::
151+
152+
let x = *p ?? 0 // 0 if p is null
153+
154+
.. _pointer_delete:
155+
156+
--------
157+
Deletion
158+
--------
159+
160+
``delete`` frees heap memory and sets the pointer to null. **Requires unsafe.**
161+
162+
::
163+
164+
var p = new Point()
165+
unsafe {
166+
delete p // frees memory, p becomes null
167+
}
168+
169+
Prefer ``var inscope`` for automatic cleanup — it adds a ``finally`` block
170+
that deletes the pointer when the scope exits::
171+
172+
var inscope p = new Point()
173+
// p is automatically deleted at end of scope
174+
175+
.. _pointer_arithmetic:
176+
177+
-------------------
178+
Pointer arithmetic
179+
-------------------
180+
181+
All pointer arithmetic **requires unsafe**. No bounds checking is performed.
182+
183+
Indexing
184+
^^^^^^^^
185+
186+
``p[i]`` accesses the ``i``-th element at the pointer's address::
187+
188+
var arr <- [10, 20, 30, 40, 50]
189+
unsafe {
190+
var p = addr(arr[0])
191+
print("{p[0]}, {p[2]}\n") // 10, 30
192+
}
193+
194+
Increment and addition
195+
^^^^^^^^^^^^^^^^^^^^^^
196+
197+
::
198+
199+
unsafe {
200+
++ p // advance pointer by one element
201+
p += 3 // advance by three elements
202+
}
203+
204+
.. warning::
205+
206+
Pointer arithmetic can easily cause out-of-bounds access or invalid
207+
pointer states. Use array bounds-checked access whenever possible.
208+
209+
.. _pointer_void:
210+
211+
--------------
212+
Void pointers
213+
--------------
214+
215+
``void?`` is an untyped pointer — equivalent to ``void*`` in C/C++. It is
216+
used for opaque handles and C/C++ interop. You must ``reinterpret`` it back
217+
to a typed pointer before dereferencing::
218+
219+
unsafe {
220+
var x = 123
221+
var px = addr(x)
222+
var vp : void? = reinterpret<void?> px // erase type
223+
var px2 = reinterpret<int?> vp // restore type
224+
print("{*px2}\n") // 123
225+
}
226+
227+
.. _pointer_intptr:
228+
229+
------
230+
intptr
231+
------
232+
233+
``intptr(p)`` converts any pointer (raw or smart) to a ``uint64`` integer
234+
representing its memory address::
235+
236+
let address = intptr(p) // uint64
237+
238+
Useful for debugging, logging, pointer identity comparisons, or hashing.
239+
240+
.. _pointer_reinterpret:
241+
242+
-----------
243+
reinterpret
244+
-----------
245+
246+
``reinterpret<T>`` performs a raw bit cast between types of the same size.
247+
**Requires unsafe.** It does not convert values — it reinterprets the raw bits::
248+
249+
unsafe {
250+
let f = 1.0
251+
let bits = reinterpret<int> f // IEEE 754: 0x3f800000
252+
let back = reinterpret<float> bits // 1.0
253+
}
254+
255+
Can also cast between pointer types::
256+
257+
unsafe {
258+
var p : int? = addr(x)
259+
var vp = reinterpret<void?> p // to void?
260+
var p2 = reinterpret<int?> vp // back to int?
261+
}
262+
263+
.. _pointer_typeinfo:
264+
265+
---------
266+
Type info
267+
---------
268+
269+
Several ``typeinfo`` queries test pointer properties at compile time::
270+
271+
typeinfo(is_pointer p) // true if p is a pointer type
272+
typeinfo(is_smart_ptr p) // true if p is a smart_ptr<T>
273+
typeinfo(is_void_pointer p) // true if p is void?
274+
typeinfo(can_delete_ptr p) // true if delete is valid for p
275+
276+
.. _pointer_summary:
277+
278+
-------
279+
Summary
280+
-------
281+
282+
**Safe (no unsafe required):**
283+
284+
* ``new T()`` — heap allocate, returns ``T?``
285+
* ``*p`` / ``deref(p)`` — dereference (panics if null)
286+
* ``p.field`` — auto-deref field access
287+
* ``p?.field`` — safe navigation (null-propagating)
288+
* ``p ?? default`` — null coalescing
289+
* ``safe_addr(x)`` — temporary pointer (``T?#``)
290+
* ``var inscope p = new T()`` — automatic cleanup
291+
* ``intptr(p)`` — pointer to integer
292+
293+
**Unsafe (requires unsafe block):**
294+
295+
* ``addr(x)`` — address of variable
296+
* ``delete p`` — free heap memory
297+
* ``p[i]`` — pointer indexing
298+
* ``++ p`` / ``p += N`` — pointer arithmetic
299+
* ``reinterpret<T>`` — raw bit cast
300+
301+
.. seealso::
302+
303+
:ref:`Unsafe <unsafe>` for the full list of unsafe operations.
304+
305+
:ref:`Values and Data Types <datatypes_and_values>` for smart pointers
306+
(``smart_ptr<T>``).
307+
308+
:ref:`Temporary types <temporary>` for temporary pointers (``T?#``) and
309+
``safe_addr``.
310+
311+
:ref:`Tutorial: Pointers <tutorial_pointers>` for a hands-on walkthrough.

doc/source/reference/tutorials.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ introduced in earlier tutorials.
5050
tutorials/33_algorithm.rst
5151
tutorials/34_decs.rst
5252
tutorials/35_jobque.rst
53+
tutorials/36_pointers.rst
5354

5455
C Integration Tutorials
5556
-----------------------

doc/source/reference/tutorials/35_jobque.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,8 @@ for long-lived work that should not block the job queue:
305305

306306
Previous tutorial: :ref:`tutorial_decs`
307307

308+
Next tutorial: :ref:`tutorial_pointers`
309+
308310
:ref:`Lambda <lambdas>` — lambda language reference.
309311

310312
:ref:`Blocks <blocks>` — block language reference.

0 commit comments

Comments
 (0)