1. Updates on Eu 4.2.0

Hello,

I'm just curious if there has been any recent development on Euphoria 4.2.0?

new topic     » topic index » view message » categorize

2. Re: Updates on Eu 4.2.0

Icy_Viking said...

Hello,

I'm just curious if there has been any recent development on Euphoria 4.2.0?

I've been trying to put the memstruct feature through its paces and I've run into a few bugs with parsing and other runtime crashes that I need to sort out. I'm also still debating renaming the keywords for memstruct. I'm open to input and suggestions on this. Pretty sure it's a trivial change in the parser. If we eventually pull in Matt's OOEU to add classes, I'd definitely want to avoid his current "euclass" keyword and just use "class" instead.

Current Proposed
memstruct struct
memunion union
memtype typedef

I'm also trying to get a continuous integration environment set up using Docker and GitHub Actions so that we can have more regular release cycles. Ideally you'd be able to run something like docker run openeuphoria/euphoria-build:latest on your own machine to get a complete build, and GitHub would run the same thing on pushes and merges to verify the build was passing. Then when we tag new versions, it could package everything and publish it to the project's "Releases" page.

-Greg

new topic     » goto parent     » topic index » view message » categorize

3. Re: Updates on Eu 4.2.0

Hi

My 2 new pence worth - if the meanings follow C, then I have no problem - if it's significantly different then it could create confusion. ie if a struct in Euphoria can create a struct that C can use, then that's good. If you have to do much fiddling to get the eu struct to a c struct then that is not good. I take it the idea is to get direct insertion into C created DLLs?

Andy's probably wrapped it already anyway.

Cheers

Chris

new topic     » goto parent     » topic index » view message » categorize

4. Re: Updates on Eu 4.2.0

ChrisB said...

My 2 new pence worth - if the meanings follow C, then I have no problem - if it's significantly different then it could create confusion. ie if a struct in Euphoria can create a struct that C can use, then that's good. If you have to do much fiddling to get the eu struct to a c struct then that is not good. I take it the idea is to get direct insertion into C created DLLs?

Yes, that's the intent. Here's the introduction from the docs. You can read more here: Memory Structures

docs said...

Introduction

Writing Euphoria code to interact with the operating system or external libraries often requires communicating via data structures stored in memory. In addition to using peeks and pokes to read and write to memory locations, Euphoria programmers can also define structures that can be used to more easily read and write values from and into memory.

The conventions used are similar to those found in the C programming language, since that's the way the most commonly encountered structures are defined and meant to be used. This is meant to provide a familiar syntax to those who already know C, and also to make it easy to define and use memory structures.

I'd say the only thing "Euphorian" about the syntax is that we're avoiding the use of the asterisk * for pointer declarations, and instead using the literal keyword pointer. However, it seems Matt still chose to use an asterisk for dereferencing pointers, which I'm not fond of.

docs said...

Reading and assigning with pointers

A memstruct member that is itself a pointer has an additional way to be used. The normal assignment and reading operations deal with the value of the pointer itself. To access the value to which the pointer points, use an additional dot, then an asterisk:

memstruct PTR_TO_INT 
    pointer int a 
end memstruct 
 
atom ptr = allocate( sizeof( PTR_TO_INT ) ) 
ptr.PTR_TO_INT.a = allocate( sizeof( int ) ) 
 
ptr.PTR_TO_INT.a.* = 5 
ptr.PTR_TO_INT.a.* += 5 
 
? ptr.PTR_TO_INT.a.* -- prints 10 

I think I'd rather see this syntax go away and instead encourage use of peek() and poke(). Internally, we'd have to adapt the parser to account for memstructs the same way it does for sizeof(). Given the example above, this would probably require introducing some new routines for operating on values memory, like incr() as shown below.

--ptr.PTR_TO_INT.a.* = 5 
poke( ptr.PTR_TO_INT.a, 5 ) 
 
--ptr.PTR_TO_INT.a.* += 5 
incr( ptr.PTR_TO_INT.a, 5 ) 
 
--? ptr.PTR_TO_INT.a.* -- prints 10 
? peek( ptr.PTR_TO_INT.a ) 

I'm not trying to hide pointers from those who want to use them. But I feel like mixing in little bits of C breaks the syntax and readability of Euphoria code. Plus, using routines to do things like this may help people better understand what the code is supposed to be doing.

This seems clear to me. It says, "increment the value at ptr.PTR_TO_INT.a by a value of 5."

incr( ptr.PTR_TO_INT.a, 5 ) 

Where as this... uh... what's that asterisk for again? I guess it's adding 5 to something?

ptr.PTR_TO_INT.a.* += 5 

