]> ocean-lang.org Git - ocean-D/commitdiff
updates
authorNeilBrown <neil@brown.name>
Tue, 9 Nov 2021 07:53:40 +0000 (18:53 +1100)
committerNeilBrown <neil@brown.name>
Tue, 9 Nov 2021 07:53:40 +0000 (18:53 +1100)
00-TODO
Blog-pointers
Ocean-functions
Ocean-operators
Ocean-references [new file with mode: 0644]

diff --git a/00-TODO b/00-TODO
index 5675fdb226b41beb48c4ba1f0111494811589e7c..ac474b28506bfa2ff427392fd1a5c566284d59d6 100644 (file)
--- a/00-TODO
+++ b/00-TODO
@@ -23,7 +23,6 @@ Current version (Cataract Creek)
      << >> #
      bit-ops & | ~ &~
      op=
      << >> #
      bit-ops & | ~ &~
      op=
-- split values so I can have an array of just the value (1 byte for u8)
 - integers, unsigned, bitfield, float, double?
 - pointers
    - owned or borrowed
 - integers, unsigned, bitfield, float, double?
 - pointers
    - owned or borrowed
@@ -36,7 +35,6 @@ Current version (Cataract Creek)
 
 - allow "do stuff" as a stand-alone statement (scope)
 - 'use' labels *must* appear in case statements.
 
 - allow "do stuff" as a stand-alone statement (scope)
 - 'use' labels *must* appear in case statements.
-- re-read parsergen lit-doc and make sure it is still coherent.
 
 Next version (Govetts Creek):
 - functions and procedures
 
 Next version (Govetts Creek):
 - functions and procedures
index 372efc66b0ef889252e5f4fd610b9db42dff06ae..2539232ddae05443b331b93e01e327ac716f7311 100644 (file)
@@ -167,7 +167,7 @@ Rust uses smart pointers to implement
  others.
 It even has Box<> to create on heap instead of stack.
 
  others.
 It even has Box<> to create on heap instead of stack.
 
-Why doesn't I just do that?  Partly because I don't have classes yet!!
+Why don't I just do that?  Partly because I don't have classes yet!!
 
 I like a simple syntax to test if a pointer is over-loaded.
    if pointer?
 
 I like a simple syntax to test if a pointer is over-loaded.
    if pointer?
@@ -241,3 +241,30 @@ or better
 
   fun foo<x:thing>(a:x, b:x) : x
 
 
   fun foo<x:thing>(a:x, b:x) : x
 
+------------------------
+Years later - March 2021
+
+I need somewhere to start so I need to be able to ignore lots of this detail.
+So in the first instance all references are counted references.  They must refer
+to a struct that contains 'refcount'.
+
+A reference is declared with
+   name : ref base-type
+and the base object can be accessed with
+   name.ref
+though this can sometimes be inferred from "name".
+In particular
+   name.foo
+will find 'foo' either as an attribute of name, or of what name refers to.
+If name refers to a reference, this recurses.
+
+A ref can be checked with "name.valid"
+
+A new object can be allocated with "name.new()", which returns the ref.
+So "name.new().valid" is true if the allocation succeeded, which is always
+will on Linux.
+
+Future ideas might include:
+  type name : ref(attr,list) basetype
+where attr,list can include borrow,counted,single, etc
+
index 9014d1adc9b26d9d057c3d6d9361046db713acc8..50834001635905cb15e345b353f972f39ea1f280 100644 (file)
@@ -1,8 +1,9 @@
-I want to add functions and procedures soon.  I should decide on syntax at least.
+I want to add functions and procedures soon.  I should decide on syntax
+at least.
 
 
-The args to a function are effective a struct, so I want it to look the same.
-C doesn't allow "int a, b, c" in the parameters, which I think is clumsy.
-struct can be
+The args to a function are effectively a struct, so I want it to look
+the same.  C doesn't allow "int a, b, c" in the parameters, which I
+think is clumsy.  struct can be
 
   struct name:
      a,b,c:number
 
   struct name:
      a,b,c:number
@@ -13,7 +14,7 @@ So function might be
    func name:
        arg1, arg2: type
        arg3: type2
    func name:
        arg1, arg2: type
        arg3: type2
