/// <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]); }
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); }