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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
Syntax for types and declarations
=================================
Shortened type definitions?
---------------------------
Replace the "type I = ..." syntax with the following?
Type definitions:
class I { ... }
record I { ... }
enum I { ... }
error I { ... }
# Should it be possible to define function types?
# Or should function types always go into records?
# Or should there a separate keyword for function types?
# - functype? callback? ...?
callback Compare<T>(T a, T b) -> ComparisonResult
functype Compare<T>(T a, T b) -> ComparisonResult
Declarations of private types
class I
record I
enum I
error I
Disadvantages:
- Does not allow definitions of integer types
- It is not obvious to the user that non-class types can have
methods and "constructors"/typescopes
- Type declarations can be confused with global variables.
Order of declaration
--------------------
Switch to "right-to-left" declarations:
int[5] ref arr <-- reference to array of length 5 of int
Should generics syntax be switched around also?
<int,byte>Map m
Types vs other identifiers
--------------------------
A distinction between names of types and variables/constants/fields/funcs
is important for two reasons:
1. Syntax highlighting can color types in a different colors
(this makes declarations stand out more)
2. Types can start with an identifier, so no "ref" or "data" keyword is
needed in declarations.
Declarations start with uppercase, and expressions with lowercase.
Uppercase, _Uppercase = type
lowercase, _lowercase = variable/constant/field/func
_1 = forbidden
Avoiding the "ref" keyword
--------------------------
Functions:
- Remove the "ref" keyword completely. It doesn't make sense to distinguish
between "ref" and "non-ref" funcs, and function references might be
implemented as something that is not a pointer, or a different kind of
pointer than a normal data pointer.
Objects:
- Objects with identity should always be passed by reference, so the "ref"
keyword is redundant.
Records, enums and elementary types:
- These may be passed by value, so there could more than one "instance" of
what appears to be the same instance. So pointers don't work well here.
Also, small records, enums and numbers may have sub-byte sizes/boundaries,
so pointers won't work anyway.
Strings:
- Single characters are special (encoded in the pointer), so pointers don't
work here either.
Arrays:
- Arrays should work like records.
Qualifiers when parameter needs to be passed by reference
---------------------------------------------------------
"var", "threaded", "aliased" could be used for those purposes.
There is no point in explicitly passing a non-aliased constant
parameter by reference. The compiler can decide automatically
when to pass by reference or by value.
Qualifiers in classes/records/arrays
------------------------------------
In classes and records, it is necessary to specify whether the
item should be inlined or not, when it is a structure or array.
type A = object {
#class A {
B inplace x # type structure must be known (i.e. cannot be private in place of declaration of A)
B ref y
int[] ref a
int[3] inplace b # arrays can only be inplace-allocated if they have a compile-time constant size
inplace B[3] inplace c # array is inplace allocated, and so are the elements
}
New "out" qualfier for parameters
---------------------------------
Unlike "writeonly", this MUST be initialized in all code paths (except on error).
Qualifiers on variables/parameters
----------------------------------
It can be desirable to have modifiable references also.
That could be written like this:
func do_stuff(int out result)
{
File? var f = find_file("a.txt")
if f == none {
f = find_file("b.txt")
result = 2
} else {
result = 1
}
}
Qualifiers on arrays
--------------------
There are several things that can be controlled by qualfiers:
- the field (if the array is in a struct)
- the array size
- the array "slots"
- the array "element contents"
Field:
int[] ref a <-- Reference to an array
int[] var ref a <-- Modifiable reference to an array
Array size:
int[var] ref a
Array "slots":
Buffer var[] ref a <-- "Buffer" objects can be exchanged in list, but not modified themselves
Array "element contents":
var Buffer[] ref a <-- "Buffer" objects themselves can be modified, but not exchanged in list.
Error enums
-----------
Like enums, but can be used as follows:
type FileError = error {
#error FileError {
not_found
permission_denied
}
func .open(string filename) -> File or FileError
...in impl file:
func work()
{
File f1 = .open("1.txt") or FileError e1 {
...handle error...
}
File f2 = .open("2.txt") or goto fail
...
return
fail:
# XXX how to get the error code?
...handle error...
}
|