From fb71b26483853b4e8198c3b5ca1c3f2ec554a800 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 9 Nov 2021 18:53:40 +1100 Subject: [PATCH] updates --- 00-TODO | 2 - Blog-pointers | 29 ++++++++++++++- Ocean-functions | 85 ++++++++++++++++++++++++++++++++++++++----- Ocean-operators | 44 +++++++++++++++++++++- Ocean-references | 95 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 241 insertions(+), 14 deletions(-) create mode 100644 Ocean-references diff --git a/00-TODO b/00-TODO index 5675fdb..ac474b2 100644 --- a/00-TODO +++ b/00-TODO @@ -23,7 +23,6 @@ Current version (Cataract Creek) << >> # 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 @@ -36,7 +35,6 @@ Current version (Cataract Creek) - 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 diff --git a/Blog-pointers b/Blog-pointers index 372efc6..2539232 100644 --- a/Blog-pointers +++ b/Blog-pointers @@ -167,7 +167,7 @@ Rust uses smart pointers to implement 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? @@ -241,3 +241,30 @@ or better fun foo(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 + diff --git a/Ocean-functions b/Ocean-functions index 9014d1a..5083400 100644 --- a/Ocean-functions +++ b/Ocean-functions @@ -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 @@ -13,7 +14,7 @@ So function might be func name: arg1, arg2: type arg3: type2 - returns type + return type 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 - func name: + func name args:types - returns: + return results:types - do: + do 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. diff --git a/Ocean-operators b/Ocean-operators index d70058b..a2b1ef9 100644 --- a/Ocean-operators +++ b/Ocean-operators @@ -9,7 +9,7 @@ I might want: Binary: and then, or else, integer division Prefix: int - Suffix: dereference + Suffix: dereference (ref) Do I want COND ? IFTRUE : IFFALSE @@ -59,7 +59,7 @@ I might want: a @@= b does a deep copy -What types do operators act one? +What types do operators act on? 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. + +# 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 index 0000000..42391e2 --- /dev/null +++ b/Ocean-references @@ -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. -- 2.43.0