Module refinery.lib.scripts.ps1.synth

AST-to-source synthesizer for PowerShell.

Expand source code Browse git
"""
AST-to-source synthesizer for PowerShell.
"""
from __future__ import annotations

import io

from refinery.lib.scripts import Block, Node, Visitor
from refinery.lib.scripts.ps1.deobfuscation._helpers import KEYWORD_SPELLING
from refinery.lib.scripts.ps1.model import (
    Expression,
    Ps1ArrayExpression,
    Ps1ArrayLiteral,
    Ps1AssignmentExpression,
    Ps1Attribute,
    Ps1BinaryExpression,
    Ps1BreakStatement,
    Ps1CastExpression,
    Ps1CatchClause,
    Ps1CommandArgument,
    Ps1CommandArgumentKind,
    Ps1CommandInvocation,
    Ps1ContinueStatement,
    Ps1DataSection,
    Ps1DoUntilLoop,
    Ps1DoWhileLoop,
    Ps1ErrorNode,
    Ps1ExitStatement,
    Ps1ExpandableHereString,
    Ps1ExpandableString,
    Ps1ExpressionStatement,
    Ps1ForEachLoop,
    Ps1ForLoop,
    Ps1FunctionDefinition,
    Ps1HashLiteral,
    Ps1HereString,
    Ps1IfStatement,
    Ps1IndexExpression,
    Ps1IntegerLiteral,
    Ps1InvokeMember,
    Ps1MemberAccess,
    Ps1ParamBlock,
    Ps1ParameterDeclaration,
    Ps1ParenExpression,
    Ps1Pipeline,
    Ps1PipelineElement,
    Ps1RangeExpression,
    Ps1RealLiteral,
    Ps1Redirection,
    Ps1ReturnStatement,
    Ps1ScopeModifier,
    Ps1Script,
    Ps1ScriptBlock,
    Ps1StringLiteral,
    Ps1SubExpression,
    Ps1SwitchStatement,
    Ps1ThrowStatement,
    Ps1TrapStatement,
    Ps1TryCatchFinally,
    Ps1TypeExpression,
    Ps1UnaryExpression,
    Ps1Variable,
    Ps1WhileLoop,
)


