2 Types have a per-module namespace.
3 This is pre-populated with
4 int i8 i16 uint u8 u64 etc
10 Types can be added with:
17 name is optional, and can list (parameters) and /attributes
19 Types can be constructed with
21 name(args) parameterized type
24 (args:: args) procedure type
25 (args:: type) function type
27 I think that for pointer/array constructor, the decoration comes first.
29 is an array of 5 integers, so foo[5] is an int
31 is an owned pointer to bar, so "foo@" is a bar.
33 is an owner pointer to 5 integers while
35 is an array of 5 borrowed pointers to integers.
36 Having the result type at the end fits better with the function type.
38 then foo(1,2) returns a string.
41 The content of struct and record are a list of:
44 fieldname/attribute: type
47 indicate endianness - bigendian littleendian hostendian
50 protected by a given lock??
52 For enum, content is list of
54 where "= value" is optional
57 to assign a pointer, use foo = stuff
58 to update what the pointer points to, use foo^ = stuff
59 to get a reference to store in a pointer....
60 references are either borrowed or owned.
61 a name defined "type^" is a borrowed reference, a name defined
63 borrowed references may be taken of anything, but only remain defined
64 as long as the owner remains defined.
65 owned references can only be taken of ownable objects, and
68 There are various ways to own an object:
70 - ownership of a containing object.
71 - ownership provided by class method
73 non-type names (vars, constants) can be introduced with
75 const prefix: name = value; ...
76 func: name(args::type): statements
77 proc: name(args::result): statements
88 decide on data structure
89 different types can't really be handled by a big switch now,
90 I probably need and object with function pointers.
91 free_value(), vtype_compat(), val_init(),
92 dup_value(), value_cmp(), print_value(), parse_value()
94 parse_value only needed for args - str and num
96 print_value - only needed for print and code-dump
97 dup_value - needed until pointers can make sense
98 vtype_compat - needed for various things
99 value_cmp - needed until we have object behaviours
107 I think I need to disassociate the type from the storage.
108 So a 'value' is a parsed constant, but something new is needed for
109 the content of a variable.
110 Also, something new is needed for an intermediate lvalue such as an
111 index to an array or a field in a record. Ths is a type plus a pointer.
112 What about rvalues and the result of a calculation. I guess I store
113 that in a temp location, with a pointer...
115 I need to be clear what "interp_exec()" returns. Conceptually it
116 can be an object of any type, and for procedures it can be a tuple of
117 objects. It needs to identify a type and a value of that type.
118 The "value" might be a reference into a variable, or it might be
119 a copy from a calculation. Eventually the reference will have
120 ownership information
126 0/ when does 1/2 produce an integer? Only when explicitly expected.
127 1/ remove 'tail' from value
129 3/ Add a 'Vtyped' vtype and a 'type' pointer
130 4/ add an owership enum: borrowed, single
131 3/ add a 'void *valref' ??
132 4/ Convert num bool str label to Vtyped
134 No, this is awkward because propagate_types wants a 'type' and this intermediate
135 format has a enum+pointer. So make it just a pointer...
138 Vunknown - NULL pointer
139 Vnone - special value
142 A 'type' must be able to:
143 check is it can convert to some other type, reporting if it wants to
144 convert to another type. This requires visibility into other types.
145 print, compare, parse
146 add subtract multiply divide index
149 I currently have an enum of types that is used to test compatability
151 This needs to change .... I guess I need a struct type* What goes in it?
153 - scalar/record/struct/array/pointer/func/enum
156 Do I need forward declarations? Maybe I can just be lazy and
157 require everything to be declared eventually.
158 That isn't sufficient for:
159 - mutually recursive functions
160 - mutually recursive structures
162 What about unions ???
163 blend with enum: a tag with fields?
167 .Bool.true = a:char; b:char
170 Are enums just a fancy way of doing 'const'?
172 const: a=1; b=2; c; d
173 which defines module-wide consts.
176 which defines consts foo.a foo.b foo.c
177 But I don't really like foo entering the val namespace.
178 If bar:foo, then bar.a could be true/false depending on value of bar.
179 bar.a! could set it?? bar.a=true?
182 How do we allocate new objects?
188 Maybe ^= assigns a borrowed reference, and @= assigns an owned reference.
190 allocating isn't really a top priority, so I should just focus on
195 I need a list of steps again:
197 - look up type by name and add syntax for
204 e.g. int[4] or foo@[3]
205 What is int[5][20] ?? it is an array of int[5], which is backwards.
206 So maybe I want [5][20]int ??
207 declares an array of that type/size
208 name : [] = [ 1,2,3 ]
209 declares an array of 3 numbers.
211 extracts an element from the array,
215 creates a slice, which can be stored in a var (borrowed ref) or
219 - new type class which has a size and member type
220 - new type access methods: index and size(?)
222 - new manifest values: [a,b,c] creates an array of whatever member type.
225 struct name : [[ name : type ]]
226 to define a new struct
228 - add syntax to extra a field from a struct
229 how is this type-checked if I don't know the type yet?
231 - add syntax for pointers
233 a:struct foo^ = new()
237 If I declare "struct foo ..." do I use "foo" or "struct foo" to ref the type?
239 So structs, records, enums, and classes must have distinct names.
241 When do I differentiate between compile-time constants and run-time values?
242 When declaring an array, do I require the size to be constant?
243 In a struct I do ... at time of declaration I calculate the size.
245 I do that too - and it is at run-time.
246 So during parsing, I need to describe the array with a member-type and executable size.
247 When that is evaluated, a type is created.
248 So we really need an executable which returns a type.
249 But ... we need to know the type when doing type analysis. So while variable size
250 is OK, the compiler needs to know what it is. Maybe the size needs to be a constant, as in
251 a names assiged with "size ::= 4*5". This gives the compiler some chance of comparing
252 types of array - and doing range checking on indexes.
254 We currently call var_init to set the type of a variable during type
255 analysis - which makes sense.
256 But for an array we don't have the final type until run-time. So we need an
258 So (for now) the size of an array is either a NUMBER or an IDENTIFIER which must be a
260 I need a point where the type is instantiated - where the variable is evaluated
261 and the size is set. I guess this happens when the 'struct var' is evaluated...
262 no, when a Declare binode is evaluated.
264 What happens if I have
265 a:[foo]number = thing
266 I guess the type analysis needs to afirm that thing has the correct type,
267 then a doesn't need to be initialized.
271 and 'a' hasn't been declared .... obviously an error.
274 For field access, I need to know the type of the variable.
275 But I can delay the look up until type analysis.
276 So a[4] is Index(a, 4) - a binode
277 a.foo is Field(a, "foo") - need a new exec type - Fieldname
278 a(args) is Call(a, args) - need a new Binode type - Tuple.
280 So I have to delay 'const' assessment to later too.