Skip to content

Commit

Permalink
built in logicals
Browse files Browse the repository at this point in the history
  • Loading branch information
tacheraSasi committed Nov 27, 2024
1 parent 81b8df4 commit 51baea0
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 0 deletions.
70 changes: 70 additions & 0 deletions evaluator/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,76 @@ var builtins = map[string]*object.Builtin{
}
},
},

"and": {
Fn: func(args ...object.Object) object.Object {
// Ensure that there are exactly 2 arguments
if len(args) != 2 {
return newError("and requires 2 arguments, you provided %d", len(args))
}

// Get the boolean value of the first argument
bool1, err := getBooleanValue(args[0])
if err != nil {
// Return an error if the first argument is not a boolean
return newError("First argument must be a boolean")
}

// Get the boolean value of the second argument
bool2, err := getBooleanValue(args[1])
if err != nil {
// Return an error if the second argument is not a boolean
return newError("Second argument must be a boolean")
}

// Perform the logical AND operation and return the result as a boolean
return &object.Boolean{Value: bool1 && bool2}
},
},
"or": {
Fn: func(args ...object.Object) object.Object {
// Ensure that there are exactly 2 arguments
if len(args) != 2 {
return newError("or requires 2 arguments, you provided %d", len(args))
}

// Get the boolean value of the first argument
bool1, err := getBooleanValue(args[0])
if err != nil {
// Return an error if the first argument is not a boolean
return newError("First argument must be a boolean")
}

// Get the boolean value of the second argument
bool2, err := getBooleanValue(args[1])
if err != nil {
// Return an error if the second argument is not a boolean
return newError("Second argument must be a boolean")
}

// Perform the logical OR operation and return the result as a boolean
return &object.Boolean{Value: bool1 || bool2}
},
},
"not": {
Fn: func(args ...object.Object) object.Object {
// Ensure that there is exactly 1 argument
if len(args) != 1 {
return newError("not requires 1 argument, you provided %d", len(args))
}

// Get the boolean value of the argument
boolVal, err := getBooleanValue(args[0])
if err != nil {
// Return an error if the argument is not a boolean
return newError("Argument must be a boolean")
}

// Perform the logical NOT operation and return the result as a boolean
return &object.Boolean{Value: !boolVal}
},
},

}

func getIntValue(obj object.Object) (int64, error) {
Expand Down
32 changes: 32 additions & 0 deletions evaluator/type.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package evaluator

import (
"fmt"
"strconv"

"github.com/ekilie/vint-lang/object"
Expand All @@ -14,17 +15,20 @@ func convertToInteger(obj object.Object) object.Object {
case *object.Float:
return &object.Integer{Value: int64(obj.Value)}
case *object.String:
// Parse the string to an integer
i, err := strconv.ParseInt(obj.Value, 10, 64)
if err != nil {
return newError("Cannot convert '%s' to INTEGER", obj.Value)
}
return &object.Integer{Value: i}
case *object.Boolean:
// Convert boolean to integer: true -> 1, false -> 0
if obj.Value {
return &object.Integer{Value: 1}
}
return &object.Integer{Value: 0}
default:
// Return error if type is not convertible to integer
return newError("Cannot convert %s to INTEGER", obj.Type())
}
}
Expand All @@ -35,42 +39,70 @@ func convertToFloat(obj object.Object) object.Object {
case *object.Float:
return obj
case *object.Integer:
// Convert integer to float
return &object.Float{Value: float64(obj.Value)}
case *object.String:
// Parse the string to a float
f, err := strconv.ParseFloat(obj.Value, 64)
if err != nil {
return newError("Cannot convert '%s' to FLOAT", obj.Value)
}
return &object.Float{Value: f}
case *object.Boolean:
// Convert boolean to float: true -> 1.0, false -> 0.0
if obj.Value {
return &object.Float{Value: 1.0}
}
return &object.Float{Value: 0.0}
default:
// Return error if type is not convertible to float
return newError("Cannot convert %s to FLOAT", obj.Type())
}
}

// Converts an object to a string
func convertToString(obj object.Object) object.Object {
// Simply return the string representation of the object
return &object.String{Value: obj.Inspect()}
}

// Converts an object to a boolean
func convertToBoolean(obj object.Object) object.Object {
switch obj := obj.(type) {
case *object.Boolean:
// Return the boolean object as is
return obj
case *object.Integer:
// Convert integer to boolean: non-zero -> true, zero -> false
return &object.Boolean{Value: obj.Value != 0}
case *object.Float:
// Convert float to boolean: non-zero -> true, zero -> false
return &object.Boolean{Value: obj.Value != 0}
case *object.String:
// Convert string to boolean: empty string -> false, non-empty -> true
return &object.Boolean{Value: len(obj.Value) > 0}
case *object.Null:
// Null is considered as false
return &object.Boolean{Value: false}
default:
// Default to true for any other type
return &object.Boolean{Value: true}
}
}

// Helper function to extract the boolean value from an object
// Returns an error if the object is not a boolean
func getBooleanValue(obj object.Object) (bool, error) {
switch obj := obj.(type) {
case *object.Boolean:
return obj.Value, nil
case *object.Integer:
return obj.Value != 0, nil
case *object.Float:
return obj.Value != 0, nil
case *object.String:
return len(obj.Value) > 0, nil
default:
return false, fmt.Errorf("expected Boolean, Integer, Float, or String, got %s", obj.Type())
}
}
19 changes: 19 additions & 0 deletions vintLang/logicals.vint
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Sample Vint program demonstrating logical operators

// Define a function to test 'and', 'or', and 'not'
let test_logical_operators = func () {
// Testing 'and' operator
let result_and = and(true, false) // Should return false
print("Result of true AND false: ", result_and)

// Testing 'or' operator
let result_or = or(false, true) // Should return true
print("Result of false OR true: ", result_or)

// Testing 'not' operator
let result_not = not(true) // Should return false
print("Result of NOT true: ", result_not)
}

// Call the function to test the logical operators
test_logical_operators()

0 comments on commit 51baea0

Please sign in to comment.