Skip to content

Commit

Permalink
Iterators and misc other improvements (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
myzie committed Jun 28, 2023
1 parent cc15061 commit 4b82d9e
Show file tree
Hide file tree
Showing 59 changed files with 1,557 additions and 832 deletions.
177 changes: 123 additions & 54 deletions builtins/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func String(ctx context.Context, args ...object.Object) object.Object {
return object.NewError(err)
}
return object.NewString(string(arg.Value()))
case *object.BSlice:
case *object.ByteSlice:
if err := lim.TrackCost(argCost); err != nil {
return object.NewError(err)
}
Expand All @@ -202,12 +202,54 @@ func String(ctx context.Context, args ...object.Object) object.Object {
}
}

func BSlice(ctx context.Context, args ...object.Object) object.Object {
if err := arg.RequireRange("bslice", 0, 1, args); err != nil {
func FloatSlice(ctx context.Context, args ...object.Object) object.Object {
if err := arg.RequireRange("float_slice", 0, 1, args); err != nil {
return err
}
if len(args) == 0 {
return object.NewBSlice(nil)
return object.NewFloatSlice(nil)
}
arg := args[0]
argCost := arg.Cost()
if err := limits.TrackCost(ctx, argCost); err != nil {
return object.NewError(err)
}
switch arg := arg.(type) {
case *object.FloatSlice:
return arg.Clone()
case *object.Int:
val := arg.Value()
if err := limits.TrackCost(ctx, int(val)-argCost); err != nil {
return object.NewError(err)
}
return object.NewFloatSlice(make([]float64, val))
case *object.List:
items := arg.Value()
floats := make([]float64, len(items))
for i, item := range items {
switch item := item.(type) {
case *object.Byte:
floats[i] = float64(item.Value())
case *object.Int:
floats[i] = float64(item.Value())
case *object.Float:
floats[i] = item.Value()
default:
return object.Errorf("type error: float_slice() list item unsupported (%s given)", item.Type())
}
}
return object.NewFloatSlice(floats)
default:
return object.Errorf("type error: float_slice() unsupported argument (%s given)", args[0].Type())
}
}

func ByteSlice(ctx context.Context, args ...object.Object) object.Object {
if err := arg.RequireRange("byte_slice", 0, 1, args); err != nil {
return err
}
if len(args) == 0 {
return object.NewByteSlice(nil)
}
arg := args[0]
argCost := arg.Cost()
Expand All @@ -216,30 +258,33 @@ func BSlice(ctx context.Context, args ...object.Object) object.Object {
}
switch arg := arg.(type) {
case *object.Buffer:
return object.NewBSlice(arg.Value())
case *object.BSlice:
return object.NewByteSlice(arg.Value())
case *object.ByteSlice:
return arg.Clone()
case *object.String:
return object.NewBSlice([]byte(arg.Value()))
return object.NewByteSlice([]byte(arg.Value()))
case *object.Int:
val := arg.Value()
if err := limits.TrackCost(ctx, int(val)-argCost); err != nil {
return object.NewError(err)
}
return object.NewBSlice(make([]byte, val))
return object.NewByteSlice(make([]byte, val))
case *object.List:
items := arg.Value()
bytes := make([]byte, len(items))
for i, item := range items {
intObj, ok := item.(*object.Int)
if !ok {
return object.Errorf("type error: bslice() list argument should contain only ints (got %s)", item.Type())
switch item := item.(type) {
case *object.Int:
bytes[i] = byte(item.Value())
case *object.Byte:
bytes[i] = item.Value()
default:
return object.Errorf("type error: byte_slice() list item unsupported (%s given)", item.Type())
}
bytes[i] = byte(intObj.Value())
}
return object.NewBSlice(bytes)
return object.NewByteSlice(bytes)
default:
return object.Errorf("type error: bslice() unsupported argument (%s given)", args[0].Type())
return object.Errorf("type error: byte_slice() unsupported argument (%s given)", args[0].Type())
}
}

Expand All @@ -261,7 +306,7 @@ func Buffer(ctx context.Context, args ...object.Object) object.Object {
return object.NewError(err)
}
return object.NewBufferFromBytes(arg.Value())
case *object.BSlice:
case *object.ByteSlice:
if err := lim.TrackCost(arg.Cost()); err != nil {
return object.NewError(err)
}
Expand Down Expand Up @@ -331,7 +376,7 @@ func Any(ctx context.Context, args ...object.Object) object.Object {
return object.True
}
}
case *object.BSlice:
case *object.ByteSlice:
for _, val := range arg.Value() {
if val != 0 {
return object.True
Expand Down Expand Up @@ -377,7 +422,7 @@ func All(ctx context.Context, args ...object.Object) object.Object {
return object.False
}
}
case *object.BSlice:
case *object.ByteSlice:
for _, val := range arg.Value() {
if val == 0 {
return object.False
Expand Down Expand Up @@ -437,7 +482,7 @@ func Sorted(ctx context.Context, args ...object.Object) object.Object {
items = arg.List().Value()
case *object.String:
items = arg.Runes()
case *object.BSlice:
case *object.ByteSlice:
items = arg.Integers()
default:
return object.Errorf("type error: sorted() unsupported argument (%s given)", arg.Type())
Expand All @@ -463,7 +508,7 @@ func Reversed(ctx context.Context, args ...object.Object) object.Object {
return arg.Reversed()
case *object.String:
return arg.Reversed()
case *object.BSlice:
case *object.ByteSlice:
return arg.Reversed()
default:
return object.Errorf("type error: reversed() unsupported argument (%s given)", arg.Type())
Expand Down Expand Up @@ -541,6 +586,30 @@ func Keys(ctx context.Context, args ...object.Object) object.Object {
}
}

func Byte(ctx context.Context, args ...object.Object) object.Object {
if err := arg.RequireRange("byte", 0, 1, args); err != nil {
return err
}
if len(args) == 0 {
return object.NewByte(0)
}
switch obj := args[0].(type) {
case *object.Int:
return object.NewByte(byte(obj.Value()))
case *object.Byte:
return object.NewByte(obj.Value())
case *object.Float:
return object.NewByte(byte(obj.Value()))
case *object.String:
if i, err := strconv.ParseInt(obj.Value(), 0, 8); err == nil {
return object.NewByte(byte(i))
}
return object.Errorf("value error: invalid literal for byte(): %q", obj.Value())
default:
return object.Errorf("type error: byte() unsupported argument (%s given)", args[0].Type())
}
}

func Int(ctx context.Context, args ...object.Object) object.Object {
if err := arg.RequireRange("int", 0, 1, args); err != nil {
return err
Expand All @@ -551,19 +620,15 @@ func Int(ctx context.Context, args ...object.Object) object.Object {
switch obj := args[0].(type) {
case *object.Int:
return obj
case *object.Byte:
return object.NewInt(int64(obj.Value()))
case *object.Float:
return object.NewInt(int64(obj.Value()))
case *object.String:
if i, err := strconv.ParseInt(obj.Value(), 0, 64); err == nil {
return object.NewInt(i)
}
return object.Errorf("value error: invalid literal for int(): %q", obj.Value())
case *object.BSlice:
val := obj.Value()
if len(val) != 1 {
return object.Errorf("value error: bslice must be exactly one byte long")
}
return object.NewInt(int64(val[0]))
default:
return object.Errorf("type error: int() unsupported argument (%s given)", args[0].Type())
}
Expand All @@ -579,6 +644,8 @@ func Float(ctx context.Context, args ...object.Object) object.Object {
switch obj := args[0].(type) {
case *object.Int:
return object.NewFloat(float64(obj.Value()))
case *object.Byte:
return object.NewFloat(float64(obj.Value()))
case *object.Float:
return obj
case *object.String:
Expand Down Expand Up @@ -709,34 +776,36 @@ func CodeObj(ctx context.Context, args ...object.Object) object.Object {

func Builtins() map[string]object.Object {
return map[string]object.Object{
"all": object.NewBuiltin("all", All),
"any": object.NewBuiltin("any", Any),
"assert": object.NewBuiltin("assert", Assert),
"bool": object.NewBuiltin("bool", Bool),
"bslice": object.NewBuiltin("bslice", BSlice),
"buffer": object.NewBuiltin("buffer", Buffer),
"call": object.NewBuiltin("call", Call),
"chr": object.NewBuiltin("chr", Chr),
"codeobj": object.NewBuiltin("codeobj", CodeObj),
"decode": object.NewBuiltin("decode", Decode),
"delete": object.NewBuiltin("delete", Delete),
"encode": object.NewBuiltin("encode", Encode),
"error": object.NewBuiltin("error", Error),
"float": object.NewBuiltin("float", Float),
"getattr": object.NewBuiltin("getattr", GetAttr),
"int": object.NewBuiltin("int", Int),
"iter": object.NewBuiltin("iter", Iter),
"keys": object.NewBuiltin("keys", Keys),
"len": object.NewBuiltin("len", Len),
"list": object.NewBuiltin("list", List),
"map": object.NewBuiltin("map", Map),
"ord": object.NewBuiltin("ord", Ord),
"reversed": object.NewBuiltin("reversed", Reversed),
"set": object.NewBuiltin("set", Set),
"sorted": object.NewBuiltin("sorted", Sorted),
"sprintf": object.NewBuiltin("sprintf", Sprintf),
"string": object.NewBuiltin("string", String),
"try": object.NewBuiltin("try", Try),
"type": object.NewBuiltin("type", Type),
"all": object.NewBuiltin("all", All),
"any": object.NewBuiltin("any", Any),
"assert": object.NewBuiltin("assert", Assert),
"bool": object.NewBuiltin("bool", Bool),
"byte": object.NewBuiltin("byte", Byte),
"byte_slice": object.NewBuiltin("byte_slice", ByteSlice),
"buffer": object.NewBuiltin("buffer", Buffer),
"call": object.NewBuiltin("call", Call),
"chr": object.NewBuiltin("chr", Chr),
"codeobj": object.NewBuiltin("codeobj", CodeObj),
"decode": object.NewBuiltin("decode", Decode),
"delete": object.NewBuiltin("delete", Delete),
"encode": object.NewBuiltin("encode", Encode),
"error": object.NewBuiltin("error", Error),
"float": object.NewBuiltin("float", Float),
"float_slice": object.NewBuiltin("float_slice", FloatSlice),
"getattr": object.NewBuiltin("getattr", GetAttr),
"int": object.NewBuiltin("int", Int),
"iter": object.NewBuiltin("iter", Iter),
"keys": object.NewBuiltin("keys", Keys),
"len": object.NewBuiltin("len", Len),
"list": object.NewBuiltin("list", List),
"map": object.NewBuiltin("map", Map),
"ord": object.NewBuiltin("ord", Ord),
"reversed": object.NewBuiltin("reversed", Reversed),
"set": object.NewBuiltin("set", Set),
"sorted": object.NewBuiltin("sorted", Sorted),
"sprintf": object.NewBuiltin("sprintf", Sprintf),
"string": object.NewBuiltin("string", String),
"try": object.NewBuiltin("try", Try),
"type": object.NewBuiltin("type", Type),
}
}
6 changes: 3 additions & 3 deletions builtins/codecs.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ func decodeBase64(ctx context.Context, obj object.Object) object.Object {
if decodeErr != nil {
return object.NewError(decodeErr)
}
return object.NewBSlice(dst[:count])
return object.NewByteSlice(dst[:count])
}

func decodeBase32(ctx context.Context, obj object.Object) object.Object {
Expand All @@ -242,7 +242,7 @@ func decodeBase32(ctx context.Context, obj object.Object) object.Object {
if decodeErr != nil {
return object.NewError(decodeErr)
}
return object.NewBSlice(dst[:count])
return object.NewByteSlice(dst[:count])
}

func decodeHex(ctx context.Context, obj object.Object) object.Object {
Expand All @@ -255,7 +255,7 @@ func decodeHex(ctx context.Context, obj object.Object) object.Object {
if decodeErr != nil {
return object.NewError(decodeErr)
}
return object.NewBSlice(dst[:count])
return object.NewByteSlice(dst[:count])
}

func decodeJSON(ctx context.Context, obj object.Object) object.Object {
Expand Down
6 changes: 5 additions & 1 deletion modules/aws/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ func (c *Client) GetAttr(name string) (object.Object, bool) {
return NewMethod(methodName, c.client, method), true
}

func (c *Client) SetAttr(name string, value object.Object) error {
return fmt.Errorf("attribute error: aws.client object has no attribute %q", name)
}

func (c *Client) Interface() interface{} {
return c.client
}
Expand Down Expand Up @@ -67,7 +71,7 @@ func (c *Client) RunOperation(opType op.BinaryOpType, right object.Object) objec
}

func (c *Client) Cost() int {
return 8
return 0
}

func NewClient(service string, client interface{}) *Client {
Expand Down
6 changes: 5 additions & 1 deletion modules/aws/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ func (c *Config) GetAttr(name string) (object.Object, bool) {
return nil, false
}

func (c *Config) SetAttr(name string, value object.Object) error {
return fmt.Errorf("attribute error: aws.config object has no attribute %q", name)
}

func (c *Config) Interface() interface{} {
return c.cfg
}
Expand Down Expand Up @@ -191,7 +195,7 @@ func (c *Config) RunOperation(opType op.BinaryOpType, right object.Object) objec
}

func (c *Config) Cost() int {
return 8
return 0
}

func NewConfig(cfg aws.Config) *Config {
Expand Down
4 changes: 2 additions & 2 deletions modules/base64/base64.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func Decode(ctx context.Context, args ...object.Object) object.Object {
if decodeErr != nil {
return object.NewError(decodeErr)
}
return object.NewBSlice(dst[:count])
return object.NewByteSlice(dst[:count])
}

func URLDecode(ctx context.Context, args ...object.Object) object.Object {
Expand Down Expand Up @@ -122,7 +122,7 @@ func URLDecode(ctx context.Context, args ...object.Object) object.Object {
if decodeErr != nil {
return object.NewError(decodeErr)
}
return object.NewBSlice(dst[:count])
return object.NewByteSlice(dst[:count])
}

func Module() *object.Module {
Expand Down
Loading

0 comments on commit 4b82d9e

Please sign in to comment.