public static mysToken Evaluate( mysSymbol symbol, mysToken value, Stack<mysSymbolSpace> spaceStack ) { // NOTICE THIS // since each function has it's own internal space // before grabbing our reference to the space in which // we want to define our symbol, we need to pop the // internal off, or we're going to be defining the symbol // in our internal space, i.e. it will scope out as soon as // we're done. So we pop the internal off, grab our reference // to the space outside of that, then push the internal back on. mysSymbolSpace top = spaceStack.Pop(); mysSymbolSpace ss = spaceStack.Peek(); if ( value.Type == typeof(mysFunction) ) { defineFunction( symbol, value.Value as mysFunction, spaceStack.Peek() ); } else { mysSymbolSpace space = symbol.DefinedIn( spaceStack ); if ( space != null ) { space.Define( symbol, value ); } else { ss.Define( symbol, value ); } } spaceStack.Push( top ); return null; }
static void defineFunction( mysSymbol symbol, mysFunction f, mysSymbolSpace ss ) { mysFunctionGroup fg = null; // if symbol defined and of wrong type, undef it if ( ss.Defined( symbol ) && ss.GetValue( symbol ).Type != typeof(mysFunctionGroup) ) { // we could just overwrite it with define, // but I'd rather be entirely sure that we delete // the old value beforehand. ss.Undefine( symbol ); } // if we're defined at this point, we know it's a function group if ( ss.Defined( symbol ) ) { fg = ss.GetValue( symbol ).Value as mysFunctionGroup; } else { // create fg = new mysFunctionGroup(); ss.Define( symbol, new mysToken( fg ) ); } mysFunction collision = fg.Variants.FirstOrDefault( v => v.Signature.Count() == f.Signature.Count() && v.Signature .Zip( f.Signature, (a, b) => a == b ) .Count() == v.Signature.Count() ); if ( collision != null ) { // overwrite a conflicting sig! should probably // notify the user about this when it happens. fg.Variants.Remove( collision ); } fg.Variants.Add( f ); }