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
195 lines
5.5 KiB
Markdown
195 lines
5.5 KiB
Markdown
# 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](interp/typecheck.go) didn't recognize the new Moxie pointer-wrapped type categories (`ptrSliceT`, `ptrMapT`, `ptrChanT`).
|
|
|
|
#### Solution
|
|
**File**: [interp/typecheck.go](interp/typecheck.go)
|
|
**Lines**: 943-971
|
|
|
|
Extended `arrayDeref()` to handle Moxie pointer-wrapped types:
|
|
|
|
```go
|
|
// 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](interp/run.go)
|
|
**Lines**: 3341-3368
|
|
|
|
Added auto-dereferencing logic to `_cap()` function (matching existing `_len()` implementation):
|
|
|
|
```go
|
|
// 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](interp/cfg.go)
|
|
**Lines**: 1081-1113
|
|
|
|
Added a flag to skip integer index validation for maps:
|
|
|
|
```go
|
|
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](interp/run.go)
|
|
**Lines**: 1786-1851 (getIndexMap)
|
|
**Lines**: 1854-1910 (getIndexMap2)
|
|
|
|
Added auto-dereferencing logic to both functions:
|
|
|
|
```go
|
|
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](_test/phase_1_1_complete_test.go) demonstrating all features.
|
|
|
|
### Test Results
|
|
```bash
|
|
$ 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](interp/typecheck.go)** - Extended `arrayDeref()` for Moxie types
|
|
2. **[interp/cfg.go](interp/cfg.go)** - Fixed map index validation
|
|
3. **[interp/run.go](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!
|