2023-07-29 00:11:09 +00:00
|
|
|
|
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<ClassNode> Classes {get;set;}=new List<ClassNode>();
|
|
|
|
|
public List<FunctionDeclaritionNode> Functions {get;set;}=new List<FunctionDeclaritionNode>();
|
|
|
|
|
public BytecodeChunk RootChunk = new BytecodeChunk();
|
|
|
|
|
public List<BytecodeChunk> Chunks {get;set;}=new List<BytecodeChunk>();
|
|
|
|
|
|
|
|
|
|
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);
|
2023-07-30 07:55:10 +00:00
|
|
|
|
GenerateCode(cValue.Node,_chunk,0,0,-1,-1,false);
|
|
|
|
|
|
2023-07-29 00:11:09 +00:00
|
|
|
|
WriteBigEndianInt(strm,closure);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-07-30 07:55:10 +00:00
|
|
|
|
byte c = 0b00000000;
|
2023-07-29 00:11:09 +00:00
|
|
|
|
|
|
|
|
|
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);
|
2023-07-30 07:55:10 +00:00
|
|
|
|
GenerateCode(new ReturnNode(classEntry.InitialValue),_chunk,0,0,-1,-1,false);
|
|
|
|
|
|
2023-07-29 00:11:09 +00:00
|
|
|
|
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;
|
2023-07-30 07:55:10 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
2023-07-29 00:11:09 +00:00
|
|
|
|
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);
|
2023-07-30 07:55:10 +00:00
|
|
|
|
GenerateCode(new NotNode(new MethodCallNode(variableNode,"movenext")),chunk,scopeBreakIndex+1,0,labelNum,labelNumEnd,false);
|
2023-07-29 00:11:09 +00:00
|
|
|
|
JumpConditional conditional = new JumpConditional($"_label{labelNumEnd}");
|
|
|
|
|
chunk.Add(conditional);
|
|
|
|
|
|
2023-07-30 07:55:10 +00:00
|
|
|
|
SetVariableNode variableNode2=new SetVariableNode(eachNode.Name,new GetMemberNode(variableNode,"current"));
|
2023-07-29 00:11:09 +00:00
|
|
|
|
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);
|
2023-07-30 07:55:10 +00:00
|
|
|
|
|
2023-07-29 00:11:09 +00:00
|
|
|
|
LabelInstruction labelNode=new LabelInstruction($"_label{labelNum}");
|
|
|
|
|
chunk.Add(labelNode);
|
|
|
|
|
|
|
|
|
|
GenerateCode(new NotNode(forNode.Condition),chunk,scopeIndex+1,0,labelNum,labelNumEnd,false);
|
2023-07-30 07:55:10 +00:00
|
|
|
|
//chunk.Add(new SimpleInstruction(Instruction.POP));
|
2023-07-29 00:11:09 +00:00
|
|
|
|
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);
|
2023-07-30 07:55:10 +00:00
|
|
|
|
|
2023-07-29 00:11:09 +00:00
|
|
|
|
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;
|
2023-07-30 07:55:10 +00:00
|
|
|
|
int i = Chunks.Count;
|
|
|
|
|
|
|
|
|
|
Chunks.Add(_chunk);
|
2023-07-29 00:11:09 +00:00
|
|
|
|
GenerateCode(closureNode.Node,_chunk,0,0,-1,-1,false);
|
2023-07-30 07:55:10 +00:00
|
|
|
|
|
2023-07-29 00:11:09 +00:00
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|