HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PY_CompiledCode.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * COMMENTS:
7  * This class represents a compiled piece of python code that
8  * can be evaluated.
9  */
10 
11 #ifndef __PY_CompiledCode_h__
12 #define __PY_CompiledCode_h__
13 
14 #include "PY_API.h"
15 #include "PY_Result.h"
16 #include "PY_InterpreterAutoLock.h"
17 #include "PY_EvaluationContext.h"
18 #include <UT/UT_String.h>
19 #include <iosfwd>
20 class PY_EvaluationCache;
21 class UT_IStream;
22 
23 #define ALLOW_DIFFERENT_CONSTRUCTOR_AND_EVAL_THREADS
24 
26 {
27 public:
28  enum CodeType { STATEMENTS, EXPRESSION };
29 
30  // Python code can be compiled as either an expression or a (list of)
31  // statements. Statements do not return anything -- even if the last
32  // statement is an expression, evaluating code as statements will never
33  // return a value. See the compile() python builtin for more information;
34  // expressions correspond to 'eval' and statements correspond to 'exec'.
35  //
36  // The python code is compiled when this class is instanced. Check
37  // for syntax errors with hasSyntaxErrors() and syntaxErrors(). You
38  // can always access the code regardless of whether or not there were
39  // syntax errors.
40  //
41  // as_file is the file name used when reporting syntax errors.
42  //
43  // If allow_function_bodies is true, code_type is EXPRESSION, and the
44  // Python code contains multiple lines, it will be interpreted as the
45  // body of a Python expression.
46  //
47  // NOTE: It's important to call the evaluate*() methods from the
48  // same thread from which this object is constructed.
50  const char *python_code,
51  CodeType code_type,
52  const char *as_file = NULL,
53  bool allow_function_bodies = false);
54 
55  // This constructor reads in compiled python code from a stream.
57  UT_IStream &is,
58  CodeType code_type);
59 
60  ~PY_CompiledCode();
61 
62  // Normally this is called from PY_CompiledCode's constructor.
63  // If you create this class in one thread but then evaluate it from a
64  // different thread, then you need to call this from the other thread prior
65  // to evaluation in order to ensure that the correct evaluation cache stack
66  // is used.
67  void setEvaluationCacheStackForCurrentThread();
68 
69  // This can't get the size of any compiled code object from
70  // Python, but can still count this, its strings, and its
71  // evaluation cache.
72  int64 getMemoryUsage(bool inclusive) const;
73 
74  // The syntax errors will be empty if there are none.
75  bool hasSyntaxErrors() const;
76  const UT_String &syntaxErrors() const;
77 
78  // Get the code that was compiled.
79  const UT_String &code() const;
80 
81  // Use marchalling to convert the compiled code object to a string.
82  // We use a UT_WorkBuffer because the returned string may have null
83  // characters in it.
84  void compiledCodeAsString(UT_WorkBuffer &result) const;
85 
86  // This method saves the compiled form of our code.
87  bool saveCompiledCode(std::ostream &os);
88 
89  // Evaluate the compiled python code. The desired result type really
90  // only has an effect if the compiled code is an expression.
91  //
92  // Evaluating code that had syntax errors will set the result type to
93  // PY_ResultType::ERR, with the string containing the syntax errors.
94  void evaluate(
95  PY_Result::Type desired_result_type, PY_Result &result) const;
96 
97  // Evaluate using a custom dictionary for both the global and local
98  // dictionary
100  PY_Result::Type desired_result_type,
101  void* opaque_dict,
102  PY_Result &result) const
103  {
104  PY_InterpreterAutoLock auto_lock;
105  evaluateUsingDicts(desired_result_type,
106  opaque_dict, opaque_dict, result);
107  }
108 
109  // evaluateInContext() is the same as evaluate() except it uses the
110  // local and global dictionaries from the context passed to it. This
111  // way, any code run won't set variables in the __main__ module's global
112  // dictionary. It is inlined for speed.
114  PY_Result::Type desired_result_type,
116  PY_Result &result) const
117  {
118  PY_InterpreterAutoLock auto_lock;
119  evaluateUsingDicts(desired_result_type,
120  context.myOpaqueGlobalsDict, context.myOpaqueGlobalsDict, result);
121  }
122 
123  // Similar to the above, but an additional local variable dictionary can
124  // be passed in. This is used along with the global dictionary from the
125  // context.
127  PY_Result::Type desired_result_type,
129  void* opaque_locals_dict,
130  PY_Result &result) const
131  {
132  PY_InterpreterAutoLock auto_lock;
133  evaluateUsingDicts(desired_result_type,
134  context.myOpaqueGlobalsDict, opaque_locals_dict, result);
135  }
136 
137  // These convenience versions of evaluate() and evaluateInContext() return
138  // the PY_Result by value, instead of passing it in by reference.
139  // These versions can be used by code that isn't performance-critical.
140  PY_Result evaluate(PY_Result::Type desired_result_type) const
141  {
143  evaluate(desired_result_type, result);
144  return result;
145  }
146 
148  PY_Result::Type desired_result_type,
150  {
152  evaluateInContext(desired_result_type, context, result);
153  return result;
154  }
155 
156  inline bool isPureCompiled()
157  {
158  return !myCode.isstring() && !mySyntaxErrors.isstring() && myOpaqueCodeObject;
159  }
160 
161  inline CodeType codeType() const
162  {
163  return myCodeType;
164  }
165 
166 private:
167  PY_CompiledCode(const PY_CompiledCode &); // unimplemented
168 
169  void initializeThreadInfoAndEvalCache();
170 
171  PY_Result evaluateUsingDicts(
172  PY_Result::Type desired_result_type,
173  void *opaque_globals_dict,
174  void *opaque_locals_dict) const;
175  void evaluateUsingDicts(
176  PY_Result::Type desired_result_type,
177  void *opaque_globals_dict,
178  void *opaque_locals_dict,
179  PY_Result &result) const;
180 
181  int startInterruptableEvaluation() const;
182  void endInterruptableEvaluation(int id) const;
183 
184  void *myOpaqueCodeObject;
185  CodeType myCodeType;
186  UT_String myCode;
187  UT_String mySyntaxErrors;
188 
189 #ifndef ALLOW_DIFFERENT_CONSTRUCTOR_AND_EVAL_THREADS
190  UT_ValArray<PY_EvaluationCache *> *myEvaluationCacheStack;
191 #endif
192  mutable PY_EvaluationCache *myEvaluationCache;
193 };
194 
195 #endif
void evaluateInContext(PY_Result::Type desired_result_type, PY_EvaluationContext &context, void *opaque_locals_dict, PY_Result &result) const
CodeType codeType() const
void evaluateInContext(PY_Result::Type desired_result_type, PY_EvaluationContext &context, PY_Result &result) const
PY_Result evaluateInContext(PY_Result::Type desired_result_type, PY_EvaluationContext &context) const
#define PY_API
Definition: PY_API.h:10
long long int64
Definition: SYS_Types.h:116
void evaluateWithDict(PY_Result::Type desired_result_type, void *opaque_dict, PY_Result &result) const
PY_Result evaluate(PY_Result::Type desired_result_type) const
GLuint64EXT * result
Definition: glew.h:14007