-   returns type
+   return type
    do:
        stuff
 
    do:
        stuff
 
@@ -22,16 +23,82 @@ it has a return structure.  So many C functions have 'ret' or 'result'
 variable that it might be nice to follow the Pascal approach of
 assigning to the function name??  or having
 
 variable that it might be nice to follow the Pascal approach of
 assigning to the function name??  or having
 
-    func name:
+    func name
        args:types
        args:types
-    returns:
+    return
        results:types
        results:types
-    do:
+    do
        statements
 
 A shorter version would be
 
     func name(args:types;args:types):type { }
 or
        statements
 
 A shorter version would be
 
     func name(args:types;args:types):type { }
 or
-    proc name(args:types;args:types):(result:type;...) {}
+    func name(args:types;args:types):(result:type;...) {}
 
 
+
+Can arguments be optional?
+ - yes, if "= value" follows the type
+Can we have variable number of args
+ - yes. Any arg can be an inline-array. The last arg can
+   have undefined length [].
+Can named args be passed in
+ - yes, once I have a syntax for manifest structs
+   
+Arrays seem very different from structs.
+ - they don't have names (as types)
+ - they don't need grouping in function params??
+Does this make any sense?
+Maybe I should require the grouping
+  printf("%d %d %d", (1,2,3))
+??
+
+
+Functions can be used before being declared - analysis happens after all is read.
+
+'main' is given an array of strings of unknown length.
+So I need the formal parameter to accept variable-length arrays.
+Do I use
+   argv:[] string
+and support "argv.len", or do I use
+   argv:[argc] string
+which instantiates argc with the length?
+Probably the latter.
+
+Arrays have to be passed by reference, they are const if :: used for type.
+Structs .. ditto.
+Strings and numbers are immutable.
+
+So I need functions to turn strings into number or bool.
+Just bool() and number() for now.
+So
+DONE 1/ change 'program' to make everything a string, and use functions to get numbers.
+DONE 2/ change 'program' to receive an array with bindably size
+DONE 3/ change 'program' to 'func main' etc
+DONE4/ allow more functions.
+
+What syntax to use for formal types?
+I will need type parameterisation some day.  For now I just need the
+size of an array to be parameterised.
+  argv:[argc]string
+looks like normal type.  But it isn't clear if argc is a global constant
+or a variable.
+  argv:[argc:int]string
+seem redunant because of course the array index is an int.
+  argv:[argc:]string
+might be acceptable.
+It is like leaving out the type is
+   a := 4
+
+So let's go with that.
+
+
+DONE To handle functions, and recursion in particular, I need a concept of a
+stack frame in the interpreter.  This needs to include room for
+parameters and results and local variables.  So a function needs to know
+the size of its frame, and each variable needs an offset.
+So I need to switch 'program' over to this approach before adding
+functions.
+Then the function frame will have a results frame separate from the
+main frame, as it can last longer.  So each variable needs to be marked
+as 'result' or not.
index d70058b19df36c9832cc463ab6f9b2cd4bf8aeeb..a2b1ef90788d1d53ef0992c203daf51a927394eb 100644 (file)
@@ -9,7 +9,7 @@ I might want:
 
  Binary: and then, or else, integer division
  Prefix: int
 
  Binary: and then, or else, integer division
  Prefix: int
- Suffix: dereference
+ Suffix: dereference (ref)
 
 
  Do I want  COND ? IFTRUE : IFFALSE
 
 
  Do I want  COND ? IFTRUE : IFFALSE
@@ -59,7 +59,7 @@ I might want:
       a @@= b
    does a deep copy
 
       a @@= b
    does a deep copy
 
-What types do operators act one?
+What types do operators act on?
 
    numbers  + - * / %
    bitsets  & | ~ &~
 
    numbers  + - * / %
    bitsets  & | ~ &~
@@ -123,3 +123,43 @@ But ... what syntax do I want for test-and-set?  More genericly cmpxchg.
 An operator that modifies a variable is something I wanted to avoid.
   var ? oldval = newval
 could 'use false' if it fails.
 An operator that modifies a variable is something I wanted to avoid.
   var ? oldval = newval
 could 'use false' if it fails.
