"""Macro support for Ophis. Ophis Macros are cached SequenceNodes with arguments set via .alias commands and prevented from escaping with .scope and .scend commands.""" # Copyright 2002-2014 Michael C. Martin and additional contributors. # You may use, modify, and distribute this file under the MIT # license: See README for details. import sys import Ophis.IR as IR import Ophis.Errors as Err macros = {} currentname = None currentbody = None def newMacro(name): "Start creating a new macro with the specified name." global currentname global currentbody global macros if currentname is not None: Err.log("Internal error! Nested macro attempt!") else: if name in macros: Err.log("Duplicate macro definition '%s'" % name) currentname = name currentbody = [] def registerNode(node): global currentbody currentbody.append(IR.Node(node.ppt, node.nodetype, *node.data)) def endMacro(): global currentname global currentbody global macros if currentname is None: Err.log("Internal error! Ended a non-existent macro!") else: macros[currentname] = currentbody currentname = None currentbody = None def expandMacro(ppt, name, arglist): global macros if name not in macros: Err.log("Undefined macro '%s'" % name) return IR.NullNode argexprs = [IR.Node(ppt, "Label", "_*%d" % i, arg) for (i, arg) in zip(range(1, sys.maxsize), arglist)] bindexprs = [IR.Node(ppt, "Label", "_%d" % i, IR.LabelExpr("_*%d" % i)) for i in range(1, len(arglist) + 1)] body = [IR.Node("%s->%s" % (ppt, node.ppt), node.nodetype, *node.data) for node in macros[name]] invocation = [IR.Node(ppt, "ScopeBegin")] + argexprs + \ [IR.Node(ppt, "ScopeBegin")] + bindexprs + body + \ [IR.Node(ppt, "ScopeEnd"), IR.Node(ppt, "ScopeEnd")] return IR.SequenceNode(ppt, invocation) def dump(): global macros for mac in macros: body = macros[mac] print("Macro: " + mac, file=sys.stderr) for node in body: print(node, file=sys.stderr) print("", file=sys.stderr)