Files
moxa/phase-1.1-progress.md
mleku b974bb23ea
Some checks failed
Build Cross OS / Go (/go, oldstable, macos-latest) (push) Has been cancelled
Build Cross OS / Go (/go, oldstable, ubuntu-latest) (push) Has been cancelled
Build Cross OS / Go (/go, stable, macos-latest) (push) Has been cancelled
Build Cross OS / Go (/go, stable, ubuntu-latest) (push) Has been cancelled
Build Cross OS / Go (\go, oldstable, windows-latest) (push) Has been cancelled
Build Cross OS / Go (\go, stable, windows-latest) (push) Has been cancelled
Main / Linting (push) Has been cancelled
Main / Checks code and generated code (oldstable) (push) Has been cancelled
Main / Checks code and generated code (stable) (push) Has been cancelled
Main / Build and Test (oldstable) (push) Has been cancelled
Main / Build and Test (stable) (push) Has been cancelled
implement 1.1 explicit collection type pointers
2025-11-22 09:58:03 +00:00

7.9 KiB

Phase 1.1 Implementation Progress

Summary

This document tracks the progress of implementing Phase 1.1: Explicit Pointer Types for Reference Types in the Moxa interpreter.

Completed Work

1. Type System Foundation

  • Added new type categories to interp/type.go:
    • ptrSliceT - Represents *[]T
    • ptrMapT - Represents *map[K]V
    • ptrChanT, ptrChanSendT, ptrChanRecvT - Represents *chan T variants
  • Updated cats string array for new types
  • Modified ptrOf() function to convert slice/map/chan types to pointer-wrapped variants when & is applied

2. Reflection Type Support

  • Updated refType() method in interp/type.go to handle pointer-wrapped types
  • Updated frameType() method to support new types
  • Updated isComplete() function to check completeness of new pointer types

3. Composite Literal Support

  • Updated interp/cfg.go to handle pointer-wrapped types in:
    • compositeLitExpr cases (lines 1457-1460)
    • compositeGenerator function (lines 2976-2979)
    • Range statement handling for maps and slices (lines 183, 202)
  • Updated interp/gta.go to handle new types in definedType() (line 448, 453)
  • Updated interp/generic.go for generic type inference (lines 228, 231)

4. Runtime Support for Literals

  • Modified arrayLit() in interp/run.go to create pointer-wrapped slices
    • Handles *[]T by creating a pointer to a slice
    • Auto-dereferencing for element assignment
  • Modified mapLit() in interp/run.go to create pointer-wrapped maps
    • Handles *map[K]V by creating a pointer to a map
    • Auto-dereferencing for element assignment

5. Address and Dereference Operations

  • Separated addressExpr and starExpr handling in interp/type.go:
    • addressExpr (&): Creates pointer-wrapped types via ptrOf()
    • starExpr (*): Dereferences pointer-wrapped types back to value types

Current Status

Working

  • Creating pointer-wrapped slices: s := &[]int{1, 2, 3}
  • Creating pointer-wrapped maps: m := &map[string]int{"a": 1}
  • Printing pointer-wrapped types

In Progress 🚧

  • Dereferencing pointer-wrapped types: deref := *s
    • Type creation works at compile-time
    • Runtime assignment fails with type mismatch error
    • Issue: Newly created itype for dereferenced type doesn't have proper reflection type set

Known Issues

1. Type Mismatch on Dereference Assignment

Location: interp/type.go

Problem: When dereferencing *s where s is *[]int, we create a new sliceT itype, but it doesn't have the proper rtype field set, causing runtime type mismatches.

Error:

reflect.Set: value of type []int is not assignable to type int

Root Cause: The newly created itype in starExpr case doesn't go through proper type initialization that sets up reflection types.

Potential Solutions:

  1. Use existing slice/map/chan types from scope instead of creating new ones
  2. Call proper type initialization after creating new itype
  3. Use sliceOf/mapOf/chanOf functions with options to create dereferenced types

Next Steps