+
+# decided so far:
+
+  +            addition or abs value
+  -            subtraction or negation
+  *            multiply
+  /            div
+  %            remainder
+  ++           catentate
+  ()           group
+  if else      conditional
+  and, or, not  Boolean
+  and then     Boolean
+  or else      Boolean
+  =             assignment
+  :             type
+  < > != == <= >=  comparison
+  [ ]           array access
+  .             field access
+  " ' `         quoting
+  , ;           list
+  {  }          grouping
+
+# expect
+  &            bit and
+  |            bit or
+  &^           bit subtract
+  ^            bit invert (prefix or infix)
+  #             1<< (prefix)
+  << >>         shift
+
+  += -= *= /= %= ++= &= |= &^= ^=
+        What about boolean? and=?
+        if c: a=True // if not c: a=False
+  
+# undecided
+  ?  !  @ $ \ ~
+  -- ** @@ ^^
+
+  Equiv of "a ?: b".  i.e. a if a else b.  Only works if non-Bools can be tested.
diff --git a/Ocean-references b/Ocean-references
new file mode 100644 (file)
index 0000000..42391e2
--- /dev/null
@@ -0,0 +1,95 @@
+References can be 'owned' or 'borrowed'.
+They can also be 'shared' or 'exclusive'
+And maybe I need 'const' as well??
+
+Borrowed references need to be borrowed from somewhere, and it must be
+clear where.
+- from a caller via function parameter passing
+- from a data structure via a lookup function - if structure is
+  append-only
+- from a lock - which asserts ownership while held
+
+Owned references can be:
+  refcounted - are these borrowed from the refcount?
+  single - there is only ever one owner
+The difference is that 'single' uses zero bits for the refcount.
+So maybe if a structure has a field declared 'refcount' it is 
+refcounted, else it can only be 'single'.
+
+A pointer is declared as
+    name: @type
+Attributes can appear afterwards
+    name: @type owned shared
+
+ownership is transferred using
+     new := *old (??)
+This nulls the variable or marks it invalid.
+An assignment like
+     new : @type = old
+will create a new owned reference and is only permitted for refcounted
+
+Owned references are dropped when they are replaced or go out of scope.
+This results in a dec of refcount and possible a free - or "close" once
+I have objects.
+
+When a reference is borrowed I need to know where it is borrowed from.
+The owner can be some other (complex) object or the call stack.
+It might be some set of objects if we don't know for certain.
+
+
+What are some difficult pointer usages that need clear understanding.
+
+1/ linked lists and trees are easy.  The link is owned.
+2/ double-linked lists have two problems.
+  A/ The 'prev' link cannot be owned - so who is it borrowed from?
+  B/ The tail link back to the header.
+
+The links aren't where the ownership resides.  The ownership resides in
+the total data structure - the list.
+The list - represented by the head - owns the references to all members.
+The pointers are just record keeping.
+
+Pointers *can* store ownership, but they are just one option.
+A function can declare that some ownership is stored or released
+without the language being able to confirm it.
+
+I need to write some code to explore what I want.
+
+A ref is dereferenced with '@', but it can be left off if there is a field
+reference, so "ref@.foo" and "ref.foo" are the same.
+
+ref@new allocates a new object
+ref@valid is true if the ref points to something
+ref@drop drops the ref and invalidates the pointer ??
+
+Maybe
+    foo:@type = @new()
+    foo = @null
+
+    foo?
+
+
+
+----
+I wonder if I want user-defined reference attributes.
+This would require generic support in the language.
+The idea is that the language gurantees some simple properties
+and the code provie the manipulations.
+
+So the "owned" attribute is declared as 'single' meaning it isn't
+copied with the pointer.  However it can be explicitly copied
+by a "get_ref" function which returns an 'owned' flag without consuming one.
+
+Some attributes would be "sticky" meaning they follow a value around.
+"mut" or "ro" would be like this.
+Some fields in an object may only be accessed or changed by a method,
+which may explicitly change flags.
+"ro" might prevent updates, "mut" might permit them, "hidden" might
+prevent all accesses, or "xray" might be needed to see anything.
+
+Attributes could define trigger functions which are called in
+certain circumstances.
+"owned" might call free() when the value goes out of scope without being consumed.
+
+Tracking the connection between "owned" and "borrowed" might be
+tricky.  I need some code to play with.