One thing I've gleaned from playing around with newer languages like Go, Rust, etc. is that they really love their punctuation-based and abbreviated-keyword syntax, to the point where a newcomer to the language can't make sense of what's going on without keeping a reference manual in their hand. The power of Euphoria, I believe, is that anyone can read the code out loud and make sense of it. I want to ensure we maintain this. I'm not sure we can lean hard on "the fastest" any more, but we can still promote "clean and readable" code.

Again, I'm open to suggestions. Changes like these may be worthwhile but will also take more time.

-Greg

new topic     » goto parent     » topic index » view message » categorize

5. Re: Updates on Eu 4.2.0

I like having the names changed from memstruct to struct and so on. I think it makes the coder easier to read. I also like the idea of using poke and peek in dealing with pointers.

new topic     » goto parent     » topic index » view message » categorize

6. Re: Updates on Eu 4.2.0

ghaberek said...

One thing I've gleaned from playing around with newer languages like Go, Rust, etc. is that they really love their punctuation-based and abbreviated-keyword syntax, to the point where a newcomer to the language can't make sense of what's going on without keeping a reference manual in their hand. The power of Euphoria, I believe, is that anyone can read the code out loud and make sense of it. I want to ensure we maintain this. I'm not sure we can lean hard on "the fastest" any more, but we can still promote "clean and readable" code.

I completely agree with this.

new topic     » goto parent     » topic index » view message » categorize

7. Re: Updates on Eu 4.2.0

ghaberek said...

I'm not trying to hide pointers from those who want to use them. But I feel like mixing in little bits of C breaks the syntax and readability of Euphoria code. Plus, using routines to do things like this may help people better understand what the code is supposed to be doing.

I believe Euphoria needs to copy some C++ ideas, like RAII and move-semantics, and hide the structs inside an object system, to keep the value semantics for the rest of the program

new topic     » goto parent     » topic index » view message » categorize

8. Re: Updates on Eu 4.2.0

acEduardo said...

I believe Euphoria needs to copy some C++ ideas

I've been doing some pretty deep digging on the Euphoria source code over the past year or so. I'm by no means an expert yet but I don't think much of that is necessary. Here are my thoughts.

acEduardo said...

like RAII

