HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros 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  // evaluateInContext() is the same as evaluate() except it uses the
98  // local and global dictionaries from the context passed to it. This
99  // way, any code run won't set variables in the __main__ module's global
100  // dictionary. It is inlined for speed.
102  PY_Result::Type desired_result_type,
103  PY_EvaluationContext &context,
104  PY_Result &result) const
105  {
106  PY_InterpreterAutoLock auto_lock;
107  evaluateUsingDicts(desired_result_type,
108  context.myOpaqueGlobalsDict, context.myOpaqueGlobalsDict, result);
109  }
110 
111  // Similar to the above, but an additional local variable dictionary can
112  // be passed in. This is used along with the global dictionary from the
113  // context.
115  PY_Result::Type desired_result_type,
116  PY_EvaluationContext &context,
117  void* opaque_locals_dict,
118  PY_Result &result) const
119  {
120  PY_InterpreterAutoLock auto_lock;
121  evaluateUsingDicts(desired_result_type,
122  context.myOpaqueGlobalsDict, opaque_locals_dict, result);
123  }
124 
125  // These convenience versions of evaluate() and evaluateInContext() return
126  // the PY_Result by value, instead of passing it in by reference.
127  // These versions can be used by code that isn't performance-critical.
128  PY_Result evaluate(PY_Result::Type desired_result_type) const
129  {
130  PY_Result result;
131  evaluate(desired_result_type, result);
132  return result;
133  }
134 
136  PY_Result::Type desired_result_type,
137  PY_EvaluationContext &context) const
138  {
139  PY_Result result;
140  evaluateInContext(desired_result_type, context, result);
141  return result;
142  }
143 
144  inline bool isPureCompiled()
145  {
146  return !myCode.isstring() && !mySyntaxErrors.isstring() && myOpaqueCodeObject;
147  }
148 
149 private:
150  PY_CompiledCode(const PY_CompiledCode &); // unimplemented
151 
152  void initializeThreadInfoAndEvalCache();
153 
154  PY_Result evaluateUsingDicts(
155  PY_Result::Type desired_result_type,
156  void *opaque_globals_dict,
157  void *opaque_locals_dict) const;
158  void evaluateUsingDicts(
159  PY_Result::Type desired_result_type,
160  void *opaque_globals_dict,
161  void *opaque_locals_dict,
162  PY_Result &result) const;
163 
164  int startInterruptableEvaluation() const;
165  void endInterruptableEvaluation(int id) const;
166 
167  void *myOpaqueCodeObject;
168  CodeType myCodeType;
169  UT_String myCode;
170  UT_String mySyntaxErrors;
171 
172 #ifndef ALLOW_DIFFERENT_CONSTRUCTOR_AND_EVAL_THREADS
173  UT_ValArray<PY_EvaluationCache *> *myEvaluationCacheStack;
174 #endif
175  mutable PY_EvaluationCache *myEvaluationCache;
176 };
177 
178 #endif
void evaluateInContext(PY_Result::Type desired_result_type, PY_EvaluationContext &context, void *opaque_locals_dict, PY_Result &result) 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
long long int64
Definition: SYS_Types.h:106
#define PY_API
Definition: PY_API.h:10
PY_Result evaluate(PY_Result::Type desired_result_type) const