fixed ast parent pointers

This commit is contained in:
Irmen de Jong 2018-01-30 01:38:37 +01:00
parent 4d70e3d42f
commit d299742ddf
8 changed files with 224 additions and 138 deletions

View File

@ -40,6 +40,7 @@ class PlyParser:
# the following shall only be done on the main module after all imports have been done:
self.apply_directive_options(module)
self.determine_subroutine_usage(module)
self.all_parents_connected(module)
self.semantic_check(module)
self.allocate_zeropage_vars(module)
except ParseError as x:
@ -68,6 +69,18 @@ class PlyParser:
raise ParseError("last statement in a block/subroutine must be a return or goto, "
"(or %noreturn directive to silence this error)", last_stmt.sourceref)
def all_parents_connected(self, module: Module) -> None:
# check that all parents are connected in all nodes
def check(node: AstNode, expected_parent: AstNode) -> None:
if node.parent is not expected_parent:
raise CompileError("parent node invalid", node, node.parent, expected_parent, node.sourceref, expected_parent.sourceref)
for child_node in node.nodes:
if isinstance(child_node, AstNode):
check(child_node, node)
else:
raise TypeError("invalid child node type", child_node, " in ", node, " sref", node.sourceref)
check(module, None)
def semantic_check(self, module: Module) -> None:
# perform semantic analysis / checks on the syntactic parse tree we have so far
# (note: symbol names have already been checked to exist when we start this)
@ -203,12 +216,15 @@ class PlyParser:
@no_type_check
def create_multiassigns(self, module: Module) -> None:
# create multi-assign statements from nested assignments (A=B=C=5),
# and optimize TargetRegisters down to single Register if it's just one register.
# @todo optimize TargetRegisters down to single Register if it's just one register.
def reduce_right(assign: Assignment) -> Assignment:
if isinstance(assign.right, Assignment):
right = reduce_right(assign.right)
for rn in right.left.nodes:
rn.parent = assign.left
assign.left.nodes.extend(right.left.nodes)
assign.right = right.right
assign.right.parent = assign
return assign
for node in module.all_nodes(Assignment):
@ -325,12 +341,10 @@ class PlyParser:
elif isinstance(expr, ExpressionWithOperator):
self._get_subroutine_usages_from_expression(usages, expr.left, parent_scope)
self._get_subroutine_usages_from_expression(usages, expr.right, parent_scope)
elif isinstance(expr, LiteralValue):
elif isinstance(expr, (LiteralValue, AddressOf)):
return
elif isinstance(expr, Dereference):
return self._get_subroutine_usages_from_expression(usages, expr.operand, parent_scope)
elif isinstance(expr, AddressOf):
return self._get_subroutine_usages_from_expression(usages, expr.name, parent_scope)
elif isinstance(expr, SymbolName):
try:
symbol = parent_scope.lookup(expr.name)

View File

@ -7,7 +7,7 @@ Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
from collections import defaultdict
from typing import Dict, List, Callable, Any, no_type_check
from ..plyparse import Block, VarType, VarDef, LiteralValue
from ..plyparse import Block, VarType, VarDef, LiteralValue, AddressOf
from ..datatypes import DataType, STRING_DATATYPES
from . import to_hex, to_mflpt5, CodeError
@ -66,6 +66,8 @@ def generate_block_init(out: Callable, block: Block) -> None:
prev_value_a = bytevar.value.value
out("\vsta {:s}".format(bytevar.name))
for wordvar in sorted(vars_by_datatype[DataType.WORD], key=lambda vd: vd.value):
if isinstance(wordvar.value, AddressOf):
raise CodeError("can't yet use addressof here", wordvar.sourceref) # XXX
assert isinstance(wordvar.value, LiteralValue) and type(wordvar.value.value) is int
v_hi, v_lo = divmod(wordvar.value.value, 256)
if v_hi != prev_value_a:

View File