class Ps1Synthesizer(Visitor):

    def __init__(self, indent: str = '  '):
        super().__init__()
        self._indent = indent
        self._depth = 0
        self._parts = io.StringIO()

    def convert(self, node: Node) -> str:
        self._parts.seek(0)
        self._parts.truncate(0)
        self._depth = 0
        self.visit(node)
        return self._parts.getvalue()

    def _write(self, text: str):
        self._parts.write(text)

    def _newline(self):
        self._parts.write('\n')
        self._parts.write(self._indent * self._depth)

    def _emit_block(self, block: Block):
        self._write('{')
        self._depth += 1
        for stmt in block.body:
            self._newline()
            self.visit(stmt)
        self._depth -= 1
        if block.body:
            self._newline()
        self._write('}')

    def _emit_statement_list(self, stmts: list):
        for i, stmt in enumerate(stmts):
            if i > 0:
                self._newline()
            self.visit(stmt)

    def generic_visit(self, node: Node):
        self._write(F'<{type(node).__name__}>')

    def visit_Ps1Variable(self, node: Ps1Variable):
        prefix = '@' if node.splatted else '$'
        scope_str = ''
        if node.scope != Ps1ScopeModifier.NONE:
            scope_str = F'{node.scope.value}:'
        name = F'{{{node.name}}}' if node.braced else node.name
        self._write(F'{prefix}{scope_str}{name}')

    def visit_Ps1IntegerLiteral(self, node: Ps1IntegerLiteral):
        self._write(node.raw)

    def visit_Ps1RealLiteral(self, node: Ps1RealLiteral):
        self._write(node.raw)

    def visit_Ps1StringLiteral(self, node: Ps1StringLiteral):
        self._write(node.raw)

    def visit_Ps1ExpandableString(self, node: Ps1ExpandableString):
        self._write('"')
        for part in node.parts:
            if isinstance(part, Ps1StringLiteral):
                self._write(self._escape_for_dq(part.value))
            elif isinstance(part, Ps1Variable):
                self._emit_variable_in_dq(part)
            else:
                self.visit(part)
        self._write('"')

    def _emit_variable_in_dq(self, node: Ps1Variable):
        prefix = '@' if node.splatted else '$'
        scope_str = ''
        if node.scope != Ps1ScopeModifier.NONE:
            scope_str = F'{node.scope.value}:'
        self._write(F'{prefix}{{{scope_str}{node.name}}}')

    @staticmethod
    def _escape_for_dq(value: str) -> str:
        return value.replace('`', '``').replace('"', '""').replace('$', '`$')

    def visit_Ps1HereString(self, node: Ps1HereString):
        self._write(node.raw)

    def visit_Ps1ExpandableHereString(self, node: Ps1ExpandableHereString):
        self._write(node.raw)

    def visit_Ps1BinaryExpression(self, node: Ps1BinaryExpression):
        spine: list[tuple[str, Expression | None]] = []
        current: Expression | None = node
        while isinstance(current, Ps1BinaryExpression):
            spine.append((current.operator, current.right))
            current = current.left
        if current:
            self.visit(current)
        for operator, right in reversed(spine):
            self._write(F' {operator} ')
            if right:
                self.visit(right)

    def visit_Ps1UnaryExpression(self, node: Ps1UnaryExpression):
        if node.prefix:
            self._write(node.operator)
            if node.operator.startswith('-') and len(node.operator) > 1:
                self._write(' ')
            if node.operand:
                self.visit(node.operand)
        else:
            if node.operand:
                self.visit(node.operand)
            self._write(node.operator)

    def visit_Ps1TypeExpression(self, node: Ps1TypeExpression):
        self._write(F'[{node.name}]')

    def visit_Ps1CastExpression(self, node: Ps1CastExpression):
        self._write(F'[{node.type_name}]')
        if node.operand:
            self.visit(node.operand)

    def visit_Ps1MemberAccess(self, node: Ps1MemberAccess):
        if node.object:
            self.visit(node.object)
        self._write(node.access.value)
        if isinstance(node.member, Expression):
            self.visit(node.member)
        else:
            self._write(str(node.member))

    def visit_Ps1IndexExpression(self, node: Ps1IndexExpression):
        if node.object:
            self.visit(node.object)
        self._write('[')
        if node.index:
            self.visit(node.index)
        self._write(']')

    def visit_Ps1InvokeMember(self, node: Ps1InvokeMember):
        if node.object:
            self.visit(node.object)
        self._write(node.access.value)
        if isinstance(node.member, Expression):
            self.visit(node.member)
        else:
            self._write(str(node.member))
        self._write('(')
        for i, arg in enumerate(node.arguments):
            if i > 0:
                self._write(', ')
            self.visit(arg)
        self._write(')')

    def visit_Ps1CommandInvocation(self, node: Ps1CommandInvocation):
        if node.invocation_operator:
            self._write(node.invocation_operator)
            self._write(' ')
        if node.name:
            self.visit(node.name)
        for arg in node.arguments:
            self._write(' ')
            self.visit(arg)

    def visit_Ps1CommandArgument(self, node: Ps1CommandArgument):
        if node.kind == Ps1CommandArgumentKind.SWITCH:
            self._write(node.name)
        elif node.kind == Ps1CommandArgumentKind.NAMED:
            self._write(F'{node.name}:')
            if node.value:
                self._emit_argument_value(node.value)
        elif node.kind == Ps1CommandArgumentKind.POSITIONAL:
            if node.value:
                self._emit_argument_value(node.value)

    def _emit_argument_value(self, value: Expression):
        if isinstance(value, Ps1BinaryExpression):
            self._write('(')
            self.visit(value)
            self._write(')')
        else:
            self.visit(value)

    def visit_Ps1CallExpression(self, node):
        if node.callee:
            self.visit(node.callee)
        self._write('(')
        for i, arg in enumerate(node.arguments):
            if i > 0:
                self._write(', ')
            self.visit(arg)
        self._write(')')

    def visit_Ps1AssignmentExpression(self, node: Ps1AssignmentExpression):
        if node.target:
            self.visit(node.target)
        self._write(F' {node.operator} ')
        if node.value:
            self.visit(node.value)

    def visit_Ps1ArrayLiteral(self, node: Ps1ArrayLiteral):
        for i, elem in enumerate(node.elements):
            if i > 0:
                self._write(', ')
            self.visit(elem)

    def visit_Ps1ArrayExpression(self, node: Ps1ArrayExpression):
        self._write('@(')
        self._emit_statement_list(node.body)
        self._write(')')

    def visit_Ps1HashLiteral(self, node: Ps1HashLiteral):
        self._write('@{')
        if node.pairs:
            self._depth += 1
            for key, value in node.pairs:
                self._newline()
                self.visit(key)
                self._write(' = ')
                self.visit(value)
            self._depth -= 1
            self._newline()
        self._write('}')

    def visit_Ps1SubExpression(self, node: Ps1SubExpression):
        self._write('$(')
        self._emit_statement_list(node.body)
        self._write(')')

    def visit_Ps1ParenExpression(self, node: Ps1ParenExpression):
        self._write('(')
        if node.expression:
            self.visit(node.expression)
        self._write(')')

    def visit_Ps1ScriptBlock(self, node: Ps1ScriptBlock):
        self._write('{')
        self._depth += 1
        if node.param_block:
            self._newline()
            self.visit(node.param_block)
        has_named = (
            node.begin_block or node.process_block
            or node.end_block or node.dynamicparam_block
        )
        if has_named:
            if node.begin_block:
                self._newline()
                self._write('begin ')
                self._emit_block(node.begin_block)
            if node.process_block:
                self._newline()
                self._write('process ')
                self._emit_block(node.process_block)
            if node.end_block:
                self._newline()
                self._write('end ')
                self._emit_block(node.end_block)
            if node.dynamicparam_block:
                self._newline()
                self._write('dynamicparam ')
                self._emit_block(node.dynamicparam_block)
        else:
            for stmt in node.body:
                self._newline()
                self.visit(stmt)
        self._depth -= 1
        if node.body or has_named or node.param_block:
            self._newline()
        self._write('}')

    def visit_Ps1RangeExpression(self, node: Ps1RangeExpression):
        if node.start:
            self.visit(node.start)
        self._write('..')
        if node.end:
            self.visit(node.end)

    def visit_Ps1Attribute(self, node: Ps1Attribute):
        self._write(F'[{node.name}')
        if node.positional_args or node.named_args:
            self._write('(')
            items: list[str] = []
            for arg in node.positional_args:
                old_parts = self._parts
                self._parts = io.StringIO()
                self.visit(arg)
                items.append(self._parts.getvalue())
                self._parts = old_parts
            for key, val in node.named_args:
                old_parts = self._parts
                self._parts = io.StringIO()
                self.visit(val)
                v = self._parts.getvalue()
                self._parts = old_parts
                items.append(F'{key}={v}')
            self._write(', '.join(items))
            self._write(')')
        self._write(']')

    def visit_Ps1ParameterDeclaration(self, node: Ps1ParameterDeclaration):
        for attr in node.attributes:
            self.visit(attr)
        if node.variable:
            self.visit(node.variable)
        if node.default_value:
            self._write(' = ')
            self.visit(node.default_value)

    def visit_Ps1ParamBlock(self, node: Ps1ParamBlock):
        for attr in node.attributes:
            self.visit(attr)
            self._newline()
        self._write(KEYWORD_SPELLING.get('param', 'param'))
        self._write('(')
        for i, param in enumerate(node.parameters):
            if i > 0:
                self._write(', ')
            self.visit(param)
        self._write(')')

    def visit_Ps1Redirection(self, node: Ps1Redirection):
        self._write(node.operator)
        self._write(' ')
        if node.target:
            self.visit(node.target)

    def visit_Ps1PipelineElement(self, node: Ps1PipelineElement):
        if node.expression:
            self.visit(node.expression)
        for redir in node.redirections:
            self._write(' ')
            self.visit(redir)

    def visit_Ps1Pipeline(self, node: Ps1Pipeline):
        for i, elem in enumerate(node.elements):
            if i > 0:
                self._write(' | ')
            self.visit(elem)

    def visit_Ps1ExpressionStatement(self, node: Ps1ExpressionStatement):
        if node.expression:
            self.visit(node.expression)

    def visit_Ps1IfStatement(self, node: Ps1IfStatement):
        for i, (cond, body) in enumerate(node.clauses):
            if i == 0:
                self._write('if (')
            else:
                self._write(' elseif (')
            if cond:
                self.visit(cond)
            self._write(') ')
            self._emit_block(body)
        if node.else_block:
            self._write(' else ')
            self._emit_block(node.else_block)

    def visit_Ps1WhileLoop(self, node: Ps1WhileLoop):
        if node.label:
            self._write(F'{node.label} ')
        self._write('while (')
        if node.condition:
            self.visit(node.condition)
        self._write(') ')
        if node.body:
            self._emit_block(node.body)

    def visit_Ps1DoWhileLoop(self, node: Ps1DoWhileLoop):
        if node.label:
            self._write(F'{node.label} ')
        self._write('do ')
        if node.body:
            self._emit_block(node.body)
        self._write(' while (')
        if node.condition:
            self.visit(node.condition)
        self._write(')')

    def visit_Ps1DoUntilLoop(self, node: Ps1DoUntilLoop):
        if node.label:
            self._write(F'{node.label} ')
        self._write('do ')
        if node.body:
            self._emit_block(node.body)
        self._write(' until (')
        if node.condition:
            self.visit(node.condition)
        self._write(')')

    def visit_Ps1ForLoop(self, node: Ps1ForLoop):
        if node.label:
            self._write(F'{node.label} ')
        self._write('for (')
        if node.initializer:
            self.visit(node.initializer)
        self._write('; ')
        if node.condition:
            self.visit(node.condition)
        self._write('; ')
        if node.iterator:
            self.visit(node.iterator)
        self._write(') ')
        if node.body:
            self._emit_block(node.body)

    def visit_Ps1ForEachLoop(self, node: Ps1ForEachLoop):
        if node.label:
            self._write(F'{node.label} ')
        self._write('foreach ')
        if node.parallel:
            self._write('-Parallel ')
        self._write('(')
        if node.variable:
            self.visit(node.variable)
        self._write(' in ')
        if node.iterable:
            self.visit(node.iterable)
        self._write(') ')
        if node.body:
            self._emit_block(node.body)

    def visit_Ps1SwitchStatement(self, node: Ps1SwitchStatement):
        if node.label:
            self._write(F'{node.label} ')
        self._write('switch ')
        if node.regex:
            self._write('-Regex ')
        if node.wildcard:
            self._write('-Wildcard ')
        if node.exact:
            self._write('-Exact ')
        if node.case_sensitive:
            self._write('-CaseSensitive ')
        if node.file:
            self._write('-File ')
            if node.value:
                self.visit(node.value)
            self._write(' {')
        else:
            self._write('(')
            if node.value:
                self.visit(node.value)
            self._write(') {')
        self._depth += 1
        for cond, body in node.clauses:
            self._newline()
            if cond is None:
                self._write('default ')
            else:
                self.visit(cond)
                self._write(' ')
            self._emit_block(body)
        self._depth -= 1
        self._newline()
        self._write('}')

    def visit_Ps1TryCatchFinally(self, node: Ps1TryCatchFinally):
        self._write('try ')
        if node.try_block:
            self._emit_block(node.try_block)
        for clause in node.catch_clauses:
            self._write(' catch')
            if clause.types:
                self._write(' ')
                self._write(' '.join(F'[{t}]' for t in clause.types))
            self._write(' ')
            if clause.body:
                self._emit_block(clause.body)
        if node.finally_block:
            self._write(' finally ')
            self._emit_block(node.finally_block)

    def visit_Ps1CatchClause(self, node: Ps1CatchClause):
        pass

    def visit_Ps1TrapStatement(self, node: Ps1TrapStatement):
        self._write('trap ')
        if node.type_name:
            self._write(F'[{node.type_name}] ')
        if node.body:
            self._emit_block(node.body)

    def visit_Ps1FunctionDefinition(self, node: Ps1FunctionDefinition):
        kw = 'filter' if node.is_filter else 'function'
        self._write(F'{kw} {node.name} ')
        if node.body:
            self.visit(node.body)

    def visit_Ps1ReturnStatement(self, node: Ps1ReturnStatement):
        self._write('return')
        if node.pipeline:
            self._write(' ')
            self.visit(node.pipeline)

    def visit_Ps1ThrowStatement(self, node: Ps1ThrowStatement):
        self._write('throw')
        if node.pipeline:
            self._write(' ')
            self.visit(node.pipeline)

    def visit_Ps1BreakStatement(self, node: Ps1BreakStatement):
        self._write('break')
        if node.label:
            self._write(' ')
            self.visit(node.label)

    def visit_Ps1ContinueStatement(self, node: Ps1ContinueStatement):
        self._write('continue')
        if node.label:
            self._write(' ')
            self.visit(node.label)

    def visit_Ps1ExitStatement(self, node: Ps1ExitStatement):
        self._write('exit')
        if node.pipeline:
            self._write(' ')
            self.visit(node.pipeline)

    def visit_Ps1DataSection(self, node: Ps1DataSection):
        self._write('data ')
        if node.name:
            self._write(F'{node.name} ')
        if node.commands:
            self._write('-SupportedCommand ')
            for i, cmd in enumerate(node.commands):
                if i > 0:
                    self._write(', ')
                self.visit(cmd)
            self._write(' ')
        if node.body:
            self._emit_block(node.body)

    def visit_Ps1ErrorNode(self, node: Ps1ErrorNode):
        self._write(node.text)

    def visit_Ps1Script(self, node: Ps1Script):
        if node.param_block:
            self.visit(node.param_block)
            self._newline()
        has_named = (
            node.begin_block or node.process_block
            or node.end_block or node.dynamicparam_block
        )
        if has_named:
            if node.begin_block:
                self._write('begin ')
                self._emit_block(node.begin_block)
                self._newline()
            if node.process_block:
                self._write('process ')
                self._emit_block(node.process_block)
                self._newline()
            if node.end_block:
                self._write('end ')
                self._emit_block(node.end_block)
                self._newline()
            if node.dynamicparam_block:
                self._write('dynamicparam ')
                self._emit_block(node.dynamicparam_block)
                self._newline()
        else:
            self._emit_statement_list(node.body)

    def visit_Block(self, node: Block):
        self._emit_block(node)

