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
- interp/typecheck.go - Extended
arrayDeref()for Moxie types - interp/cfg.go - Fixed map index validation
- 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!