diff --git a/ssc/ast/nodes.cs b/ssc/ast/nodes.cs index 6ab3e19..0418a6b 100644 --- a/ssc/ast/nodes.cs +++ b/ssc/ast/nodes.cs @@ -49,8 +49,9 @@ namespace arookas { public bool IsBranch { get { return Count > 0; } } public bool IsLeaf { get { return Count < 1; } } - public int MaxLocalCount { + public int LocalCount { get { +#if SSC_SCOPES var locals = 0; var maxChildLocals = 0; foreach (var child in this) { @@ -58,16 +59,28 @@ namespace arookas { ++locals; } else if (child is sunCompoundStatement) { - locals += child.MaxLocalCount; // HACK: compound statements aren't their own scope + 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.MaxLocalCount; + var childLocals = child.LocalCount; if (childLocals > maxChildLocals) { maxChildLocals = childLocals; } } } return locals + maxChildLocals; +#else + var locals = 0; + foreach (var child in this) { + if (child is sunVariableDeclaration || child is sunVariableDefinition) { + ++locals; + } + else if (!(child is sunFunctionDefinition)) { // don't recurse into function bodies + locals += child.LocalCount; + } + } + return locals; +#endif } } diff --git a/ssc/ast/nodes.flow.cs b/ssc/ast/nodes.flow.cs index 505af05..fd14dfe 100644 --- a/ssc/ast/nodes.flow.cs +++ b/ssc/ast/nodes.flow.cs @@ -99,7 +99,9 @@ namespace arookas { : base(location) { } public override void Compile(sunCompiler compiler) { +#if SSC_SCOPES compiler.Context.Scopes.Push(); +#endif var loop = PushLoop(compiler.Context); TryCompile(Declaration, compiler); var bodyPrologue = compiler.Binary.OpenPoint(); @@ -112,7 +114,9 @@ namespace arookas { compiler.Binary.ClosePoint(bodyEpilogue); loop.BreakPoint = compiler.Binary.OpenPoint(); compiler.Context.Loops.Pop(compiler); +#if SSC_SCOPES compiler.Context.Scopes.Pop(); +#endif } } class sunForDeclaration : sunNode { diff --git a/ssc/ast/nodes.statements.cs b/ssc/ast/nodes.statements.cs index 475a252..e6fdfa2 100644 --- a/ssc/ast/nodes.statements.cs +++ b/ssc/ast/nodes.statements.cs @@ -9,9 +9,13 @@ : 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 } } diff --git a/ssc/context.cs b/ssc/context.cs index d641fca..82b259d 100644 --- a/ssc/context.cs +++ b/ssc/context.cs @@ -102,7 +102,11 @@ namespace arookas { if (symbol == null) { throw new sunRedeclaredVariableException(node); } - if (Scopes.Top.Type == sunScopeType.Script) { // global-scope variables are added to the symbol table +#if SSC_SCOPES + if (Scopes.Top.Type == sunScopeType.Script) { +#else + if (Scopes.Count == 1) { +#endif SymbolTable.Add(symbol); } return symbol; diff --git a/ssc/scope.cs b/ssc/scope.cs index c7ae774..0c67263 100644 --- a/ssc/scope.cs +++ b/ssc/scope.cs @@ -5,12 +5,15 @@ using System.Linq; namespace arookas { class sunScopeStack : IEnumerable { List mStack; - int mGlobals, mLocals; +#if SSC_SCOPES + int mLocals; +#endif public int Count { get { return mStack.Count; } } - + +#if SSC_SCOPES public sunScope Root { get { return this.FirstOrDefault(i => i.Type == Top.Type); } } @@ -20,6 +23,7 @@ namespace arookas { public sunScope Function { get { return this.FirstOrDefault(i => i.Type == sunScopeType.Function); } } +#endif public sunScope Top { get { return this[Count - 1]; } } @@ -30,48 +34,69 @@ namespace arookas { public sunScopeStack() { mStack = new List(8); +#if SSC_SCOPES Push(sunScopeType.Script); // push global scope +#else + Push(); +#endif } - public void Push() { Push(Top.Type); } + public void Push() { +#if SSC_SCOPES + Push(Top.Type); +#else + mStack.Add(new sunScope()); +#endif + } +#if SSC_SCOPES public void Push(sunScopeType type) { mStack.Add(new sunScope(type)); } - public void Pop() { +#endif + public void Pop(sunCompiler compiler) { 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 + foreach (var variable in Top) { + variable.CloseRelocations(compiler); + } +#endif mStack.RemoveAt(Count - 1); } } public void Clear() { mStack.Clear(); +#if SSC_SCOPES Push(sunScopeType.Script); // add global scope - mGlobals = 0; - mLocals = 0; - } - - public void ResetGlobalCount() { - mGlobals = 0; - } - public void ResetLocalCount() { mLocals = 0; +#else + Push(); +#endif } 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); +#endif } public sunConstantSymbol DeclareConstant(string name, sunExpression expression) { return Top.DeclareConstant(name, expression); } +#if SSC_SCOPES sunVariableSymbol DeclareGlobal(string name) { - var symbol = Top.DeclareVariable(name, 0, mGlobals); - if (symbol != null) { - ++mGlobals; - } - return symbol; + // 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); @@ -80,6 +105,7 @@ namespace arookas { } return symbol; } +#endif public IEnumerator GetEnumerator() { return mStack.GetEnumerator(); @@ -91,15 +117,25 @@ namespace arookas { class sunScope : IEnumerable { List 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() { +#endif mStorables = new List(10); +#if SSC_SCOPES mType = type; +#endif } public int StorableCount { @@ -151,8 +187,10 @@ namespace arookas { } } +#if SSC_SCOPES enum sunScopeType { - Script, // outside of a function - Function, // inside of a function + Script, + Function, } +#endif } diff --git a/ssc/symbol.cs b/ssc/symbol.cs index da755f7..f4aa53c 100644 --- a/ssc/symbol.cs +++ b/ssc/symbol.cs @@ -50,6 +50,17 @@ namespace arookas { mSymbols.Clear(); } + public IEnumerable Get() { + return mSymbols; + } + public IEnumerable Get() where TSymbol : sunSymbol { + return mSymbols.OfType(); + } + + public int GetCount() where TSymbol : sunSymbol { + return mSymbols.Count(i => i is TSymbol); + } + public IEnumerator GetEnumerator() { return mSymbols.GetEnumerator(); } @@ -187,16 +198,19 @@ namespace arookas { public override void Compile(sunCompiler compiler) { mOffset = compiler.Binary.Offset; +#if SSC_SCOPES compiler.Context.Scopes.Push(sunScopeType.Function); - compiler.Context.Scopes.ResetLocalCount(); +#else + compiler.Context.Scopes.Push(); +#endif foreach (var parameter in Parameters) { compiler.Context.Scopes.DeclareVariable(parameter); // since there is no AST node for these, they won't affect MaxLocalCount } compiler.Binary.WriteMKDS(1); - compiler.Binary.WriteMKFR(mBody.MaxLocalCount); + compiler.Binary.WriteMKFR(mBody.LocalCount); mBody.Compile(compiler); compiler.Binary.WriteRET0(); - compiler.Context.Scopes.Pop(); + compiler.Context.Scopes.Pop(compiler); ++mCompiles; } public override sunRelocation CreateCallSite(sunCompiler compiler, int argCount) {