]> ocean-lang.org Git - ocean-D/blobdiff - Ocean-types
updates
[ocean-D] / Ocean-types
index b29b64c2729192aac89af8a010d8cf502e3b1f64..a89544cc3c87da1b04b679ff0cff88bc5d401720 100644 (file)
@@ -24,6 +24,19 @@ Types can be constructed with
    (args:: args)  procedure type
    (args:: type)    function type
 
+  I think that for pointer/array constructor, the decoration comes first.
+    foo: [5]int
+  is an array of 5 integers, so foo[5] is an int
+    foo: @bar
+  is an owned pointer to bar, so "foo@" is a bar.
+    foo: @[5]int
+  is an owner pointer to 5 integers while
+    foo:[5]^int
+  is an array of 5 borrowed pointers to integers.
+  Having the result type at the end fits better with the function type.
+   foo:(int, int)string
+  then foo(1,2) returns a string.
+
 
 The content of struct and record are a list of:
    fieldname: type
@@ -133,7 +146,7 @@ What do I do with
   add subtract multiply divide index
 ----------
 
- I currently have an enum of types that is used to test compatability
+ I currently have an enum of types that is used to test comparability
  and for propagation.
  This needs to change .... I guess I need a struct type* What goes in it?
   - name
@@ -154,6 +167,26 @@ What do I do with
      .Bool.true = a:char; b:char
      .Bool.false = ......
 
+  I like "inheritance" but that doesn't allow the size of the whole to
+  be known in advance.
+  I need a way to talk about which instance is active, even if the value
+  isn't stored.  So Pascal-like variant records are good.
+  Maybe a struct could be declared as 'extensible' and other structs
+  could 'extend', and it literally makes it bigger
+  struct a extensible {x1:int}
+  struct b extends a {y1:int}
+  struct c extends a extensible {y2:int}
+  struct d extends c  {z1:int}
+
+  now 'a' has room for x1, (y2 and z1) or y1
+  Which is used depends on context .. or by assertion on content.
+  So extensions can set values for existing fields
+    struct z extends a {x1=4; string c}
+
+  Syntax is a bit clumsy.  Do I need "extensible"??
+  
+
+
  Are enums just a fancy way of doing 'const'?
  I could have
    const: a=1; b=2; c; d
@@ -188,6 +221,9 @@ I need a list of steps again:
 
  - Add arrays:
       name : type[size]
+        e.g. int[4] or foo@[3]
+          What is int[5][20] ?? it is an array of int[5], which is backwards.
+          So maybe I want [5][20]int ??
     declares an array of that type/size
       name : [] = [ 1,2,3 ]
     declares an array of 3 numbers.
@@ -221,3 +257,163 @@ Questions:
   If I declare "struct foo ..." do I use "foo" or "struct foo" to ref the type?
   I think just "foo".
   So structs, records, enums, and classes must have distinct names.
