Skip to content

Commit

Permalink
file io!!
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonak-Adipta-Kalita committed May 9, 2023
1 parent 7700c17 commit 2679fcf
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 0 deletions.
122 changes: 122 additions & 0 deletions evaluator/builtins.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package evaluator

import (
"bufio"
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
Expand Down Expand Up @@ -314,4 +316,124 @@ var builtins = map[string]*object.Builtin{
}
},
},

"open": {
Fn: func(file string, line int, args ...object.Object) object.Object {
if len(args) != 2 {
return newError("wrong number of arguments. got=%d, want=2", file, line, len(args))
}
if args[0].Type() != object.STRING_OBJ {
return newError("argument to `open` must be STRING, got %s", file, line, args[0].Type())
}
if args[1].Type() != object.STRING_OBJ {
return newError("argument to `open` must be STRING, got %s", file, line, args[1].Type())
}
filename := args[0].(*object.String).Value
mode := args[1].(*object.String).Value
var flag int
switch mode {
case "r":
flag = os.O_RDONLY
case "w":
flag = os.O_WRONLY | os.O_CREATE
case "a":
flag = os.O_WRONLY | os.O_APPEND | os.O_CREATE
default:
return newError("invalid mode %s", file, line, mode)
}
openedFile, err := os.OpenFile(filename, flag, 0644)
if err != nil {
return newError("could not open file %s", file, line, filename)
}
return &object.File{File: openedFile}
},
},
"close": {
Fn: func(file string, line int, args ...object.Object) object.Object {
if len(args) != 1 {
return newError("wrong number of arguments. got=%d, want=1", file, line, len(args))
}
if args[0].Type() != object.FILE_OBJ {
return newError("argument to `close` must be FILE, got %s", file, line, args[0].Type())
}
fileObj := args[0].(*object.File)
err := fileObj.File.Close()
if err != nil {
return newError("could not close file %s", file, line, fileObj.File.Name())
}
return NULL
},
},
"read": {
Fn: func(file string, line int, args ...object.Object) object.Object {
if len(args) != 1 {
return newError("wrong number of arguments. got=%d, want=1", file, line, len(args))
}
if args[0].Type() != object.FILE_OBJ {
return newError("argument to `read` must be FILE, got %s", file, line, args[0].Type())
}
fileObj := args[0].(*object.File)
content, err := ioutil.ReadAll(fileObj.File)
if err != nil {
return newError("could not read file %s", file, line, fileObj.File.Name())
}
return &object.String{Value: string(content)}
},
},
"write": {
Fn: func(file string, line int, args ...object.Object) object.Object {
if len(args) != 2 {
return newError("wrong number of arguments. got=%d, want=2", file, line, len(args))
}
if args[0].Type() != object.FILE_OBJ {
return newError("argument to `write` must be FILE, got %s", file, line, args[0].Type())
}
if args[1].Type() != object.STRING_OBJ {
return newError("argument to `write` must be STRING, got %s", file, line, args[1].Type())
}
fileObj := args[0].(*object.File)
_, err := fileObj.File.WriteString(args[1].(*object.String).Value)
if err != nil {
return newError("could not write to file %s", file, line, fileObj.File.Name())
}
return NULL
},
},
"readline": {
Fn: func(file string, line int, args ...object.Object) object.Object {
if len(args) != 1 {
return newError("wrong number of arguments. got=%d, want=1", file, line, len(args))
}
if args[0].Type() != object.FILE_OBJ {
return newError("argument to `readline` must be FILE, got %s", file, line, args[0].Type())
}
fileObj := args[0].(*object.File)
content, err := bufio.NewReader(fileObj.File).ReadString('\n')
if err != nil {
return newError("could not read file %s", file, line, fileObj.File.Name())
}
return &object.String{Value: content}
},
},
"readlines": {
Fn: func(file string, line int, args ...object.Object) object.Object {
if len(args) != 1 {
return newError("wrong number of arguments. got=%d, want=1", file, line, len(args))
}
if args[0].Type() != object.FILE_OBJ {
return newError("argument to `readlines` must be FILE, got %s", file, line, args[0].Type())
}
fileObj := args[0].(*object.File)
content, err := ioutil.ReadAll(fileObj.File)
if err != nil {
return newError("could not read file %s", file, line, fileObj.File.Name())
}
var elements []object.Object
for _, line := range strings.Split(string(content), "\n") {
elements = append(elements, &object.String{Value: line})
}

return &object.Array{Elements: elements}
},
},
}
9 changes: 9 additions & 0 deletions object/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"hash/fnv"
"os"
"strconv"
"strings"
"unicode/utf8"
Expand Down Expand Up @@ -35,6 +36,7 @@ const (
BUILTIN_OBJ = "BUILTIN"
QUOTE_OBJ = "QUOTE"
MACRO_OBJ = "MACRO"
FILE_OBJ = "FILE"
)

type Boolean struct {
Expand Down Expand Up @@ -265,3 +267,10 @@ type Float struct {

func (f *Float) Inspect() string { return strconv.FormatFloat(f.Value, 'f', -1, 64) }
func (f *Float) Type() ObjectType { return FLOAT_OBJ }

type File struct {
File *os.File
}

func (f *File) Inspect() string { return f.File.Name() }
func (f *File) Type() ObjectType { return FILE_OBJ }

0 comments on commit 2679fcf

Please sign in to comment.