LL1 Memory Pattern

new topic     » topic index » view thread      » older message » newer message

LL1 Memory Pattern. Safe and Scalable Object-like Structures Using eumem

Author: Ronald Weidner

This post summarizes a design pattern discussion I had while building an LL(1) token stream structure in OpenEuphoria. The goal was to build a reusable, memory-safe, pointer-driven object without needing full OOP. The result was a fully testable, efficient, and idiomatic structure using ''eumem''.

Why This Pattern?

Euphoria passes everything by value. This means that without explicit handling, all state is copied, mutated in isolation, and discarded unless reassigned. To simulate pass-by-reference structures, I built a reusable LL(1) stream backed by ''eumem''.

This design allows:

  • Pointer-based memory
  • Shared state between procedures
  • Explicit free and lifecycle control
  • Type-safe tagging
  • Struct-like layouts

The Layout

enum 
    __TYPE__,       -- must be first 
    LL1_INDEX,      -- current stream position 
    LL1_DATA,       -- sequence of tokens 
    __MYSIZE__      -- must be last 

constant LL1_ID = "LL1$T54yhwe%^%$^$@3yjhw@$%^" 

Each LL1 instance is created using:

public function new(sequence tokens) 
    return eumem:malloc({LL1_ID, 1, tokens, SIZEOF_LL1}) 
end function 

And type validation is performed with:

public type LL1(atom ptr) 
    if eumem:valid(ptr, __MYSIZE__) then 
        if equal(eumem:ram_space[ptr][__TYPE__], LL1_ID) then 
            return 1 
        end if 
    end if 
    return 0 
end type 

Safe for Multiple Instances

You do not need a dynamic ID. Every LL1 object shares the same ''LL1_ID''. That tag is not for uniqueness. It's for type validation. Each call to ''new()'' creates a new memory block with its own pointer, index, and token list. They're separate instances, but all valid for ''type LL1''.

What Happens on Free?

When calling:

LL1:free(ptr) 

All internal fields, including ''LL1_INDEX'', are erased. ''eumem:free()'' deletes the entire struct. After that:

  • ''eumem:valid(ptr, MYSIZE)'' will return 0
  • ''type LL1(ptr)'' will fail
  • Accessing the freed pointer will result in garbage or error

The caller is responsible for setting the pointer to NULL if needed.

Why This Matters

This pattern has proven valuable in:

  • FreeBASIC
  • C
  • Now Euphoria

It's simple, scales well, and allows for object-like design without embracing full OOP or class inheritance.

You can use this for:

  • ASTs
  • Tokenizers
  • Stacks
  • Symbol tables
  • Virtual machines
  • Dynamic data structures

Final Thought

Euphoria gives you enough control to simulate objects, but not enough to hide from responsibility. This pattern bridges the gap. It's clean, performant, and honest.

Thanks for reading. I would love to hear how others have solved pass-by-reference or struct emulation in their own projects.

Ronald Weidner

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu