Created
June 4, 2018 19:57
-
-
Save sbarisic/9f1f72fe718dd60f1fb6451901a2e602 to your computer and use it in GitHub Desktop.
Shitcode
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
using System.Globalization; | |
namespace Bsm { | |
public class BsmObject { | |
public object Value; | |
public BsmObject(object Val) { | |
Value = Val; | |
} | |
public BsmObject() { | |
} | |
public override string ToString() { | |
return Value?.ToString() ?? "null"; | |
} | |
} | |
public class BsmFunction : BsmObject { | |
List<string> Source; | |
BsmNativeFunction Native; | |
public List<string> ArgumentNames = new List<string>(); | |
public BsmFunction() { | |
Value = Source = new List<string>(); | |
} | |
public BsmFunction(BsmNativeFunction Native) { | |
Value = this.Native = Native; | |
} | |
public void AddArgument(string Name) { | |
ArgumentNames.Add(Name); | |
} | |
public void AppendLine(string Line) { | |
if (Source == null && Native != null) | |
throw new Exception("Can't append line to a native function"); | |
Source.Add(Line); | |
} | |
public virtual void Invoke(BLang B) { | |
if (Native != null) | |
Native(B); | |
else | |
B.RunLines(Source.ToArray()); | |
} | |
} | |
public delegate void BsmNativeFunction(BLang B); | |
public class BLang { | |
Dictionary<string, BsmObject> Globals; | |
Stack<Dictionary<string, BsmObject>> Locals; | |
BsmObject CurrentObject; | |
BsmFunction CurrentFunc { | |
get { | |
return CurrentObject as BsmFunction; | |
} | |
} | |
public BLang() { | |
Globals = new Dictionary<string, BsmObject>(); | |
Locals = new Stack<Dictionary<string, BsmObject>>(); | |
RegisterGlobal("print", new BsmFunction((B) => { | |
BsmObject[] Args = B.Locals.Peek().ToArray().Select((KV) => KV.Value).ToArray(); | |
foreach (var Arg in Args) | |
Console.Write(Arg); | |
Console.WriteLine(); | |
})); | |
} | |
public void RegisterGlobal(string Name, BsmObject Obj) { | |
Globals.Add(Name, Obj); | |
} | |
public void Run(string Src) { | |
RunLines(Src.Trim().Replace("\r", "").Replace(';', '\n').Split('\n').Where((Str) => !string.IsNullOrWhiteSpace(Str)).ToArray()); | |
} | |
public void RunLines(params string[] Lines) { | |
foreach (var L in Lines) | |
RunLine(L); | |
} | |
public void RunLine(string Line) { | |
Line = Line.Trim(); | |
string[] Tokens = Tokenize(Line); | |
switch (Tokens[0]) { | |
case "func": | |
if (CurrentObject != null) | |
throw new Exception("Cannot declare a function while declaring another object"); | |
CurrentObject = new BsmFunction(); | |
for (int i = 3; i < Tokens.Length - 1; i++) { | |
if (i % 2 == 0 && Tokens[i] == ",") | |
continue; | |
CurrentFunc.AddArgument(Tokens[i]); | |
} | |
RegisterGlobal(Tokens[1], CurrentObject); | |
break; | |
case "end": | |
CurrentObject = null; | |
break; | |
default: { | |
if (CurrentFunc != null) | |
CurrentFunc.AppendLine(Line); | |
else { | |
if (Tokens[0] == "var") { | |
Console.WriteLine("Variable definition!"); | |
} else if (Globals.ContainsKey(Tokens[0])) { | |
List<object> Arguments = new List<object>(); | |
if (Tokens[1] == "(" && Tokens[Tokens.Length - 1] == ")") { | |
for (int i = 2; i < Tokens.Length - 1; i++) { | |
if (i % 2 != 0 && Tokens[i] == ",") | |
continue; | |
Dictionary<string, BsmObject> LocalObjects = null; | |
if (Locals.Count > 0) | |
LocalObjects = Locals.Peek(); | |
if (double.TryParse(Tokens[i], NumberStyles.Any, CultureInfo.InvariantCulture, out double D)) { | |
Arguments.Add(D); | |
} else if (Tokens[i].StartsWith("\"") && Tokens[i].EndsWith("\"")) { | |
Arguments.Add(Tokens[i].Substring(1, Tokens[i].Length - 2)); | |
} else if (LocalObjects?.ContainsKey(Tokens[i]) ?? false) { | |
Arguments.Add(LocalObjects[Tokens[i]].Value); | |
} else if (Globals.ContainsKey(Tokens[i])) { | |
Arguments.Add(Globals[Tokens[i]]); | |
} else | |
throw new Exception("Invalid argument " + Tokens[i]); | |
} | |
Locals.Push(new Dictionary<string, BsmObject>()); | |
Dictionary<string, BsmObject> CurrentLocals = Locals.Peek(); | |
object[] ArgumentsArr = Arguments.ToArray(); | |
int ArgIdx = 0; | |
foreach (var ArgName in ((BsmFunction)Globals[Tokens[0]]).ArgumentNames) | |
CurrentLocals.Add(ArgName, new BsmObject(ArgumentsArr[ArgIdx++])); | |
int NameIdx = 0; | |
for (int i = ArgIdx; i < ArgumentsArr.Length; i++) | |
CurrentLocals.Add("_arg" + (NameIdx++).ToString(), new BsmObject(ArgumentsArr[i])); | |
(Globals[Tokens[0]] as BsmFunction).Invoke(this); | |
Locals.Pop(); | |
} else if (Tokens[1] == "=") { | |
throw new Exception("Assignment not supported"); | |
} else | |
throw new Exception("Invalid operation on line " + Line); | |
} else | |
throw new Exception("Unknown identifier " + Tokens[0]); | |
} | |
break; | |
} | |
} | |
} | |
static string[] Tokenize(string Line) { | |
List<string> Tokens = new List<string>(); | |
bool InQuote = false; | |
StringBuilder SB = new StringBuilder(); | |
char[] Symbols = new char[] { '(', ')', '{', '}', '+', '-', '*', '/', '[', ']', ',' }; | |
foreach (var Chr in Line) { | |
if (Chr == '"') { | |
InQuote = !InQuote; | |
if (SB.Length != 0) { | |
if (!InQuote) | |
Tokens.Add('"' + SB.ToString() + '"'); | |
else | |
Tokens.Add(SB.ToString()); | |
SB.Length = 0; | |
} | |
continue; | |
} | |
if (!InQuote) { | |
if (char.IsWhiteSpace(Chr)) { | |
if (SB.Length != 0) { | |
Tokens.Add(SB.ToString()); | |
SB.Length = 0; | |
} | |
continue; | |
} else if (Symbols.Contains(Chr)) { | |
if (SB.Length != 0) { | |
Tokens.Add(SB.ToString()); | |
SB.Length = 0; | |
} | |
Tokens.Add(Chr.ToString()); | |
continue; | |
} | |
} | |
SB.Append(Chr); | |
} | |
if (SB.Length != 0) { | |
Tokens.Add(SB.ToString()); | |
SB.Length = 0; | |
} | |
return Tokens.ToArray(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment