initial commit
This commit is contained in:
commit
998fa271db
18 changed files with 951 additions and 0 deletions
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
build/
|
||||
recovery/
|
||||
AutomateCl/repositories/
|
||||
AutomateCl/build
|
||||
BeefSpace_User.toml
|
18
BeefProj.toml
Normal file
18
BeefProj.toml
Normal file
|
@ -0,0 +1,18 @@
|
|||
FileVersion = 1
|
||||
Dependencies = {corlib = "*", corlib = "*"}
|
||||
|
||||
[Project]
|
||||
Name = "Automate"
|
||||
StartupObject = "Automate.Program"
|
||||
|
||||
[Platform.Windows]
|
||||
IconFile = "automate.ico"
|
||||
Description = "Scripting language runner"
|
||||
Company = "Booklordofthedings"
|
||||
Product = "Automate"
|
||||
Copyright = "Booklordofthedings"
|
||||
FileVersion = "1.0"
|
||||
ProductVersion = "1.0"
|
||||
|
||||
[Configs.Debug.Win64]
|
||||
TargetName = "Automate"
|
20
BeefSpace.toml
Normal file
20
BeefSpace.toml
Normal file
|
@ -0,0 +1,20 @@
|
|||
FileVersion = 1
|
||||
Projects = {Automate = {Path = "."}}
|
||||
|
||||
[Workspace]
|
||||
StartupProject = "Automate"
|
||||
|
||||
[Configs.Debug.wasm32]
|
||||
AllocType = "CRT"
|
||||
EnableObjectDebugFlags = false
|
||||
EmitObjectAccessCheck = false
|
||||
|
||||
[Configs.Paranoid.wasm32]
|
||||
AllocType = "CRT"
|
||||
EnableObjectDebugFlags = false
|
||||
EmitObjectAccessCheck = false
|
||||
|
||||
[Configs.Test.wasm32]
|
||||
AllocType = "CRT"
|
||||
EnableObjectDebugFlags = false
|
||||
EmitObjectAccessCheck = false
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 Jannis
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
2
README.md
Normal file
2
README.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Automate
|
||||
Stack based crossplatform* automation language written in Beef
|
BIN
automate.ico
Normal file
BIN
automate.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
101
src/Automate.bf
Normal file
101
src/Automate.bf
Normal file
|
@ -0,0 +1,101 @@
|
|||
namespace Automate;
|
||||
using Automate.Commands;
|
||||
using System;
|
||||
using System.Collections;
|
||||
class Automate
|
||||
{
|
||||
public AutomateStack Stack = new .() ~ delete _;
|
||||
public AutomateInstructions Instructions = new .() ~ delete _;
|
||||
public function void(StringView) ConsoleCallback = => Console.WriteLine;
|
||||
|
||||
private Dictionary<StringView, function void(Automate)> Commands = new .(100) ~ delete _;
|
||||
private bool shouldRun = true;
|
||||
|
||||
public this()
|
||||
{
|
||||
///Register the default commands that automate is using
|
||||
|
||||
//Conversions
|
||||
Commands.Add("string->num", => Conversions.StringToNum);
|
||||
Commands.Add("num->string", => Conversions.NumToString);
|
||||
Commands.Add("string->bool", => Conversions.StringToBool);
|
||||
Commands.Add("bool->string", => Conversions.BoolToString);
|
||||
|
||||
//Math
|
||||
Commands.Add("+", => Automate.Commands.Math.Add);
|
||||
Commands.Add("-", => Automate.Commands.Math.Sub);
|
||||
Commands.Add("*", => Automate.Commands.Math.Mult);
|
||||
Commands.Add("/", => Automate.Commands.Math.Div);
|
||||
Commands.Add("sqrt", => Automate.Commands.Math.Root);
|
||||
Commands.Add("%", => Automate.Commands.Math.Modulo);
|
||||
Commands.Add("pow", => Automate.Commands.Math.Pow);
|
||||
Commands.Add("sqr", => Automate.Commands.Math.Square);
|
||||
Commands.Add("cube", => Automate.Commands.Math.Cube);
|
||||
Commands.Add("pi", => Automate.Commands.Math.Pi);
|
||||
Commands.Add("round", => Automate.Commands.Math.Round);
|
||||
Commands.Add("roundfin", => Automate.Commands.Math.RoundFin);
|
||||
|
||||
//Comparisons
|
||||
Commands.Add("less", => Comparisons.LessThan);
|
||||
Commands.Add("greater", => Comparisons.GreaterThan);
|
||||
Commands.Add("lessEquals", => Comparisons.LessThanEquals);
|
||||
Commands.Add("greaterEquals", => Comparisons.GreaterThanEquals);
|
||||
Commands.Add("equals", => Comparisons.Equals);
|
||||
|
||||
//IO
|
||||
Commands.Add("mkf", => Files.MakeFile);
|
||||
Commands.Add("cpf", => Files.CopyFile);
|
||||
Commands.Add("rmf", => Files.DeleteFile);
|
||||
Commands.Add("mkd", => Directories.MakeDirectory);
|
||||
|
||||
//Debugging
|
||||
Commands.Add("print", => Echo.Echo);
|
||||
Commands.Add("printf", => Echo.Print);
|
||||
|
||||
//Functions
|
||||
Commands.Add("call", => Functions.Call);
|
||||
Commands.Add("return", => Functions.Return);
|
||||
Commands.Add("goto", => Functions.Goto);
|
||||
Commands.Add("gorel", => Functions.GotoRelative);
|
||||
Commands.Add("jmpiz", => Functions.JumpIfZero);
|
||||
Commands.Add("jmp", => Functions.Jump);
|
||||
}
|
||||
|
||||
public void ThrowError(StringView error)
|
||||
{
|
||||
ConsoleCallback(scope $"Error on line {Instructions.GetProgramCounter()} -> {Instructions.[Friend]_Instructions[Instructions.GetProgramCounter()-1]}: {error}");
|
||||
shouldRun = false;
|
||||
}
|
||||
|
||||
///Run the previously loaded code
|
||||
public void Run()
|
||||
{
|
||||
shouldRun = true;
|
||||
while(shouldRun)
|
||||
{
|
||||
var line = Instructions.GetNextCommand();
|
||||
if(line == "exit")
|
||||
shouldRun = false;
|
||||
else if(line == "")
|
||||
continue;
|
||||
else if(line.StartsWith('>'))
|
||||
Stack.Push(Variant.Create<String>(new .(line, 1), true));
|
||||
else if(line.StartsWith('<'))
|
||||
Stack.Push(Variant.Create<double>(Instructions.[Friend]_Literals[line]));
|
||||
else if(line.StartsWith('#') || line.StartsWith('$'))
|
||||
continue;
|
||||
else if(!Commands.ContainsKey(line))
|
||||
ThrowError(scope $"Command '{line}' doesnt exist");
|
||||
else
|
||||
Commands[line](this);
|
||||
}
|
||||
}
|
||||
|
||||
public bool RegisterCommand(StringView name, function void(Automate) func)
|
||||
{
|
||||
if(Commands.ContainsKey(name))
|
||||
return false;
|
||||
Commands.Add(name, func);
|
||||
return true;
|
||||
}
|
||||
}
|
109
src/AutomateInstructions.bf
Normal file
109
src/AutomateInstructions.bf
Normal file
|
@ -0,0 +1,109 @@
|
|||
namespace Automate;
|
||||
using System;
|
||||
using System.Collections;
|
||||
class AutomateInstructions
|
||||
{
|
||||
|
||||
private List<StringView> _Instructions = new .(200) ~ delete _;
|
||||
private List<int64> _FunctionCalls = new .(100) ~ delete _;
|
||||
private Dictionary<StringView, int64> _Labels = new .(5) ~ delete _;
|
||||
private Dictionary<StringView, double> _Literals = new .(10) ~ delete _;
|
||||
private int _OffsetCounter = 0;
|
||||
private int _ProgramCounter = 0;
|
||||
|
||||
///Append a piece of code to the code counter and parse labels
|
||||
[Inline]
|
||||
public void LoadCode(StringView pToLoad)
|
||||
{
|
||||
var split = pToLoad.Split('\n',.None);
|
||||
for(var line in split)
|
||||
{
|
||||
_OffsetCounter++;
|
||||
if(line.StartsWith('$'))
|
||||
_Labels.Add(.(line,1),_OffsetCounter);
|
||||
else if(line.StartsWith('<'))
|
||||
{
|
||||
if(!_Literals.ContainsKey(line))
|
||||
{
|
||||
var res = double.Parse(.(line,1));
|
||||
if(res case .Ok(let val))
|
||||
_Literals.Add(line,val);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
_Instructions.Add(line);
|
||||
}
|
||||
}
|
||||
|
||||
///Removes all loaded code, labels and resets the program counter
|
||||
[Inline]
|
||||
public void Clear()
|
||||
{
|
||||
_Instructions.Clear();
|
||||
_Labels.Clear();
|
||||
_Literals.Clear();
|
||||
_OffsetCounter = 0;
|
||||
_ProgramCounter = 0;
|
||||
}
|
||||
|
||||
///Sets the program counter to the position of a specific label or returns false
|
||||
[Inline]
|
||||
public bool Goto(StringView pLabel)
|
||||
{
|
||||
if(!_Labels.ContainsKey(pLabel))
|
||||
return false;
|
||||
_ProgramCounter = _Labels[pLabel];
|
||||
return true;
|
||||
}
|
||||
|
||||
[Inline]
|
||||
public void SetProgramCounter(int64 pValue)
|
||||
{
|
||||
_ProgramCounter = pValue;
|
||||
}
|
||||
|
||||
[Inline]
|
||||
public int64 GetProgramCounter()
|
||||
{
|
||||
return _ProgramCounter;
|
||||
}
|
||||
|
||||
[Inline]
|
||||
public int64 MaxProgramCounter()
|
||||
{
|
||||
return _OffsetCounter;
|
||||
}
|
||||
|
||||
[Inline]
|
||||
public StringView GetNextCommand()
|
||||
{
|
||||
if(_ProgramCounter < _OffsetCounter)
|
||||
{
|
||||
_ProgramCounter++;
|
||||
return _Instructions[_ProgramCounter-1];
|
||||
|
||||
}
|
||||
return "exit";
|
||||
}
|
||||
|
||||
[Inline]
|
||||
public void Call(StringView pLabel)
|
||||
{
|
||||
if(_Labels.ContainsKey(pLabel))
|
||||
{
|
||||
_FunctionCalls.Add(_ProgramCounter);
|
||||
_ProgramCounter = _Labels[pLabel];
|
||||
}
|
||||
}
|
||||
|
||||
[Inline]
|
||||
public void Return()
|
||||
{
|
||||
if(_FunctionCalls.Count > 0)
|
||||
{
|
||||
var t = _FunctionCalls.PopBack();
|
||||
_ProgramCounter = t;
|
||||
}
|
||||
}
|
||||
}
|
65
src/AutomateStack.bf
Normal file
65
src/AutomateStack.bf
Normal file
|
@ -0,0 +1,65 @@
|
|||
namespace Automate;
|
||||
using System;
|
||||
using System.Collections;
|
||||
class AutomateStack
|
||||
{
|
||||
private List<Variant> _Stack = new List<Variant>(100) ~ DeleteContainerAndDisposeItems!(_);
|
||||
|
||||
///Peek the last added object
|
||||
[Inline]
|
||||
public Variant Peek()
|
||||
{
|
||||
if(_Stack.Count > 0)
|
||||
return _Stack[^1];
|
||||
return .();
|
||||
}
|
||||
|
||||
///Peek the nth last added object
|
||||
[Inline]
|
||||
public Variant PeekN(int pOffset)
|
||||
{
|
||||
if(_Stack.Count > pOffset)
|
||||
return _Stack[^pOffset];
|
||||
return .();
|
||||
}
|
||||
|
||||
///Add a new variant to the stack
|
||||
[Inline]
|
||||
public void Push(Variant pToAdd)
|
||||
{
|
||||
_Stack.Add(pToAdd);
|
||||
}
|
||||
|
||||
[Inline]
|
||||
public void Clear()
|
||||
{
|
||||
for(var i in _Stack)
|
||||
i.Dispose();
|
||||
_Stack.Clear();
|
||||
}
|
||||
|
||||
///Pops the highest object on the stack
|
||||
[Inline]
|
||||
public Variant Pop()
|
||||
{
|
||||
if(_Stack.Count > 0)
|
||||
return _Stack.PopBack();
|
||||
return .();
|
||||
}
|
||||
|
||||
///Pops the highest object and automatically disposes it in the scope of it being called
|
||||
public mixin Pop()
|
||||
{
|
||||
var val = Pop();
|
||||
defer:mixin val.Dispose();
|
||||
val
|
||||
}
|
||||
|
||||
public int Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Stack.Count;
|
||||
}
|
||||
}
|
||||
}
|
104
src/Commands/Comparisons.bf
Normal file
104
src/Commands/Comparisons.bf
Normal file
|
@ -0,0 +1,104 @@
|
|||
namespace Automate.Commands;
|
||||
using System;
|
||||
class Comparisons
|
||||
{
|
||||
public static void LessThan(Automate au)
|
||||
{
|
||||
var one = au.Stack.Pop!();
|
||||
if(one.HasValue && one.VariantType == typeof(double))
|
||||
{
|
||||
var two = au.Stack.Pop!();
|
||||
if(two.HasValue && two.VariantType == typeof(double))
|
||||
{
|
||||
if(two.Get<double>() < one.Get<double>())
|
||||
au.Stack.Push(Variant.Create(true));
|
||||
else
|
||||
au.Stack.Push(Variant.Create(false));
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot compare non numbers");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot compare non numbers");
|
||||
}
|
||||
|
||||
public static void GreaterThan(Automate au)
|
||||
{
|
||||
var one = au.Stack.Pop!();
|
||||
if(one.HasValue && one.VariantType == typeof(double))
|
||||
{
|
||||
var two = au.Stack.Pop!();
|
||||
if(two.HasValue && two.VariantType == typeof(double))
|
||||
{
|
||||
if(two.Get<double>() > one.Get<double>())
|
||||
au.Stack.Push(Variant.Create(true));
|
||||
else
|
||||
au.Stack.Push(Variant.Create(false));
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot compare non numbers");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot compare non numbers");
|
||||
}
|
||||
|
||||
public static void LessThanEquals(Automate au)
|
||||
{
|
||||
var one = au.Stack.Pop!();
|
||||
if(one.HasValue && one.VariantType == typeof(double))
|
||||
{
|
||||
var two = au.Stack.Pop!();
|
||||
if(two.HasValue && two.VariantType == typeof(double))
|
||||
{
|
||||
if(two.Get<double>() <= one.Get<double>())
|
||||
au.Stack.Push(Variant.Create(true));
|
||||
else
|
||||
au.Stack.Push(Variant.Create(false));
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot compare non numbers");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot compare non numbers");
|
||||
}
|
||||
|
||||
public static void GreaterThanEquals(Automate au)
|
||||
{
|
||||
var one = au.Stack.Pop!();
|
||||
if(one.HasValue && one.VariantType == typeof(double))
|
||||
{
|
||||
var two = au.Stack.Pop!();
|
||||
if(two.HasValue && two.VariantType == typeof(double))
|
||||
{
|
||||
if(two.Get<double>() >= one.Get<double>())
|
||||
au.Stack.Push(Variant.Create(true));
|
||||
else
|
||||
au.Stack.Push(Variant.Create(false));
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot compare non numbers");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot compare non numbers");
|
||||
}
|
||||
|
||||
public static void Equals(Automate au)
|
||||
{
|
||||
var one = au.Stack.Pop!();
|
||||
if(one.HasValue && one.VariantType == typeof(double))
|
||||
{
|
||||
var two = au.Stack.Pop!();
|
||||
if(two.HasValue && two.VariantType == typeof(double))
|
||||
{
|
||||
if(two.Get<double>() == one.Get<double>())
|
||||
au.Stack.Push(Variant.Create(true));
|
||||
else
|
||||
au.Stack.Push(Variant.Create(false));
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot compare non numbers");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot compare non numbers");
|
||||
}
|
||||
}
|
54
src/Commands/Conversions.bf
Normal file
54
src/Commands/Conversions.bf
Normal file
|
@ -0,0 +1,54 @@
|
|||
namespace Automate.Commands;
|
||||
using System;
|
||||
class Conversions
|
||||
{
|
||||
public static void StringToNum(Automate au)
|
||||
{
|
||||
var obj = au.Stack.Pop!();
|
||||
if(obj.HasValue && obj.VariantType == typeof(String))
|
||||
{
|
||||
var res = double.Parse(obj.Get<String>());
|
||||
if(res case .Ok(let val))
|
||||
au.Stack.Push(Variant.Create(val));
|
||||
else
|
||||
au.ThrowError("The string is not a parseable number");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot convert to number, since the object is no string");
|
||||
}
|
||||
|
||||
public static void NumToString(Automate au)
|
||||
{
|
||||
var obj = au.Stack.Pop!();
|
||||
if(obj.HasValue && obj.VariantType == typeof(double))
|
||||
au.Stack.Push(Variant.Create(obj.Get<double>().ToString(.. new .()), true));
|
||||
else
|
||||
au.ThrowError("Cannot convert to string, since the object is no number");
|
||||
}
|
||||
|
||||
public static void StringToBool(Automate au)
|
||||
{
|
||||
var obj = au.Stack.Pop!();
|
||||
if(obj.HasValue && obj.VariantType == typeof(String))
|
||||
{
|
||||
var res = bool.Parse(obj.Get<String>());
|
||||
if(res case .Ok(let val))
|
||||
{
|
||||
au.Stack.Push(Variant.Create(val));
|
||||
}
|
||||
else
|
||||
au.ThrowError("Couldnt parse the string to a boolean");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot convert something that isnt a string to a bool");
|
||||
}
|
||||
|
||||
public static void BoolToString(Automate au)
|
||||
{
|
||||
var obj = au.Stack.Pop!();
|
||||
if(obj.HasValue && obj.VariantType == typeof(bool))
|
||||
au.Stack.Push(Variant.Create<String>(obj.Get<bool>().ToString(.. new .()),true));
|
||||
else
|
||||
au.ThrowError("Not a bool");
|
||||
}
|
||||
}
|
18
src/Commands/Directories.bf
Normal file
18
src/Commands/Directories.bf
Normal file
|
@ -0,0 +1,18 @@
|
|||
namespace Automate.Commands;
|
||||
using System;
|
||||
using System.IO;
|
||||
class Directories
|
||||
{
|
||||
public static void MakeDirectory(Automate au)
|
||||
{
|
||||
var loc = au.Stack.Pop!();
|
||||
if(loc.HasValue && loc.VariantType == typeof(String))
|
||||
{
|
||||
var res = Directory.CreateDirectory(loc.Get<String>());
|
||||
if(res case .Err)
|
||||
au.ThrowError(scope $"Could not create directory at {loc.Get<String>()}");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Input parameter for makedir is not a string");
|
||||
}
|
||||
}
|
34
src/Commands/Echo.bf
Normal file
34
src/Commands/Echo.bf
Normal file
|
@ -0,0 +1,34 @@
|
|||
namespace Automate.Commands;
|
||||
using System;
|
||||
using System.IO;
|
||||
class Echo
|
||||
{
|
||||
public static void Echo(Automate au)
|
||||
{
|
||||
var obj = au.Stack.Pop!();
|
||||
if(obj.HasValue && obj.VariantType == typeof(String))
|
||||
{
|
||||
au.ConsoleCallback(obj.Get<String>());
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot echo non String object");
|
||||
}
|
||||
|
||||
public static void Print(Automate au)
|
||||
{
|
||||
var obj = au.Stack.Pop!();
|
||||
if(obj.HasValue && obj.VariantType == typeof(String))
|
||||
{
|
||||
String text = scope .();
|
||||
var res = File.ReadAllText(obj.Get<String>(),text);
|
||||
if(res case .Ok)
|
||||
{
|
||||
au.ConsoleCallback(text);
|
||||
}
|
||||
else
|
||||
au.ThrowError(scope $"Could not read from file: {obj.Get<String>()}");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot print non String object");
|
||||
}
|
||||
}
|
59
src/Commands/Files.bf
Normal file
59
src/Commands/Files.bf
Normal file
|
@ -0,0 +1,59 @@
|
|||
namespace Automate.Commands;
|
||||
using System;
|
||||
using System.IO;
|
||||
class Files
|
||||
{
|
||||
public static void MakeFile(Automate au)
|
||||
{
|
||||
var loc = au.Stack.Pop!();
|
||||
if(loc.HasValue && loc.VariantType == typeof(String))
|
||||
{
|
||||
if(!File.Exists(loc.Get<String>()))
|
||||
{
|
||||
var res = File.WriteAllText(loc.Get<String>(),"");
|
||||
if(res case .Err)
|
||||
au.ThrowError(scope $"Could not create file at {loc.Get<String>()}");
|
||||
}
|
||||
else
|
||||
au.ThrowError("The file that is supposed to be created already exists");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Input parameter for makefile is not a string");
|
||||
}
|
||||
|
||||
public static void DeleteFile(Automate au)
|
||||
{
|
||||
var loc = au.Stack.Pop!();
|
||||
if(loc.HasValue && loc.VariantType == typeof(String))
|
||||
{
|
||||
if(File.Exists(loc.Get<String>()))
|
||||
{
|
||||
var res = File.Delete(loc.Get<String>());
|
||||
if(res case .Err)
|
||||
au.ThrowError( scope $"Could not delete file with the name: {loc.Get<String>()}");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot delete a file that doesnt exist");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Input parameter for deletefile is not a string");
|
||||
}
|
||||
|
||||
public static void CopyFile(Automate au)
|
||||
{
|
||||
var dest = au.Stack.Pop!();
|
||||
if(dest.HasValue && dest.VariantType == typeof(String))
|
||||
{
|
||||
var target = au.Stack.Pop!();
|
||||
if(target.HasValue && target.VariantType == typeof(String) && File.Exists(target.Get<String>()))
|
||||
{
|
||||
File.Copy(target.Get<String>(),dest.Get<String>())
|
||||
.IgnoreError();
|
||||
}
|
||||
else
|
||||
au.ThrowError("Invalid target file");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Destination is not a string or unavailable");
|
||||
}
|
||||
}
|
81
src/Commands/Functions.bf
Normal file
81
src/Commands/Functions.bf
Normal file
|
@ -0,0 +1,81 @@
|
|||
namespace Automate.Commands;
|
||||
using Automate;
|
||||
using System;
|
||||
class Functions
|
||||
{
|
||||
public static void Call(Automate au)
|
||||
{
|
||||
var obj = au.Stack.Pop!();
|
||||
if(obj.HasValue && obj.VariantType == typeof(String))
|
||||
{
|
||||
au.Instructions.Call(obj.Get<String>());
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot call function with a nonstring value");
|
||||
}
|
||||
|
||||
public static void Return(Automate au)
|
||||
{
|
||||
au.Instructions.Return();
|
||||
}
|
||||
|
||||
public static void Goto(Automate au)
|
||||
{
|
||||
var obj = au.Stack.Pop!();
|
||||
if(obj.HasValue && obj.VariantType == typeof(double))
|
||||
{
|
||||
au.Instructions.SetProgramCounter((.)obj.Get<double>());
|
||||
if(au.Instructions.GetProgramCounter() >= au.Instructions.MaxProgramCounter() || au.Instructions.GetProgramCounter() < 0)
|
||||
au.ThrowError("Program counter out of bounds");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot go to non number location");
|
||||
}
|
||||
|
||||
public static void GotoRelative(Automate au)
|
||||
{
|
||||
var obj = au.Stack.Pop!();
|
||||
if(obj.HasValue && obj.VariantType == typeof(double))
|
||||
{
|
||||
au.Instructions.SetProgramCounter(au.Instructions.GetProgramCounter() + (.)obj.Get<double>());
|
||||
if(au.Instructions.GetProgramCounter() >= au.Instructions.MaxProgramCounter() || au.Instructions.GetProgramCounter() < 0)
|
||||
au.ThrowError("Program counter out of bounds");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot go to non number location");
|
||||
}
|
||||
|
||||
public static void JumpIfZero(Automate au)
|
||||
{
|
||||
var obj = au.Stack.Pop!();
|
||||
if(obj.HasValue && obj.VariantType == typeof(double))
|
||||
{
|
||||
var one = au.Stack.Pop!();
|
||||
if(one.HasValue && one.VariantType == typeof(double))
|
||||
{
|
||||
if(one.Get<double>() == 0)
|
||||
au.Instructions.SetProgramCounter((.)obj.Get<double>());
|
||||
}
|
||||
else
|
||||
au.ThrowError("No valid value to compare to 0");
|
||||
}
|
||||
else
|
||||
au.ThrowError("No valid target jump value");
|
||||
}
|
||||
|
||||
public static void Jump(Automate au)
|
||||
{
|
||||
var obj = au.Stack.Pop!();
|
||||
if(obj.HasValue && obj.VariantType == typeof(double))
|
||||
{
|
||||
var value = au.Stack.Pop!();
|
||||
if(value.HasValue && value.VariantType == typeof(bool))
|
||||
{
|
||||
if(value.Get<bool>())
|
||||
au.Instructions.SetProgramCounter((.)obj.Get<double>());
|
||||
}
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot jump to a non numerical value");
|
||||
}
|
||||
}
|
175
src/Commands/Math.bf
Normal file
175
src/Commands/Math.bf
Normal file
|
@ -0,0 +1,175 @@
|
|||
namespace Automate.Commands;
|
||||
using System;
|
||||
class Math
|
||||
{
|
||||
public static void Add(Automate au)
|
||||
{
|
||||
var one = au.Stack.Pop!();
|
||||
if(one.HasValue && one.VariantType == typeof(double))
|
||||
{
|
||||
var two = au.Stack.Pop!();
|
||||
if(two.HasValue && two.VariantType == typeof(double))
|
||||
{
|
||||
au.Stack.Push(Variant.Create(one.Get<double>() + two.Get<double>()));
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot add non numbers");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot add non numbers");
|
||||
}
|
||||
|
||||
public static void Sub(Automate au)
|
||||
{
|
||||
var one = au.Stack.Pop!();
|
||||
if(one.HasValue && one.VariantType == typeof(double))
|
||||
{
|
||||
var two = au.Stack.Pop!();
|
||||
if(two.HasValue && two.VariantType == typeof(double))
|
||||
{
|
||||
au.Stack.Push(Variant.Create(two.Get<double>() - one.Get<double>() ));
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot sub non numbers");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot sub non numbers");
|
||||
}
|
||||
|
||||
public static void Mult(Automate au)
|
||||
{
|
||||
var one = au.Stack.Pop!();
|
||||
if(one.HasValue && one.VariantType == typeof(double))
|
||||
{
|
||||
var two = au.Stack.Pop!();
|
||||
if(two.HasValue && two.VariantType == typeof(double))
|
||||
{
|
||||
au.Stack.Push(Variant.Create(two.Get<double>() * one.Get<double>() ));
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot mult non numbers");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot mult non numbers");
|
||||
}
|
||||
|
||||
public static void Div(Automate au)
|
||||
{
|
||||
var one = au.Stack.Pop!();
|
||||
if(one.HasValue && one.VariantType == typeof(double))
|
||||
{
|
||||
if(one.Get<double>() == 0)
|
||||
au.ThrowError("Cannot divide by 0");
|
||||
else
|
||||
{
|
||||
var two = au.Stack.Pop!();
|
||||
if(two.HasValue && two.VariantType == typeof(double))
|
||||
{
|
||||
au.Stack.Push(Variant.Create(two.Get<double>() / one.Get<double>() ));
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot sub non numbers");
|
||||
}
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot sub non numbers");
|
||||
}
|
||||
|
||||
public static void Root(Automate au)
|
||||
{
|
||||
var one = au.Stack.Pop!();
|
||||
if(one.HasValue && one.VariantType == typeof(double))
|
||||
{
|
||||
au.Stack.Push(Variant.Create(System.Math.Sqrt(one.Get<double>())));
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot take the root of a non numerical value");
|
||||
}
|
||||
|
||||
public static void Square(Automate au)
|
||||
{
|
||||
var one = au.Stack.Pop!();
|
||||
if(one.HasValue && one.VariantType == typeof(double))
|
||||
{
|
||||
var val = one.Get<double>();
|
||||
au.Stack.Push(Variant.Create(val * val));
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot square non number");
|
||||
}
|
||||
|
||||
public static void Cube(Automate au)
|
||||
{
|
||||
var one = au.Stack.Pop!();
|
||||
if(one.HasValue && one.VariantType == typeof(double))
|
||||
{
|
||||
var val = one.Get<double>();
|
||||
au.Stack.Push(Variant.Create(val * val * val));
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot cube non number");
|
||||
}
|
||||
|
||||
public static void Pi(Automate au)
|
||||
{
|
||||
au.Stack.Push(Variant.Create(System.Math.PI_d));
|
||||
}
|
||||
|
||||
|
||||
public static void Modulo(Automate au)
|
||||
{
|
||||
var one = au.Stack.Pop!();
|
||||
if(one.HasValue && one.VariantType == typeof(double))
|
||||
{
|
||||
var two = au.Stack.Pop!();
|
||||
if(two.HasValue && two.VariantType == typeof(double))
|
||||
{
|
||||
au.Stack.Push(Variant.Create(two.Get<double>() % one.Get<double>()));
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot calculate the modulo of a non number");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot calculate the modulo of a non number");
|
||||
}
|
||||
|
||||
public static void Pow(Automate au)
|
||||
{
|
||||
var one = au.Stack.Pop!();
|
||||
if(one.HasValue && one.VariantType == typeof(double))
|
||||
{
|
||||
var two = au.Stack.Pop!();
|
||||
if(two.HasValue && two.VariantType == typeof(double))
|
||||
{
|
||||
au.Stack.Push(Variant.Create(System.Math.Pow(two.Get<double>(), one.Get<double>())));
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot take power of non number");
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot take power of non number");
|
||||
}
|
||||
|
||||
public static void Round(Automate au)
|
||||
{
|
||||
var obj = au.Stack.Pop!();
|
||||
if(obj.HasValue && obj.VariantType == typeof(double))
|
||||
{
|
||||
au.Stack.Push(Variant.Create(System.Math.Round(obj.Get<double>(),0)));
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot round a non number");
|
||||
}
|
||||
|
||||
public static void RoundFin(Automate au)
|
||||
{
|
||||
var obj = au.Stack.Pop!();
|
||||
if(obj.HasValue && obj.VariantType == typeof(double))
|
||||
{
|
||||
au.Stack.Push(Variant.Create(System.Math.Round(obj.Get<double>(),0,.AwayFromZero)));
|
||||
|
||||
}
|
||||
else
|
||||
au.ThrowError("Cannot round a non number");
|
||||
}
|
||||
}
|
38
src/Program.bf
Normal file
38
src/Program.bf
Normal file
|
@ -0,0 +1,38 @@
|
|||
namespace Automate;
|
||||
using System;
|
||||
using System.IO;
|
||||
class Program
|
||||
{
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
if(args.Count < 1)
|
||||
{
|
||||
Console.WriteLine("""
|
||||
Automate - A stack based scripting language thingy
|
||||
--------------------------------------------------
|
||||
Version: 1.0
|
||||
Author: Booklordofthedings
|
||||
Source Repository: https://Github.com/Booklordofthedings/automate
|
||||
--------------------------------------------------
|
||||
This is the compiled tool, to use it,
|
||||
simply pass the executeable a path to a readable
|
||||
automate script.
|
||||
A list of all valid commands is avilable in the source repo.
|
||||
""");
|
||||
return;
|
||||
}
|
||||
String text = new .();
|
||||
defer delete text;
|
||||
var res = File.ReadAllText(args[0],text);
|
||||
if(res case .Err)
|
||||
{
|
||||
Console.WriteLine("Automate: Could not read the file to execute. Maybe it doesnt exist or you dont have acess rights.");
|
||||
return;
|
||||
}
|
||||
|
||||
Automate o = new .();
|
||||
o.Instructions.LoadCode(text);
|
||||
o.Run();
|
||||
delete o;
|
||||
}
|
||||
}
|
47
src/cmd
Normal file
47
src/cmd
Normal file
|
@ -0,0 +1,47 @@
|
|||
//Instruction set
|
||||
x Create file //Create a file at the given location on disk or error if thats not possible for some reason
|
||||
x Copy file
|
||||
x Delete file
|
||||
o Rename file
|
||||
o Exists file
|
||||
x Print file
|
||||
|
||||
x Create Dir
|
||||
o Remove Dir
|
||||
o Copy Dir
|
||||
o Rename Dir
|
||||
o Exists Dir
|
||||
|
||||
x Add
|
||||
x Subtract
|
||||
x Multiply
|
||||
x Divide
|
||||
x Squareroot
|
||||
x Modulo
|
||||
x Pow
|
||||
x Square
|
||||
x Cube
|
||||
x Pi
|
||||
x Round
|
||||
x RoundFinance
|
||||
|
||||
x Lesser
|
||||
x Greater
|
||||
x LesserEquals
|
||||
x GreateEquals
|
||||
x Equals
|
||||
|
||||
x StringToBool
|
||||
x BoolToString
|
||||
x StringToDouble
|
||||
x DoubleToString
|
||||
|
||||
x Goto //Set the program counter to the given number
|
||||
x Goto relative //Change the program counter by the given number
|
||||
x JumpIfZero //Jump if the stack has a 0
|
||||
x JumpIf //Jump if the stack has a true
|
||||
o CMD //Call a shell command
|
||||
x Call
|
||||
x Return
|
||||
|
||||
x Print
|
Loading…
Add table
Reference in a new issue