Skip to content

Commit

Permalink
chore: refactor to simplify functions for readability
Browse files Browse the repository at this point in the history
  • Loading branch information
tucats committed Dec 2, 2024
1 parent 9538aa4 commit a13754e
Show file tree
Hide file tree
Showing 11 changed files with 797 additions and 627 deletions.
60 changes: 34 additions & 26 deletions bytecode/equal.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,40 +89,48 @@ func equalByteCode(c *Context, i interface{}) error {
}

default:
// If type checking is set to strict, the types must match exactly.
if c.typeStrictness == defs.StrictTypeEnforcement {
if !data.TypeOf(v1).IsType(data.TypeOf(v2)) {
return c.error(errors.ErrTypeMismatch).
Context(data.TypeOf(v2).String() + ", " + data.TypeOf(v1).String())
}
} else {
// Otherwise, normalize the types to the same type.
v1, v2 = data.Normalize(v1, v2)
return genericEqualCompare(c, v1, v2)
}

return c.push(result)
}

func genericEqualCompare(c *Context, v1 interface{}, v2 interface{}) error {
var result bool

// If type checking is set to strict, the types must match exactly.
if c.typeStrictness == defs.StrictTypeEnforcement {
if !data.TypeOf(v1).IsType(data.TypeOf(v2)) {
return c.error(errors.ErrTypeMismatch).
Context(data.TypeOf(v2).String() + ", " + data.TypeOf(v1).String())
}
} else {
// Otherwise, normalize the types to the same type.
v1, v2 = data.Normalize(v1, v2)
}

if v1 == nil && v2 == nil {
result = true
} else {
// Based on the now-normalized types, do the comparison.
if v1 == nil && v2 == nil {
result = true
} else {
switch v1.(type) {
case nil:
result = false
switch v1.(type) {
case nil:
result = false

case byte, int32, int, int64:
result = data.Int64(v1) == data.Int64(v2)
case byte, int32, int, int64:
result = data.Int64(v1) == data.Int64(v2)

case float64:
result = v1.(float64) == v2.(float64)
case float64:
result = v1.(float64) == v2.(float64)

case float32:
result = v1.(float32) == v2.(float32)
case float32:
result = v1.(float32) == v2.(float32)

case string:
result = v1.(string) == v2.(string)
case string:
result = v1.(string) == v2.(string)

case bool:
result = v1.(bool) == v2.(bool)
}
case bool:
result = v1.(bool) == v2.(bool)
}
}

Expand Down
190 changes: 119 additions & 71 deletions bytecode/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,111 +253,55 @@ func storeViaPointerByteCode(c *Context, i interface{}) error {

// Get the value we are going to store from the stack. if it's
// a stack marker, there was no return value on the stack.
src, err := c.PopWithoutUnwrapping()
value, err := c.PopWithoutUnwrapping()
if err != nil {
return err
}

if isStackMarker(src) {
if isStackMarker(value) {
return c.error(errors.ErrFunctionReturnedVoid)
}

// Based on the type, do the store.
switch actual := dest.(type) {
// Based on the type of the destination pointer, do the store.
switch destinationPointer := dest.(type) {
case *data.Immutable:
return c.error(errors.ErrReadOnlyValue)

case *interface{}:
*actual = src
*destinationPointer = value

case *bool:
d := src
if c.typeStrictness > defs.RelaxedTypeEnforcement {
d = data.Coerce(src, true)
} else if _, ok := d.(string); !ok {
return c.error(errors.ErrInvalidVarType).Context(name)
}

*actual = d.(bool)
return storeBoolViaPointer(c, name, value, destinationPointer)

case *byte:
d := src
if c.typeStrictness > defs.RelaxedTypeEnforcement {
d = data.Coerce(src, byte(1))
} else if _, ok := d.(string); !ok {
return c.error(errors.ErrInvalidVarType).Context(name)
}

*actual = d.(byte)
return storeByteViaPointer(c, name, value, destinationPointer)

case *int32:
d := src
if c.typeStrictness > defs.RelaxedTypeEnforcement {
d = data.Coerce(src, int32(1))
} else if _, ok := d.(string); !ok {
return c.error(errors.ErrInvalidVarType).Context(name)
}

*actual = d.(int32)
return storeInt32ViaPointer(c, name, value, destinationPointer)

case *int:
d := src
if c.typeStrictness > defs.RelaxedTypeEnforcement {
d = data.Coerce(src, int(1))
} else if _, ok := d.(string); !ok {
return c.error(errors.ErrInvalidVarType).Context(name)
}

*actual = d.(int)
return storeIntViaPointer(c, name, value, destinationPointer)

case *int64:
d := src
if c.typeStrictness > defs.RelaxedTypeEnforcement {
d = data.Coerce(src, int64(1))
} else if _, ok := d.(string); !ok {
return c.error(errors.ErrInvalidVarType).Context(name)
}

*actual = d.(int64)
return storeInt64ViaPointer(c, name, value, destinationPointer)

case *float64:
d := src
if c.typeStrictness > defs.RelaxedTypeEnforcement {
d = data.Coerce(src, float64(0))
} else if _, ok := d.(string); !ok {
return c.error(errors.ErrInvalidVarType).Context(name)
}

*actual = d.(float64)
return storeFloat64ViaPointer(c, name, value, destinationPointer)

case *float32:
d := src
if c.typeStrictness > defs.RelaxedTypeEnforcement {
d = data.Coerce(src, float32(0))
} else if _, ok := d.(string); !ok {
return c.error(errors.ErrInvalidVarType).Context(name)
}

*actual = d.(float32)
return storeFloat32ViaPointer(c, name, value, destinationPointer)

case *string:
d := src
if c.typeStrictness > defs.RelaxedTypeEnforcement {
d = data.Coerce(src, "")
} else if _, ok := d.(string); !ok {
return c.error(errors.ErrInvalidVarType).Context(name)
}

*actual = d.(string)
return storeStringViaPointer(c, name, value, destinationPointer)

case *data.Array:
*actual, ok = src.(data.Array)
*destinationPointer, ok = value.(data.Array)
if !ok {
return c.error(errors.ErrNotAPointer).Context(name)
}

case **data.Channel:
*actual, ok = src.(*data.Channel)
*destinationPointer, ok = value.(*data.Channel)
if !ok {
return c.error(errors.ErrNotAPointer).Context(name)
}
Expand All @@ -369,6 +313,110 @@ func storeViaPointerByteCode(c *Context, i interface{}) error {
return nil
}

func storeStringViaPointer(c *Context, name string, src interface{}, destinationPointer *string) error {
d := src
if c.typeStrictness > defs.RelaxedTypeEnforcement {
d = data.Coerce(src, "")
} else if _, ok := d.(string); !ok {
return c.error(errors.ErrInvalidVarType).Context(name)
}

*destinationPointer = d.(string)

return nil
}

func storeFloat32ViaPointer(c *Context, name string, src interface{}, destinationPointer *float32) error {
d := src
if c.typeStrictness > defs.RelaxedTypeEnforcement {
d = data.Coerce(src, float32(0))
} else if _, ok := d.(string); !ok {
return c.error(errors.ErrInvalidVarType).Context(name)
}

*destinationPointer = d.(float32)

return nil
}

func storeFloat64ViaPointer(c *Context, name string, src interface{}, destinationPointer *float64) error {
d := src
if c.typeStrictness > defs.RelaxedTypeEnforcement {
d = data.Coerce(src, float64(0))
} else if _, ok := d.(string); !ok {
return c.error(errors.ErrInvalidVarType).Context(name)
}

*destinationPointer = d.(float64)

return nil
}

func storeInt64ViaPointer(c *Context, name string, src interface{}, actual *int64) error {
d := src
if c.typeStrictness > defs.RelaxedTypeEnforcement {
d = data.Coerce(src, int64(1))
} else if _, ok := d.(string); !ok {
return c.error(errors.ErrInvalidVarType).Context(name)
}

*actual = d.(int64)

return nil
}

func storeIntViaPointer(c *Context, name string, src interface{}, actual *int) error {
d := src
if c.typeStrictness > defs.RelaxedTypeEnforcement {
d = data.Coerce(src, int(1))
} else if _, ok := d.(string); !ok {
return c.error(errors.ErrInvalidVarType).Context(name)
}

*actual = d.(int)

return nil
}

func storeInt32ViaPointer(c *Context, name string, src interface{}, actual *int32) error {
d := src
if c.typeStrictness > defs.RelaxedTypeEnforcement {
d = data.Coerce(src, int32(1))
} else if _, ok := d.(string); !ok {
return c.error(errors.ErrInvalidVarType).Context(name)
}

*actual = d.(int32)

return nil
}

func storeByteViaPointer(c *Context, name string, src interface{}, actual *byte) error {
d := src
if c.typeStrictness > defs.RelaxedTypeEnforcement {
d = data.Coerce(src, byte(1))
} else if _, ok := d.(string); !ok {
return c.error(errors.ErrInvalidVarType).Context(name)
}

*actual = d.(byte)

return nil
}

func storeBoolViaPointer(c *Context, name string, src interface{}, actual *bool) error {
d := src
if c.typeStrictness > defs.RelaxedTypeEnforcement {
d = data.Coerce(src, true)
} else if _, ok := d.(string); !ok {
return c.error(errors.ErrInvalidVarType).Context(name)
}

*actual = d.(bool)

return nil
}

// storeAlwaysByteCode instruction processor. This function
// is used to store a value in a symbol table regardless of
// whether the value is readonly or protected.
Expand Down
Loading

0 comments on commit a13754e

Please sign in to comment.