Skip to content

Commit

Permalink
Added file functions
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardoboss committed Aug 29, 2023
1 parent 91fbd67 commit 877c432
Show file tree
Hide file tree
Showing 9 changed files with 266 additions and 0 deletions.
25 changes: 25 additions & 0 deletions StepLang.Wiki/Functions/FileDelete.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Description

`fileDelete` deletes a file from the file system.

# Syntax

```step
fileDelete(string path)
```

- `path` is the path to the file to delete.

# Remarks

- If the file does not exist, the function does nothing.
- If the file is a directory, the function does nothing.
- If the file is open, the function does nothing.
- If the file is read-only, the function does nothing.
- Returns `true` if the file was deleted, `false` otherwise.

# Examples

```step
fileDelete("C:/Temp/MyFile.txt")
```
45 changes: 45 additions & 0 deletions StepLang.Wiki/Functions/FileExists.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Description

The `fileExists` function checks if a file at the given path exists and returns a boolean indicating the result.

# Syntax

```step
fileExists(string path)
```

- `path` is the path to a file or link/junction to a file.

# Remarks

- The function only checks if the file exists, not if it can be read using `fileRead` (so it may exist but is currently not readable)
- The path can be relative and is interpreted relative to the current working directory
- Absolute paths may require a drive letter (system dependent)

# Examples

```
/
data/
a.txt
b.txt
lib/
main.step
c.txt
```

`lib/main.step` run in `/lib/`:

```step
if (fileExists("/data/a.txt")) {
println("/data/a.txt found") // will get printed
}
if (fileExists("b.txt")) {
println("b.txt in current dir found") // will NOT get printed
}
if (fileExists("c.txt")) {
println("c.txt in current dir found") // will get printed
}
```
36 changes: 36 additions & 0 deletions StepLang.Wiki/Functions/FileRead.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Description

The `fileRead` function takes a files path as a string and returns the contents of the file as a string or `null` if the
file does not exist.

# Syntax

```step
fileRead(string path)
```

- `path` is the path to a file or a link/junction to a file.

# Remarks

- If the file specified in `path` does not exist, `null` is returned.
- If the file contains binary data the data is decoded as ASCII and returned as a string (so `\u09` is interpreted as an HTAB character)
- If the file cannot be opened (e.g. because it is in use by another program), `null` is returned

# Examples

`hello.txt`

```
Hello World!
This is a sample text file.
```

`main.step`

```step
string contents = fileRead("hello.txt")
println(contents) // "Hello World!\n\n..."
```
28 changes: 28 additions & 0 deletions StepLang.Wiki/Functions/FileWrite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Description

`fileWrite` is a function that writes a string to a file and returns a boolean indicating whether it was successful.

# Syntax

```step
fileWrite(string path, string content, bool append = false)
```

- `path` is the path to the file to write to
- `content` is the content to write to the file
- `append` is a boolean that indicates whether to append the content to the file or overwrite the file

# Remarks

- If the file does not exist, it will be created
- If the file exists and `append` is `true`, the content will be appended to the file
- If the file exists and `append` is `false`, the file will be overwritten with the content
- If the content was successfully written to the file, `true` will be returned, `false` otherwise

# Examples

```step
fileWrite("C:/test.txt", "Hello, world!") // creates or overwrites the file
fileWrite("C:/test.txt", "Another hello", true) // appends to the file
fileWrite("C:/test.txt", "Hello, world again!", false) // overwrites the file
```
6 changes: 6 additions & 0 deletions StepLang/Framework/NativeFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,10 @@ protected static void CheckArgumentCount(IReadOnlyList<Expression> arguments, in
if (arguments.Count != expectedCount)
throw new InvalidArgumentCountException(expectedCount, arguments.Count);
}

protected static void CheckArgumentCount(IReadOnlyList<Expression> arguments, int minCount, int maxCount)
{
if (arguments.Count < minCount || arguments.Count > maxCount)
throw new InvalidArgumentCountException(minCount, arguments.Count, maxCount);
}
}
31 changes: 31 additions & 0 deletions StepLang/Framework/Other/FileDeleteFunction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using StepLang.Interpreting;
using StepLang.Parsing.Expressions;

