Skip to content

Commit

Permalink
types: use truthy() and display() instead of casting to str or bool
Browse files Browse the repository at this point in the history
This prevents needless struct wrapping plus forbids types not supporting string or bool lowering
  • Loading branch information
rpbeltran committed Dec 27, 2024
1 parent 87becc8 commit 8b3fc42
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 206 deletions.
40 changes: 10 additions & 30 deletions types/boolean.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,14 @@ func MakeBool(value bool) *PrimitiveBool {
return &PrimitiveBool{value}
}

func (boolean *PrimitiveBool) Display() string {
if boolean.value {
return "true"
} else {
return "false"
}
}

// Logical Operators

func (boolean *PrimitiveBool) And(other Primitive) (Primitive, error) {
if other_bool, err := other.CastImplicitBool(); err != nil {
return nil, fmt.Errorf("attempting to And: %w", err)
} else {
return &PrimitiveBool{boolean.value && other_bool.value}, nil
}
return &PrimitiveBool{boolean.value && other.Truthy()}, nil
}

func (boolean *PrimitiveBool) Or(other Primitive) (Primitive, error) {
if other_bool, err := other.CastImplicitBool(); err != nil {
return nil, fmt.Errorf("attempting to Or: %w", err)
} else {
return &PrimitiveBool{boolean.value || other_bool.value}, nil
}
return &PrimitiveBool{boolean.value || other.Truthy()}, nil
}

// Non logical Operators
Expand Down Expand Up @@ -123,25 +107,21 @@ func (boolean *PrimitiveBool) CastImplicitNum() (*PrimitiveNum, error) {
return nil, fmt.Errorf("bool %q used where number-like required", boolean.Display())
}

func (boolean *PrimitiveBool) CastImplicitStr() (*PrimitiveStr, error) {
return nil, fmt.Errorf("bool %q used where string-like required", boolean.Display())
}

func (boolean *PrimitiveBool) CastImplicitBool() (*PrimitiveBool, error) {
return boolean, nil
}

func (boolean *PrimitiveBool) CastExplicitNum() (*PrimitiveNum, error) {
if boolean.value {
return &PrimitiveNum{*big.NewRat(1, 1)}, nil
}
return &PrimitiveNum{*big.NewRat(0, 1)}, nil
}