Classes

class Ps1Synthesizer (indent=' ')

Dispatch-based tree walker. Subclasses define visit_ClassName methods; unhandled nodes fall through to generic_visit.

Expand source code Browse git
class Ps1Synthesizer(Visitor):

    def __init__(self, indent: str = '  '):
        super().__init__()
        self._indent = indent
        self._depth = 0
        self._parts = io.StringIO()

    def convert(self, node: Node) -> str:
        self._parts.seek(0)
        self._parts.truncate(0)
        self._depth = 0
        self.visit(node)
        return self._parts.getvalue()

    def _write(self, text: str):
        self._parts.write(text)

    def _newline(self):
        self._parts.write('\n')
        self._parts.write(self._indent * self._depth)

    def _emit_block(self, block: Block):
        self._write('{')
        self._depth += 1
        for stmt in block.body:
            self._newline()
            self.visit(stmt)
        self._depth -= 1
        if block.body:
            self._newline()
        self._write('}')

    def _emit_statement_list(self, stmts: list):
        for i, stmt in enumerate(stmts):
            if i > 0:
                self._newline()
            self.visit(stmt)

    def generic_visit(self, node: Node):
        self._write(F'<{type(node).__name__}>')

    def visit_Ps1Variable(self, node: Ps1Variable):
        prefix = '@' if node.splatted else '$'
        scope_str = ''
        if node.scope != Ps1ScopeModifier.NONE:
            scope_str = F'{node.scope.value}:'
        name = F'{{{node.name}}}' if node.braced else node.name
        self._write(F'{prefix}{scope_str}{name}')

    def visit_Ps1IntegerLiteral(self, node: Ps1IntegerLiteral):
        self._write(node.raw)

    def visit_Ps1RealLiteral(self, node: Ps1RealLiteral):
        self._write(node.raw)

    def visit_Ps1StringLiteral(self, node: Ps1StringLiteral):
        self._write(node.raw)

    def visit_Ps1ExpandableString(self, node: Ps1ExpandableString):
        self._write('"')
        for part in node.parts:
            if isinstance(part, Ps1StringLiteral):
                self._write(self._escape_for_dq(part.value))
            elif isinstance(part, Ps1Variable):
                self._emit_variable_in_dq(part)
            else:
                self.visit(part)
        self._write('"')

    def _emit_variable_in_dq(self, node: Ps1Variable):
        prefix = '@' if node.splatted else '$'
        scope_str = ''
        if node.scope != Ps1ScopeModifier.NONE:
            scope_str = F'{node.scope.value}:'
        self._write(F'{prefix}{{{scope_str}{node.name}}}')

    @staticmethod
    def _escape_for_dq(value: str) -> str:
        return value.replace('`', '``').replace('"', '""').replace('$', '`$')

    def visit_Ps1HereString(self, node: Ps1HereString):
        self._write(node.raw)

    def visit_Ps1ExpandableHereString(self, node: Ps1ExpandableHereString):
        self._write(node.raw)

    def visit_Ps1BinaryExpression(self, node: Ps1BinaryExpression):
        spine: list[tuple[str, Expression | None]] = []
        current: Expression | None = node
        while isinstance(current, Ps1BinaryExpression):
            spine.append((current.operator, current.right))
            current = current.left
        if current:
            self.visit(current)
        for operator, right in reversed(spine):
            self._write(F' {operator} ')
            if right:
                self.visit(right)

    def visit_Ps1UnaryExpression(self, node: Ps1UnaryExpression):
        if node.prefix:
            self._write(node.operator)
            if node.operator.startswith('-') and len(node.operator) > 1:
                self._write(' ')
            if node.operand:
                self.visit(node.operand)
        else:
            if node.operand:
                self.visit(node.operand)
            self._write(node.operator)

    def visit_Ps1TypeExpression(self, node: Ps1TypeExpression):
        self._write(F'[{node.name}]')

    def visit_Ps1CastExpression(self, node: Ps1CastExpression):
        self._write(F'[{node.type_name}]')
        if node.operand:
            self.visit(node.operand)

    def visit_Ps1MemberAccess(self, node: Ps1MemberAccess):
        if node.object:
            self.visit(node.object)
        self._write(node.access.value)
        if isinstance(node.member, Expression):
            self.visit(node.member)
        else:
            self._write(str(node.member))

    def visit_Ps1IndexExpression(self, node: Ps1IndexExpression):
        if node.object:
            self.visit(node.object)
        self._write('[')
        if node.index:
            self.visit(node.index)
        self._write(']')

    def visit_Ps1InvokeMember(self, node: Ps1InvokeMember):
        if node.object:
            self.visit(node.object)
        self._write(node.access.value)
        if isinstance(node.member, Expression):
            self.visit(node.member)
        else:
            self._write(str(node.member))
        self._write('(')
        for i, arg in enumerate(node.arguments):
            if i > 0:
                self._write(', ')
            self.visit(arg)
        self._write(')')

    def visit_Ps1CommandInvocation(self, node: Ps1CommandInvocation):
        if node.invocation_operator:
            self._write(node.invocation_operator)
            self._write(' ')
        if node.name:
            self.visit(node.name)
        for arg in node.arguments:
            self._write(' ')
            self.visit(arg)

    def visit_Ps1CommandArgument(self, node: Ps1CommandArgument):
        if node.kind == Ps1CommandArgumentKind.SWITCH:
            self._write(node.name)
        elif node.kind == Ps1CommandArgumentKind.NAMED:
            self._write(F'{node.name}:')
            if node.value:
                self._emit_argument_value(node.value)
        elif node.kind == Ps1CommandArgumentKind.POSITIONAL:
            if node.value:
                self._emit_argument_value(node.value)

    def _emit_argument_value(self, value: Expression):
        if isinstance(value, Ps1BinaryExpression):
            self._write('(')
            self.visit(value)
            self._write(')')
        else:
            self.visit(value)

    def visit_Ps1CallExpression(self, node):
        if node.callee:
            self.visit(node.callee)
        self._write('(')
        for i, arg in enumerate(node.arguments):
            if i > 0:
                self._write(', ')
            self.visit(arg)
        self._write(')')

    def visit_Ps1AssignmentExpression(self, node: Ps1AssignmentExpression):
        if node.target:
            self.visit(node.target)
        self._write(F' {node.operator} ')
        if node.value:
            self.visit(node.value)

    def visit_Ps1ArrayLiteral(self, node: Ps1ArrayLiteral):
        for i, elem in enumerate(node.elements):
            if i > 0:
                self._write(', ')
            self.visit(elem)

    def visit_Ps1ArrayExpression(self, node: Ps1ArrayExpression):
        self._write('@(')
        self._emit_statement_list(node.body)
        self._write(')')

    def visit_Ps1HashLiteral(self, node: Ps1HashLiteral):
        self._write('@{')
        if node.pairs:
            self._depth += 1
            for key, value in node.pairs:
                self._newline()
                self.visit(key)
                self._write(' = ')
                self.visit(value)
            self._depth -= 1
            self._newline()
        self._write('}')

    def visit_Ps1SubExpression(self, node: Ps1SubExpression):
        self._write('$(')
        self._emit_statement_list(node.body)
        self._write(')')

    def visit_Ps1ParenExpression(self, node: Ps1ParenExpression):
        self._write('(')
        if node.expression:
            self.visit(node.expression)
        self._write(')')

    def visit_Ps1ScriptBlock(self, node: Ps1ScriptBlock):
        self._write('{')
        self._depth += 1
        if node.param_block:
            self._newline()
            self.visit(node.param_block)
        has_named = (
            node.begin_block or node.process_block
            or node.end_block or node.dynamicparam_block
        )
        if has_named:
            if node.begin_block:
                self._newline()
                self._write('begin ')
                self._emit_block(node.begin_block)
            if node.process_block:
                self._newline()
                self._write('process ')
                self._emit_block(node.process_block)
            if node.end_block:
                self._newline()
                self._write('end ')
                self._emit_block(node.end_block)
            if node.dynamicparam_block:
                self._newline()
                self._write('dynamicparam ')
                self._emit_block(node.dynamicparam_block)
        else:
            for stmt in node.body:
                self._newline()
                self.visit(stmt)
        self._depth -= 1
        if node.body or has_named or node.param_block:
            self._newline()
        self._write('}')

    def visit_Ps1RangeExpression(self, node: Ps1RangeExpression):
        if node.start:
            self.visit(node.start)
        self._write('..')
        if node.end:
            self.visit(node.end)

    def visit_Ps1Attribute(self, node: Ps1Attribute):
        self._write(F'[{node.name}')
        if node.positional_args or node.named_args:
            self._write('(')
            items: list[str] = []
            for arg in node.positional_args:
                old_parts = self._parts
                self._parts = io.StringIO()
                self.visit(arg)
                items.append(self._parts.getvalue())
                self._parts = old_parts
            for key, val in node.named_args:
                old_parts = self._parts
                self._parts = io.StringIO()
                self.visit(val)
                v = self._parts.getvalue()
                self._parts = old_parts
                items.append(F'{key}={v}')
            self._write(', '.join(items))
            self._write(')')
        self._write(']')

    def visit_Ps1ParameterDeclaration(self, node: Ps1ParameterDeclaration):
        for attr in node.attributes:
            self.visit(attr)
        if node.variable:
            self.visit(node.variable)
        if node.default_value:
            self._write(' = ')
            self.visit(node.default_value)

    def visit_Ps1ParamBlock(self, node: Ps1ParamBlock):
        for attr in node.attributes:
            self.visit(attr)
            self._newline()
        self._write(KEYWORD_SPELLING.get('param', 'param'))
        self._write('(')
        for i, param in enumerate(node.parameters):
            if i > 0:
                self._write(', ')
            self.visit(param)
        self._write(')')

    def visit_Ps1Redirection(self, node: Ps1Redirection):
        self._write(node.operator)
        self._write(' ')
        if node.target:
            self.visit(node.target)

    def visit_Ps1PipelineElement(self, node: Ps1PipelineElement):
        if node.expression:
            self.visit(node.expression)
        for redir in node.redirections:
            self._write(' ')
            self.visit(redir)

    def visit_Ps1Pipeline(self, node: Ps1Pipeline):
        for i, elem in enumerate(node.elements):
            if i > 0:
                self._write(' | ')
            self.visit(elem)

    def visit_Ps1ExpressionStatement(self, node: Ps1ExpressionStatement):
        if node.expression:
            self.visit(node.expression)

    def visit_Ps1IfStatement(self, node: Ps1IfStatement):
        for i, (cond, body) in enumerate(node.clauses):
            if i == 0:
                self._write('if (')
            else:
                self._write(' elseif (')
            if cond:
                self.visit(cond)
            self._write(') ')
            self._emit_block(body)
        if node.else_block:
            self._write(' else ')
            self._emit_block(node.else_block)

    def visit_Ps1WhileLoop(self, node: Ps1WhileLoop):
        if node.label:
            self._write(F'{node.label} ')
        self._write('while (')
        if node.condition:
            self.visit(node.condition)
        self._write(') ')
        if node.body:
            self._emit_block(node.body)

    def visit_Ps1DoWhileLoop(self, node: Ps1DoWhileLoop):
        if node.label:
            self._write(F'{node.label} ')
        self._write('do ')
        if node.body:
            self._emit_block(node.body)
        self._write(' while (')
        if node.condition:
            self.visit(node.condition)
        self._write(')')

    def visit_Ps1DoUntilLoop(self, node: Ps1DoUntilLoop):
        if node.label:
            self._write(F'{node.label} ')
        self._write('do ')
        if node.body:
            self._emit_block(node.body)
        self._write(' until (')
        if node.condition:
            self.visit(node.condition)
        self._write(')')

    def visit_Ps1ForLoop(self, node: Ps1ForLoop):
        if node.label:
            self._write(F'{node.label} ')
        self._write('for (')
        if node.initializer:
            self.visit(node.initializer)
        self._write('; ')
        if node.condition:
            self.visit(node.condition)
        self._write('; ')
        if node.iterator:
            self.visit(node.iterator)
        self._write(') ')
        if node.body:
            self._emit_block(node.body)

    def visit_Ps1ForEachLoop(self, node: Ps1ForEachLoop):
        if node.label:
            self._write(F'{node.label} ')
        self._write('foreach ')
        if node.parallel:
            self._write('-Parallel ')
        self._write('(')
        if node.variable:
            self.visit(node.variable)
        self._write(' in ')
        if node.iterable:
            self.visit(node.iterable)
        self._write(') ')
        if node.body:
            self._emit_block(node.body)

    def visit_Ps1SwitchStatement(self, node: Ps1SwitchStatement):
        if node.label:
            self._write(F'{node.label} ')
        self._write('switch ')
        if node.regex:
            self._write('-Regex ')
        if node.wildcard:
            self._write('-Wildcard ')
        if node.exact:
            self._write('-Exact ')
        if node.case_sensitive:
            self._write('-CaseSensitive ')
        if node.file:
            self._write('-File ')
            if node.value:
                self.visit(node.value)
            self._write(' {')
        else:
            self._write('(')
            if node.value:
                self.visit(node.value)
            self._write(') {')
        self._depth += 1
        for cond, body in node.clauses:
            self._newline()
            if cond is None:
                self._write('default ')
            else:
                self.visit(cond)
                self._write(' ')
            self._emit_block(body)
        self._depth -= 1
        self._newline()
        self._write('}')

    def visit_Ps1TryCatchFinally(self, node: Ps1TryCatchFinally):
        self._write('try ')
        if node.try_block:
            self._emit_block(node.try_block)
        for clause in node.catch_clauses:
            self._write(' catch')
            if clause.types:
                self._write(' ')
                self._write(' '.join(F'[{t}]' for t in clause.types))
            self._write(' ')
            if clause.body:
                self._emit_block(clause.body)
        if node.finally_block:
            self._write(' finally ')
            self._emit_block(node.finally_block)

    def visit_Ps1CatchClause(self, node: Ps1CatchClause):
        pass

    def visit_Ps1TrapStatement(self, node: Ps1TrapStatement):
        self._write('trap ')
        if node.type_name:
            self._write(F'[{node.type_name}] ')
        if node.body:
            self._emit_block(node.body)

    def visit_Ps1FunctionDefinition(self, node: Ps1FunctionDefinition):
        kw = 'filter' if node.is_filter else 'function'
        self._write(F'{kw} {node.name} ')
        if node.body:
            self.visit(node.body)

    def visit_Ps1ReturnStatement(self, node: Ps1ReturnStatement):
        self._write('return')
        if node.pipeline:
            self._write(' ')
            self.visit(node.pipeline)

    def visit_Ps1ThrowStatement(self, node: Ps1ThrowStatement):
        self._write('throw')
        if node.pipeline:
            self._write(' ')
            self.visit(node.pipeline)

    def visit_Ps1BreakStatement(self, node: Ps1BreakStatement):
        self._write('break')
        if node.label:
            self._write(' ')
            self.visit(node.label)

    def visit_Ps1ContinueStatement(self, node: Ps1ContinueStatement):
        self._write('continue')
        if node.label:
            self._write(' ')
            self.visit(node.label)

    def visit_Ps1ExitStatement(self, node: Ps1ExitStatement):
        self._write('exit')
        if node.pipeline:
            self._write(' ')
            self.visit(node.pipeline)

    def visit_Ps1DataSection(self, node: Ps1DataSection):
        self._write('data ')
        if node.name:
            self._write(F'{node.name} ')
        if node.commands:
            self._write('-SupportedCommand ')
            for i, cmd in enumerate(node.commands):
                if i > 0:
                    self._write(', ')
                self.visit(cmd)
            self._write(' ')
        if node.body:
            self._emit_block(node.body)

    def visit_Ps1ErrorNode(self, node: Ps1ErrorNode):
        self._write(node.text)

    def visit_Ps1Script(self, node: Ps1Script):
        if node.param_block:
            self.visit(node.param_block)
            self._newline()
        has_named = (
            node.begin_block or node.process_block
            or node.end_block or node.dynamicparam_block
        )
        if has_named:
            if node.begin_block:
                self._write('begin ')
                self._emit_block(node.begin_block)
                self._newline()
            if node.process_block:
                self._write('process ')
                self._emit_block(node.process_block)
                self._newline()
            if node.end_block:
                self._write('end ')
                self._emit_block(node.end_block)
                self._newline()
            if node.dynamicparam_block:
                self._write('dynamicparam ')
                self._emit_block(node.dynamicparam_block)
                self._newline()
        else:
            self._emit_statement_list(node.body)

    def visit_Block(self, node: Block):
        self._emit_block(node)