namespace StepLang.Framework.Other;

public class FileDeleteFunction : NativeFunction
{
public const string Identifier = "fileDelete";

/// <inheritdoc />
public override async Task<ExpressionResult> EvaluateAsync(Interpreter interpreter, IReadOnlyList<Expression> arguments, CancellationToken cancellationToken = default)
{
CheckArgumentCount(arguments, 1);

var path = await arguments.Single().EvaluateAsync(interpreter, r => r.ExpectString().Value, cancellationToken);

try
{
File.Delete(path);
}
catch (IOException)
{
return BoolResult.False;
}

return BoolResult.True;
}

/// <inheritdoc />
protected override string DebugParamsString => "string path";
}
20 changes: 20 additions & 0 deletions StepLang/Framework/Other/FileExistsFunction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using StepLang.Interpreting;
using StepLang.Parsing.Expressions;

namespace StepLang.Framework.Other;

public class FileExistsFunction : NativeFunction
{
/// <inheritdoc />
public override async Task<ExpressionResult> EvaluateAsync(Interpreter interpreter, IReadOnlyList<Expression> arguments, CancellationToken cancellationToken = default)
{
CheckArgumentCount(arguments, 1);

var path = await arguments.Single().EvaluateAsync(interpreter, r => r.ExpectString().Value, cancellationToken);

return new BoolResult(File.Exists(path));
}

/// <inheritdoc />
protected override string DebugParamsString => "string path";
}
35 changes: 35 additions & 0 deletions StepLang/Framework/Other/FileReadFunction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Text;
using StepLang.Interpreting;
using StepLang.Parsing.Expressions;

namespace StepLang.Framework.Other;

public class FileReadFunction : NativeFunction
{
public const string Identifier = "fileRead";

/// <inheritdoc />
public override async Task<ExpressionResult> EvaluateAsync(Interpreter interpreter, IReadOnlyList<Expression> arguments, CancellationToken cancellationToken = default)
{
CheckArgumentCount(arguments, 1);

var path = await arguments.Single().EvaluateAsync(interpreter, r => r.ExpectString().Value, cancellationToken);

if (!File.Exists(path))
return NullResult.Instance;

try
{
var contents = await File.ReadAllTextAsync(path, Encoding.ASCII, cancellationToken);

return new StringResult(contents);
}
catch (IOException)
{
return NullResult.Instance;
}
}

/// <inheritdoc />
protected override string DebugParamsString => "string path";
}
40 changes: 40 additions & 0 deletions StepLang/Framework/Other/FileWriteFunction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Text;
using StepLang.Interpreting;
using StepLang.Parsing.Expressions;

namespace StepLang.Framework.Other;

public class FileWriteFunction : NativeFunction
{
public const string Identifier = "fileWrite";

/// <inheritdoc />
public override async Task<ExpressionResult> EvaluateAsync(Interpreter interpreter, IReadOnlyList<Expression> arguments, CancellationToken cancellationToken = default)
{
CheckArgumentCount(arguments, 2, 3);

var path = await arguments[0].EvaluateAsync(interpreter, r => r.ExpectString().Value, cancellationToken);
var content = await arguments[1].EvaluateAsync(interpreter, r => r.ExpectString().Value, cancellationToken);

var append = false;
if (arguments.Count >= 3)
append = await arguments[2].EvaluateAsync(interpreter, r => r.ExpectBool().Value, cancellationToken);

try
{
if (append)
await File.AppendAllTextAsync(path, content, Encoding.ASCII, cancellationToken);
else
await File.WriteAllTextAsync(path, content, Encoding.ASCII, cancellationToken);
}
catch (IOException)
{
return BoolResult.False;
}

return BoolResult.True;
}

/// <inheritdoc />
protected override string DebugParamsString => "string path, string content, append = false";
}

0 comments on commit 877c432

Please sign in to comment.