+
+ When do I differentiate between compile-time constants and run-time values?
+ When declaring an array, do I require the size to be constant?
+ In a struct I do ... at time of declaration I calculate the size.
+ For foo:[sqr(a)]int
+ I do that too - and it is at run-time.
+ So during parsing, I need to describe the array with a member-type and executable size.
+ When that is evaluated, a type is created.
+ So we really need an executable which returns a type.
+ But ... we need to know the type when doing type analysis.  So while variable size
+ is OK, the compiler needs to know what it is.  Maybe the size needs to be a constant, as in
+ a names assiged with "size ::= 4*5".  This gives the compiler some chance of comparing
+ types of array - and doing range checking on indexes.
+
+ We currently call var_init to set the type of a variable during type
+ analysis - which makes sense.
+ But for an array we don't have the final type until run-time.  So we need an
+ intermediate type.
+ So (for now) the size of an array is either a NUMBER or an IDENTIFIER which must be a
+  constant var.
+ I need a point where the type is instantiated - where the variable is evaluated
+  and the size is set.  I guess this happens when the 'struct var' is evaluated...
+  no, when a Declare binode is evaluated.
+
+ What happens if I have
+    a:[foo]number = thing
+ I guess the type analysis needs to afirm that thing has the correct type,
+ then a doesn't need to be initialized.
+
+ If I find
+    a[4] = "hello"
+ and 'a' hasn't been declared .... obviously an error.
+
+ When/what/how.
+  For field access, I need to know the type of the variable.
+  But I can delay the look up until type analysis.
+  So a[4] is Index(a, 4) - a binode
+     a.foo is Field(a, "foo") -  need a new exec type - Fieldname
+     a(args) is Call(a, args) - need a new Binode type - Tuple.
+
+So I have to delay 'const' assessment to later too.
+
+----------
+Where do type definition go?
+I don't think they go with statements, they belong separately.
+I don't want the full separation of a "type" section like Pascal
+So they probably go at the top level, equivalent to "program" - and before.
+They start with "struct" or "enum" or "record" etc.
+
+So: what about constants?  These are currently statements and so affect a scope in time.
+But for declaring arrays in structs, or initial values of fields, we might want constants.
+A constant could be within a struct, but only that it too limiting.  I need module-wide
+constants.
+So I guess:
+
+   const:
+      name ::= value
+      name ::= value
+
+or
+   const { name ::= value ; name ::= value }
+
+--------------
+I'm in the middle of stage-1 on structures.
+
+I need a type to parse the declaration into.  It needs to be a linked list
+of fields, each of which is a type, a name, and an initial value.  i.e. a 'struct field'.
+
+-----------------
+
+Numbers...
+I want signed/unsigned/bitset integers (and probably floats).
+These are different sizes, and I want to move 'type' out of 'value'
+so I can have arrays of numbers that are *just* the densely packets numbers.
+
+So there are two questions here: how will I handle values in oceani, and
+what are the semantics of numbers in ocean.
+
+I think I want bitops to requires bitsets and arith ops to require signed/unsigned.
+But there is some overlap.
+e.g. we use bitops to test if a number is a power of two
+We sometimes use bitops to multiply, but that is probably best avoided.
+use * to multiply.
+
+Converting between the two can be done with simple assignment.
+
+So + - * / %     require/assume signed or unsigned
+   | & ~ << >>   require/assume bitset
+
+  #  accepts either and produces a bitset
+
+Other issue is overflow/underflow checking.
+Do we need another unsigned type - cyclic
+
+    i32 - signed integer in 32 bits
+    u32 - unsigned integer
+    c32 - unsigned with overflow permitted and ignored
+    b32 - bitset
+
+    int uint cint bset - whatever size.
+
+i32 and u32 detect overflow/underflow and set to NaN - all 1's
+If I want to allow overloading (such a NaN), I need a type that
+declare no overloading. s32 and c32?  Or annotations.  !s32 !u32
+
+So what about values in oceani?  I want to separate out the type and not
+use a union.
+Where are they used?
+ - return of init, prepare, parse, dup
+ - passed to  print, cmp, dup, free, to_int, to_float, to_mpq
+ - field in 'struct variable'
+ - field in 'struct lrval'
+ - result of 'interp'
+ - intermediate left/right in interp
+ - field in array and struct field
+ - field in 'struct val' for manifest constants
+
+So:
+  variable gets a 'type' pointer and a union which can be a pointer
+  to the value, or the value itself (depending on size)
+  lrval get a type pointer as well, plus the union
+  interp returns ...
+
+
+-----------------
+Struct/array initialisers.
+I like [a,b,c] rather than {a,b,c} because the latter can look like code.
+But [] is also array indexing.
+So an array initializer could look:
+  [ [1] = "hello", [5] = "there" ]
+and that is confusingly similar to nested initialization
+  [ [1,2] , [3,4] ]
+Options:
+ 1/ use different outer.  {}  () <> << >>
+   < is possibly as it is not a prefix operator.
+     But nesting results in <<1,2>,<3,4>> which looks like << instead of < <
+   {} I already don't like
+   () is bad enough with function calls - it is best if it is grouping only.
+     though with function calls it is a list ...
+   << [1]="hello", [2]="there" >>...  I don't really like that
+
+   array[ ]
+   struct[ ]
+     No, too noisy.
+
+ 2/ use different inner syntax.
+     [ .[1] = "hello", .[5] = "hello" ]
+
+ What about a newline-based syntax:
+  a: [4]int :
+       [0] = 2
+       [1] = 3
+       [3] = 1
+
+ Nice, but doesn't actually help.  Still need .[] because I want to allow
+ a one-line syntax too.
+ Maybe I just use {} after all.
+
+  a:[4]int = { [0]=2, [1]=3, [3]=1 }
+ Yes, I guess that is best.