Ancestors

Methods

def convert(self, node)
Expand source code Browse git
def convert(self, node: Node) -> str:
    self._parts.seek(0)
    self._parts.truncate(0)
    self._depth = 0
    self.visit(node)
    return self._parts.getvalue()
def generic_visit(self, node)
Expand source code Browse git
def generic_visit(self, node: Node):
    self._write(F'<{type(node).__name__}>')
def visit_Ps1Variable(self, node)
Expand source code Browse git
def visit_Ps1Variable(self, node: Ps1Variable):
    prefix = '@' if node.splatted else '$'
    scope_str = ''
    if node.scope != Ps1ScopeModifier.NONE:
        scope_str = F'{node.scope.value}:'
    name = F'{{{node.name}}}' if node.braced else node.name
    self._write(F'{prefix}{scope_str}{name}')
def visit_Ps1IntegerLiteral(self, node)
Expand source code Browse git
def visit_Ps1IntegerLiteral(self, node: Ps1IntegerLiteral):
    self._write(node.raw)
def visit_Ps1RealLiteral(self, node)
Expand source code Browse git
def visit_Ps1RealLiteral(self, node: Ps1RealLiteral):
    self._write(node.raw)
def visit_Ps1StringLiteral(self, node)
Expand source code Browse git
def visit_Ps1StringLiteral(self, node: Ps1StringLiteral):
    self._write(node.raw)
