public static object MacroExpandBase(object expr, AnalysisScope env) { var sym = expr as Symbol; if (sym != null) { if (!Keywordp(sym)) { var entry = env.FindLocal(sym, ScopeFlags.Referenced); var macro = (entry != null) ? entry.SymbolMacroValue : sym.SymbolMacroValue; if (macro != null) { return(macro.Form); } } return(expr); } var form = expr as Cons; if (form != null) { var head = First(form) as Symbol; if (head == null || Keywordp(head)) { return(expr); } var entry = env.FindLocal(head, ScopeFlags.Referenced); var macro = (entry != null) ? entry.MacroValue : head.MacroValue; if (macro != null) { var hook = (IApply)GetDynamic(Symbols.MacroexpandHook); return(Funcall(hook, macro, form, new AnalysisScope(env))); } else { return(expr); } } return(expr); }
public static bool FindNameOrMacroInEnvironment(Symbol sym, AnalysisScope env) { return env != null && env.FindLocal(sym) != null; }
public static object MacroExpandBase(object expr, AnalysisScope env) { var sym = expr as Symbol; if (sym != null) { var entry = env.FindLocal(sym); var macro = (entry != null) ? entry.SymbolMacroValue : sym.SymbolMacroValue; if (macro != null) { return macro.Form; } else { return expr; } } var form = expr as Cons; if (form != null) { var head = First(form) as Symbol; if (head == null) { return expr; } var entry = env.FindLocal(head); var macro = (entry != null) ? entry.MacroValue : head.MacroValue; if (macro != null) { var hook = (IApply)GetDynamic(Symbols.MacroexpandHook); return Funcall(hook, macro, form, new AnalysisScope(env, "try-macroexpand")); } else { return expr; } } return expr; }
public static bool FindNameOrMacroInEnvironment(Symbol sym, AnalysisScope env) { return(env != null && env.FindLocal(sym) != null); }
public static Expression CompileGetVariable(Symbol sym, AnalysisScope scope, bool useEnvironment) { if (sym.IsDynamic) { return CallRuntime(GetDynamicMethod, Expression.Constant(sym)); } else if (Keywordp(sym)) { return Expression.Constant(sym, typeof(Symbol)); } else { int depth; ScopeEntry entry; if (scope.FindLocal(sym, ScopeFlags.Referenced, out depth, out entry)) { Expression code; if (entry.MacroValue != null || entry.SymbolMacroValue != null) { throw new LispException("{0}: cannot compile reference to (symbol)macro variable", sym); } else if (entry.Parameter != null) { code = entry.Parameter; } else { code = CallRuntime(GetLexicalMethod, Expression.Constant(depth), Expression.Constant(entry.Index)); } if ((entry.Flags & ScopeFlags.Future) != 0) { // This also handles the lazy-future case. code = CallRuntime(GetTaskResultMethod, Expression.Convert(code, typeof(ThreadContext))); } else if ((entry.Flags & ScopeFlags.Lazy) != 0) { code = CallRuntime(GetDelayedExpressionResultMethod, Expression.Convert(code, typeof(DelayedExpression))); } return code; } else if (useEnvironment) { return Expression.PropertyOrField(Expression.Constant(sym), "CheckedOrEnvironmentValue"); } else { return Expression.PropertyOrField(Expression.Constant(sym), "CheckedValue"); } } }
public static Expression CompileDeclare(Cons form, AnalysisScope scope) { CheckLength(form, 2); foreach (var item in Cdr(form)) { if (item is Cons) { var declaration = (Cons)item; var declare = (Symbol)First(declaration); switch (declare.Name) { case "ignore": { if (!scope.IsBlockScope) { throw new LispException("(declare (ignore ...)) statement requires block scope: {0}", form); } foreach (Symbol sym in Cdr(declaration)) { scope.FindLocal(sym, ScopeFlags.Ignore); } break; } case "ignorable": { if (!scope.IsBlockScope) { throw new LispException("(declare (ignorable ...)) statement requires block scope: {0}", form); } foreach (Symbol sym in Cdr(declaration)) { scope.FindLocal(sym, ScopeFlags.Ignorable); } break; } case "dynamic": { foreach (Symbol sym in Cdr(declaration)) { sym.IsDynamic = true; } break; } default: { break; } } } } return Expression.Constant(null, typeof(object)); }
public static Expression CompileWrapped(object expr1, AnalysisScope scope) { var expr = MacroExpand(expr1, scope); // At this point expr is either not a macro call, or it is a macro call // that refused to expand by returning the &whole parameter. if (expr is Symbol) { var sym = (Symbol)expr; // This optimization does not help much, I think. //if ( sym.IsDynamic || scope.HasLocalVariable( sym, int.MaxValue ) ) //{ // return CompileGetVariable( sym, scope ); //} //else if ( sym.IsFunction && ( sym.Value is ImportedFunction || sym.Value is ImportedConstructor ) ) //{ // return Expression.Constant( sym.Value, typeof( object ) ); //} //else { return CompileGetVariable(sym, scope, false); } } else if (expr is Cons) { var form = (Cons)expr; if (First(form) is Symbol) { var head = (Symbol)First(form); var shadowed = scope.FindLocal(head) != null; if (shadowed) { return CompileFunctionCall(form, scope); } else if (head.SpecialFormValue != null) { return head.SpecialFormValue.Helper(form, scope); } else { return CompileFunctionCall(form, scope); } } else { return CompileFunctionCall(form, scope); } } else { // anything else is a literal return CompileLiteral(expr); } }
public static Expression CompileSetq(Cons form, AnalysisScope scope) { // setq sym expr CheckLength(form, 3); var sym = CheckSymbol(Second(form)); var form2 = MacroExpand(sym, scope); if (form2 != sym) { // symbol macro - change setq to setf var expr = MakeListStar(Symbols.Setf, form2, Cddr(form)); return Compile(expr, scope); } var value = Compile(Third(form), scope); if (sym.IsDynamic) { if (scope.Parent == null && !scope.IsFileScope) { // REPL does not require def before set. return Expression.Assign(Expression.PropertyOrField(Expression.Constant(sym), "LessCheckedValue"), value); } else { return CallRuntime(SetDynamicMethod, Expression.Constant(sym), value); } } else { int depth; ScopeEntry entry; if (scope.FindLocal(sym, ScopeFlags.Assigned, out depth, out entry)) { if (entry.MacroValue != null || entry.SymbolMacroValue != null) { throw new LispException("{0}: cannot compile reference to (symbol)macro variable", sym); } var constant = (entry.Flags & ScopeFlags.Constant) != 0; if (constant) { throw new LispException("Cannot assign to a constant, future or lazy variable: {0}", sym); } if (entry.Parameter != null) { return Expression.Assign(entry.Parameter, value); } else { return CallRuntime(SetLexicalMethod, Expression.Constant(depth), Expression.Constant(entry.Index), value); } } else if (scope.Parent == null) { // REPL assigments return Expression.Assign(Expression.PropertyOrField(Expression.Constant(sym), "LessCheckedValue"), value); } else { return Expression.Assign(Expression.PropertyOrField(Expression.Constant(sym), "CheckedValue"), value); } } }