@ -64,7 +64,8 @@ class Optimizer:
evaluated = process_expression(expression) # type: ignore
if evaluated is not expression:
# replace the node with the newly evaluated result
expression.parent.replace_node(expression, evaluated)
parent = expression.parent
parent.replace_node(expression, evaluated)
self.optimizations_performed = True
except ParseError:
raise
@ -389,15 +390,18 @@ class Optimizer:
node.my_scope().nodes.remove(node)
def process_expression(expr: Expression) -> Any:
def process_expression(expr: Expression) -> Expression:
# process/simplify all expressions (constant folding etc)
result = None # type: Expression
if expr.is_compile_constant() or isinstance(expr, ExpressionWithOperator) and expr.must_be_constant:
return process_constant_expression(expr, expr.sourceref)
result = _process_constant_expression(expr, expr.sourceref)
else:
return process_dynamic_expression(expr, expr.sourceref)
result = _process_dynamic_expression(expr, expr.sourceref)
result.parent = expr.parent
return result
def process_constant_expression(expr: Expression, sourceref: SourceRef) -> LiteralValue:
def _process_constant_expression(expr: Expression, sourceref: SourceRef) -> LiteralValue:
# the expression must result in a single (constant) value (int, float, whatever) wrapped as LiteralValue.
if isinstance(expr, LiteralValue):
return expr
@ -418,8 +422,8 @@ def process_constant_expression(expr: Expression, sourceref: SourceRef) -> Liter
else:
raise ExpressionEvaluationError("constant symbol required, not {}".format(value.__class__.__name__), expr.sourceref)
elif isinstance(expr, AddressOf):
assert isinstance(expr.name, SymbolName)
value = check_symbol_definition(expr.name.name, expr.my_scope(), expr.sourceref)
assert isinstance(expr.name, str)
value = check_symbol_definition(expr.name, expr.my_scope(), expr.sourceref)
if isinstance(value, VarDef):
if value.vartype == VarType.MEMORY:
if isinstance(value.value, LiteralValue):
@ -427,18 +431,18 @@ def process_constant_expression(expr: Expression, sourceref: SourceRef) -> Liter
else:
raise ExpressionEvaluationError("constant literal value required", value.sourceref)
if value.vartype == VarType.CONST:
raise ExpressionEvaluationError("can't take the address of a constant", expr.name.sourceref)
raise ExpressionEvaluationError("can't take the address of a constant", expr.sourceref)
raise ExpressionEvaluationError("address-of this {} isn't a compile-time constant"
.format(value.__class__.__name__), expr.name.sourceref)
.format(value.__class__.__name__), expr.sourceref)
else:
raise ExpressionEvaluationError("constant address required, not {}"
.format(value.__class__.__name__), expr.name.sourceref)
.format(value.__class__.__name__), expr.sourceref)
elif isinstance(expr, SubCall):
if isinstance(expr.target, SymbolName): # 'function(1,2,3)'
funcname = expr.target.name
if funcname in math_functions or funcname in builtin_functions:
func_args = []
for a in (process_constant_expression(callarg.value, sourceref) for callarg in expr.arguments.nodes):
for a in (_process_constant_expression(callarg.value, sourceref) for callarg in list(expr.arguments.nodes)):
if isinstance(a, LiteralValue):
func_args.append(a.value)
else:
@ -459,7 +463,8 @@ def process_constant_expression(expr: Expression, sourceref: SourceRef) -> Liter
elif isinstance(expr, ExpressionWithOperator):
if expr.unary:
left_sourceref = expr.left.sourceref if isinstance(expr.left, AstNode) else sourceref
expr.left = process_constant_expression(expr.left, left_sourceref)
expr.left = _process_constant_expression(expr.left, left_sourceref)
expr.left.parent = expr
if isinstance(expr.left, LiteralValue) and type(expr.left.value) in (int, float):
try:
if expr.operator == '-':
@ -474,9 +479,11 @@ def process_constant_expression(expr: Expression, sourceref: SourceRef) -> Liter
raise ValueError("invalid operand type for unary operator", expr.left, expr.operator)
else:
left_sourceref = expr.left.sourceref if isinstance(expr.left, AstNode) else sourceref
expr.left = process_constant_expression(expr.left, left_sourceref)
expr.left = _process_constant_expression(expr.left, left_sourceref)
expr.left.parent = expr
right_sourceref = expr.right.sourceref if isinstance(expr.right, AstNode) else sourceref
expr.right = process_constant_expression(expr.right, right_sourceref)
expr.right = _process_constant_expression(expr.right, right_sourceref)
expr.right.parent = expr
if isinstance(expr.left, LiteralValue):
if isinstance(expr.right, LiteralValue):
return expr.evaluate_primitive_constants(expr.right.sourceref)
@ -490,7 +497,7 @@ def process_constant_expression(expr: Expression, sourceref: SourceRef) -> Liter
raise ExpressionEvaluationError("constant value required, not {}".format(expr.__class__.__name__), expr.sourceref)
def process_dynamic_expression(expr: Expression, sourceref: SourceRef) -> Any:
def _process_dynamic_expression(expr: Expression, sourceref: SourceRef) -> Expression:
# constant-fold a dynamic expression
if isinstance(expr, LiteralValue):
return expr
@ -498,17 +505,17 @@ def process_dynamic_expression(expr: Expression, sourceref: SourceRef) -> Any:
return LiteralValue(value=expr.const_value(), sourceref=sourceref) # type: ignore
elif isinstance(expr, SymbolName):
try:
return process_constant_expression(expr, sourceref)
return _process_constant_expression(expr, sourceref)
except ExpressionEvaluationError:
return expr
elif isinstance(expr, AddressOf):
try:
return process_constant_expression(expr, sourceref)
return _process_constant_expression(expr, sourceref)
except ExpressionEvaluationError:
return expr
elif isinstance(expr, SubCall):
try:
return process_constant_expression(expr, sourceref)
return _process_constant_expression(expr, sourceref)
except ExpressionEvaluationError:
if isinstance(expr.target, SymbolName):
check_symbol_definition(expr.target.name, expr.my_scope(), expr.target.sourceref)
@ -522,18 +529,21 @@ def process_dynamic_expression(expr: Expression, sourceref: SourceRef) -> Any:
elif isinstance(expr, ExpressionWithOperator):
if expr.unary:
left_sourceref = expr.left.sourceref if isinstance(expr.left, AstNode) else sourceref
expr.left = process_dynamic_expression(expr.left, left_sourceref)
expr.left = _process_dynamic_expression(expr.left, left_sourceref)
expr.left.parent = expr
try:
return process_constant_expression(expr, sourceref)
return _process_constant_expression(expr, sourceref)
except ExpressionEvaluationError:
return expr
else:
left_sourceref = expr.left.sourceref if isinstance(expr.left, AstNode) else sourceref
expr.left = process_dynamic_expression(expr.left, left_sourceref)
expr.left = _process_dynamic_expression(expr.left, left_sourceref)
expr.left.parent = expr
right_sourceref = expr.right.sourceref if isinstance(expr.right, AstNode) else sourceref
expr.right = process_dynamic_expression(expr.right, right_sourceref)
expr.right = _process_dynamic_expression(expr.right, right_sourceref)
expr.right.parent = expr
try:
return process_constant_expression(expr, sourceref)
return _process_constant_expression(expr, sourceref)
except ExpressionEvaluationError:
return expr
else:

