Files
moxa/PHASE_1_1_FINAL_FIXES.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

5.5 KiB

Phase 1.1 Final Fixes - Session Summary

This document summarizes the final fixes applied to complete Phase 1.1 of the Moxie implementation.

🎯 Objective

Complete the remaining features for Phase 1.1: Explicit Pointer Types for Reference Types

  • Fix map auto-dereference indexing (m[k] on *map[K]V)
  • Fix built-in function auto-dereference (len(s), cap(s) on *[]T)

Fixes Applied

1. Built-in Function Auto-Dereference

Problem

len(s) and cap(s) were failing on pointer-wrapped slices with error: "invalid argument for len/cap"

Root Cause

The arrayDeref() function in interp/typecheck.go didn't recognize the new Moxie pointer-wrapped type categories (ptrSliceT, ptrMapT, ptrChanT).

Solution

File: interp/typecheck.go Lines: 943-971

Extended arrayDeref() to handle Moxie pointer-wrapped types:

// Moxie: Auto-dereference pointer-wrapped types
switch typ.cat {
case ptrSliceT:
    return sliceOf(typ.val)
case ptrMapT:
    return mapOf(typ.key, typ.val)
case ptrChanT:
    return chanOf(typ.val, chanSendRecv)
case ptrChanSendT:
    return chanOf(typ.val, chanSend)
case ptrChanRecvT:
    return chanOf(typ.val, chanRecv)
}

File: interp/run.go Lines: 3341-3368

Added auto-dereferencing logic to _cap() function (matching existing _len() implementation):

// Moxie: Auto-dereference pointer-wrapped types
if isPtr(n.child[1].typ) {
    val := value
    value = func(f *frame) reflect.Value {
        v := val(f).Elem()
        for v.Kind() == reflect.Ptr {
            v = v.Elem()
        }
        return v
    }
}

Result

len(s) and cap(s) now work on *[]T types Both compile-time type checking and runtime execution work correctly


2. Map Auto-Dereference Indexing

Problem

m["key"] was failing on pointer-wrapped maps with error: "index string must be integer"

Root Cause #1: Type Validation

The check.index() function was being called unconditionally for all indexing operations, including maps. This function validates that the index is an integer, which is correct for arrays/slices but wrong for maps.

Solution #1

File: interp/cfg.go Lines: 1081-1113

Added a flag to skip integer index validation for maps:

l := -1
isMapIndex := false
switch k := typ.Kind(); k {
// ... array/slice cases ...
case reflect.Ptr:
    typ2 := typ.Elem()
    switch typ2.Kind() {
    // ... array/slice cases ...
    case reflect.Map:
        // Moxie: Handle *map[K]V indexing
        isMapIndex = true
        err = check.assignment(n.child[1], t.key, "map index")
        n.gen = getIndexMap
    }
}

// Only validate integer index for arrays/slices/strings, not maps
if !isMapIndex {
    err = check.index(n.child[1], l)
}

Root Cause #2: Runtime Execution

After fixing type checking, runtime execution failed with: "reflect: call of reflect.Value.MapIndex on ptr Value"

The getIndexMap() and getIndexMap2() functions were trying to call MapIndex() on pointer values instead of dereferencing them first.

Solution #2

File: interp/run.go Lines: 1786-1851 (getIndexMap) Lines: 1854-1910 (getIndexMap2)

Added auto-dereferencing logic to both functions:

value0 := genValue(n.child[0]) // map
// Moxie: Auto-dereference pointer-wrapped maps
if isPtr(n.child[0].typ) {
    val := value0
    value0 = func(f *frame) reflect.Value {
        v := val(f).Elem()
        for v.Kind() == reflect.Ptr {
            v = v.Elem()
        }
        return v
    }
}

Result

m[k] now works on *map[K]V types Both type checking and runtime execution work correctly Map indexing with status (val, ok := m[k]) also works


🧪 Verification

Test File

Created _test/phase_1_1_complete_test.go demonstrating all features.

Test Results

$ go run ./cmd/yaegi _test/phase_1_1_complete_test.go

=== Slice Tests ===
✅ Auto-dereference indexing: s[0], s[1], s[4]
✅ Manual dereference: *s, (*s)[i]
✅ Built-in functions: len(s), cap(s)

=== Map Tests ===
✅ Auto-dereference indexing: m["x"], m["y"], m["z"]
✅ Manual dereference: (*m)["x"]
✅ Built-in functions: len(m)

🎉 All tests passing!

📊 Summary

Files Modified

  1. interp/typecheck.go - Extended arrayDeref() for Moxie types
  2. interp/cfg.go - Fixed map index validation
  3. interp/run.go - Added auto-dereference to _cap(), getIndexMap(), getIndexMap2()

Lines Changed

  • ~30 lines added across 3 files
  • Total Phase 1.1 implementation: ~350 lines modified across 6 files

Features Completed

Feature Before After
len(s) on *[]T Error Works
cap(s) on *[]T Error Works
m[k] on *map[K]V Error Works
val, ok := m[k] Error Works

🎉 Conclusion

Phase 1.1 is now 100% complete!

All core features of explicit pointer types for reference types are implemented and working:

  • Pointer-wrapped slices: *[]T
  • Pointer-wrapped maps: *map[K]V
  • Pointer-wrapped channels: *chan T
  • Composite literal creation: &[]T{...}, &map[K]V{...}
  • Manual dereferencing: *s, *m
  • Auto-dereferencing for indexing: s[i], m[k]
  • Auto-dereferencing for built-ins: len(), cap()
  • Full reflection support

The Moxa interpreter successfully implements the Moxie Phase 1.1 specification and is ready for Phase 1.2!