using System; using System.Collections.Generic; using System.IO; using TLang.Parser; using TLang.Common; namespace TLang.BytecodeCompiler { public class ByteCodeGenerator { private int I = 0; public int NextNumber() { return I++; } public ByteCodeGenerator() { Chunks.Add(RootChunk); } public List Classes {get;set;}=new List(); public List Functions {get;set;}=new List(); public BytecodeChunk RootChunk = new BytecodeChunk(); public List Chunks {get;set;}=new List(); public static void GenerateToStream(Node node,Stream strm,TLangVersion vmVersion,TLangVersion version,params TLangDependency[] dependencies) { ByteCodeGenerator gen=new ByteCodeGenerator(); gen._generateFile(node,strm,vmVersion,version,dependencies); } private void _generateFile(Node node,Stream strm,TLangVersion vmVersion,TLangVersion version,TLangDependency[] dependencies) { byte[] data = new byte[]{(byte)'T',(byte)'V',(byte)'M',vmVersion.Major,vmVersion.Minor,vmVersion.Patch,vmVersion.Build,version.Major,version.Minor,version.Patch,version.Build}; strm.Write(data,0,data.Length); WriteBigEndianInt(strm,dependencies.Length); foreach(var item in dependencies) { byte[] bytes = System.Text.Encoding.UTF8.GetBytes(item.Name); WriteBigEndianInt(strm,bytes.Length); strm.Write(bytes,0,bytes.Length); byte[] dependV = new byte[]{item.Version.Major,item.Version.Minor,item.Version.Patch,item.Version.Build}; strm.Write(dependV,0,dependV.Length); } GenerateCode(node,RootChunk,0,0,-1,-1,true); WriteBigEndianInt(strm,Functions.Count); foreach(var item in Functions) { int closure = Chunks.Count; BytecodeChunk _chunk = new BytecodeChunk(); _chunk.Arguments = item.ClosureNode.Arguments; Chunks.Add(_chunk); GenerateCode(item.ClosureNode.Node,_chunk,0,0,-1,-1,false); byte[] bytes = System.Text.Encoding.UTF8.GetBytes(item.FunctionName); WriteBigEndianInt(strm,bytes.Length); strm.Write(bytes,0,bytes.Length); WriteBigEndianInt(strm,closure); } WriteBigEndianInt(strm,Classes.Count); foreach(var item in Classes) { byte[] bytes = System.Text.Encoding.UTF8.GetBytes(item.Name); WriteBigEndianInt(strm,bytes.Length); strm.Write(bytes,0,bytes.Length); bytes = System.Text.Encoding.UTF8.GetBytes(item.InheritsFrom); WriteBigEndianInt(strm,bytes.Length); strm.Write(bytes,0,bytes.Length); WriteBigEndianInt(strm,item.Entries.Count); foreach(var classEntry in item.Entries) { var cValue = classEntry.InitialValue as ClosureNode; if(cValue != null) { byte c = 0b00000100; if(classEntry.Abstract) { c |= 0b00001000;} if(classEntry.Modifier == "prot") {c |= 0b00000001;} if(classEntry.Modifier == "pub") {c |= 0b00000010;} strm.WriteByte(c); bytes = System.Text.Encoding.UTF8.GetBytes(classEntry.Name); WriteBigEndianInt(strm,bytes.Length); strm.Write(bytes,0,bytes.Length); int closure = Chunks.Count; BytecodeChunk _chunk = new BytecodeChunk(); _chunk.Arguments = cValue.Arguments; Chunks.Add(_chunk); GenerateCode(cValue.Node,_chunk,0,0,-1,-1,false); WriteBigEndianInt(strm,closure); } else { byte c = 0b00000000; if(classEntry.Modifier == "prot") {c |= 0b00000001;} if(classEntry.Modifier == "pub") {c |= 0b00000010;} strm.WriteByte(c); bytes = System.Text.Encoding.UTF8.GetBytes(classEntry.Name); WriteBigEndianInt(strm,bytes.Length); strm.Write(bytes,0,bytes.Length); int closure = Chunks.Count; BytecodeChunk _chunk = new BytecodeChunk(); Chunks.Add(_chunk); GenerateCode(new ReturnNode(classEntry.InitialValue),_chunk,0,0,-1,-1,false); WriteBigEndianInt(strm,closure); } } } WriteBigEndianInt(strm,Chunks.Count); foreach(var item in Chunks) { item.SetLabelable(); WriteBigEndianInt(strm,item.Arguments.Count); foreach(var arg in item.Arguments) { byte[] bytes = System.Text.Encoding.UTF8.GetBytes(arg); WriteBigEndianInt(strm,bytes.Length); strm.Write(bytes,0,bytes.Length); } WriteBigEndianInt(strm,item.CurrentByteLength); foreach(var instruction in item.Instructions) { instruction.WriteData(strm); } } } private void WriteBigEndianInt(Stream strm, int count) { byte[] data = BitConverter.GetBytes(count); if(BitConverter.IsLittleEndian) Array.Reverse(data); strm.Write(data,0,data.Length); } public void GenerateCode(Node node,BytecodeChunk chunk,int scopeIndex,int scopeBreakIndex,int _labelBeginningLoop,int _labelEndLoop,bool isRoot=false) { var funcDec = node as FunctionDeclaritionNode; var chrNode = node as CharNode; var strNode = node as StringNode; var dblNode = node as ConstNumberNode; var clsDec = node as ClassNode; var addNode = node as AddNode; var subNode = node as SubtractNode; var timesNode = node as MultiplyNode; var divNode = node as DivideNode; var modNode = node as ModuloNode; var powNode = node as PowNode; var lshiftNode = node as LeftShiftNode; var rshiftNode = node as RightShiftNode; var bOrNode = node as BOrNode; var bAndNode = node as BAndNode; var xOrNode = node as XOrNode; var negNode = node as NegativeNode; var bNotNode = node as BitwiseNotNode; var nEqNode = node as NotEqualsNode; var eqNode = node as EqualsNode; var lOrNode = node as LOrNode; var lAndNode = node as LAndNode; var ltNode = node as LessThanNode; var lteNode = node as LessThanEqualsNode; var gtNode = node as GreaterThanNode; var gteNode = node as GreaterThanEqualsNode; var notNode = node as NotNode; var scNode = node as ScopeNode; var retNode = node as ReturnNode; var closureNode = node as ClosureNode; var whileNode = node as WhileLoop; var eachNode = node as EachLoopNode; var forNode = node as ForLoopNode; var ifNode = node as IfNode; var functionCallNode = node as FunctionCallNode; var methodCallNode = node as MethodCallNode; var getVariableNode = node as GetVariableNode; var getMemberNode = node as GetMemberNode; var getArrayValue = node as GetArrayNode; var setVariableNode = node as SetVariableNode; var postFixIncrement = node as PostFixIncrementNode; var postFixDecrement = node as PostFixDecrementNode; if(postFixDecrement != null) { GenerateCode(postFixDecrement.SymbolNode,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); SetVariableNode variableNode = new SetVariableNode(postFixDecrement.SymbolNode,new SubtractNode(postFixDecrement.SymbolNode,new ConstNumberNode(1))); GenerateCode(variableNode,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); } if(postFixIncrement != null) { GenerateCode(postFixIncrement.SymbolNode,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); SetVariableNode variableNode = new SetVariableNode(postFixIncrement.SymbolNode,new AddNode(postFixIncrement.SymbolNode,new ConstNumberNode(1))); GenerateCode(variableNode,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); } if(scNode != null) { if(scNode.IsSwitchScope) { int caseNumber = NextNumber(); int labelNumEnd = NextNumber(); int caseNo2=0; chunk.Add(new SimpleInstruction(Instruction.SCOPE_BEGIN)); bool hasDefault =false; bool beforeCase=true; foreach(var item in scNode.Nodes) { var c = item as CaseNode; var d = item as DefaultNode; if(c != null) { beforeCase = false; EqualsNode equals=new EqualsNode(scNode.SwitchCondition,c.Variable); GenerateCode(equals,chunk,scopeIndex+1,0,_labelBeginningLoop,labelNumEnd,false); JumpConditional unconditional = new JumpConditional($"_case{caseNumber}_{caseNo2}"); chunk.Add(unconditional); caseNo2++; } if(d != null) { hasDefault =false; beforeCase = false; JumpUnconditional unconditional = new JumpUnconditional($"_default{caseNumber}"); chunk.Add(unconditional); } if(beforeCase) { GenerateCode(item,chunk,scopeIndex+1,0,_labelBeginningLoop,_labelEndLoop,isRoot); } } if(!hasDefault) { JumpUnconditional unconditional = new JumpUnconditional($"_label{labelNumEnd}"); chunk.Add(unconditional); } beforeCase=true; caseNo2=0; foreach(var item in scNode.Nodes) { var c = item as CaseNode; var d = item as DefaultNode; if(c != null) { beforeCase = false; LabelInstruction instruction = new LabelInstruction($"_case{caseNumber}_{caseNo2}"); chunk.Add(instruction); caseNo2++; } if(d != null) { beforeCase = false; LabelInstruction instruction = new LabelInstruction($"_default{caseNumber}"); chunk.Add(instruction); } if(!beforeCase && c == null && d == null) { GenerateCode(item,chunk,scopeIndex+1,scopeBreakIndex,_labelBeginningLoop,labelNumEnd,scNode.RootScope); } } LabelInstruction endLabel = new LabelInstruction($"_label{labelNumEnd}"); chunk.Add(endLabel); chunk.Add(new SimpleInstruction(Instruction.SCOPE_END)); } else { if(!scNode.RootScope) chunk.Add(new SimpleInstruction(Instruction.SCOPE_BEGIN)); foreach(var item in scNode.Nodes) { GenerateCode(item,chunk,scopeIndex+1,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,scNode.RootScope); } if(!scNode.RootScope) chunk.Add(new SimpleInstruction(Instruction.SCOPE_END)); } } if(ifNode != null) { int labelNumNo = NextNumber(); int labelNumEnd = NextNumber(); GenerateCode(new NotNode(ifNode.Condition),chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); JumpConditional jc=new JumpConditional($"_label{labelNumNo}"); chunk.Add(jc); GenerateCode(ifNode.Yes,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); JumpUnconditional ju = new JumpUnconditional($"_label{labelNumEnd}"); chunk.Add(ju); LabelInstruction labelNo = new LabelInstruction($"_label{labelNumNo}"); chunk.Add(labelNo); GenerateCode(ifNode.No,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); LabelInstruction labelEnd = new LabelInstruction($"_label{labelNumEnd}"); chunk.Add(labelEnd); } if(bNotNode != null) { GenerateCode(bNotNode.Node,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.BNOT)); } if(negNode != null) { GenerateCode(negNode.Node,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.NEG)); } if(notNode != null) { GenerateCode(notNode.Node,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.LNOT)); } if(eachNode != null) { int ittrVarNum = NextNumber(); int labelNum = NextNumber(); int labelNumEnd = NextNumber(); chunk.Add(new SimpleInstruction(Instruction.SCOPE_BEGIN)); GetVariableNode variableNode=new GetVariableNode($"__compGen{ittrVarNum}"); var member= new GetMemberNode(eachNode.Itterator,"ittr"); SetVariableNode variableNode1=new SetVariableNode(variableNode,member); GenerateCode(variableNode1,chunk,scopeIndex+1,0,_labelBeginningLoop,_labelEndLoop,false); LabelInstruction labelNode=new LabelInstruction($"_label{labelNum}"); chunk.Add(labelNode); GenerateCode(new NotNode(new MethodCallNode(variableNode,"movenext")),chunk,scopeBreakIndex+1,0,labelNum,labelNumEnd,false); JumpConditional conditional = new JumpConditional($"_label{labelNumEnd}"); chunk.Add(conditional); SetVariableNode variableNode2=new SetVariableNode(eachNode.Name,new GetMemberNode(variableNode,"current")); GenerateCode(variableNode2,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false); GenerateCode(eachNode.Body,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false); JumpUnconditional juC=new JumpUnconditional($"_label{labelNum}"); chunk.Add(juC); LabelInstruction endLabel = new LabelInstruction($"_label{labelNumEnd}"); chunk.Add(endLabel); chunk.Add(new SimpleInstruction(Instruction.SCOPE_END)); } if(forNode != null) { int labelNum = NextNumber(); int labelNumEnd = NextNumber(); chunk.Add(new SimpleInstruction(Instruction.SCOPE_BEGIN)); GenerateCode(forNode.Init,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false); LabelInstruction labelNode=new LabelInstruction($"_label{labelNum}"); chunk.Add(labelNode); GenerateCode(new NotNode(forNode.Condition),chunk,scopeIndex+1,0,labelNum,labelNumEnd,false); //chunk.Add(new SimpleInstruction(Instruction.POP)); JumpConditional conditional = new JumpConditional($"_label{labelNumEnd}"); chunk.Add(conditional); GenerateCode(forNode.Body,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false); GenerateCode(forNode.Increment,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false); JumpUnconditional juC=new JumpUnconditional($"_label{labelNum}"); chunk.Add(juC); LabelInstruction endLabel = new LabelInstruction($"_label{labelNumEnd}"); chunk.Add(endLabel); chunk.Add(new SimpleInstruction(Instruction.SCOPE_END)); } if(whileNode != null) { int labelNum = NextNumber(); int labelNumEnd = NextNumber(); chunk.Add(new SimpleInstruction(Instruction.SCOPE_BEGIN)); LabelInstruction labelNode=new LabelInstruction($"_label{labelNum}"); chunk.Add(labelNode); if(whileNode.IsDo) { GenerateCode(whileNode.Body,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false); GenerateCode(new NotNode(whileNode.Condition),chunk,scopeIndex+1,0,labelNum,labelNumEnd,false); JumpConditional conditional = new JumpConditional($"_label{labelNum}"); chunk.Add(conditional); } else { GenerateCode(new NotNode(whileNode.Condition),chunk,scopeIndex+1,0,labelNum,labelNumEnd,false); JumpConditional conditional = new JumpConditional($"_label{labelNumEnd}"); chunk.Add(conditional); GenerateCode(whileNode.Body,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false); JumpUnconditional juC=new JumpUnconditional($"_label{labelNum}"); chunk.Add(juC); } LabelInstruction endLabel = new LabelInstruction($"_label{labelNumEnd}"); chunk.Add(endLabel); chunk.Add(new SimpleInstruction(Instruction.SCOPE_END)); } if(node is ContinueNode && _labelBeginningLoop >= 0) { for(int i = scopeBreakIndex;i>0;i--) { chunk.Add(new SimpleInstruction(Instruction.SCOPE_END)); } JumpUnconditional conditional=new JumpUnconditional($"_label{_labelBeginningLoop}"); chunk.Add(conditional); } if(node is BreakNode && _labelEndLoop >= 0) { for(int i = scopeBreakIndex;i>0;i--) { chunk.Add(new SimpleInstruction(Instruction.SCOPE_END)); } JumpUnconditional conditional=new JumpUnconditional($"_label{_labelEndLoop}"); chunk.Add(conditional); } if(closureNode != null) { BytecodeChunk _chunk = new BytecodeChunk(); _chunk.Arguments = closureNode.Arguments; int i = Chunks.Count; Chunks.Add(_chunk); GenerateCode(closureNode.Node,_chunk,0,0,-1,-1,false); chunk.Add(new PushClosureNode(i)); } if(node is NullNode) { chunk.Add(new SimpleInstruction(Instruction.PUSH_NULL)); } if(node is UndefinedNode) { chunk.Add(new SimpleInstruction(Instruction.PUSH_UNDEFINED)); } if(node is TrueNode) { chunk.Add(new SimpleInstruction(Instruction.PUSH_TRUE)); } if(node is FalseNode) { chunk.Add(new SimpleInstruction(Instruction.PUSH_FALSE)); } if(chrNode != null) { chunk.Add(new PushCharNode(chrNode.Text)); } if(strNode != null) { chunk.Add(new PushStringInstruction(strNode.Text)); } if(dblNode != null) { chunk.Add(new PushDoubleInstruction(dblNode.Value)); } if(funcDec != null) { if(isRoot) { Functions.Add(funcDec); } else { SetVariableNode variableNode=new SetVariableNode(new GetVariableNode(funcDec.FunctionName),funcDec.ClosureNode) {LineInfo = funcDec.LineInfo}; GenerateCode(variableNode,chunk,scopeIndex,scopeBreakIndex,-1,-1,false); } } if(clsDec != null) { Classes.Add(clsDec); } if(addNode != null) { GenerateCode(addNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(addNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.ADD)); } if(subNode != null) { GenerateCode(subNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(subNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.SUB)); } if(timesNode != null) { GenerateCode(timesNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(timesNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.TIMES)); } if(divNode != null) { GenerateCode(divNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(divNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.DIVIDE)); } if(modNode != null) { GenerateCode(modNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(modNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.MOD)); } if(powNode != null) { GenerateCode(powNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(powNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.POW)); } if(lshiftNode != null) { GenerateCode(lshiftNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(lshiftNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.LSHIFT)); } if(rshiftNode != null) { GenerateCode(rshiftNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(rshiftNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.RSHIFT)); } if(bOrNode != null) { GenerateCode(bOrNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(bOrNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.BOR)); } if(bAndNode != null) { GenerateCode(bAndNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(bAndNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.BAND)); } if(xOrNode != null) { GenerateCode(xOrNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(xOrNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.XOR)); } if(nEqNode != null) { GenerateCode(nEqNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(nEqNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.NEQ)); } if(eqNode != null) { GenerateCode(eqNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(eqNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.EQ)); } if(lOrNode != null) { GenerateCode(lOrNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(lOrNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.LOR)); } if(lAndNode != null) { GenerateCode(lAndNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(lAndNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.LAND)); } if(ltNode != null) { GenerateCode(ltNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(ltNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.LT)); } if(lteNode != null) { GenerateCode(lteNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(lteNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.LTE)); } if(gtNode != null) { GenerateCode(gtNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(gtNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.GT)); } if(gteNode != null) { GenerateCode(gteNode.Left,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(gteNode.Right,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.GTE)); } if(retNode != null) { GenerateCode(retNode.Expression,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); for(int i = scopeIndex;i>0;i--) { chunk.Add(new SimpleInstruction(Instruction.SCOPE_END)); } chunk.Add(new SimpleInstruction(Instruction.RET)); } if(methodCallNode != null) { GenerateCode(methodCallNode.Symbol,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new PushStringInstruction(methodCallNode.Name)); foreach(var arg in methodCallNode.Arguments) { GenerateCode(arg,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); } chunk.Add(new PushDoubleInstruction(methodCallNode.Arguments.Count)); chunk.Add(new SimpleInstruction(Instruction.CALL_METHOD)); } if(functionCallNode != null) { chunk.Add(new PushStringInstruction(functionCallNode.Name)); foreach(var arg in functionCallNode.Arguments) { GenerateCode(arg,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); } chunk.Add(new PushDoubleInstruction(functionCallNode.Arguments.Count)); chunk.Add(new SimpleInstruction(Instruction.CALL_FUNC)); } if(getVariableNode != null) { chunk.Add(new PushStringInstruction(getVariableNode.Name)); chunk.Add(new SimpleInstruction(Instruction.PUSH_VARIABLE_VALUE)); } if(getMemberNode != null) { GenerateCode(getMemberNode.Symbol,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new PushStringInstruction(getMemberNode.Name)); chunk.Add(new SimpleInstruction(Instruction.PUSH_FIELD_VALUE)); } if(getArrayValue != null) { GenerateCode(getArrayValue.Symbol,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(getArrayValue.Expression,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.PUSH_ARRAY_VALUE)); } if(setVariableNode != null) { var gVN = setVariableNode.SetTo as GetVariableNode; var gMN = setVariableNode.SetTo as GetMemberNode; var gAN = setVariableNode.SetTo as GetArrayNode; if(gVN != null) { chunk.Add(new PushStringInstruction(gVN.Name)); GenerateCode(setVariableNode.Expression,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.POP_VARIABLE_VALUE)); } if(gMN != null) { GenerateCode(gMN.Symbol,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new PushStringInstruction(gMN.Name)); GenerateCode(setVariableNode.Expression,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.POP_FIELD_VALUE)); } if(gAN != null) { GenerateCode(gAN.Symbol,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(gAN.Expression,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); GenerateCode(setVariableNode.Expression,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); chunk.Add(new SimpleInstruction(Instruction.POP_ARRAY_VALUE)); } } } } }