Skip to content
Permalink
Browse files

Add stat() for file stat as builtin

  • Loading branch information...
thesephist committed Jul 23, 2019
1 parent ceaf278 commit c193048a2a0af3464056eb63614c9484307b63cc
Showing with 106 additions and 1 deletion.
  1. +2 −1 SPEC.md
  2. +103 −0 runtime.go
  3. +1 −0 utils/ink.vim
@@ -151,8 +151,9 @@ These are the right primitives, but we can build much more sophisticated systems

- `in(callback<string> => boolean)`: Read from stdin. The callback function returns a boolean that determines whether to continue reading from input.
- `out(string)`: Print to stdout.
- `dir(string, callback<list>)`: List the contents of a directory. The callback gets a list of values of the form `{name: string, len: number, dir: boolean}`.
- `dir(string, callback<list>)`: List the contents of a directory. The callback gets a list of values of the form `{name: string, len: number, dir: boolean}`. Effectively `stat()` for all files in the directory.
- `make(string, callback)`: Make a new directory at the given path.
- `stat(string, callback)`: `stat` a file at a path, returning its canonicalized filename, size, and whether it's a directory or a file.
- `read(string, number, number, callback<string>)`: Read from given file descriptor from some offset for some bytes, returned as a list of bytes (numbers).
- `write(string, number, string, callback)`: Write to given file descriptor at some offset, some given bytes.
- `delete(string, callback)`: Delete some given file.
@@ -45,6 +45,7 @@ func (ctx *Context) LoadEnvironment() {
ctx.LoadFunc("out", inkOut)
ctx.LoadFunc("dir", inkDir)
ctx.LoadFunc("make", inkMake)
ctx.LoadFunc("stat", inkStat)
ctx.LoadFunc("read", inkRead)
ctx.LoadFunc("write", inkWrite)
ctx.LoadFunc("delete", inkDelete)
@@ -257,6 +258,7 @@ func inkDir(ctx *Context, in []Value) (Value, error) {
})
cbMaybeErr(err)
})
return
}

fileList := ValueTable{}
@@ -358,6 +360,107 @@ func inkMake(ctx *Context, in []Value) (Value, error) {
return NullValue{}, nil
}

func inkStat(ctx *Context, in []Value) (Value, error) {
if (len(in)) != 2 {
return nil, Err{
ErrRuntime,
fmt.Sprintf("stat() expects two arguments: path and callback, but got %d", len(in)),
}
}

statPath, isStatPathString := in[0].(StringValue)
cb, isCbFunction := in[1].(FunctionValue)
if !isStatPathString || !isCbFunction {
return nil, Err{
ErrRuntime,
"unsupported combination of argument types in stat()",
}
}

cbMaybeErr := func(err error) {
if err != nil {
ctx.LogErr(Err{
ErrRuntime,
fmt.Sprintf("error in callback to stat(), %s", err.Error()),
})
}
}

ctx.Engine.Listeners.Add(1)
go func() {
defer ctx.Engine.Listeners.Done()

if !ctx.Engine.Permissions.Read {
ctx.ExecListener(func() {
_, err := evalInkFunction(cb, false, CompositeValue{
entries: ValueTable{
"type": StringValue("data"),
"data": CompositeValue{
entries: ValueTable{
"name": statPath,
"len": NumberValue(0),
"dir": BooleanValue(false),
},
},
},
})
cbMaybeErr(err)
})
return
}

f, err := os.Open(string(statPath))
if err != nil {
ctx.ExecListener(func() {
_, err := evalInkFunction(cb, false, CompositeValue{
entries: ValueTable{
"type": StringValue("error"),
"message": StringValue(
fmt.Sprintf("error opening file in stat(), %s", err.Error()),
),
},
})
cbMaybeErr(err)
})
return
}

fi, err := f.Stat()
if err != nil {
ctx.ExecListener(func() {
_, err := evalInkFunction(cb, false, CompositeValue{
entries: ValueTable{
"type": StringValue("error"),
"message": StringValue(
fmt.Sprintf("error getting file data in stat(), %s", err.Error()),
),
},
})
cbMaybeErr(err)
})
return
}

ctx.ExecListener(func() {
_, err := evalInkFunction(cb, false, CompositeValue{
entries: ValueTable{
"type": StringValue("data"),
"data": CompositeValue{
entries: ValueTable{
"name": StringValue(fi.Name()),
"len": NumberValue(fi.Size()),
"dir": BooleanValue(fi.IsDir()),
},
},
},
})
cbMaybeErr(err)
})
}()

return NullValue{}, nil
}

func inkRead(ctx *Context, in []Value) (Value, error) {
if len(in) != 4 {
return nil, Err{
@@ -65,6 +65,7 @@ syntax keyword inkBuiltin in contained
syntax keyword inkBuiltin out contained
syntax keyword inkBuiltin dir contained
syntax keyword inkBuiltin make contained
syntax keyword inkBuiltin stat contained
syntax keyword inkBuiltin read contained
syntax keyword inkBuiltin write contained
syntax keyword inkBuiltin delete contained

0 comments on commit c193048

Please sign in to comment.
You can’t perform that action at this time.