aboutsummaryrefslogtreecommitdiff
path: root/docs/notes/misc_syntax.txt
blob: 70cb4b24046bf11604dd894fcfd22fa0fa65dd29 (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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403


see also:
    http://www.slideshare.net/devstonez/introducing-the-ceylon-project-gavin-king-presentation-at-qcon-beijing-2011


string concatenation
--------------------

goals:
    string concatenation is very common, so it should be easy
    but maybe it should be avoided in some cases? strings in general?
    make the performance clear to the programmer
    

syntaxes:

    "hello " + name
        used by many languages, some people consider this to be a problem
        because the + operator gets two meanings.
    
    "hello " $ name
    
        a special string concatenation operator. Some languages use this,
        like PHP.

    "hello " name
    
        no operator at all, used by the POSIX shell script language.
        also, constants are concatenated this way in C.

    merge("hello ", name, NULL);
    
        could be done, but looks quite ugly
    
    String s = String.new("Hello");
    s.append(name);


parameters, structs and separators
----------------------------------

    Pascal uses ";" as the only separator. This maks everything consistent,
    here's how it could look like in this new language:
    
        typedef Time = (int time; int minute);
        
        int time_diff(Time a; Time b);
        
        Time a, b;
        
    Additionally, this allows "," to be used when the same type is repeated, even
    in parameter lists:
        
        typedef Time = (int time, minute);
        
        int time_def(Time a, b);
        
        Time a, b;


const by default?
-----------------

    var int sessionId = 0;
    
    typedef Time = (
        int hour, minute;  // struct members are not const by default
    );
    
    var Time start;
    
    () add_time(var Time* time, int minutes);
    

generics
--------
    
    The common syntax:
    
        List<Date> dates;
    
    But I think that parsing this could get complicated:
    
        A < B;
    
    Especially if repeated comparison operators are allowed:
    
        A < B > C;
    
    This is a problem because at the time of parsing, it might not be known
    whether A,B,C are types or objects.
    
    
    There are two more syntaxes that look good (IMO) and could work:
    
        List[Date] dates;
        List(Date) dates;
    
    With [] we have to distinguish it from array definitions, and with () we
    have to distinguish it from functions and parameter lists / structs. For
    example:
    
        int[10] constants;
        int[size] prices;
        List[Date] dates;
    
    That looks quite hard imo, especially int[size] vs List[Date].
    Paranthesises might be a better choice:
    
        int[10] constants;
        int[size] prices;
        List(Date) dates;
        
        replace(constants, 3, 8) || sort(prices);
        List(Date).sort();   // List(Date) could be a function or a namespace!
                             // On the other hand, this doesn't matter, because
                             // both can evaluate to a namespace.
    
    

generics and variable elements
------------------------------

    List[int] a;          // an immutable list of immutable elements
    List[var int] a;      // an immutable list of variable elements
    var List[int] a;      // a variable list of immutable elements
    var List[var int] a;  // a variable list of variable elements

    typedef List[T] = 


lists
-----

list initialization:

    int[] list = [1, 2, 3, 4];

list comprehensions:
    
    count size = 10;
    int[size] list = [i^2  for i in 0..size];

automatic list sizes

    count size = 10;
    int[] list = [i^2  for i in 0..size];

    // compiler knows the length of list here
    list[9] = 0;


type extension vs aliasing
--------------------------------

    typedef A is int
    typedef B extends A
    
    But this might be unnecessary, because type extension can be done through
    the "base" identifier in structs!

repetitions
-----------

use cases:

    typedef E = enum {
        a = 1;
        b = 2;
        c = 4;
        d = 8;
    }


type enums & type-array dispatch
--------------------------------

we want to simplify things like this:

    typedef EventType extends enum(
        Click; MouseDown; MouseUp; MouseOver;
    );
    
    typedef Event = struct(
        EventType type;
    );
    
    typedef ClickEvent = struct(
        Event base = (Click);
        int x, y;
        int buttons;
    );
    
    ...
    
    () handle_event(Event e) {
        switch (e.type) {
            case Click:
                ClickEvent ce = ???;
                handle_click(ce);
                break;
            ...
        }
    }
    
alternative, with "namespace substitution":

    namespace eventparams = {
        typedef Click = struct(
            int x, y;
            int buttons;
        );
    };
    
    typedef EventType extends enum(import eventparams);
    
    typedef Event extends struct(
        EventType type;
        union[type](import eventparams);
    );

    () handle_event(Event e) {
        switch (e.type) {
            // shouldn't each entry in the handlers namespace implement some interface?
            case namespace(handlers) h:
                handlers.h(e.h);
                break;
        }
    }

"namespace substitution" could also work with loops and arrays:

    for (namespace h : handlers) {
    }

    ()()*[] triggerfuncs = [import triggers];
    
    triggerfunctions[3]();
    
    
shorthand for "this" code pattern (OO paradigm)
-----------------------------------------------

Use $ as a shortcut, like Zimbu does:
http://www.zimbu.org/design/classes-and-modules

For instance:

    typedef A = (
        int x,
    );

    int A:$work(int y) // how can we say that "this" should be mutable?
    {
        $x += y;
    }
    
becomes:

    typedef A = (
        int x,
    );

    int A:work(var A^ this, int y)
    {
        this^.x += y;
    }



"empty" values and "or-empty"-operator (when)
---------------------------------------------

namespace string {
    typedef here =  ....;
    
    string empty_value = "";
    // could be an "is_empty(x)" function also
}



() fizzbuzz()
{
    for i in range(100) {
        // empty value for string is ""
        string line = ("fizz" when i mod 3 == 0) + ("buzz" when i mod 5 == 0) + "\n"
        line.print();
    }
}

thing^? get_thing()
{
    other^? o = get_other();
    // empty value for thing^? is none
    return o?^.extract_thing() when o != none;
}

first-non-empty operator
------------------------

a = ""
b = "x"
c = "y"

v = a else b else c  // "x"


free-after-use operator
-----------------------

Free's the object as soon as it has been used.

    Thing own^ getThing();

    printThing(getThing()~); // free'd after printThing returns

    printName(getThing()~^.getName()~); // value from getThing is free'd after getName returns. Value from getName is free'd after printName returns.
    
    Thing own^ a = getThing();
    printThing(a~); // free'd after printThing returns

    //a^.getName(); // NOT ALLOWED!


require-block
-------------
behaves like if, but with a different name for clarity.

    if action == "POST" {
        require name != none and thing != none {
            // ...
        } else {
            log.error("missin parameters");
        }
    }

choice statement
----------------

bool value = choice {
    if a == none choose false;
    if a == b choose true;
    choose false;
};

This generates a temporary that's assigned by the statement, which is then
assigned to the "value" variable. This can also be used as an alternative
to the "then-else" statement:

    int x = (a == b then 42 else 0);
    // equivalent
    int x = choice {
        if a == b choose 42;
        else choose 0;
    };


generalize the "alias" keyword
------------------------------
"alias" can be used for macros/inlining also!

    alias float PI = 3.1416;
    
    alias float tan(float x)
        return sin(x) / cos(x);


with blocks and alternatives
----------------------------

With block:
    // syntax
    // resources need to be inited before their first "exit path".
    with type1 resource1 [= init1], type2, resource2 [=init2]...  {
        ...
    } 

    // example
    with FILE^ f = fopen("test.txt", "w") {
        fputs("hello", f);
    }


Declaration qualifier (like "alias"):
    
    autofree FILE^ f = fopen("test.txt", "w");
    fputs("hello", f);


controlling endianess of constants
----------------------------------

    // we can't use a-f and we shouldn't use number-like characters such as "l" or "O"
    // we also shouldn't use things that could be confused with C syntax, such as L, U, d etc.
    uint16 a = 0x1234'L; // little endian
    uint16 b = 0x1234'B;