full rework

This commit is contained in:
Booklordofthedings 2024-08-12 19:36:30 +02:00
parent ece745a051
commit f473f33521
12 changed files with 1 additions and 881 deletions

View file

@ -1,101 +0,0 @@
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;
}
}

View file

@ -1,109 +0,0 @@
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;
}
}
}

View file

@ -1,65 +0,0 @@
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;
}
}
}

View file

@ -1,104 +0,0 @@
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");
}
}

View file

@ -1,54 +0,0 @@
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");
}
}

View file

@ -1,18 +0,0 @@
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");
}
}

View file

@ -1,34 +0,0 @@
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");
}
}

View file

@ -1,59 +0,0 @@
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");
}
}

View file

@ -1,81 +0,0 @@
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");
}
}

View file

@ -1,175 +0,0 @@
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");
}
}

View file

@ -1,38 +1,5 @@
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
View file

@ -1,47 +0,0 @@
//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