[IronPython] Building via AST

Dino Viehland dinov at microsoft.com
Wed Apr 14 22:32:23 CEST 2010

The problem here is just that you actually have a nested code context when for the top-level code you just need a single global context.  Replace the line:

                                    var codeContext = new CodeContext(
                                                new PythonDictionary(),

var codeContext = moduleContext.GlobalContext;

and it’ll work.  The nested code context that you’re creating is only used for when we’re inside of a function definition or a class definition.

Also you can avoid creating the script scope and just pull Example out of the globals dictionary as well.

From: users-bounces at lists.ironpython.com [mailto:users-bounces at lists.ironpython.com] On Behalf Of Justin Chase
Sent: Wednesday, April 14, 2010 11:24 AM
To: Discussion of IronPython
Subject: Re: [IronPython] Building via AST

I feel like I'm sooooo close but something isn't quite working. Here is my current code:

                                  var runtime = Python.CreateRuntime();

                                  var engine = runtime.GetEngineByFileExtension(".py");
                                  var context = (PythonContext)HostingHelpers.GetLanguageContext(engine);

                                  var globals = new PythonDictionary();
                                  globals.Add("__name__", "<test>"); // I get an exception without this.

                                  var options = new PythonCompilerOptions(ModuleOptions.ExecOrEvalCode | ModuleOptions.Initialize);
                                  var unit = new SourceUnit(context, NullTextContentProvider.Null, "", SourceCodeKind.Statements);

                                  var moduleContext = new ModuleContext(globals, context);
                                  var codeContext = new CodeContext(
                                              new PythonDictionary(),

                                  var classDefinition = new IronPython.Compiler.Ast.ClassDefinition(
                                              new Expression[] { },
                                              new FunctionDefinition(
                                                          new[] { new Parameter("self") },
                                                          new ReturnStatement(new ConstantExpression("hello python!"))));

                                  var pythonAst = new PythonAst(
                                              new IronPython.Compiler.Ast.SuiteStatement(new Statement[] { /* import, */ classDefinition }),
                                              new CompilerContext(
                                                          new ThrowsErrorSink()));

                                  var lambda = (System.Linq.Expressions.LambdaExpression)pythonAst.Reduce();
                                  var func = (Func<CodeContext, FunctionCode, object>)lambda.Compile();
                                  var result = func(codeContext, null); // result is null

                                  dynamic python = HostingHelpers.CreateScriptScope(engine, moduleContext.GlobalScope);
                                  dynamic example = python.Example(); // fails! Example is not in scope.

Can anyone tell me what I'm missing? This has got to be pretty close.

On Mon, Apr 12, 2010 at 7:51 PM, Justin Chase <justin.m.chase at gmail.com<mailto:justin.m.chase at gmail.com>> wrote:

Awesome.  I will thanks.
On Apr 12, 2010 7:49 PM, "Dino Viehland" <dinov at microsoft.com<mailto:dinov at microsoft.com>> wrote:
This might be possible.  If you wrap this all up in a PythonAst object (calling the constructor which takes a CompilerContext), call Bind on it then you should get a LambdaExpression back out.  You can Compile() on that.

But it’s not like this is well traveled territory and this only applies to 2.6.1 (before that the trees weren’t DLR ASTs so they weren’t reducable).  When we do this ourselves we also call the produced delegate and flow in some data.  The delegate is going to want at least a FunctionCode object as an argument but I think you could get away with passing null (at least as long as no exceptions are thrown).  The delegate might also want a CodeContext object as well depending on the compilation mode we end up using (which is based on the CompilerContext you give us).  This you wouldn’t be able to get away w/ passing null.  But you can get one by doing new ModuleContext(new PythonDictionary(), pythonContext).GlobalContext.  The HostingHelpers class can give you a LanguageContext from the ScriptEngine for Python which you can cast to a PythonContext.

Let me know if it works! ☺

From: users-bounces at lists.ironpython.com<mailto:users-bounces at lists.ironpython.com> [mailto:users-bounces at lists.ironpython.com<mailto:users-bounces at lists.ironpython.com>] On Behalf Of Justin Chase
Sent: Monday, April 12, 2010 4:09 PM

To: Discussion of IronPython Subject: Re: [IronPython] Building via AST

  Ok, so at risk of being a nuissance I have one last question because I feel like I'm half way t...

Users mailing list
Users at lists.ironpython.com<mailto:Users at lists.ironpython.com>

Justin Chase
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/ironpython-users/attachments/20100414/cd4c06e0/attachment.html>

More information about the Ironpython-users mailing list