High Priority

  1. Fix starExpr dereference type creation

    • Ensure proper rtype initialization
    • Consider using existing types or proper constructor functions
  2. Implement auto-dereferencing for indexing

    • Modify indexing operations in interp/run.go
    • s[i] should work on *[]int by auto-dereferencing
    • m[k] should work on *map[K]V by auto-dereferencing
  3. Update built-in functions

    • len() and cap() should work on *[]T
    • Handle auto-dereferencing in built-in function implementations

Medium Priority

  1. Channel support

    • Implement composite literal syntax for channels: &chan T{cap: n}
    • This will require parser changes for the new syntax
  2. Range statement auto-dereferencing

    • for x := range s should work on *[]T
    • Already partially implemented, needs testing
  3. Comprehensive testing

    • Test all operations with pointer-wrapped types
    • Test nil pointer handling
    • Test type compatibility and conversions

Files Modified

Core Type System

  • interp/type.go - Added new type categories, updated ptrOf(), separated address/star expr handling
    • Lines 28-32: New type categories
    • Lines 246-273: Modified ptrOf()
    • Lines 453-492: Separated addressExpr and starExpr

Configuration and Parsing

  • interp/cfg.go - Updated composite literal and range handling
    • Lines 183, 202: Range statement updates
    • Lines 1457-1460: Composite literal type checking
    • Lines 2976-2979: Composite generator

Runtime Execution

  • interp/run.go - Updated literal creation functions
    • Lines 2546-2570: arrayLit() for pointer-wrapped slices
    • Lines 2580-2612: mapLit() for pointer-wrapped maps

Type Analysis

  • interp/gta.go - Updated type definition checking
    • Lines 448, 453: Handle new pointer types

Generic Type Inference

  • interp/generic.go - Updated type inference
    • Lines 228, 231: Handle pointer-wrapped types in inference

Testing

Test Files Created

Test Results

# Creating pointer-wrapped types works:
go run ./cmd/yaegi _test/simple_test.go
# Output: Slice created: &[1 2 3]
#         Test completed!

# Dereferencing has issues (needs fix):
# Error: reflect.Set: value of type []int is not assignable to type int

Architecture Notes

Type Conversion Flow

  1. User writes: s := &[]int{1, 2, 3}
  2. Parser creates: compositeLitExpr with arrayType wrapped in addressExpr
  3. Type resolution:
    • arrayType (no length) → sliceOf()sliceT
    • addressExprptrOf(sliceT)ptrSliceT
  4. Code generation: arrayLit() creates *[]int value
  5. Runtime: Stores pointer to slice in variable

Deference Flow (Currently Broken)

  1. User writes: deref := *s
  2. Parser creates: starExpr wrapping identifier s
  3. Type resolution:
    • s has type ptrSliceT
    • starExpr should convert to sliceT
    • BUG: Created sliceT doesn't have proper rtype
  4. Runtime: Type mismatch when assigning

Design Decisions

Why Separate ptrSliceT instead of using ptrT?

Using separate categories (ptrSliceT, ptrMapT, etc.) instead of generic ptrT allows:

  • Clearer type distinction in Moxie semantics
  • Easier implementation of auto-dereferencing
  • Better error messages
  • Direct access to key/val types for maps without extra indirection

Why Modify ptrOf() instead of sliceOf()?

Keeping sliceOf(), mapOf(), chanOf() creating non-pointer types and using ptrOf() to wrap them ensures:

  • &[]int{...} syntax works naturally (address operator wraps the slice type)
  • Type constructors remain simple
  • Pointer wrapping is explicit in the code flow

Performance Considerations

Memory Impact

  • Pointer-wrapped types add one level of indirection
  • Reflection type creation might have slight overhead
  • Overall impact should be minimal for most code

Runtime Impact

  • Auto-dereferencing adds minimal overhead (one pointer dereference)
  • Composite literal creation slightly more complex
  • Type checking remains O(1) with category-based switches

Future Work (Post Phase 1.1)

  • Phase 1.2: Remove platform-dependent integer types (int, uint)
  • Phase 2.1: Mutable strings as *[]byte
  • Phase 2.2: Concatenation operator |
  • Phase 3: Built-in function modifications

References