def visit_Ps1ExpandableString(self, node)
Expand source code Browse git
def visit_Ps1ExpandableString(self, node: Ps1ExpandableString):
    self._write('"')
    for part in node.parts:
        if isinstance(part, Ps1StringLiteral):
            self._write(self._escape_for_dq(part.value))
        elif isinstance(part, Ps1Variable):
            self._emit_variable_in_dq(part)
        else:
            self.visit(part)
    self._write('"')
def visit_Ps1HereString(self, node)
Expand source code Browse git
def visit_Ps1HereString(self, node: Ps1HereString):
    self._write(node.raw)
def visit_Ps1ExpandableHereString(self, node)
Expand source code Browse git
def visit_Ps1ExpandableHereString(self, node: Ps1ExpandableHereString):
    self._write(node.raw)
def visit_Ps1BinaryExpression(self, node)
Expand source code Browse git
def visit_Ps1BinaryExpression(self, node: Ps1BinaryExpression):
    spine: list[tuple[str, Expression | None]] = []
    current: Expression | None = node
    while isinstance(current, Ps1BinaryExpression):
        spine.append((current.operator, current.right))
        current = current.left
    if current:
        self.visit(current)
    for operator, right in reversed(spine):
        self._write(F' {operator} ')
        if right:
            self.visit(right)