As I understand it, RAII is only concerned with stack-allocated objects that are holding heap-allocated resources, and ensuring those heap-allocated resources get released when the stack-allocated object goes out of scope. (Please correct me if I'm wrong.) However in Euphoria, everything (except the integer type) is already heap-allocated, and you can use delete_routine() as a "destructor" to release any associated resources. This is how things like map:new() and allocate_string() work.

One feature that could be beneficial here is a using syntax that guarantees the lifetime of an object. But, while this might be a nice feature to have, I think it would also have to come with some sort of tracing/profiling feature that could tell you where those references accumulated. I already ran into this trying to use maps with Euphoria MVC to the point where I made the mapdbg library to trace each allocation and then back-track where things didn't get cleaned up correctly.

Here's an example of what using might look like:

include std/machine.e 
 
sequence globalFoos = {} 
 
memstruct FooType 
    -- some data types here 
end memstruct 
 
function newFoo() 
    atom foo = allocate_data( sizeof(FooType) ) 
     
    return delete_routine( foo, "free" ) -- free foo when it goes out of scope 
end function 
 
procedure saveFoo( atom foo ) 
    globalFoos &= foo -- this will keep a reference to foo 
end procedure 
 
using atom myFoo = newFoo() do 
 
    saveFoo( myFoo ) 
 
end using -- tries to delete myFoo but a reference is held in globalFoos, so 
          -- it throws an error ("cannot delete myFoo: too many references") 
acEduardo said...

and move-semantics

Like I said, everything in Euphoria is heap-allocated. Objects are syntactically passed by value but they're actually passed by reference. The backend just hides the pointers from you. Objects are reference counted so values are automatically "moved" simply by being assigned to one variable when another goes out of scope. Only when an object is modified does it get copied, and for sequences that's always "shallow" copy (elements are ref'd by 1) not a "deep" copy (elements are also copied).

acEduardo said...

and hide the structs inside an object system to keep the value semantics for the rest of the program

So skip implementing memstruct and move straight to classes? That's not a terrible idea but it would scrap a bunch of existing work. I'm not opposed to it though. It also would get 4.2 out the door sooner. Do you have more thoughts on what that might look like? I guess it'd probably be similar to Python's struct library?

-Greg

new topic     » goto parent     » topic index » view message » categorize

9. Re: Updates on Eu 4.2.0

ghaberek said...
using atom myFoo = newFoo() do 
 
    saveFoo( myFoo ) 
 
end using -- tries to delete myFoo but a reference is held in globalFoos, so 
          -- it throws an error ("cannot delete myFoo: too many references") 

I think I'd prefer

atom myFoo = newFoo() 
saveFoo(myFoo) 
myFoo = cleanup(myFoo) -- tries to delete myFoo but a reference is held in globalFoos, so 
                       -- it throws an error ("cannot delete myFoo: too many references") 

Then you could do things like (in Phix/if Euphoria gets try/catch)

try 
   myFoo = cleanup(myFoo) -- (sets myFoo to NULL if all goes well) 
catch e 
   ... 
end try 

Of course you could make the myFoo = part optional/implicit, and/or invoke cleanup({myFoo,myOtherFoo,etc}), or maybe use delete(x,true) where the second parameter forces "last ref" checks

new topic     » goto parent     » topic index » view message » categorize

10. Re: Updates on Eu 4.2.0

ghaberek said...

As I understand it, RAII is only concerned with stack-allocated objects that are holding heap-allocated resources, and ensuring those heap-allocated resources get released when the stack-allocated object goes out of scope. (Please correct me if I'm wrong.)

I will have to disagree. RAII is a lifecycle management system for all objects in program memory. RAII uses stack context destruction discipline to call destructors for all objects, whether they are allocated in the stack or in the heap.

Since Euphoria operates with value semantics, RAII would be perfect for eliminating the garbage collector.

We could replace the allocation in heap arenas (managed by the garbage collector), with a region allocation system. Each region would be tied to the stack frame of the function that created it, and all objects created in that stack frame would be allocated to the region. Objects that escape function termination via return would be moved to the region of the stack frame above (move-semantics), and objects that are referenced at a sequence should be copied to the region of the sequence (copy-semantics). Coroutines would have their region allocated by the scheduler, so yields would not destroy the objects in use.

So Euphoria could deallocate the regions with a unique free() call when the stack frame is destroyed, and we can add a syntax for object destructors. Copy-on-write would still work the same, but each object pointer would have to carry with it a pointer to the region where it was created.

I believe that object destructors without a object system is incomplete, and object systems are very useful, so we could add a native object/class system for Euphoria.

I envision a object system that is a little different from what most mainstream OO languages have: It would have interfaces, abstract classes (partially implemented interfaces), concrete classes without class inheritance (new classes could only subtype existing classes by adding new constructors, i.e. a simple adapter/decorator system), properties and signals just like Qt MOC has.

ghaberek said...

So skip implementing memstruct and move straight to classes?

No, I believe that these two features are complementary to each other. Memstructs would become more powerful with classes, and classes could hide implementation details involving memstructs.

Yes, I dream of completely replacing my C/C++ code to use Euphoria in all my projects!

new topic     » goto parent     » topic index » view message » categorize

11. Re: Updates on Eu 4.2.0

ghaberek said...

Do you have more thoughts on what that might look like?

Yes I do, I'll send my drafts later. (I just haven't written a prototype because I don't have enough self-confidence :( )

new topic     » goto parent     » topic index » view message » categorize

12. Re: Updates on Eu 4.2.0

acEduardo said...

Since Euphoria operates with value semantics, RAII would be perfect for eliminating the garbage collector.

No, Euphoria operates with copy-on-write semantics. Euphoria is reference counted, with objects being freed when their reference count drops to zero, so there is no garbage collector, and hence no move-semantics.

Further, you cannot have objects on the stack. You can have a reference to an object (or an integer) on the stack, but it makes no sense whatsoever to create or permit a reference to such a transient memory area.

new topic     » goto parent     » topic index » view message » categorize

13. Re: Updates on Eu 4.2.0

Since I'm curious, is 4.2.0 any closer to coming out?

new topic     » goto parent     » topic index » view message » categorize

14. Re: Updates on Eu 4.2.0

Icy_Viking said...

Since I'm curious, is 4.2.0 any closer to coming out?

Pretty close, I think. My current focus has been a "light" overhaul of the documentation. And I've got MD5 and SHA224/SHA256 working for hash().

After that I need to merge the struct branch and rename the keywords from memstruct to just struct, etc.

Still trying to see if I can get it to not need the struct name in the dot notation, e.g. addr.STRUCT.member versus addr.member.

-Greg

new topic     » goto parent     » topic index » view message » categorize

15. Re: Updates on Eu 4.2.0

ghaberek said...
Icy_Viking said...

Since I'm curious, is 4.2.0 any closer to coming out?

Pretty close, I think. My current focus has been a "light" overhaul of the documentation. And I've got MD5 and SHA224/SHA256 working for hash().

After that I need to merge the struct branch and rename the keywords from memstruct to just struct, etc.

Still trying to see if I can get it to not need the struct name in the dot notation, e.g. addr.STRUCT.member versus addr.member.

-Greg

Sounds great Greg. Hope to see it soon!

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu