Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Not your typical cup of J..., try a shot of ZUMBRA.
- `sizeOf`
- `addToArray`, `removeFromArray`, `first`, `last`, `allButFirst`, `min`, `max`, `indexOf`
- `addToDict`, `removeFromDict`
- `toInt`, `toString`, `toFloat`
- 🧠 **Don't forget the ";"**

## 🛠 Code_examples
Expand Down
3 changes: 3 additions & 0 deletions code_examples/parse.zum
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
show(toInt("1"))//1
show(toString(1))//"1"
show(toFloat(true))//1.0
8 changes: 8 additions & 0 deletions code_examples/types.zum
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
var text << "text"; //string
var number << 10 //int
var ok << true // boolean
var notOk << false // boolean
var array << [] //array
var dict << {}// dict
var float << 10.5 // float
var function << fct(){} //function
3 changes: 3 additions & 0 deletions evaluator/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ var builtins = map[string]*object.Builtin{
"indexOf": object.GetBuiltinByName("indexOf"),
"addToDict": object.GetBuiltinByName("addToDict"),
"deleteFromDict": object.GetBuiltinByName("deleteFromDict"),
"toString": object.GetBuiltinByName("toString"),
"toInt": object.GetBuiltinByName("toInt"),
"toFloat": object.GetBuiltinByName("toFloat"),
}
3 changes: 3 additions & 0 deletions evaluator/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ func Eval(node ast.Node, env *object.Environment) object.Object {
}
return evalPrefixExpression(node.Operator, right)

case *ast.FloatLiteral:
return &object.Float{Value: node.Value}

case *ast.InfixExpression:

if node.Operator == "<<" {
Expand Down
39 changes: 39 additions & 0 deletions evaluator/evaluator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -584,3 +584,42 @@ i;`, 10},
}
}
}

func TestTypeConverter(t *testing.T) {
tests := []struct {
input string
expected interface{}
}{
{`toString(1)`, "1"},
{`toString(true)`, "true"},
{`toString(333)`, "333"},
{`toString(2.2)`, "2.2"},
{`toInt("333")`, 333},
{`toInt(true)`, 1},
{`toInt(false)`, 0},
{`toInt(10.2)`, 10},
{`toFloat(10)`, 10.0},
{`toFloat("10.2")`, 10.2},
{`toFloat(true)`, 1.0},
}

for _, tt := range tests {
evaluated := testEval(tt.input)

switch expected := tt.expected.(type) {
case int:
testIntegerObject(t, evaluated, int64(expected))
case string:
str, ok := evaluated.(*object.String)

if !ok {
t.Fatalf("object is not *object.String. got=%T (%+v)", evaluated, evaluated)
}

if str.Value != tt.expected {
t.Errorf("String has wrong value. got=%q", str.Value)
}
}

}
}
92 changes: 92 additions & 0 deletions object/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package object
import (
"fmt"
"math"
"strconv"
)

var Builtins = []struct {
Expand Down Expand Up @@ -315,8 +316,99 @@ var Builtins = []struct {
},
},
},
{
"toString", &Builtin{
Fn: func(args ...Object) Object {
if len(args) != 1 {
return NewError("wrong number of arguments. got=%d, want=1", len(args))
}

var value any

switch obj := args[0].(type) {
case *Integer:
value = obj.Value
case *Float:
value = obj.Value
case *Boolean:
value = obj.Value
default:
return NewError("argument to `toString` not supported, got=%s", args[0].Type())
}

return NewString(fmt.Sprintf("%v", value))
},
},
},
{
"toInt", &Builtin{
Fn: func(args ...Object) Object {
if len(args) != 1 {
return NewError("wrong number of arguments. got=%d, want=1", len(args))
}

switch obj := args[0].(type) {
case *String:
value, errors := strconv.Atoi(obj.Value)

if errors != nil {
return NewError("Error to parse string. %s", errors.Error())
}

return NewInteger(int64(value))
case *Float:
return NewInteger(int64(math.Floor(obj.Value)))
case *Boolean:
if obj.Value == true {
return NewInteger(1)
} else {
return NewInteger(0)
}
case *Integer:
return obj
default:
return NewError("argument to `toInt` not supported, got=%s", args[0].Type())
}
},
},
},
{
"toFloat", &Builtin{
Fn: func(args ...Object) Object {
if len(args) != 1 {
return NewError("wrong number of arguments. got=%d, want=1", len(args))
}

switch obj := args[0].(type) {
case *String:
value, errors := strconv.ParseFloat(obj.Value, 64)

if errors != nil {
return NewError("Error to parse string. %s", errors.Error())
}

return NewFloat(float64(value))
case *Float:
return obj
case *Boolean:
if obj.Value == true {
return NewFloat(1)
} else {
return NewFloat(0)
}
case *Integer:
return NewFloat(float64(obj.Value))
default:
return NewError("argument to `toFloat` not supported, got=%s", args[0].Type())
}
},
},
},
}

func NewFloat(value float64) *Float {
return &Float{Value: value}
}
func NewString(value string) *String {
return &String{Value: value}
}
Expand Down