aboutsummaryrefslogtreecommitdiffhomepage
path: root/notes/struct_alternatives.txt
blob: 5899d0d1cf45d565e88bf3dedf6b6fda198de19b (plain)
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

Alterantives to struct/union
============================

See also usability_improvements.txt

- record: a type without a single unique adress (similar to a "value type" in other languages)
- object: a type with a single unique adress (always passed by reference and compared by reference)
- variant: a type that can have one of several types (sometimes called "sum type")

Semantic details
----------------
- objects cannot be declared inline / anonymously.
- taking a reference of an anonymous record should NOT be allowed.

Syntax details
--------------
* When referenced from identifiers, you should have to specifiy whether it is a copy or ref
    - By a qualifier keyword: "ref"/"copy"? (perhaps a better solution?)
    - Or inferred by a type keyworde: "record"/"object"/"variant"?
* record could imply "copy" when it appears *direcly* (without going through an identifier) in another type

Variants
--------
    type E1 = enum {
        A,
        B
    }
    type V1 = variant E1 {
        A = record {
            ...
        }
        B = record {
            ...
        }
    }

Make syntax more readable for nested "structs"?
-----------------------------------------------

Problem:

    type T1 = record {
        record {
            ...
        } f1
        record {
            ...
        } f2
    }

It would be nicer to be able to the field name on the first line of the
field declaration.

Syntax alternative 1: Use Pascal/Go order of identifier/type

    type T1 = record {
        f1: record {
            ...
        } f1
        f2: record {
            ...
        }
    }

Syntax alternative 2: Special case for "structs"

    type T1 = record {
        record f1 {
            ...
        } f1
        record f2 {
            ...
        }
    }



Simplification: Remove "kwb" keyword?
--------------------------------------
Instead of this:

    type R = record { ... }
    type O = object { ... }
    type E = enum { ... }
    type I = int<0..5>          # size is 3 bits

it could be written like this:

    record R { ... }
    class C { ... }              # keyword: "class" or "object?
    enum E { ... }
    record I { int<0..5> num }   # size is 3 bits (for record types only)

But this syntax is identical with "syntax alternative 2" for nested records!
But on the other hand, when reading it, I think it is obvious what it does,
and it's very concise:

    record R {
        int field1
        record field2 {
            int nested1
            int nested2
            enum nested3 {
                a
                b
            }
        }
    }

Keywords for "object" vs "record"
---------------------------------

With/without identity and address:
- object    /   record  (Pascal style)
- class     /   struct  (C# style, but can be confused with C++)
- class the /   class one   (English language style)
- class     /   record
- class unique C / class data C (self-explanatory style 1)
- class C unique / class C data (self-explanatory style 2)
- class     /   data    (needs a keyword rename for data decls)

    class File unique { ... }
    class Point data { ... }

But enums are also identity-less!

Also, it is not obvious that "enum E { ... }" is a type.
The reader could interpret it as a variable.

Methods inside class definitons?
--------------------------------
Is this a good or bad idea?

    class File {
        func .open(string filename) or FileError
        func read(var []byte buffer) -> usize or FileError
        func close() or FileError
    }

It can shorten the lines a lot if the class name is long and/or
if there are type parameters!

On the other hand, it leads to one additional level of indentation on
all lines.

Shorthand syntax for union-with-constructors?
---------------------------------------------

    type FileParam = union {
        # ... tag field?
        struct {
            string filename
        } from_filename
        struct {
            usize len
            ref [len]byte data
        } from_buffer
    }

    func MarkdownFormatter.format(ref FileParam fp) -> Formatted
        lifetime return >= this

    func do_stuff()
    {
        ref Formatted formatted
        ...
        formatted = mdformatter.format(.from_filename("README.md"))
    }