public void compileXVARScript(StreamReader source, ImportedObject[] imports, BinaryWriter output) { Dictionary <string, VMObject> objects = new Dictionary <string, VMObject>(); double objPos = 0; #region Import logic output.Write(imports.ToArray().Length); foreach (ImportedObject e in imports) { objects.Add(e.Name, e.VObject); if (e.VObject.refValue >= objPos) { //Write the reference value as a double! output.Write(e.VObject.refValue); //Whether or not to literally interpolate the value output.Write(e.VObject.storeAsLiteral); //TODO here //Somehow convert the native functions relating to the object into virtual XVAR function //definitions MethodInfo[] methods = e.VObject.GetType().GetMethods(); try { int methodindex = 0; foreach (MethodInfo et in methods) { e.VObject.functions.Add(methodindex, new FunctionDeclaration() { nativeMethod = et }); e.VObject.functionIdentifiers.Add(et.Name, methodindex); methodindex += 1; } } catch (Exception) { //Must have already been added } //END TODO here if (e.VObject.storeAsLiteral) { byte[] data = e.VObject.Serialize(); output.Write(data.Length); output.Write(data); } objPos = e.VObject.refValue + 1; } } #endregion #region Compilation logic bool hascalled = false; long spos = output.BaseStream.Position; output.Write((long)0); while (!source.EndOfStream) { string instruction = source.ReadLine(); string[] parts = intellisplit(instruction); if (parts[0] == "unalloc") { //Opcode 3 try { output.Write((byte)3); output.Write(objects[parts[1]].refValue); objects.Remove(parts[1]); } catch (KeyNotFoundException) { throw new NullReferenceException("Invalid reference. Variable " + parts[1] + " has not been declared."); } } if (parts[0] == "allocstr") { //Opcode 2 output.Write((byte)2); //Store the string to a variable parts[1] = parts[1].Replace("\"", ""); output.Write(parts[1]); if (objects.Keys.Contains(parts[2])) { objects[parts[2]] = new VMString(parts[1]) { refValue = objPos }; } else { objects.Add(parts[2], new VMString(parts[1]) { refValue = objPos }); } output.Write(objPos); objPos += 1; } if (parts[0] == "ndinit") { if (!hascalled) { long cpos = output.BaseStream.Position; output.BaseStream.Position = spos; output.Write(cpos); output.BaseStream.Position = cpos; hascalled = true; } else { throw new ArgumentException("endinit may only be called once per session! What were you thinking?!?!?"); } } if (parts[0] == "call") { //Write out opcode (as byte) output.Write((byte)0); try { VMObject currentObj = objects[parts[1]]; //Write out index of reference object (as double) output.Write(currentObj.refValue); try { FunctionDeclaration function = currentObj.functions[currentObj.functionIdentifiers[parts[2]]]; //Write out index of function (as int32) output.Write(currentObj.functionIdentifiers[parts[2]]); //Write out length of parameters (as int32) string[] args; try { args = parts[3].Split(",".ToArray(), StringSplitOptions.RemoveEmptyEntries); if (args[0] == "null") { args = new string[0]; } } catch (Exception) { args = new string[0]; } output.Write(args.Length); foreach (string et in args) { //Write out each reference as a double output.Write(objects[et].refValue); } if (parts.Length == 5) { //Whether or not the output should be assigned to a variable output.Write(true); //The variable to assign it to if (objects.ContainsKey(parts[4])) { output.Write(objects[parts[4]].refValue); } else { VMObject tobj = (VMObject)function.returnType.GetConstructor(new Type[0]).Invoke(null); tobj.refValue = objPos; //Populate the object's methods objects.Add(parts[4], tobj); output.Write(objPos); objPos += 1; } } else { output.Write(false); } } catch (Exception) { throw new MethodAccessException("The function " + parts[2] + " does not exist."); } } catch (KeyNotFoundException) { throw new NullReferenceException("Invalid reference. Variable " + parts[1] + " has not been declared."); } } } #endregion }
public void compileXVARScript(StreamReader source, ImportedObject[] imports, BinaryWriter output) { Dictionary <string, VMObject> objects = new Dictionary <string, VMObject>(); double objPos = 0; #region Import logic output.Write(imports.ToArray().Length); foreach (ImportedObject e in imports) { objects.Add(e.Name, e.VObject); if (e.VObject.refValue >= objPos) { //Write the reference value as a double! output.Write(e.VObject.refValue); //Whether or not to literally interpolate the value output.Write(e.VObject.storeAsLiteral); //TODO here //Somehow convert the native functions relating to the object into virtual XVAR function //definitions MethodInfo[] methods = e.VObject.GetType().GetMethods(); try { int methodindex = 0; foreach (MethodInfo et in methods) { e.VObject.functions.Add(methodindex, new FunctionDeclaration() { nativeMethod = et }); e.VObject.functionIdentifiers.Add(et.Name, methodindex); methodindex += 1; } } catch (Exception) { //Must have already been added } //END TODO here if (e.VObject.storeAsLiteral) { byte[] data = e.VObject.Serialize(); output.Write(data.Length); output.Write(data); } objPos = e.VObject.refValue + 1; } } #endregion //Opcode 4 = Internal function offset declaration (long) #region Compilation logic long lastfunctionoffset = 0; bool hascalled = false; long spos = output.BaseStream.Position; int funcID = 0; output.Write((long)0); long zpos = output.BaseStream.Position; string currentFunction = ""; FunctionDeclaration mdec = new FunctionDeclaration(); Dictionary <string, long> lostandfound = new Dictionary <string, long>(); VMObject parentObject = null; while (!source.EndOfStream) { string instruction = source.ReadLine(); string[] parts = intellisplit(instruction); if (parts[0] == "function") { mdec = new FunctionDeclaration(); output.BaseStream.Position = lastfunctionoffset; //Length of function output.Write((int)0); currentFunction = parts[3]; //Return type foreach (KeyValuePair <double, Type> e in VMObject.types) { if (e.Value.Name == parts[1]) { output.Write(e.Key); break; } } //Associate function with object VMObject obj = objects[parts[2]]; parentObject = obj; output.Write(obj.refValue); int ival = obj.functions.Count + 1; funcID = ival; obj.functionIdentifiers.Add(parts[3], ival); //Write out the index of the function output.Write(ival); } if (parts[0] == "ndfunction") { long yval = output.BaseStream.Position; int tval = (int)(output.BaseStream.Position - lastfunctionoffset); output.BaseStream.Position = lastfunctionoffset; //Write function length output.Write(tval); //Data's already been written. Seek to beginning of stream! output.BaseStream.Position = yval; //Read the function back in output.BaseStream.Position = lastfunctionoffset; //Read function byte array byte[] mray = new byte[tval]; output.BaseStream.Read(mray, 0, mray.Length); mdec.function = mray; long previous = lastfunctionoffset; parentObject.functions.Add(funcID, mdec); lastfunctionoffset = output.BaseStream.Position; if (lostandfound.Keys.Contains(currentFunction)) { output.BaseStream.Position = lostandfound[currentFunction]; output.Write(previous); output.BaseStream.Position = lastfunctionoffset; } } if (parts[0] == "unalloc") { //Opcode 3 try { output.Write((byte)3); output.Write(objects[parts[1]].refValue); objects.Remove(parts[1]); } catch (KeyNotFoundException) { throw new NullReferenceException("Invalid reference. Variable " + parts[1] + " has not been declared."); } } if (parts[0] == "stralloc") { //Opcode 2 output.Write((byte)2); //Store the string to a variable parts[1] = parts[1].Replace("\"", ""); output.Write(parts[1]); if (objects.Keys.Contains(parts[2])) { objects[parts[2]] = new VMString(parts[1]) { refValue = objPos }; } else { objects.Add(parts[2], new VMString(parts[1]) { refValue = objPos }); } output.Write(objPos); objPos += 1; } if (parts[0] == "ndinit") { if (!hascalled) { long cpos = output.BaseStream.Position; output.BaseStream.Position = spos; output.Write(cpos - zpos); output.BaseStream.Position = cpos; hascalled = true; lastfunctionoffset = cpos; } else { throw new ArgumentException("endinit may only be called once per session! What were you thinking?!?!?"); } } if (parts[0] == "call") { //Write out opcode (as byte) VMObject currentObj = objects[parts[1]]; if (!currentObj.functionIdentifiers.ContainsKey(parts[2])) { output.Write((byte)4); long ntpos = output.BaseStream.Position; //Function offset to be determined output.Write((long)-1); lostandfound.Add(parts[2], ntpos); } else { output.Write((byte)0); try { //Write out index of reference object (as double) output.Write(currentObj.refValue); try { FunctionDeclaration function = currentObj.functions[currentObj.functionIdentifiers[parts[2]]]; //Write out index of function (as int32) output.Write(currentObj.functionIdentifiers[parts[2]]); //Write out length of parameters (as int32) string[] args; try { args = parts[3].Split(",".ToArray(), StringSplitOptions.RemoveEmptyEntries); if (args[0] == "null") { args = new string[0]; } } catch (Exception) { args = new string[0]; } output.Write(args.Length); foreach (string et in args) { //Write out each reference as a double output.Write(objects[et].refValue); } if (parts.Length == 5) { //Whether or not the output should be assigned to a variable output.Write(true); //The variable to assign it to if (objects.ContainsKey(parts[4])) { output.Write(objects[parts[4]].refValue); } else { VMObject tobj = (VMObject)function.returnType.GetConstructor(new Type[0]).Invoke(null); tobj.refValue = objPos; //Populate the object's methods objects.Add(parts[4], tobj); output.Write(objPos); objPos += 1; } } else { output.Write(false); } } catch (AccessViolationException) { } } catch (KeyNotFoundException) { throw new NullReferenceException("Invalid reference. Variable " + parts[1] + " has not been declared."); } } } } #endregion }
public VMObject Invoke(VMObject[] args) { //Parse the code in the script and return the resultant value BinaryReader mreader = new BinaryReader(internstream); while (true) { try { byte opcode = mreader.ReadByte(); if (opcode == 3) { vmInstance.internalobjects.Remove(mreader.ReadDouble()); } if (opcode == 2) { string txt = mreader.ReadString(); VMString mstr = new VMString(txt); mstr.refValue = mreader.ReadDouble(); if (vmInstance.internalobjects.Keys.Contains(mstr.refValue)) { vmInstance.internalobjects[mstr.refValue] = mstr; } else { vmInstance.internalobjects.Add(mstr.refValue, mstr); } } if (opcode == 1) { //CALL and RETURN statement double objIndex = mreader.ReadDouble(); VMObject obj = vmInstance.internalobjects[objIndex]; //Read in index of function (as a 32 bit integer) int functionIndex = mreader.ReadInt32(); FunctionDeclaration function = obj.functions[functionIndex]; //Read in array of parameters int paramlen = mreader.ReadInt32(); List <object> parameters = new List <object>(); for (int i = 0; i < paramlen; i++) { parameters.Add(vmInstance.internalobjects[mreader.ReadDouble()]); } return((VMObject)function.Invoke(parameters.ToArray(), obj)); } if (opcode == 0) { //CALL statement double objIndex = mreader.ReadDouble(); VMObject obj = vmInstance.internalobjects[objIndex]; //Read in index of function (as a 32 bit integer) int functionIndex = mreader.ReadInt32(); FunctionDeclaration function = obj.functions[functionIndex]; //Read in array of parameters int paramlen = mreader.ReadInt32(); List <object> parameters = new List <object>(); for (int i = 0; i < paramlen; i++) { parameters.Add(vmInstance.internalobjects[mreader.ReadDouble()]); } VMObject assignment = (VMObject)function.Invoke(parameters.ToArray(), obj); if (mreader.ReadBoolean()) { double assignmentVar = mreader.ReadDouble(); assignment.refValue = assignmentVar; if (vmInstance.internalobjects.Keys.Contains(assignmentVar)) { vmInstance.internalobjects[assignmentVar] = assignment; } else { vmInstance.internalobjects.Add(assignmentVar, assignment); } } } }catch (EndOfStreamException) { return(null); } } }