PageRenderTime 53ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/DICK.B1/IronPython/Compiler/Ast/PythonAst.cs

https://bitbucket.org/williamybs/uidipythontool
C# | 844 lines | 637 code | 142 blank | 65 comment | 91 complexity | ab8055f46a7ce935711c4d3306b7ded4 MD5 | raw file
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Microsoft Public License. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Microsoft Public License, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Microsoft Public License.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. using System;
  16. using System.Collections.Generic;
  17. using System.Collections.ObjectModel;
  18. using System.Diagnostics;
  19. using System.Dynamic;
  20. using System.IO;
  21. using System.Runtime.CompilerServices;
  22. using Microsoft.Scripting;
  23. using Microsoft.Scripting.Actions;
  24. using Microsoft.Scripting.Interpreter;
  25. using Microsoft.Scripting.Runtime;
  26. using Microsoft.Scripting.Utils;
  27. using IronPython.Runtime;
  28. using IronPython.Runtime.Binding;
  29. using IronPython.Runtime.Operations;
  30. #if !CLR2
  31. using MSAst = System.Linq.Expressions;
  32. #else
  33. using MSAst = Microsoft.Scripting.Ast;
  34. #endif
  35. using AstUtils = Microsoft.Scripting.Ast.Utils;
  36. namespace IronPython.Compiler.Ast {
  37. using Ast = MSAst.Expression;
  38. /// <summary>
  39. /// Top-level ast for all Python code. Typically represents a module but could also
  40. /// be exec or eval code.
  41. /// </summary>
  42. public sealed class PythonAst : ScopeStatement {
  43. private Statement _body;
  44. private CompilationMode _mode;
  45. private readonly bool _isModule;
  46. private readonly bool _printExpressions;
  47. private readonly ModuleOptions _languageFeatures;
  48. private readonly CompilerContext _compilerContext;
  49. private readonly MSAst.SymbolDocumentInfo _document;
  50. private readonly string/*!*/ _name;
  51. private PythonVariable _docVariable, _nameVariable, _fileVariable;
  52. private ModuleContext _modContext;
  53. internal MSAst.Expression _arrayExpression;
  54. private UncollectableCompilationMode.ConstantInfo _contextInfo;
  55. private Dictionary<PythonVariable, MSAst.Expression> _globalVariables = new Dictionary<PythonVariable, MSAst.Expression>();
  56. internal readonly Profiler _profiler; // captures timing data if profiling
  57. internal const string GlobalContextName = "$globalContext";
  58. internal static MSAst.ParameterExpression _functionCode = Ast.Variable(typeof(FunctionCode), "$functionCode");
  59. internal readonly static MSAst.ParameterExpression/*!*/ _globalArray = Ast.Parameter(typeof(PythonGlobal[]), "$globalArray");
  60. internal static readonly MSAst.ParameterExpression/*!*/ _globalContext = Ast.Parameter(typeof(CodeContext), GlobalContextName);
  61. internal static readonly ReadOnlyCollection<MSAst.ParameterExpression> _arrayFuncParams = new ReadOnlyCollectionBuilder<MSAst.ParameterExpression>(new[] { _globalContext, _functionCode }).ToReadOnlyCollection();
  62. public PythonAst(Statement body, bool isModule, ModuleOptions languageFeatures, bool printExpressions) {
  63. ContractUtils.RequiresNotNull(body, "body");
  64. _body = body;
  65. _isModule = isModule;
  66. _printExpressions = printExpressions;
  67. _languageFeatures = languageFeatures;
  68. }
  69. public PythonAst(Statement body, bool isModule, ModuleOptions languageFeatures, bool printExpressions, CompilerContext context) {
  70. ContractUtils.RequiresNotNull(body, "body");
  71. _body = body;
  72. _isModule = isModule;
  73. _printExpressions = printExpressions;
  74. _languageFeatures = languageFeatures;
  75. _mode = ((PythonCompilerOptions)context.Options).CompilationMode ?? GetCompilationMode(context);
  76. _compilerContext = context;
  77. FuncCodeExpr = _functionCode;
  78. PythonCompilerOptions pco = context.Options as PythonCompilerOptions;
  79. Debug.Assert(pco != null);
  80. string name;
  81. if (!context.SourceUnit.HasPath || (pco.Module & ModuleOptions.ExecOrEvalCode) != 0) {
  82. name = "<module>";
  83. } else {
  84. name = context.SourceUnit.Path;
  85. }
  86. _name = name;
  87. Debug.Assert(_name != null);
  88. PythonOptions po = ((PythonContext)context.SourceUnit.LanguageContext).PythonOptions;
  89. if (po.EnableProfiler && _mode != CompilationMode.ToDisk) {
  90. _profiler = Profiler.GetProfiler(PyContext);
  91. }
  92. _document = context.SourceUnit.Document ?? Ast.SymbolDocument(name, PyContext.LanguageGuid, PyContext.VendorGuid);
  93. }
  94. /// <summary>
  95. /// Binds an AST and makes it capable of being reduced and compiled. Before calling Bind an AST cannot successfully
  96. /// be reduced.
  97. /// </summary>
  98. public void Bind() {
  99. PythonNameBinder.BindAst(this, _compilerContext);
  100. }
  101. public override string Name {
  102. get {
  103. return "<module>";
  104. }
  105. }
  106. public override void Walk(PythonWalker walker) {
  107. if (walker.Walk(this)) {
  108. if (_body != null) {
  109. _body.Walk(walker);
  110. }
  111. }
  112. walker.PostWalk(this);
  113. }
  114. #region Name Binding Support
  115. internal override bool ExposesLocalVariable(PythonVariable variable) {
  116. return true;
  117. }
  118. internal override void FinishBind(PythonNameBinder binder) {
  119. _contextInfo = CompilationMode.GetContext();
  120. // create global variables for compiler context.
  121. PythonGlobal[] globalArray = new PythonGlobal[Variables == null ? 0 : Variables.Count];
  122. Dictionary<string, PythonGlobal> globals = new Dictionary<string, PythonGlobal>();
  123. GlobalDictionaryStorage storage = new GlobalDictionaryStorage(globals, globalArray);
  124. var modContext = _modContext = new ModuleContext(new PythonDictionary(storage), PyContext);
  125. MSAst.Expression array;
  126. if (_mode == CompilationMode.ToDisk) {
  127. _arrayExpression = array = _globalArray;
  128. } else {
  129. _arrayExpression = array = Ast.Constant(globalArray);
  130. }
  131. if (Variables != null) {
  132. int globalIndex = 0;
  133. foreach (PythonVariable variable in Variables.Values) {
  134. PythonGlobal global = new PythonGlobal(modContext.GlobalContext, variable.Name);
  135. _globalVariables[variable] = CompilationMode.GetGlobal(GetGlobalContext(), globals.Count, variable, global);
  136. globalArray[globalIndex++] = globals[variable.Name] = global;
  137. }
  138. }
  139. CompilationMode.PublishContext(modContext.GlobalContext, _contextInfo);
  140. }
  141. internal override MSAst.Expression LocalContext {
  142. get {
  143. return GetGlobalContext();
  144. }
  145. }
  146. internal override PythonVariable BindReference(PythonNameBinder binder, PythonReference reference) {
  147. return EnsureVariable(reference.Name);
  148. }
  149. internal override bool TryBindOuter(ScopeStatement from, PythonReference reference, out PythonVariable variable) {
  150. // Unbound variable
  151. from.AddReferencedGlobal(reference.Name);
  152. if (from.HasLateBoundVariableSets) {
  153. // If the context contains unqualified exec, new locals can be introduced
  154. // Therefore we need to turn this into a fully late-bound lookup which
  155. // happens when we don't have a PythonVariable.
  156. variable = null;
  157. return false;
  158. } else {
  159. // Create a global variable to bind to.
  160. variable = EnsureGlobalVariable(reference.Name);
  161. return true;
  162. }
  163. }
  164. internal override bool IsGlobal {
  165. get { return true; }
  166. }
  167. internal PythonVariable DocVariable {
  168. get { return _docVariable; }
  169. set { _docVariable = value; }
  170. }
  171. internal PythonVariable NameVariable {
  172. get { return _nameVariable; }
  173. set { _nameVariable = value; }
  174. }
  175. internal PythonVariable FileVariable {
  176. get { return _fileVariable; }
  177. set { _fileVariable = value; }
  178. }
  179. internal CompilerContext CompilerContext {
  180. get {
  181. return _compilerContext;
  182. }
  183. }
  184. internal MSAst.Expression GlobalArrayInstance {
  185. get {
  186. return _arrayExpression;
  187. }
  188. }
  189. internal MSAst.SymbolDocumentInfo Document {
  190. get {
  191. return _document;
  192. }
  193. }
  194. internal Dictionary<PythonVariable, MSAst.Expression> ModuleVariables {
  195. get {
  196. return _globalVariables;
  197. }
  198. }
  199. internal ModuleContext ModuleContext {
  200. get {
  201. return _modContext;
  202. }
  203. }
  204. /// <summary>
  205. /// Creates a variable at the global level. Called for known globals (e.g. __name__),
  206. /// for variables explicitly declared global by the user, and names accessed
  207. /// but not defined in the lexical scope.
  208. /// </summary>
  209. internal PythonVariable/*!*/ EnsureGlobalVariable(string name) {
  210. PythonVariable variable;
  211. if (!TryGetVariable(name, out variable)) {
  212. variable = CreateVariable(name, VariableKind.Global);
  213. }
  214. return variable;
  215. }
  216. #endregion
  217. #region MSASt.Expression Overrides
  218. public override Type Type {
  219. get {
  220. return CompilationMode.DelegateType;
  221. }
  222. }
  223. /// <summary>
  224. /// Reduces the PythonAst to a LambdaExpression of type Type.
  225. /// </summary>
  226. public override MSAst.Expression Reduce() {
  227. return GetLambda();
  228. }
  229. internal override MSAst.LambdaExpression GetLambda() {
  230. string name = ((PythonCompilerOptions)_compilerContext.Options).ModuleName ?? "<unnamed>";
  231. return CompilationMode.ReduceAst(this, name);
  232. }
  233. #endregion
  234. #region Public API
  235. /// <summary>
  236. /// True division is enabled in this AST.
  237. /// </summary>
  238. public bool TrueDivision {
  239. get { return (_languageFeatures & ModuleOptions.TrueDivision) != 0; }
  240. }
  241. /// <summary>
  242. /// True if the with statement is enabled in this AST.
  243. /// </summary>
  244. public bool AllowWithStatement {
  245. get {
  246. return (_languageFeatures & ModuleOptions.WithStatement) != 0;
  247. }
  248. }
  249. /// <summary>
  250. /// True if absolute imports are enabled
  251. /// </summary>
  252. public bool AbsoluteImports {
  253. get {
  254. return (_languageFeatures & ModuleOptions.AbsoluteImports) != 0;
  255. }
  256. }
  257. internal PythonDivisionOptions DivisionOptions {
  258. get {
  259. return PyContext.PythonOptions.DivisionOptions;
  260. }
  261. }
  262. public Statement Body {
  263. get { return _body; }
  264. }
  265. public bool Module {
  266. get { return _isModule; }
  267. }
  268. #endregion
  269. #region Transformation
  270. /// <summary>
  271. /// Returns a ScriptCode object for this PythonAst. The ScriptCode object
  272. /// can then be used to execute the code against it's closed over scope or
  273. /// to execute it against a different scope.
  274. /// </summary>
  275. internal ScriptCode ToScriptCode() {
  276. return CompilationMode.MakeScriptCode(this);
  277. }
  278. internal MSAst.Expression ReduceWorker() {
  279. ReadOnlyCollectionBuilder<MSAst.Expression> block = new ReadOnlyCollectionBuilder<MSAst.Expression>();
  280. if (_body is ReturnStatement && (_languageFeatures == ModuleOptions.None || _languageFeatures == (ModuleOptions.ExecOrEvalCode | ModuleOptions.Interpret))) {
  281. // for simple eval's we can construct a simple tree which just
  282. // leaves the value on the stack. Return's can't exist in modules
  283. // so this is always safe.
  284. Debug.Assert(!_isModule);
  285. var ret = (ReturnStatement)_body;
  286. return Ast.Block(
  287. Ast.DebugInfo(
  288. _document,
  289. ret.Expression.Start.Line,
  290. ret.Expression.Start.Column,
  291. ret.Expression.End.Line,
  292. ret.Expression.End.Column
  293. ),
  294. AstUtils.Convert(
  295. ret.Expression.Reduce(),
  296. typeof(object)
  297. )
  298. );
  299. }
  300. AddInitialiation(block);
  301. if (_isModule) {
  302. block.Add(AssignValue(GetVariableExpression(_docVariable), Ast.Constant(GetDocumentation(_body))));
  303. }
  304. block.Add(_body);
  305. MSAst.Expression body = Ast.Block(block.ToReadOnlyCollection());
  306. body = WrapScopeStatements(body, Body.CanThrow); // new ComboActionRewriter().VisitNode(Transform(ag))
  307. body = AddModulePublishing(body);
  308. body = AddProfiling(body);
  309. body = Ast.Label(FunctionDefinition._returnLabel, AstUtils.Convert(body, typeof(object)));
  310. if (body.Type == typeof(void)) {
  311. body = Ast.Block(body, Ast.Constant(null));
  312. }
  313. return body;
  314. }
  315. private void AddInitialiation(ReadOnlyCollectionBuilder<MSAst.Expression> block) {
  316. if (_isModule) {
  317. block.Add(AssignValue(GetVariableExpression(_fileVariable), Ast.Constant(ModuleFileName)));
  318. block.Add(AssignValue(GetVariableExpression(_nameVariable), Ast.Constant(ModuleName)));
  319. }
  320. if (_languageFeatures != ModuleOptions.None || _isModule) {
  321. block.Add(
  322. Ast.Call(
  323. AstMethods.ModuleStarted,
  324. LocalContext,
  325. AstUtils.Constant(_languageFeatures)
  326. )
  327. );
  328. }
  329. }
  330. internal override bool PrintExpressions {
  331. get {
  332. return _printExpressions;
  333. }
  334. }
  335. private MSAst.Expression AddModulePublishing(MSAst.Expression body) {
  336. if (_isModule) {
  337. PythonCompilerOptions pco = _compilerContext.Options as PythonCompilerOptions;
  338. string moduleName = ModuleName;
  339. if ((pco.Module & ModuleOptions.Initialize) != 0) {
  340. var tmp = Ast.Variable(typeof(object), "$originalModule");
  341. // TODO: Should be try/fault
  342. body = Ast.Block(
  343. new[] { tmp },
  344. AstUtils.Try(
  345. Ast.Assign(tmp, Ast.Call(AstMethods.PublishModule, LocalContext, Ast.Constant(moduleName))),
  346. body
  347. ).Catch(
  348. typeof(Exception),
  349. Ast.Call(AstMethods.RemoveModule, LocalContext, Ast.Constant(moduleName), tmp),
  350. Ast.Rethrow(body.Type)
  351. )
  352. );
  353. }
  354. }
  355. return body;
  356. }
  357. private string ModuleFileName {
  358. get {
  359. return _name;
  360. }
  361. }
  362. private string ModuleName {
  363. get {
  364. PythonCompilerOptions pco = _compilerContext.Options as PythonCompilerOptions;
  365. string moduleName = pco.ModuleName;
  366. if (moduleName == null) {
  367. #if !SILVERLIGHT
  368. if (_compilerContext.SourceUnit.HasPath && _compilerContext.SourceUnit.Path.IndexOfAny(Path.GetInvalidFileNameChars()) == -1) {
  369. moduleName = Path.GetFileNameWithoutExtension(_compilerContext.SourceUnit.Path);
  370. #else
  371. if (_compilerContext.SourceUnit.HasPath) {
  372. moduleName = _compilerContext.SourceUnit.Path;
  373. #endif
  374. } else {
  375. moduleName = "<module>";
  376. }
  377. }
  378. return moduleName;
  379. }
  380. }
  381. internal override FunctionAttributes Flags {
  382. get {
  383. ModuleOptions features = ((PythonCompilerOptions)_compilerContext.Options).Module;
  384. FunctionAttributes funcAttrs = 0;
  385. if ((features & ModuleOptions.TrueDivision) != 0) {
  386. funcAttrs |= FunctionAttributes.FutureDivision;
  387. }
  388. return funcAttrs;
  389. }
  390. }
  391. internal SourceUnit SourceUnit {
  392. get {
  393. if (_compilerContext == null) {
  394. return null;
  395. }
  396. return _compilerContext.SourceUnit;
  397. }
  398. }
  399. internal string[] GetNames() {
  400. string[] res = new string[Variables.Count];
  401. int i = 0;
  402. foreach (var variable in Variables.Values) {
  403. res[i++] = variable.Name;
  404. }
  405. return res;
  406. }
  407. #endregion
  408. #region Compilation Mode (TODO: Factor out)
  409. private static Compiler.CompilationMode GetCompilationMode(CompilerContext context) {
  410. PythonCompilerOptions options = (PythonCompilerOptions)context.Options;
  411. if ((options.Module & ModuleOptions.ExecOrEvalCode) != 0) {
  412. return CompilationMode.Lookup;
  413. }
  414. PythonContext pc = ((PythonContext)context.SourceUnit.LanguageContext);
  415. return ((pc.PythonOptions.Optimize || options.Optimized) && !pc.PythonOptions.LightweightScopes) ?
  416. CompilationMode.Uncollectable :
  417. CompilationMode.Collectable;
  418. }
  419. internal CompilationMode CompilationMode {
  420. get {
  421. return _mode;
  422. }
  423. }
  424. private MSAst.Expression GetGlobalContext() {
  425. if (_contextInfo != null) {
  426. return _contextInfo.Expression;
  427. }
  428. return _globalContext;
  429. }
  430. internal void PrepareScope(ReadOnlyCollectionBuilder<MSAst.ParameterExpression> locals, List<MSAst.Expression> init) {
  431. CompilationMode.PrepareScope(this, locals, init);
  432. }
  433. internal new MSAst.Expression Constant(object value) {
  434. return new PythonConstantExpression(CompilationMode, value);
  435. }
  436. #endregion
  437. #region Binder Factories
  438. internal MSAst.Expression/*!*/ Convert(Type/*!*/ type, ConversionResultKind resultKind, MSAst.Expression/*!*/ target) {
  439. if (resultKind == ConversionResultKind.ExplicitCast) {
  440. return new DynamicConvertExpression(
  441. PyContext.Convert(
  442. type,
  443. resultKind
  444. ),
  445. CompilationMode,
  446. target
  447. );
  448. }
  449. return CompilationMode.Dynamic(
  450. PyContext.Convert(
  451. type,
  452. resultKind
  453. ),
  454. type,
  455. target
  456. );
  457. }
  458. internal MSAst.Expression/*!*/ Operation(Type/*!*/ resultType, PythonOperationKind operation, MSAst.Expression arg0) {
  459. if (resultType == typeof(object)) {
  460. return new PythonDynamicExpression1(
  461. Binders.UnaryOperationBinder(
  462. PyContext,
  463. operation
  464. ),
  465. CompilationMode,
  466. arg0
  467. );
  468. }
  469. return CompilationMode.Dynamic(
  470. Binders.UnaryOperationBinder(
  471. PyContext,
  472. operation
  473. ),
  474. resultType,
  475. arg0
  476. );
  477. }
  478. internal MSAst.Expression/*!*/ Operation(Type/*!*/ resultType, PythonOperationKind operation, MSAst.Expression arg0, MSAst.Expression arg1) {
  479. if (resultType == typeof(object)) {
  480. return new PythonDynamicExpression2(
  481. Binders.BinaryOperationBinder(
  482. PyContext,
  483. operation
  484. ),
  485. _mode,
  486. arg0,
  487. arg1
  488. );
  489. }
  490. return CompilationMode.Dynamic(
  491. Binders.BinaryOperationBinder(
  492. PyContext,
  493. operation
  494. ),
  495. resultType,
  496. arg0,
  497. arg1
  498. );
  499. }
  500. internal MSAst.Expression/*!*/ Set(string/*!*/ name, MSAst.Expression/*!*/ target, MSAst.Expression/*!*/ value) {
  501. return new PythonDynamicExpression2(
  502. PyContext.SetMember(
  503. name
  504. ),
  505. CompilationMode,
  506. target,
  507. value
  508. );
  509. }
  510. internal MSAst.Expression/*!*/ Get(string/*!*/ name, MSAst.Expression/*!*/ target) {
  511. return new DynamicGetMemberExpression(PyContext.GetMember(name), _mode, target, LocalContext);
  512. }
  513. internal MSAst.Expression/*!*/ Delete(Type/*!*/ resultType, string/*!*/ name, MSAst.Expression/*!*/ target) {
  514. return CompilationMode.Dynamic(
  515. PyContext.DeleteMember(
  516. name
  517. ),
  518. resultType,
  519. target
  520. );
  521. }
  522. internal MSAst.Expression/*!*/ GetIndex(MSAst.Expression/*!*/[]/*!*/ expressions) {
  523. return new PythonDynamicExpressionN(
  524. PyContext.GetIndex(
  525. expressions.Length
  526. ),
  527. CompilationMode,
  528. expressions
  529. );
  530. }
  531. internal MSAst.Expression/*!*/ GetSlice(MSAst.Expression/*!*/[]/*!*/ expressions) {
  532. return new PythonDynamicExpressionN(
  533. PyContext.GetSlice,
  534. CompilationMode,
  535. expressions
  536. );
  537. }
  538. internal MSAst.Expression/*!*/ SetIndex(MSAst.Expression/*!*/[]/*!*/ expressions) {
  539. return new PythonDynamicExpressionN(
  540. PyContext.SetIndex(
  541. expressions.Length - 1
  542. ),
  543. CompilationMode,
  544. expressions
  545. );
  546. }
  547. internal MSAst.Expression/*!*/ SetSlice(MSAst.Expression/*!*/[]/*!*/ expressions) {
  548. return new PythonDynamicExpressionN(
  549. PyContext.SetSliceBinder,
  550. CompilationMode,
  551. expressions
  552. );
  553. }
  554. internal MSAst.Expression/*!*/ DeleteIndex(MSAst.Expression/*!*/[]/*!*/ expressions) {
  555. return CompilationMode.Dynamic(
  556. PyContext.DeleteIndex(
  557. expressions.Length
  558. ),
  559. typeof(void),
  560. expressions
  561. );
  562. }
  563. internal MSAst.Expression/*!*/ DeleteSlice(MSAst.Expression/*!*/[]/*!*/ expressions) {
  564. return new PythonDynamicExpressionN(
  565. PyContext.DeleteSlice,
  566. CompilationMode,
  567. expressions
  568. );
  569. }
  570. #endregion
  571. #region Lookup Rewriting
  572. /// <summary>
  573. /// Rewrites the tree for performing lookups against globals instead of being bound
  574. /// against the optimized scope. This is used if the user compiles optimied code and then
  575. /// runs it against a different scope.
  576. /// </summary>
  577. internal PythonAst MakeLookupCode() {
  578. //Debug.Assert(false);
  579. PythonAst res = (PythonAst)MemberwiseClone();
  580. res._mode = CompilationMode.Lookup;
  581. res._contextInfo = null;
  582. // update the top-level globals for class/funcs accessing __name__, __file__, etc...
  583. Dictionary<PythonVariable, MSAst.Expression> newGlobals = new Dictionary<PythonVariable, MSAst.Expression>();
  584. foreach (var v in _globalVariables) {
  585. newGlobals[v.Key] = CompilationMode.Lookup.GetGlobal(_globalContext, -1, v.Key, null);
  586. }
  587. res._globalVariables = newGlobals;
  588. res._body = new RewrittenBodyStatement(_body, new LookupVisitor(res, GetGlobalContext()).Visit(_body));
  589. return res;
  590. }
  591. internal class RewrittenBodyStatement : Statement {
  592. private readonly MSAst.Expression _body;
  593. private readonly string _doc;
  594. private readonly Statement _originalBody;
  595. public RewrittenBodyStatement(Statement originalBody, MSAst.Expression body) {
  596. _body = body;
  597. _doc = originalBody.Documentation;
  598. _originalBody = originalBody;
  599. }
  600. public override MSAst.Expression Reduce() {
  601. return _body;
  602. }
  603. public override string Documentation {
  604. get {
  605. return _doc;
  606. }
  607. }
  608. public override void Walk(PythonWalker walker) {
  609. _originalBody.Walk(walker);
  610. }
  611. }
  612. internal class LookupVisitor : MSAst.ExpressionVisitor {
  613. private readonly MSAst.Expression _globalContext;
  614. private ScopeStatement _curScope;
  615. public LookupVisitor(PythonAst ast, MSAst.Expression globalContext) {
  616. _globalContext = globalContext;
  617. _curScope = ast;
  618. }
  619. protected override MSAst.Expression VisitMember(MSAst.MemberExpression node) {
  620. if (node == _globalContext) {
  621. return PythonAst._globalContext;
  622. }
  623. return base.VisitMember(node);
  624. }
  625. protected override MSAst.Expression VisitExtension(MSAst.Expression node) {
  626. if (node == _globalContext) {
  627. return PythonAst._globalContext;
  628. }
  629. // we need to re-write nested scoeps
  630. ScopeStatement scope = node as ScopeStatement;
  631. if (scope != null) {
  632. return base.VisitExtension(VisitScope(scope));
  633. }
  634. LambdaExpression lambda = node as LambdaExpression;
  635. if (lambda != null) {
  636. return base.VisitExtension(new LambdaExpression((FunctionDefinition)VisitScope(lambda.Function)));
  637. }
  638. // update the global get/set/raw gets variables
  639. PythonGlobalVariableExpression global = node as PythonGlobalVariableExpression;
  640. if (global != null) {
  641. return new LookupGlobalVariable(
  642. _curScope == null ? PythonAst._globalContext : _curScope.LocalContext,
  643. global.Variable.Name,
  644. global.Variable.Kind == VariableKind.Local
  645. );
  646. }
  647. // set covers sets and deletes
  648. var setGlobal = node as PythonSetGlobalVariableExpression;
  649. if (setGlobal != null) {
  650. if (setGlobal.Value == PythonGlobalVariableExpression.Uninitialized) {
  651. return new LookupGlobalVariable(
  652. _curScope == null ? PythonAst._globalContext : _curScope.LocalContext,
  653. setGlobal.Global.Variable.Name,
  654. setGlobal.Global.Variable.Kind == VariableKind.Local
  655. ).Delete();
  656. } else {
  657. return new LookupGlobalVariable(
  658. _curScope == null ? PythonAst._globalContext : _curScope.LocalContext,
  659. setGlobal.Global.Variable.Name,
  660. setGlobal.Global.Variable.Kind == VariableKind.Local
  661. ).Assign(Visit(setGlobal.Value));
  662. }
  663. }
  664. var rawValue = node as PythonRawGlobalValueExpression;
  665. if (rawValue != null) {
  666. return new LookupGlobalVariable(
  667. _curScope == null ? PythonAst._globalContext : _curScope.LocalContext,
  668. rawValue.Global.Variable.Name,
  669. rawValue.Global.Variable.Kind == VariableKind.Local
  670. );
  671. }
  672. return base.VisitExtension(node);
  673. }
  674. private ScopeStatement VisitScope(ScopeStatement scope) {
  675. var newScope = scope.CopyForRewrite();
  676. ScopeStatement prevScope = _curScope;
  677. try {
  678. // rewrite the method body
  679. _curScope = newScope;
  680. newScope.Parent = prevScope;
  681. newScope.RewriteBody(this);
  682. } finally {
  683. _curScope = prevScope;
  684. }
  685. return newScope;
  686. }
  687. }
  688. #endregion
  689. internal override string ProfilerName {
  690. get {
  691. if (_mode == CompilationMode.Lookup) {
  692. return NameForExec;
  693. }
  694. if (_name.IndexOfAny(System.IO.Path.GetInvalidPathChars()) >= 0) {
  695. return "module " + _name;
  696. } else {
  697. return "module " + System.IO.Path.GetFileNameWithoutExtension(_name);
  698. }
  699. }
  700. }
  701. }
  702. }