public async Task <bool> Initialize() { if (IsInitialized) { return(true); } return(await StandardLibrary.InitializeStandardLib() && await Task.Run(() => { if (IsInitialized) { return true; } bool success; lock (initializationLock) { if (IsInitialized) { return true; } success = InternalInitialize(); IsInitialized = success; HadInitializationError = !success; } InitializationStatusChange?.Invoke(true); return success; })); }
private bool InternalInitialize() { try { _symbols = StandardLibrary.GetSymbolTable(); var files = EntryImporter.GetPossibleAssociatedFiles(Pcc); var gameFiles = MELoadedFiles.GetFilesLoadedInGame(Pcc.Game); foreach (var fileName in Enumerable.Reverse(files)) { if (gameFiles.TryGetValue(fileName, out string path) && File.Exists(path)) { using var pcc = MEPackageHandler.OpenMEPackage(path); if (!StandardLibrary.ResolveAllClassesInPackage(pcc, ref _symbols)) { return(false); } } } return(StandardLibrary.ResolveAllClassesInPackage(Pcc, ref _symbols)); } catch (Exception e) { return(false); } }
static void GenerateCode(Node root, string outputPath, Scope scope) { var generator = new CodeGenerator(); string name = Path.GetFileNameWithoutExtension(outputPath); string filename = Path.GetFileName(outputPath); string directory = Path.GetDirectoryName(outputPath); directory = directory == "" ? "./" : directory; AssemblyName assemblyName = new AssemblyName(name); generator.Assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave, directory); generator.Module = generator.Assembly.DefineDynamicModule(name, filename); StandardLibrary.Build(generator, scope); generator.Type = generator.Module.DefineType("Program"); MethodBuilder mainMethod = generator.Type.DefineMethod("Main", MethodAttributes.Static, typeof(void), Type.EmptyTypes); generator.Assembly.SetEntryPoint(mainMethod); generator.Method = mainMethod; generator.Generator = mainMethod.GetILGenerator(); root.Generate(generator); generator.Type.CreateType(); generator.Module.CreateGlobalFunctions(); generator.Assembly.Save(filename); }
public CodeGenerator(string fileName) { typecount = 0; funccount = 0; string clearname = Path.GetFileNameWithoutExtension(fileName); EXEFileName = clearname + ".exe"; ScopedGenerators = new Stack <ILGenerator>(); AssemblyName assemName = new AssemblyName("TigerProgram"); ILAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemName, AssemblyBuilderAccess.RunAndSave, Path.GetDirectoryName(fileName)); ILModule = ILAssembly.DefineDynamicModule(clearname, EXEFileName); BuiltInFunctiontoBuilder = new Dictionary <string, MethodBuilder>(); //Creating the Standard Library StandardLibrary = ILModule.DefineType("StandardLibrary", TypeAttributes.Public | TypeAttributes.Class); GenerateCodeForBuiltInFunctions(); StandardLibrary.CreateType(); //Creating the Program class Program = ILModule.DefineType("Program", TypeAttributes.Public | TypeAttributes.Class); EntryPoint = Program.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static); ILAssembly.SetEntryPoint(EntryPoint); EnterGenerationScope(EntryPoint.GetILGenerator()); }
public static StandardLibrary Instance() { if (_stdlib == null) { _stdlib = new StandardLibrary(); } return(_stdlib); }
public RootScope(Context context) { _context = context; _functions = new FunctionCollection(); _variables = new VariableCollection(); _classes = new ClassCollection(); _objects = new ObjectCollection(); _arrays = new ArrayCollection(); StandardLibrary.Populate(_functions); StandardLibrary.Populate(_variables); }
public static Function CompileFunctionBodyAST(ExportEntry parentExport, string scriptText, Function func, MessageLog log, FileLib lib = null) { var symbols = lib?.GetSymbolTable() ?? StandardLibrary.GetSymbolTable(); symbols.RevertToObjectStack(); if (parentExport.IsClass && symbols.TryGetType(parentExport.ObjectName, out Class containingClass)) { int funcIdx = containingClass.Functions.FindIndex(fun => fun.Name == func.Name); Function originalFunction = containingClass.Functions[funcIdx]; originalFunction.Body = func.Body; originalFunction.Body.Outer = originalFunction; for (int i = 0; i < func.Parameters.Count && i < originalFunction.Parameters.Count; i++) { originalFunction.Parameters[i].UnparsedDefaultParam = func.Parameters[i].UnparsedDefaultParam; } originalFunction.Locals.Clear(); if (!containingClass.Name.CaseInsensitiveEquals("Object")) { symbols.GoDirectlyToStack(((Class)containingClass.Parent).GetInheritanceString()); symbols.PushScope(containingClass.Name); } CodeBodyParser.ParseFunction(originalFunction, scriptText, symbols, log); return(originalFunction); } //in state if (parentExport.Parent is ExportEntry classExport && classExport.IsClass && symbols.TryGetType(classExport.ObjectNameString, out Class cls) && cls.States.FirstOrDefault(s => s.Name.CaseInsensitiveEquals(parentExport.ObjectNameString)) is State state && state.Functions.FirstOrDefault(f => f.Name == func.Name) is Function canonicalFunction) { canonicalFunction.Body = func.Body; canonicalFunction.Body.Outer = canonicalFunction; for (int i = 0; i < func.Parameters.Count && i < canonicalFunction.Parameters.Count; i++) { canonicalFunction.Parameters[i].UnparsedDefaultParam = func.Parameters[i].UnparsedDefaultParam; } canonicalFunction.Locals.Clear(); symbols.GoDirectlyToStack(((Class)cls.Parent).GetInheritanceString()); symbols.PushScope(cls.Name); symbols.PushScope(state.Name); CodeBodyParser.ParseFunction(canonicalFunction, scriptText, symbols, log); return(canonicalFunction); } return(null); }
/// <summary> /// Generate a function in the StandardLibrary /// </summary> /// <param name="returntype"></param> /// <param name="parameters"></param> /// <returns></returns> private MethodBuilder CreateSTDFunction(Type returntype, Type[] parameters) { return(StandardLibrary.DefineMethod(GetNewFunctionName(), MethodAttributes.Public | MethodAttributes.Static, returntype, parameters)); }
public static void BuildTigerProgram(string output, InstructionNode programExp) { string fileName = Path.GetFileNameWithoutExtension(output); string exeName = fileName + ".exe"; //Definimos el nombre del ensamblado AssemblyName assemblyName = new AssemblyName(fileName); //Creamos un assemblyBuilder con el nombre del ensamblado deseado y en modo save AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave, Path.GetDirectoryName(output)); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(fileName, exeName); TypeBuilder typeBuilder = moduleBuilder.DefineType("TigerProgram", TypeAttributes.Public | TypeAttributes.Class); MethodBuilder methodBuilder = typeBuilder.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new Type[0]); StandardLibrary stdlib = new StandardLibrary(moduleBuilder); ILGenerator gen = methodBuilder.GetILGenerator(); ILCodeGenerator cg = new ILCodeGenerator(moduleBuilder, typeBuilder, gen, stdlib); var result = gen.DeclareLocal(typeof(int)); //asigno 0 a result gen.Emit(OpCodes.Ldc_I4_0); gen.Emit(OpCodes.Stloc, result); // Begin the try block. gen.BeginExceptionBlock(); programExp.GenCode(cg); if (!(programExp.ReturnType is VoidType))//saco el resultado de la pila { gen.Emit(OpCodes.Pop); } // Start the catch block for any Exception gen.BeginCatchBlock(typeof(Exception)); PropertyInfo message = typeof(Exception).GetProperty("Message"); MethodInfo getMessage = message.GetGetMethod(); gen.Emit(OpCodes.Callvirt, getMessage); MethodInfo writeLine = typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }); gen.Emit(OpCodes.Call, writeLine); MethodInfo readLine = typeof(Console).GetMethod("ReadLine"); gen.Emit(OpCodes.Call, readLine); gen.Emit(OpCodes.Pop); //pongo 1 en result gen.Emit(OpCodes.Ldc_I4_1); gen.Emit(OpCodes.Stloc, result); gen.EndExceptionBlock(); //en result estara el codigo de salida gen.Emit(OpCodes.Ldloc, result); gen.Emit(OpCodes.Ret); typeBuilder.CreateType(); assemblyBuilder.SetEntryPoint(methodBuilder); assemblyBuilder.Save(exeName); }
static void Main(string[] args) { Lexer lexer = new Lexer(); Session session = new Session(); CodeGenerator codeGenerator = new CodeGenerator(session); //Add the standard library StandardLibrary.AddStandardLibrary(codeGenerator); while (true) { try { string input = Console.ReadLine(); var tokens = lexer.Tokenize(input); Parser parser = new Parser(tokens, session.BinaryOperatorPrecedence); foreach (var currentTree in parser.Parse()) { currentTree.GenerateCode(codeGenerator, SyntaxTreeGeneratorData.Empty); if (currentTree is FunctionSyntaxTree) { FunctionSyntaxTree funcTree = (FunctionSyntaxTree)currentTree; if (funcTree.Prototype.Name != "") { Console.WriteLine("Defined function '" + funcTree.Prototype.Name + "'"); } } if (currentTree is ExternalFunctionSyntaxTree) { ExternalFunctionSyntaxTree funcTree = (ExternalFunctionSyntaxTree)currentTree; if (funcTree.Prototype.Name != "") { Console.WriteLine("Defined external function '" + funcTree.Prototype.Name + "' referencing: " + funcTree.FuncReference); } } } if (codeGenerator.Methods.ContainsKey("main")) { var mainMethod = codeGenerator.Methods["main"]; mainMethod.Invoke(null, null); } } catch (ParserException e) { Console.WriteLine(e.Message); } catch (CodeGeneratorException e) { Console.WriteLine(e.Message); } codeGenerator.Methods.Remove("main"); } }
public Evaluator(Parser interpreter) { p = interpreter; interpreter.evaluator = this; var includeStatement = new Operation("include") { canBeGlobal = true, association = Operation.Association.None, unaryFunction = (none) => { List <string> toInclude = new List <string>(); p.Eat("l curly"); while (p.CurrentToken != "r curly") { toInclude.Add(p.GetIdentifier().ToLower()); if (p.CurrentToken != "r curly") { p.Eat("comma"); } } p.Eat(); /*toInclude.Reverse(); * * Lexer.inputText = Lexer.inputText.Substring(Lexer.pointer); * Lexer.pointer = 0; * foreach (var file in toInclude) * { * Lexer.inputText = System.IO.File.ReadAllText(file + ".hpy") + "\n" + Lexer.inputText; * } * * p.lastLexerPoint = 0; * p.PreviousToken = null; * p.CurrentToken = Lexer.GetNextToken();*/ return(Value.VOID); } }; var functionDeclaration = new Operation("function") { canBeGlobal = true, association = Operation.Association.None, unaryFunction = (none) => { if (p.depth > 0) { throw p.Exception("Can only declare a function in the global scope"); } if (p.CurrentToken == "inline") { p.Eat(); } string name = p.GetIdentifier(); List <string> argNames = new List <string>(); List <Value.BatchType> argTypes = new List <Value.BatchType>(); p.Eat("l bracket"); while (p.CurrentToken != "r bracket") { argNames.Add(p.Eat <string>("identifier")); p.Eat("colon"); argTypes.Add(Value.ParseType(p.GetIdentifier())); if (p.CurrentToken != "r bracket") { p.Eat("comma"); } } p.Eat(); Value.BatchType returnType = Value.BatchType.Void; if (p.CurrentToken == "colon") { p.Eat("colon"); returnType = Value.ParseType(p.GetIdentifier()); } var func = UserFunctions.Get(name, argTypes); int id = UserFunctions.GetID(func); Variables.suffix = "_F" + id; int index = p.output.Length; string originalOutput = p.output; if (func.inline) { for (int i = 0; i < argNames.Count; i++) { Variables.Create(argNames[i] + "_I" + id, argTypes[i]); } } else { p.Comment("BEGIN FUNCTION DECLARATION: " + UserFunctions.GetSignature(name, argTypes) + ": " + returnType.ToString().ToLower()); p.output += ":func_" + id + "\n"; for (int i = 0; i < argNames.Count; i++) { Variables.Create(argNames[i], new Value(argTypes[i], "%~" + (i + 1)), 1); } } currentContext = func; p.EvaluateBlock(); currentContext = null; if (!func.inline) { if (!p.output.Trim().EndsWith("goto :EOF")) { //Variables.variables.Exists(x => false); Variables.DeleteOutOfScopeVariables(); p.output += "goto :EOF\n"; } } //p.Comment("END FUNCTION DECLARATION"); if (UserFunctions.IsRecursive(func, func)) { throw p.Exception("Recursion is forbidden"); } Variables.suffix = ""; string newOutput = p.output; p.output = originalOutput; string code = newOutput.Substring(index); func.body = code; return(Value.VOID); } }; var variableDeclaration = new Operation("var") { canBeGlobal = true, association = Operation.Association.None, unaryFunction = (none) => { int depth = p.depth; string name; Value val; if (depth == 0) { if (p.CurrentToken == "global") { p.Eat(); } name = p.Eat <string>("identifier"); var v = Variables.Get(name); p.Eat("colon"); var type = Value.ParseType(p.GetIdentifier()); if (p.CurrentToken == "equals") { p.Eat(); val = Evaluate(); if (type != val.type) { throw p.Exception("Attempt to assign value of type " + val.type + " to a variable of type " + type); } Variables.Assign(name, val); } return(Value.VOID); } if (p.CurrentToken == "global") { p.Eat(); depth = 0; } name = p.Eat <string>("identifier"); if (Variables.variables.Exists(x => x.name == name)) { //throw p.Exception("Variable already exists in this scope: " + name); } if (p.CurrentToken == "colon") { p.Eat(); var type = Value.ParseType(p.GetIdentifier()); if (Value.TypeEquals(type, Value.BatchType.Void)) { throw p.Exception("Cannot declare a variable of type Void"); } if (p.CurrentToken != "equals") { Variables.Create(name, type, depth); return(Value.VOID); } p.Eat("equals"); val = Evaluate(); if (type != val.type) { throw p.Exception("Attempt to assign value of type " + val.type + " to a variable of type " + type); } Variables.Create(name, val, depth); } else { if (depth == 0) { throw p.Exception("Variables in the global scope must have their types specified"); } p.Eat("equals"); val = Evaluate(); if (Value.TypeEquals(val.type, Value.BatchType.Void)) { throw p.Exception("Cannot declare a variable of type Void"); } if (depth > 0) { Variables.Create(name, val, depth); } } return(Value.VOID); } }; var numberLiteral = new Operation("number") { eatOperator = false, association = Operation.Association.None, unaryFunction = (none) => new Value(Value.BatchType.Int, p.Eat <float>().ToString()) }; var stringLiteral = new Operation("string") { eatOperator = false, association = Operation.Association.None, unaryFunction = (none) => new Value(Value.BatchType.String, p.Eat <string>()) }; var boolLiteral = new Operation("bool") { eatOperator = false, association = Operation.Association.None, unaryFunction = (none) => new Value(Value.BatchType.Bool, p.Eat <bool>() ? "1==1" : "1==0") }; var bracket = new Operation("l bracket") { association = Operation.Association.None, unaryFunction = (none) => { var outp = Evaluate(); p.Eat("r bracket"); if (outp.type == Value.BatchType.Int) { return(new Value(Value.BatchType.Int, "(" + outp.value + ")")); } var temp = Variables.CreateTemporary(outp.value); return(new Value(outp.type, temp)); } }; var neg = new Operation("minus") { association = Operation.Association.Right, unaryFunction = (right) => new Value(Value.BatchType.Int, "-" + right) }; var mul = new Operation("multiply") { binaryFunction = (left, right) => binaryOp(left, right, Value.BatchType.Int, "*") }; var div = new Operation("divide") { binaryFunction = (left, right) => binaryOp(left, right, Value.BatchType.Int, "/") }; var mod = new Operation("modulus") { binaryFunction = (left, right) => binaryOp(left, right, Value.BatchType.Int, "%%") }; var add = new Operation("plus") { binaryFunction = (left, right) => binaryOp(left, right, Value.BatchType.Int, "+") }; var concat = new Operation("concat") { binaryFunction = (left, right) => new Value(Value.BatchType.String, left.value + right.value) }; var sub = new Operation("minus") { binaryFunction = (left, right) => binaryOp(left, right, Value.BatchType.Int, "-") }; var identifier = new Operation("identifier") { eatOperator = false, association = Operation.Association.None, unaryFunction = (none) => { string name = p.Eat <string>("identifier").ToString(); if (StandardLibrary.Exists(name)) { List <Value> args = new List <Value>(); p.Eat("l bracket"); while (p.CurrentToken != "r bracket") { args.Add(Evaluate()); if (p.CurrentToken != "r bracket") { p.Eat("comma"); } } p.Eat(); return(StandardLibrary.CallFunction(name, args.ToArray())); } else { if (p.CurrentToken == "l bracket") { p.Comment("FUNCTION CALL TO " + name); List <Value> args = new List <Value>(); p.Eat("l bracket"); while (p.CurrentToken != "r bracket") { args.Add(Evaluate()); if (p.CurrentToken != "r bracket") { p.Eat("comma"); } } p.Eat(); var func = UserFunctions.Get(name, args.Select(x => x.type).ToList()); int id = UserFunctions.GetID(func); currentContext?.calls.Add(func); if (func.inline) { for (int i = 0; i < func.argumentNames.Count; i++) { Variables.Create(func.argumentNames[i] + "_I" + id, args[i]); } p.output += func.body; for (int i = 0; i < func.argumentNames.Count; i++) { Variables.Delete(func.argumentNames[i] + "_I" + id); } } else { p.output += "call :func_" + id + " " + string.Join(" ", args.Select(x => (x.type == Value.BatchType.String && x.value.Contains(" ")) ? "\"" + x.value + "\"" : x.value)) + "\n"; } if (func.returnType == Value.BatchType.Void) { p.Comment("END FUNCTION CALL"); return(Value.VOID); } else { //string temp = Variables.CreateTemporary("%return_value%"); p.Comment("END FUNCTION CALL"); return(new Value(func.returnType, "%return_value%")); } } if (p.CurrentToken == "increment") { p.Eat(); Variables.VerifyType(name, Value.BatchType.Int); var va = Variables.Get(name); p.output += "set /a var_" + name + (va.depth > 0 ? Variables.suffix : "") + "+=1\n"; return(Value.VOID); } else if (p.CurrentToken == "decrement") { p.Eat(); Variables.VerifyType(name, Value.BatchType.Int); var va = Variables.Get(name); p.output += "set /a var_" + name + (va.depth > 0 ? Variables.suffix : "") + "-=1\n"; return(Value.VOID); } else if (p.CurrentToken == "add") { p.Eat(); var v = Evaluate(); var va = Variables.Get(name); p.output += "set /a var_" + name + (va.depth > 0 ? Variables.suffix : "") + "+=" + v.value + "\n"; return(Value.VOID); } else if (p.CurrentToken == "subtract") { p.Eat(); var v = Evaluate(); var va = Variables.Get(name); p.output += "set /a var_" + name + (va.depth > 0 ? Variables.suffix : "") + "-=" + v.value + "\n"; return(Value.VOID); } else if (p.CurrentToken == "string add") { p.Eat(); var v = Evaluate(); var va = Variables.Get(name); p.output += "set var_" + name + (va.depth > 0 ? Variables.suffix : "") + "=!var_" + name + Variables.suffix + "!" + v.value + "\n"; return(Value.VOID); } else if (p.CurrentToken == "inc mul") { p.Eat(); var v = Evaluate(); var va = Variables.Get(name); p.output += "set /a var_" + name + (va.depth > 0 ? Variables.suffix : "") + "*=" + v.value + "\n"; return(Value.VOID); } else if (p.CurrentToken == "inc div") { p.Eat(); var v = Evaluate(); var va = Variables.Get(name); p.output += "set /a var_" + name + (va.depth > 0 ? Variables.suffix : "") + "/=" + v.value + "\n"; return(Value.VOID); } else if (p.CurrentToken == "equals") { p.Eat(); var v = Evaluate(); if (!Variables.Exists(name) && !name.Contains("%")) { throw p.Exception("No such variable exists: " + name); } Variables.Assign(name, v); return(Value.VOID); } else { if (name.Contains("%")) { //var temp1 = Variables.CreateTemporary("var_" + name); //var temp2 = Variables.CreateTemporary(""); //var temp2name = Variables.NameFromTempReference(temp2); //p.EmitLn("call set " + temp2name + "=%%" + temp1 + "%%"); return(new Value(Value.BatchType.Indeterminate, "!var_" + name + "!")); } else { //return Variables.GetReference(name); if (currentContext != null && currentContext.inline) { return(Variables.GetReference(name + "_I" + UserFunctions.GetID(currentContext))); } else { return(Variables.GetReference(name)); } } //return Variables.GetReference(name); } } } }; var openBracket = new Operation("l curly") { eatOperator = false, association = Operation.Association.None, unaryFunction = (none) => { p.Eat(); return(new Value(Value.BatchType.Void, "")); } }; var closeBracket = new Operation("r curly") { eatOperator = false, association = Operation.Association.None, unaryFunction = (none) => { p.Eat(); return(new Value(Value.BatchType.Void, "")); } }; var ifStatement = new Operation("if") { association = Operation.Association.None, unaryFunction = (none) => { int selfid = ++ifid; var condition = EvaluateCondition(); string output = ""; string temp = Variables.CreateTemporary(condition.value); output += "if " + temp + " (\n"; output += "goto if_" + selfid + "\n"; output += ")"; string ifContents = p.PreEvaluateBlock(); List <string> elseIfContents = new List <string>(); int elseifs = 0; while (p.CurrentToken == "elseif") { elseifs++; p.Eat(); condition = EvaluateCondition(); temp = Variables.CreateTemporary(condition.value); output += " else (\nif " + temp + " (\n"; output += "goto if_" + selfid + "_elseif_" + elseifs + "\n"; output += ")"; elseIfContents.Add(p.PreEvaluateBlock()); } string elseContents = null; if (p.CurrentToken == "else") { p.Eat(); output += " else (\n"; output += "goto if_" + selfid + "_else\n"; output += ")"; elseContents = p.PreEvaluateBlock(); } for (int i = 0; i < elseifs; i++) { output += "\n)"; } output += "\ngoto if_" + selfid + "_end"; output += "\n:if_" + selfid + "\n"; output += ifContents; output += "goto if_" + selfid + "_end\n"; for (int i = 1; i <= elseifs; i++) { output += ":if_" + selfid + "_elseif_" + i + "\n"; output += elseIfContents[i - 1]; output += "goto if_" + selfid + "_end\n"; } if (elseContents != null) { output += ":if_" + selfid + "_else\n"; output += elseContents; } output += ":if_" + selfid + "_end\n"; p.output += output; return(new Value(Value.BatchType.Void, "")); } }; var whileLoop = new Operation("while") { association = Operation.Association.None, unaryFunction = (none) => { int loop = ++loopid; p.output += ":loop_" + loop + "\n"; var condition = EvaluateCondition(); var temp = Variables.CreateTemporary(condition.value); p.output += "if not " + temp + " goto loop_" + loop + "_end\n"; p.loopIDs.Push(loop); p.EvaluateBlock(); p.loopIDs.Pop(); p.output += "goto loop_" + loop + "\n"; p.output += ":loop_" + loop + "_end"; return(new Value(Value.BatchType.Void, "")); } }; var untilLoop = new Operation("until") { association = Operation.Association.None, unaryFunction = (none) => { int loop = ++loopid; p.output += ":loop_" + loop + "\n"; var condition = EvaluateCondition(); var temp = Variables.CreateTemporary(condition.value); p.output += "if " + temp + " goto loop_" + loop + "_end\n"; p.loopIDs.Push(loop); p.EvaluateBlock(); p.loopIDs.Pop(); p.output += "goto loop_" + loop + "\n"; p.output += ":loop_" + loop + "_end"; return(new Value(Value.BatchType.Void, "")); } }; void VerifyType(Value v, Value.BatchType type) { if (v.type != type) { throw p.Exception("Expected value of type " + type + ", not " + v.type); } } var forLoop = new Operation("from") { association = Operation.Association.None, unaryFunction = (none) => { var start = Evaluate(); VerifyType(start, Value.BatchType.Int); p.Eat("to"); var end = Evaluate(); VerifyType(end, Value.BatchType.Int); bool upwards; try { upwards = int.Parse(start.value) < int.Parse(end.value); } catch { upwards = true; } Value step; if (p.CurrentToken == "by") { p.Eat(); step = Evaluate(); VerifyType(step, Value.BatchType.Int); } else { step = new Value(Value.BatchType.Int, upwards ? "1" : "-1"); } bool usingVariable = p.CurrentToken == "with"; string name = null; string reference = null; if (usingVariable) { p.Eat(); string varname = p.Eat <string>(); reference = Variables.Create(varname, start, p.depth).value; // %var_x% name = "var_" + varname; // var_x } else { reference = Variables.CreateTemporaryInt(start.value); // %temp_x% name = Variables.NameFromTempReference(reference); // temp_x } int loop = ++loopid; p.output += ":loop" + loop + "\n"; p.output += "if not " + reference + " " + (upwards ? "LSS" : "GTR") + " " + end.value + " goto loop" + loop + "_end\n"; p.EvaluateBlock(); p.loopIDs.Pop(); p.output += "set /a " + name + (usingVariable ? Variables.suffix : "") + "+=" + step.value + "\n"; p.output += "goto loop" + loop + "\n"; p.output += ":loop" + loop + "_end\n"; if (usingVariable) { Variables.Delete(Variables.NameFromReference(reference)); } return(Value.VOID); } }; var continueStatement = new Operation("continue") { association = Operation.Association.None, unaryFunction = (none) => { return(new Value(Value.BatchType.Void, "goto loop" + p.loopIDs.Peek())); } }; var breakStatement = new Operation("break") { association = Operation.Association.None, unaryFunction = (none) => { return(new Value(Value.BatchType.Void, "goto loop" + p.loopIDs.Peek() + "_end")); } }; var not = new Operation("not") { association = Operation.Association.Right, unaryFunction = (right) => new Value(Value.BatchType.Bool, "not " + right) }; Value BoolOp(Value left, Value right, string op) { var tempL = Variables.FlexibleTemporary(left); var tempR = Variables.FlexibleTemporary(right); var tempResult = Variables.CreateTemporary("1==0"); var name = Variables.NameFromTempReference(tempResult); p.EmitLn("if " + tempL + " " + op + " " + tempR + " set " + name + "=1==1"); return(new Value(Value.BatchType.Bool, tempResult)); } Value IntComparisonOp(Value left, Value right, string op) { VerifyType(left, Value.BatchType.Int); VerifyType(right, Value.BatchType.Int); return(BoolOp(left, right, op)); } var eq = new Operation("double equal") { binaryFunction = (left, right) => BoolOp(left, right, "EQU") }; var neq = new Operation("not equal") { binaryFunction = (left, right) => BoolOp(left, right, "NEQ") }; var gr = new Operation("greater than") { binaryFunction = (left, right) => IntComparisonOp(left, right, "GTR") }; var ls = new Operation("less than") { binaryFunction = (left, right) => IntComparisonOp(left, right, "LSS") }; var geq = new Operation("greater or equal") { binaryFunction = (left, right) => IntComparisonOp(left, right, "GEQ") }; var leq = new Operation("less or equal") { binaryFunction = (left, right) => IntComparisonOp(left, right, "LEQ") }; var semicolon = new Operation("semicolon") { association = Operation.Association.None, unaryFunction = (none) => { return(Value.VOID); } }; var and = new Operation("and") { binaryFunction = (left, right) => { string reference = Variables.CreateTemporary("1==0"); string name = Variables.NameFromTempReference(reference); //p.output += NewTempBoolVar("1==0"); //int id = varid; p.output += "if " + left.value + " ( if " + right.value + " ( \n"; p.output += "set " + name + "=1==1\n"; p.output += ") \n)\n"; return(new Value(Value.BatchType.Bool, reference)); } }; var or = new Operation("or") { binaryFunction = (left, right) => { string reference = Variables.CreateTemporary("1==0"); string name = Variables.NameFromTempReference(reference); //p.output += NewTempBoolVar("1==1"); //int id = varid; p.output += "if " + left.value + " set " + name + "=1==1\n"; p.output += "if " + right.value + " set " + name + "=1==1\n"; return(new Value(Value.BatchType.Bool, reference)); } }; /* * var arrayLiteral = new Operation("l square") * { * association = Operation.Association.None, * unaryFunction = (none) => * { * string array = ""; * while(p.CurrentToken != "r square") * { * array += Evaluate() + " "; * * if (p.CurrentToken != "r square") * { * p.Eat("comma"); * } * } * p.Eat(); * * return new Value(Value.BatchType.Array, array.TrimEnd()); * } * };*/ var returnStatement = new Operation("return") { association = Operation.Association.None, unaryFunction = (none) => { if (currentContext == null) { throw p.Exception("Can only return a value from within a function"); } Value v; if (p.CurrentToken == "semicolon") { v = Value.VOID; } else { v = Evaluate(); p.output += "set " + (v.type == Value.BatchType.Int ? "/a " : "") + "\"return_value=" + v.value + "\"\n"; } if (currentContext.returnType != v.type) { throw p.Exception("Must return value of type " + currentContext.returnType + ", not " + v.type); } //returnValueType = v.type; int depth = p.depth; p.depth = 0; Variables.DeleteOutOfScopeVariables(); p.depth = depth; /*foreach (var name in variablesDeclaredInsideFunction) * { * name.de * }*/ return(new Value(Value.BatchType.Void, currentContext.inline ? "" : "goto :EOF")); } }; var referenceOf = new Operation("ampersand") { association = Operation.Association.None, unaryFunction = (none) => { var name = p.GetIdentifier(); if (name.Contains("%")) { return(new Value(Value.BatchType.String, name)); } var val = Variables.Get(name); return(new Value(Value.BatchType.String, name + (val.depth > 0 ? Variables.suffix : ""))); } }; var deleteStatement = new Operation("delete") { association = Operation.Association.None, unaryFunction = (none) => { var var = p.GetIdentifier(); Variables.Delete(var, true); return(Value.VOID); } }; var asStatement = new Operation("as") { association = Operation.Association.Left, unaryFunction = (left) => { VerifyType(left, Value.BatchType.Indeterminate); return(new Value(Value.ParseType(p.GetIdentifier()), left.value)); } }; void register(Operation op) { precedences.Last().Add(op); } void precedence() { precedences.Add(new List <Operation>()); } precedence(); register(semicolon); precedence(); register(referenceOf); //register(toStringLiteral); //register(thisLiteral); //register(baseLiteral); register(bracket); //register(undefinedLiteral); //register(arrayLiteral); register(numberLiteral); register(stringLiteral); register(boolLiteral); //register(tableLiteral); //register(charLiteral); ////register(instantiation); precedence(); register(identifier); //register(methodCall); //register(traverse); //register(index); precedence(); register(asStatement); precedence(); register(variableDeclaration); precedence(); register(neg); register(not); //precedence(); //register(pow); precedence(); register(mul); register(div); register(mod); precedence(); register(concat); register(add); register(sub); precedence(); register(eq); register(neq); register(gr); register(ls); register(geq); register(leq); precedence(); register(and); precedence(); register(or); //precedence(); //register(conditional); precedence(); register(closeBracket); register(openBracket); register(ifStatement); register(whileLoop); register(untilLoop); //register(includeStatement); //register(forEachLoop); register(continueStatement); register(breakStatement); register(functionDeclaration); //register(funcLiteral); register(returnStatement); register(deleteStatement); register(forLoop); //register(structureLiteral); //register(include); //register(tryCatch); //register(throwStatement); }
static void Main(string[] args) { CalculationContext userContext = new CalculationContext(); userContext.AssignContext(StandardLibrary.GenerateStandardContext()); /* * FinishedFunction length2d = linker.BuildFunction(constructor.Construct(tokenizer.Tokenize( * "sqrt(x^2 + y^2)")), userContext, new string[] { * "x", "y" }); * userContext.FunctionTable.AssignItem("length2d", length2d); * userContext.FunctionTable.AssignItem("length3d", linker.BuildFunction(constructor.Construct(tokenizer.Tokenize( * "sqrt(x^2 + y^2 + z^2)")), userContext, new string[] { * "x", "y", "z" })); * userContext.FunctionTable.AssignItem("distance2d", linker.BuildFunction(constructor.Construct(tokenizer.Tokenize( * "length2d(x2 - x1, y2 - y1)")), userContext, new string[] { * "x1", "y1", "x2", "y2" })); * userContext.FunctionTable.AssignItem("distance3d", linker.BuildFunction(constructor.Construct(tokenizer.Tokenize( * "length3d(x2 - x1, y2 - y1, z2 - z1)")), userContext, new string[] { * "x1", "y1", "z1", "x2", "y2", "z2" })); */ while (true) { Console.ForegroundColor = ConsoleColor.Green; Console.Write("> "); string input = Console.ReadLine(); Console.ResetColor(); try { if (String.IsNullOrEmpty(input)) { continue; } if (input.StartsWith("~")) { if (input.StartsWith("~help")) { Console.WriteLine("Try those inputs: "); Console.ForegroundColor = ConsoleColor.Gray; Console.WriteLine("2 + 2"); Console.WriteLine("f(x) = e^x"); Console.WriteLine("myVar = f(4)"); Console.ResetColor(); void printCommand(string name, string desc, string[] parameters) { Console.ForegroundColor = ConsoleColor.Cyan; Console.Write("~{0}", name); Console.ForegroundColor = ConsoleColor.Yellow; for (int i = 0; i < parameters.Length; ++i) { Console.Write(" [{0}]", parameters[i]); } Console.ResetColor(); Console.Write(" - "); Console.ForegroundColor = ConsoleColor.Gray; Console.WriteLine(desc); Console.ResetColor(); } Console.WriteLine(); Console.WriteLine("List of commands: "); printCommand("help", "this command", new string[0]); printCommand("summary", "prints what functions does your library have", new string[0]); printCommand("library", "prints all trees of all functions in your library", new string[0]); printCommand("lexer", "divides expression into tokens, that's all", new string[] { "expr" }); printCommand("tree", "prints function tree", new string[] { "func" }); printCommand("test", "test function with random parameters for correctness and effectiveness", new string[] { "func" }); printCommand("optimize", "look how your function can be optimized", new string[] { "func" }); printCommand("dx", "find differential with respect to 1st parameter", new string[] { "func" }); printCommand("dy", "find differential with respect to 2nd parameter", new string[] { "func" }); printCommand("dz", "find differential with respect to 3rd parameter", new string[] { "func" }); continue; } if (input.StartsWith("~summary")) { PrintLibrarySummary(userContext); continue; } if (input.StartsWith("~library")) { PrintLibrary(userContext); continue; } if (input.StartsWith("~tree ")) { string funcName = input.Substring(6).Trim(' '); visualizer.VisualizeAsTree(userContext.FunctionTable[funcName].TopNode, userContext); continue; } if (input.StartsWith("~lexer ")) { string expression = input.Substring(7).Trim(' '); Token[] tokens = lexer.Tokenize(expression); Console.Write("Tokens: [ "); foreach (Token token in tokens) { switch (token) { case NumberToken _: Console.ForegroundColor = ConsoleColor.White; break; case SymbolToken _: Console.ForegroundColor = ConsoleColor.Yellow; break; case IdentifierToken _: Console.ForegroundColor = ConsoleColor.Cyan; break; } Console.Write("{0} ", token.ToString()); Console.ResetColor(); } Console.WriteLine("]\n"); continue; } if (input.StartsWith("~test ")) { TestInput(input, userContext); continue; } if (input.StartsWith("~dx ")) { FindDifferentialInput(input, 0, userContext); continue; } if (input.StartsWith("~dy ")) { FindDifferentialInput(input, 1, userContext); continue; } if (input.StartsWith("~dz ")) { FindDifferentialInput(input, 2, userContext); continue; } if (input.StartsWith("~optimize ")) { OptimizeInput(input, userContext); continue; } throw new Exception("Unknown command"); } string expressionString = input; TreeNode firstHalfTree = null; int equalsPos = input.IndexOf('='); if (equalsPos > 0) { expressionString = input.Substring(equalsPos + 1); string identifierString = input.Substring(0, equalsPos); Token[] firstHalfTokens = lexer.Tokenize(identifierString); firstHalfTree = parser.Construct(firstHalfTokens); switch (firstHalfTree) { case UndefinedFunctionTreeNode fDefinition: DefineFunctionInput(fDefinition, expressionString, userContext); break; case UndefinedVariableTreeNode vDefinition: DefineVariableInput(vDefinition, expressionString, userContext); break; default: throw new Exception("Unknown syntax"); } } else { CalculateInput(input, userContext); } } catch (Exception ex) { Console.WriteLine(String.Format("Error: {0}", ex.Message)); } Console.WriteLine(); } }
protected GameContext(IGraphicsPlugin graphics, IInputPlugin input, IAudioPlugin audio, ITimerPlugin timer, IResourceContext predefinedResources) { Timer = timer; Graphics = graphics; Input = input; Audio = audio; var sprites = predefinedResources.GetPredefinedSprites(this); Sprites = new IndexedResourceManager <GameSprite>(sprites); var sounds = predefinedResources.GetPredefinedSounds(this); Sounds = new IndexedResourceManager <GameSound>(sounds); var backgrounds = predefinedResources.GetPredefinedBackgrounds(this); Backgrounds = new IndexedResourceManager <GameBackground>(backgrounds); var fonts = predefinedResources.GetPredefinedFonts(this); Fonts = new IndexedResourceManager <GameFont>(fonts); var paths = predefinedResources.GetPredefinedPaths(this); Paths = new IndexedResourceManager <GamePath>(paths); var scripts = predefinedResources.GetPredefinedScripts(this); Scripts = new IndexedResourceManager <GameScript>(scripts); var timelines = predefinedResources.GetPredefinedTimelines(this); Timelines = new IndexedResourceManager <GameTimeline>(timelines); var objects = predefinedResources.GetPredefinedObjects(this); Objects = new IndexedResourceManager <GameObject>(objects); foreach (var gameObject in Objects) { gameObject.OnRegisterEvents(); } Instances = new IndexedResourceManager <IInstance>(100001); var rooms = predefinedResources.GetPredefinedRooms(this); Rooms = new IndexedResourceManager <GameRoom>(rooms); RoomOrder = rooms.Select(r => r.Id).ToList(); var triggers = predefinedResources.GetPredefinedTriggers(this); Triggers = new IndexedResourceManager <ITrigger>(triggers); Instances.SetNextIndex(predefinedResources.NextInstanceId); Sprites.SetNextIndex(predefinedResources.NextSpriteId); Objects.SetNextIndex(predefinedResources.NextObjectId); Rooms.SetNextIndex(predefinedResources.NextRoomId); Graphics.Load += Graphics_Load; Graphics.Draw += Graphics_Update; Input.KeyPress += Input_KeyPress; Library = new StandardLibrary(this); Init(); }