Пример #1
0
 /// <summary>
 /// Gets the additional arguments from the scope.
 /// </summary>
 /// <param name="scope">The scope.</param>
 /// <returns>The result.</returns>
 public static object[] GetAdditionalArgs(this LispScope scope)
 {
     if (scope.ContainsKey(LispEnvironment.ArgsMeta))
     {
         LispVariant variant = scope[LispEnvironment.ArgsMeta] as LispVariant;
         if (variant != null)
         {
             return(variant.ListValue.ToArray());
         }
     }
     return(new object[0]);
 }
Пример #2
0
        private static object ExpandMacros(object ast, LispScope globalScope, ref bool anyMacroReplaced)
        {
            if (ast == null || ast is LispVariant)
            {
                return(ast);
            }

            var astAsList = ((IEnumerable <object>)ast).ToList();

            if (astAsList.Count == 0)
            {
                return(ast);
            }

            // compile time macro: process define-macro statements ==> call special form, this will add macro to global scope as side effect
            var function     = astAsList.First();
            var functionName = function.ToString();

            if (globalScope != null && globalScope.ContainsKey(functionName))
            {
                var fcn = ((LispVariant)globalScope[functionName]).FunctionValue;
                if (fcn.IsEvalInExpand)
                {
                    var args = new List <object>(astAsList);
                    args.RemoveAt(0);

                    // process compile time macro definition
                    //   --> side effect: add macro definition to internal macro scope
                    fcn.Function(args.ToArray(), globalScope);

                    // compile time macros definitions will be removed from code in expand macro phase
                    // because only the side effect above is needed for further macro replacements
                    return(null);
                }
            }

            // compile time macros: process macro expansion in an expression which calls a macro
            if (LispEnvironment.IsMacro(function, globalScope))
            {
                var macro = LispEnvironment.GetMacro(function, globalScope);
                if (macro is LispMacroCompileTimeExpand)
                {
                    anyMacroReplaced = true;
                    var macroExpand = (LispMacroCompileTimeExpand)macro;
                    var astWithReplacedArguments = ReplaceFormalArgumentsInExpression(macroExpand.FormalArguments, astAsList, macroExpand.Expression, globalScope, ref anyMacroReplaced).ToList();   // PATCH
                    // process recursive macro expands (do not wrap list as LispVariant at this point)
                    return(ConvertLispVariantListToListIfNeeded(EvalAst(astWithReplacedArguments, globalScope)));
                }
            }

            var expandedAst = new List <object>();

            // Expand recursively and handle enumarations (make them flat !)
            foreach (var elem in astAsList)
            {
                var expandResult = ExpandMacros(elem, globalScope);
                // ignore code which is removed in macro expand phase
                if (expandResult != null)
                {
                    // process recursive macro expands (do not wrap list as LispVariant at this point)
                    expandedAst.Add(ConvertLispVariantListToListIfNeeded(expandResult));
                }
            }

            return(expandedAst);
        }