def visit_Ps1UnaryExpression(self, node)
Expand source code Browse git
def visit_Ps1UnaryExpression(self, node: Ps1UnaryExpression):
    if node.prefix:
        self._write(node.operator)
        if node.operator.startswith('-') and len(node.operator) > 1:
            self._write(' ')
        if node.operand:
            self.visit(node.operand)
    else:
        if node.operand:
            self.visit(node.operand)
        self._write(node.operator)
def visit_Ps1TypeExpression(self, node)
Expand source code Browse git
def visit_Ps1TypeExpression(self, node: Ps1TypeExpression):
    self._write(F'[{node.name}]')
def visit_Ps1CastExpression(self, node)
Expand source code Browse git
def visit_Ps1CastExpression(self, node: Ps1CastExpression):
    self._write(F'[{node.type_name}]')
    if node.operand:
        self.visit(node.operand)
def visit_Ps1MemberAccess(self, node)
Expand source code Browse git
def visit_Ps1MemberAccess(self, node: Ps1MemberAccess):
    if node.object:
        self.visit(node.object)
    self._write(node.access.value)
    if isinstance(node.member, Expression):
        self.visit(node.member)
    else:
        self._write(str(node.member))
def visit_Ps1IndexExpression(self, node)
Expand source code Browse git
def visit_Ps1IndexExpression(self, node: Ps1IndexExpression):
    if node.object:
        self.visit(node.object)
    self._write('[')
    if node.index:
        self.visit(node.index)
    self._write(']')
def visit_Ps1InvokeMember(self, node)
Expand source code Browse git
def visit_Ps1InvokeMember(self, node: Ps1InvokeMember):
    if node.object:
        self.visit(node.object)
    self._write(node.access.value)
    if isinstance(node.member, Expression):
        self.visit(node.member)
    else:
        self._write(str(node.member))
    self._write('(')
    for i, arg in enumerate(node.arguments):
        if i > 0:
            self._write(', ')
        self.visit(arg)
    self._write(')')
def visit_Ps1CommandInvocation(self, node)
Expand source code Browse git
def visit_Ps1CommandInvocation(self, node: Ps1CommandInvocation):
    if node.invocation_operator:
        self._write(node.invocation_operator)
        self._write(' ')
    if node.name:
        self.visit(node.name)
    for arg in node.arguments:
        self._write(' ')
        self.visit(arg)
def visit_Ps1CommandArgument(self, node)
Expand source code Browse git
def visit_Ps1CommandArgument(self, node: Ps1CommandArgument):
    if node.kind == Ps1CommandArgumentKind.SWITCH:
        self._write(node.name)
    elif node.kind == Ps1CommandArgumentKind.NAMED:
        self._write(F'{node.name}:')
        if node.value:
            self._emit_argument_value(node.value)
    elif node.kind == Ps1CommandArgumentKind.POSITIONAL:
        if node.value:
            self._emit_argument_value(node.value)
