mirror of https://github.com/KLayout/klayout.git
Merge pull request #937 from KLayout/more-macro-bindings
More macro bindings
This commit is contained in:
commit
91d358398b
|
|
@ -22,12 +22,24 @@
|
|||
|
||||
|
||||
#include "gsiDeclBasic.h"
|
||||
#include "gsiInterpreter.h"
|
||||
#include "gsiDecl.h"
|
||||
#include "tlTypeTraits.h"
|
||||
|
||||
namespace tl
|
||||
{
|
||||
template <> struct type_traits<gsi::Interpreter>
|
||||
: tl::type_traits<void>
|
||||
{
|
||||
typedef false_tag has_copy_constructor;
|
||||
typedef false_tag has_default_constructor;
|
||||
typedef false_tag has_public_destructor;
|
||||
};
|
||||
}
|
||||
|
||||
namespace gsi
|
||||
{
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
// A generic value wrapper that allows wrapping a plain data type into an object
|
||||
|
||||
|
|
@ -66,4 +78,83 @@ Class<Value> decl_Value ("tl", "Value",
|
|||
"This class has been introduced in version 0.22."
|
||||
);
|
||||
|
||||
static void eval_string_impl (Interpreter *ip, const char *string, const char *filename, int line)
|
||||
{
|
||||
ip->eval_string (string, filename, line);
|
||||
}
|
||||
|
||||
static tl::Variant eval_expr_impl (Interpreter *ip, const char *string, const char *filename, int line)
|
||||
{
|
||||
return ip->eval_expr (string, filename, line);
|
||||
}
|
||||
|
||||
static void define_variable_impl (Interpreter *ip, const std::string &name, const tl::Variant &value)
|
||||
{
|
||||
ip->define_variable (name, value);
|
||||
}
|
||||
|
||||
static gsi::Interpreter *interpreter_by_name (const std::string &name)
|
||||
{
|
||||
for (tl::Registrar<gsi::Interpreter>::iterator i = gsi::interpreters.begin (); i != gsi::interpreters.end (); ++i) {
|
||||
if (i.current_name () == name) {
|
||||
return i->available () ? i.operator-> () : 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gsi::Interpreter *python_interpreter ()
|
||||
{
|
||||
return interpreter_by_name ("pya");
|
||||
}
|
||||
|
||||
static gsi::Interpreter *ruby_interpreter ()
|
||||
{
|
||||
return interpreter_by_name ("rba");
|
||||
}
|
||||
|
||||
Class<Interpreter> decl_Macro ("tl", "Interpreter",
|
||||
gsi::method ("load_file", &Interpreter::load_file, gsi::arg ("path"),
|
||||
"@brief Loads the given file into the interpreter\n"
|
||||
"This will execute the code inside the file.\n"
|
||||
) +
|
||||
gsi::method_ext ("eval_string", &eval_string_impl, gsi::arg ("string"), gsi::arg ("filename", (const char *) 0, "nil"), gsi::arg ("line", 1),
|
||||
"@brief Executes the code inside the given string\n"
|
||||
"Use 'filename' and 'line' to indicate the original source for the error messages.\n"
|
||||
) +
|
||||
gsi::method_ext ("eval_expr", &eval_expr_impl, gsi::arg ("string"), gsi::arg ("filename", (const char *) 0, "nil"), gsi::arg ("line", 1),
|
||||
"@brief Executes the expression inside the given string and returns the result value\n"
|
||||
"Use 'filename' and 'line' to indicate the original source for the error messages.\n"
|
||||
) +
|
||||
gsi::method_ext ("define_variable", &define_variable_impl, gsi::arg ("name"), gsi::arg ("value"),
|
||||
"@brief Defines a (global) variable with the given name and value\n"
|
||||
"You can use the \\Value class to provide 'out' or 'inout' parameters which can be modified by code executed inside the interpreter and read back by the caller."
|
||||
) +
|
||||
gsi::method ("python_interpreter", &python_interpreter,
|
||||
"@brief Gets the instance of the Python interpreter\n"
|
||||
) +
|
||||
gsi::method ("ruby_interpreter", &ruby_interpreter,
|
||||
"@brief Gets the instance of the Ruby interpreter\n"
|
||||
),
|
||||
"@brief A generalization of script interpreters\n"
|
||||
"The main purpose of this class is to provide cross-language call options. "
|
||||
"Using the Python interpreter, it is possible to execute Python code from Ruby for example.\n"
|
||||
"\n"
|
||||
"The following example shows how to use the interpreter class to execute Python code from Ruby "
|
||||
"and how to pass values from Ruby to Python and back using the \\Value wrapper object:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"pya = RBA::Interpreter::python_interpreter\n"
|
||||
"out_param = RBA::Value::new(17)\n"
|
||||
"pya.define_variable(\"out_param\", out_param)\n"
|
||||
"pya.eval_string(<<END)\n"
|
||||
"print(\"This is Python now!\")\n"
|
||||
"out_param.value = out_param.value + 25\n"
|
||||
"END\n"
|
||||
"puts out_param.value # gives '42'"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"This class was introduced in version 0.27.5.\n"
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <iostream>
|
||||
|
||||
#include "tlVariant.h"
|
||||
#include "gsiObject.h"
|
||||
|
||||
namespace gsi
|
||||
{
|
||||
|
|
@ -38,6 +39,7 @@ namespace gsi
|
|||
* @brief Provides a basic implementation for a "boxed" plain value using a Variant as the basic type
|
||||
*/
|
||||
class GSI_PUBLIC Value
|
||||
: public gsi::ObjectBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "tlScriptError.h"
|
||||
#include "tlClassRegistry.h"
|
||||
#include "tlVariant.h"
|
||||
#include "gsiCommon.h"
|
||||
|
||||
namespace gsi
|
||||
|
|
@ -267,7 +268,7 @@ public:
|
|||
/**
|
||||
* @brief Defines a global variable with the given name and value
|
||||
*/
|
||||
virtual void define_variable (const std::string &name, const std::string &value) = 0;
|
||||
virtual void define_variable (const std::string &name, const tl::Variant &value) = 0;
|
||||
|
||||
/**
|
||||
* @brief Installs the given console for output
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "gsiDecl.h"
|
||||
#include "gsiDeclBasic.h"
|
||||
#include "gsiInterpreter.h"
|
||||
#include "gsiEnums.h"
|
||||
#include "lymMacroInterpreter.h"
|
||||
#include "lymMacro.h"
|
||||
#include "rba.h"
|
||||
|
|
@ -96,11 +97,11 @@ Class<gsi::MacroExecutionContext> decl_MacroExecutionContext ("lay", "MacroExecu
|
|||
"suppress exceptions when re-raising them."
|
||||
);
|
||||
|
||||
class MacroInterpreter
|
||||
class MacroInterpreterImpl
|
||||
: public lym::MacroInterpreter
|
||||
{
|
||||
public:
|
||||
MacroInterpreter ()
|
||||
MacroInterpreterImpl ()
|
||||
: lym::MacroInterpreter (),
|
||||
mp_registration (0), m_supports_include_expansion (true)
|
||||
{
|
||||
|
|
@ -111,7 +112,7 @@ public:
|
|||
m_debugger_scheme = lym::MacroInterpreter::debugger_scheme ();
|
||||
}
|
||||
|
||||
~MacroInterpreter ()
|
||||
~MacroInterpreterImpl ()
|
||||
{
|
||||
delete mp_registration;
|
||||
mp_registration = 0;
|
||||
|
|
@ -161,9 +162,9 @@ public:
|
|||
return m_supports_include_expansion;
|
||||
}
|
||||
|
||||
void set_storage_scheme (int scheme)
|
||||
void set_storage_scheme (lym::Macro::Format scheme)
|
||||
{
|
||||
m_storage_scheme = lym::Macro::Format (scheme);
|
||||
m_storage_scheme = scheme;
|
||||
}
|
||||
|
||||
virtual lym::Macro::Format storage_scheme () const
|
||||
|
|
@ -171,9 +172,9 @@ public:
|
|||
return m_storage_scheme;
|
||||
}
|
||||
|
||||
void set_debugger_scheme (int scheme)
|
||||
void set_debugger_scheme (lym::Macro::Interpreter scheme)
|
||||
{
|
||||
m_debugger_scheme = lym::Macro::Interpreter (scheme);
|
||||
m_debugger_scheme = scheme;
|
||||
}
|
||||
|
||||
virtual lym::Macro::Interpreter debugger_scheme () const
|
||||
|
|
@ -256,50 +257,58 @@ private:
|
|||
bool m_supports_include_expansion;
|
||||
};
|
||||
|
||||
int const_PlainTextFormat ()
|
||||
{
|
||||
return int (lym::Macro::PlainTextFormat);
|
||||
}
|
||||
|
||||
int const_PlainTextWithHashAnnotationsFormat ()
|
||||
{
|
||||
return int (lym::Macro::PlainTextWithHashAnnotationsFormat);
|
||||
}
|
||||
|
||||
int const_MacroFormat ()
|
||||
{
|
||||
return int (lym::Macro::MacroFormat);
|
||||
}
|
||||
|
||||
int const_RubyDebugger ()
|
||||
{
|
||||
return int (lym::Macro::Ruby);
|
||||
}
|
||||
|
||||
int const_NoDebugger ()
|
||||
{
|
||||
return int (lym::Macro::None);
|
||||
}
|
||||
|
||||
Class<gsi::MacroInterpreter> decl_MacroInterpreter ("lay", "MacroInterpreter",
|
||||
gsi::method ("PlainTextFormat", &const_PlainTextFormat,
|
||||
"@brief Indicates plain text format for \\storage_scheme\n"
|
||||
gsi::EnumIn<lym::Macro, lym::Macro::Format> decl_FormatEnum ("lay", "Format",
|
||||
gsi::enum_const ("PlainTextFormat", lym::Macro::PlainTextFormat,
|
||||
"@brief The macro has plain text format"
|
||||
) +
|
||||
gsi::method ("PlainTextWithHashAnnotationsFormat", &const_PlainTextWithHashAnnotationsFormat,
|
||||
"@brief Indicates plain text format for \\storage_scheme\n"
|
||||
"This format is identical to \\PlainTextFormat but indicates that it is possible "
|
||||
"to insert annotations (properties) into the text in a hash-commented header."
|
||||
gsi::enum_const ("PlainTextWithHashAnnotationsFormat", lym::Macro::PlainTextWithHashAnnotationsFormat,
|
||||
"@brief The macro has plain text format with special pseudo-comment annotations"
|
||||
) +
|
||||
gsi::method ("MacroFormat", &const_MacroFormat,
|
||||
"@brief Indicates macro (XML) format for \\storage_scheme\n"
|
||||
gsi::enum_const ("MacroFormat", lym::Macro::MacroFormat,
|
||||
"@brief The macro has macro (XML) format"
|
||||
),
|
||||
"@brief Specifies the format of a macro\n"
|
||||
"This enum has been introduced in version 0.27.5."
|
||||
);
|
||||
|
||||
gsi::EnumIn<lym::Macro, lym::Macro::Interpreter> decl_InterpreterEnum ("lay", "Interpreter",
|
||||
gsi::enum_const ("Ruby", lym::Macro::Ruby,
|
||||
"@brief The interpreter is Ruby"
|
||||
) +
|
||||
gsi::enum_const ("Python", lym::Macro::Python,
|
||||
"@brief The interpreter is Python"
|
||||
) +
|
||||
gsi::enum_const ("Text", lym::Macro::Text,
|
||||
"@brief Plain text"
|
||||
) +
|
||||
gsi::enum_const ("DSLInterpreter", lym::Macro::DSLInterpreter,
|
||||
"@brief A domain-specific interpreter (DSL)"
|
||||
) +
|
||||
gsi::enum_const ("None", lym::Macro::None,
|
||||
"@brief No specific interpreter"
|
||||
),
|
||||
"@brief Specifies the interpreter used for executing a macro\n"
|
||||
"This enum has been introduced in version 0.27.5."
|
||||
);
|
||||
|
||||
lym::Macro::Interpreter const_RubyDebugger ()
|
||||
{
|
||||
return lym::Macro::Ruby;
|
||||
}
|
||||
|
||||
lym::Macro::Interpreter const_NoDebugger ()
|
||||
{
|
||||
return lym::Macro::None;
|
||||
}
|
||||
|
||||
Class<MacroInterpreterImpl> decl_MacroInterpreter ("lay", "MacroInterpreter",
|
||||
gsi::method ("RubyDebugger", &const_RubyDebugger,
|
||||
"@brief Indicates Ruby debugger for \\debugger_scheme\n"
|
||||
) +
|
||||
gsi::method ("NoDebugger", &const_NoDebugger,
|
||||
"@brief Indicates no debugging for \\debugger_scheme\n"
|
||||
) +
|
||||
gsi::method ("register", &MacroInterpreter::register_gsi, gsi::arg ("name"),
|
||||
gsi::method ("register", &MacroInterpreterImpl::register_gsi, gsi::arg ("name"),
|
||||
"@brief Registers the macro interpreter\n"
|
||||
"@param name The interpreter name. This is an arbitrary string which should be unique.\n"
|
||||
"\n"
|
||||
|
|
@ -307,7 +316,7 @@ Class<gsi::MacroInterpreter> decl_MacroInterpreter ("lay", "MacroInterpreter",
|
|||
"is set to 'dsl' can use this object to run the script. For executing a script, the system will "
|
||||
"call the interpreter's \\execute method.\n"
|
||||
) +
|
||||
gsi::method ("create_template", &MacroInterpreter::create_template, gsi::arg ("url"),
|
||||
gsi::method ("create_template", &MacroInterpreterImpl::create_template, gsi::arg ("url"),
|
||||
"@brief Creates a new macro template\n"
|
||||
"@param url The template will be initialized from that URL.\n"
|
||||
"\n"
|
||||
|
|
@ -317,7 +326,7 @@ Class<gsi::MacroInterpreter> decl_MacroInterpreter ("lay", "MacroInterpreter",
|
|||
"\n"
|
||||
"This method must be called after \\register has called.\n"
|
||||
) +
|
||||
gsi::method ("supports_include_expansion=", &MacroInterpreter::set_supports_include_expansion, gsi::arg ("flag"),
|
||||
gsi::method ("supports_include_expansion=", &MacroInterpreterImpl::set_supports_include_expansion, gsi::arg ("flag"),
|
||||
"@brief Sets a value indicating whether this interpreter supports the default include file expansion scheme.\n"
|
||||
"If this value is set to true (the default), lines like '# %include ...' will be substituted by the "
|
||||
"content of the file following the '%include' keyword.\n"
|
||||
|
|
@ -325,7 +334,7 @@ Class<gsi::MacroInterpreter> decl_MacroInterpreter ("lay", "MacroInterpreter",
|
|||
"\n"
|
||||
"This attribute has been introduced in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("syntax_scheme=", &gsi::MacroInterpreter::set_syntax_scheme, gsi::arg ("scheme"),
|
||||
gsi::method ("syntax_scheme=", &MacroInterpreterImpl::set_syntax_scheme, gsi::arg ("scheme"),
|
||||
"@brief Sets a string indicating the syntax highlighter scheme\n"
|
||||
"\n"
|
||||
"The scheme string can be empty (indicating no syntax highlighting), \"ruby\" for the Ruby syntax "
|
||||
|
|
@ -337,7 +346,7 @@ Class<gsi::MacroInterpreter> decl_MacroInterpreter ("lay", "MacroInterpreter",
|
|||
"Before version 0.25 this attribute was a re-implementable method. It has been turned into an attribute for "
|
||||
"performance reasons in version 0.25.\n"
|
||||
) +
|
||||
gsi::method ("debugger_scheme=", &gsi::MacroInterpreter::set_debugger_scheme, gsi::arg ("scheme"),
|
||||
gsi::method ("debugger_scheme=", &MacroInterpreterImpl::set_debugger_scheme, gsi::arg ("scheme"),
|
||||
"@brief Sets the debugger scheme (which debugger to use for the DSL macro)\n"
|
||||
"\n"
|
||||
"The value can be one of the constants \\RubyDebugger or \\NoDebugger.\n"
|
||||
|
|
@ -347,7 +356,7 @@ Class<gsi::MacroInterpreter> decl_MacroInterpreter ("lay", "MacroInterpreter",
|
|||
"Before version 0.25 this attribute was a re-implementable method. It has been turned into an attribute for "
|
||||
"performance reasons in version 0.25.\n"
|
||||
) +
|
||||
gsi::method ("storage_scheme=", &gsi::MacroInterpreter::set_storage_scheme, gsi::arg ("scheme"),
|
||||
gsi::method ("storage_scheme=", &MacroInterpreterImpl::set_storage_scheme, gsi::arg ("scheme"),
|
||||
"@brief Sets the storage scheme (the format as which the macro is stored)\n"
|
||||
"\n"
|
||||
"This value indicates how files for this DSL macro type shall be stored. "
|
||||
|
|
@ -358,7 +367,7 @@ Class<gsi::MacroInterpreter> decl_MacroInterpreter ("lay", "MacroInterpreter",
|
|||
"Before version 0.25 this attribute was a re-implementable method. It has been turned into an attribute for "
|
||||
"performance reasons in version 0.25.\n"
|
||||
) +
|
||||
gsi::method ("description=", &gsi::MacroInterpreter::set_description, gsi::arg ("description"),
|
||||
gsi::method ("description=", &MacroInterpreterImpl::set_description, gsi::arg ("description"),
|
||||
"@brief Sets a description string\n"
|
||||
"\n"
|
||||
"This string is used for showing the type of DSL macro in the file selection box together with the "
|
||||
|
|
@ -369,7 +378,7 @@ Class<gsi::MacroInterpreter> decl_MacroInterpreter ("lay", "MacroInterpreter",
|
|||
"Before version 0.25 this attribute was a re-implementable method. It has been turned into an attribute for "
|
||||
"performance reasons in version 0.25.\n"
|
||||
) +
|
||||
gsi::method ("suffix=", &gsi::MacroInterpreter::set_suffix, gsi::arg ("suffix"),
|
||||
gsi::method ("suffix=", &MacroInterpreterImpl::set_suffix, gsi::arg ("suffix"),
|
||||
"@brief Sets the file suffix\n"
|
||||
"\n"
|
||||
"This string defines which file suffix to associate with the DSL macro. If an empty string is given (the default) "
|
||||
|
|
@ -380,7 +389,7 @@ Class<gsi::MacroInterpreter> decl_MacroInterpreter ("lay", "MacroInterpreter",
|
|||
"Before version 0.25 this attribute was a re-implementable method. It has been turned into an attribute for "
|
||||
"performance reasons in version 0.25.\n"
|
||||
) +
|
||||
gsi::callback ("executable", &gsi::MacroInterpreter::executable, &gsi::MacroInterpreter::f_executable, gsi::arg ("macro"),
|
||||
gsi::callback ("executable", &MacroInterpreterImpl::executable, &MacroInterpreterImpl::f_executable, gsi::arg ("macro"),
|
||||
"@brief Returns the executable object which implements the macro execution\n"
|
||||
"This method must be reimplemented to return an \\Executable object for the actual implementation. "
|
||||
"The system will use this function to execute the script when a macro with interpreter type 'dsl' and the "
|
||||
|
|
@ -469,6 +478,9 @@ Class<gsi::MacroInterpreter> decl_MacroInterpreter ("lay", "MacroInterpreter",
|
|||
"This class has been introduced in version 0.23 and modified in 0.27.\n"
|
||||
);
|
||||
|
||||
// Inject the Macro::Format declarations into MacroInterpreter:
|
||||
gsi::ClassExt<MacroInterpreterImpl> inject_Format_in_parent (decl_FormatEnum.defs ());
|
||||
|
||||
static lym::Macro *macro_by_path (const std::string &path)
|
||||
{
|
||||
return lym::MacroCollection::root ().find_macro (path);
|
||||
|
|
@ -492,7 +504,133 @@ static int real_line (const std::string &path, int line)
|
|||
}
|
||||
}
|
||||
|
||||
lym::Macro *new_from_path (const std::string &path)
|
||||
{
|
||||
std::unique_ptr<lym::Macro> m (new lym::Macro ());
|
||||
m->set_is_file ();
|
||||
m->set_file_path (path);
|
||||
m->load_from (path);
|
||||
return m.release ();
|
||||
}
|
||||
|
||||
Class<lym::Macro> decl_Macro ("lay", "Macro",
|
||||
gsi::constructor ("new", &new_from_path, gsi::arg ("path"),
|
||||
"@brief Loads the macro from the given file path\n"
|
||||
"\n"
|
||||
"This constructor has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("run", &lym::Macro::run,
|
||||
"@brief Executes the macro\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("save_to", &lym::Macro::save_to, gsi::arg ("path"),
|
||||
"@brief Saves the macro to the given file\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("version", &lym::Macro::version,
|
||||
"@brief Gets the macro's version\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("version=", &lym::Macro::set_version, gsi::arg ("version"),
|
||||
"@brief Sets the macro's version\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("doc", &lym::Macro::doc,
|
||||
"@brief Gets the macro's documentation string\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("doc=", &lym::Macro::set_doc, gsi::arg ("doc"),
|
||||
"@brief Sets the macro's documentation string\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("shortcut", &lym::Macro::shortcut,
|
||||
"@brief Gets the macro's keyboard shortcut\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("shortcut=", &lym::Macro::set_shortcut, gsi::arg ("shortcut"),
|
||||
"@brief Sets the macro's keyboard shortcut\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("is_autorun?", &lym::Macro::is_autorun,
|
||||
"@brief Gets a flag indicating whether the macro is automatically executed on startup\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("is_autorun=", &lym::Macro::set_autorun, gsi::arg ("flag"),
|
||||
"@brief Sets a flag indicating whether the macro is automatically executed on startup\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("is_autorun_early?", &lym::Macro::is_autorun_early,
|
||||
"@brief Gets a flag indicating whether the macro is automatically executed early on startup\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("is_autorun_early=", &lym::Macro::set_autorun_early, gsi::arg ("flag"),
|
||||
"@brief Sets a flag indicating whether the macro is automatically executed early on startup\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("format", &lym::Macro::format,
|
||||
"@brief Gets the macro's storage format\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("format=", &lym::Macro::set_format, gsi::arg ("format"),
|
||||
"@brief Sets the macro's storage format\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("interpreter", &lym::Macro::interpreter,
|
||||
"@brief Gets the macro's interpreter\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("interpreter=", &lym::Macro::set_interpreter, gsi::arg ("interpreter"),
|
||||
"@brief Sets the macro's interpreter\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("interpreter_name", &lym::Macro::interpreter_name,
|
||||
"@brief Gets the macro interpreter name\n"
|
||||
"This is the string version of \\interpreter.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("dsl_interpreter", &lym::Macro::dsl_interpreter,
|
||||
"@brief Gets the macro's DSL interpreter name (if interpreter is DSLInterpreter)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("dsl_interpreter=", &lym::Macro::set_dsl_interpreter, gsi::arg ("dsl_interpreter"),
|
||||
"@brief Sets the macro's DSL interpreter name (if interpreter is DSLInterpreter)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("sync_text_with_properties", &lym::Macro::sync_text_with_properties,
|
||||
"@brief Synchronizes the macro text with the properties\n"
|
||||
"\n"
|
||||
"This method applies to PlainTextWithHashAnnotationsFormat format. The macro text will "
|
||||
"be enhanced with pseudo-comments reflecting the macro properties. This way, the macro "
|
||||
"properties can be stored in plain files.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("sync_properties_with_text", &lym::Macro::sync_properties_with_text,
|
||||
"@brief Synchronizes the macro properties with the text\n"
|
||||
"\n"
|
||||
"This method performs the reverse process of \\sync_text_with_properties.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27.5.\n"
|
||||
) +
|
||||
gsi::method ("path", &lym::Macro::path,
|
||||
"@brief Gets the path of the macro\n"
|
||||
"\n"
|
||||
|
|
@ -589,7 +727,7 @@ Class<lym::Macro> decl_Macro ("lay", "Macro",
|
|||
"@brief Sets the menu path\n"
|
||||
"See \\menu_path for details.\n"
|
||||
) +
|
||||
gsi::method ("real_path", &real_path,
|
||||
gsi::method ("real_path", &real_path, gsi::arg ("path"), gsi::arg ("line"),
|
||||
"@brief Gets the real path for an include-encoded path and line number\n"
|
||||
"\n"
|
||||
"When using KLayout's include scheme based on '# %include ...', __FILE__ and __LINE__ (Ruby) will "
|
||||
|
|
@ -614,7 +752,7 @@ Class<lym::Macro> decl_Macro ("lay", "Macro",
|
|||
"\n"
|
||||
"This feature has been introduced in version 0.27."
|
||||
) +
|
||||
gsi::method ("real_line", &real_line,
|
||||
gsi::method ("real_line", &real_line, gsi::arg ("path"), gsi::arg ("line"),
|
||||
"@brief Gets the real line number for an include-encoded path and line number\n"
|
||||
"\n"
|
||||
"When using KLayout's include scheme based on '# %include ...', __FILE__ and __LINE__ (Ruby) will "
|
||||
|
|
@ -647,7 +785,27 @@ Class<lym::Macro> decl_Macro ("lay", "Macro",
|
|||
"This class is provided mainly to support generation of template macros in the "
|
||||
"DSL interpreter framework provided by \\MacroInterpreter. The implementation may be "
|
||||
"enhanced in future versions and provide access to macros stored inside KLayout's macro repository."
|
||||
"\n"
|
||||
"But it can be used to execute macro code in a consistent way:\n"
|
||||
"\n"
|
||||
"@code\n"
|
||||
"path = \"path-to-macro.lym\"\n"
|
||||
"RBA::Macro::new(path).run()\n"
|
||||
"@/code\n"
|
||||
"\n"
|
||||
"Using the Macro class with \\run for executing code will chose the right interpreter and is "
|
||||
"able to execute DRC and LVS scripts in the proper environment. This also provides an option to "
|
||||
"execute Ruby code from Python and vice versa.\n"
|
||||
"\n"
|
||||
"In this scenario you can pass values to the script using \\Interpreter#define_variable. "
|
||||
"The interpreter to choose for DRC and LVS scripts is \\Interpreter#ruby_interpreter. "
|
||||
"For passing values back from the script, wrap the variable value into a \\Value object "
|
||||
"which can be modified by the called script and read back by the caller."
|
||||
);
|
||||
|
||||
// Inject the Macro::Format declarations into MacroInterpreter:
|
||||
gsi::ClassExt<lym::Macro> inject_Format_in_macro (decl_FormatEnum.defs ());
|
||||
gsi::ClassExt<lym::Macro> inject_Interpreter_in_macro (decl_InterpreterEnum.defs ());
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -175,7 +175,8 @@ static void reset_interpreter ()
|
|||
}
|
||||
|
||||
PythonInterpreter::PythonInterpreter (bool embedded)
|
||||
: mp_current_console (0), mp_current_exec_handler (0), m_current_exec_level (0),
|
||||
: gsi::Interpreter (0, "pya"),
|
||||
mp_current_console (0), mp_current_exec_handler (0), m_current_exec_level (0),
|
||||
m_in_trace (false), m_block_exceptions (false), m_ignore_next_exception (false),
|
||||
mp_current_frame (NULL), mp_py3_app_name (0), m_embedded (embedded)
|
||||
{
|
||||
|
|
@ -572,7 +573,7 @@ PythonInterpreter::inspector (int context)
|
|||
}
|
||||
|
||||
void
|
||||
PythonInterpreter::define_variable (const std::string &name, const std::string &value)
|
||||
PythonInterpreter::define_variable (const std::string &name, const tl::Variant &value)
|
||||
{
|
||||
PythonPtr main_module (PyImport_AddModule ("__main__"));
|
||||
PythonPtr dict (PyModule_GetDict (main_module.get ()));
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ public:
|
|||
/**
|
||||
* @brief Defines a global variable with the given name and value
|
||||
*/
|
||||
void define_variable (const std::string &name, const std::string &value);
|
||||
void define_variable (const std::string &name, const tl::Variant &value);
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the interpreter is available
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ static void fail (const char *file, int line)
|
|||
static PythonInterpreter *sp_pya_interpreter = 0;
|
||||
|
||||
PythonInterpreter::PythonInterpreter ()
|
||||
: gsi::Interpreter (0, "pya")
|
||||
{
|
||||
tl_assert (! sp_pya_interpreter);
|
||||
sp_pya_interpreter = this;
|
||||
|
|
@ -118,7 +119,7 @@ PythonInterpreter::inspector (int)
|
|||
}
|
||||
|
||||
void
|
||||
PythonInterpreter::define_variable (const std::string &, const std::string &)
|
||||
PythonInterpreter::define_variable (const std::string &, const tl::Variant &)
|
||||
{
|
||||
// .. nothing ..
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ public:
|
|||
/**
|
||||
* @brief Defines a global variable with the given name and value
|
||||
*/
|
||||
void define_variable (const std::string &name, const std::string &value);
|
||||
void define_variable (const std::string &name, const tl::Variant &value);
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the interpreter is available
|
||||
|
|
|
|||
|
|
@ -1758,7 +1758,8 @@ rba_init (RubyInterpreterPrivateData *d)
|
|||
}
|
||||
|
||||
RubyInterpreter::RubyInterpreter ()
|
||||
: d (new RubyInterpreterPrivateData ())
|
||||
: gsi::Interpreter (0, "rba"),
|
||||
d (new RubyInterpreterPrivateData ())
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, "Initializing Ruby");
|
||||
|
||||
|
|
@ -2057,9 +2058,9 @@ RubyInterpreter::eval_string_and_print (const char *expr, const char *file, int
|
|||
}
|
||||
|
||||
void
|
||||
RubyInterpreter::define_variable (const std::string &name, const std::string &value)
|
||||
RubyInterpreter::define_variable (const std::string &name, const tl::Variant &value)
|
||||
{
|
||||
rb_gv_set (name.c_str (), rb_str_new (value.c_str (), long (value.size ())));
|
||||
rb_gv_set (name.c_str (), c2ruby (value));
|
||||
}
|
||||
|
||||
gsi::Inspector *
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ public:
|
|||
/**
|
||||
* @brief Defines a global variable with the given name and value
|
||||
*/
|
||||
void define_variable (const std::string &name, const std::string &value);
|
||||
void define_variable (const std::string &name, const tl::Variant &value);
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the interpreter is available
|
||||
|
|
|
|||
|
|
@ -141,6 +141,7 @@ RUBYTEST (imgObject, "imgObject.rb")
|
|||
RUBYTEST (layLayers, "layLayers.rb")
|
||||
RUBYTEST (layLayoutView, "layLayoutView.rb")
|
||||
RUBYTEST (layMarkers, "layMarkers.rb")
|
||||
RUBYTEST (layMacro, "layMacro.rb")
|
||||
RUBYTEST (layMenuTest, "layMenuTest.rb")
|
||||
RUBYTEST (laySession, "laySession.rb")
|
||||
RUBYTEST (layTechnologies, "layTechnologies.rb")
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ static void fail (const char *file, int line)
|
|||
static RubyInterpreter *sp_rba_interpreter = 0;
|
||||
|
||||
RubyInterpreter::RubyInterpreter ()
|
||||
: gsi::Interpreter (0, "rba")
|
||||
{
|
||||
tl_assert (! sp_rba_interpreter);
|
||||
sp_rba_interpreter = this;
|
||||
|
|
@ -110,7 +111,7 @@ RubyInterpreter::eval_string_and_print (const char *, const char *file, int line
|
|||
}
|
||||
|
||||
void
|
||||
RubyInterpreter::define_variable (const std::string &, const std::string &)
|
||||
RubyInterpreter::define_variable (const std::string &, const tl::Variant &)
|
||||
{
|
||||
// .. nothing ..
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ public:
|
|||
/**
|
||||
* @brief Defines a global variable with the given name and value
|
||||
*/
|
||||
void define_variable (const std::string &name, const std::string &value);
|
||||
void define_variable (const std::string &name, const tl::Variant &value);
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the interpreter is available
|
||||
|
|
|
|||
|
|
@ -0,0 +1,184 @@
|
|||
# encoding: UTF-8
|
||||
|
||||
# KLayout Layout Viewer
|
||||
# Copyright (C) 2006-2021 Matthias Koefferlein
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
if !$:.member?(File::dirname($0))
|
||||
$:.push(File::dirname($0))
|
||||
end
|
||||
|
||||
load("test_prologue.rb")
|
||||
|
||||
class LAYMacro_TestClass < TestBase
|
||||
|
||||
def test_1
|
||||
|
||||
macro = RBA::Macro::new
|
||||
|
||||
macro.version = "1.7"
|
||||
assert_equal(macro.version, "1.7")
|
||||
|
||||
macro.doc = "%doc"
|
||||
assert_equal(macro.doc, "%doc")
|
||||
|
||||
macro.description = "%description"
|
||||
assert_equal(macro.description, "%description")
|
||||
|
||||
macro.prolog = "%prolog"
|
||||
assert_equal(macro.prolog, "%prolog")
|
||||
|
||||
macro.epilog = "%epilog"
|
||||
assert_equal(macro.epilog, "%epilog")
|
||||
|
||||
macro.category = "%category"
|
||||
assert_equal(macro.category, "%category")
|
||||
|
||||
macro.shortcut = "%shortcut"
|
||||
assert_equal(macro.shortcut, "%shortcut")
|
||||
|
||||
assert_equal(macro.is_autorun?, false)
|
||||
macro.is_autorun = true
|
||||
assert_equal(macro.is_autorun?, true)
|
||||
|
||||
assert_equal(macro.is_autorun_early?, false)
|
||||
macro.is_autorun_early = true
|
||||
assert_equal(macro.is_autorun_early?, true)
|
||||
|
||||
macro.format = RBA::Macro::PlainTextFormat
|
||||
assert_equal(macro.format == RBA::Macro::PlainTextFormat, true)
|
||||
macro.format = RBA::Macro::MacroFormat
|
||||
assert_equal(macro.format == RBA::Macro::MacroFormat, true)
|
||||
|
||||
macro.interpreter = RBA::Macro::Ruby
|
||||
assert_equal(macro.interpreter == RBA::Macro::Ruby, true)
|
||||
assert_equal(macro.interpreter_name, "Ruby")
|
||||
macro.interpreter = RBA::Macro::Python
|
||||
assert_equal(macro.interpreter == RBA::Macro::Python, true)
|
||||
assert_equal(macro.interpreter_name, "Python")
|
||||
|
||||
macro.dsl_interpreter = "%dsl"
|
||||
assert_equal(macro.dsl_interpreter, "%dsl")
|
||||
|
||||
macro.text = "%text"
|
||||
macro.format = RBA::Macro::PlainTextWithHashAnnotationsFormat
|
||||
assert_equal(macro.text, "%text")
|
||||
macro.sync_text_with_properties
|
||||
assert_equal(macro.text, "# $description: %description\n" +
|
||||
"# $prolog: %prolog\n" +
|
||||
"# $epilog: %epilog\n" +
|
||||
"# $version: 1.7\n" +
|
||||
"# $autorun\n" +
|
||||
"# $autorun-early\n" +
|
||||
"# $shortcut: %shortcut\n" +
|
||||
"%text")
|
||||
|
||||
macro.text = "# $description: %description\n" +
|
||||
"# $prolog: %prolog\n" +
|
||||
"# $epilog: %epilog\n" +
|
||||
"# $version: 7.1\n" +
|
||||
"# $autorun\n" +
|
||||
"# $autorun-early\n" +
|
||||
"# $shortcut: %shortcut\n" +
|
||||
"%text"
|
||||
macro.sync_properties_with_text
|
||||
assert_equal(macro.version, "7.1")
|
||||
|
||||
macro.group_name = "%group"
|
||||
assert_equal(macro.group_name, "%group")
|
||||
|
||||
assert_equal(macro.show_in_menu?, false)
|
||||
macro.show_in_menu = true
|
||||
assert_equal(macro.show_in_menu?, true)
|
||||
|
||||
macro.menu_path = "menu.path"
|
||||
assert_equal(macro.menu_path, "menu.path")
|
||||
|
||||
end
|
||||
|
||||
def test_2
|
||||
|
||||
macro_file = File.join($ut_testtmp, "test.lym")
|
||||
File.open(macro_file, "w") do |file|
|
||||
file.write(<<"END")
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<klayout-macro>
|
||||
<description>%description</description>
|
||||
<version>42</version>
|
||||
<interpreter>ruby</interpreter>
|
||||
<text>
|
||||
$test_output = "x" + $test_input
|
||||
</text>
|
||||
</klayout-macro>
|
||||
END
|
||||
end
|
||||
|
||||
macro = RBA::Macro::new(macro_file)
|
||||
assert_equal(macro.description, "%description")
|
||||
assert_equal(macro.path, macro_file)
|
||||
|
||||
$test_input = "42"
|
||||
$test_output = ""
|
||||
macro.run
|
||||
assert_equal($test_output, "x42")
|
||||
|
||||
macro_file2 = File.join($ut_testtmp, "test2.lym")
|
||||
macro.save_to(macro_file2)
|
||||
|
||||
macro2 = RBA::Macro::new(macro_file2)
|
||||
assert_equal(macro2.path, macro_file2)
|
||||
|
||||
end
|
||||
|
||||
def test_3
|
||||
|
||||
pya = RBA::Interpreter.python_interpreter
|
||||
if !pya
|
||||
return
|
||||
end
|
||||
|
||||
macro_file = File.join($ut_testtmp, "test.lym")
|
||||
File.open(macro_file, "w") do |file|
|
||||
file.write(<<"END")
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<klayout-macro>
|
||||
<description>%description</description>
|
||||
<version>42</version>
|
||||
<interpreter>python</interpreter>
|
||||
<text>
|
||||
print("Python calling!")
|
||||
context.value = "x" + context.value
|
||||
</text>
|
||||
</klayout-macro>
|
||||
END
|
||||
end
|
||||
|
||||
macro = RBA::Macro::new(macro_file)
|
||||
assert_equal(macro.description, "%description")
|
||||
assert_equal(macro.path, macro_file)
|
||||
|
||||
context = RBA::Value::new
|
||||
context.value = "42"
|
||||
pya.define_variable("context", context)
|
||||
|
||||
macro.run
|
||||
assert_equal(context.value, "x42")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
Loading…
Reference in New Issue