This repository has been archived on 2024-04-07. You can view files and clone it, but cannot push or open issues or pull requests.
chovy-gm/GMAssetCompiler/GML2JavaScript.cs

1139 lines
27 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
namespace GMAssetCompiler
{
internal class GML2JavaScript
{
private static GMLCode ms_code;
private static GMAssets ms_assets;
private static int ms_numErrors;
private static bool ms_error;
public static string ms_varPrefix = "gml";
public static Dictionary<string, string> ms_globals = new Dictionary<string, string>();
private static Dictionary<string, string> ms_locals = new Dictionary<string, string>();
private static Dictionary<string, string> ms_arguments = new Dictionary<string, string>();
private static Stack<string> ms_thisName = new Stack<string>();
private static Stack<string> ms_otherName = new Stack<string>();
private static Stack<string> ms_breakContext = new Stack<string>();
private static int ms_unique = 0;
private static int ms_statements = 0;
private static Dictionary<string, int> ms_arrays = new Dictionary<string, int>();
private static StringBuilder ms_sbVariableName = new StringBuilder();
private static string GetUniqueName()
{
return string.Format("__yy__v{0}", ms_unique++);
}
public static void Error(string _errorMessage, GMLToken _token)
{
if (!Program.InhibitErrorOutput)
{
int num = 1;
for (int i = 0; i < _token.Index; i++)
{
if (ms_code.Code[i] == '\n')
{
num++;
}
}
Console.WriteLine("Error : {0}({1}) : {2}", ms_code.Name, num, _errorMessage);
}
ms_numErrors++;
ms_error = true;
Program.ExitCode = 1;
}
private static eType CompileUnary(GMLToken _tok, TextWriter _sw)
{
eType result = eType.eGMLT_Unknown;
switch (_tok.Id)
{
case 203:
_sw.Write("!(");
if (CompileExpression(_tok.Children[0], _sw) != 0)
{
_sw.Write(" > 0.5)");
}
else
{
_sw.Write(")");
}
result = eType.eGMLT_Bool;
break;
case 210:
case 211:
case 220:
_sw.Write(_tok.Text);
result = CompileExpression(_tok.Children[0], _sw);
break;
}
return result;
}
private static eType CompileBinary(GMLToken _tok, TextWriter _sw)
{
eType result = 0;
bool flag = false;
switch (_tok.Children[1].Token)
{
case eToken.eDiv:
_sw.Write("(~~");
break;
case eToken.eAnd:
case eToken.eOr:
flag = true;
break;
}
_sw.Write("(");
if (flag)
{
_sw.Write("(");
}
eType eType = CompileExpression(_tok.Children[0], _sw);
if (flag && eType != 0)
{
_sw.Write(" > 0.5");
}
if (flag)
{
_sw.Write(")");
}
for (int i = 1; i < _tok.Children.Count; i += 2)
{
switch (_tok.Children[i].Token)
{
case eToken.eNot:
_sw.Write("!");
break;
case eToken.eBitXor:
_sw.Write("^");
break;
case eToken.eDiv:
_sw.Write("/");
break;
case eToken.eMod:
_sw.Write("%");
break;
case eToken.eAnd:
_sw.Write("&&");
break;
case eToken.eOr:
_sw.Write("||");
break;
case eToken.eNotEqual:
_sw.Write("!=");
break;
case eToken.eAssign:
case eToken.eEqual:
_sw.Write("==");
break;
default:
_sw.Write(_tok.Children[i].Text);
break;
}
if (flag)
{
_sw.Write("(");
}
eType eType2 = CompileExpression(_tok.Children[i + 1], _sw);
if (flag && eType2 != 0)
{
_sw.Write(" > 0.5");
}
if (flag)
{
_sw.Write(")");
}
switch (_tok.Children[i].Token)
{
case eToken.eAssign:
case eToken.eAnd:
case eToken.eOr:
case eToken.eLess:
case eToken.eLessEqual:
case eToken.eEqual:
case eToken.eNotEqual:
case eToken.eGreaterEqual:
case eToken.eGreater:
result = eType.eGMLT_Bool;
break;
}
eType = eType2;
}
_sw.Write(")");
eToken token = _tok.Children[1].Token;
if (token == eToken.eDiv)
{
_sw.Write(")");
}
return result;
}
private static eType CompileConstant(GMLToken _tok, TextWriter _sw)
{
bool _setFunc = false;
eType result = eType.eGMLT_Var;
switch (_tok.Text)
{
case "global":
case "other":
case "self":
CompileVariable(_tok, _sw, false, out _setFunc);
break;
default:
switch (_tok.Value.Kind)
{
case eKind.eConstant:
_sw.Write("g_gmlConst.{0}", _tok.Value.ValueS);
break;
case eKind.eNone:
_sw.Write("null");
break;
case eKind.eNumber:
if (_tok.Value.ValueI < 0.0)
{
_sw.Write("(");
}
_sw.Write("{0}", Convert.ToString(_tok.Value.ValueI, CultureInfo.InvariantCulture.NumberFormat));
if (_tok.Value.ValueI < 0.0)
{
_sw.Write(")");
}
result = ((!(_tok.Text == "true") && !(_tok.Text == "false")) ? eType.eGMLT_Real : eType.eGMLT_Bool);
break;
case eKind.eString:
{
string text = _tok.Value.ValueS.Replace("\\", "\\\\");
text = text.Replace("\"", "\\\"");
text = text.Replace(Environment.NewLine, "#");
text = text.Replace(new string('\n', 1), "#");
_sw.Write("\"{0}\"", text);
result = eType.eGMLT_String;
break;
}
}
break;
}
return result;
}
private static eType CompileExpression(GMLToken _tok, TextWriter _sw)
{
eType result = eType.eGMLT_Unknown;
bool _setFunc = false;
switch (_tok.Token)
{
case eToken.eConstant:
result = CompileConstant(_tok, _sw);
break;
case eToken.eBinary:
result = CompileBinary(_tok, _sw);
break;
case eToken.eUnary:
result = CompileUnary(_tok, _sw);
break;
case eToken.eFunction:
result = CompileFunction(_tok, _sw);
break;
case eToken.eVariable:
case eToken.eDot:
result = CompileVariable(_tok, _sw, false, out _setFunc);
break;
}
return result;
}
private static void CompileSimpleVariable(GMLToken _tok, StringWriter _sw, bool _lvalue, out bool _setFunc, bool _inhibitExpansion)
{
string text = null;
string text2 = _tok.Text;
GMLVariable value = null;
if (!GMLCompile.ms_builtins.TryGetValue(text2, out value))
{
GMLCompile.ms_builtinsLocal.TryGetValue(text2, out value);
}
_setFunc = false;
if (value != null)
{
if (_lvalue && value.setFunction != null)
{
text2 = string.Format("{0}( ", value.setFunction);
_setFunc = true;
}
else if (!_lvalue && value.getFunction != null)
{
text2 = string.Format("{0}()", value.getFunction);
}
}
else
{
text2 = ms_varPrefix + text2;
}
text = text2;
if (!_inhibitExpansion && _tok.Id < 100000 && GMLCompile.ms_builtins.TryGetValue(_tok.Text, out value) && !ms_arguments.TryGetValue(_tok.Text, out text))
{
string empty = string.Empty;
empty = ((!(text2 == "argument_count")) ? string.Format("g_pBuiltIn.{0}", text2) : string.Format("({0}.arguments.length-2)", ms_code.Name));
_sw.Write(empty);
}
else if (!_inhibitExpansion && ms_globals.TryGetValue(_tok.Text, out text))
{
string value2 = string.Format("global.{0}", text2);
_sw.Write(value2);
}
else if (_inhibitExpansion || ms_locals.TryGetValue(text2, out text) || ms_arguments.TryGetValue(_tok.Text, out text) || string.IsNullOrEmpty(ms_thisName.Peek()))
{
_sw.Write(text);
}
else if (!_inhibitExpansion && GMLCompile.Find(ms_assets.Objects, _tok.Text) >= 0)
{
_sw.Write(GMLCompile.Find(ms_assets.Objects, _tok.Text).ToString());
}
else
{
string value3 = string.Format("{0}.{1}", ms_thisName.Peek(), text2);
_sw.Write(value3);
}
bool flag = false;
string value4 = "]";
string text3 = string.Empty;
if (_tok.Children.Count > 0)
{
string text4 = _sw.GetStringBuilder().ToString();
if (text4 == "g_pBuiltIn.instance_id")
{
_sw.GetStringBuilder().Length = 0;
_sw.Write("g_pBuiltIn.get_instance_id(");
value4 = ")";
flag = true;
}
else if (text4 == "g_pBuiltIn.argument")
{
_sw.GetStringBuilder().Length = 0;
_sw.Write("{0}.arguments[", ms_code.Name);
text3 = "2+";
flag = true;
}
else
{
int num = text4.LastIndexOf('.');
string arg = (num < 0) ? "_inst" : text4.Substring(0, num);
string arg2 = (num < 0) ? text4 : text4.Substring(num + 1, text4.Length - (num + 1));
_sw.GetStringBuilder().Length = 0;
_setFunc = _lvalue;
if (_lvalue)
{
string value5 = string.Format("array_set_{0}D( {1}, \"__{2}__\" ", _tok.Children.Count, arg, arg2);
_sw.Write(value5);
}
else
{
string value6 = string.Format("array_get_{0}D( {1}, \"__{2}__\" ", _tok.Children.Count, arg, arg2);
_sw.Write(value6);
}
}
}
ms_thisName.Pop();
if (_tok.Token != eToken.eVariable)
{
return;
}
int num2 = 0;
foreach (GMLToken child in _tok.Children)
{
if (!flag || num2 > 0)
{
_sw.Write(", ");
}
if (!string.IsNullOrEmpty(text3))
{
_sw.Write("{0} (", text3);
}
CompileExpression(child, _sw);
if (!string.IsNullOrEmpty(text3))
{
_sw.Write(")");
}
num2++;
}
if (_tok.Children.Count > 0)
{
if (flag)
{
_sw.Write(value4);
}
else if (_lvalue)
{
_sw.Write(", ");
}
else
{
_sw.Write(" ) ");
}
}
}
private static eType CompileVariable(GMLToken _tok, TextWriter _sw, bool _lvalue, out bool _setFunc)
{
eType result = eType.eGMLT_Var;
_setFunc = false;
int count = ms_thisName.Count;
ms_sbVariableName.Length = 0;
bool flag = false;
StringBuilder stringBuilder = new StringBuilder();
StringWriter stringWriter = new StringWriter(stringBuilder);
switch (_tok.Token)
{
case eToken.eDot:
switch (_tok.Children.Count)
{
case 0:
case 1:
Error("Expecting expression after the '.' ", _tok);
break;
default:
{
string text = null;
switch (_tok.Children[0].Text)
{
case "global":
text = _tok.Children[0].Text;
stringWriter.Write(text);
flag = true;
break;
case "self":
stringWriter.Write(ms_thisName.Peek());
flag = true;
break;
case "other":
stringWriter.Write(ms_otherName.Peek());
flag = true;
break;
default:
switch (_tok.Children[0].Token)
{
case eToken.eConstant:
CompileConstant(_tok.Children[0], stringWriter);
break;
case eToken.eVariable:
ms_thisName.Push(ms_thisName.Peek());
CompileSimpleVariable(_tok.Children[0], stringWriter, false, out _setFunc, false);
break;
case eToken.eFunction:
CompileFunction(_tok.Children[0], stringWriter);
break;
case eToken.eDot:
CompileVariable(_tok.Children[0], stringWriter, _lvalue, out _setFunc);
break;
default:
Console.WriteLine("This is a problem now!");
break;
}
break;
}
for (int i = 1; i < _tok.Children.Count; i++)
{
if (!flag)
{
string arg = stringBuilder.ToString();
stringBuilder.Length = 0;
stringWriter.Write("yyInst({0})", arg);
}
flag = false;
stringWriter.Write(".");
ms_thisName.Push("");
CompileSimpleVariable(_tok.Children[i], stringWriter, i == _tok.Children.Count - 1 && _lvalue, out _setFunc, true);
}
break;
}
}
break;
case eToken.eVariable:
ms_thisName.Push(ms_thisName.Peek());
CompileSimpleVariable(_tok, stringWriter, _lvalue, out _setFunc, false);
break;
case eToken.eConstant:
switch (_tok.Text)
{
default:
Error("constant is invalid here", _tok);
break;
case "self":
stringWriter.Write("{0}.id", ms_thisName.Peek());
break;
case "other":
stringWriter.Write("{0}.id", ms_otherName.Peek());
break;
}
break;
}
stringWriter.Close();
_sw.Write(stringBuilder.ToString());
if (count != ms_thisName.Count)
{
Error("Houston we have a problem!", _tok);
}
return result;
}
private static void CompileVar(GMLToken _tok, TextWriter _sw)
{
if (_tok.Children.Count > 0)
{
_sw.Write("var ");
int num = 0;
foreach (GMLToken child in _tok.Children)
{
if (num != 0)
{
_sw.Write(",");
}
string text = ms_varPrefix + child.Text;
_sw.Write("{0}", text);
string value;
if (!ms_locals.TryGetValue(text, out value))
{
ms_locals.Add(text, text);
}
num++;
}
}
}
private static void CompileGlobalVar(GMLToken _tok, TextWriter _sw)
{
foreach (GMLToken child in _tok.Children)
{
ms_globals[child.Text] = child.Text;
}
}
private static void CompileRepeat(GMLToken _tok, TextWriter _sw)
{
if (_tok.Children.Count != 2)
{
Error("malformed repeat statement", _tok);
}
string uniqueName = GetUniqueName();
string uniqueName2 = GetUniqueName();
_sw.Write("for( var {0}=0, {1}=", uniqueName, uniqueName2);
CompileExpression(_tok.Children[0], _sw);
_sw.Write("; {0}<{1}; {0}++) ", uniqueName, uniqueName2);
if (_tok.Children[1].Token == eToken.eBegin)
{
ms_statements++;
}
ms_breakContext.Push("CompileRepeat");
CompileStatement(_tok.Children[1], _sw);
ms_breakContext.Pop();
}
private static void CompileIf(GMLToken _tok, TextWriter _sw)
{
if (_tok.Children.Count < 2)
{
Error("malformed if statement", _tok);
}
_sw.Write("if (");
if (CompileExpression(_tok.Children[0], _sw) != 0)
{
_sw.Write(" > 0.5");
}
_sw.Write(") {");
if (_tok.Children.Count > 1)
{
if (_tok.Children[1].Token == eToken.eBegin)
{
ms_statements++;
}
CompileStatement(_tok.Children[1], _sw);
_sw.WriteLine(";}");
if (_tok.Children.Count > 2)
{
_sw.Write(" else {");
if (_tok.Children[2].Token == eToken.eBegin)
{
ms_statements++;
}
CompileStatement(_tok.Children[2], _sw);
_sw.Write(";}");
}
}
else
{
Error("if requires a then statement", _tok);
}
}
private static void CompileWhile(GMLToken _tok, TextWriter _sw)
{
if (_tok.Children.Count != 2)
{
Error("malformed while statement", _tok);
}
_sw.Write("while (");
CompileExpression(_tok.Children[0], _sw);
_sw.Write(") ");
ms_breakContext.Push("CompileWhile");
if (_tok.Children[1].Token == eToken.eBegin)
{
ms_statements++;
}
CompileStatement(_tok.Children[1], _sw);
ms_breakContext.Pop();
}
private static void CompileDo(GMLToken _tok, TextWriter _sw)
{
if (_tok.Children.Count != 2)
{
Error("malformed do statement", _tok);
}
_sw.WriteLine("do {");
ms_breakContext.Push("CompileDo");
CompileStatement(_tok.Children[0], _sw);
ms_breakContext.Pop();
_sw.Write("} while( !(");
CompileExpression(_tok.Children[1], _sw);
_sw.WriteLine("))");
}
private static void CompileFor(GMLToken _tok, TextWriter _sw)
{
if (_tok.Children.Count != 4)
{
Error("malformed for statement", _tok);
}
_sw.Write("for (");
CompileStatement(_tok.Children[0], _sw);
_sw.Write(" ; ");
CompileExpression(_tok.Children[1], _sw);
_sw.Write(" ; ");
CompileStatement(_tok.Children[2], _sw);
_sw.Write(") ");
if (_tok.Children[3].Token == eToken.eBegin)
{
ms_statements++;
}
ms_breakContext.Push("CompileFor");
CompileStatement(_tok.Children[3], _sw);
ms_breakContext.Pop();
}
private static void CompileWith(GMLToken _tok, TextWriter _sw)
{
if (_tok.Children.Count != 2)
{
Error("malformed with statement", _tok);
}
if (_tok.Children[0].Token == eToken.eConstant && (_tok.Children[0].Text == "other" || _tok.Children[0].Text == "self"))
{
string item = string.Empty;
switch (_tok.Children[0].Text)
{
case "other":
item = ms_otherName.Peek();
break;
case "self":
item = ms_thisName.Peek();
break;
}
ms_otherName.Push(ms_thisName.Peek());
ms_thisName.Push(item);
CompileStatement(_tok.Children[1], _sw);
if (_tok.Children[1].Token != eToken.eBegin)
{
_sw.Write(";");
}
ms_thisName.Pop();
ms_otherName.Pop();
return;
}
_sw.WriteLine("{");
string uniqueName = GetUniqueName();
string uniqueName2 = GetUniqueName();
string uniqueName3 = GetUniqueName();
_sw.Write("var {0} = GetWithArray(", uniqueName);
CompileExpression(_tok.Children[0], _sw);
_sw.WriteLine(" );");
_sw.WriteLine("for( var {0} in {1} ) {{", uniqueName2, uniqueName);
_sw.WriteLine(" var {0} = {1}[{2}];", uniqueName3, uniqueName, uniqueName2);
ms_otherName.Push(ms_thisName.Peek());
ms_thisName.Push(uniqueName3);
ms_statements++;
ms_breakContext.Push("CompileWith");
CompileStatement(_tok.Children[1], _sw);
ms_breakContext.Pop();
if (_tok.Children[1].Token != eToken.eBegin)
{
_sw.Write(";");
}
_sw.WriteLine("}");
ms_thisName.Pop();
ms_otherName.Pop();
_sw.WriteLine("}");
}
private static void CompileSwitch(GMLToken _tok, TextWriter _sw)
{
if (_tok.Children.Count == 0)
{
Error("malformed switch statement", _tok);
}
_sw.Write("switch(");
CompileExpression(_tok.Children[0], _sw);
_sw.WriteLine(") {");
ms_breakContext.Push("CompileSwitch");
bool flag = false;
for (int i = 1; i < _tok.Children.Count; i++)
{
switch (_tok.Children[i].Token)
{
case eToken.eCase:
_sw.Write("case ");
CompileExpression(_tok.Children[i].Children[0], _sw);
_sw.WriteLine(":");
flag = true;
break;
case eToken.eDefault:
_sw.WriteLine("default:");
flag = true;
break;
case eToken.eBreak:
if (!flag)
{
Error("statement in a switch MUST appear after case or default", _tok.Children[i]);
break;
}
CompileStatement(_tok.Children[i], _sw);
_sw.WriteLine(";");
flag = false;
break;
default:
if (!flag)
{
Error("statement in a switch MUST appear after case or default", _tok.Children[i]);
break;
}
CompileStatement(_tok.Children[i], _sw);
_sw.WriteLine(";");
break;
}
}
_sw.Write("}");
ms_breakContext.Pop();
}
private static eType CompileFunction(GMLToken _tok, TextWriter _sw)
{
eType result = eType.eGMLT_Var;
string text = _tok.Text;
int num = 0;
bool flag = false;
bool flag2 = false;
bool flag3 = false;
if (_tok.Id < 100000)
{
if (_tok.Text == "script_execute")
{
_sw.Write("JSON_game.Scripts[ ");
CompileExpression(_tok.Children[0], _sw);
_sw.Write("]( ");
flag = true;
flag2 = true;
flag3 = true;
}
else
{
int num2 = _tok.Id - GMLCompile.ms_id;
int index = (num2 >> 8) & 0xF;
int index2 = num2 >> 12;
if (_tok.Id > GMLCompile.ms_id && ms_assets.Extensions[index].Includes[index2].Kind == 2)
{
_sw.Write("gml_Script_{0}( ", _tok.Text);
flag = true;
flag2 = true;
}
else
{
GMLFunction value = null;
GMLCompile.ms_funcs.TryGetValue(text, out value);
_sw.Write("{0}( ", text);
flag = (value != null && value.InstanceFirstParam);
flag2 = (value != null && value.OtherSecondParam);
}
}
}
else
{
_sw.Write("gml_Script_{0}( ", _tok.Text);
flag = true;
flag2 = true;
}
if (flag)
{
if (!string.IsNullOrEmpty(ms_thisName.Peek()))
{
_sw.Write("{0} ", ms_thisName.Peek());
num++;
}
else
{
Error("calling a function that needs an instance and no instance is available", _tok);
}
if (flag2)
{
if (!string.IsNullOrEmpty(ms_otherName.Peek()))
{
_sw.Write(", {0} ", ms_otherName.Peek());
num++;
}
else
{
Error("calling a function that needs an \"other\" and no \"other\" is available", _tok);
}
}
}
foreach (GMLToken child in _tok.Children)
{
if ((flag3 && num < 2) || !flag3)
{
if (num != 0)
{
_sw.Write(", ");
}
CompileExpression(child, _sw);
}
num++;
flag3 = false;
}
_sw.Write(" )");
return result;
}
private static void CompileAssign(GMLToken _tok, TextWriter _sw)
{
if (_tok.Children.Count != 3)
{
Error("malformed assignment statement", _tok);
}
bool _setFunc = false;
CompileVariable(_tok.Children[0], _sw, true, out _setFunc);
if (!_setFunc)
{
switch (_tok.Children[1].Token)
{
case eToken.eAssignPlus:
case eToken.eAssignMinus:
case eToken.eAssignTimes:
case eToken.eAssignDivide:
case eToken.eAssignOr:
case eToken.eAssignAnd:
case eToken.eAssignXor:
_sw.Write(_tok.Children[1].Text);
CompileExpression(_tok.Children[2], _sw);
break;
case eToken.eAssign:
_sw.Write("=");
CompileExpression(_tok.Children[2], _sw);
break;
}
return;
}
switch (_tok.Children[1].Token)
{
case eToken.eAssignPlus:
case eToken.eAssignMinus:
case eToken.eAssignTimes:
case eToken.eAssignDivide:
case eToken.eAssignOr:
case eToken.eAssignAnd:
case eToken.eAssignXor:
CompileVariable(_tok.Children[0], _sw, false, out _setFunc);
_sw.Write(" {0} ", _tok.Children[1].Text[0]);
CompileExpression(_tok.Children[2], _sw);
break;
case eToken.eAssign:
CompileExpression(_tok.Children[2], _sw);
break;
}
_sw.Write(" )");
}
private static void CompileReturn(GMLToken _tok, TextWriter _sw)
{
_sw.Write("return ");
if (_tok.Children.Count > 0)
{
CompileExpression(_tok.Children[0], _sw);
}
}
private static void CompileBreak(GMLToken _tok, TextWriter _sw)
{
if (ms_breakContext.Count > 0)
{
_sw.Write("break");
}
else
{
_sw.Write("return");
}
}
private static void CompileExit(GMLToken _tok, TextWriter _sw)
{
_sw.Write("return");
}
private static void CompileContinue(GMLToken _tok, TextWriter _sw)
{
if (ms_breakContext.Count > 0)
{
_sw.Write("continue");
}
else
{
_sw.Write("return");
}
}
private static void CompileStatement(GMLToken _tok, TextWriter _sw)
{
switch (_tok.Token)
{
case eToken.eVar:
CompileVar(_tok, _sw);
break;
case eToken.eGlobalVar:
CompileGlobalVar(_tok, _sw);
break;
case eToken.eBegin:
case eToken.eBlock:
CompileBlock(_tok, _sw);
break;
case eToken.eRepeat:
CompileRepeat(_tok, _sw);
break;
case eToken.eIf:
CompileIf(_tok, _sw);
break;
case eToken.eWhile:
CompileWhile(_tok, _sw);
break;
case eToken.eDo:
CompileDo(_tok, _sw);
break;
case eToken.eFor:
CompileFor(_tok, _sw);
break;
case eToken.eWith:
CompileWith(_tok, _sw);
break;
case eToken.eSwitch:
CompileSwitch(_tok, _sw);
break;
case eToken.eFunction:
CompileFunction(_tok, _sw);
break;
case eToken.eAssign:
CompileAssign(_tok, _sw);
break;
case eToken.eReturn:
CompileReturn(_tok, _sw);
break;
case eToken.eBreak:
CompileBreak(_tok, _sw);
break;
case eToken.eExit:
CompileExit(_tok, _sw);
break;
case eToken.eContinue:
CompileContinue(_tok, _sw);
break;
}
}
private static void CheckEmitArrayCheck(TextWriter _sw)
{
IEnumerable<KeyValuePair<string, int>> enumerable = ms_arrays.Where((KeyValuePair<string, int> a) => a.Value == ms_statements);
foreach (KeyValuePair<string, int> item in enumerable)
{
_sw.WriteLine("if (!{0}) {0} = [];", item.Key);
}
}
private static void CompileStatement2(GMLToken _tok, TextWriter _sw)
{
CheckEmitArrayCheck(_sw);
CompileStatement(_tok, _sw);
ms_statements++;
}
private static void CompileBlock(GMLToken _tok, TextWriter _sw)
{
_sw.WriteLine("{");
foreach (GMLToken child in _tok.Children)
{
CompileStatement2(child, _sw);
_sw.WriteLine(";");
}
_sw.WriteLine("}");
}
private static void CompileProgram(GMLToken _tok, TextWriter _sw)
{
switch (_tok.Token)
{
case eToken.eEOF:
break;
case eToken.eBlock:
CompileBlock(_tok, _sw);
break;
default:
Error("No program to compile", _tok);
break;
}
}
private static void GatherArgs(GMLToken _tok)
{
eToken token = _tok.Token;
if (token == eToken.eVariable)
{
switch (_tok.Text)
{
case "argument0":
case "argument1":
case "argument2":
case "argument3":
case "argument4":
case "argument5":
case "argument6":
case "argument7":
case "argument8":
case "argument9":
case "argument10":
case "argument11":
case "argument12":
case "argument13":
case "argument14":
case "argument15":
{
string value;
if (!ms_arguments.TryGetValue(_tok.Text, out value))
{
ms_arguments.Add(_tok.Text, _tok.Text);
}
break;
}
}
}
foreach (GMLToken child in _tok.Children)
{
GatherArgs(child);
}
}
public static void Compile(GMAssets _assets, GMLCode _code, TextWriter _sw)
{
ms_assets = _assets;
ms_code = _code;
ms_numErrors = 0;
ms_error = false;
Console.WriteLine("Compiling - {0}", _code.Name);
_sw.WriteLine("\n// #####################################################################################################");
string[] array = _code.Code.Split('\n');
string[] array2 = array;
foreach (string text in array2)
{
string text2 = text.Replace('\r', ' ');
text2 = text2.Replace('\n', ' ');
_sw.WriteLine("// {0}", text2);
}
ms_arguments.Clear();
switch (_code.Type)
{
case eGMLCodeType.eRoomCreate:
_sw.WriteLine("function {0}(_inst)", _code.Name);
ms_thisName.Push("_inst");
ms_otherName.Push("_inst");
break;
case eGMLCodeType.eScript:
{
GatherArgs(_code.Token);
_sw.Write("function {0}( _inst, _other ", _code.Name);
for (int j = 0; j < ms_arguments.Count; j++)
{
string text3 = string.Format("argument{0}", j);
string value = string.Empty;
if (!ms_arguments.TryGetValue(text3, out value))
{
Error(string.Format("argument naming error, {0} arguments but no reference found to {1}", ms_arguments.Count, text3), _code.Token);
}
_sw.Write(", {0}", text3);
}
_sw.Write(")");
ms_thisName.Push("_inst");
ms_otherName.Push("_other");
break;
}
case eGMLCodeType.eRoomInstanceCreate:
_sw.WriteLine("function {0}( _inst )", _code.Name);
ms_thisName.Push("_inst");
ms_otherName.Push("_inst");
break;
case eGMLCodeType.eEvent:
case eGMLCodeType.eTrigger:
_sw.WriteLine("function {0}( _inst, _other )", _code.Name);
ms_thisName.Push("_inst");
ms_otherName.Push("_other");
break;
case eGMLCodeType.eConstant:
_sw.WriteLine("function {0}()", _code.Name);
ms_thisName.Push("");
ms_otherName.Push("");
break;
}
DummyStream stream = new DummyStream();
StreamWriter sw = new StreamWriter(stream);
int num = ms_unique;
ms_locals.Clear();
ms_arrays.Clear();
ms_breakContext.Clear();
ms_statements = 0;
CompileProgram(_code.Token, sw);
if (!ms_error)
{
ms_unique = num;
ms_locals.Clear();
ms_breakContext.Clear();
ms_statements = 0;
CompileProgram(_code.Token, _sw);
}
ms_thisName.Pop();
ms_otherName.Pop();
}
}
}