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
|
Automatic dereferencing and usability
=====================================
It would be nice to avoid symbols & * @ ^ that other languages have.
But on the other hand, in some cases it is not obvious what is going on
if there is no extra indication. It shouldn't be necessary to look up
definitiions to see what is happening in a function call involving pointers.
For example, what happens here?
rv = somefunc(a, b, c)
the return could be:
- a ref, passed rv that is a ref
- a ref, passed rv that is a stack allocated struct
- a stack allocated struct, passed to rv that is a stack allocated struct
the parameters could be
- refs, where the value passed are refs
- refs, where the value passed are stack allocated structs
- stack allocated structs, where the values passed are refs
- stack allocated structs, where the values passed are stack allocated structs
Similarly, there is a the questions of mutabilty and aliasing (and maybe threading?)
It would be nice if this could be seen directly from the call expression.
For example:
rv = somefunc(a, var b, stack c)
rv own = makesomething(arena a)
#rv rawown = makesomething()
if ref a == ref b { ... }
# value comparison is tricky due to 1) padding and also 2) versioning!
# and only works with non-private structs.
#if value a == value b { ... }
How should this work with nested pointers?
func find(ref Tree tree, string key, ref var ref Node node) -> bool
{
ref Node found_node
...
# FIXME this will not work, because we cannot have a keyword that
# starts a type at a location where the expr could end.
node = found_node
# or
node ref = found_node
# or
node ref ref = found_node
# or
node ref = found_node
}
func example(ref Tree tree) -> void
{
var ref Node n
find(tree, "abc", var node)
}
Or, we could use out parameters:
(how to make it clear what the difference is between "ref var" and "ref var ref"?)
func find(ref Tree tree, string key, out var ref Node node) -> bool
{
ref Node found_node
...
node = found_node
}
func initialize_node(out Node node) -> void
{
...
}
func example(ref Tree tree)
{
var ref Node node
find(tree, "abc", out node)
# FIXME but this is unclear.... is it the ref or the node data that is being modified? (well, with var it would be been the node data itself)
# how about something like this:
find(tree, "abc", out ref node) # for the ref
initialize_node(out node) # for the node data
}
How to make it clear what the difference is between "ref var" and "ref var ref":
ref T = normal ref
ref var T = input/output ref
out T = ref to output
out ref T = ref to output ref
out is basically "ref writeonly"
|