So this is awesome by the way. I added the import and casting-to-an-interface code back in and it works like a charm. I'm generating python code purely via AST!
On Thu, Apr 15, 2010 at 1:25 PM, Justin Chase <justin.m.ch...@gmail.com>wrote: > SUCCESS! > > Here's the final code: > var runtime = Python.CreateRuntime(); > > var functionDefinition = new FunctionDefinition( > "Do", > new[] { new Parameter("self") }, > new ReturnStatement(new ConstantExpression("hello python!"))); > > var classDefinition = new IronPython.Compiler.Ast.ClassDefinition( > "Example", > new Expression[] { }, > functionDefinition); > > dynamic python = runtime.Compile(classDefinition); > dynamic example = python.Example(); > > Console.WriteLine(example.Do()); > Console.ReadKey(true); > > public static class DLRHelper > { > public static dynamic Compile(this ScriptRuntime runtime, params > Statement[] statements) > { > var engine = runtime.GetEngineByFileExtension(".py"); > var context = (PythonContext)HostingHelpers.GetLanguageContext(engine); > > var globals = new PythonDictionary(); > globals.Add("__name__", "<dynamic>"); > > var options = new PythonCompilerOptions(ModuleOptions.ExecOrEvalCode); > var unit = new SourceUnit(context, NullTextContentProvider.Null, "", > SourceCodeKind.AutoDetect); > > var moduleContext = new ModuleContext(globals, context); > var codeContext = moduleContext.GlobalContext; > var pythonAst = new PythonAst( > new IronPython.Compiler.Ast.SuiteStatement(statements), > false, > ModuleOptions.ExecOrEvalCode, > false, > new CompilerContext( > unit, > options, > ErrorSink.Default)); > > pythonAst.Walk(new EnsureLocWalker()); > > pythonAst.Bind(); > var lambda = (System.Linq.Expressions.LambdaExpression)pythonAst.Reduce(); > var func = (Func<CodeContext, FunctionCode, object>)lambda.Compile(); > var result = func(codeContext, null); // result is null > > return HostingHelpers.CreateScriptScope(engine, codeContext.GlobalScope); > } > > // I created a walker called EnsureLocWalker that overrides all Walk > methods and calls SetLoc to new SourceSpan(new SourceLocation(1, 1, 1), new > SourceLocation(2, 2, 2)); > // and header when appropriate to new SourceLocation(1, 1, 1) > } > > > FYI your WithStatement, TryStatement and ForStatement are missing getters > on their header property. That's frustrating. I want to be able to do this: > > if (node.Header == SourceLocation.Invalid) > node.Header = new SourceLocation(1, 1, 1); > > Also it would be nice if the headers and locations were completely ignored > if they're invalid instead of throwing exceptions. Also it would be *reaaaally > *nice if you had a Walk(Node node) override on the PythonWalker. So you > could do something to all nodes. Also, why have a million overrides for > this? Can't you just make a generic PythonWalker? Then just have a single > Walk(T node) and AfterWalk(T node). That would be a lot less gross. > > The reason why I want to do this is because I am working on a DSL tool ( > http://metasharp.codeplex.com) where I'm compiling down into an AST. > Currently I have transforms to create CodeDom objects and linq Expression > objects but I lack the ability to dynamically create Types or directly > generate IL. Using this I think i can save a TON of work for myself. > > Thanks for all the help! > > > On Wed, Apr 14, 2010 at 6:21 PM, Dino Viehland <di...@microsoft.com>wrote: > >> Try calling SetLoc on the FunctionDefinition and also try setting the >> Header property. I think if it’s some reasonable span it’ll work. >> >> >> >> *From:* users-boun...@lists.ironpython.com [mailto: >> users-boun...@lists.ironpython.com] *On Behalf Of *Justin Chase >> *Sent:* Wednesday, April 14, 2010 3:35 PM >> >> *To:* Discussion of IronPython >> *Subject:* Re: [IronPython] Building via AST >> >> >> >> Ok awesome! >> >> >> >> So now I have: >> >> dynamic example = globals["Example"]; >> >> dynamic instance = example(); >> >> Console.WriteLine(instance.Do()); >> >> >> >> But I'm getting an exception about a line number. Any idea how I can get >> past that? I've tried a bunch of things but I'm not sure what's going on. >> >> >> >> ArgumentOutOfRangeException >> >> Specified argument was out of the range of valid values. Parameter name: >> line must be greater than or equal to 1 >> >> at Microsoft.Scripting.SourceLocation.ValidateLocation(Int32 index, >> Int32 line, Int32 column) >> >> at Microsoft.Scripting.SourceLocation..ctor(Int32 index, Int32 line, >> Int32 column) >> >> at IronPython.Compiler.Ast.FunctionDefinition.CreateFunctionLambda() >> >> at IronPython.Compiler.Ast.FunctionDefinition.EnsureFunctionLambda() >> >> at IronPython.Compiler.Ast.FunctionDefinition.GetLambda() >> >> at IronPython.Runtime.FunctionCode.get_Code() >> >> at IronPython.Runtime.FunctionCode.GetGeneratorOrNormalLambda() >> >> at IronPython.Runtime.FunctionCode.UpdateDelegate(PythonContext >> context, Boolean forceCreation) >> >> at >> IronPython.Runtime.FunctionCode.LazyCompileFirstTarget(PythonFunction >> function) >> >> at >> IronPython.Compiler.PythonCallTargets.OriginalCallTarget1(PythonFunction >> function, Object arg0) >> >> at IronPython.Runtime.PythonFunction.FunctionCaller`1.Call1(CallSite >> site, CodeContext context, Object func, T0 arg0) >> >> at >> System.Dynamic.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet](CallSite >> site, T0 arg0, T1 arg1, T2 arg2) >> >> at CallSite.Target(Closure , CallSite , Object ) >> >> at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite >> site, T0 arg0) >> >> at CallSite.Target(Closure , CallSite , Object ) >> >> at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite >> site, T0 arg0) >> >> >> >> >> >> On Wed, Apr 14, 2010 at 3:32 PM, Dino Viehland <di...@microsoft.com> >> wrote: >> >> 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(), >> >> moduleContext); >> >> >> >> with: >> >> 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-boun...@lists.ironpython.com [mailto: >> users-boun...@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(); >> >> >> runtime.LoadAssembly(typeof(IExample).Assembly); >> >> >> >> 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(), >> >> moduleContext); >> >> >> >> var classDefinition = new >> IronPython.Compiler.Ast.ClassDefinition( >> >> "Example", >> >> new Expression[] { }, >> >> new FunctionDefinition( >> >> "Do", >> >> new[] { new >> Parameter("self") }, >> >> new >> ReturnStatement(new ConstantExpression("hello python!")))); >> >> >> >> var pythonAst = new PythonAst( >> >> new >> IronPython.Compiler.Ast.SuiteStatement(new Statement[] { /* import, */ >> classDefinition }), >> >> false, >> >> >> ModuleOptions.ExecOrEvalCode, >> >> false, >> >> new CompilerContext( >> >> unit, >> >> options, >> >> new >> ThrowsErrorSink())); >> >> >> >> pythonAst.Bind(); >> >> 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.* >> >> Console.WriteLine(example.Do()); >> >> Console.ReadKey(true); >> >> >> >> >> >> 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.ch...@gmail.com> >> wrote: >> >> Awesome. I will thanks. >> >> On Apr 12, 2010 7:49 PM, "Dino Viehland" <di...@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! J >> >> >> >> *From:* users-boun...@lists.ironpython.com [mailto: >> users-boun...@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@lists.ironpython.com >> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com >> >> >> >> >> -- >> Justin Chase >> http://www.justnbusiness.com >> >> >> _______________________________________________ >> Users mailing list >> Users@lists.ironpython.com >> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com >> >> >> >> >> -- >> Justin Chase >> http://www.justnbusiness.com >> >> _______________________________________________ >> Users mailing list >> Users@lists.ironpython.com >> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com >> >> > > > -- > Justin Chase > http://www.justnbusiness.com > -- Justin Chase http://www.justnbusiness.com
_______________________________________________ Users mailing list Users@lists.ironpython.com http://lists.ironpython.com/listinfo.cgi/users-ironpython.com