ssc/ssc/symbol.cs
2016-02-07 16:20:01 -05:00

355 lines
8.7 KiB
C#

using arookas.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace arookas {
class sunSymbolTable : IEnumerable<sunSymbol> {
List<sunSymbol> mSymbols;
public int Count { get { return mSymbols.Count; } }
public sunSymbol this[int index] {
get { return mSymbols[index]; }
}
public sunSymbolTable() {
mSymbols = new List<sunSymbol>(10);
}
public void Add(sunSymbol symbol) {
if (symbol == null) {
throw new ArgumentNullException("symbol");
}
mSymbols.Add(symbol);
}
public void Remove(sunSymbol symbol) {
if (symbol == null) {
throw new ArgumentNullException("symbol");
}
mSymbols.Remove(symbol);
}
public void RemoveAt(int index) {
mSymbols.RemoveAt(index);
}
public void Clear() {
mSymbols.Clear();
}
public IEnumerable<sunSymbol> Get() {
return mSymbols;
}
public IEnumerable<TSymbol> Get<TSymbol>() where TSymbol : sunSymbol {
return mSymbols.OfType<TSymbol>();
}
public int GetCount<TSymbol>() where TSymbol : sunSymbol {
return mSymbols.Count(i => i is TSymbol);
}
public IEnumerator<sunSymbol> GetEnumerator() {
return mSymbols.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}
abstract class sunSymbol {
string mName;
sunSymbolModifiers mModifiers;
List<sunRelocation> mRelocations;
public string Name {
get { return mName; }
}
public sunSymbolModifiers Modifiers {
get { return mModifiers; }
set { mModifiers = value; }
}
public bool HasRelocations {
get { return mRelocations.Count > 0; }
}
// symbol table
public abstract sunSymbolType Type { get; }
public abstract uint Data { get; }
protected sunSymbol(string name) {
mName = name;
mRelocations = new List<sunRelocation>(10);
}
public abstract void Compile(sunCompiler compiler);
public void OpenRelocation(sunRelocation relocation) {
if (relocation == null) {
throw new ArgumentNullException("relocation");
}
mRelocations.Add(relocation);
}
public void CloseRelocations(sunCompiler compiler) {
compiler.Binary.Keep();
foreach (var relocation in mRelocations) {
relocation.Relocate(compiler);
}
compiler.Binary.Back();
}
public static sunSymbolModifiers GetModifiers(sunNode modifierlist) {
if (modifierlist == null) {
return sunSymbolModifiers.None;
}
var modifiers = sunSymbolModifiers.None;
if (modifierlist.Any(i => i is sunConstKeyword)) {
modifiers |= sunSymbolModifiers.Constant;
}
if (modifierlist.Any(i => i is sunLocalKeyword)) {
modifiers |= sunSymbolModifiers.Local;
}
return modifiers;
}
}
abstract class sunCallableSymbol : sunSymbol {
sunParameterInfo mParameters;
protected int mCompiles;
public sunParameterInfo Parameters {
get { return mParameters; }
}
public int CompileCount {
get { return mCompiles; }
}
protected sunCallableSymbol(string name, sunParameterInfo parameterInfo)
: base(name) {
mParameters = parameterInfo;
}
public abstract sunRelocation CreateCallSite(sunCompiler compiler, int argCount);
}
class sunBuiltinSymbol : sunCallableSymbol {
int mIndex;
public int Index {
get { return mIndex; }
set { mIndex = value; }
}
// symbol table
public override sunSymbolType Type { get { return sunSymbolType.Builtin; } }
public override uint Data { get { return (uint)mIndex; } }
public sunBuiltinSymbol(string name, int index)
: this(name, null, index) { }
public sunBuiltinSymbol(string name, sunParameterInfo parameters, int index)
: base(name, parameters) {
mIndex = index;
}
public override void Compile(sunCompiler compiler) {
// don't compile builtins
++mCompiles;
}
public override sunRelocation CreateCallSite(sunCompiler compiler, int argCount) {
return new sunBuiltinCallSite(this, compiler, argCount);
}
}
class sunFunctionSymbol : sunCallableSymbol {
uint mOffset;
sunNode mBody;
public uint Offset {
get { return mOffset; }
}
// symbol table
public override sunSymbolType Type {
get { return sunSymbolType.Function; }
}
public override uint Data {
get { return (uint)Offset; }
}
public sunFunctionSymbol(string name, sunParameterInfo parameters, sunNode body)
: base(name, parameters) {
if (body == null) {
throw new ArgumentNullException("body");
}
mBody = body;
}
public override void Compile(sunCompiler compiler) {
mOffset = compiler.Binary.Offset;
#if SSC_SCOPES
compiler.Context.Scopes.Push(sunScopeType.Function);
#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);
var locals = mBody.LocalCount;
if (locals > 0) {
compiler.Binary.WriteMKFR(locals);
}
mBody.Compile(compiler);
compiler.Binary.WriteRET0();
compiler.Context.Scopes.Pop(compiler);
++mCompiles;
}
public override sunRelocation CreateCallSite(sunCompiler compiler, int argCount) {
return new sunFunctionCallSite(this, compiler, argCount);
}
}
class sunParameterInfo : IEnumerable<string> {
string[] mParameters;
bool mVariadic;
public int Minimum {
get { return mParameters.Length; }
}
public bool IsVariadic {
get { return mVariadic; }
}
public sunParameterInfo(IEnumerable<sunIdentifier> parameters, bool variadic) {
// validate parameter names
var duplicate = parameters.FirstOrDefault(a => parameters.Count(b => a.Value == b.Value) > 1);
if (duplicate != null) {
throw new sunRedeclaredParameterException(duplicate);
}
mParameters = parameters.Select(i => i.Value).ToArray();
mVariadic = variadic;
}
public sunParameterInfo(IEnumerable<string> parameters, bool variadic) {
// validate parameter names
mParameters = parameters.ToArray();
mVariadic = variadic;
}
public bool ValidateArgumentCount(int count) {
return mVariadic ? count >= Minimum : count == Minimum;
}
public IEnumerator<string> GetEnumerator() {
return mParameters.GetArrayEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}
abstract class sunStorableSymbol : sunSymbol {
protected sunStorableSymbol(string name)
: base(name) { }
public override void Compile(sunCompiler compiler) {
CompileGet(compiler);
}
public abstract void CompileGet(sunCompiler compiler);
public abstract void CompileSet(sunCompiler compiler);
public virtual void CompileInc(sunCompiler compiler) {
CompileGet(compiler);
compiler.Binary.WriteINT(1);
compiler.Binary.WriteADD();
}
public virtual void CompileDec(sunCompiler compiler) {
CompileGet(compiler);
compiler.Binary.WriteINT(1);
compiler.Binary.WriteSUB();
}
}
class sunVariableSymbol : sunStorableSymbol {
int mDisplay, mIndex;
public int Display {
get { return mDisplay; }
set { mDisplay = value; }
}
public int Index {
get { return mIndex; }
set { mIndex = value; }
}
// symbol table
public override sunSymbolType Type {
get { return sunSymbolType.Variable; }
}
public override uint Data {
get { return (uint)Index; }
}
public sunVariableSymbol(string name)
: this(name, 0, 0) { }
public sunVariableSymbol(string name, int display, int index)
: base(name) {
mDisplay = display;
mIndex = index;
}
public override void CompileGet(sunCompiler compiler) {
OpenRelocation(new sunVariableGetSite(this, compiler));
}
public override void CompileSet(sunCompiler compiler) {
OpenRelocation(new sunVariableSetSite(this, compiler));
}
public override void CompileInc(sunCompiler compiler) {
OpenRelocation(new sunVariableIncSite(this, compiler));
}
public override void CompileDec(sunCompiler compiler) {
OpenRelocation(new sunVariableDecSite(this, compiler));
}
}
class sunConstantSymbol : sunStorableSymbol {
sunExpression mExpression;
// symbol table
public override sunSymbolType Type {
get { return sunSymbolType.Constant; }
}
public override uint Data {
get { return 0; }
}
public sunConstantSymbol(string name, sunExpression expression)
: base(name) {
if (expression == null) {
throw new ArgumentNullException("expression");
}
mExpression = expression;
}
public override void CompileGet(sunCompiler compiler) {
mExpression.Compile(compiler);
}
public override void CompileSet(sunCompiler compiler) {
// checks against this have to be implemented at a higher level
throw new InvalidOperationException();
}
}
public enum sunSymbolType {
Builtin,
Function,
Variable,
Constant,
}
[Flags]
enum sunSymbolModifiers {
None = 0,
Constant = 1 << 0,
Local = 1 << 1,
}
}