View File

@ -86,12 +86,17 @@ class AstNode:
yield from node.all_nodes(*nodetypes)
def remove_node(self, node: 'AstNode') -> None:
assert node.parent is self
self.nodes.remove(node)
node.parent = None
def replace_node(self, oldnode: 'AstNode', newnode: 'AstNode') -> None:
assert oldnode.parent is self
assert isinstance(newnode, AstNode)
idx = self.nodes.index(oldnode)
self.nodes[idx] = newnode
newnode.parent = self
oldnode.parent = None
def add_node(self, newnode: 'AstNode', index: int = None) -> None:
assert isinstance(newnode, AstNode)
@ -99,6 +104,7 @@ class AstNode:
self.nodes.append(newnode)
else:
self.nodes.insert(index, newnode)
newnode.parent = self
@attr.s(cmp=False)
@ -421,7 +427,7 @@ class LiteralValue(Expression):
@attr.s(cmp=False)
class AddressOf(Expression):
# no subnodes.
name = attr.ib(type=str)
name = attr.ib(type=str, validator=attr.validators._InstanceOfValidator(type=str))
def is_compile_constant(self) -> bool:
return False
@ -455,12 +461,12 @@ class SymbolName(Expression):
@attr.s(cmp=False)
class Dereference(Expression):
# one subnode: operand (SymbolName, int or register name)
# one subnode: operand (SymbolName, integer LiteralValue or Register)
datatype = attr.ib()
size = attr.ib(type=int, default=None)
@property
def operand(self) -> Union[SymbolName, int, str]:
def operand(self) -> Union[SymbolName, LiteralValue, Register]:
return self.nodes[0] # type: ignore
def __attrs_post_init__(self):
@ -475,6 +481,8 @@ class Dereference(Expression):
if not self.datatype.to_enum().isnumeric():
raise ParseError("dereference target value must be byte, word, float", self.datatype.sourceref)
self.datatype = self.datatype.to_enum()
if self.nodes and not isinstance(self.nodes[0], (SymbolName, LiteralValue, Register)):
raise TypeError("operand of dereference invalid type", self.nodes[0], self.sourceref)
def is_compile_constant(self) -> bool:
return False
@ -514,13 +522,34 @@ class IncrDecr(AstNode):
@attr.s(cmp=False, slots=True, repr=False)
class ExpressionWithOperator(Expression):
left = attr.ib() # type: Expression
# 2 nodes: left (Expression), right (not present if unary, Expression if not unary)
operator = attr.ib(type=str)
right = attr.ib() # type: Expression
unary = attr.ib(type=bool, default=False)
# when evaluating the expression, does it have to be a compile-time constant value?
must_be_constant = attr.ib(type=bool, init=False, default=False)
@property
def unary(self) -> bool:
return len(self.nodes) == 1
@property
def left(self) -> Expression:
return self.nodes[0] # type: ignore
@left.setter
def left(self, newleft: Expression) -> None:
if self.nodes:
self.nodes[0] = newleft
else:
self.nodes.append(newleft)
@property
def right(self) -> Optional[Expression]:
return self.nodes[1] if len(self.nodes) == 2 else None # type: ignore
@right.setter
def right(self, newright: Expression) -> None:
self.nodes[1] = newright
def __attrs_post_init__(self):
assert self.operator not in ("++", "--"), "incr/decr should not be an expression"
if self.operator == "mod":
@ -540,7 +569,9 @@ class ExpressionWithOperator(Expression):
raise ValueError("operator", self.operator)
estr = "{} {} {}".format(repr(self.left.value), self.operator, repr(self.right.value))
try:
return LiteralValue(value=eval(estr, {}, {}), sourceref=sourceref) # type: ignore # safe because of checks above
lv = LiteralValue(value=eval(estr, {}, {}), sourceref=sourceref) # type: ignore # safe because of checks above
lv.parent = self.parent
return lv
except ZeroDivisionError:
raise ParseError("division by zero", sourceref)
except Exception as x:
@ -580,12 +611,12 @@ class CallArguments(AstNode):
@attr.s(cmp=False, repr=False)
class SubCall(Expression):
# has three subnodes:
# 0: target (Symbolname, int, or Dereference),
# 0: target (Symbolname, integer LiteralValue, or Dereference),
# 1: preserve_regs (PreserveRegs)
# 2: arguments (CallArguments).
@property
def target(self) -> Union[SymbolName, int, Dereference]:
def target(self) -> Union[SymbolName, LiteralValue, Dereference]:
return self.nodes[0] # type: ignore
@property
@ -659,6 +690,7 @@ class VarDef(AstNode):
print("warning: {}: array/matrix with size 1, use normal byte/word instead".format(self.sourceref))
if self.value is None and (self.datatype.isnumeric() or self.datatype.isarray()):
self.value = LiteralValue(value=0, sourceref=self.sourceref)
self.value.parent = self
# if it's a matrix with interleave, it must be memory mapped
if self.datatype == DataType.MATRIX and len(self.size) == 3:
if self.vartype != VarType.MEMORY:
@ -795,7 +827,9 @@ def coerce_constant_value(datatype: DataType, value: AstNode,
if isinstance(value, LiteralValue):
if type(value.value) is str and len(value.value) == 1 and (datatype.isnumeric() or datatype.isarray()):
# convert a string of length 1 to its numeric character value
return True, LiteralValue(value=char_to_bytevalue(value.value), sourceref=value.sourceref) # type: ignore
lv = LiteralValue(value=char_to_bytevalue(value.value), sourceref=value.sourceref) # type: ignore
lv.parent = value.parent
return True, lv
# if we're an integer value and the passed value is float, truncate it (and give a warning)
if datatype in (DataType.BYTE, DataType.WORD, DataType.MATRIX) and isinstance(value.value, float):
frac = math.modf(value.value)
@ -803,7 +837,9 @@ def coerce_constant_value(datatype: DataType, value: AstNode,
print_warning("float value truncated ({} to datatype {})".format(value.value, datatype.name), sourceref=sourceref)
v2 = int(value.value)
verify_bounds(v2)
return True, LiteralValue(value=v2, sourceref=value.sourceref) # type: ignore
lv = LiteralValue(value=v2, sourceref=value.sourceref) # type: ignore
lv.parent = value.parent
return True, lv
if type(value.value) in (int, float):
verify_bounds(value.value)
if datatype == DataType.WORD:
@ -821,7 +857,9 @@ def coerce_constant_value(datatype: DataType, value: AstNode,
elif isinstance(value, AddressOf):
try:
address = value.const_value()
return True, LiteralValue(value=address, sourceref=value.sourceref) # type: ignore
lv = LiteralValue(value=address, sourceref=value.sourceref) # type: ignore
lv.parent = value.parent
return True, lv
except TypeError:
return False, value
if datatype == DataType.WORD and not isinstance(value, (LiteralValue, Dereference, Register, SymbolName, AddressOf)):
@ -1174,8 +1212,11 @@ def p_call_subroutine(p):
"""
sref = _token_sref(p, 3)
p[0] = SubCall(sourceref=sref)
p[0].nodes.append(p[1])
p[0].nodes.append(p[2])
target = p[1]
if isinstance(target, int):
target = LiteralValue(value=target, sourceref=sref)
p[0].nodes.append(target)
p[0].nodes.append(p[2] or PreserveRegs(registers="", sourceref=sref))
p[0].nodes.append(CallArguments(nodes=p[4] or [], sourceref=sref))
@ -1300,7 +1341,14 @@ def p_dereference(p):
dereference : '[' dereference_operand ']'
"""
p[0] = Dereference(datatype=p[2][1], sourceref=_token_sref(p, 1))
p[0].nodes.append(p[2][0])
operand = p[2][0]
if isinstance(operand, int):
p[0].nodes.append(LiteralValue(value=operand, sourceref=p[0].sourceref))
elif isinstance(operand, str):
p[0].nodes.append(Register(name=operand, sourceref=p[0].sourceref))
elif isinstance(operand, SymbolName):
p[0].nodes.append(operand)
attr.validate(p[0])
def p_dereference_operand(p):
@ -1380,35 +1428,40 @@ def p_expression(p):
| expression EQUALS expression
| expression NOTEQUALS expression
"""
p[0] = ExpressionWithOperator(left=p[1], operator=p[2], right=p[3], sourceref=_token_sref(p, 2))
p[0] = ExpressionWithOperator(operator=p[2], sourceref=_token_sref(p, 2))
p[0].nodes.append(p[1])
p[0].nodes.append(p[3])
def p_expression_uminus(p):
"""
expression : '-' expression %prec UNARY_MINUS
"""
p[0] = ExpressionWithOperator(left=p[2], operator=p[1], right=None, unary=True, sourceref=_token_sref(p, 1))
p[0] = ExpressionWithOperator(operator=p[1], sourceref=_token_sref(p, 1))
p[0].nodes.append(p[2])
def p_expression_addressof(p):
"""
expression : BITAND symbolname %prec UNARY_ADDRESSOF
"""
p[0] = AddressOf(name=p[2], sourceref=_token_sref(p, 1))
p[0] = AddressOf(name=p[2].name, sourceref=_token_sref(p, 1))
def p_unary_expression_bitinvert(p):
"""
expression : BITINVERT expression
"""
p[0] = ExpressionWithOperator(left=p[2], operator=p[1], right=None, unary=True, sourceref=_token_sref(p, 1))
p[0] = ExpressionWithOperator(operator=p[1], sourceref=_token_sref(p, 1))
p[0].nodes.append(p[2])
def p_unary_expression_logicnot(p):
"""
expression : LOGICNOT expression
"""
p[0] = ExpressionWithOperator(left=p[2], operator=p[1], right=None, unary=True, sourceref=_token_sref(p, 1))
p[0] = ExpressionWithOperator(operator=p[1], sourceref=_token_sref(p, 1))
p[0].nodes.append(p[2])
def p_expression_group(p):

View File

@ -1,7 +1,7 @@
import pytest
from il65.plylex import lexer, tokens, find_tok_column, literals, reserved, SourceRef
from il65.plyparse import parser, connect_parents, TokenFilter, Module, Subroutine, Block, IncrDecr, Scope, \
VarDef, Expression, ExpressionWithOperator, LiteralValue, Label, SubCall, Dereference
VarDef, Register, ExpressionWithOperator, LiteralValue, Label, SubCall, Dereference
from il65.datatypes import DataType
@ -137,7 +137,7 @@ def test_parser():
assert sub2 is sub
assert sub2.lineref == "src l. 19"
all_nodes = list(result.all_nodes())
assert len(all_nodes) == 12
assert len(all_nodes) == 14
all_nodes = list(result.all_nodes(Subroutine))
assert len(all_nodes) == 1
assert isinstance(all_nodes[0], Subroutine)
@ -176,8 +176,8 @@ def test_parser_2():
call = block.scope.nodes[0]
assert isinstance(call, SubCall)
assert len(call.arguments.nodes) == 2
assert isinstance(call.target, int)
assert call.target == 999
assert isinstance(call.target, LiteralValue)
assert call.target.value == 999
call = block.scope.nodes[1]
assert isinstance(call, SubCall)
assert len(call.arguments.nodes) == 0
@ -219,10 +219,14 @@ def test_typespec():
assert isinstance(t2, Dereference)
assert isinstance(t3, Dereference)
assert isinstance(t4, Dereference)
assert t1.operand == 0xc000
assert t2.operand == 0xc000
assert t3.operand == "AX"
assert t4.operand == "AX"
assert isinstance(t1.operand, LiteralValue)
assert isinstance(t2.operand, LiteralValue)
assert isinstance(t3.operand, Register)
assert isinstance(t4.operand, Register)
assert t1.operand.value == 0xc000
assert t2.operand.value == 0xc000
assert t3.operand.name == "AX"
assert t4.operand.name == "AX"
assert t1.datatype == DataType.WORD
assert t2.datatype == DataType.BYTE
assert t3.datatype == DataType.WORD

View File

@ -61,7 +61,8 @@ def test_set_value():
assert v.value is None
v.value = LiteralValue(value="hello", sourceref=sref)
assert v.value.value == "hello"
e = ExpressionWithOperator(left=LiteralValue(value=42, sourceref=sref), operator="-", unary=True, right=None, sourceref=sref)
e = ExpressionWithOperator(operator="-", sourceref=sref)
e.left = LiteralValue(value=42, sourceref=sref)
assert not e.must_be_constant
v.value = e
assert v.value is e
@ -94,7 +95,8 @@ def test_const_value():
assert v.const_value() == 0
v.value = LiteralValue(value=42.9988, sourceref=sref)
assert v.const_value() == 42.9988
e = ExpressionWithOperator(left=LiteralValue(value=42, sourceref=sref), operator="-", unary=True, right=None, sourceref=sref)
e = ExpressionWithOperator(operator="-", sourceref=sref)
e.left = LiteralValue(value=42, sourceref=sref)
v.value = e
with pytest.raises(TypeError):
v.const_value()

View File

@ -313,7 +313,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -321,7 +321,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -353,7 +353,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -378,7 +378,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -667,7 +667,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -675,7 +675,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -707,7 +707,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -732,7 +732,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -1021,7 +1021,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -1029,7 +1029,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -1061,7 +1061,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -1086,7 +1086,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -1375,7 +1375,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -1383,7 +1383,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -1415,7 +1415,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -1440,7 +1440,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -1729,7 +1729,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -1737,7 +1737,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -1769,7 +1769,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -1794,7 +1794,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -2083,7 +2083,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -2091,7 +2091,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -2123,7 +2123,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -2148,7 +2148,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -2437,7 +2437,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -2445,7 +2445,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -2477,7 +2477,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -2502,7 +2502,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -2791,7 +2791,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -2799,7 +2799,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -2831,7 +2831,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -2856,7 +2856,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -3145,7 +3145,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -3153,7 +3153,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -3185,7 +3185,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -3210,7 +3210,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -3499,7 +3499,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -3507,7 +3507,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -3539,7 +3539,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -3564,7 +3564,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -3853,7 +3853,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -3861,7 +3861,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -3893,7 +3893,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -3918,7 +3918,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -4207,7 +4207,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -4215,7 +4215,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -4247,7 +4247,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -4272,7 +4272,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -4561,7 +4561,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -4569,7 +4569,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -4601,7 +4601,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -4626,7 +4626,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -4915,7 +4915,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -4923,7 +4923,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -4955,7 +4955,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -4980,7 +4980,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -5269,7 +5269,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -5277,7 +5277,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -5309,7 +5309,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -5334,7 +5334,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -5623,7 +5623,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -5631,7 +5631,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -5663,7 +5663,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -5688,7 +5688,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -5977,7 +5977,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -5985,7 +5985,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -6017,7 +6017,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -6042,7 +6042,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -6331,7 +6331,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -6339,7 +6339,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -6371,7 +6371,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -6396,7 +6396,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -6685,7 +6685,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -6693,7 +6693,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -6725,7 +6725,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -6750,7 +6750,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)
@ -7039,7 +7039,7 @@ max:
sub sub1 () -> (X?) = $ffdd
sub sub2 (A) -> (Y?) = $eecc
sub sub3 (XY) -> (Y?) = $ddaa
sub sub3 (thing: XY) -> (Y?) = $ddaa
sub sub4 (string: XY, other : A) -> (Y?) = $dd22
@ -7047,7 +7047,7 @@ bar:
goto sub1
return sub2 (1 )
return sub3 (3)
return sub3 (XY="hello")
return sub3 (thing="hello")
return sub3 ("hello, there")
return sub4 (string="hello, there", other = 42)
return sub4 ("hello", 42)
@ -7079,7 +7079,7 @@ bar:
sub1!()
sub2!(11)
sub3 !(3)
sub3! (XY="hello")
sub3! (thing="hello")
sub3! ("hello, there")
sub4! ("hello", 42)
sub4! ("hello", other=42)
@ -7104,7 +7104,7 @@ bar:
sub1()
sub2(11)
sub3 (3)
sub3 (XY="hello")
sub3 (thing="hello")
sub3 ("hello, there")
sub4 ("hello", 42)
sub4 ("hello", other= 42)

View File

@ -2,6 +2,7 @@
~ main {
var .float flt
var .word vmemaddr1 = &flt
start: