PageRenderTime 112ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/Aurora/AuroraDotNetEngine/CompilerTools/CSCodeGenerator.cs

https://bitbucket.org/VirtualReality/aurora-sim
C# | 3413 lines | 2479 code | 407 blank | 527 comment | 602 complexity | 7996c0e698533e0a6ab24dd9d668b6c2 MD5 | raw file
  1. /*
  2. * Copyright (c) Contributors, http://aurora-sim.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the Aurora-Sim Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Text;
  30. using Tools;
  31. using Aurora.ScriptEngineParser;
  32. namespace Aurora.ScriptEngine.AuroraDotNetEngine.CompilerTools
  33. {
  34. public static class Extension
  35. {
  36. public static bool CompareWildcards(this string WildString, string Mask, bool IgnoreCase)
  37. {
  38. int i = 0;
  39. if (String.IsNullOrEmpty(Mask))
  40. return false;
  41. if (Mask == "*")
  42. return true;
  43. while (i != Mask.Length)
  44. {
  45. if (CompareWildcard(WildString, Mask.Substring(i), IgnoreCase))
  46. return true;
  47. while (i != Mask.Length && Mask[i] != ';')
  48. i += 1;
  49. if (i != Mask.Length && Mask[i] == ';')
  50. {
  51. i += 1;
  52. while (i != Mask.Length && Mask[i] == ' ')
  53. i += 1;
  54. }
  55. }
  56. return false;
  57. }
  58. public static bool CompareWildcard(this string WildString, string Mask, bool IgnoreCase)
  59. {
  60. int i = 0, k = 0;
  61. while (k != WildString.Length)
  62. {
  63. if ((i + 1) > Mask.Length)
  64. return true;
  65. switch (Mask[i])
  66. {
  67. case '*':
  68. if ((i + 1) >= Mask.Length)
  69. return true;
  70. while (k != WildString.Length)
  71. {
  72. if (CompareWildcard(WildString.Substring(k + 1), Mask.Substring(i + 1), IgnoreCase))
  73. return true;
  74. k += 1;
  75. }
  76. return false;
  77. case '?':
  78. break;
  79. default:
  80. if (IgnoreCase == false && WildString[k] != Mask[i])
  81. return false;
  82. if (IgnoreCase && Char.ToLower(WildString[k]) != Char.ToLower(Mask[i]))
  83. return false;
  84. break;
  85. }
  86. i += 1;
  87. k += 1;
  88. }
  89. if (k == WildString.Length)
  90. {
  91. if (i == Mask.Length || Mask[i] == ';' || Mask[i] == '*')
  92. return true;
  93. }
  94. return false;
  95. }
  96. }
  97. public class CSCodeGenerator : IDisposable
  98. {
  99. private readonly List<string> AfterFuncCalls = new List<string>();
  100. private readonly HashSet<string> DTFunctions = new HashSet<string>();
  101. private readonly List<string> FuncCalls = new List<string>();
  102. // public Dictionary<string, string> IenFunctions = new Dictionary<string, string>();
  103. private readonly Dictionary<string, GlobalVar> GlobalVariables = new Dictionary<string, GlobalVar>();
  104. private Dictionary<string, SYMBOL> DuplicatedGlobalVariables = new Dictionary<string, SYMBOL>();
  105. private Dictionary<string, Dictionary<string, SYMBOL>> DuplicatedLocalVariables = new Dictionary<string, Dictionary<string, SYMBOL>>();
  106. /// <summary>
  107. /// This saves the variables in methods so that we can make sure multiple variables do not have the same name, and if they do, rename/assign them to the correct variable name
  108. /// </summary>
  109. private readonly Dictionary<string, GlobalVar> MethodVariables = new Dictionary<string, GlobalVar>();
  110. private readonly List<string> MethodsToAdd = new List<string>();
  111. /// <summary>
  112. /// This contains a list of variables that we need to rename because of some constraint
  113. /// </summary>
  114. private readonly Dictionary<string, VarRename> VariablesToRename = new Dictionary<string, VarRename>();
  115. private readonly Dictionary<string, List<ArgumentDeclarationList>> m_allMethods =
  116. new Dictionary<string, List<ArgumentDeclarationList>>();
  117. /// <summary>
  118. /// Param 1 - the API function name, Param 2 - the API name
  119. /// </summary>
  120. private readonly Dictionary<string, IScriptApi> m_apiFunctions = new Dictionary<string, IScriptApi>();
  121. private readonly Compiler m_compiler;
  122. private bool FuncCntr;
  123. private bool IsParentEnumerable;
  124. private bool IsaGlobalVar;
  125. public Dictionary<string, ObjectList> LocalMethodArguements = new Dictionary<string, ObjectList>();
  126. public Dictionary<string, string> LocalMethods = new Dictionary<string, string>();
  127. private string OriginalScript = "";
  128. private bool isAdditionExpression;
  129. private int m_CSharpCol; // the current column of generated C# code
  130. private int m_CSharpLine; // the current line of generated C# code
  131. private SYMBOL m_astRoot;
  132. private int m_braceCount; // for indentation
  133. private int m_indentWidth = 4; // for indentation
  134. private bool m_isInEnumeratedDeclaration;
  135. private Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> m_positionMap;
  136. private Parser p;
  137. /// <summary>
  138. /// Creates an 'empty' CSCodeGenerator instance.
  139. /// </summary>
  140. public CSCodeGenerator(Compiler compiler)
  141. {
  142. #region DTFunctions
  143. // api funtions that can return a time delay only
  144. // must be type DateTime in stub files and implementation
  145. DTFunctions.Add("llAddToLandBanList");
  146. DTFunctions.Add("llAddToLandPassList");
  147. DTFunctions.Add("llAdjustSoundVolume");
  148. DTFunctions.Add("llCloseRemoteDataChannel");
  149. DTFunctions.Add("llCreateLink");
  150. DTFunctions.Add("llDialog");
  151. DTFunctions.Add("llEjectFromLand");
  152. DTFunctions.Add("llEmail");
  153. DTFunctions.Add("llGiveInventory");
  154. DTFunctions.Add("llInstantMessage");
  155. DTFunctions.Add("llLoadURL");
  156. DTFunctions.Add("llMakeExplosion");
  157. DTFunctions.Add("llMakeFire");
  158. DTFunctions.Add("llMakeFountain");
  159. DTFunctions.Add("llMakeSmoke");
  160. DTFunctions.Add("llMapDestination");
  161. DTFunctions.Add("llOffsetTexture");
  162. DTFunctions.Add("llOpenRemoteDataChannel");
  163. DTFunctions.Add("llParcelMediaCommandList");
  164. DTFunctions.Add("llPreloadSound");
  165. DTFunctions.Add("llRefreshPrimURL");
  166. DTFunctions.Add("llRemoteDataReply");
  167. DTFunctions.Add("llRemoteLoadScript");
  168. DTFunctions.Add("llRemoteLoadScriptPin");
  169. DTFunctions.Add("llRemoveFromLandBanList");
  170. DTFunctions.Add("llRemoveFromLandPassList");
  171. DTFunctions.Add("llResetLandBanList");
  172. DTFunctions.Add("llResetLandPassList");
  173. DTFunctions.Add("llRezAtRoot");
  174. DTFunctions.Add("llRezObject");
  175. DTFunctions.Add("llRotateTexture");
  176. DTFunctions.Add("llScaleTexture");
  177. DTFunctions.Add("llSetLinkTexture");
  178. DTFunctions.Add("llSetLocalRot");
  179. DTFunctions.Add("llSetParcelMusicURL");
  180. DTFunctions.Add("llSetPos");
  181. DTFunctions.Add("llSetPrimURL");
  182. DTFunctions.Add("llSetRot");
  183. DTFunctions.Add("llSetTexture");
  184. DTFunctions.Add("llSleep");
  185. DTFunctions.Add("llTeleportAgentHome");
  186. DTFunctions.Add("llTextBox");
  187. DTFunctions.Add("osTeleportAgent");
  188. DTFunctions.Add("osTeleportOwner");
  189. /* suspended: some API functions are not compatible with IEnum
  190. // Api functions that can return a delay, a value or breakable in timeslices
  191. // must be IEnumerator in stub, interface and implementation files
  192. IenFunctions.Add("llRequestAgentData", "LSL_Types.LSLString");
  193. IenFunctions.Add("llRequestInventoryData", "LSL_Types.LSLString");
  194. IenFunctions.Add("llSendRemoteData", "LSL_Types.LSLString");
  195. IenFunctions.Add("llXorBase64Strings", "LSL_Types.LSLString");
  196. IenFunctions.Add("llRequestSimulatorData", "LSL_Types.LSLString");
  197. IenFunctions.Add("llParcelMediaQuery", "LSL_Types.list");
  198. IenFunctions.Add("llGetPrimMediaParams", "LSL_Types.list");
  199. IenFunctions.Add("llSetPrimMediaParams", "LSL_Types.LSLInteger");
  200. IenFunctions.Add("llClearPrimMedia", "LSL_Types.LSLInteger");
  201. IenFunctions.Add("llModPow", "LSL_Types.LSLInteger");
  202. IenFunctions.Add("llGetNumberOfNotecardLines", "LSL_Types.LSLString");
  203. IenFunctions.Add("llGetParcelPrimOwners", "LSL_Types.list");
  204. IenFunctions.Add("llGetNotecardLine", "LSL_Types.LSLString");
  205. */
  206. // the rest will be directly called
  207. #endregion
  208. ResetCounters();
  209. m_compiler = compiler;
  210. m_apiFunctions = compiler.ScriptEngine.GetAllFunctionNamesAPIs();
  211. }
  212. /// <summary>
  213. /// Get the mapping between LSL and C# line/column number.
  214. /// </summary>
  215. /// <returns>Dictionary\<KeyValuePair\<int, int\>, KeyValuePair\<int, int\>\>.</returns>
  216. public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> PositionMap
  217. {
  218. get { return m_positionMap; }
  219. }
  220. /// <summary>
  221. /// Get the mapping between LSL and C# line/column number.
  222. /// </summary>
  223. /// <returns>SYMBOL pointing to root of the abstract syntax tree.</returns>
  224. public SYMBOL ASTRoot
  225. {
  226. get { return m_astRoot; }
  227. }
  228. #region IDisposable Members
  229. public void Dispose()
  230. {
  231. ResetCounters();
  232. }
  233. #endregion
  234. /// <summary>
  235. /// Resets various counters and metadata.
  236. /// </summary>
  237. private void ResetCounters()
  238. {
  239. //NOTE: This takes a VERY long time to rebuild. Ideally, this should be reset, but interesting errors are happening when it is reset..
  240. p = new LSLSyntax(new yyLSLSyntax(), new ErrorHandler(true));
  241. MethodVariables.Clear();
  242. VariablesToRename.Clear();
  243. GlobalVariables.Clear();
  244. m_braceCount = 0;
  245. m_CSharpLine = 15;
  246. m_CSharpCol = 1;
  247. m_positionMap = new Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>();
  248. LocalMethods.Clear();
  249. m_astRoot = null;
  250. IsParentEnumerable = false;
  251. OriginalScript = "";
  252. lock (FuncCalls)
  253. FuncCalls.Clear();
  254. FuncCntr = false;
  255. IsaGlobalVar = false;
  256. MethodsToAdd.Clear();
  257. LocalMethodArguements.Clear();
  258. m_allMethods.Clear();
  259. }
  260. public static int GetHeaderCount(Compiler compiler)
  261. {
  262. int i = 0;
  263. foreach (IScriptApi api in compiler.ScriptEngine.GetAPIs())
  264. foreach (string nameSpace in api.NamespaceAdditions)
  265. i++;
  266. return 13 + i;
  267. }
  268. public static string CreateCompilerScript(Compiler compiler,
  269. List<string> MethodsToAdd, string ScriptClass)
  270. {
  271. string compiledScript = "";
  272. foreach (IScriptApi api in compiler.ScriptEngine.GetAPIs())
  273. foreach (string nameSpace in api.NamespaceAdditions)
  274. compiledScript += "using " + nameSpace + ";\n";
  275. compiledScript += "using Aurora.ScriptEngine.AuroraDotNetEngine.APIs.Interfaces;\n";
  276. compiledScript += "using LSL_Types = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types;\n";
  277. compiledScript += "using System;\n";
  278. compiledScript += "namespace Script\n";
  279. compiledScript += "{\n";
  280. compiledScript += "[Serializable]\n";
  281. compiledScript +=
  282. "public class ScriptClass : Aurora.ScriptEngine.AuroraDotNetEngine.Runtime.ScriptBaseClass\n";
  283. compiledScript += "{\n";
  284. compiledScript += ScriptClass;
  285. foreach (string method in MethodsToAdd)
  286. {
  287. compiledScript += method;
  288. }
  289. compiledScript += "}\n"; // Close Class
  290. compiledScript += "}\n"; // Close Namespace
  291. return compiledScript;
  292. }
  293. /// <summary>
  294. /// Generate the code from the AST we have.
  295. /// </summary>
  296. /// <param name = "script">The LSL source as a string.</param>
  297. /// <returns>String containing the generated C# code.</returns>
  298. public string Convert(string script)
  299. {
  300. //Unless we are using the same LSL_Converter instance for all scripts, we don't need to reset this
  301. //ResetCounters();
  302. LSL2CSCodeTransformer codeTransformer;
  303. try
  304. {
  305. // lock (p)
  306. {
  307. codeTransformer = new LSL2CSCodeTransformer(p.Parse(script));
  308. // p.m_lexer.Reset();
  309. }
  310. }
  311. catch (CSToolsException e)
  312. {
  313. string message;
  314. // LL start numbering lines at 0 - geeks!
  315. // Also need to subtract one line we prepend!
  316. //
  317. string emessage = e.Message;
  318. string slinfo = e.slInfo.ToString();
  319. // Remove wrong line number info
  320. //
  321. if (emessage.StartsWith(slinfo + ": "))
  322. emessage = emessage.Substring(slinfo.Length + 2);
  323. if (e.slInfo.lineNumber - 1 <= 0)
  324. e.slInfo.lineNumber = 2;
  325. if (e.slInfo.charPosition - 1 <= 0)
  326. e.slInfo.charPosition = 2;
  327. message = String.Format("({0},{1}) {2}",
  328. e.slInfo.lineNumber - 1,
  329. e.slInfo.charPosition - 1, emessage);
  330. m_compiler.AddError(message);
  331. // p.m_lexer.Reset();
  332. ResetCounters();
  333. return "Error parsing the script. " + message;
  334. }
  335. m_astRoot = codeTransformer.Transform(LocalMethods, LocalMethodArguements);
  336. DuplicatedGlobalVariables = codeTransformer.DuplicatedGlobalVars;
  337. DuplicatedLocalVariables = codeTransformer.DuplicatedLocalVars;
  338. OriginalScript = script;
  339. string returnstring = "";
  340. // line number
  341. //m_CSharpLine += 3;
  342. // here's the payload
  343. returnstring += GenerateLine();
  344. foreach (SYMBOL s in m_astRoot.kids)
  345. returnstring += GenerateNode(s);
  346. returnstring += GenerateFireEventMethod();
  347. // Removes all carriage return characters which may be generated in Windows platform.
  348. //Is there a cleaner way of doing this?
  349. returnstring = returnstring.Replace("\r", "");
  350. try
  351. {
  352. CheckEventCasts(returnstring);
  353. }
  354. catch (InvalidOperationException ex)
  355. {
  356. m_compiler.AddError(ex.Message);
  357. return ex.Message;
  358. }
  359. return CreateCompilerScript(m_compiler, MethodsToAdd, returnstring);
  360. }
  361. private string GenerateFireEventMethod()
  362. {
  363. StringBuilder retVal = new StringBuilder();
  364. retVal.AppendLine("public override System.Collections.IEnumerator FireEvent (string evName, object[] parameters)");
  365. retVal.AppendLine("{");
  366. foreach (KeyValuePair<string, List<ArgumentDeclarationList>> method in m_allMethods)
  367. {
  368. retVal.AppendLine("if(evName == \"" + method.Key + "\")"); // if(evName == "state_entry")
  369. retVal.Append("return " + method.Key + " (");
  370. foreach (ArgumentDeclarationList t in method.Value)
  371. {
  372. for (int b = 0; b < t.kids.Count; b++)
  373. {
  374. retVal.Append("(" + ((Declaration)t.kids[b]).Datatype + ")");
  375. retVal.Append("parameters[" + b + "]");
  376. if (b != t.kids.Count - 1)
  377. retVal.Append(", ");
  378. }
  379. }
  380. retVal.AppendLine(");");
  381. }
  382. retVal.AppendLine("return null;");
  383. retVal.AppendLine("}");
  384. return retVal.ToString();
  385. }
  386. private string CheckFloatExponent(string script)
  387. {
  388. string[] SplitScript = script.Split('\n');
  389. List<string> ReconstructableScript = new List<string>();
  390. foreach (string line in SplitScript)
  391. {
  392. string AddLine = line;
  393. if (AddLine.Replace(" ", "") == "default")
  394. break; //We only check above default
  395. if (AddLine.Contains("float"))
  396. {
  397. if (line.Contains("e") && !line.Contains("(") && !line.Contains(")"))
  398. // Looking for exponents, but not for functions that have ()
  399. {
  400. //Should have this - float *** = 151e9;
  401. string[] SplitBeforeE = AddLine.Split('='); // Split at the e so we can look at the syntax
  402. if (SplitBeforeE.Length != 1)
  403. {
  404. string[] SplitBeforeESpace = SplitBeforeE[1].Split(';');
  405. //Should have something like this now - 151
  406. if (SplitBeforeESpace[0].Contains("e"))
  407. {
  408. if (!SplitBeforeESpace[0].Contains("."))
  409. {
  410. //Needs one then
  411. string[] Split = SplitBeforeESpace[0].Split('e');
  412. // Split at the e so we can look at the syntax
  413. Split[0] += ".";
  414. string TempString = "";
  415. foreach (string tempLine in Split)
  416. {
  417. TempString += tempLine + "e";
  418. }
  419. TempString = TempString.Remove(TempString.Length - 1, 1);
  420. SplitBeforeESpace[0] = TempString;
  421. TempString = "";
  422. foreach (string tempLine in SplitBeforeESpace)
  423. {
  424. TempString += tempLine + ";";
  425. }
  426. //Remove the last ;
  427. TempString = TempString.Remove(TempString.Length - 1, 1);
  428. SplitBeforeE[1] = TempString;
  429. foreach (string tempLine in SplitBeforeE)
  430. {
  431. AddLine += tempLine + "=";
  432. }
  433. //Remove the last e
  434. AddLine = AddLine.Remove(AddLine.Length - 1, 1);
  435. }
  436. }
  437. }
  438. }
  439. }
  440. ReconstructableScript.Add(AddLine);
  441. }
  442. string RetVal = "";
  443. foreach (string line in ReconstructableScript)
  444. {
  445. RetVal += line + "\n";
  446. }
  447. return RetVal;
  448. }
  449. private string CheckForInlineVectors(string script)
  450. {
  451. string[] SplitScript = script.Split('\n');
  452. List<string> ReconstructableScript = new List<string>();
  453. foreach (string line in SplitScript)
  454. {
  455. string AddLine = line;
  456. if (AddLine.Contains("<") && AddLine.Contains(">"))
  457. {
  458. if (AddLine.Contains("\"")) // if it contains ", we need to be more careful
  459. {
  460. string[] SplitByParLine = AddLine.Split('\"');
  461. int lineNumber = 0;
  462. List<string> ReconstructableLine = new List<string>();
  463. foreach (string parline in SplitByParLine)
  464. {
  465. string AddInsideLine = parline;
  466. //throw out all odd numbered lines as they are inside ""
  467. if (lineNumber % 2 != 1)
  468. {
  469. string[] SplitLineA = AddLine.Split('<');
  470. if (SplitLineA.Length > 1)
  471. {
  472. string SplitLineB = SplitLineA[1].Split('>')[0];
  473. if (SplitLineB.CompareWildcard("*,*,*", true))
  474. {
  475. AddInsideLine = AddInsideLine.Replace("<", "(<");
  476. AddInsideLine = AddInsideLine.Replace(">", ">)");
  477. }
  478. }
  479. }
  480. ReconstructableLine.Add(AddInsideLine);
  481. lineNumber++;
  482. }
  483. AddLine = "";
  484. foreach (string insideline in ReconstructableLine)
  485. {
  486. AddLine += insideline + "\"";
  487. }
  488. AddLine = AddLine.Remove(AddLine.Length - 1, 1);
  489. }
  490. else
  491. {
  492. string[] SplitLineA = AddLine.Split('<');
  493. if (SplitLineA.Length > 1)
  494. {
  495. string SplitLineB = SplitLineA[1].Split('>')[0];
  496. if (SplitLineB.CompareWildcard("*,*,*", true))
  497. {
  498. AddLine = AddLine.Replace("<", "(<");
  499. AddLine = AddLine.Replace(">", ">)");
  500. }
  501. }
  502. }
  503. }
  504. ReconstructableScript.Add(AddLine);
  505. }
  506. string RetVal = "";
  507. foreach (string line in ReconstructableScript)
  508. {
  509. RetVal += line + "\n";
  510. }
  511. return RetVal;
  512. }
  513. /// <summary>
  514. /// Checks the C# script for the correct casts in events
  515. /// This stops errors from misformed events ex. 'touch(vector3 position)' instead of 'touch(int touch)'
  516. /// </summary>
  517. /// <param name = "script"></param>
  518. private void CheckEventCasts(string script)
  519. {
  520. CheckEvent(script, "default");
  521. string[] States = OriginalScript.Split(new string[] { "state " }, StringSplitOptions.RemoveEmptyEntries);
  522. foreach (string state in States)
  523. {
  524. string stateName = state.Split(' ')[0].Split('\n')[0];
  525. if (!stateName.Contains("default"))
  526. CheckEvent(script, stateName);
  527. }
  528. }
  529. private void CheckEvent(string script, string state)
  530. {
  531. if (script.Contains(state + "_event_state_entry("))
  532. {
  533. string Valid = state + "_event_state_entry()";
  534. int charNum = script.IndexOf(state + "_event_state_entry(");
  535. string splitScript = script.Remove(0, charNum);
  536. charNum = splitScript.IndexOf('\n');
  537. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  538. if (splitScript != Valid)
  539. FindWrongParameterCountLineNumbers("state_entry", 0, 1);
  540. }
  541. if (script.Contains(state + "_event_touch_start("))
  542. {
  543. //Valid : default_event_touch_start(LSL_Types.LSLInteger number)
  544. int charNum = script.IndexOf(state + "_event_touch_start(");
  545. string splitScript = script.Remove(0, charNum);
  546. charNum = splitScript.IndexOf('\n');
  547. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  548. string arguments = splitScript.Split('(')[1];
  549. arguments = arguments.Split(')')[0];
  550. string[] AllArguments = arguments.Split(',');
  551. int i = 0;
  552. foreach (string argument in AllArguments)
  553. {
  554. if (i == 0)
  555. {
  556. if (!argument.Contains("LSL_Types.LSLInteger"))
  557. FindLineNumbers("touch_start", "Invalid argument");
  558. }
  559. i++;
  560. }
  561. if (i != 1)
  562. FindWrongParameterCountLineNumbers("touch_start", 1, i);
  563. }
  564. if (script.Contains(state + "_event_at_rot_target("))
  565. {
  566. //Valid : default_event_at_rot_target(LSL_Types.LSLInteger tnum, LSL_Types.Quaternion targetrot, LSL_Types.Quaternion ourrot)
  567. int charNum = script.IndexOf(state + "_event_at_rot_target(");
  568. string splitScript = script.Remove(0, charNum);
  569. charNum = splitScript.IndexOf('\n');
  570. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  571. string arguments = splitScript.Split('(')[1];
  572. arguments = arguments.Split(')')[0];
  573. string[] AllArguments = arguments.Split(',');
  574. int i = 0;
  575. foreach (string argument in AllArguments)
  576. {
  577. if (i == 0)
  578. if (!argument.Contains("LSL_Types.LSLInteger"))
  579. FindLineNumbers("at_rot_target", "Invalid argument");
  580. if (i == 1 || i == 2)
  581. if (!argument.Contains("LSL_Types.Quaternion"))
  582. FindLineNumbers("at_rot_target", "Invalid argument");
  583. i++;
  584. }
  585. if (i != 3)
  586. FindWrongParameterCountLineNumbers("at_rot_target", 3, i);
  587. }
  588. if (script.Contains(state + "_event_at_target("))
  589. {
  590. //Valid : default_event_at_rot_target(LSL_Types.LSLInteger tnum, LSL_Types.Quaternion targetrot, LSL_Types.Quaternion ourrot)
  591. int charNum = script.IndexOf(state + "_event_at_target(");
  592. string splitScript = script.Remove(0, charNum);
  593. charNum = splitScript.IndexOf('\n');
  594. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  595. string arguments = splitScript.Split('(')[1];
  596. arguments = arguments.Split(')')[0];
  597. string[] AllArguments = arguments.Split(',');
  598. int i = 0;
  599. foreach (string argument in AllArguments)
  600. {
  601. if (i == 0)
  602. if (!argument.Contains("LSL_Types.LSLInteger"))
  603. FindLineNumbers("at_target", "Invalid argument");
  604. if (i == 1 || i == 2)
  605. if (!argument.Contains("LSL_Types.Vector3"))
  606. FindLineNumbers("at_target", "Invalid argument");
  607. i++;
  608. }
  609. if (i != 3)
  610. FindWrongParameterCountLineNumbers("at_target", 3, i);
  611. }
  612. if (script.Contains(state + "_event_not_at_target("))
  613. {
  614. int charNum = script.IndexOf(state + "_event_not_at_target(");
  615. string splitScript = script.Remove(0, charNum);
  616. charNum = splitScript.IndexOf('\n');
  617. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  618. string Valid = state + "_event_not_at_target()";
  619. if (splitScript != Valid)
  620. FindWrongParameterCountLineNumbers("not_at_target", 0, 1);
  621. }
  622. if (script.Contains(state + "_event_attach("))
  623. {
  624. int charNum = script.IndexOf(state + "_event_attach(");
  625. string splitScript = script.Remove(0, charNum);
  626. charNum = splitScript.IndexOf('\n');
  627. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  628. string arguments = splitScript.Split('(')[1];
  629. arguments = arguments.Split(')')[0];
  630. string[] AllArguments = arguments.Split(',');
  631. int i = 0;
  632. foreach (string argument in AllArguments)
  633. {
  634. if (i == 0)
  635. {
  636. if (!argument.Contains("LSL_Types.LSLString"))
  637. FindLineNumbers("attach", "Invalid argument");
  638. }
  639. i++;
  640. }
  641. if (i != 1)
  642. FindWrongParameterCountLineNumbers("attach", 1, i);
  643. }
  644. if (script.Contains(state + "_event_changed("))
  645. {
  646. int charNum = script.IndexOf(state + "_event_changed(");
  647. string splitScript = script.Remove(0, charNum);
  648. charNum = splitScript.IndexOf('\n');
  649. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  650. string arguments = splitScript.Split('(')[1];
  651. arguments = arguments.Split(')')[0];
  652. string[] AllArguments = arguments.Split(',');
  653. int i = 0;
  654. foreach (string argument in AllArguments)
  655. {
  656. if (i == 0)
  657. {
  658. if (!argument.Contains("LSL_Types.LSLInteger"))
  659. FindLineNumbers("changed", "Invalid argument");
  660. }
  661. i++;
  662. }
  663. if (i != 1)
  664. FindWrongParameterCountLineNumbers("changed", 1, i);
  665. }
  666. if (script.Contains(state + "_event_collision("))
  667. {
  668. int charNum = script.IndexOf(state + "_event_collision(");
  669. string splitScript = script.Remove(0, charNum);
  670. charNum = splitScript.IndexOf('\n');
  671. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  672. string arguments = splitScript.Split('(')[1];
  673. arguments = arguments.Split(')')[0];
  674. string[] AllArguments = arguments.Split(',');
  675. int i = 0;
  676. foreach (string argument in AllArguments)
  677. {
  678. if (i == 0)
  679. {
  680. if (!argument.Contains("LSL_Types.LSLInteger"))
  681. FindLineNumbers("collision", "Invalid argument");
  682. }
  683. i++;
  684. }
  685. if (i != 1)
  686. FindWrongParameterCountLineNumbers("collision", 1, i);
  687. }
  688. if (script.Contains(state + "_event_collision_end("))
  689. {
  690. int charNum = script.IndexOf(state + "_event_collision_end(");
  691. string splitScript = script.Remove(0, charNum);
  692. charNum = splitScript.IndexOf('\n');
  693. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  694. string arguments = splitScript.Split('(')[1];
  695. arguments = arguments.Split(')')[0];
  696. string[] AllArguments = arguments.Split(',');
  697. int i = 0;
  698. foreach (string argument in AllArguments)
  699. {
  700. if (i == 0)
  701. {
  702. if (!argument.Contains("LSL_Types.LSLInteger"))
  703. FindLineNumbers("collision_end", "Invalid argument");
  704. }
  705. i++;
  706. }
  707. if (i != 1)
  708. FindWrongParameterCountLineNumbers("collision_end", 1, i);
  709. }
  710. if (script.Contains(state + "_event_collision_start("))
  711. {
  712. int charNum = script.IndexOf(state + "_event_collision_start(");
  713. string splitScript = script.Remove(0, charNum);
  714. charNum = splitScript.IndexOf('\n');
  715. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  716. string arguments = splitScript.Split('(')[1];
  717. arguments = arguments.Split(')')[0];
  718. string[] AllArguments = arguments.Split(',');
  719. int i = 0;
  720. foreach (string argument in AllArguments)
  721. {
  722. if (i == 0)
  723. {
  724. if (!argument.Contains("LSL_Types.LSLInteger"))
  725. FindLineNumbers("collision_start", "Invalid argument");
  726. }
  727. i++;
  728. }
  729. if (i != 1)
  730. FindWrongParameterCountLineNumbers("collision_start", 1, i);
  731. }
  732. if (script.Contains(state + "_event_run_time_permissions("))
  733. {
  734. int charNum = script.IndexOf(state + "_event_run_time_permissions(");
  735. string splitScript = script.Remove(0, charNum);
  736. charNum = splitScript.IndexOf('\n');
  737. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  738. string arguments = splitScript.Split('(')[1];
  739. arguments = arguments.Split(')')[0];
  740. string[] AllArguments = arguments.Split(',');
  741. int i = 0;
  742. foreach (string argument in AllArguments)
  743. {
  744. if (i == 0)
  745. {
  746. if (!argument.Contains("LSL_Types.LSLInteger"))
  747. FindLineNumbers("run_time_permissions", "Invalid argument");
  748. }
  749. i++;
  750. }
  751. if (i != 1)
  752. FindWrongParameterCountLineNumbers("run_time_permissions", 1, i);
  753. }
  754. if (script.Contains(state + "_event_control("))
  755. {
  756. int charNum = script.IndexOf(state + "_event_control(");
  757. string splitScript = script.Remove(0, charNum);
  758. charNum = splitScript.IndexOf('\n');
  759. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  760. string arguments = splitScript.Split('(')[1];
  761. arguments = arguments.Split(')')[0];
  762. string[] AllArguments = arguments.Split(',');
  763. int i = 0;
  764. foreach (string argument in AllArguments)
  765. {
  766. if (i == 0)
  767. if (!argument.Contains("LSL_Types.LSLString"))
  768. FindLineNumbers("control", "Invalid argument");
  769. if (i == 1 || i == 2)
  770. if (!argument.Contains("LSL_Types.LSLInteger"))
  771. FindLineNumbers("control", "Invalid argument");
  772. i++;
  773. }
  774. if (i != 3)
  775. FindWrongParameterCountLineNumbers("control", 3, i);
  776. }
  777. if (script.Contains(state + "_event_dataserver("))
  778. {
  779. int charNum = script.IndexOf(state + "_event_dataserver(");
  780. string splitScript = script.Remove(0, charNum);
  781. charNum = splitScript.IndexOf('\n');
  782. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  783. string arguments = splitScript.Split('(')[1];
  784. arguments = arguments.Split(')')[0];
  785. string[] AllArguments = arguments.Split(',');
  786. int i = 0;
  787. foreach (string argument in AllArguments)
  788. {
  789. if (i == 0 || i == 1)
  790. if (!argument.Contains("LSL_Types.LSLString"))
  791. FindLineNumbers("dataserver", "Invalid argument");
  792. i++;
  793. }
  794. if (i != 2)
  795. FindWrongParameterCountLineNumbers("dataserver", 2, i);
  796. }
  797. if (script.Contains(state + "_event_timer("))
  798. {
  799. int charNum = script.IndexOf(state + "_event_timer(");
  800. string splitScript = script.Remove(0, charNum);
  801. charNum = splitScript.IndexOf('\n');
  802. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  803. string arguments = splitScript.Split('(')[1];
  804. arguments = arguments.Split(')')[0];
  805. string Valid = state + "_event_timer()";
  806. if (splitScript != Valid)
  807. FindWrongParameterCountLineNumbers("timer", 0, 1);
  808. }
  809. if (script.Contains(state + "_event_email("))
  810. {
  811. int charNum = script.IndexOf(state + "_event_email(");
  812. string splitScript = script.Remove(0, charNum);
  813. charNum = splitScript.IndexOf('\n');
  814. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  815. string arguments = splitScript.Split('(')[1];
  816. arguments = arguments.Split(')')[0];
  817. string[] AllArguments = arguments.Split(',');
  818. int i = 0;
  819. foreach (string argument in AllArguments)
  820. {
  821. if (i == 0 || i == 1 || i == 2 || i == 3)
  822. if (!argument.Contains("LSL_Types.LSLString"))
  823. FindLineNumbers("email", "Invalid argument");
  824. if (i == 4)
  825. if (!argument.Contains("LSL_Types.LSLInteger"))
  826. FindLineNumbers("email", "Invalid argument");
  827. i++;
  828. }
  829. if (i != 5)
  830. FindWrongParameterCountLineNumbers("email", 5, i);
  831. }
  832. if (script.Contains(state + "_event_http_request("))
  833. {
  834. int charNum = script.IndexOf(state + "_event_http_request(");
  835. string splitScript = script.Remove(0, charNum);
  836. charNum = splitScript.IndexOf('\n');
  837. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  838. string arguments = splitScript.Split('(')[1];
  839. arguments = arguments.Split(')')[0];
  840. string[] AllArguments = arguments.Split(',');
  841. int i = 0;
  842. foreach (string argument in AllArguments)
  843. {
  844. if (i == 0 || i == 1 || i == 2)
  845. if (!argument.Contains("LSL_Types.LSLString"))
  846. FindLineNumbers("http_request", "Invalid argument");
  847. i++;
  848. }
  849. if (i != 3)
  850. FindWrongParameterCountLineNumbers("http_request", 3, i);
  851. }
  852. if (script.Contains(state + "_event_http_response("))
  853. {
  854. int charNum = script.IndexOf(state + "_event_http_response(");
  855. string splitScript = script.Remove(0, charNum);
  856. charNum = splitScript.IndexOf('\n');
  857. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  858. string arguments = splitScript.Split('(')[1];
  859. arguments = arguments.Split(')')[0];
  860. string[] AllArguments = arguments.Split(',');
  861. int i = 0;
  862. foreach (string argument in AllArguments)
  863. {
  864. if (i == 0 || i == 3)
  865. if (!argument.Contains("LSL_Types.LSLString"))
  866. FindLineNumbers("http_response", "Invalid argument");
  867. if (i == 1)
  868. if (!argument.Contains("LSL_Types.LSLInteger"))
  869. FindLineNumbers("http_response", "Invalid argument");
  870. if (i == 2)
  871. if (!argument.Contains("LSL_Types.list"))
  872. FindLineNumbers("http_response", "Invalid argument");
  873. i++;
  874. }
  875. if (i != 4)
  876. FindWrongParameterCountLineNumbers("http_response", 4, i);
  877. }
  878. if (script.Contains(state + "_event_land_collision_end("))
  879. {
  880. int charNum = script.IndexOf(state + "_event_land_collision_end(");
  881. string splitScript = script.Remove(0, charNum);
  882. charNum = splitScript.IndexOf('\n');
  883. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  884. string arguments = splitScript.Split('(')[1];
  885. arguments = arguments.Split(')')[0];
  886. string[] AllArguments = arguments.Split(',');
  887. int i = 0;
  888. foreach (string argument in AllArguments)
  889. {
  890. if (i == 0)
  891. if (!argument.Contains("LSL_Types.Vector3"))
  892. FindLineNumbers("land_collision_end", "Invalid argument");
  893. i++;
  894. }
  895. if (i != 1)
  896. FindWrongParameterCountLineNumbers("land_collision_end", 1, i);
  897. }
  898. if (script.Contains(state + "_event_land_collision("))
  899. {
  900. int charNum = script.IndexOf(state + "_event_land_collision(");
  901. string splitScript = script.Remove(0, charNum);
  902. charNum = splitScript.IndexOf('\n');
  903. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  904. string arguments = splitScript.Split('(')[1];
  905. arguments = arguments.Split(')')[0];
  906. string[] AllArguments = arguments.Split(',');
  907. int i = 0;
  908. foreach (string argument in AllArguments)
  909. {
  910. if (i == 0)
  911. if (!argument.Contains("LSL_Types.Vector3"))
  912. FindLineNumbers("land_collision", "Invalid argument");
  913. i++;
  914. }
  915. if (i != 1)
  916. FindWrongParameterCountLineNumbers("land_collision", 1, i);
  917. }
  918. if (script.Contains(state + "_event_land_collision_start("))
  919. {
  920. int charNum = script.IndexOf(state + "_event_land_collision_start(");
  921. string splitScript = script.Remove(0, charNum);
  922. charNum = splitScript.IndexOf('\n');
  923. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  924. string arguments = splitScript.Split('(')[1];
  925. arguments = arguments.Split(')')[0];
  926. string[] AllArguments = arguments.Split(',');
  927. int i = 0;
  928. foreach (string argument in AllArguments)
  929. {
  930. if (i == 0)
  931. if (!argument.Contains("LSL_Types.Vector3"))
  932. FindLineNumbers("land_collision_start", "Invalid argument");
  933. i++;
  934. }
  935. if (i != 1)
  936. FindWrongParameterCountLineNumbers("land_collision_start", 1, i);
  937. }
  938. if (script.Contains(state + "_event_link_message("))
  939. {
  940. int charNum = script.IndexOf(state + "_event_link_message(");
  941. string splitScript = script.Remove(0, charNum);
  942. charNum = splitScript.IndexOf('\n');
  943. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  944. string arguments = splitScript.Split('(')[1];
  945. arguments = arguments.Split(')')[0];
  946. string[] AllArguments = arguments.Split(',');
  947. int i = 0;
  948. foreach (string argument in AllArguments)
  949. {
  950. if (i == 0 || i == 1)
  951. if (!argument.Contains("LSL_Types.LSLInteger"))
  952. FindLineNumbers("link_message", "Invalid argument");
  953. if (i == 2 || i == 3)
  954. if (!argument.Contains("LSL_Types.LSLString"))
  955. FindLineNumbers("link_message", "Invalid argument");
  956. i++;
  957. }
  958. if (i != 4)
  959. FindWrongParameterCountLineNumbers("link_message", 4, i);
  960. }
  961. if (script.Contains(state + "_event_listen("))
  962. {
  963. int charNum = script.IndexOf(state + "_event_listen(");
  964. string splitScript = script.Remove(0, charNum);
  965. charNum = splitScript.IndexOf('\n');
  966. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  967. string arguments = splitScript.Split('(')[1];
  968. arguments = arguments.Split(')')[0];
  969. string[] AllArguments = arguments.Split(',');
  970. int i = 0;
  971. foreach (string argument in AllArguments)
  972. {
  973. if (i == 0)
  974. if (!argument.Contains("LSL_Types.LSLInteger"))
  975. FindLineNumbers("listen", "Invalid argument");
  976. if (i == 1 || i == 2 || i == 3)
  977. if (!argument.Contains("LSL_Types.LSLString"))
  978. FindLineNumbers("listen", "Invalid argument");
  979. i++;
  980. }
  981. if (i != 4)
  982. FindWrongParameterCountLineNumbers("listen", 4, i);
  983. }
  984. if (script.Contains(state + "_event_on_rez("))
  985. {
  986. int charNum = script.IndexOf(state + "_event_on_rez(");
  987. string splitScript = script.Remove(0, charNum);
  988. charNum = splitScript.IndexOf('\n');
  989. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  990. string arguments = splitScript.Split('(')[1];
  991. arguments = arguments.Split(')')[0];
  992. string[] AllArguments = arguments.Split(',');
  993. int i = 0;
  994. foreach (string argument in AllArguments)
  995. {
  996. if (i == 0)
  997. if (!argument.Contains("LSL_Types.LSLInteger"))
  998. FindLineNumbers("on_rez", "Invalid argument");
  999. i++;
  1000. }
  1001. if (i != 1)
  1002. FindWrongParameterCountLineNumbers("on_rez", 1, i);
  1003. }
  1004. if (script.Contains(state + "_event_money("))
  1005. {
  1006. int charNum = script.IndexOf(state + "_event_money(");
  1007. string splitScript = script.Remove(0, charNum);
  1008. charNum = splitScript.IndexOf('\n');
  1009. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  1010. string arguments = splitScript.Split('(')[1];
  1011. arguments = arguments.Split(')')[0];
  1012. string[] AllArguments = arguments.Split(',');
  1013. int i = 0;
  1014. foreach (string argument in AllArguments)
  1015. {
  1016. if (i == 0)
  1017. if (!argument.Contains("LSL_Types.LSLString"))
  1018. FindLineNumbers("money", "Invalid argument");
  1019. if (i == 1)
  1020. if (!argument.Contains("LSL_Types.LSLInteger"))
  1021. FindLineNumbers("money", "Invalid argument");
  1022. i++;
  1023. }
  1024. if (i != 2)
  1025. FindWrongParameterCountLineNumbers("money", 2, i);
  1026. }
  1027. if (script.Contains(state + "_event_moving_end("))
  1028. {
  1029. int charNum = script.IndexOf(state + "_event_moving_end(");
  1030. string splitScript = script.Remove(0, charNum);
  1031. charNum = splitScript.IndexOf('\n');
  1032. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  1033. string Valid = state + "_event_moving_end()";
  1034. if (splitScript != Valid)
  1035. FindWrongParameterCountLineNumbers("moving_end", 0, 1);
  1036. }
  1037. if (script.Contains(state + "_event_moving_start("))
  1038. {
  1039. int charNum = script.IndexOf(state + "_event_moving_start(");
  1040. string splitScript = script.Remove(0, charNum);
  1041. charNum = splitScript.IndexOf('\n');
  1042. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  1043. string Valid = state + "_event_moving_start()";
  1044. if (splitScript != Valid)
  1045. FindLineNumbers("moving_start", "Too many arguments");
  1046. }
  1047. if (script.Contains(state + "_event_no_sensor("))
  1048. {
  1049. int charNum = script.IndexOf(state + "_event_no_sensor(");
  1050. string splitScript = script.Remove(0, charNum);
  1051. charNum = splitScript.IndexOf('\n');
  1052. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  1053. string Valid = state + "_event_no_sensor()";
  1054. if (splitScript != Valid)
  1055. FindWrongParameterCountLineNumbers("no_sensor", 0, 1);
  1056. }
  1057. if (script.Contains(state + "_event_not_at_rot_target("))
  1058. {
  1059. int charNum = script.IndexOf(state + "_event_not_at_rot_target(");
  1060. string splitScript = script.Remove(0, charNum);
  1061. charNum = splitScript.IndexOf('\n');
  1062. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  1063. string Valid = state + "_event_not_at_rot_target()";
  1064. if (splitScript != Valid)
  1065. FindWrongParameterCountLineNumbers("not_at_rot_target", 0, 1);
  1066. }
  1067. if (script.Contains(state + "_event_object_rez("))
  1068. {
  1069. int charNum = script.IndexOf(state + "_event_object_rez(");
  1070. string splitScript = script.Remove(0, charNum);
  1071. charNum = splitScript.IndexOf('\n');
  1072. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  1073. string arguments = splitScript.Split('(')[1];
  1074. arguments = arguments.Split(')')[0];
  1075. string[] AllArguments = arguments.Split(',');
  1076. int i = 0;
  1077. foreach (string argument in AllArguments)
  1078. {
  1079. if (i == 0)
  1080. if (!argument.Contains("LSL_Types.LSLString"))
  1081. FindLineNumbers("object_rez", "Invalid argument");
  1082. i++;
  1083. }
  1084. if (i != 1)
  1085. FindWrongParameterCountLineNumbers("object_rez", 1, i);
  1086. }
  1087. if (script.Contains(state + "_event_on_error("))
  1088. {
  1089. int charNum = script.IndexOf(state + "_event_on_error(");
  1090. string splitScript = script.Remove(0, charNum);
  1091. charNum = splitScript.IndexOf('\n');
  1092. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  1093. string arguments = splitScript.Split('(')[1];
  1094. arguments = arguments.Split(')')[0];
  1095. string[] AllArguments = arguments.Split(',');
  1096. int i = 0;
  1097. foreach (string argument in AllArguments)
  1098. {
  1099. if (i == 0)
  1100. if (!argument.Contains("LSL_Types.LSLString"))
  1101. FindLineNumbers("on_error", "Invalid argument");
  1102. i++;
  1103. }
  1104. if (i != 1)
  1105. FindWrongParameterCountLineNumbers("on_error", 1, i);
  1106. }
  1107. if (script.Contains(state + "_event_remote_data("))
  1108. {
  1109. int charNum = script.IndexOf(state + "_event_remote_data(");
  1110. string splitScript = script.Remove(0, charNum);
  1111. charNum = splitScript.IndexOf('\n');
  1112. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  1113. string arguments = splitScript.Split('(')[1];
  1114. arguments = arguments.Split(')')[0];
  1115. string[] AllArguments = arguments.Split(',');
  1116. int i = 0;
  1117. foreach (string argument in AllArguments)
  1118. {
  1119. if (i == 0 || i == 4)
  1120. if (!argument.Contains("LSL_Types.LSLInteger"))
  1121. FindLineNumbers("remote_data", "Invalid argument");
  1122. if (i == 1 || i == 2 || i == 3 || i == 5)
  1123. if (!argument.Contains("LSL_Types.LSLString"))
  1124. FindLineNumbers("remote_data", "Invalid argument");
  1125. i++;
  1126. }
  1127. if (i != 6)
  1128. FindWrongParameterCountLineNumbers("remote_data", 6, i);
  1129. }
  1130. if (script.Contains(state + "_event_sensor("))
  1131. {
  1132. int charNum = script.IndexOf(state + "_event_sensor(");
  1133. string splitScript = script.Remove(0, charNum);
  1134. charNum = splitScript.IndexOf('\n');
  1135. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  1136. string arguments = splitScript.Split('(')[1];
  1137. arguments = arguments.Split(')')[0];
  1138. string[] AllArguments = arguments.Split(',');
  1139. int i = 0;
  1140. foreach (string argument in AllArguments)
  1141. {
  1142. if (i == 0)
  1143. if (!argument.Contains("LSL_Types.LSLInteger"))
  1144. FindLineNumbers("sensor", "Invalid argument");
  1145. i++;
  1146. }
  1147. if (i != 1)
  1148. FindWrongParameterCountLineNumbers("sensor", 1, i);
  1149. }
  1150. if (script.Contains(state + "_event_state_exit("))
  1151. {
  1152. int charNum = script.IndexOf(state + "_event_state_exit(");
  1153. string splitScript = script.Remove(0, charNum);
  1154. charNum = splitScript.IndexOf('\n');
  1155. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  1156. string Valid = state + "_event_state_exit()";
  1157. if (splitScript != Valid)
  1158. FindWrongParameterCountLineNumbers("state_exit", 0, 1);
  1159. }
  1160. if (script.Contains(state + "_event_touch("))
  1161. {
  1162. int charNum = script.IndexOf(state + "_event_touch(");
  1163. string splitScript = script.Remove(0, charNum);
  1164. charNum = splitScript.IndexOf('\n');
  1165. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  1166. string arguments = splitScript.Split('(')[1];
  1167. arguments = arguments.Split(')')[0];
  1168. string[] AllArguments = arguments.Split(',');
  1169. int i = 0;
  1170. foreach (string argument in AllArguments)
  1171. {
  1172. if (i == 0)
  1173. if (!argument.Contains("LSL_Types.LSLInteger"))
  1174. FindLineNumbers("touch", "Invalid argument");
  1175. i++;
  1176. }
  1177. if (i != 1)
  1178. FindWrongParameterCountLineNumbers("touch", 1, i);
  1179. }
  1180. if (script.Contains(state + "_event_touch_end("))
  1181. {
  1182. int charNum = script.IndexOf(state + "_event_touch_end(");
  1183. string splitScript = script.Remove(0, charNum);
  1184. charNum = splitScript.IndexOf('\n');
  1185. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  1186. string arguments = splitScript.Split('(')[1];
  1187. arguments = arguments.Split(')')[0];
  1188. string[] AllArguments = arguments.Split(',');
  1189. int i = 0;
  1190. foreach (string argument in AllArguments)
  1191. {
  1192. if (i == 0)
  1193. if (!argument.Contains("LSL_Types.LSLInteger"))
  1194. FindLineNumbers("touch_end", "Invalid argument");
  1195. i++;
  1196. }
  1197. if (i != 1)
  1198. FindWrongParameterCountLineNumbers("touch_end", 1, i);
  1199. }
  1200. if (script.Contains(state + "_event_transaction_result("))
  1201. {
  1202. int charNum = script.IndexOf(state + "_event_transaction_result(");
  1203. string splitScript = script.Remove(0, charNum);
  1204. charNum = splitScript.IndexOf('\n');
  1205. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  1206. string arguments = splitScript.Split('(')[1];
  1207. arguments = arguments.Split(')')[0];
  1208. string[] AllArguments = arguments.Split(',');
  1209. int i = 0;
  1210. foreach (string argument in AllArguments)
  1211. {
  1212. if (i == 0 || i == 2)
  1213. if (!argument.Contains("LSL_Types.LSLString"))
  1214. FindLineNumbers("transaction_result", "Invalid argument");
  1215. if (i == 1)
  1216. if (!argument.Contains("LSL_Types.LSLInteger"))
  1217. FindLineNumbers("transaction_result", "Invalid argument");
  1218. i++;
  1219. }
  1220. if (i != 3)
  1221. FindWrongParameterCountLineNumbers("transaction_result", 3, i);
  1222. }
  1223. if (script.Contains(state + "_event_path_update("))
  1224. {
  1225. int charNum = script.IndexOf(state + "_event_path_update(");
  1226. string splitScript = script.Remove(0, charNum);
  1227. charNum = splitScript.IndexOf('\n');
  1228. splitScript = splitScript.Remove(charNum, splitScript.Length - charNum);
  1229. string arguments = splitScript.Split('(')[1];
  1230. arguments = arguments.Split(')')[0];
  1231. string[] AllArguments = arguments.Split(',');
  1232. int i = 0;
  1233. foreach (string argument in AllArguments)
  1234. {
  1235. if (i == 0)
  1236. if (!argument.Contains("LSL_Types.LSLInteger"))
  1237. FindLineNumbers("path_update", "Invalid argument");
  1238. if (i == 1)
  1239. if (!argument.Contains("LSL_Types.list"))
  1240. FindLineNumbers("path_update", "Invalid argument");
  1241. i++;
  1242. }
  1243. if (i != 2)
  1244. FindWrongParameterCountLineNumbers("path_update", 2, i);
  1245. }
  1246. }
  1247. private void FindWrongParameterCountLineNumbers(string EventName, int correct, int i)
  1248. {
  1249. if (i > correct)
  1250. FindLineNumbers(EventName, "Too many arguments, " + i + " arguments given, " + correct + " expected");
  1251. else
  1252. FindLineNumbers(EventName, "Too few arguments, " + i + " arguments given, " + correct + " expected");
  1253. }
  1254. private void FindLineNumbers(string EventName, string Problem)
  1255. {
  1256. //string testScript = OriginalScript.Replace(" ", "");
  1257. int lineNumber = 0;
  1258. int charNumber = 0;
  1259. int i = 0;
  1260. foreach (string str in OriginalScript.Split('\n'))
  1261. {
  1262. if (str.Contains(EventName + "("))
  1263. {
  1264. lineNumber = i;
  1265. charNumber = str.IndexOf(EventName);
  1266. break;
  1267. }
  1268. i++;
  1269. }
  1270. throw new InvalidOperationException(String.Format("({0},{1}) {2}",
  1271. lineNumber,
  1272. charNumber, Problem + " in '" + EventName + "'\n"));
  1273. }
  1274. private void AddWarning(string warning)
  1275. {
  1276. m_compiler.AddWarning(warning);
  1277. }
  1278. /// <summary>
  1279. /// Recursively called to generate each type of node. Will generate this
  1280. /// node, then all it's children.
  1281. /// </summary>
  1282. /// <param name = "s">The current node to generate code for.</param>
  1283. /// <returns>String containing C# code for SYMBOL s.</returns>
  1284. private string GenerateNode(SYMBOL s)
  1285. {
  1286. string fullretstr = "";
  1287. // make sure to put type lower in the inheritance hierarchy first
  1288. // ie: since IdentArgument and ExpressionArgument inherit from
  1289. // Argument, put IdentArgument and ExpressionArgument before Argument
  1290. if (s is GlobalFunctionDefinition)
  1291. {
  1292. fullretstr += GenerateGlobalFunctionDefinition((GlobalFunctionDefinition)s);
  1293. }
  1294. else if (s is GlobalVariableDeclaration)
  1295. {
  1296. fullretstr += GenerateGlobalVariableDeclaration((GlobalVariableDeclaration)s);
  1297. }
  1298. else if (s is State)
  1299. {
  1300. fullretstr += GenerateState((State)s);
  1301. }
  1302. else if (s is CompoundStatement)
  1303. {
  1304. fullretstr += GenerateCompoundStatement((CompoundStatement)s);
  1305. }
  1306. else if (s is Declaration)
  1307. {
  1308. fullretstr += GenerateDeclaration((Declaration)s);
  1309. }
  1310. else if (s is Statement)
  1311. {
  1312. fullretstr += GenerateStatement((Statement)s);
  1313. }
  1314. else if (s is ReturnStatement)
  1315. {
  1316. fullretstr += GenerateReturnStatement((ReturnStatement)s);
  1317. }
  1318. else if (s is JumpLabel)
  1319. {
  1320. fullretstr += GenerateJumpLabel((JumpLabel)s);
  1321. }
  1322. else if (s is JumpStatement)
  1323. {
  1324. fullretstr += GenerateJumpStatement((JumpStatement)s);
  1325. }
  1326. else if (s is StateChange)
  1327. {
  1328. fullretstr += GenerateStateChange((StateChange)s);
  1329. }
  1330. else if (s is IfStatement)
  1331. {
  1332. fullretstr += GenerateIfStatement((IfStatement)s);
  1333. }
  1334. else if (s is WhileStatement)
  1335. {
  1336. fullretstr += GenerateWhileStatement((WhileStatement)s);
  1337. }
  1338. else if (s is DoWhileStatement)
  1339. {
  1340. fullretstr += GenerateDoWhileStatement((DoWhileStatement)s);
  1341. }
  1342. else if (s is ForLoop)
  1343. {
  1344. fullretstr += GenerateForLoop((ForLoop)s);
  1345. }
  1346. else if (s is ArgumentList)
  1347. {
  1348. fullretstr += GenerateArgumentList((ArgumentList)s);
  1349. }
  1350. else if (s is Assignment)
  1351. {
  1352. fullretstr += GenerateAssignment((Assignment)s);
  1353. }
  1354. else if (s is BinaryExpression)
  1355. {
  1356. fullretstr += GenerateBinaryExpression((BinaryExpression)s, false, "");
  1357. }
  1358. else if (s is ParenthesisExpression)
  1359. {
  1360. fullretstr += GenerateParenthesisExpression((ParenthesisExpression)s);
  1361. }
  1362. else if (s is UnaryExpression)
  1363. {
  1364. fullretstr += GenerateUnaryExpression((UnaryExpression)s);
  1365. }
  1366. else if (s is IncrementDecrementExpression)
  1367. {
  1368. fullretstr += GenerateIncrementDecrementExpression((IncrementDecrementExpression)s);
  1369. }
  1370. else if (s is TypecastExpression)
  1371. {
  1372. fullretstr += GenerateTypecastExpression((TypecastExpression)s);
  1373. }
  1374. else if (s is FunctionCall)
  1375. {
  1376. fullretstr += GenerateFunctionCall((FunctionCall)s, true);
  1377. }
  1378. else if (s is VectorConstant)
  1379. {
  1380. fullretstr += GenerateVectorConstant((VectorConstant)s);
  1381. }
  1382. else if (s is RotationConstant)
  1383. {
  1384. fullretstr += GenerateRotationConstant((RotationConstant)s);
  1385. }
  1386. else if (s is ListConstant)
  1387. {
  1388. fullretstr += GenerateListConstant((ListConstant)s);
  1389. }
  1390. else if (s is Constant)
  1391. {
  1392. fullretstr += GenerateConstant((Constant)s);
  1393. }
  1394. else if (s is IdentDotExpression)
  1395. {
  1396. fullretstr += Generate(
  1397. CheckName(((IdentDotExpression)s).Name) + "." + ((IdentDotExpression)s).Member, s);
  1398. }
  1399. else if (s is IdentExpression)
  1400. {
  1401. fullretstr += Generate(CheckName(((IdentExpression)s).Name), s);
  1402. }
  1403. else if (s is IDENT)
  1404. {
  1405. fullretstr += Generate(CheckName(((TOKEN)s).yytext), s);
  1406. }
  1407. else
  1408. {
  1409. foreach (SYMBOL kid in s.kids)
  1410. {
  1411. fullretstr += GenerateNode(kid);
  1412. }
  1413. }
  1414. return fullretstr;
  1415. }
  1416. private GlobalFunctionDefinition _currentGlobalFunctionDeclaration = null;
  1417. private StateEvent _currentLocalFunctionDeclaration = null;
  1418. private State _currentLocalStateDeclaration = null;
  1419. /// <summary>
  1420. /// Generates the code for a GlobalFunctionDefinition node.
  1421. /// </summary>
  1422. /// <param name = "gf">The GlobalFunctionDefinition node.</param>
  1423. /// <returns>String containing C# code for GlobalFunctionDefinition gf.</returns>
  1424. private string GenerateGlobalFunctionDefinition(GlobalFunctionDefinition gf)
  1425. {
  1426. MethodVariables.Clear();
  1427. VariablesToRename.Clear();
  1428. StringBuilder retstr = new StringBuilder();
  1429. _currentGlobalFunctionDeclaration = gf;
  1430. // we need to separate the argument declaration list from other kids
  1431. List<SYMBOL> argumentDeclarationListKids = new List<SYMBOL>();
  1432. List<SYMBOL> remainingKids = new List<SYMBOL>();
  1433. foreach (SYMBOL kid in gf.kids)
  1434. if (kid is ArgumentDeclarationList)
  1435. argumentDeclarationListKids.Add(kid);
  1436. else
  1437. remainingKids.Add(kid);
  1438. retstr.Append(GenerateIndented(String.Format("public System.Collections.IEnumerator {0}(", CheckName(gf.Name)), gf));
  1439. IsParentEnumerable = true;
  1440. // print the state arguments, if any
  1441. List<ArgumentDeclarationList> args = new List<ArgumentDeclarationList>();
  1442. foreach (SYMBOL kid in argumentDeclarationListKids)
  1443. {
  1444. ArgumentDeclarationList ADL = (ArgumentDeclarationList)kid;
  1445. args.Add(ADL);
  1446. retstr.Append(GenerateArgumentDeclarationList(ADL));
  1447. }
  1448. m_allMethods.Add(CheckName(gf.Name), args);
  1449. retstr.Append(GenerateLine(")"));
  1450. foreach (SYMBOL kid in remainingKids)
  1451. retstr.Append(GenerateNode(kid));
  1452. if (gf.ReturnType == "void")
  1453. {
  1454. int i;
  1455. for (i = 1; i < 5; i++)
  1456. {
  1457. if (retstr[retstr.Length - i] == '}')
  1458. {
  1459. retstr.Insert(retstr.Length - i, GenerateLine(" yield break;"));
  1460. break;
  1461. }
  1462. }
  1463. }
  1464. IsParentEnumerable = false;
  1465. _currentGlobalFunctionDeclaration = null;
  1466. return retstr.ToString();
  1467. }
  1468. /// <summary>
  1469. /// Generates the code for a GlobalVariableDeclaration node.
  1470. /// </summary>
  1471. /// <param name = "gv">The GlobalVariableDeclaration node.</param>
  1472. /// <returns>String containing C# code for GlobalVariableDeclaration gv.</returns>
  1473. private string GenerateGlobalVariableDeclaration(GlobalVariableDeclaration gv)
  1474. {
  1475. string retstr = "";
  1476. foreach (SYMBOL s in gv.kids)
  1477. {
  1478. retstr += Indent();
  1479. retstr += "public ";
  1480. if (s is Assignment)
  1481. {
  1482. string innerretstr = "";
  1483. Assignment a = s as Assignment;
  1484. List<string> identifiers = new List<string>();
  1485. checkForMultipleAssignments(identifiers, a);
  1486. IsaGlobalVar = true;
  1487. SYMBOL variableName = (SYMBOL)a.kids.Pop();
  1488. string VarName = GenerateNode(variableName);
  1489. innerretstr += VarName;
  1490. IsaGlobalVar = false;
  1491. #region Find the var name and type
  1492. Declaration dec = variableName as Declaration;
  1493. string type = dec.Datatype;
  1494. string varName = dec.Id;
  1495. #endregion
  1496. if (DuplicatedGlobalVariables.ContainsKey(((Declaration)variableName).Id))
  1497. {
  1498. if (a.kids.Count == 1)
  1499. {
  1500. SYMBOL assignmentChild = (SYMBOL)a.kids[0];
  1501. if (assignmentChild is IdentExpression)
  1502. {
  1503. IdentExpression identEx = (IdentExpression)assignmentChild;
  1504. }
  1505. else if (assignmentChild is ListConstant)
  1506. {
  1507. ListConstant listConst = (ListConstant)assignmentChild;
  1508. foreach (SYMBOL listChild in listConst.kids)
  1509. {
  1510. if (listChild is ArgumentList)
  1511. {
  1512. ArgumentList argList = (ArgumentList)listChild;
  1513. int i = 0;
  1514. bool changed = false;
  1515. object[] p = new object[argList.kids.Count];
  1516. foreach (SYMBOL objChild in argList.kids)
  1517. {
  1518. p[i] = objChild;
  1519. if (objChild is IdentExpression)
  1520. {
  1521. IdentExpression identEx = (IdentExpression)objChild;
  1522. }
  1523. i++;
  1524. }
  1525. if (changed)
  1526. {
  1527. argList.kids = new ObjectList();
  1528. foreach (object o in p)
  1529. argList.kids.Add(o);
  1530. }
  1531. }
  1532. }
  1533. }
  1534. else if (assignmentChild is Constant)
  1535. {
  1536. Constant identEx = (Constant)assignmentChild;
  1537. string value = GetValue(identEx);
  1538. Constant dupConstant = (Constant)DuplicatedGlobalVariables[dec.Id];
  1539. dupConstant.Value = dupConstant.Value == null ? GetValue(dupConstant) : dupConstant.Value;
  1540. if (value != dupConstant.Value)
  1541. {
  1542. return "";
  1543. }
  1544. }
  1545. }
  1546. }
  1547. innerretstr += Generate(String.Format(" {0} ", a.AssignmentType), a);
  1548. foreach (SYMBOL kid in a.kids)
  1549. {
  1550. innerretstr += CheckIfGlobalVariable(varName, type, kid);
  1551. }
  1552. retstr += innerretstr;
  1553. }
  1554. else
  1555. retstr += GenerateNode(s);
  1556. retstr += GenerateLine(";");
  1557. }
  1558. return retstr;
  1559. }
  1560. private string GetValue(Constant identEx)
  1561. {
  1562. if (identEx.Value != null)
  1563. return identEx.Value;
  1564. if (identEx is VectorConstant)
  1565. {
  1566. VectorConstant vc = (VectorConstant)identEx;
  1567. string retstr = "";
  1568. retstr += Generate(String.Format("new {0}(", vc.Type), vc);
  1569. retstr += GenerateNode((SYMBOL)vc.kids[0]);
  1570. retstr += Generate(", ");
  1571. retstr += GenerateNode((SYMBOL)vc.kids[1]);
  1572. retstr += Generate(", ");
  1573. retstr += GenerateNode((SYMBOL)vc.kids[2]);
  1574. retstr += Generate(")");
  1575. return retstr;
  1576. }
  1577. if (identEx is RotationConstant)
  1578. {
  1579. RotationConstant rc = (RotationConstant)identEx;
  1580. string retstr = "";
  1581. retstr += Generate(String.Format("new {0}(", rc.Type), rc);
  1582. retstr += GenerateNode((SYMBOL)rc.kids[0]);
  1583. retstr += Generate(", ");
  1584. retstr += GenerateNode((SYMBOL)rc.kids[1]);
  1585. retstr += Generate(", ");
  1586. retstr += GenerateNode((SYMBOL)rc.kids[2]);
  1587. retstr += Generate(", ");
  1588. retstr += GenerateNode((SYMBOL)rc.kids[3]);
  1589. retstr += Generate(")");
  1590. return retstr;
  1591. }
  1592. if (identEx is ListConstant)
  1593. return GenerateListConstant((ListConstant)identEx);
  1594. return null;
  1595. }
  1596. private string CheckIfGlobalVariable(string varName, string type, SYMBOL kid)
  1597. {
  1598. string globalVarValue = "";
  1599. if (kid is Constant)
  1600. {
  1601. Constant c = kid as Constant;
  1602. // Supprt LSL's weird acceptance of floats with no trailing digits
  1603. // after the period. Turn float x = 10.; into float x = 10.0;
  1604. if ("LSL_Types.LSLFloat" == c.Type)
  1605. {
  1606. int dotIndex = c.Value.IndexOf('.') + 1;
  1607. if (0 < dotIndex && (dotIndex == c.Value.Length || !Char.IsDigit(c.Value[dotIndex])))
  1608. globalVarValue = c.Value.Insert(dotIndex, "0");
  1609. globalVarValue = "new LSL_Types.LSLFloat(" + c.Value + ") ";
  1610. }
  1611. else if ("LSL_Types.LSLInteger" == c.Type)
  1612. {
  1613. globalVarValue = "new LSL_Types.LSLInteger(" + c.Value + ") ";
  1614. }
  1615. else if ("LSL_Types.LSLString" == c.Type)
  1616. {
  1617. globalVarValue = "new LSL_Types.LSLString(\"" + c.Value + "\") ";
  1618. }
  1619. if (globalVarValue == "")
  1620. globalVarValue = c.Value;
  1621. if (globalVarValue == null)
  1622. globalVarValue = GenerateNode(c);
  1623. if (GlobalVariables.ContainsKey(globalVarValue))
  1624. {
  1625. //Its an assignment to another global var!
  1626. //reset the global value to the other's value
  1627. GlobalVar var;
  1628. GlobalVariables.TryGetValue(globalVarValue, out var);
  1629. //Do one last additional test before we set it.
  1630. if (type == var.Type)
  1631. {
  1632. globalVarValue = var.Value;
  1633. }
  1634. c.Value = globalVarValue;
  1635. }
  1636. else if (GlobalVariables.ContainsKey(varName))
  1637. {
  1638. }
  1639. else
  1640. GlobalVariables.Add(varName, new GlobalVar
  1641. {
  1642. Type = type,
  1643. Value = globalVarValue
  1644. });
  1645. return globalVarValue;
  1646. }
  1647. else if (kid is IdentExpression)
  1648. {
  1649. IdentExpression c = kid as IdentExpression;
  1650. globalVarValue = c.Name;
  1651. if (GlobalVariables.ContainsKey(globalVarValue))
  1652. {
  1653. //Its an assignment to another global var!
  1654. //reset the global value to the other's value
  1655. GlobalVar var;
  1656. GlobalVariables.TryGetValue(globalVarValue, out var);
  1657. //Do one last additional test before we set it.
  1658. if (type == var.Type)
  1659. {
  1660. globalVarValue = var.Value;
  1661. }
  1662. }
  1663. GlobalVariables.Add(varName, new GlobalVar
  1664. {
  1665. Type = type,
  1666. Value = globalVarValue
  1667. });
  1668. return globalVarValue;
  1669. }
  1670. else if (kid is UnaryExpression)
  1671. {
  1672. UnaryExpression c = kid as UnaryExpression;
  1673. foreach (SYMBOL k in c.kids)
  1674. {
  1675. globalVarValue += CheckIfGlobalVariable(varName, type, k);
  1676. }
  1677. return globalVarValue;
  1678. }
  1679. else
  1680. return GenerateNode(kid);
  1681. }
  1682. /// <summary>
  1683. /// Generates the code for a State node.
  1684. /// </summary>
  1685. /// <param name = "s">The State node.</param>
  1686. /// <returns>String containing C# code for State s.</returns>
  1687. private string GenerateState(State s)
  1688. {
  1689. string retstr = "";
  1690. _currentLocalStateDeclaration = s;
  1691. foreach (SYMBOL kid in s.kids)
  1692. if (kid is StateEvent)
  1693. retstr += GenerateStateEvent((StateEvent)kid, s.Name);
  1694. return retstr;
  1695. }
  1696. /// <summary>
  1697. /// Generates the code for a StateEvent node.
  1698. /// </summary>
  1699. /// <param name = "se">The StateEvent node.</param>
  1700. /// <param name = "parentStateName">The name of the parent state.</param>
  1701. /// <returns>String containing C# code for StateEvent se.</returns>
  1702. private string GenerateStateEvent(StateEvent se, string parentStateName)
  1703. {
  1704. StringBuilder retstr = new StringBuilder();
  1705. // we need to separate the argument declaration list from other kids
  1706. List<SYMBOL> argumentDeclarationListKids = new List<SYMBOL>();
  1707. List<SYMBOL> remainingKids = new List<SYMBOL>();
  1708. _currentLocalFunctionDeclaration = se;
  1709. MethodVariables.Clear();
  1710. VariablesToRename.Clear();
  1711. foreach (SYMBOL kid in se.kids)
  1712. if (kid is ArgumentDeclarationList)
  1713. argumentDeclarationListKids.Add(kid);
  1714. else
  1715. remainingKids.Add(kid);
  1716. // "state" (function) declaration
  1717. retstr.Append(GenerateIndented(
  1718. String.Format("public System.Collections.IEnumerator {0}_event_{1}(", parentStateName, se.Name), se));
  1719. IsParentEnumerable = true;
  1720. // print the state arguments, if any
  1721. List<ArgumentDeclarationList> args = new List<ArgumentDeclarationList>();
  1722. foreach (SYMBOL kid in argumentDeclarationListKids)
  1723. {
  1724. args.Add(((ArgumentDeclarationList)kid));
  1725. retstr.Append(GenerateArgumentDeclarationList((ArgumentDeclarationList)kid));
  1726. }
  1727. m_allMethods.Add(String.Format("{0}_event_{1}", parentStateName, se.Name), args);
  1728. retstr.Append(GenerateLine(")"));
  1729. foreach (SYMBOL kid in remainingKids)
  1730. retstr.Append(GenerateNode(kid));
  1731. if (retstr[retstr.Length - 2] == '}')
  1732. retstr.Insert(retstr.Length - 2, GenerateLine(" yield break;"));
  1733. return retstr.ToString();
  1734. }
  1735. /// <summary>
  1736. /// Generates the code for an ArgumentDeclarationList node.
  1737. /// </summary>
  1738. /// <param name = "adl">The ArgumentDeclarationList node.</param>
  1739. /// <returns>String containing C# code for ArgumentDeclarationList adl.</returns>
  1740. private string GenerateArgumentDeclarationList(ArgumentDeclarationList adl)
  1741. {
  1742. string retstr = "";
  1743. int comma = adl.kids.Count - 1; // tells us whether to print a comma
  1744. foreach (Declaration d in adl.kids)
  1745. {
  1746. retstr += GenerateDeclaration(d);
  1747. // retstr += Generate(String.Format("{0} {1}", d.Datatype, CheckName(d.Id)), d);
  1748. if (0 < comma--)
  1749. retstr += Generate(", ");
  1750. }
  1751. return retstr;
  1752. }
  1753. /// <summary>
  1754. /// Generates the code for an ArgumentList node.
  1755. /// </summary>
  1756. /// <param name = "al">The ArgumentList node.</param>
  1757. /// <returns>String containing C# code for ArgumentList al.</returns>
  1758. private string GenerateArgumentList(ArgumentList al)
  1759. {
  1760. string retstr = "";
  1761. int comma = al.kids.Count - 1; // tells us whether to print a comma
  1762. foreach (SYMBOL s in al.kids)
  1763. {
  1764. retstr += GenerateNode(s);
  1765. if (0 < comma--)
  1766. retstr += Generate(", ");
  1767. }
  1768. return retstr;
  1769. }
  1770. /// <summary>
  1771. /// Generates the code for a CompoundStatement node.
  1772. /// </summary>
  1773. /// <param name = "cs">The CompoundStatement node.</param>
  1774. /// <returns>String containing C# code for CompoundStatement cs.</returns>
  1775. private string GenerateCompoundStatement(CompoundStatement cs)
  1776. {
  1777. string retstr = "";
  1778. // opening brace
  1779. retstr += GenerateIndentedLine("{");
  1780. // if (IsParentEnumerable)
  1781. // retstr += GenerateLine("if (CheckSlice()) yield return null;");
  1782. m_braceCount++;
  1783. foreach (SYMBOL kid in cs.kids)
  1784. if (kid is Statement && kid.kids.Top is BinaryExpression &&
  1785. ((BinaryExpression)kid.kids.Top).ExpressionSymbol == "==")
  1786. continue;
  1787. else
  1788. retstr += GenerateNode(kid);
  1789. // closing brace
  1790. m_braceCount--;
  1791. retstr += GenerateIndentedLine("}");
  1792. return retstr;
  1793. }
  1794. /// <summary>
  1795. /// Generates the code for a Declaration node.
  1796. /// </summary>
  1797. /// <param name = "d">The Declaration node.</param>
  1798. /// <returns>String containing C# code for Declaration d.</returns>
  1799. private string GenerateDeclaration(Declaration d)
  1800. {
  1801. // return Generate(String.Format("{0} {1}", d.Datatype, CheckName(d.Id)), d);
  1802. GlobalVar var;
  1803. if (IsaGlobalVar)
  1804. return Generate(String.Format("{0} {1}", d.Datatype, CheckName(d.Id)), d);
  1805. if (GlobalVariables.TryGetValue(d.Id, out var))
  1806. return Generate(String.Format("{0} {1}", d.Datatype, CheckName(d.Id)), d);
  1807. //Commented out because we can't handle the same var name in different if/else statements
  1808. /*if (MethodVariables.TryGetValue(d.Id, out var))
  1809. {
  1810. if (var.Type != d.Datatype)
  1811. {
  1812. Console.WriteLine("[CSCodeGenerator]: found var needing renamed!");
  1813. string NewVariableName = RandomString(10, true);
  1814. VarRename r = new VarRename();
  1815. r.OldVarName = d.Id;
  1816. r.HasBeenAssigned = false;
  1817. r.NewVarName = NewVariableName;
  1818. VariablesToRename.Add(d.Id, r);
  1819. d.Id = NewVariableName;
  1820. MethodVariables.Add(d.Id, new GlobalVar() { Type = d.Datatype, Value = "" });
  1821. return Generate(String.Format("{0} {1}", d.Datatype, CheckName(d.Id)), d);
  1822. }
  1823. else
  1824. return Generate(String.Format("{0} {1}", d.Datatype, CheckName(d.Id)), d);
  1825. }
  1826. else
  1827. {
  1828. MethodVariables[d.Id] = new GlobalVar() { Type = d.Datatype, Value = "" };
  1829. return Generate(String.Format("{0} {1}", d.Datatype, CheckName(d.Id)), d);
  1830. }
  1831. * */
  1832. return Generate(String.Format("{0} {1}", d.Datatype, CheckName(d.Id)), d);
  1833. }
  1834. /// <summary>
  1835. /// Generates the code for a Statement node.
  1836. /// </summary>
  1837. /// <param name = "s">The Statement node.</param>
  1838. /// <returns>String containing C# code for Statement s.</returns>
  1839. private string GenerateStatement(Statement s)
  1840. {
  1841. string retstr = "";
  1842. bool printSemicolon = true;
  1843. bool marc = FuncCallsMarc();
  1844. retstr += Indent();
  1845. if (0 < s.kids.Count)
  1846. {
  1847. // Jump label prints its own colon, we don't need a semicolon.
  1848. printSemicolon = !(s.kids.Top is JumpLabel);
  1849. // If we encounter a lone Ident, we skip it, since that's a C#
  1850. // (MONO) error.
  1851. if (!(s.kids.Top is IdentExpression && 1 == s.kids.Count))
  1852. {
  1853. foreach (SYMBOL kid in s.kids)
  1854. {
  1855. // if (kid is Assignment && m_SLCompatabilityMode)
  1856. if (kid is Assignment)
  1857. {
  1858. Assignment a = kid as Assignment;
  1859. List<string> identifiers = new List<string>();
  1860. checkForMultipleAssignments(identifiers, a);
  1861. SYMBOL firstChild = (SYMBOL)a.kids[0];
  1862. bool retStrChanged = false;
  1863. if (firstChild is Declaration &&
  1864. DuplicatedLocalVariables[GetLocalDeclarationKey()].ContainsKey(((Declaration)firstChild).Id))
  1865. {
  1866. Declaration dec = ((Declaration)firstChild);
  1867. if (a.kids.Count == 2)
  1868. {
  1869. SYMBOL assignmentChild = (SYMBOL)a.kids[1];
  1870. if (assignmentChild is IdentExpression)
  1871. {
  1872. IdentExpression identEx = (IdentExpression)assignmentChild;
  1873. }
  1874. else if (assignmentChild is ListConstant)
  1875. {
  1876. ListConstant listConst = (ListConstant)assignmentChild;
  1877. foreach (SYMBOL listChild in listConst.kids)
  1878. {
  1879. if (listChild is ArgumentList)
  1880. {
  1881. ArgumentList argList = (ArgumentList)listChild;
  1882. int i = 0;
  1883. bool changed = false;
  1884. object[] p = new object[argList.kids.Count];
  1885. foreach (SYMBOL objChild in argList.kids)
  1886. {
  1887. p[i] = objChild;
  1888. if (objChild is IdentExpression)
  1889. {
  1890. IdentExpression identEx = (IdentExpression)objChild;
  1891. }
  1892. i++;
  1893. }
  1894. if (changed)
  1895. {
  1896. argList.kids = new ObjectList();
  1897. foreach (object o in p)
  1898. argList.kids.Add(o);
  1899. }
  1900. }
  1901. }
  1902. }
  1903. else if (assignmentChild is Constant)
  1904. {
  1905. Constant identEx = (Constant)assignmentChild;
  1906. string value = GetValue(identEx);
  1907. Constant dupConstant = (Constant)DuplicatedLocalVariables[GetLocalDeclarationKey()][dec.Id];
  1908. dupConstant.Value = dupConstant.Value == null ? GetValue(dupConstant) : dupConstant.Value;
  1909. if (value != dupConstant.Value)
  1910. {
  1911. retStrChanged = true;
  1912. retstr += dec.Id;
  1913. a.kids.Pop();
  1914. }
  1915. }
  1916. }
  1917. }
  1918. if (!retStrChanged)
  1919. retstr += GenerateNode((SYMBOL)a.kids.Pop());
  1920. retstr += Generate(String.Format(" {0} ", a.AssignmentType), a);
  1921. foreach (SYMBOL akid in a.kids)
  1922. {
  1923. if (akid is BinaryExpression)
  1924. {
  1925. BinaryExpression be = akid as BinaryExpression;
  1926. if (be.ExpressionSymbol.Equals("&&") || be.ExpressionSymbol.Equals("||"))
  1927. {
  1928. // special case handling for logical and/or, see Mantis 3174
  1929. retstr += "((bool)(";
  1930. retstr += GenerateNode((SYMBOL)be.kids.Pop());
  1931. retstr += "))";
  1932. retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol.Substring(0, 1)),
  1933. be);
  1934. retstr += "((bool)(";
  1935. foreach (SYMBOL bkid in be.kids)
  1936. retstr += GenerateNode(bkid);
  1937. retstr += "))";
  1938. }
  1939. else
  1940. {
  1941. retstr += GenerateNode((SYMBOL)be.kids.Pop());
  1942. retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol), be);
  1943. foreach (SYMBOL kidb in be.kids)
  1944. {
  1945. // if (kidb is FunctionCallExpression)
  1946. {
  1947. retstr += GenerateNode(kidb);
  1948. }
  1949. }
  1950. }
  1951. }
  1952. else
  1953. {
  1954. retstr += GenerateNode(akid);
  1955. }
  1956. }
  1957. }
  1958. else
  1959. {
  1960. if (kid is FunctionCallExpression)
  1961. {
  1962. foreach (SYMBOL akid in kid.kids)
  1963. {
  1964. if (akid is FunctionCall)
  1965. retstr += GenerateFunctionCall(akid as FunctionCall, false);
  1966. else
  1967. retstr += GenerateNode(akid);
  1968. }
  1969. }
  1970. else
  1971. {
  1972. // this kids will not need to dump in current string position
  1973. // so save what we have in dump and let kids have their own then take it again
  1974. retstr += DumpFunc(marc) + GenerateNode(kid);
  1975. marc = FuncCallsMarc();
  1976. }
  1977. }
  1978. }
  1979. }
  1980. }
  1981. //Nasty hack to fix if statements with yield return and yield break;
  1982. if (retstr[retstr.Length - 1] == '}')
  1983. printSemicolon = false;
  1984. if (printSemicolon)
  1985. retstr += GenerateLine(";");
  1986. return DumpFunc(marc) + retstr + DumpAfterFunc(marc);
  1987. }
  1988. private string GetLocalDeclarationKey()
  1989. {
  1990. if (_currentLocalStateDeclaration == null)
  1991. {
  1992. if (_currentGlobalFunctionDeclaration == null)
  1993. return null;
  1994. else
  1995. return "global_function_" + _currentGlobalFunctionDeclaration.Name;
  1996. }
  1997. return _currentLocalStateDeclaration.Name + "_" + _currentLocalFunctionDeclaration.Name;
  1998. }
  1999. /// <summary>
  2000. /// Generates the code for an Assignment node.
  2001. /// </summary>
  2002. /// <param name = "a">The Assignment node.</param>
  2003. /// <returns>String containing C# code for Assignment a.</returns>
  2004. private string GenerateAssignment(Assignment a)
  2005. {
  2006. string retstr = "";
  2007. List<string> identifiers = new List<string>();
  2008. bool marc = FuncCallsMarc();
  2009. checkForMultipleAssignments(identifiers, a);
  2010. if (a.kids[a.kids.Count - 1] is ListConstant && isAdditionExpression) //Deal with the list memory hack
  2011. {
  2012. a.kids.Pop(); //Get rid of the first one
  2013. foreach (SYMBOL kid in a.kids)
  2014. retstr += GenerateNode(kid);
  2015. return retstr; //If it is a list, and we are in an addition expression, we drop the assignment
  2016. }
  2017. retstr += GenerateNode((SYMBOL)a.kids.Pop());
  2018. retstr += Generate(String.Format(" {0} ", a.AssignmentType), a);
  2019. foreach (SYMBOL kid in a.kids)
  2020. retstr += GenerateNode(kid);
  2021. //fCalls += ";";//Add a ; at the end.
  2022. //lock (AfterFuncCalls)
  2023. // AfterFuncCalls.Add (fCalls);
  2024. return DumpFunc(marc) + retstr + DumpAfterFunc(marc);
  2025. }
  2026. // This code checks for LSL of the following forms, and generates a
  2027. // warning if it finds them.
  2028. //
  2029. // list l = [ "foo" ];
  2030. // l = (l=[]) + l + ["bar"];
  2031. // (produces l=["foo","bar"] in SL but l=["bar"] in OS)
  2032. //
  2033. // integer i;
  2034. // integer j;
  2035. // i = (j = 3) + (j = 4) + (j = 5);
  2036. // (produces j=3 in SL but j=5 in OS)
  2037. //
  2038. // Without this check, that code passes compilation, but does not do what
  2039. // the end user expects, because LSL in SL evaluates right to left instead
  2040. // of left to right.
  2041. //
  2042. // The theory here is that producing an error and alerting the end user that
  2043. // something needs to change is better than silently generating incorrect code.
  2044. private void checkForMultipleAssignments(List<string> identifiers, SYMBOL s)
  2045. {
  2046. if (s is Assignment)
  2047. {
  2048. Assignment a = (Assignment)s;
  2049. string newident = null;
  2050. if (a.kids[0] is Declaration)
  2051. {
  2052. newident = ((Declaration)a.kids[0]).Id;
  2053. }
  2054. else if (a.kids[0] is IDENT)
  2055. {
  2056. newident = ((IDENT)a.kids[0]).yytext;
  2057. }
  2058. else if (a.kids[0] is IdentDotExpression)
  2059. {
  2060. newident = ((IdentDotExpression)a.kids[0]).Name; // +"." + ((IdentDotExpression)a.kids[0]).Member;
  2061. }
  2062. else
  2063. {
  2064. AddWarning(String.Format(
  2065. "Multiple assignments checker internal error '{0}' at line {1} column {2}.", a.kids[0].GetType(),
  2066. ((SYMBOL)a.kids[0]).Line - 1, ((SYMBOL)a.kids[0]).Position));
  2067. }
  2068. if (identifiers.Contains(newident))
  2069. {
  2070. AddWarning(
  2071. String.Format(
  2072. "Multiple assignments to '{0}' at line {1} column {2}; results may differ between LSL and OSSL.",
  2073. newident, ((SYMBOL)a.kids[0]).Line - 1, ((SYMBOL)a.kids[0]).Position));
  2074. }
  2075. identifiers.Add(newident);
  2076. }
  2077. int index;
  2078. for (index = 0; index < s.kids.Count; index++)
  2079. {
  2080. checkForMultipleAssignments(identifiers, (SYMBOL)s.kids[index]);
  2081. }
  2082. }
  2083. /// <summary>
  2084. /// Generates the code for a ReturnStatement node.
  2085. /// </summary>
  2086. /// <param name = "rs">The ReturnStatement node.</param>
  2087. /// <returns>String containing C# code for ReturnStatement rs.</returns>
  2088. private string GenerateReturnStatement(ReturnStatement rs)
  2089. {
  2090. string retstr = "";
  2091. bool dump = FuncCallsMarc();
  2092. if (IsParentEnumerable)
  2093. {
  2094. retstr += GenerateLine("{ ");
  2095. if (rs.kids.Count == 0)
  2096. retstr += GenerateLine("yield break;", rs);
  2097. else
  2098. {
  2099. retstr += Generate(string.Format("yield return ({0})(", _currentGlobalFunctionDeclaration.ReturnType), rs);
  2100. foreach (SYMBOL kid in rs.kids)
  2101. retstr += GenerateNode(kid);
  2102. retstr += GenerateLine(");", null);
  2103. retstr += GenerateLine("yield break;", null);
  2104. }
  2105. retstr += GenerateLine("}");
  2106. }
  2107. else
  2108. {
  2109. retstr += Generate(string.Format("return ({0})", _currentGlobalFunctionDeclaration.ReturnType), rs);
  2110. foreach (SYMBOL kid in rs.kids)
  2111. retstr += GenerateNode(kid);
  2112. }
  2113. if (dump)
  2114. return DumpFunc(dump) + retstr + DumpAfterFunc(dump);
  2115. return retstr;
  2116. }
  2117. /// <summary>
  2118. /// Generates the code for a JumpLabel node.
  2119. /// </summary>
  2120. /// <param name = "jl">The JumpLabel node.</param>
  2121. /// <returns>String containing C# code for JumpLabel jl.</returns>
  2122. private string GenerateJumpLabel(JumpLabel jl)
  2123. {
  2124. return GenerateLine(Generate(String.Format("{0}:", CheckName(jl.LabelName)), jl) + " NoOp();");
  2125. }
  2126. /// <summary>
  2127. /// Generates the code for a JumpStatement node.
  2128. /// </summary>
  2129. /// <param name = "js">The JumpStatement node.</param>
  2130. /// <returns>String containing C# code for JumpStatement js.</returns>
  2131. private string GenerateJumpStatement(JumpStatement js)
  2132. {
  2133. return Generate(String.Format("goto {0}", CheckName(js.TargetName)), js);
  2134. }
  2135. /// <summary>
  2136. /// Generates the code for an IfStatement node.
  2137. /// </summary>
  2138. /// <param name = "ifs">The IfStatement node.</param>
  2139. /// <returns>String containing C# code for IfStatement ifs.</returns>
  2140. private string GenerateIfStatement(IfStatement ifs)
  2141. {
  2142. /*
  2143. * Test script that was used to make sure that if statements do not fail
  2144. integer a = 0;
  2145. integer test()
  2146. {
  2147. a++;
  2148. return a;
  2149. }
  2150. default
  2151. {
  2152. state_entry()
  2153. {
  2154. if(test() == 0) //1 gets returned here
  2155. {
  2156. llSay(0, "Script running. 0");
  2157. }
  2158. else if(test() == 1) //2 gets returned here
  2159. {
  2160. llSay(0, "Script running. 2");
  2161. }
  2162. else
  2163. {
  2164. // 3 gets returned here
  2165. if(test() == 4)
  2166. {
  2167. llSay(0, "Script running. 4");
  2168. }
  2169. else if(test() == 4)
  2170. {
  2171. // It should hit this path
  2172. llSay(0, "Script running. 2 4");
  2173. }
  2174. else
  2175. {
  2176. // 5 would be returned here
  2177. llSay(0, "Script running. else " + test());
  2178. }
  2179. }
  2180. }
  2181. }*/
  2182. string retstr = "";
  2183. string tmpstr = "";
  2184. bool DoBrace = false;
  2185. bool marc = FuncCallsMarc();
  2186. tmpstr += GenerateIndented("if (", ifs);
  2187. tmpstr += GenerateNode((SYMBOL)ifs.kids.Pop());
  2188. tmpstr += GenerateLine(")");
  2189. retstr += DumpFunc(marc) + tmpstr;
  2190. // CompoundStatement handles indentation itself but we need to do it
  2191. // otherwise.
  2192. // bool indentHere = ifs.kids.Top is Statement;
  2193. // if (indentHere) m_braceCount++;
  2194. DoBrace = !(ifs.kids.Top is CompoundStatement);
  2195. if (DoBrace)
  2196. retstr += GenerateLine("{");
  2197. retstr += GenerateNode((SYMBOL)ifs.kids.Pop());
  2198. // if (indentHere) m_braceCount--;
  2199. if (DoBrace)
  2200. retstr += GenerateLine("}");
  2201. if (0 < ifs.kids.Count) // do it again for an else
  2202. {
  2203. retstr += GenerateIndentedLine("else", ifs);
  2204. // indentHere = ifs.kids.Top is Statement;
  2205. // if (indentHere) m_braceCount++;
  2206. DoBrace = !(ifs.kids.Top is CompoundStatement);
  2207. if (DoBrace)
  2208. retstr += GenerateLine("{");
  2209. retstr += GenerateNode((SYMBOL)ifs.kids.Pop());
  2210. if (DoBrace)
  2211. retstr += GenerateLine("}");
  2212. // if (indentHere) m_braceCount--;
  2213. }
  2214. return retstr + DumpAfterFunc(marc);
  2215. }
  2216. /// <summary>
  2217. /// Generates the code for a StateChange node.
  2218. /// </summary>
  2219. /// <param name = "sc">The StateChange node.</param>
  2220. /// <returns>String containing C# code for StateChange sc.</returns>
  2221. private string GenerateStateChange(StateChange sc)
  2222. {
  2223. //State is in the LSL_Api because it requires a ref to the ScriptEngine, which we can't have in the ScriptBase
  2224. string retStr = GenerateLine("try", null);
  2225. retStr += GenerateLine("{", null);
  2226. retStr += Generate(
  2227. String.Format("((ILSL_Api)m_apis[\"ll\"]).state(\"{0}\");", sc.NewState)
  2228. , sc);
  2229. retStr += GenerateLine("}", null);
  2230. retStr += GenerateLine("catch", null);
  2231. retStr += GenerateLine("{", null);
  2232. retStr += GenerateLine("yield break;", null);
  2233. retStr += GenerateLine("}", null);
  2234. return retStr;
  2235. }
  2236. /// <summary>
  2237. /// Generates the code for a WhileStatement node.
  2238. /// </summary>
  2239. /// <param name = "ws">The WhileStatement node.</param>
  2240. /// <returns>String containing C# code for WhileStatement ws.</returns>
  2241. private string GenerateWhileStatement(WhileStatement ws)
  2242. {
  2243. string retstr = "";
  2244. string tmpstr = "";
  2245. bool marc = FuncCallsMarc();
  2246. tmpstr += GenerateIndented("while (", ws);
  2247. tmpstr += GenerateNode((SYMBOL)ws.kids.Pop());
  2248. tmpstr += GenerateLine(")");
  2249. //Forces all functions to use MoveNext() instead of .Current, as it never changes otherwise, and the loop runs infinitely
  2250. m_isInEnumeratedDeclaration = true;
  2251. retstr += DumpFunc(marc) + tmpstr;
  2252. m_isInEnumeratedDeclaration = false; //End above
  2253. if (IsParentEnumerable)
  2254. {
  2255. retstr += GenerateLine("{"); // SLAM! No 'while(true) doThis(); ' statements for you!
  2256. retstr += GenerateLine("if (CheckSlice()) yield return null;");
  2257. }
  2258. // CompoundStatement handles indentation itself but we need to do it
  2259. // otherwise.
  2260. bool indentHere = ws.kids.Top is Statement;
  2261. if (indentHere) m_braceCount++;
  2262. retstr += GenerateNode((SYMBOL)ws.kids.Pop());
  2263. if (indentHere) m_braceCount--;
  2264. if (IsParentEnumerable)
  2265. retstr += GenerateLine("}");
  2266. return retstr + DumpAfterFunc(marc);
  2267. }
  2268. /// <summary>
  2269. /// Generates the code for a DoWhileStatement node.
  2270. /// </summary>
  2271. /// <param name = "dws">The DoWhileStatement node.</param>
  2272. /// <returns>String containing C# code for DoWhileStatement dws.</returns>
  2273. private string GenerateDoWhileStatement(DoWhileStatement dws)
  2274. {
  2275. string retstr = "";
  2276. string tmpstr = "";
  2277. tmpstr += GenerateIndentedLine("do", dws);
  2278. if (IsParentEnumerable)
  2279. {
  2280. tmpstr += GenerateLine("{"); // SLAM!
  2281. tmpstr += GenerateLine("if (CheckSlice()) yield return null;");
  2282. }
  2283. // CompoundStatement handles indentation itself but we need to do it
  2284. // otherwise.
  2285. bool indentHere = dws.kids.Top is Statement;
  2286. if (indentHere) m_braceCount++;
  2287. tmpstr += GenerateNode((SYMBOL)dws.kids.Pop());
  2288. if (indentHere) m_braceCount--;
  2289. if (IsParentEnumerable)
  2290. tmpstr += GenerateLine("}");
  2291. bool marc = FuncCallsMarc();
  2292. //Forces all functions to use MoveNext() instead of .Current, as it never changes otherwise, and the loop runs infinitely
  2293. m_isInEnumeratedDeclaration = true;
  2294. tmpstr += GenerateIndented("while (", dws);
  2295. tmpstr += GenerateNode((SYMBOL)dws.kids.Pop());
  2296. tmpstr += GenerateLine(");");
  2297. m_isInEnumeratedDeclaration = false; //End above
  2298. retstr += DumpFunc(marc) + tmpstr;
  2299. return retstr + DumpAfterFunc(marc);
  2300. }
  2301. /// <summary>
  2302. /// Generates the code for a ForLoop node.
  2303. /// </summary>
  2304. /// <param name = "fl">The ForLoop node.</param>
  2305. /// <returns>String containing C# code for ForLoop fl.</returns>
  2306. private string GenerateForLoop(ForLoop fl)
  2307. {
  2308. string retstr = "";
  2309. string tmpstr = "";
  2310. bool marc = FuncCallsMarc();
  2311. tmpstr += GenerateIndented("for (", fl);
  2312. // It's possible that we don't have an assignment, in which case
  2313. // the child will be null and we only print the semicolon.
  2314. // for (x = 0; x < 10; x++)
  2315. // ^^^^^
  2316. ForLoopStatement s = (ForLoopStatement)fl.kids.Pop();
  2317. if (null != s)
  2318. {
  2319. tmpstr += GenerateForLoopStatement(s);
  2320. }
  2321. tmpstr += Generate("; ");
  2322. // for (x = 0; x < 10; x++)
  2323. // ^^^^^^
  2324. tmpstr += GenerateNode((SYMBOL)fl.kids.Pop());
  2325. tmpstr += Generate("; ");
  2326. // for (x = 0; x < 10; x++)
  2327. // ^^^
  2328. tmpstr += GenerateForLoopStatement((ForLoopStatement)fl.kids.Pop());
  2329. tmpstr += GenerateLine(")");
  2330. retstr += DumpFunc(marc) + tmpstr;
  2331. if (IsParentEnumerable)
  2332. {
  2333. retstr += GenerateLine("{"); // SLAM! No 'for(i = 0; i < 1; i = 0) doSomething();' statements for you
  2334. retstr += GenerateLine("if (CheckSlice()) yield return null;");
  2335. }
  2336. // CompoundStatement handles indentation itself but we need to do it
  2337. // otherwise.
  2338. bool indentHere = fl.kids.Top is Statement;
  2339. if (indentHere) m_braceCount++;
  2340. retstr += GenerateNode((SYMBOL)fl.kids.Pop());
  2341. if (indentHere) m_braceCount--;
  2342. if (IsParentEnumerable)
  2343. retstr += GenerateLine("}");
  2344. return retstr + DumpAfterFunc(marc);
  2345. }
  2346. /// <summary>
  2347. /// Generates the code for a ForLoopStatement node.
  2348. /// </summary>
  2349. /// <param name = "fls">The ForLoopStatement node.</param>
  2350. /// <returns>String containing C# code for ForLoopStatement fls.</returns>
  2351. private string GenerateForLoopStatement(ForLoopStatement fls)
  2352. {
  2353. string retstr = "";
  2354. int comma = fls.kids.Count - 1; // tells us whether to print a comma
  2355. // It's possible that all we have is an empty Ident, for example:
  2356. //
  2357. // for (x; x < 10; x++) { ... }
  2358. //
  2359. // Which is illegal in C# (MONO). We'll skip it.
  2360. if (fls.kids.Top is IdentExpression && 1 == fls.kids.Count)
  2361. return retstr;
  2362. for (int i = 0; i < fls.kids.Count; i++)
  2363. {
  2364. SYMBOL s = (SYMBOL)fls.kids[i];
  2365. // Statements surrounded by parentheses in for loops
  2366. //
  2367. // e.g. for ((i = 0), (j = 7); (i < 10); (++i))
  2368. //
  2369. // are legal in LSL but not in C# so we need to discard the parentheses
  2370. //
  2371. // The following, however, does not appear to be legal in LLS
  2372. //
  2373. // for ((i = 0, j = 7); (i < 10); (++i))
  2374. //
  2375. // As of Friday 20th November 2009, the Linden Lab simulators appear simply never to compile or run this
  2376. // script but with no debug or warnings at all! Therefore, we won't deal with this yet (which looks
  2377. // like it would be considerably more complicated to handle).
  2378. while (s is ParenthesisExpression)
  2379. s = (SYMBOL)s.kids.Pop();
  2380. retstr += GenerateNode(s);
  2381. if (0 < comma--)
  2382. retstr += Generate(", ");
  2383. }
  2384. return retstr;
  2385. }
  2386. /// <summary>
  2387. /// Generates the code for a BinaryExpression node.
  2388. /// </summary>
  2389. /// <param name = "be">The BinaryExpression node.</param>
  2390. /// <returns>String containing C# code for BinaryExpression be.</returns>
  2391. private string GenerateBinaryExpression(BinaryExpression be, bool isUnaryExpression, string addition)
  2392. {
  2393. string retstr = "";
  2394. bool marc = FuncCallsMarc();
  2395. if (be.ExpressionSymbol.Equals("&&") || be.ExpressionSymbol.Equals("||"))
  2396. {
  2397. // special case handling for logical and/or, see Mantis 3174
  2398. retstr += "((LSL_Types.LSLInteger)( " +
  2399. (isUnaryExpression ? addition : "") +
  2400. "(bool)(";
  2401. retstr += GenerateNode((SYMBOL)be.kids.Pop());
  2402. retstr += "))";
  2403. retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol.Substring(0, 1)), be);
  2404. retstr += "((LSL_Types.LSLInteger)((bool)(";
  2405. foreach (SYMBOL kid in be.kids)
  2406. retstr += GenerateNode(kid);
  2407. retstr += "))))";
  2408. }
  2409. else if (be.ExpressionSymbol.Equals("!=") || be.ExpressionSymbol.Equals("=="))
  2410. {
  2411. retstr += "((LSL_Types.LSLInteger)(";
  2412. retstr += GenerateNode((SYMBOL)be.kids.Pop());
  2413. retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol), be);
  2414. foreach (SYMBOL kid in be.kids)
  2415. retstr += GenerateNode(kid);
  2416. retstr += "))";
  2417. }
  2418. else
  2419. {
  2420. /*ObjectList kids = new ObjectList ();
  2421. for (int i = be.kids.Count-1; i >= 0; i--)
  2422. {
  2423. kids.Add(be.kids[i]);
  2424. }*/
  2425. bool weSetTheAdditionExpression = false;
  2426. if (be.ExpressionSymbol == "+" && !isAdditionExpression)
  2427. {
  2428. weSetTheAdditionExpression = true;
  2429. isAdditionExpression = true;
  2430. }
  2431. retstr += GenerateNode((SYMBOL)be.kids.Pop());
  2432. if (weSetTheAdditionExpression)
  2433. isAdditionExpression = false;
  2434. if (!(retstr == "()" || retstr == ""))
  2435. retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol), be);
  2436. else
  2437. //Something was removed, we need to remove the operator here!
  2438. retstr = "";
  2439. foreach (SYMBOL kid in be.kids)
  2440. retstr += GenerateNode(kid);
  2441. }
  2442. return DumpFunc(marc) + retstr + DumpAfterFunc(marc);
  2443. }
  2444. /// <summary>
  2445. /// Generates the code for a UnaryExpression node.
  2446. /// </summary>
  2447. /// <param name = "ue">The UnaryExpression node.</param>
  2448. /// <returns>String containing C# code for UnaryExpression ue.</returns>
  2449. private string GenerateUnaryExpression(UnaryExpression ue)
  2450. {
  2451. string retstr = "";
  2452. retstr += Generate(ue.UnarySymbol, ue);
  2453. SYMBOL kid = (SYMBOL)ue.kids.Pop();
  2454. if (kid is BinaryExpression)
  2455. {
  2456. string tempretstr = retstr;
  2457. retstr = "";
  2458. retstr += GenerateBinaryExpression((BinaryExpression)kid, true, tempretstr);
  2459. }
  2460. else
  2461. retstr += GenerateNode(kid);
  2462. return retstr;
  2463. }
  2464. /// <summary>
  2465. /// Generates the code for a ParenthesisExpression node.
  2466. /// </summary>
  2467. /// <param name = "pe">The ParenthesisExpression node.</param>
  2468. /// <returns>String containing C# code for ParenthesisExpression pe.</returns>
  2469. private string GenerateParenthesisExpression(ParenthesisExpression pe)
  2470. {
  2471. string retstr = "";
  2472. retstr += Generate("(");
  2473. foreach (SYMBOL kid in pe.kids)
  2474. retstr += GenerateNode(kid);
  2475. retstr += Generate(")");
  2476. return retstr;
  2477. }
  2478. /// <summary>
  2479. /// Generates the code for a IncrementDecrementExpression node.
  2480. /// </summary>
  2481. /// <param name = "ide">The IncrementDecrementExpression node.</param>
  2482. /// <returns>String containing C# code for IncrementDecrementExpression ide.</returns>
  2483. private string GenerateIncrementDecrementExpression(IncrementDecrementExpression ide)
  2484. {
  2485. string retstr = "";
  2486. if (0 < ide.kids.Count)
  2487. {
  2488. IdentDotExpression dot = (IdentDotExpression)ide.kids.Top;
  2489. retstr +=
  2490. Generate(
  2491. String.Format("{0}",
  2492. ide.PostOperation
  2493. ? CheckName(dot.Name) + "." + dot.Member + ide.Operation
  2494. : ide.Operation + CheckName(dot.Name) + "." + dot.Member), ide);
  2495. }
  2496. else
  2497. retstr +=
  2498. Generate(
  2499. String.Format("{0}",
  2500. ide.PostOperation
  2501. ? CheckName(ide.Name) + ide.Operation
  2502. : ide.Operation + CheckName(ide.Name)), ide);
  2503. return retstr;
  2504. }
  2505. /// <summary>
  2506. /// Generates the code for a TypecastExpression node.
  2507. /// </summary>
  2508. /// <param name = "te">The TypecastExpression node.</param>
  2509. /// <returns>String containing C# code for TypecastExpression te.</returns>
  2510. private string GenerateTypecastExpression(TypecastExpression te)
  2511. {
  2512. string retstr = "";
  2513. // we wrap all typecasted statements in parentheses
  2514. retstr += Generate(String.Format("({0}) (", te.TypecastType), te);
  2515. retstr += GenerateNode((SYMBOL)te.kids.Pop());
  2516. retstr += Generate(")");
  2517. return retstr;
  2518. }
  2519. /// <summary>
  2520. /// Generates the code for a FunctionCall node.
  2521. /// </summary>
  2522. /// <param name = "fc">The FunctionCall node.</param>
  2523. /// <returns>String containing C# code for FunctionCall fc.</returns>
  2524. private string GenerateFunctionCall(FunctionCall fc, bool NeedRetVal)
  2525. {
  2526. string retstr = "";
  2527. bool marc = FuncCallsMarc();
  2528. string Mname = "";
  2529. bool isEnumerable = false;
  2530. string tempString = "";
  2531. //int NeedCloseParent = 0;
  2532. foreach (SYMBOL kid in fc.kids)
  2533. {
  2534. // if (kid is ArgumentList && m_SLCompatabilityMode)
  2535. if (kid is ArgumentList)
  2536. {
  2537. ArgumentList al = kid as ArgumentList;
  2538. int comma = al.kids.Count - 1; // tells us whether to print a comma
  2539. foreach (SYMBOL s in al.kids)
  2540. {
  2541. if (s is BinaryExpression)
  2542. {
  2543. BinaryExpression be = s as BinaryExpression;
  2544. //FunctionCalls += GenerateNode(s);
  2545. if (be.ExpressionSymbol.Equals("&&") || be.ExpressionSymbol.Equals("||"))
  2546. {
  2547. // special case handling for logical and/or, see Mantis 3174
  2548. tempString += "((bool)(";
  2549. tempString += GenerateNode((SYMBOL)be.kids.Pop());
  2550. tempString += "))";
  2551. tempString += Generate(String.Format(" {0} ", be.ExpressionSymbol.Substring(0, 1)), be);
  2552. tempString += "((bool)(";
  2553. foreach (SYMBOL kidb in be.kids)
  2554. retstr += GenerateNode(kidb);
  2555. tempString += "))";
  2556. }
  2557. else
  2558. {
  2559. tempString += GenerateNode((SYMBOL)be.kids.Pop());
  2560. tempString += Generate(String.Format(" {0} ", be.ExpressionSymbol), be);
  2561. foreach (SYMBOL kidb in be.kids)
  2562. {
  2563. if (kidb is FunctionCallExpression)
  2564. {
  2565. tempString += GenerateNode(kidb);
  2566. }
  2567. else if (kidb is TypecastExpression)
  2568. {
  2569. tempString +=
  2570. Generate(String.Format("({0}) (", ((TypecastExpression)kidb).TypecastType));
  2571. tempString += GenerateNode((SYMBOL)kidb.kids.Pop());
  2572. tempString += Generate(")");
  2573. }
  2574. else
  2575. tempString += GenerateNode(kidb);
  2576. }
  2577. }
  2578. }
  2579. else if (s is TypecastExpression)
  2580. {
  2581. tempString += Generate(String.Format("({0}) (", ((TypecastExpression)s).TypecastType));
  2582. tempString += GenerateNode((SYMBOL)s.kids.Pop());
  2583. tempString += Generate(")");
  2584. }
  2585. else
  2586. {
  2587. tempString += GenerateNode(s);
  2588. }
  2589. if (0 < comma--)
  2590. tempString += Generate(", ");
  2591. }
  2592. }
  2593. else
  2594. {
  2595. tempString += GenerateNode(kid);
  2596. }
  2597. }
  2598. isEnumerable = false;
  2599. bool DTFunction = false;
  2600. string rettype = "void";
  2601. if (LocalMethods.TryGetValue(fc.Id, out rettype))
  2602. isEnumerable = true;
  2603. /* suspended.. API fails with IEnums
  2604. else if (IenFunctions.TryGetValue(fc.Id, out rettype))
  2605. isEnumerable = true;
  2606. */
  2607. else if (DTFunctions.Contains(fc.Id))
  2608. {
  2609. DTFunction = true;
  2610. }
  2611. //Check whether this function is an API function
  2612. if (m_apiFunctions.ContainsKey(CheckName(fc.Id)))
  2613. {
  2614. //Add the m_apis link
  2615. fc.Id = String.Format("(({0})m_apis[\"{1}\"]).{2}",
  2616. m_apiFunctions[CheckName(fc.Id)].InterfaceName,
  2617. m_apiFunctions[CheckName(fc.Id)].Name, fc.Id);
  2618. }
  2619. if (DTFunction)
  2620. {
  2621. retstr += Generate("yield return ");
  2622. retstr += Generate(String.Format("{0}(", CheckName(fc.Id)), fc);
  2623. retstr += tempString;
  2624. retstr += Generate(")");
  2625. }
  2626. else if (isEnumerable)
  2627. {
  2628. if (m_isInEnumeratedDeclaration && NeedRetVal) //Got to have a retVal for do/while
  2629. {
  2630. //This is for things like the do/while statement, where a function is in the while() part and can't be dumped in front of the do/while
  2631. string MethodName = Aurora.Framework.StringUtils.RandomString(10, true);
  2632. string typeDefs = "";
  2633. ObjectList arguements = null;
  2634. if (LocalMethodArguements.TryGetValue(fc.Id, out arguements))
  2635. {
  2636. // print the state arguments, if any
  2637. foreach (SYMBOL kid in arguements)
  2638. {
  2639. if (kid is ArgumentDeclarationList)
  2640. {
  2641. ArgumentDeclarationList ADL = (ArgumentDeclarationList)kid;
  2642. typeDefs += (GenerateArgumentDeclarationList(ADL)) + ",";
  2643. }
  2644. }
  2645. }
  2646. if (typeDefs.Length != 0)
  2647. typeDefs = typeDefs.Remove(typeDefs.Length - 1);
  2648. string newMethod = string.Format("private {0} {1}({2}, out bool ahwowuerogng)", rettype, MethodName,
  2649. typeDefs);
  2650. newMethod += (Generate("{"));
  2651. newMethod += (Generate("ahwowuerogng = true;"));
  2652. Mname = Aurora.Framework.StringUtils.RandomString(10, true);
  2653. newMethod += (Generate("System.Collections.IEnumerator " + Mname + " = "));
  2654. newMethod += (Generate(String.Format("{0}(", CheckName(fc.Id)), fc));
  2655. newMethod += (tempString);
  2656. newMethod += (Generate(");"));
  2657. newMethod += (Generate(" try {"));
  2658. newMethod += (Generate(Mname + ".MoveNext();"));
  2659. newMethod += (Generate(" if(" + Mname + ".Current != null)"));
  2660. newMethod += (Generate(" return (" + rettype + ")" + Mname + ".Current;"));
  2661. newMethod += (Generate(" }")); //End of try
  2662. newMethod += (Generate(" catch(Exception ex) "));
  2663. newMethod += (Generate(" {"));
  2664. newMethod += (Generate(" }")); //End of catch
  2665. newMethod += (Generate("ahwowuerogng = true;"));
  2666. newMethod += (Generate("return default(" + rettype + ");")); //End while
  2667. newMethod += "}";
  2668. MethodsToAdd.Add(newMethod);
  2669. List<string> fCalls = new List<string>();
  2670. string boolname = Aurora.Framework.StringUtils.RandomString(10, true);
  2671. fCalls.Add(Generate("bool " + boolname + " = true;"));
  2672. retstr += MethodName + "(" + tempString + ", out " + boolname + ")";
  2673. lock (FuncCalls)
  2674. FuncCalls.AddRange(fCalls);
  2675. }
  2676. else
  2677. {
  2678. //Function calls are added to the DumpFunc command, and will be dumped safely before the statement that occurs here, so we don't have to deal with the issues behind having { and } in this area.
  2679. Mname = Aurora.Framework.StringUtils.RandomString(10, true);
  2680. string Exname = Aurora.Framework.StringUtils.RandomString(10, true);
  2681. List<string> fCalls = new List<string>
  2682. {
  2683. Generate("string " + Exname + " = \"\";"),
  2684. Generate("System.Collections.IEnumerator " + Mname + " = "),
  2685. Generate(String.Format("{0}(", CheckName(fc.Id)), fc),
  2686. tempString,
  2687. Generate(");"),
  2688. Generate("while (true) {"),
  2689. Generate(" try {"),
  2690. Generate(" if(!" + Mname + ".MoveNext())"),
  2691. Generate(" break;"),
  2692. Generate(" }"),
  2693. Generate(" catch(Exception ex) "),
  2694. Generate(" {"),
  2695. Generate(" " + Exname + " = ex.Message;"),
  2696. Generate(" }"),
  2697. Generate(" if(" + Exname + " != \"\")"),
  2698. Generate(" yield return " + Exname + ";"),
  2699. Generate(" else if(" + Mname + ".Current == null || " + Mname +
  2700. ".Current is DateTime)"),
  2701. Generate(" yield return " + Mname + ".Current;"),
  2702. Generate(" else break;"),
  2703. Generate(" }")
  2704. };
  2705. //Let the other things process for a bit here at the end of each enumeration
  2706. //Let the other things process for a bit here at the end of each enumeration
  2707. if (NeedRetVal && rettype != "void")
  2708. {
  2709. retstr += " (" + rettype + ") " + Mname + ".Current";
  2710. }
  2711. lock (FuncCalls)
  2712. FuncCalls.AddRange(fCalls);
  2713. }
  2714. }
  2715. else
  2716. {
  2717. retstr += Generate(String.Format("{0}(", CheckName(fc.Id)), fc);
  2718. retstr += tempString;
  2719. retstr += Generate(")");
  2720. }
  2721. //Function calls are first if needed
  2722. return DumpFunc(marc) + retstr + DumpAfterFunc(marc);
  2723. }
  2724. /// <summary>
  2725. /// Generates the code for a Constant node.
  2726. /// </summary>
  2727. /// <param name = "c">The Constant node.</param>
  2728. /// <returns>String containing C# code for Constant c.</returns>
  2729. private string GenerateConstant(Constant c)
  2730. {
  2731. string retstr = "";
  2732. // Supprt LSL's weird acceptance of floats with no trailing digits
  2733. // after the period. Turn float x = 10.; into float x = 10.0;
  2734. if ("LSL_Types.LSLFloat" == c.Type)
  2735. {
  2736. int dotIndex = c.Value.IndexOf('.') + 1;
  2737. if (0 < dotIndex && (dotIndex == c.Value.Length || !Char.IsDigit(c.Value[dotIndex])))
  2738. c.Value = c.Value.Insert(dotIndex, "0");
  2739. c.Value = "new LSL_Types.LSLFloat(" + c.Value + ")";
  2740. }
  2741. else if ("LSL_Types.LSLInteger" == c.Type)
  2742. {
  2743. c.Value = "new LSL_Types.LSLInteger(" + c.Value + ")";
  2744. }
  2745. else if ("LSL_Types.LSLString" == c.Type)
  2746. {
  2747. c.Value = "new LSL_Types.LSLString(\"" + c.Value + "\")";
  2748. }
  2749. retstr += Generate(c.Value, c);
  2750. return retstr;
  2751. }
  2752. /// <summary>
  2753. /// Generates the code for a VectorConstant node.
  2754. /// </summary>
  2755. /// <param name = "vc">The VectorConstant node.</param>
  2756. /// <returns>String containing C# code for VectorConstant vc.</returns>
  2757. private string GenerateVectorConstant(VectorConstant vc)
  2758. {
  2759. string retstr = "";
  2760. retstr += Generate(String.Format("new {0}(", vc.Type), vc);
  2761. retstr += GenerateNode((SYMBOL)vc.kids.Pop());
  2762. retstr += Generate(", ");
  2763. retstr += GenerateNode((SYMBOL)vc.kids.Pop());
  2764. retstr += Generate(", ");
  2765. retstr += GenerateNode((SYMBOL)vc.kids.Pop());
  2766. retstr += Generate(")");
  2767. return retstr;
  2768. }
  2769. /// <summary>
  2770. /// Generates the code for a RotationConstant node.
  2771. /// </summary>
  2772. /// <param name = "rc">The RotationConstant node.</param>
  2773. /// <returns>String containing C# code for RotationConstant rc.</returns>
  2774. private string GenerateRotationConstant(RotationConstant rc)
  2775. {
  2776. string retstr = "";
  2777. retstr += Generate(String.Format("new {0}(", rc.Type), rc);
  2778. retstr += GenerateNode((SYMBOL)rc.kids.Pop());
  2779. retstr += Generate(", ");
  2780. retstr += GenerateNode((SYMBOL)rc.kids.Pop());
  2781. retstr += Generate(", ");
  2782. retstr += GenerateNode((SYMBOL)rc.kids.Pop());
  2783. retstr += Generate(", ");
  2784. retstr += GenerateNode((SYMBOL)rc.kids.Pop());
  2785. retstr += Generate(")");
  2786. return retstr;
  2787. }
  2788. /// <summary>
  2789. /// Generates the code for a ListConstant node.
  2790. /// </summary>
  2791. /// <param name = "lc">The ListConstant node.</param>
  2792. /// <returns>String containing C# code for ListConstant lc.</returns>
  2793. private string GenerateListConstant(ListConstant lc)
  2794. {
  2795. string retstr = "";
  2796. retstr += Generate(String.Format("new {0}(", lc.Type), lc);
  2797. foreach (SYMBOL kid in lc.kids)
  2798. retstr += GenerateNode(kid);
  2799. retstr += Generate(")");
  2800. return retstr;
  2801. }
  2802. /// <summary>
  2803. /// Prints a newline.
  2804. /// </summary>
  2805. /// <returns>A newline.</returns>
  2806. private string GenerateLine()
  2807. {
  2808. return GenerateLine("");
  2809. }
  2810. /// <summary>
  2811. /// Prints text, followed by a newline.
  2812. /// </summary>
  2813. /// <param name = "s">String of text to print.</param>
  2814. /// <returns>String s followed by newline.</returns>
  2815. private string GenerateLine(string s)
  2816. {
  2817. return GenerateLine(s, null);
  2818. }
  2819. /// <summary>
  2820. /// Prints text, followed by a newline.
  2821. /// </summary>
  2822. /// <param name = "s">String of text to print.</param>
  2823. /// <param name = "sym">Symbol being generated to extract original line
  2824. /// number and column from.</param>
  2825. /// <returns>String s followed by newline.</returns>
  2826. private string GenerateLine(string s, SYMBOL sym)
  2827. {
  2828. string retstr = Generate(s, sym) + "\n";
  2829. m_CSharpLine++;
  2830. m_CSharpCol = 1;
  2831. return retstr;
  2832. }
  2833. /// <summary>
  2834. /// Prints text.
  2835. /// </summary>
  2836. /// <param name = "s">String of text to print.</param>
  2837. /// <returns>String s.</returns>
  2838. private string Generate(string s)
  2839. {
  2840. return Generate(s, null);
  2841. }
  2842. /// <summary>
  2843. /// Prints text.
  2844. /// </summary>
  2845. /// <param name = "s">String of text to print.</param>
  2846. /// <param name = "sym">Symbol being generated to extract original line
  2847. /// number and column from.</param>
  2848. /// <returns>String s.</returns>
  2849. private string Generate(string s, SYMBOL sym)
  2850. {
  2851. if (null != sym)
  2852. m_positionMap.Add(new KeyValuePair<int, int>(m_CSharpLine, m_CSharpCol),
  2853. new KeyValuePair<int, int>(sym.Line, sym.Position));
  2854. m_CSharpCol += s.Length;
  2855. return s;
  2856. }
  2857. /// <summary>
  2858. /// Prints text correctly indented, followed by a newline.
  2859. /// </summary>
  2860. /// <param name = "s">String of text to print.</param>
  2861. /// <returns>Properly indented string s followed by newline.</returns>
  2862. private string GenerateIndentedLine(string s)
  2863. {
  2864. return GenerateIndentedLine(s, null);
  2865. }
  2866. /// <summary>
  2867. /// Prints text correctly indented, followed by a newline.
  2868. /// </summary>
  2869. /// <param name = "s">String of text to print.</param>
  2870. /// <param name = "sym">Symbol being generated to extract original line
  2871. /// number and column from.</param>
  2872. /// <returns>Properly indented string s followed by newline.</returns>
  2873. private string GenerateIndentedLine(string s, SYMBOL sym)
  2874. {
  2875. string retstr = GenerateIndented(s, sym) + "\n";
  2876. m_CSharpLine++;
  2877. m_CSharpCol = 1;
  2878. return retstr;
  2879. }
  2880. /// <summary>
  2881. /// Prints text correctly indented.
  2882. /// </summary>
  2883. /// <param name = "s">String of text to print.</param>
  2884. /// <param name = "sym">Symbol being generated to extract original line
  2885. /// number and column from.</param>
  2886. /// <returns>Properly indented string s.</returns>
  2887. private string GenerateIndented(string s, SYMBOL sym)
  2888. {
  2889. string retstr = Indent() + s;
  2890. if (null != sym)
  2891. m_positionMap.Add(new KeyValuePair<int, int>(m_CSharpLine, m_CSharpCol),
  2892. new KeyValuePair<int, int>(sym.Line, sym.Position));
  2893. m_CSharpCol += s.Length;
  2894. return retstr;
  2895. }
  2896. /// <summary>
  2897. /// Prints correct indentation.
  2898. /// </summary>
  2899. /// <returns>Indentation based on brace count.</returns>
  2900. private string Indent()
  2901. {
  2902. string retstr = String.Empty;
  2903. for (int i = 0; i < m_braceCount; i++)
  2904. for (int j = 0; j < m_indentWidth; j++)
  2905. {
  2906. retstr += " ";
  2907. m_CSharpCol++;
  2908. }
  2909. return retstr;
  2910. }
  2911. ///<summary>
  2912. /// Returns the passed name with an underscore prepended if that name is a reserved word in C#
  2913. /// and not resevered in LSL otherwise it just returns the passed name.
  2914. ///
  2915. /// This makes no attempt to cache the results to minimise future lookups. For a non trivial
  2916. /// scripts the number of unique identifiers could easily grow to the size of the reserved word
  2917. /// list so maintaining a list or dictionary and doing the lookup there firstwould probably not
  2918. /// give any real speed advantage.
  2919. ///
  2920. /// I believe there is a class Microsoft.CSharp.CSharpCodeProvider that has a function
  2921. /// CreateValidIdentifier(str) that will return either the value of str if it is not a C#
  2922. /// key word or "_"+str if it is. But availability under Mono?
  2923. ///</summary>
  2924. private string CheckName(string s)
  2925. {
  2926. if (CSReservedWords.IsReservedWord(s))
  2927. return "@" + s;
  2928. else
  2929. {
  2930. /*VarRename var;
  2931. if(VariablesToRename.TryGetValue(s, out var))
  2932. {
  2933. Console.WriteLine("[CSCodeGenerator]: found var needing renamed!");
  2934. if (var.HasBeenAssigned)
  2935. s = var.NewVarName;
  2936. else
  2937. {
  2938. s = var.OldVarName;
  2939. var.HasBeenAssigned = true;
  2940. VariablesToRename[s] = var;
  2941. }
  2942. }*/
  2943. return s;
  2944. }
  2945. }
  2946. private string DumpFunc(bool marc)
  2947. {
  2948. string ret = "";
  2949. if (!marc)
  2950. return ret;
  2951. FuncCntr = false;
  2952. if (FuncCalls.Count == 0)
  2953. {
  2954. return ret;
  2955. }
  2956. lock (FuncCalls)
  2957. {
  2958. foreach (string s in FuncCalls)
  2959. ret += GenerateIndentedLine(s);
  2960. FuncCalls.Clear();
  2961. }
  2962. return ret;
  2963. }
  2964. private string DumpAfterFunc(bool marc)
  2965. {
  2966. string ret = "";
  2967. if (!marc)
  2968. return ret;
  2969. FuncCntr = false;
  2970. if (AfterFuncCalls.Count == 0)
  2971. {
  2972. return ret;
  2973. }
  2974. lock (FuncCalls)
  2975. {
  2976. foreach (string s in AfterFuncCalls)
  2977. ret += GenerateIndentedLine(s);
  2978. AfterFuncCalls.Clear();
  2979. }
  2980. return ret;
  2981. }
  2982. private bool FuncCallsMarc()
  2983. {
  2984. if (FuncCntr)
  2985. return false;
  2986. FuncCntr = true;
  2987. return true;
  2988. }
  2989. #region Nested type: GlobalVar
  2990. private class GlobalVar
  2991. {
  2992. public string Type;
  2993. public string Value;
  2994. }
  2995. #endregion
  2996. #region Nested type: VarRename
  2997. private class VarRename
  2998. {
  2999. //public string NewVarName;
  3000. //public bool HasBeenAssigned;
  3001. //public string OldVarName;
  3002. }
  3003. #endregion
  3004. }
  3005. }