summaryrefslogtreecommitdiff
path: root/notes/syntax.txt
blob: 1766fe3428f41947fffe96a945cb4378b796f204 (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

toplevels
---------

    type NAME = T
    [interface] func N(T a, ...) [return T] KW...
    T NAME [= VALUE]

should we have "->" or "return" or "returns" or ":" ?


elementary types
----------------

    bool
    size    - unsigned
    ssize   - signed
    offset  - unsigned, offset in files
    soffset - signed, offset in files
    byte    - unsigned,  8 bit, wrapping
    short   - signed,   16 bit
    ushort  - unsigned, 16 bit
    wushort - unsigned, 16 bit, wrapping
    int     - signed,   16/32 bit
    uint    - unsigned, 16/32 bit
    wuint   - unsigned, 16/32 bit, wrapping
    long    - signed,   32/64 bit
    ulong   - unsigned, 32/64 bit
    wulong  - unsigned, 32/64 bit, wrapping
    int32
    uint32
    wuint32
    int64    *1
    uint64   *1
    wuint64  *1
    (int128, uint128, wuint128) *2
    (float, double, float16, float32, float64, float80, float128?) *2
    
    *1 = not available in bootstrap
    *2 = only available if supported by target platfrom. not available in bootstrap
    
other types
-----------

- for parameters it is probably enough to have ref/out/inout/addr/stck
- for data there is only stack (we don't allow pointers, since that would require an initializer)
- for function-locals we need:
-- var
-- stck (for initialized const-arrays/structs and named types)
-- addr
-- ref
-- rwref (or inout, varref or mutref?)
-- wref  (or out?)
("var ref" and "ref var" could be confusing, and even more so "ref var ref")
for structs we need
-- nested (for const-arrays/structs and named types)
-- addr, ref
-- rwref, wref (for write access, or copying to another location,
                these also require write access to the struct itself)

structs can use plain () syntax without a keyword
this should work well with the keywords (nested/ref/stck/etc)

function pointers, should that be "ref func(T x, ...) return T" syntax?

optional types could use "?" or "opt" before the type, e.g. "?int" or "opt int"

enums could use "enum (a = 1)". and "enum byte (a = 1, b, c)" etc.
- the syntax above will only allow elementary types (incl. named types)? (probably a pragmatic choice)

arrays:
- [3]int
- [len]int
- [enumtype]int
- [inttype]int
- how to combine inttype and length expression?
-- pragmatic choice: use type of length expression. we could also use an "as" expression here
-- or instead of "as": "[T L]A", e.g. "[indextype 3]arr"
-- do we want to support lower bounds as well? e.g. [1..5,3..10] or [indextype 1..5, indextype2 3..10]

parametric types:
- <int>list
- or list<int> ?

types referenced by identifier
- a type can't start with an identifier.
- as a workaround, require:
-- that enums start with "enum" (always)
-- that stack structs have a "stack" qualifier
IF we also disallow typedefs to builtin types, arrays etc. and only allow typedefs of structs/enums,
this would mean that any bare identifier reference is a reference to a struct type.

type qualifiers:
- shared
- reading(...)  (objects that are read from)   - (or "using"?)
- writing(...)  (objects that are written to)
- readwriting(...)  (objects that are read and written to)
- static (for functions-locals). by default, it creates a constant non-pointer
- (var?)
- own
- own(...)
- takeown ("this" param takes ownership)
- dropown ("this" param looses ownership)
- takeown(x) / dropown(x)   (x takes/looses ownership)
- takeshare/dropshare ? or just use plain shared(...)
- dedup (for generic-typed parameters, to allow values that fit in a pointer
         to be passed inside the pointer, avoiding creation of a temporary
         stack item and indirections to access it)

Expressions
-----------
- can we have only prefix and infix (+ maybe ternary-infix) operators?
-- we still need . [] ()
- pointers:
-- addrof
-- deref (may be needed for final deref)
- optional types:
-- makeopt
-- optval (or ? as postfix operator)... or use typeasserts instead, more meaningful!
- arithmetic:
-- + - * / mod
-- ++ -- (or inc/dec)
-- unary -
- boolean
-- and or xor not
- bitwise
-- bitand bitor bitxor neg shl shr (shra?) (rol ror?)
- array index x[i] (with explicit pointer deref)
- struct member s.m (with explicit pointer deref)
- function call (with explicit pointer deref?)
- ternary operator? select operator? in operator? etc...
-- we want to avoid commas in multi-line statements
-- multiline statements are probably a better idea (for readability)
-- there could be built-in or stdlib functions/macros for common conversions like bool<->int
   select [0, 1]
   select [:false 0, :true 1]
   select [
       :false  0
       :true   1]
   select [
       :false => 0
       :true => 1]
   select {
       case :true => 0
       case :false => 1
   }
   # conversion functions with typescope
   :from_bool(:true)
   :from_int(1)
   # without typescope (clearer?)
   bool2int(:true)
   int2bool(1)