Skip to content

Instantly share code, notes, and snippets.

@sbarisic
Created June 4, 2018 19:57
Show Gist options
  • Save sbarisic/9f1f72fe718dd60f1fb6451901a2e602 to your computer and use it in GitHub Desktop.
Save sbarisic/9f1f72fe718dd60f1fb6451901a2e602 to your computer and use it in GitHub Desktop.
Shitcode
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