aboutsummaryrefslogtreecommitdiff
path: root/src/smp/macro_processor.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/smp/macro_processor.py')
-rw-r--r--src/smp/macro_processor.py76
1 files changed, 46 insertions, 30 deletions
diff --git a/src/smp/macro_processor.py b/src/smp/macro_processor.py
index e85fbe9..8fa9d91 100644
--- a/src/smp/macro_processor.py
+++ b/src/smp/macro_processor.py
@@ -41,6 +41,8 @@ class MacroProcessor:
warnings: list[Any]
""" Global environment for python execution """
py_global_env: dict
+ py_local_env_alt: dict
+ py_local_env_current: dict
special_macros: dict[str, tuple[Any, Any]]
@@ -49,32 +51,40 @@ class MacroProcessor:
self.macro_invocations = list()
self.warnings = list()
self.py_global_env = dict()
- self._define_builtins(prefix=prefix)
-
- def _define_builtins(self, prefix=""):
- self.macros[f"{prefix}define"] = smp.builtins.smp_builtin_define
- self.macros[f"{prefix}undefine"] = smp.builtins.smp_builtin_undefine
- self.macros[f"{prefix}define_array"] = smp.builtins.smp_builtin_define_array
- self.macros[f"{prefix}ifdef"] = smp.builtins.smp_builtin_ifdef
- self.macros[f"{prefix}ifndef"] = smp.builtins.smp_builtin_ifndef
- self.macros[f"{prefix}ifeq"] = smp.builtins.smp_builtin_ifeq
- self.macros[f"{prefix}ifneq"] = smp.builtins.smp_builtin_ifneq
- self.macros[f"{prefix}include"] = smp.builtins.smp_builtin_include
- self.macros[f"{prefix}include_verbatim"] = (
- smp.builtins.smp_builtin_include_verbatim
- )
- self.macros[f"{prefix}shell"] = smp.builtins.smp_builtin_shell
- self.macros[f"{prefix}dumpenv"] = smp.builtins.smp_builtin_dumpenv
- self.macros[f"{prefix}eval"] = smp.builtins.smp_builtin_eval
- self.macros[f"{prefix}array_push"] = smp.builtins.smp_builtin_array_push
- self.macros[f"{prefix}array_each"] = smp.builtins.smp_builtin_array_each
- self.macros[f"{prefix}array_size"] = smp.builtins.smp_builtin_array_size
- self.macros[f"{prefix}explode"] = smp.builtins.smp_builtin_explode
- self.macros[f"{prefix}format_time"] = smp.builtins.smp_builtin_format_time
- self.macros[f"{prefix}html_from_markdown"] = (
- smp.builtins.smp_builtin_html_from_markdown
- )
- self.macros[f"{prefix}wodl"] = smp.builtins.smp_builtin_wodl
+ self.py_local_env_alt = dict()
+ self.py_local_env_current = self.macros
+ self.indent_level = ""
+
+ self._define_builtins(self.macros, prefix=prefix)
+ self._define_builtins(self.py_local_env_alt, prefix=prefix)
+
+ def _define_builtins(self, env, prefix=""):
+ env[f"{prefix}macro_processor"] = self
+ env[f"{prefix}define"] = smp.builtins.smp_builtin_define
+ env[f"{prefix}undefine"] = smp.builtins.smp_builtin_undefine
+ env[f"{prefix}define_array"] = smp.builtins.smp_builtin_define_array
+ env[f"{prefix}ifdef"] = smp.builtins.smp_builtin_ifdef
+ env[f"{prefix}ifndef"] = smp.builtins.smp_builtin_ifndef
+ env[f"{prefix}ifeq"] = smp.builtins.smp_builtin_ifeq
+ env[f"{prefix}ifneq"] = smp.builtins.smp_builtin_ifneq
+ env[f"{prefix}include"] = smp.builtins.smp_builtin_include
+ env[f"{prefix}include_verbatim"] = smp.builtins.smp_builtin_include_verbatim
+ env[f"{prefix}shell"] = smp.builtins.smp_builtin_shell
+ env[f"{prefix}dumpenv"] = smp.builtins.smp_builtin_dumpenv
+ env[f"{prefix}eval"] = smp.builtins.smp_builtin_eval
+ env[f"{prefix}array_push"] = smp.builtins.smp_builtin_array_push
+ env[f"{prefix}array_each"] = smp.builtins.smp_builtin_array_each
+ env[f"{prefix}array_size"] = smp.builtins.smp_builtin_array_size
+ env[f"{prefix}explode"] = smp.builtins.smp_builtin_explode
+ env[f"{prefix}format_time"] = smp.builtins.smp_builtin_format_time
+ env[f"{prefix}html_from_markdown"] = smp.builtins.smp_builtin_html_from_markdown
+ env[f"{prefix}wodl"] = smp.builtins.smp_builtin_wodl
+
+ def define_macro_string(self, macro_name, macro_value):
+ self.define_macro(macro_name, str(macro_value))
+
+ def define_macro(self, macro_name, macro_value):
+ self.macros[macro_name] = macro_value
def expand_macro(self, macro_name: str, args: list[str] = list()) -> str:
# Ignore trailing underscore in macro name, the parser will pop a space in front if
@@ -104,14 +114,18 @@ class MacroProcessor:
if callable(macro):
signature = inspect.signature(macro)
- macro_args = []
+ macro_args: list[Any] = []
if (
"macro_processor" in signature.parameters
or "smp" in signature.parameters
):
macro_args.append(self)
macro_args.extend(args)
- return str(macro(*macro_args))
+ try:
+ return str(macro(*macro_args))
+ except Exception as e:
+ s = f"{macro_name}({','.join([repr(x) for x in macro_args])})"
+ raise Exception(s)
if isinstance(macro, str):
expanded = macro
for i, arg in enumerate(args):
@@ -143,8 +157,11 @@ class MacroProcessor:
skip_next_line_ending = False
+ line_begin = True
+
# We should keep track of filename, linenumber, and character number on line here
# So we can give sensible error messages
+ # Probably add to python stack trace?
quote_level = 0
parens_level = 0
@@ -153,7 +170,6 @@ class MacroProcessor:
while i < len(input):
c = input[i]
peek = None if i + 1 >= len(input) else input[i + 1]
-
# import sys
# print(f"[{i:4}] {repr(c):4} -> {repr(peek):4} [{state}] = {repr(output)}", file=sys.stderr)
@@ -264,7 +280,7 @@ class MacroProcessor:
try:
f = StringIO()
with redirect_stdout(f):
- exec(py_expr, self.py_global_env, self.macros)
+ exec(py_expr, self.py_global_env, self.py_local_env_current)
s = f.getvalue()
if s != "":
output += s