From 998fa271dba7f425ef2e73d0cb35206610331f8b Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Sat, 11 May 2024 19:23:23 +0200 Subject: [PATCH] initial commit --- .gitignore | 5 ++ BeefProj.toml | 18 ++++ BeefSpace.toml | 20 +++++ LICENSE | 21 +++++ README.md | 2 + automate.ico | Bin 0 -> 4286 bytes src/Automate.bf | 101 +++++++++++++++++++++ src/AutomateInstructions.bf | 109 ++++++++++++++++++++++ src/AutomateStack.bf | 65 ++++++++++++++ src/Commands/Comparisons.bf | 104 +++++++++++++++++++++ src/Commands/Conversions.bf | 54 +++++++++++ src/Commands/Directories.bf | 18 ++++ src/Commands/Echo.bf | 34 +++++++ src/Commands/Files.bf | 59 ++++++++++++ src/Commands/Functions.bf | 81 +++++++++++++++++ src/Commands/Math.bf | 175 ++++++++++++++++++++++++++++++++++++ src/Program.bf | 38 ++++++++ src/cmd | 47 ++++++++++ 18 files changed, 951 insertions(+) create mode 100644 .gitignore create mode 100644 BeefProj.toml create mode 100644 BeefSpace.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 automate.ico create mode 100644 src/Automate.bf create mode 100644 src/AutomateInstructions.bf create mode 100644 src/AutomateStack.bf create mode 100644 src/Commands/Comparisons.bf create mode 100644 src/Commands/Conversions.bf create mode 100644 src/Commands/Directories.bf create mode 100644 src/Commands/Echo.bf create mode 100644 src/Commands/Files.bf create mode 100644 src/Commands/Functions.bf create mode 100644 src/Commands/Math.bf create mode 100644 src/Program.bf create mode 100644 src/cmd diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..82fc9a9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +build/ +recovery/ +AutomateCl/repositories/ +AutomateCl/build +BeefSpace_User.toml \ No newline at end of file diff --git a/BeefProj.toml b/BeefProj.toml new file mode 100644 index 0000000..f51ed9c --- /dev/null +++ b/BeefProj.toml @@ -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" diff --git a/BeefSpace.toml b/BeefSpace.toml new file mode 100644 index 0000000..3f29d80 --- /dev/null +++ b/BeefSpace.toml @@ -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 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d8a8fd1 --- /dev/null +++ b/LICENSE @@ -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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..28e9136 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# Automate +Stack based crossplatform* automation language written in Beef diff --git a/automate.ico b/automate.ico new file mode 100644 index 0000000000000000000000000000000000000000..ca77e4b12a7e84b9df807e9e8d655f5ae22da0be GIT binary patch literal 4286 zcmd^Cu~Gst5M74iN~~<5w6?Rt>-Y%&1#17o&dP7NPXYY_8yyPf)_pk7iJ2tim;_}w z=CR3Uci+qA?ifTy_LpXOw4uP+Yb*RJF5Sk-r2xlsmdQdY* zLrHE|7j$esUiTV8d#0}zKeVt1a;Kh=9`s(A+I z#?N;rE$`t&mhrTV$NP_cPFbG8?c<%gKt0xqS;V+G7$X)nQ=I-9;{7_9AJP!Y$vO92 z{*;CgH+)0)PA#z>gfx`q9-^TZcaDbI+{b7*_Pogzv#3k>`=-AZx3392)PQm9H{H)G zH4pKhQiIEnKKz#+l Console.WriteLine; + + private Dictionary 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(new .(line, 1), true)); + else if(line.StartsWith('<')) + Stack.Push(Variant.Create(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; + } +} \ No newline at end of file diff --git a/src/AutomateInstructions.bf b/src/AutomateInstructions.bf new file mode 100644 index 0000000..311f46b --- /dev/null +++ b/src/AutomateInstructions.bf @@ -0,0 +1,109 @@ +namespace Automate; +using System; +using System.Collections; +class AutomateInstructions +{ + + private List _Instructions = new .(200) ~ delete _; + private List _FunctionCalls = new .(100) ~ delete _; + private Dictionary _Labels = new .(5) ~ delete _; + private Dictionary _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; + } + } +} \ No newline at end of file diff --git a/src/AutomateStack.bf b/src/AutomateStack.bf new file mode 100644 index 0000000..e7b1f19 --- /dev/null +++ b/src/AutomateStack.bf @@ -0,0 +1,65 @@ +namespace Automate; +using System; +using System.Collections; +class AutomateStack +{ + private List _Stack = new List(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; + } + } +} \ No newline at end of file diff --git a/src/Commands/Comparisons.bf b/src/Commands/Comparisons.bf new file mode 100644 index 0000000..a058847 --- /dev/null +++ b/src/Commands/Comparisons.bf @@ -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() < one.Get()) + 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() > one.Get()) + 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() <= one.Get()) + 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() >= one.Get()) + 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() == one.Get()) + 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"); + } +} \ No newline at end of file diff --git a/src/Commands/Conversions.bf b/src/Commands/Conversions.bf new file mode 100644 index 0000000..71d074d --- /dev/null +++ b/src/Commands/Conversions.bf @@ -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()); + 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().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()); + 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(obj.Get().ToString(.. new .()),true)); + else + au.ThrowError("Not a bool"); + } +} \ No newline at end of file diff --git a/src/Commands/Directories.bf b/src/Commands/Directories.bf new file mode 100644 index 0000000..8b6af2d --- /dev/null +++ b/src/Commands/Directories.bf @@ -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()); + if(res case .Err) + au.ThrowError(scope $"Could not create directory at {loc.Get()}"); + } + else + au.ThrowError("Input parameter for makedir is not a string"); + } +} \ No newline at end of file diff --git a/src/Commands/Echo.bf b/src/Commands/Echo.bf new file mode 100644 index 0000000..0fce70c --- /dev/null +++ b/src/Commands/Echo.bf @@ -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()); + } + 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(),text); + if(res case .Ok) + { + au.ConsoleCallback(text); + } + else + au.ThrowError(scope $"Could not read from file: {obj.Get()}"); + } + else + au.ThrowError("Cannot print non String object"); + } +} \ No newline at end of file diff --git a/src/Commands/Files.bf b/src/Commands/Files.bf new file mode 100644 index 0000000..1fd1133 --- /dev/null +++ b/src/Commands/Files.bf @@ -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())) + { + var res = File.WriteAllText(loc.Get(),""); + if(res case .Err) + au.ThrowError(scope $"Could not create file at {loc.Get()}"); + } + 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())) + { + var res = File.Delete(loc.Get()); + if(res case .Err) + au.ThrowError( scope $"Could not delete file with the name: {loc.Get()}"); + } + 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())) + { + File.Copy(target.Get(),dest.Get()) + .IgnoreError(); + } + else + au.ThrowError("Invalid target file"); + } + else + au.ThrowError("Destination is not a string or unavailable"); + } +} \ No newline at end of file diff --git a/src/Commands/Functions.bf b/src/Commands/Functions.bf new file mode 100644 index 0000000..d3a96f1 --- /dev/null +++ b/src/Commands/Functions.bf @@ -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()); + } + 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()); + 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()); + 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() == 0) + au.Instructions.SetProgramCounter((.)obj.Get()); + } + 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()) + au.Instructions.SetProgramCounter((.)obj.Get()); + } + } + else + au.ThrowError("Cannot jump to a non numerical value"); + } +} \ No newline at end of file diff --git a/src/Commands/Math.bf b/src/Commands/Math.bf new file mode 100644 index 0000000..803e2f5 --- /dev/null +++ b/src/Commands/Math.bf @@ -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() + two.Get())); + } + 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() - one.Get() )); + } + 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() * one.Get() )); + } + 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() == 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() / one.Get() )); + } + 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()))); + } + 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(); + 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(); + 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() % one.Get())); + } + 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(), one.Get()))); + } + 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(),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(),0,.AwayFromZero))); + + } + else + au.ThrowError("Cannot round a non number"); + } +} \ No newline at end of file diff --git a/src/Program.bf b/src/Program.bf new file mode 100644 index 0000000..f8c0717 --- /dev/null +++ b/src/Program.bf @@ -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; + } +} \ No newline at end of file diff --git a/src/cmd b/src/cmd new file mode 100644 index 0000000..1d4e924 --- /dev/null +++ b/src/cmd @@ -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 \ No newline at end of file