def visit_Ps1CallExpression(self, node)
Expand source code Browse git
def visit_Ps1CallExpression(self, node):
    if node.callee:
        self.visit(node.callee)
    self._write('(')
    for i, arg in enumerate(node.arguments):
        if i > 0:
            self._write(', ')
        self.visit(arg)
    self._write(')')
def visit_Ps1AssignmentExpression(self, node)
Expand source code Browse git
def visit_Ps1AssignmentExpression(self, node: Ps1AssignmentExpression):
    if node.target:
        self.visit(node.target)
    self._write(F' {node.operator} ')
    if node.value:
        self.visit(node.value)
def visit_Ps1ArrayLiteral(self, node)
Expand source code Browse git
def visit_Ps1ArrayLiteral(self, node: Ps1ArrayLiteral):
    for i, elem in enumerate(node.elements):
        if i > 0:
            self._write(', ')
        self.visit(elem)
def visit_Ps1ArrayExpression(self, node)
Expand source code Browse git
def visit_Ps1ArrayExpression(self, node: Ps1ArrayExpression):
    self._write('@(')
    self._emit_statement_list(node.body)
    self._write(')')
def visit_Ps1HashLiteral(self, node)
Expand source code Browse git
def visit_Ps1HashLiteral(self, node: Ps1HashLiteral):
    self._write('@{')
    if node.pairs:
        self._depth += 1
        for key, value in node.pairs:
            self._newline()
            self.visit(key)
            self._write(' = ')
            self.visit(value)
        self._depth -= 1
        self._newline()
    self._write('}')
def visit_Ps1SubExpression(self, node)
Expand source code Browse git
def visit_Ps1SubExpression(self, node: Ps1SubExpression):
    self._write('$(')
    self._emit_statement_list(node.body)
    self._write(')')
def visit_Ps1ParenExpression(self, node)
Expand source code Browse git
def visit_Ps1ParenExpression(self, node: Ps1ParenExpression):
    self._write('(')
    if node.expression:
        self.visit(node.expression)
    self._write(')')
def visit_Ps1ScriptBlock(self, node)
Expand source code Browse git
def visit_Ps1ScriptBlock(self, node: Ps1ScriptBlock):
    self._write('{')
    self._depth += 1
    if node.param_block:
        self._newline()
        self.visit(node.param_block)
    has_named = (
        node.begin_block or node.process_block
        or node.end_block or node.dynamicparam_block
    )
    if has_named:
        if node.begin_block:
            self._newline()
            self._write('begin ')
            self._emit_block(node.begin_block)
        if node.process_block:
            self._newline()
            self._write('process ')
            self._emit_block(node.process_block)
        if node.end_block:
            self._newline()
            self._write('end ')
            self._emit_block(node.end_block)
        if node.dynamicparam_block:
            self._newline()
            self._write('dynamicparam ')
            self._emit_block(node.dynamicparam_block)
    else:
        for stmt in node.body:
            self._newline()
            self.visit(stmt)
    self._depth -= 1
    if node.body or has_named or node.param_block:
        self._newline()
    self._write('}')
def visit_Ps1RangeExpression(self, node)
Expand source code Browse git
def visit_Ps1RangeExpression(self, node: Ps1RangeExpression):
    if node.start:
        self.visit(node.start)
    self._write('..')
    if node.end:
        self.visit(node.end)
def visit_Ps1Attribute(self, node)
Expand source code Browse git
def visit_Ps1Attribute(self, node: Ps1Attribute):
    self._write(F'[{node.name}')
    if node.positional_args or node.named_args:
        self._write('(')
        items: list[str] = []
        for arg in node.positional_args:
            old_parts = self._parts
            self._parts = io.StringIO()
            self.visit(arg)
            items.append(self._parts.getvalue())
            self._parts = old_parts
        for key, val in node.named_args:
            old_parts = self._parts
            self._parts = io.StringIO()
            self.visit(val)
            v = self._parts.getvalue()
            self._parts = old_parts
            items.append(F'{key}={v}')
        self._write(', '.join(items))
        self._write(')')
    self._write(']')
def visit_Ps1ParameterDeclaration(self, node)
Expand source code Browse git
def visit_Ps1ParameterDeclaration(self, node: Ps1ParameterDeclaration):
    for attr in node.attributes:
        self.visit(attr)
    if node.variable:
        self.visit(node.variable)
    if node.default_value:
        self._write(' = ')
        self.visit(node.default_value)
def visit_Ps1ParamBlock(self, node)
Expand source code Browse git
def visit_Ps1ParamBlock(self, node: Ps1ParamBlock):
    for attr in node.attributes:
        self.visit(attr)
        self._newline()
    self._write(KEYWORD_SPELLING.get('param', 'param'))
    self._write('(')
    for i, param in enumerate(node.parameters):
        if i > 0:
            self._write(', ')
        self.visit(param)
    self._write(')')
def visit_Ps1Redirection(self, node)
Expand source code Browse git
def visit_Ps1Redirection(self, node: Ps1Redirection):
    self._write(node.operator)
    self._write(' ')
    if node.target:
        self.visit(node.target)
def visit_Ps1PipelineElement(self, node)
Expand source code Browse git
def visit_Ps1PipelineElement(self, node: Ps1PipelineElement):
    if node.expression:
        self.visit(node.expression)
    for redir in node.redirections:
        self._write(' ')
        self.visit(redir)
def visit_Ps1Pipeline(self, node)
Expand source code Browse git
def visit_Ps1Pipeline(self, node: Ps1Pipeline):
    for i, elem in enumerate(node.elements):
        if i > 0:
            self._write(' | ')
        self.visit(elem)
def visit_Ps1ExpressionStatement(self, node)
Expand source code Browse git
def visit_Ps1ExpressionStatement(self, node: Ps1ExpressionStatement):
    if node.expression:
        self.visit(node.expression)
def visit_Ps1IfStatement(self, node)
Expand source code Browse git
def visit_Ps1IfStatement(self, node: Ps1IfStatement):
    for i, (cond, body) in enumerate(node.clauses):
        if i == 0:
            self._write('if (')
        else:
            self._write(' elseif (')
        if cond:
            self.visit(cond)
        self._write(') ')
        self._emit_block(body)
    if node.else_block:
        self._write(' else ')
        self._emit_block(node.else_block)
def visit_Ps1WhileLoop(self, node)
Expand source code Browse git
def visit_Ps1WhileLoop(self, node: Ps1WhileLoop):
    if node.label:
        self._write(F'{node.label} ')
    self._write('while (')
    if node.condition:
        self.visit(node.condition)
    self._write(') ')
    if node.body:
        self._emit_block(node.body)
