Compare commits

...

5 commits
master ... dev

Author SHA1 Message Date
arookas
74fc59f232 Clean up sunSpcBinary 2017-04-15 20:52:05 -04:00
arookas
c556939972 Added conditional attribute to instruction tracing.
This uses a lot less directive spam at the cost of the function still
being compiled into the IL in release.
2016-03-08 16:20:13 -05:00
arookas
23aee05fb4 Removed old scope code.
It was flawed to begin with, so it'd need to be redesigned from the
ground up to be put back in.
2016-03-08 02:25:33 -05:00
arookas
fbb0430325 Fixed: check against local function variables. 2016-03-08 02:21:09 -05:00
arookas
2f6058d49f Added error message for constant declarations. 2016-03-08 02:16:13 -05:00
9 changed files with 160 additions and 329 deletions

View file

@ -66,25 +66,6 @@ namespace arookas {
public int LocalCount { public int LocalCount {
get { get {
#if SSC_SCOPES
var locals = 0;
var maxChildLocals = 0;
foreach (var child in this) {
if (child is sunVariableDeclaration || child is sunVariableDefinition) {
++locals;
}
else if (child is sunCompoundStatement) {
locals += child.LocalCount; // HACK: compound statements aren't their own scope
}
else if (!(child is sunFunctionDefinition)) { // don't recurse into function bodies
var childLocals = child.LocalCount;
if (childLocals > maxChildLocals) {
maxChildLocals = childLocals;
}
}
}
return locals + maxChildLocals;
#else
var locals = 0; var locals = 0;
foreach (var child in this) { foreach (var child in this) {
if (child is sunVariableDeclaration || child is sunVariableDefinition) { if (child is sunVariableDeclaration || child is sunVariableDefinition) {
@ -95,7 +76,6 @@ namespace arookas {
} }
} }
return locals; return locals;
#endif
} }
} }

View file

@ -99,9 +99,6 @@ namespace arookas {
: base(location) { } : base(location) { }
public override void Compile(sunCompiler compiler) { public override void Compile(sunCompiler compiler) {
#if SSC_SCOPES
compiler.Context.Scopes.Push();
#endif
var loop = PushLoop(compiler.Context); var loop = PushLoop(compiler.Context);
TryCompile(Declaration, compiler); TryCompile(Declaration, compiler);
var bodyPrologue = compiler.Binary.Offset; var bodyPrologue = compiler.Binary.Offset;
@ -114,9 +111,6 @@ namespace arookas {
bodyEpilogue.Relocate(); bodyEpilogue.Relocate();
loop.BreakPoint = compiler.Binary.Offset; loop.BreakPoint = compiler.Binary.Offset;
compiler.Context.Loops.Pop(compiler); compiler.Context.Loops.Pop(compiler);
#if SSC_SCOPES
compiler.Context.Scopes.Pop();
#endif
} }
} }
class sunForDeclaration : sunNode { class sunForDeclaration : sunNode {

View file

@ -7,16 +7,6 @@
class sunStatementBlock : sunNode { class sunStatementBlock : sunNode {
public sunStatementBlock(sunSourceLocation location) public sunStatementBlock(sunSourceLocation location)
: base(location) { } : base(location) { }
public override void Compile(sunCompiler compiler) {
#if SSC_SCOPES
compiler.Context.Scopes.Push(compiler.Context.Scopes.Top.Type);
#endif
base.Compile(compiler);
#if SSC_SCOPES
compiler.Context.Scopes.Pop();
#endif
}
} }
class sunImport : sunNode { class sunImport : sunNode {

View file

@ -35,7 +35,7 @@
var symbol = compiler.Context.DeclareVariable(this); var symbol = compiler.Context.DeclareVariable(this);
symbol.Modifiers = Modifiers; symbol.Modifiers = Modifiers;
if ((Modifiers & sunSymbolModifiers.Constant) != 0) { if ((Modifiers & sunSymbolModifiers.Constant) != 0) {
throw new sunInvalidModifierException(this[0]); throw new sunConstantDeclarationException(this);
} }
} }
} }

View file

@ -87,380 +87,319 @@ namespace arookas {
sealed class sunSpcBinary : sunBinary { sealed class sunSpcBinary : sunBinary {
aBinaryWriter mWriter; aBinaryWriter mWriter;
sunSpcBinarySection mText, mData, mDataString, mSymbol, mSymbolString; sunSpcStringTable mStringTable;
uint mTextOffset, mDataOffset, mSymbolOffset;
int mDataCount, mSymbolCount, mVarCount; int mDataCount, mSymbolCount, mVarCount;
public override uint Offset { public override uint Offset {
get { return mText.Offset; } get { return (uint)mWriter.Position; }
} }
public sunSpcBinary(Stream output) { public sunSpcBinary(Stream output) {
mWriter = new aBinaryWriter(output, Endianness.Big, Encoding.GetEncoding(932)); mWriter = new aBinaryWriter(output, Endianness.Big, Encoding.GetEncoding(932));
mText = new sunSpcBinarySection(); mStringTable = new sunSpcStringTable(Encoding.GetEncoding(932));
mData = new sunSpcBinarySection();
mDataString = new sunSpcBinarySection();
mSymbol = new sunSpcBinarySection();
mSymbolString = new sunSpcBinarySection();
mWriter.PushAnchor();
} }
public override void Open() {
mWriter.PushAnchor();
WriteHeader();
}
public override void Close() { public override void Close() {
// header WriteHeader();
mWriter.WriteString("SPCB"); mWriter.PopAnchor();
mWriter.Write32(0x1C); }
mWriter.Write32(0x1C + mText.Size);
void WriteHeader() {
mWriter.Goto(0);
mWriter.Write8(0x53); // 'S'
mWriter.Write8(0x50); // 'P'
mWriter.Write8(0x43); // 'C'
mWriter.Write8(0x42); // 'B'
mWriter.Write32(mTextOffset);
mWriter.Write32(mDataOffset);
mWriter.WriteS32(mDataCount); mWriter.WriteS32(mDataCount);
mWriter.Write32(0x1C + mText.Size + mData.Size + mDataString.Size); mWriter.Write32(mSymbolOffset);
mWriter.WriteS32(mSymbolCount); mWriter.WriteS32(mSymbolCount);
mWriter.WriteS32(mVarCount); mWriter.WriteS32(mVarCount);
// sections
mText.Copy(mWriter);
mData.Copy(mWriter);
mDataString.Copy(mWriter);
mSymbol.Copy(mWriter);
mSymbolString.Copy(mWriter);
} }
// text // text
public override void Keep() { public override void Keep() {
mText.Writer.Keep(); mWriter.Keep();
} }
public override void Back() { public override void Back() {
mText.Writer.Back(); mWriter.Back();
} }
public override void Goto(uint offset) { public override void Goto(uint offset) {
mText.Writer.Goto(offset); mWriter.Goto(offset);
} }
public override void BeginText() {
mTextOffset = Offset;
mWriter.PushAnchor();
}
public override void WriteINT(int value) { public override void WriteINT(int value) {
switch (value) { // shortcut commands switch (value) { // shortcut commands
case 0: WriteINT0(); return; case 0: WriteINT0(); return;
case 1: WriteINT1(); return; case 1: WriteINT1(); return;
} }
#if DEBUG
TraceInstruction("int {0} # ${0:X}", value); TraceInstruction("int {0} # ${0:X}", value);
#endif mWriter.Write8(0x00);
mText.Writer.Write8(0x00); mWriter.WriteS32(value);
mText.Writer.WriteS32(value);
} }
public override void WriteFLT(float value) { public override void WriteFLT(float value) {
#if DEBUG
TraceInstruction("flt {0}", value); TraceInstruction("flt {0}", value);
#endif mWriter.Write8(0x01);
mText.Writer.Write8(0x01); mWriter.WriteF32(value);
mText.Writer.WriteF32(value);
} }
public override void WriteSTR(int index) { public override void WriteSTR(int index) {
#if DEBUG
TraceInstruction("str {0}", index); TraceInstruction("str {0}", index);
#endif mWriter.Write8(0x02);
mText.Writer.Write8(0x02); mWriter.WriteS32(index);
mText.Writer.WriteS32(index);
} }
public override void WriteADR(uint value) { public override void WriteADR(uint value) {
#if DEBUG
TraceInstruction("adr ${0:X8}", value); TraceInstruction("adr ${0:X8}", value);
#endif mWriter.Write8(0x03);
mText.Writer.Write8(0x03); mWriter.Write32(value);
mText.Writer.Write32(value);
} }
public override void WriteVAR(int display, int index) { public override void WriteVAR(int display, int index) {
#if DEBUG
TraceInstruction("var {0} {1}", display, index); TraceInstruction("var {0} {1}", display, index);
#endif mWriter.Write8(0x04);
mText.Writer.Write8(0x04); mWriter.WriteS32(display);
mText.Writer.WriteS32(display); mWriter.WriteS32(index);
mText.Writer.WriteS32(index);
} }
public override void WriteNOP() { public override void WriteNOP() {
#if DEBUG
TraceInstruction("nop"); TraceInstruction("nop");
#endif mWriter.Write8(0x05);
mText.Writer.Write8(0x05);
} }
public override void WriteINC(int display, int index) { public override void WriteINC(int display, int index) {
#if DEBUG
TraceInstruction("inc {0} {1}", display, index); TraceInstruction("inc {0} {1}", display, index);
#endif mWriter.Write8(0x06);
mText.Writer.Write8(0x06); mWriter.WriteS32(display);
mText.Writer.WriteS32(display); mWriter.WriteS32(index);
mText.Writer.WriteS32(index);
} }
public override void WriteDEC(int display, int index) { public override void WriteDEC(int display, int index) {
#if DEBUG
TraceInstruction("dec {0} {1}", display, index); TraceInstruction("dec {0} {1}", display, index);
#endif mWriter.Write8(0x07);
mText.Writer.Write8(0x07); mWriter.WriteS32(display);
mText.Writer.WriteS32(display); mWriter.WriteS32(index);
mText.Writer.WriteS32(index);
} }
public override void WriteADD() { public override void WriteADD() {
#if DEBUG
TraceInstruction("add"); TraceInstruction("add");
#endif mWriter.Write8(0x08);
mText.Writer.Write8(0x08);
} }
public override void WriteSUB() { public override void WriteSUB() {
#if DEBUG
TraceInstruction("sub"); TraceInstruction("sub");
#endif mWriter.Write8(0x09);
mText.Writer.Write8(0x09);
} }
public override void WriteMUL() { public override void WriteMUL() {
#if DEBUG
TraceInstruction("mul"); TraceInstruction("mul");
#endif mWriter.Write8(0x0A);
mText.Writer.Write8(0x0A);
} }
public override void WriteDIV() { public override void WriteDIV() {
#if DEBUG
TraceInstruction("div"); TraceInstruction("div");
#endif mWriter.Write8(0x0B);
mText.Writer.Write8(0x0B);
} }
public override void WriteMOD() { public override void WriteMOD() {
#if DEBUG
TraceInstruction("mod"); TraceInstruction("mod");
#endif mWriter.Write8(0x0C);
mText.Writer.Write8(0x0C);
} }
public override void WriteASS(int display, int index) { public override void WriteASS(int display, int index) {
#if DEBUG
TraceInstruction("ass {0} {1}", display, index); TraceInstruction("ass {0} {1}", display, index);
#endif mWriter.Write8(0x0D);
mText.Writer.Write8(0x0D); mWriter.Write8(0x04); // unused (skipped over by TSpcInterp)
mText.Writer.Write8(0x04); // unused (skipped over by TSpcInterp) mWriter.WriteS32(display);
mText.Writer.WriteS32(display); mWriter.WriteS32(index);
mText.Writer.WriteS32(index);
} }
public override void WriteEQ() { public override void WriteEQ() {
#if DEBUG
TraceInstruction("eq"); TraceInstruction("eq");
#endif mWriter.Write8(0x0E);
mText.Writer.Write8(0x0E);
} }
public override void WriteNE() { public override void WriteNE() {
#if DEBUG
TraceInstruction("ne"); TraceInstruction("ne");
#endif mWriter.Write8(0x0F);
mText.Writer.Write8(0x0F);
} }
public override void WriteGT() { public override void WriteGT() {
#if DEBUG
TraceInstruction("gt"); TraceInstruction("gt");
#endif mWriter.Write8(0x10);
mText.Writer.Write8(0x10);
} }
public override void WriteLT() { public override void WriteLT() {
#if DEBUG
TraceInstruction("lt"); TraceInstruction("lt");
#endif mWriter.Write8(0x11);
mText.Writer.Write8(0x11);
} }
public override void WriteGE() { public override void WriteGE() {
#if DEBUG
TraceInstruction("ge"); TraceInstruction("ge");
#endif mWriter.Write8(0x12);
mText.Writer.Write8(0x12);
} }
public override void WriteLE() { public override void WriteLE() {
#if DEBUG
TraceInstruction("le"); TraceInstruction("le");
#endif mWriter.Write8(0x13);
mText.Writer.Write8(0x13);
} }
public override void WriteNEG() { public override void WriteNEG() {
#if DEBUG
TraceInstruction("neg"); TraceInstruction("neg");
#endif mWriter.Write8(0x14);
mText.Writer.Write8(0x14);
} }
public override void WriteNOT() { public override void WriteNOT() {
#if DEBUG
TraceInstruction("not"); TraceInstruction("not");
#endif mWriter.Write8(0x15);
mText.Writer.Write8(0x15);
} }
public override void WriteAND() { public override void WriteAND() {
#if DEBUG
TraceInstruction("and"); TraceInstruction("and");
#endif mWriter.Write8(0x16);
mText.Writer.Write8(0x16);
} }
public override void WriteOR() { public override void WriteOR() {
#if DEBUG
TraceInstruction("or"); TraceInstruction("or");
#endif mWriter.Write8(0x17);
mText.Writer.Write8(0x17);
} }
public override void WriteBAND() { public override void WriteBAND() {
#if DEBUG
TraceInstruction("band"); TraceInstruction("band");
#endif mWriter.Write8(0x18);
mText.Writer.Write8(0x18);
} }
public override void WriteBOR() { public override void WriteBOR() {
#if DEBUG
TraceInstruction("bor"); TraceInstruction("bor");
#endif mWriter.Write8(0x19);
mText.Writer.Write8(0x19);
} }
public override void WriteSHL() { public override void WriteSHL() {
#if DEBUG
TraceInstruction("shl"); TraceInstruction("shl");
#endif mWriter.Write8(0x1A);
mText.Writer.Write8(0x1A);
} }
public override void WriteSHR() { public override void WriteSHR() {
#if DEBUG
TraceInstruction("shr"); TraceInstruction("shr");
#endif mWriter.Write8(0x1B);
mText.Writer.Write8(0x1B);
} }
public override void WriteCALL(uint offset, int count) { public override void WriteCALL(uint offset, int count) {
#if DEBUG
TraceInstruction("call ${0:X8} {1}", offset, count); TraceInstruction("call ${0:X8} {1}", offset, count);
#endif mWriter.Write8(0x1C);
mText.Writer.Write8(0x1C); mWriter.Write32(offset);
mText.Writer.Write32(offset); mWriter.WriteS32(count);
mText.Writer.WriteS32(count);
} }
public override void WriteFUNC(int index, int count) { public override void WriteFUNC(int index, int count) {
#if DEBUG
TraceInstruction("func {0} {1}", index, count); TraceInstruction("func {0} {1}", index, count);
#endif mWriter.Write8(0x1D);
mText.Writer.Write8(0x1D); mWriter.WriteS32(index);
mText.Writer.WriteS32(index); mWriter.WriteS32(count);
mText.Writer.WriteS32(count);
} }
public override void WriteMKFR(int count) { public override void WriteMKFR(int count) {
#if DEBUG
TraceInstruction("mkfr {0}", count); TraceInstruction("mkfr {0}", count);
#endif mWriter.Write8(0x1E);
mText.Writer.Write8(0x1E); mWriter.WriteS32(count);
mText.Writer.WriteS32(count);
} }
public override void WriteMKDS(int display) { public override void WriteMKDS(int display) {
#if DEBUG
TraceInstruction("mkds {0}", display); TraceInstruction("mkds {0}", display);
#endif mWriter.Write8(0x1F);
mText.Writer.Write8(0x1F); mWriter.WriteS32(display);
mText.Writer.WriteS32(display);
} }
public override void WriteRET() { public override void WriteRET() {
#if DEBUG
TraceInstruction("ret"); TraceInstruction("ret");
#endif mWriter.Write8(0x20);
mText.Writer.Write8(0x20);
} }
public override void WriteRET0() { public override void WriteRET0() {
#if DEBUG
TraceInstruction("ret0"); TraceInstruction("ret0");
#endif mWriter.Write8(0x21);
mText.Writer.Write8(0x21);
} }
public override void WriteJNE(uint offset) { public override void WriteJNE(uint offset) {
#if DEBUG
TraceInstruction("jne ${0:X8}", offset); TraceInstruction("jne ${0:X8}", offset);
#endif mWriter.Write8(0x22);
mText.Writer.Write8(0x22); mWriter.Write32(offset);
mText.Writer.Write32(offset);
} }
public override void WriteJMP(uint offset) { public override void WriteJMP(uint offset) {
#if DEBUG
TraceInstruction("jmp ${0:X8}", offset); TraceInstruction("jmp ${0:X8}", offset);
#endif mWriter.Write8(0x23);
mText.Writer.Write8(0x23); mWriter.Write32(offset);
mText.Writer.Write32(offset);
} }
public override void WritePOP() { public override void WritePOP() {
#if DEBUG
TraceInstruction("pop"); TraceInstruction("pop");
#endif mWriter.Write8(0x24);
mText.Writer.Write8(0x24);
} }
public override void WriteINT0() { public override void WriteINT0() {
#if DEBUG
TraceInstruction("int0"); TraceInstruction("int0");
#endif mWriter.Write8(0x25);
mText.Writer.Write8(0x25);
} }
public override void WriteINT1() { public override void WriteINT1() {
#if DEBUG
TraceInstruction("int1"); TraceInstruction("int1");
#endif mWriter.Write8(0x26);
mText.Writer.Write8(0x26);
} }
public override void WriteEND() { public override void WriteEND() {
#if DEBUG
TraceInstruction("end"); TraceInstruction("end");
#endif mWriter.Write8(0x27);
mText.Writer.Write8(0x27); }
public override void EndText() {
mWriter.PopAnchor();
} }
#if DEBUG [Conditional("DEBUG")]
void TraceInstruction(string format, params object[] args) { void TraceInstruction(string format, params object[] args) {
var instruction = String.Format(format, args); var instruction = String.Format(format, args);
Debug.WriteLine("{0:X8} {1}", mText.Size, instruction); Debug.WriteLine("{0:X8} {1}", mWriter.Position, instruction);
} }
#endif
// data // data
public override void BeginData() {
mDataCount = 0;
mDataOffset = Offset;
mWriter.PushAnchor();
mStringTable.Clear();
}
public override void WriteData(string data) { public override void WriteData(string data) {
if (data == null) { if (data == null) {
throw new ArgumentNullException("data"); throw new ArgumentNullException("data");
} }
mData.Writer.Write32(mDataString.Size); mWriter.Write32(mStringTable.Add(data));
mDataString.Writer.WriteString<aZSTR>(data);
++mDataCount; ++mDataCount;
} }
public override void EndData() {
mWriter.WriteString(mStringTable.ToString());
mWriter.PopAnchor();
mStringTable.Clear();
}
// symbol // symbol
public override void BeginSymbol() {
mSymbolCount = 0;
mSymbolOffset = Offset;
mWriter.PushAnchor();
mStringTable.Clear();
}
public override void WriteSymbol(sunSymbolType type, string name, uint data) { public override void WriteSymbol(sunSymbolType type, string name, uint data) {
mSymbol.Writer.WriteS32((int)type); mWriter.WriteS32((int)type);
mSymbol.Writer.Write32(mSymbolString.Size); mWriter.Write32(mStringTable.Add(name));
mSymbol.Writer.Write32(data); mWriter.Write32(data);
mSymbol.Writer.Write32(0u); // runtime field (hash) mWriter.Write32(0u); // runtime field (hash)
mSymbol.Writer.Write32(0u); // runtime field (funcptr) mWriter.Write32(0u); // runtime field (funcptr)
mSymbolString.Writer.WriteString<aZSTR>(name);
++mSymbolCount; ++mSymbolCount;
if (type == sunSymbolType.Variable) { if (type == sunSymbolType.Variable) {
++mVarCount; ++mVarCount;
} }
} }
public override void EndSymbol() {
mWriter.WriteString(mStringTable.ToString());
mWriter.PopAnchor();
mStringTable.Clear();
}
class sunSpcBinarySection : IDisposable { class sunSpcStringTable {
readonly aBinaryWriter mWriter; StringBuilder mBuilder;
readonly MemoryStream mStream; Encoding mEncoding;
uint mSize;
public aBinaryWriter Writer { public sunSpcStringTable(Encoding encoding) {
get { return mWriter; } mBuilder = new StringBuilder(1024);
} mEncoding = encoding;
public MemoryStream Stream {
get { return mStream; }
} }
public uint Offset { public uint Add(string value) {
get { return (uint)mWriter.Position; } var size = mSize;
mBuilder.Append(value);
mBuilder.Append('\0');
mSize += (uint)mEncoding.GetByteCount(value) + 1u; // + null terminator
return size;
} }
public uint Size { public override string ToString() {
get { return (uint)mWriter.Length; } return mBuilder.ToString();
} }
public void Clear() {
public sunSpcBinarySection() { mBuilder.Clear();
mStream = new MemoryStream(1024); mSize = 0;
mWriter = new aBinaryWriter(mStream, Endianness.Big, Encoding.GetEncoding(932));
}
public void Dispose() {
mStream.Dispose();
}
public void Copy(aBinaryWriter writer) {
if (writer == null) {
throw new ArgumentNullException("writer");
}
writer.Write8s(mStream.GetBuffer(), (int)Size);
} }
} }
} }

View file

@ -97,16 +97,15 @@ namespace arookas {
} }
sunVariableSymbol DeclareVariable(sunIdentifier node, sunSymbolModifiers modifiers) { sunVariableSymbol DeclareVariable(sunIdentifier node, sunSymbolModifiers modifiers) {
var local = (modifiers & sunSymbolModifiers.Local) != 0; var local = (modifiers & sunSymbolModifiers.Local) != 0;
if (local && Scopes.Count > 1) {
throw new sunLocalFunctionVariableException(node);
}
var name = MangleSymbolName(node.Value, node.Location.ScriptId, false, local); var name = MangleSymbolName(node.Value, node.Location.ScriptId, false, local);
var symbol = Scopes.DeclareVariable(name); var symbol = Scopes.DeclareVariable(name);
if (symbol == null) { if (symbol == null) {
throw new sunRedeclaredVariableException(node); throw new sunRedeclaredVariableException(node);
} }
#if SSC_SCOPES
if (Scopes.Top.Type == sunScopeType.Script) {
#else
if (Scopes.Count == 1) { if (Scopes.Count == 1) {
#endif
SymbolTable.Add(symbol); SymbolTable.Add(symbol);
} }
return symbol; return symbol;

View file

@ -259,4 +259,20 @@ namespace arookas {
public sunInvalidModifierException(sunNode node) public sunInvalidModifierException(sunNode node)
: base(node) { } : base(node) { }
} }
class sunConstantDeclarationException : sunNodeException<sunVariableDeclaration> {
public override string Message {
get { return "Constant variables must be assigned a value."; }
}
public sunConstantDeclarationException(sunVariableDeclaration node)
: base(node) { }
}
class sunLocalFunctionVariableException : sunNodeException<sunNode> {
public override string Message {
get { return "Only script-scope variables can be declared local."; }
}
public sunLocalFunctionVariableException(sunNode node)
: base(node) { }
}
} }

View file

@ -5,25 +5,11 @@ using System.Linq;
namespace arookas { namespace arookas {
class sunScopeStack : IEnumerable<sunScope> { class sunScopeStack : IEnumerable<sunScope> {
List<sunScope> mStack; List<sunScope> mStack;
#if SSC_SCOPES
int mLocals;
#endif
public int Count { public int Count {
get { return mStack.Count; } get { return mStack.Count; }
} }
#if SSC_SCOPES
public sunScope Root {
get { return this.FirstOrDefault(i => i.Type == Top.Type); }
}
public sunScope Script {
get { return this.FirstOrDefault(i => i.Type == sunScopeType.Script); }
}
public sunScope Function {
get { return this.FirstOrDefault(i => i.Type == sunScopeType.Function); }
}
#endif
public sunScope Top { public sunScope Top {
get { return this[Count - 1]; } get { return this[Count - 1]; }
} }
@ -34,78 +20,32 @@ namespace arookas {
public sunScopeStack() { public sunScopeStack() {
mStack = new List<sunScope>(8); mStack = new List<sunScope>(8);
#if SSC_SCOPES
Push(sunScopeType.Script); // push global scope
#else
Push(); Push();
#endif
} }
public void Push() { public void Push() {
#if SSC_SCOPES
Push(Top.Type);
#else
mStack.Add(new sunScope()); mStack.Add(new sunScope());
#endif
} }
#if SSC_SCOPES
public void Push(sunScopeType type) {
mStack.Add(new sunScope(type));
}
#endif
public void Pop() { public void Pop() {
if (Count > 1) { if (Count > 1) {
#if SSC_SCOPES
if (Top.Type == sunScopeType.Script) {
mLocals = 0; // left the function, reset locals
}
#else
// close relocations while we still have references to the symbols // close relocations while we still have references to the symbols
foreach (var variable in Top) { foreach (var variable in Top) {
variable.CloseRelocations(); variable.CloseRelocations();
} }
#endif
mStack.RemoveAt(Count - 1); mStack.RemoveAt(Count - 1);
} }
} }
public void Clear() { public void Clear() {
mStack.Clear(); mStack.Clear();
#if SSC_SCOPES
Push(sunScopeType.Script); // add global scope
mLocals = 0;
#else
Push(); Push();
#endif
} }
public sunVariableSymbol DeclareVariable(string name) { public sunVariableSymbol DeclareVariable(string name) {
#if SSC_SCOPES
switch (Top.Type) {
case sunScopeType.Script: return DeclareGlobal(name);
case sunScopeType.Function: return DeclareLocal(name);
}
return null;
#else
return Top.DeclareVariable(name, Count - 1, Top.VariableCount); return Top.DeclareVariable(name, Count - 1, Top.VariableCount);
#endif
} }
public sunConstantSymbol DeclareConstant(string name, sunExpression expression) { public sunConstantSymbol DeclareConstant(string name, sunExpression expression) {
return Top.DeclareConstant(name, expression); return Top.DeclareConstant(name, expression);
} }
#if SSC_SCOPES
sunVariableSymbol DeclareGlobal(string name) {
// symbol's display/index will be
// filled out by the relocation code
return Top.DeclareVariable(name, 0, 0);
}
sunVariableSymbol DeclareLocal(string name) {
var symbol = Top.DeclareVariable(name, 1, mLocals);
if (symbol != null) {
++mLocals;
}
return symbol;
}
#endif
public IEnumerator<sunScope> GetEnumerator() { public IEnumerator<sunScope> GetEnumerator() {
return mStack.GetEnumerator(); return mStack.GetEnumerator();
@ -117,25 +57,9 @@ namespace arookas {
class sunScope : IEnumerable<sunStorableSymbol> { class sunScope : IEnumerable<sunStorableSymbol> {
List<sunStorableSymbol> mStorables; List<sunStorableSymbol> mStorables;
#if SSC_SCOPES
sunScopeType mType;
#endif
#if SSC_SCOPES
public sunScopeType Type {
get { return mType; }
}
#endif
#if SSC_SCOPES
public sunScope(sunScopeType type) {
#else
public sunScope() { public sunScope() {
#endif
mStorables = new List<sunStorableSymbol>(10); mStorables = new List<sunStorableSymbol>(10);
#if SSC_SCOPES
mType = type;
#endif
} }
public int StorableCount { public int StorableCount {
@ -186,11 +110,4 @@ namespace arookas {
return GetEnumerator(); return GetEnumerator();
} }
} }
#if SSC_SCOPES
enum sunScopeType {
Script,
Function,
}
#endif
} }

View file

@ -185,11 +185,7 @@ namespace arookas {
public override void Compile(sunCompiler compiler) { public override void Compile(sunCompiler compiler) {
mOffset = compiler.Binary.Offset; mOffset = compiler.Binary.Offset;
#if SSC_SCOPES
compiler.Context.Scopes.Push(sunScopeType.Function);
#else
compiler.Context.Scopes.Push(); compiler.Context.Scopes.Push();
#endif
foreach (var parameter in Parameters) { foreach (var parameter in Parameters) {
compiler.Context.Scopes.DeclareVariable(parameter); // since there is no AST node for these, they won't affect MaxLocalCount compiler.Context.Scopes.DeclareVariable(parameter); // since there is no AST node for these, they won't affect MaxLocalCount
} }