30 using System.Collections.Generic;
31 using System.Reflection;
34 using OpenSim.Region.Framework.Interfaces;
36 namespace OpenSim.
Region.ScriptEngine.Shared.CodeTools
42 private SYMBOL m_astRoot = null;
43 private Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> m_positionMap;
44 private int m_indentWidth = 4;
45 private int m_braceCount;
46 private int m_CSharpLine;
47 private int m_CSharpCol;
48 private List<string> m_warnings =
new List<string>();
51 private bool m_insertCoopTerminationChecks;
52 private static string m_coopTerminationCheck =
"opensim_reserved_CheckForCoopTermination();";
75 m_insertCoopTerminationChecks = insertCoopTerminationChecks;
83 public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> PositionMap
85 get {
return m_positionMap; }
94 get {
return m_astRoot; }
100 private void ResetCounters()
105 m_positionMap =
new Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>();
127 catch (CSToolsException e)
134 string emessage = e.Message;
135 string slinfo = e.slInfo.ToString();
139 if (emessage.StartsWith(slinfo+
": "))
140 emessage = emessage.Substring(slinfo.Length+2);
142 message = String.Format(
"({0},{1}) {2}",
143 e.slInfo.lineNumber - 1,
144 e.slInfo.charPosition - 1, emessage);
146 throw new Exception(message);
149 m_astRoot = codeTransformer.Transform();
151 string retstr = String.Empty;
168 retstr += GenerateLine();
169 foreach (SYMBOL s
in m_astRoot.kids)
170 retstr += GenerateNode(m_astRoot, s);
180 retstr = retstr.Replace(
"\r",
"");
191 return m_warnings.ToArray();
194 private void AddWarning(
string warning)
196 if (!m_warnings.Contains(warning))
198 m_warnings.Add(warning);
209 private string GenerateNode(SYMBOL previousSymbol, SYMBOL s)
211 string retstr = String.Empty;
216 if (s is GlobalFunctionDefinition)
217 retstr += GenerateGlobalFunctionDefinition((GlobalFunctionDefinition) s);
218 else if (s is GlobalVariableDeclaration)
219 retstr += GenerateGlobalVariableDeclaration((GlobalVariableDeclaration) s);
221 retstr += GenerateState((State) s);
222 else if (s is CompoundStatement)
223 retstr += GenerateCompoundStatement(previousSymbol, (CompoundStatement) s);
224 else if (s is Declaration)
225 retstr += GenerateDeclaration((Declaration) s);
226 else if (s is Statement)
227 retstr += GenerateStatement(previousSymbol, (Statement) s);
228 else if (s is ReturnStatement)
229 retstr += GenerateReturnStatement((ReturnStatement) s);
230 else if (s is JumpLabel)
231 retstr += GenerateJumpLabel((JumpLabel) s);
232 else if (s is JumpStatement)
233 retstr += GenerateJumpStatement((JumpStatement) s);
234 else if (s is StateChange)
235 retstr += GenerateStateChange((StateChange) s);
236 else if (s is IfStatement)
237 retstr += GenerateIfStatement((IfStatement) s);
238 else if (s is WhileStatement)
239 retstr += GenerateWhileStatement((WhileStatement) s);
240 else if (s is DoWhileStatement)
241 retstr += GenerateDoWhileStatement((DoWhileStatement) s);
242 else if (s is ForLoop)
243 retstr += GenerateForLoop((ForLoop) s);
244 else if (s is ArgumentList)
245 retstr += GenerateArgumentList((ArgumentList) s);
246 else if (s is Assignment)
247 retstr += GenerateAssignment((Assignment) s);
248 else if (s is BinaryExpression)
249 retstr += GenerateBinaryExpression((BinaryExpression) s);
250 else if (s is ParenthesisExpression)
251 retstr += GenerateParenthesisExpression((ParenthesisExpression) s);
252 else if (s is UnaryExpression)
253 retstr += GenerateUnaryExpression((UnaryExpression) s);
254 else if (s is IncrementDecrementExpression)
255 retstr += GenerateIncrementDecrementExpression((IncrementDecrementExpression) s);
256 else if (s is TypecastExpression)
257 retstr += GenerateTypecastExpression((TypecastExpression) s);
258 else if (s is FunctionCall)
259 retstr += GenerateFunctionCall((FunctionCall) s);
260 else if (s is VectorConstant)
261 retstr += GenerateVectorConstant((VectorConstant) s);
262 else if (s is RotationConstant)
263 retstr += GenerateRotationConstant((RotationConstant) s);
264 else if (s is ListConstant)
265 retstr += GenerateListConstant((ListConstant) s);
266 else if (s is Constant)
267 retstr += GenerateConstant((Constant) s);
268 else if (s is IdentDotExpression)
269 retstr += Generate(CheckName(((IdentDotExpression) s).Name) +
"." + ((IdentDotExpression) s).Member, s);
270 else if (s is IdentExpression)
271 retstr += GenerateIdentifier(((IdentExpression) s).Name, s);
273 retstr += Generate(CheckName(((TOKEN) s).yytext), s);
276 foreach (SYMBOL kid
in s.kids)
277 retstr += GenerateNode(s, kid);
288 private string GenerateGlobalFunctionDefinition(GlobalFunctionDefinition gf)
290 string retstr = String.Empty;
293 List<SYMBOL> argumentDeclarationListKids =
new List<SYMBOL>();
294 List<SYMBOL> remainingKids =
new List<SYMBOL>();
296 foreach (SYMBOL kid
in gf.kids)
297 if (kid is ArgumentDeclarationList)
298 argumentDeclarationListKids.Add(kid);
300 remainingKids.Add(kid);
302 retstr += GenerateIndented(
String.Format(
"{0} {1}(", gf.ReturnType, CheckName(gf.Name)), gf);
305 foreach (SYMBOL kid
in argumentDeclarationListKids)
306 retstr += GenerateArgumentDeclarationList((ArgumentDeclarationList) kid);
308 retstr += GenerateLine(
")");
310 foreach (SYMBOL kid
in remainingKids)
311 retstr += GenerateNode(gf, kid);
321 private string GenerateGlobalVariableDeclaration(GlobalVariableDeclaration gv)
323 string retstr = String.Empty;
325 foreach (SYMBOL s
in gv.kids)
328 retstr += GenerateNode(gv, s);
329 retstr += GenerateLine(
";");
340 private string GenerateState(State s)
342 string retstr = String.Empty;
344 foreach (SYMBOL kid
in s.kids)
345 if (kid is StateEvent)
346 retstr += GenerateStateEvent((StateEvent) kid, s.Name);
357 private string GenerateStateEvent(StateEvent se,
string parentStateName)
359 string retstr = String.Empty;
362 List<SYMBOL> argumentDeclarationListKids =
new List<SYMBOL>();
363 List<SYMBOL> remainingKids =
new List<SYMBOL>();
365 foreach (SYMBOL kid
in se.kids)
366 if (kid is ArgumentDeclarationList)
367 argumentDeclarationListKids.Add(kid);
369 remainingKids.Add(kid);
372 retstr += GenerateIndented(
String.Format(
"public void {0}_event_{1}(", parentStateName, se.Name), se);
375 foreach (SYMBOL kid
in argumentDeclarationListKids)
376 retstr += GenerateArgumentDeclarationList((ArgumentDeclarationList) kid);
378 retstr += GenerateLine(
")");
380 foreach (SYMBOL kid
in remainingKids)
381 retstr += GenerateNode(se, kid);
391 private string GenerateArgumentDeclarationList(ArgumentDeclarationList adl)
393 string retstr = String.Empty;
395 int comma = adl.kids.Count - 1;
397 foreach (Declaration d
in adl.kids)
399 retstr += Generate(
String.Format(
"{0} {1}", d.Datatype, CheckName(d.Id)), d);
401 retstr += Generate(
", ");
412 private string GenerateArgumentList(ArgumentList al)
414 string retstr = String.Empty;
416 int comma = al.kids.Count - 1;
418 foreach (SYMBOL s
in al.kids)
420 retstr += GenerateNode(al, s);
422 retstr += Generate(
", ");
433 private string GenerateCompoundStatement(SYMBOL previousSymbol, CompoundStatement cs)
435 string retstr = String.Empty;
438 retstr += GenerateIndentedLine(
"{");
441 if (m_insertCoopTerminationChecks)
444 if (previousSymbol is GlobalFunctionDefinition
445 || previousSymbol is WhileStatement
446 || previousSymbol is DoWhileStatement
447 || previousSymbol is ForLoop
448 || previousSymbol is StateEvent)
449 retstr += GenerateIndentedLine(m_coopTerminationCheck);
452 foreach (SYMBOL kid
in cs.kids)
453 retstr += GenerateNode(cs, kid);
457 retstr += GenerateIndentedLine(
"}");
467 private string GenerateDeclaration(Declaration d)
469 return Generate(
String.Format(
"{0} {1}", d.Datatype, CheckName(d.Id)), d);
477 private string GenerateStatement(SYMBOL previousSymbol, Statement s)
479 string retstr = String.Empty;
480 bool printSemicolon =
true;
481 bool transformToBlock =
false;
483 if (m_insertCoopTerminationChecks)
487 if (previousSymbol is WhileStatement
488 || previousSymbol is DoWhileStatement
489 || previousSymbol is ForLoop)
491 transformToBlock =
true;
494 retstr += GenerateIndentedLine(
"{");
496 retstr += GenerateIndentedLine(m_coopTerminationCheck);
502 if (0 < s.kids.Count)
505 printSemicolon = !(s.kids.Top is JumpLabel);
509 if (!(s.kids.Top is IdentExpression && 1 == s.kids.Count))
510 foreach (SYMBOL kid in s.kids)
511 retstr += GenerateNode(s, kid);
515 retstr += GenerateLine(
";");
517 if (transformToBlock)
520 retstr += GenerateIndentedLine(
"}");
531 private string GenerateAssignment(Assignment a)
533 string retstr = String.Empty;
535 List<string> identifiers =
new List<string>();
536 checkForMultipleAssignments(identifiers, a);
538 retstr += GenerateNode(a, (SYMBOL) a.kids.Pop());
539 retstr += Generate(
String.Format(
" {0} ", a.AssignmentType), a);
540 foreach (SYMBOL kid
in a.kids)
541 retstr += GenerateNode(a, kid);
564 private void checkForMultipleAssignments(List<string> identifiers, SYMBOL s)
568 Assignment a = (Assignment)s;
569 string newident = null;
571 if (a.kids[0] is Declaration)
573 newident = ((Declaration)a.kids[0]).Id;
575 else if (a.kids[0] is IDENT)
577 newident = ((IDENT)a.kids[0]).yytext;
579 else if (a.kids[0] is IdentDotExpression)
581 newident = ((IdentDotExpression)a.kids[0]).Name;
585 AddWarning(
String.Format(
"Multiple assignments checker internal error '{0}' at line {1} column {2}.", a.kids[0].GetType(), ((SYMBOL)a.kids[0]).Line - 1, ((SYMBOL)a.kids[0]).Position));
588 if (identifiers.Contains(newident))
590 AddWarning(
String.Format(
"Multiple assignments to '{0}' at line {1} column {2}; results may differ between LSL and OSSL.", newident, ((SYMBOL)a.kids[0]).Line - 1, ((SYMBOL)a.kids[0]).Position));
592 identifiers.Add(newident);
596 for (index = 0; index < s.kids.Count; index++)
598 checkForMultipleAssignments(identifiers, (SYMBOL) s.kids[index]);
607 private string GenerateReturnStatement(ReturnStatement rs)
609 string retstr = String.Empty;
611 retstr += Generate(
"return ", rs);
613 foreach (SYMBOL kid
in rs.kids)
614 retstr += GenerateNode(rs, kid);
624 private string GenerateJumpLabel(JumpLabel jl)
626 string labelStatement;
628 if (m_insertCoopTerminationChecks)
629 labelStatement = m_coopTerminationCheck;
631 labelStatement =
"NoOp();";
633 return GenerateLine(
String.Format(
"{0}: {1}", CheckName(jl.LabelName), labelStatement), jl);
641 private string GenerateJumpStatement(JumpStatement js)
643 return Generate(
String.Format(
"goto {0}", CheckName(js.TargetName)), js);
651 private string GenerateIfStatement(IfStatement ifs)
653 string retstr = String.Empty;
655 retstr += GenerateIndented(
"if (", ifs);
656 retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
657 retstr += GenerateLine(
")");
661 bool indentHere = ifs.kids.Top is Statement;
662 if (indentHere) m_braceCount++;
663 retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
664 if (indentHere) m_braceCount--;
666 if (0 < ifs.kids.Count)
668 retstr += GenerateIndentedLine(
"else", ifs);
670 indentHere = ifs.kids.Top is Statement;
671 if (indentHere) m_braceCount++;
672 retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
673 if (indentHere) m_braceCount--;
684 private string GenerateStateChange(StateChange sc)
686 return Generate(
String.Format(
"state(\"{0}\")", sc.NewState), sc);
694 private string GenerateWhileStatement(WhileStatement ws)
696 string retstr = String.Empty;
698 retstr += GenerateIndented(
"while (", ws);
699 retstr += GenerateNode(ws, (SYMBOL) ws.kids.Pop());
700 retstr += GenerateLine(
")");
704 bool indentHere = ws.kids.Top is Statement;
705 if (indentHere) m_braceCount++;
706 retstr += GenerateNode(ws, (SYMBOL) ws.kids.Pop());
707 if (indentHere) m_braceCount--;
717 private string GenerateDoWhileStatement(DoWhileStatement dws)
719 string retstr = String.Empty;
721 retstr += GenerateIndentedLine(
"do", dws);
725 bool indentHere = dws.kids.Top is Statement;
726 if (indentHere) m_braceCount++;
727 retstr += GenerateNode(dws, (SYMBOL) dws.kids.Pop());
728 if (indentHere) m_braceCount--;
730 retstr += GenerateIndented(
"while (", dws);
731 retstr += GenerateNode(dws, (SYMBOL) dws.kids.Pop());
732 retstr += GenerateLine(
");");
742 private string GenerateForLoop(ForLoop fl)
744 string retstr = String.Empty;
746 retstr += GenerateIndented(
"for (", fl);
752 ForLoopStatement s = (ForLoopStatement) fl.kids.Pop();
755 retstr += GenerateForLoopStatement(s);
757 retstr += Generate(
"; ");
760 retstr += GenerateNode(fl, (SYMBOL) fl.kids.Pop());
761 retstr += Generate(
"; ");
764 retstr += GenerateForLoopStatement((ForLoopStatement) fl.kids.Pop());
765 retstr += GenerateLine(
")");
769 bool indentHere = fl.kids.Top is Statement;
770 if (indentHere) m_braceCount++;
771 retstr += GenerateNode(fl, (SYMBOL) fl.kids.Pop());
772 if (indentHere) m_braceCount--;
782 private string GenerateForLoopStatement(ForLoopStatement fls)
784 string retstr = String.Empty;
786 int comma = fls.kids.Count - 1;
793 if (fls.kids.Top is IdentExpression && 1 == fls.kids.Count)
796 for (
int i = 0; i < fls.kids.Count; i++)
798 SYMBOL s = (SYMBOL)fls.kids[i];
813 while (s is ParenthesisExpression)
814 s = (SYMBOL)s.kids.Pop();
816 retstr += GenerateNode(fls, s);
818 retstr += Generate(
", ");
829 private string GenerateBinaryExpression(BinaryExpression be)
831 string retstr = String.Empty;
833 if (be.ExpressionSymbol.Equals(
"&&") || be.ExpressionSymbol.Equals(
"||"))
836 retstr +=
"((bool)(";
837 retstr += GenerateNode(be, (SYMBOL)be.kids.Pop());
839 retstr += Generate(
String.Format(
" {0} ", be.ExpressionSymbol.Substring(0,1)), be);
840 retstr +=
"((bool)(";
841 foreach (SYMBOL kid
in be.kids)
842 retstr += GenerateNode(be, kid);
847 retstr += GenerateNode(be, (SYMBOL)be.kids.Pop());
848 retstr += Generate(
String.Format(
" {0} ", be.ExpressionSymbol), be);
849 foreach (SYMBOL kid
in be.kids)
850 retstr += GenerateNode(be, kid);
861 private string GenerateUnaryExpression(UnaryExpression ue)
863 string retstr = String.Empty;
865 retstr += Generate(ue.UnarySymbol, ue);
866 retstr += GenerateNode(ue, (SYMBOL) ue.kids.Pop());
876 private string GenerateParenthesisExpression(ParenthesisExpression pe)
878 string retstr = String.Empty;
880 retstr += Generate(
"(");
881 foreach (SYMBOL kid
in pe.kids)
882 retstr += GenerateNode(pe, kid);
883 retstr += Generate(
")");
893 private string GenerateIncrementDecrementExpression(IncrementDecrementExpression ide)
895 string retstr = String.Empty;
897 if (0 < ide.kids.Count)
899 IdentDotExpression dot = (IdentDotExpression) ide.kids.Top;
900 retstr += Generate(
String.Format(
"{0}", ide.PostOperation ? CheckName(dot.Name) +
"." + dot.Member + ide.Operation : ide.Operation + CheckName(dot.Name) +
"." + dot.Member), ide);
903 retstr += Generate(
String.Format(
"{0}", ide.PostOperation ? CheckName(ide.Name) + ide.Operation : ide.Operation + CheckName(ide.Name)), ide);
913 private string GenerateTypecastExpression(TypecastExpression te)
915 string retstr = String.Empty;
918 retstr += Generate(
String.Format(
"({0}) (", te.TypecastType), te);
919 retstr += GenerateNode(te, (SYMBOL) te.kids.Pop());
920 retstr += Generate(
")");
931 private string GenerateIdentifier(
string id, SYMBOL s)
935 object value = m_comms.LookupModConstant(id);
938 string retval = null;
940 retval = String.Format(
"new LSL_Types.LSLInteger({0})",((int)value).ToString());
941 else if (value is
float)
942 retval = String.Format(
"new LSL_Types.LSLFloat({0})",((float)value).ToString());
943 else if (value is
string)
944 retval = String.Format(
"new LSL_Types.LSLString(\"{0}\")",((string)value));
945 else if (value is OpenMetaverse.UUID)
946 retval = String.Format(
"new LSL_Types.key(\"{0}\")",((OpenMetaverse.UUID)value).ToString());
947 else if (value is OpenMetaverse.Vector3)
948 retval = String.Format(
"new LSL_Types.Vector3(\"{0}\")",((OpenMetaverse.Vector3)value).ToString());
949 else if (value is OpenMetaverse.Quaternion)
950 retval = String.Format(
"new LSL_Types.Quaternion(\"{0}\")",((OpenMetaverse.Quaternion)value).ToString());
953 return Generate(retval, s);
957 return Generate(CheckName(
id), s);
965 private string GenerateFunctionCall(FunctionCall fc)
967 string retstr = String.Empty;
969 string modinvoke = null;
971 modinvoke = m_comms.LookupModInvocation(fc.Id);
973 if (modinvoke != null)
975 if (fc.kids[0] is ArgumentList)
977 if ((fc.kids[0] as ArgumentList).kids.Count == 0)
978 retstr += Generate(
String.Format(
"{0}(\"{1}\"",modinvoke,fc.Id), fc);
980 retstr += Generate(
String.Format(
"{0}(\"{1}\",",modinvoke,fc.Id), fc);
985 retstr += Generate(
String.Format(
"{0}(", CheckName(fc.Id)), fc);
988 foreach (SYMBOL kid
in fc.kids)
989 retstr += GenerateNode(fc, kid);
991 retstr += Generate(
")");
1001 private string GenerateConstant(Constant c)
1003 string retstr = String.Empty;
1007 if (
"LSL_Types.LSLFloat" == c.Type)
1009 int dotIndex = c.Value.IndexOf(
'.') + 1;
1010 if (0 < dotIndex && (dotIndex == c.Value.Length || !Char.IsDigit(c.Value[dotIndex])))
1011 c.Value = c.Value.Insert(dotIndex,
"0");
1012 c.Value =
"new LSL_Types.LSLFloat("+c.Value+
")";
1014 else if (
"LSL_Types.LSLInteger" == c.Type)
1016 c.Value =
"new LSL_Types.LSLInteger("+c.Value+
")";
1018 else if (
"LSL_Types.LSLString" == c.Type)
1020 c.Value =
"new LSL_Types.LSLString(\""+c.Value+
"\")";
1023 retstr += Generate(c.Value, c);
1033 private string GenerateVectorConstant(VectorConstant vc)
1035 string retstr = String.Empty;
1037 retstr += Generate(
String.Format(
"new {0}(", vc.Type), vc);
1038 retstr += GenerateNode(vc, (SYMBOL) vc.kids.Pop());
1039 retstr += Generate(
", ");
1040 retstr += GenerateNode(vc, (SYMBOL) vc.kids.Pop());
1041 retstr += Generate(
", ");
1042 retstr += GenerateNode(vc, (SYMBOL) vc.kids.Pop());
1043 retstr += Generate(
")");
1053 private string GenerateRotationConstant(RotationConstant rc)
1055 string retstr = String.Empty;
1057 retstr += Generate(
String.Format(
"new {0}(", rc.Type), rc);
1058 retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
1059 retstr += Generate(
", ");
1060 retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
1061 retstr += Generate(
", ");
1062 retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
1063 retstr += Generate(
", ");
1064 retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
1065 retstr += Generate(
")");
1075 private string GenerateListConstant(ListConstant lc)
1077 string retstr = String.Empty;
1079 retstr += Generate(
String.Format(
"new {0}(", lc.Type), lc);
1081 foreach (SYMBOL kid
in lc.kids)
1082 retstr += GenerateNode(lc, kid);
1084 retstr += Generate(
")");
1093 private string GenerateLine()
1095 return GenerateLine(
"");
1103 private string GenerateLine(
string s)
1105 return GenerateLine(s, null);
1115 private string GenerateLine(
string s, SYMBOL sym)
1117 string retstr = Generate(s, sym) +
"\n";
1130 private string Generate(
string s)
1132 return Generate(s, null);
1142 private string Generate(
string s, SYMBOL sym)
1145 m_positionMap.Add(
new KeyValuePair<int, int>(m_CSharpLine, m_CSharpCol),
new KeyValuePair<int, int>(sym.Line, sym.Position));
1147 m_CSharpCol += s.Length;
1157 private string GenerateIndentedLine(
string s)
1159 return GenerateIndentedLine(s, null);
1169 private string GenerateIndentedLine(
string s, SYMBOL sym)
1171 string retstr = GenerateIndented(s, sym) +
"\n";
1197 private string GenerateIndented(
string s, SYMBOL sym)
1199 string retstr = Indent() + s;
1202 m_positionMap.Add(
new KeyValuePair<int, int>(m_CSharpLine, m_CSharpCol),
new KeyValuePair<int, int>(sym.Line, sym.Position));
1204 m_CSharpCol += s.Length;
1213 private string Indent()
1215 string retstr = String.Empty;
1217 for (
int i = 0; i < m_braceCount; i++)
1218 for (
int j = 0; j < m_indentWidth; j++)
1240 private string CheckName(
string s)
1242 if (CSReservedWords.IsReservedWord(s))
Interface for communication between OpenSim modules and in-world scripts