Skip to content

Commit

Permalink
vm/memory: use a enum-style type tag for MemoryValue (#315)
Browse files Browse the repository at this point in the history
Fixes #309
  • Loading branch information
quasilyte authored Mar 19, 2024
1 parent 2f2a7cc commit 5951bfe
Showing 1 changed file with 31 additions and 23 deletions.
54 changes: 31 additions & 23 deletions pkg/vm/memory/memory_value.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,25 +74,32 @@ func (address MemoryAddress) String() string {
// - or a pointer to another Memory Cell (a `MemoryAddress`)
// both values share the same underlying memory, which is a f.Element
type MemoryValue struct {
felt f.Element
isFelt bool
isAddress bool
felt f.Element
kind memoryValueKind
}

type memoryValueKind uint8

const (
unknownMemoryValue memoryValueKind = iota
feltMemoryValue
addrMemoryValue
)

var UnknownValue = MemoryValue{}

func MemoryValueFromMemoryAddress(address *MemoryAddress) MemoryValue {
v := MemoryValue{
isAddress: true,
kind: addrMemoryValue,
}
*v.addrUnsafe() = *address
return v
}

func MemoryValueFromFieldElement(felt *f.Element) MemoryValue {
return MemoryValue{
felt: *felt,
isFelt: true,
felt: *felt,
kind: feltMemoryValue,
}
}

Expand All @@ -101,16 +108,16 @@ func MemoryValueFromInt[T constraints.Integer](v T) MemoryValue {
return MemoryValueFromUint(uint64(v))
}

value := MemoryValue{isFelt: true}
value := MemoryValue{kind: feltMemoryValue}
rhs := f.NewElement(uint64(-v))
value.felt.Sub(&value.felt, &rhs)
return value
}

func MemoryValueFromUint[T constraints.Unsigned](v T) MemoryValue {
return MemoryValue{
felt: f.NewElement(uint64(v)),
isFelt: true,
felt: f.NewElement(uint64(v)),
kind: feltMemoryValue,
}
}

Expand Down Expand Up @@ -142,54 +149,57 @@ func MemoryValueFromAny(anyType any) (MemoryValue, error) {

func EmptyMemoryValueAsFelt() MemoryValue {
return MemoryValue{
isFelt: true,
kind: feltMemoryValue,
}
}

func EmptyMemoryValueAsAddress() MemoryValue {
return MemoryValue{
isAddress: true,
kind: addrMemoryValue,
}
}

func EmptyMemoryValueAs(address bool) MemoryValue {
kind := feltMemoryValue
if address {
kind = addrMemoryValue
}
return MemoryValue{
isAddress: address,
isFelt: !address,
kind: kind,
}
}

func (mv *MemoryValue) MemoryAddress() (*MemoryAddress, error) {
if !mv.isAddress {
if !mv.IsAddress() {
return nil, errors.New("memory value is not an address")
}
return mv.addrUnsafe(), nil
}

func (mv *MemoryValue) FieldElement() (*f.Element, error) {
if !mv.isFelt {
if !mv.IsFelt() {
return nil, fmt.Errorf("memory value is not a field element")
}
return &mv.felt, nil
}

func (mv *MemoryValue) Any() any {
if mv.isAddress {
if mv.IsAddress() {
return mv.addrUnsafe()
}
return &mv.felt
}

func (mv *MemoryValue) IsAddress() bool {
return mv.isAddress
return mv.kind == addrMemoryValue
}

func (mv *MemoryValue) IsFelt() bool {
return mv.isFelt
return mv.kind == feltMemoryValue
}

func (mv *MemoryValue) Known() bool {
return mv.isAddress || mv.isFelt
return mv.kind != unknownMemoryValue
}

func (mv *MemoryValue) Equal(other *MemoryValue) bool {
Expand Down Expand Up @@ -247,8 +257,7 @@ func (mv *MemoryValue) subAddress(lhs *MemoryAddress, rhs *MemoryValue) error {
return fmt.Errorf("addresses are in different segments: rhs is in %d, lhs is in %d",
rhsAddr.SegmentIndex, lhs.SegmentIndex)
}
mv.isAddress = false
mv.isFelt = true
mv.kind = feltMemoryValue
mv.felt.SetUint64(lhs.Offset - rhsAddr.Offset)
return nil
}
Expand All @@ -261,8 +270,7 @@ func (mv *MemoryValue) subAddress(lhs *MemoryAddress, rhs *MemoryValue) error {
if rhs64 > lhs.Offset {
return fmt.Errorf("rhs %d is greater than lhs offset %d", rhs64, lhs.Offset)
}
mv.isAddress = true
mv.isFelt = false
mv.kind = addrMemoryValue
addrResult := mv.addrUnsafe()
addrResult.SegmentIndex = lhs.SegmentIndex
addrResult.Offset = lhs.Offset - rhs64
Expand Down

0 comments on commit 5951bfe

Please sign in to comment.