func (boolean *PrimitiveBool) CastExplicitStr() (*PrimitiveStr, error) {
return &PrimitiveStr{boolean.Display()}, nil
func (boolean *PrimitiveBool) Display() string {
if boolean.value {
return "true"
} else {
return "false"
}
}

func (boolean *PrimitiveBool) CastExplicitBool() (*PrimitiveBool, error) {
return boolean, nil
func (boolean *PrimitiveBool) Truthy() bool {
return boolean.value
}
44 changes: 13 additions & 31 deletions types/boolean_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,6 @@ import (
"testing"
)

func TestBoolDisplay(t *testing.T) {
if actual := MakeBool(true).Display(); actual != "true" {
t.Fatalf("MakeBool(true).Display() returned %q, expected %q", actual, "true")
}
if actual := MakeBool(false).Display(); actual != "false" {
t.Fatalf("MakeBool(false).Display() returned %q, expected %q", actual, "false")
}
}

// Test logical operators

type binop_bool_test_case struct {
Expand Down Expand Up @@ -202,16 +193,6 @@ func TestBoolCastImplicit(t *testing.T) {
if value, err := MakeBool(true).CastImplicitNum(); err == nil {
t.Fatalf("MakeBool(true).CastNum() gave %v, expected to fail with an error:", value)
}

if value, err := MakeBool(true).CastImplicitStr(); err == nil {
t.Fatalf("MakeBool(true).CastStr() gave %v, expected to fail with an error:", value)
}

if actual, err := MakeBool(false).CastImplicitBool(); err != nil {
t.Fatalf("MakeBool(false).CastBool() failed with error: %v", err)
} else if actual.value {
t.Fatalf("MakeBool(false).CastBool() gave true, expected false")
}
}

func TestBoolCastExplicit(t *testing.T) {
Expand All @@ -226,22 +207,23 @@ func TestBoolCastExplicit(t *testing.T) {
} else if actual := value.Display(); actual != "0" {
t.Fatalf("MakeBool(false).CastNum() returned %s, expected 0", actual)
}
}

if value, err := MakeBool(true).CastExplicitStr(); err != nil {
t.Fatalf("MakeBool(true).CastStr() returned the error %v but should have succeeded", err)
} else if actual := value.Display(); actual != "true" {
t.Fatalf("MakeBool(true).CastNum() returned %s, expected %q", actual, "true")
func TestBoolDisplay(t *testing.T) {
if actual := MakeBool(true).Display(); actual != "true" {
t.Fatalf("MakeBool(true).Display() returned %q, expected %q", actual, "true")
}
if actual := MakeBool(false).Display(); actual != "false" {
t.Fatalf("MakeBool(false).Display() returned %q, expected %q", actual, "false")
}
}

if value, err := MakeBool(false).CastExplicitStr(); err != nil {
t.Fatalf("MakeBool(false).CastStr() returned the error %v but should have succeeded", err)
} else if actual := value.Display(); actual != "false" {
t.Fatalf("MakeBool(false).CastNum() returned %s, expected %q", actual, "false")
func TestTruthy(t *testing.T) {
if MakeBool(false).Truthy() {
t.Fatalf("MakeBool(false).Truthy() gave true, expected false")
}

if actual, err := MakeBool(false).CastExplicitBool(); err != nil {
t.Fatalf("MakeBool(false).CastBool() failed with error: %v", err)
} else if actual.value {
t.Fatalf("MakeBool(false).CastBool() gave true, expected false")
if !MakeBool(true).Truthy() {
t.Fatalf("MakeBool(true).Truthy() gave false, expected true")
}
}
20 changes: 4 additions & 16 deletions types/numbers.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ func MakeNumber(value string) (*PrimitiveNum, error) {
return &PrimitiveNum{num}, nil
}

func (num *PrimitiveNum) Display() string {
return utils.EncodeNum(&num.value)
}

// Operators

func (num *PrimitiveNum) Add(other Primitive) (Primitive, error) {
Expand Down Expand Up @@ -217,22 +213,14 @@ func (num *PrimitiveNum) CastImplicitNum() (*PrimitiveNum, error) {
return num, nil
}

func (num *PrimitiveNum) CastImplicitStr() (*PrimitiveStr, error) {
return &PrimitiveStr{num.Display()}, nil
}

func (num *PrimitiveNum) CastImplicitBool() (*PrimitiveBool, error) {
return MakeBool(num.value.Num().BitLen() != 0), nil
}

func (num *PrimitiveNum) CastExplicitNum() (*PrimitiveNum, error) {
return num, nil
}

func (num *PrimitiveNum) CastExplicitStr() (*PrimitiveStr, error) {
return &PrimitiveStr{num.Display()}, nil
func (num *PrimitiveNum) Display() string {
return utils.EncodeNum(&num.value)
}

func (num *PrimitiveNum) CastExplicitBool() (*PrimitiveBool, error) {
return MakeBool(num.value.Num().BitLen() != 0), nil
func (num *PrimitiveNum) Truthy() bool {
return num.value.Num().BitLen() != 0
}
65 changes: 19 additions & 46 deletions types/numbers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,6 @@ func makeNumOrFail(value string, t *testing.T) *PrimitiveNum {
return num
}

func TestNumDisplay(t *testing.T) {
basic_test_cases := []string{"123", "0", "-123", "0.12345", "-0.102"}
for _, tc := range basic_test_cases {
if actual := makeNumOrFail(tc, t).Display(); actual != tc {
t.Fatalf("makePrimitiveNumber(%q).Display() returned %q, expected %q", tc, actual, tc)
}
}

big_input := "1.23e+123"
equivalent := "123" + strings.Repeat("0", 121)
if actual := makeNumOrFail(big_input, t).Display(); actual != equivalent {
t.Fatalf("makePrimitiveNumber(%q).Display() returned %q, expected %q", big_input, actual, equivalent)
}
}

func TestNumNonArithmetic(t *testing.T) {
if actual, err := makeNumOrFail("100", t).Concatenate(makeNumOrFail("100", t)); err == nil {
t.Fatalf("100 + 100 should have errored but instead succeeded and returned %s", actual.Display())
Expand Down Expand Up @@ -370,25 +355,6 @@ func TestNumCastImplicit(t *testing.T) {
} else if actual := val.Display(); actual != n {
t.Fatalf("PrimitiveNum().CastNum() returned %s, expected %s", actual, n)
}

if value, err := makeNumOrFail(n, t).CastImplicitStr(); err != nil {
t.Fatalf("PrimitiveNum().CastStr() returned the error %v but should have succeeded", err)
} else if actual := value.Display(); actual != n {
t.Fatalf("PrimitiveNum().CastStr() returned %s, expected %s", actual, n)
}

if val, err := makeNumOrFail("100", t).CastImplicitBool(); err != nil {
t.Fatalf("PrimitiveNum().CastBool() returned the error %v but should have succeeded", err)
} else if actual := val.Display(); actual != "true" {
t.Fatalf("PrimitiveNum().CastBool() returned %s, expected %s", actual, "true")
}

if val, err := makeNumOrFail("0", t).CastImplicitBool(); err != nil {
t.Fatalf("PrimitiveNum().CastBool() returned the error %v but should have succeeded", err)
} else if actual := val.Display(); actual != "false" {
t.Fatalf("PrimitiveNum().CastBool() returned %s, expected %s", actual, "false")
}

}

func TestNumCastExplicit(t *testing.T) {
Expand All @@ -398,22 +364,29 @@ func TestNumCastExplicit(t *testing.T) {
} else if actual := val.Display(); actual != n {
t.Fatalf("PrimitiveNum().CastNum() returned %s, expected %s", actual, n)
}
}

if val, err := makeNumOrFail(n, t).CastExplicitStr(); err != nil {
t.Fatalf("PrimitiveNum().CastStr() returned the error %v but should have succeeded", err)
} else if actual := val.Display(); actual != n {
t.Fatalf("PrimitiveNum().CastStr() returned %s, expected %s", actual, n)
func TestNumDisplay(t *testing.T) {
basic_test_cases := []string{"123", "0", "-123", "0.12345", "-0.102"}
for _, tc := range basic_test_cases {
if actual := makeNumOrFail(tc, t).Display(); actual != tc {
t.Fatalf("makePrimitiveNumber(%q).Display() returned %q, expected %q", tc, actual, tc)
}
}

if val, err := makeNumOrFail("100", t).CastExplicitBool(); err != nil {
t.Fatalf("PrimitiveNum().CastBool() returned the error %v but should have succeeded", err)
} else if actual := val.Display(); actual != "true" {
t.Fatalf("PrimitiveNum().CastBool() returned %s, expected %s", actual, "true")
big_input := "1.23e+123"
equivalent := "123" + strings.Repeat("0", 121)
if actual := makeNumOrFail(big_input, t).Display(); actual != equivalent {
t.Fatalf("makePrimitiveNumber(%q).Display() returned %q, expected %q", big_input, actual, equivalent)
}
}

func TestNumTruthy(t *testing.T) {
if !makeNumOrFail("100", t).Truthy() {
t.Fatalf("PrimitiveNum(100).Truthy() returned false, expected true")
}

if val, err := makeNumOrFail("0", t).CastExplicitBool(); err != nil {
t.Fatalf("PrimitiveNum().CastBool() returned the error %v but should have succeeded", err)
} else if actual := val.Display(); actual != "false" {
t.Fatalf("PrimitiveNum().CastBool() returned %s, expected %s", actual, "false")
if makeNumOrFail("0", t).Truthy() {
t.Fatalf("PrimitiveNum(0).Truthy() returned true, expected false")
}
}
34 changes: 7 additions & 27 deletions types/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,15 @@ func MakeString(value string) *PrimitiveStr {
return &PrimitiveStr{value}
}

func (str *PrimitiveStr) Display() string {
return str.value
}

// String Operators

func (str *PrimitiveStr) ConcatenateInPlace(other Primitive) error {
if other_str, err := other.CastImplicitStr(); err != nil {
return fmt.Errorf("attempting to concatenate: %w", err)
} else {
str.value = str.value + other_str.value
return nil
}
str.value = str.value + other.Display()
return nil
}

func (str *PrimitiveStr) Concatenate(other Primitive) (Primitive, error) {
if other_str, err := other.CastImplicitStr(); err != nil {
return nil, fmt.Errorf("attempting to concatenate: %w", err)
} else {
return &PrimitiveStr{str.value + other_str.value}, nil
}
return &PrimitiveStr{str.value + other.Display()}, nil
}

// Arithmetic Operators
Expand Down Expand Up @@ -122,14 +110,6 @@ func (str *PrimitiveStr) CastImplicitNum() (*PrimitiveNum, error) {
return nil, fmt.Errorf("string value %q used where implicit number was required", str.value)
}

func (str *PrimitiveStr) CastImplicitStr() (*PrimitiveStr, error) {
return str, nil
}

func (str *PrimitiveStr) CastImplicitBool() (*PrimitiveBool, error) {
return MakeBool(len(str.value) != 0), nil
}

func (str *PrimitiveStr) CastExplicitNum() (*PrimitiveNum, error) {
var num big.Rat
if _, success := num.SetString(str.value); success {
Expand All @@ -138,10 +118,10 @@ func (str *PrimitiveStr) CastExplicitNum() (*PrimitiveNum, error) {
return nil, fmt.Errorf("cannot interpret the string %q as a number", str.value)
}

func (str *PrimitiveStr) CastExplicitStr() (*PrimitiveStr, error) {
return str, nil
func (str *PrimitiveStr) Display() string {
return str.value
}

func (str *PrimitiveStr) CastExplicitBool() (*PrimitiveBool, error) {
return MakeBool(len(str.value) != 0), nil
func (str *PrimitiveStr) Truthy() bool {
return len(str.value) != 0
}
Loading

0 comments on commit 8b3fc42

Please sign in to comment.