def visit_Ps1DoWhileLoop(self, node)
Expand source code Browse git
def visit_Ps1DoWhileLoop(self, node: Ps1DoWhileLoop):
    if node.label:
        self._write(F'{node.label} ')
    self._write('do ')
    if node.body:
        self._emit_block(node.body)
    self._write(' while (')
    if node.condition:
        self.visit(node.condition)
    self._write(')')
def visit_Ps1DoUntilLoop(self, node)
Expand source code Browse git
def visit_Ps1DoUntilLoop(self, node: Ps1DoUntilLoop):
    if node.label:
        self._write(F'{node.label} ')
    self._write('do ')
    if node.body:
        self._emit_block(node.body)
    self._write(' until (')
    if node.condition:
        self.visit(node.condition)
    self._write(')')
def visit_Ps1ForLoop(self, node)
Expand source code Browse git
def visit_Ps1ForLoop(self, node: Ps1ForLoop):
    if node.label:
        self._write(F'{node.label} ')
    self._write('for (')
    if node.initializer:
        self.visit(node.initializer)
    self._write('; ')
    if node.condition:
        self.visit(node.condition)
    self._write('; ')
    if node.iterator:
        self.visit(node.iterator)
    self._write(') ')
    if node.body:
        self._emit_block(node.body)
def visit_Ps1ForEachLoop(self, node)
Expand source code Browse git
def visit_Ps1ForEachLoop(self, node: Ps1ForEachLoop):
    if node.label:
        self._write(F'{node.label} ')
    self._write('foreach ')
    if node.parallel:
        self._write('-Parallel ')
    self._write('(')
    if node.variable:
        self.visit(node.variable)
    self._write(' in ')
    if node.iterable:
        self.visit(node.iterable)
    self._write(') ')
    if node.body:
        self._emit_block(node.body)
def visit_Ps1SwitchStatement(self, node)
Expand source code Browse git
def visit_Ps1SwitchStatement(self, node: Ps1SwitchStatement):
    if node.label:
        self._write(F'{node.label} ')
    self._write('switch ')
    if node.regex:
        self._write('-Regex ')
    if node.wildcard:
        self._write('-Wildcard ')
    if node.exact:
        self._write('-Exact ')
    if node.case_sensitive:
        self._write('-CaseSensitive ')
    if node.file:
        self._write('-File ')
        if node.value:
            self.visit(node.value)
        self._write(' {')
    else:
        self._write('(')
        if node.value:
            self.visit(node.value)
        self._write(') {')
    self._depth += 1
    for cond, body in node.clauses:
        self._newline()
        if cond is None:
            self._write('default ')
        else:
            self.visit(cond)
            self._write(' ')
        self._emit_block(body)
    self._depth -= 1
    self._newline()
    self._write('}')
def visit_Ps1TryCatchFinally(self, node)
Expand source code Browse git
def visit_Ps1TryCatchFinally(self, node: Ps1TryCatchFinally):
    self._write('try ')
    if node.try_block:
        self._emit_block(node.try_block)
    for clause in node.catch_clauses:
        self._write(' catch')
        if clause.types:
            self._write(' ')
            self._write(' '.join(F'[{t}]' for t in clause.types))
        self._write(' ')
        if clause.body:
            self._emit_block(clause.body)
    if node.finally_block:
        self._write(' finally ')
        self._emit_block(node.finally_block)
def visit_Ps1CatchClause(self, node)
Expand source code Browse git
def visit_Ps1CatchClause(self, node: Ps1CatchClause):
    pass
def visit_Ps1TrapStatement(self, node)
Expand source code Browse git
def visit_Ps1TrapStatement(self, node: Ps1TrapStatement):
    self._write('trap ')
    if node.type_name:
        self._write(F'[{node.type_name}] ')
    if node.body:
        self._emit_block(node.body)
def visit_Ps1FunctionDefinition(self, node)
Expand source code Browse git
def visit_Ps1FunctionDefinition(self, node: Ps1FunctionDefinition):
    kw = 'filter' if node.is_filter else 'function'
    self._write(F'{kw} {node.name} ')
    if node.body:
        self.visit(node.body)
def visit_Ps1ReturnStatement(self, node)
Expand source code Browse git
def visit_Ps1ReturnStatement(self, node: Ps1ReturnStatement):
    self._write('return')
    if node.pipeline:
        self._write(' ')
        self.visit(node.pipeline)
def visit_Ps1ThrowStatement(self, node)
Expand source code Browse git
def visit_Ps1ThrowStatement(self, node: Ps1ThrowStatement):
    self._write('throw')
    if node.pipeline:
        self._write(' ')
        self.visit(node.pipeline)
def visit_Ps1BreakStatement(self, node)
Expand source code Browse git
def visit_Ps1BreakStatement(self, node: Ps1BreakStatement):
    self._write('break')
    if node.label:
        self._write(' ')
        self.visit(node.label)
def visit_Ps1ContinueStatement(self, node)
Expand source code Browse git
def visit_Ps1ContinueStatement(self, node: Ps1ContinueStatement):
    self._write('continue')
    if node.label:
        self._write(' ')
        self.visit(node.label)
def visit_Ps1ExitStatement(self, node)
Expand source code Browse git
def visit_Ps1ExitStatement(self, node: Ps1ExitStatement):
    self._write('exit')
    if node.pipeline:
        self._write(' ')
        self.visit(node.pipeline)
def visit_Ps1DataSection(self, node)
Expand source code Browse git
def visit_Ps1DataSection(self, node: Ps1DataSection):
    self._write('data ')
    if node.name:
        self._write(F'{node.name} ')
    if node.commands:
        self._write('-SupportedCommand ')
        for i, cmd in enumerate(node.commands):
            if i > 0:
                self._write(', ')
            self.visit(cmd)
        self._write(' ')
    if node.body:
        self._emit_block(node.body)
def visit_Ps1ErrorNode(self, node)
Expand source code Browse git
def visit_Ps1ErrorNode(self, node: Ps1ErrorNode):
    self._write(node.text)
def visit_Ps1Script(self, node)
Expand source code Browse git
def visit_Ps1Script(self, node: Ps1Script):
    if node.param_block:
        self.visit(node.param_block)
        self._newline()
    has_named = (
        node.begin_block or node.process_block
        or node.end_block or node.dynamicparam_block
    )
    if has_named:
        if node.begin_block:
            self._write('begin ')
            self._emit_block(node.begin_block)
            self._newline()
        if node.process_block:
            self._write('process ')
            self._emit_block(node.process_block)
            self._newline()
        if node.end_block:
            self._write('end ')
            self._emit_block(node.end_block)
            self._newline()
        if node.dynamicparam_block:
            self._write('dynamicparam ')
            self._emit_block(node.dynamicparam_block)
            self._newline()
    else:
        self._emit_statement_list(node.body)
def visit_Block(self, node)
Expand source code Browse git
def visit_Block(self, node: Block):
    self._emit_block(node)