mirror of
https://github.com/irmen/prog8.git
synced 2025-02-18 05:30:34 +00:00
various fixes
This commit is contained in:
parent
ab71a15007
commit
fbf52d773f
@ -101,8 +101,11 @@ class PlyParser:
|
|||||||
raise ParseError("invalid number of arguments ({:d}, required: {:d})"
|
raise ParseError("invalid number of arguments ({:d}, required: {:d})"
|
||||||
.format(len(call.arguments.nodes), len(subdef.param_spec)), call.sourceref)
|
.format(len(call.arguments.nodes), len(subdef.param_spec)), call.sourceref)
|
||||||
for arg, param in zip(call.arguments.nodes, subdef.param_spec):
|
for arg, param in zip(call.arguments.nodes, subdef.param_spec):
|
||||||
if arg.name and arg.name != param[0]:
|
if arg.name:
|
||||||
raise ParseError("parameter name mismatch", arg.sourceref)
|
if not param[0]:
|
||||||
|
raise ParseError("parameter is unnamed but name was used", arg.sourceref)
|
||||||
|
if arg.name != param[0]:
|
||||||
|
raise ParseError("parameter name mismatch", arg.sourceref)
|
||||||
|
|
||||||
def check_and_merge_zeropages(self, module: Module) -> None:
|
def check_and_merge_zeropages(self, module: Module) -> None:
|
||||||
# merge all ZP blocks into one
|
# merge all ZP blocks into one
|
||||||
@ -111,7 +114,7 @@ class PlyParser:
|
|||||||
if block.name == "ZP": # type: ignore
|
if block.name == "ZP": # type: ignore
|
||||||
if zeropage:
|
if zeropage:
|
||||||
# merge other ZP block into first ZP block
|
# merge other ZP block into first ZP block
|
||||||
for node in block.nodes:
|
for node in block.scope.nodes:
|
||||||
if isinstance(node, Directive):
|
if isinstance(node, Directive):
|
||||||
zeropage.scope.add_node(node, 0)
|
zeropage.scope.add_node(node, 0)
|
||||||
elif isinstance(node, VarDef):
|
elif isinstance(node, VarDef):
|
||||||
@ -172,7 +175,7 @@ class PlyParser:
|
|||||||
lvalue_types = set(datatype_of(lv, node.my_scope()) for lv in node.left.nodes)
|
lvalue_types = set(datatype_of(lv, node.my_scope()) for lv in node.left.nodes)
|
||||||
if len(lvalue_types) == 1:
|
if len(lvalue_types) == 1:
|
||||||
_, newright = coerce_constant_value(lvalue_types.pop(), node.right, node.sourceref)
|
_, newright = coerce_constant_value(lvalue_types.pop(), node.right, node.sourceref)
|
||||||
if isinstance(newright, (Register, LiteralValue, Expression)):
|
if isinstance(newright, (Register, LiteralValue, Expression, Dereference, SymbolName, SubCall)):
|
||||||
node.right = newright
|
node.right = newright
|
||||||
else:
|
else:
|
||||||
raise TypeError("invalid coerced constant type", newright)
|
raise TypeError("invalid coerced constant type", newright)
|
||||||
|
@ -247,6 +247,8 @@ def _format_string(value: str, screencodes: bool = False) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def _numeric_value_str(value: Any, as_hex: bool=False) -> str:
|
def _numeric_value_str(value: Any, as_hex: bool=False) -> str:
|
||||||
|
if isinstance(value, LiteralValue):
|
||||||
|
value = value.value
|
||||||
if isinstance(value, bool):
|
if isinstance(value, bool):
|
||||||
return "1" if value else "0"
|
return "1" if value else "0"
|
||||||
if type(value) is int:
|
if type(value) is int:
|
||||||
|
@ -73,11 +73,11 @@ class AstNode:
|
|||||||
if isinstance(scope, Scope):
|
if isinstance(scope, Scope):
|
||||||
return scope
|
return scope
|
||||||
scope = scope.parent
|
scope = scope.parent
|
||||||
raise LookupError("no scope found in node ancestry")
|
raise LookupError("no scope found in node ancestry", self)
|
||||||
|
|
||||||
def all_nodes(self, *nodetypes: type) -> Generator['AstNode', None, None]:
|
def all_nodes(self, *nodetypes: type) -> Generator['AstNode', None, None]:
|
||||||
nodetypes = nodetypes or (AstNode, )
|
nodetypes = nodetypes or (AstNode, )
|
||||||
for node in self.nodes:
|
for node in list(self.nodes):
|
||||||
if isinstance(node, nodetypes): # type: ignore
|
if isinstance(node, nodetypes): # type: ignore
|
||||||
yield node
|
yield node
|
||||||
for node in self.nodes:
|
for node in self.nodes:
|
||||||
@ -121,7 +121,10 @@ class Scope(AstNode):
|
|||||||
def save_registers(self) -> bool:
|
def save_registers(self) -> bool:
|
||||||
if self._save_registers is not None:
|
if self._save_registers is not None:
|
||||||
return self._save_registers
|
return self._save_registers
|
||||||
return self.my_scope().save_registers
|
try:
|
||||||
|
return self.my_scope().save_registers
|
||||||
|
except LookupError:
|
||||||
|
return False
|
||||||
|
|
||||||
@save_registers.setter
|
@save_registers.setter
|
||||||
def save_registers(self, save: bool) -> None:
|
def save_registers(self, save: bool) -> None:
|
||||||
@ -507,7 +510,7 @@ class Goto(AstNode):
|
|||||||
return self.nodes[1] if len(self.nodes) == 2 else None # type: ignore
|
return self.nodes[1] if len(self.nodes) == 2 else None # type: ignore
|
||||||
|
|
||||||
|
|
||||||
@attr.s(cmp=False, slots=True)
|
@attr.s(cmp=False, slots=True, repr=False)
|
||||||
class CallArgument(AstNode):
|
class CallArgument(AstNode):
|
||||||
# one subnode: the value (Expression)
|
# one subnode: the value (Expression)
|
||||||
name = attr.ib(type=str, default=None)
|
name = attr.ib(type=str, default=None)
|
||||||
@ -553,12 +556,12 @@ class VarDef(AstNode):
|
|||||||
zp_address = attr.ib(type=int, default=None, init=False) # the address in the zero page if this var is there, will be set later
|
zp_address = attr.ib(type=int, default=None, init=False) # the address in the zero page if this var is there, will be set later
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self) -> Union[LiteralValue, Expression]:
|
def value(self) -> Union[LiteralValue, Expression, AddressOf, SymbolName]:
|
||||||
return self.nodes[0] if self.nodes else None # type: ignore
|
return self.nodes[0] if self.nodes else None # type: ignore
|
||||||
|
|
||||||
@value.setter
|
@value.setter
|
||||||
def value(self, value: Union[LiteralValue, Expression]) -> None:
|
def value(self, value: Union[LiteralValue, Expression, AddressOf, SymbolName]) -> None:
|
||||||
assert isinstance(value, (LiteralValue, Expression))
|
assert isinstance(value, (LiteralValue, Expression, AddressOf, SymbolName))
|
||||||
if self.nodes:
|
if self.nodes:
|
||||||
self.nodes[0] = value
|
self.nodes[0] = value
|
||||||
else:
|
else:
|
||||||
@ -634,8 +637,8 @@ class Assignment(AstNode):
|
|||||||
return self.nodes[1] # type: ignore
|
return self.nodes[1] # type: ignore
|
||||||
|
|
||||||
@right.setter
|
@right.setter
|
||||||
def right(self, rvalue: Union[Register, LiteralValue, Expression]) -> None:
|
def right(self, rvalue: Union[Register, LiteralValue, Expression, Dereference, SymbolName, SubCall]) -> None:
|
||||||
assert isinstance(rvalue, (Register, LiteralValue, Expression))
|
assert isinstance(rvalue, (Register, LiteralValue, Expression, Dereference, SymbolName, SubCall))
|
||||||
self.nodes[1] = rvalue
|
self.nodes[1] = rvalue
|
||||||
|
|
||||||
|
|
||||||
@ -704,10 +707,16 @@ def coerce_constant_value(datatype: DataType, value: AstNode,
|
|||||||
raise TypeError("cannot assign '{:s}' to {:s}".format(type(value.value).__name__, datatype.name.lower()), sourceref)
|
raise TypeError("cannot assign '{:s}' to {:s}".format(type(value.value).__name__, datatype.name.lower()), sourceref)
|
||||||
elif isinstance(value, (Expression, SubCall)):
|
elif isinstance(value, (Expression, SubCall)):
|
||||||
return False, value
|
return False, value
|
||||||
|
elif isinstance(value, SymbolName):
|
||||||
|
symboldef = value.my_scope().lookup(value.name)
|
||||||
|
if isinstance(symboldef, VarDef) and symboldef.vartype == VarType.CONST:
|
||||||
|
return True, symboldef.value
|
||||||
|
elif isinstance(value, AddressOf):
|
||||||
|
raise NotImplementedError("addressof const coerce", value) # XXX implement this
|
||||||
if datatype == DataType.WORD and not isinstance(value, (LiteralValue, Dereference, Register, SymbolName, AddressOf)):
|
if datatype == DataType.WORD and not isinstance(value, (LiteralValue, Dereference, Register, SymbolName, AddressOf)):
|
||||||
raise TypeError("cannot assign '{:s}' to {:s}".format(type(value).__name__, datatype.name.lower()), sourceref)
|
raise TypeError("cannot assign '{:s}' to {:s}".format(type(value).__name__, datatype.name.lower()), sourceref)
|
||||||
elif datatype in (DataType.BYTE, DataType.WORD, DataType.FLOAT) \
|
elif datatype in (DataType.BYTE, DataType.WORD, DataType.FLOAT) \
|
||||||
and not isinstance(value, (LiteralValue, Dereference, Register, SymbolName)):
|
and not isinstance(value, (LiteralValue, Dereference, Register, SymbolName, AddressOf)):
|
||||||
raise TypeError("cannot assign '{:s}' to {:s}".format(type(value).__name__, datatype.name.lower()), sourceref)
|
raise TypeError("cannot assign '{:s}' to {:s}".format(type(value).__name__, datatype.name.lower()), sourceref)
|
||||||
return False, value
|
return False, value
|
||||||
|
|
||||||
@ -734,6 +743,8 @@ def process_constant_expression(expr: Any, sourceref: SourceRef, symbolscope: Sc
|
|||||||
value = value.value
|
value = value.value
|
||||||
if isinstance(value, Expression):
|
if isinstance(value, Expression):
|
||||||
raise ExpressionEvaluationError("circular reference?", expr.sourceref)
|
raise ExpressionEvaluationError("circular reference?", expr.sourceref)
|
||||||
|
elif isinstance(value, LiteralValue):
|
||||||
|
return value
|
||||||
elif isinstance(value, (int, float, str, bool)):
|
elif isinstance(value, (int, float, str, bool)):
|
||||||
raise TypeError("symbol value node should not be a python primitive value", expr)
|
raise TypeError("symbol value node should not be a python primitive value", expr)
|
||||||
else:
|
else:
|
||||||
@ -1199,10 +1210,11 @@ def p_call_subroutine(p):
|
|||||||
"""
|
"""
|
||||||
subroutine_call : calltarget preserveregs_opt '(' call_arguments_opt ')'
|
subroutine_call : calltarget preserveregs_opt '(' call_arguments_opt ')'
|
||||||
"""
|
"""
|
||||||
p[0] = SubCall(sourceref=_token_sref(p, 3))
|
sref = _token_sref(p, 3)
|
||||||
|
p[0] = SubCall(sourceref=sref)
|
||||||
p[0].nodes.append(p[1])
|
p[0].nodes.append(p[1])
|
||||||
p[0].nodes.append(p[2])
|
p[0].nodes.append(p[2])
|
||||||
p[0].nodes.append(CallArguments(nodes=p[4] or [], sourceref=p[0].sourceref))
|
p[0].nodes.append(CallArguments(nodes=p[4] or [], sourceref=sref))
|
||||||
|
|
||||||
|
|
||||||
def p_preserveregs_opt(p):
|
def p_preserveregs_opt(p):
|
||||||
@ -1249,7 +1261,11 @@ def p_call_argument(p):
|
|||||||
p[0] = CallArgument(sourceref=_token_sref(p, 1))
|
p[0] = CallArgument(sourceref=_token_sref(p, 1))
|
||||||
p[0].nodes.append(p[1])
|
p[0].nodes.append(p[1])
|
||||||
elif len(p) == 4:
|
elif len(p) == 4:
|
||||||
p[0] = CallArgument(name=p[1], sourceref=_token_sref(p, 1))
|
if isinstance(p[1], AstNode):
|
||||||
|
sref = p[1].sourceref
|
||||||
|
else:
|
||||||
|
sref = _token_sref(p, 2)
|
||||||
|
p[0] = CallArgument(name=p[1], sourceref=sref)
|
||||||
p[0].nodes.append(p[3])
|
p[0].nodes.append(p[3])
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,11 +32,9 @@ bar: goto $c000
|
|||||||
; ----
|
; ----
|
||||||
|
|
||||||
goto sub1
|
goto sub1
|
||||||
return sub2 ( )
|
|
||||||
return sub2 ()
|
|
||||||
return sub2 (1 )
|
return sub2 (1 )
|
||||||
return sub3 (3)
|
return sub3 (3)
|
||||||
return sub3 (XY="hello")
|
return sub3 ("hello")
|
||||||
return sub3 ("hello, there")
|
return sub3 ("hello, there")
|
||||||
return sub4 (string="hello, there", other = 42)
|
return sub4 (string="hello, there", other = 42)
|
||||||
return sub4 ("hello", 42)
|
return sub4 ("hello", 42)
|
||||||
@ -77,7 +75,7 @@ bar: goto $c000
|
|||||||
sub1!()
|
sub1!()
|
||||||
sub2!(11)
|
sub2!(11)
|
||||||
sub3 !(3)
|
sub3 !(3)
|
||||||
sub3! (XY="hello")
|
sub3! ("hello")
|
||||||
sub3! ("hello, there")
|
sub3! ("hello, there")
|
||||||
sub4! ("hello", 42)
|
sub4! ("hello", 42)
|
||||||
sub4! ("hello", other=42)
|
sub4! ("hello", other=42)
|
||||||
@ -113,7 +111,7 @@ bar: goto $c000
|
|||||||
sub1()
|
sub1()
|
||||||
sub2(11)
|
sub2(11)
|
||||||
sub3 (3)
|
sub3 (3)
|
||||||
sub3 (XY="hello")
|
sub3 ("hello")
|
||||||
sub3 ("hello, there")
|
sub3 ("hello, there")
|
||||||
sub4 ("hello", 42)
|
sub4 ("hello", 42)
|
||||||
sub4 ("hello", other= 42)
|
sub4 ("hello", other= 42)
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
~ ZP {
|
~ ZP {
|
||||||
; will be merged with other ZP blocks!
|
; will be merged with other ZP blocks!
|
||||||
var zpvar1b = $88
|
var zpvar1b = $88
|
||||||
|
|
||||||
|
; @todo should not need %noreturn because is zeropage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -190,7 +192,7 @@ start:
|
|||||||
XY = membyte2
|
XY = membyte2
|
||||||
XY = memword1
|
XY = memword1
|
||||||
XY = sin
|
XY = sin
|
||||||
XY = &sin
|
; XY = &sin ; @todo not yet implemented
|
||||||
|
|
||||||
|
|
||||||
[$c000] = A
|
[$c000] = A
|
||||||
@ -214,7 +216,7 @@ start:
|
|||||||
[$c000.word] = ""
|
[$c000.word] = ""
|
||||||
[$c000.word] = uninitbyte1
|
[$c000.word] = uninitbyte1
|
||||||
[$c000.word] = membyte2
|
[$c000.word] = membyte2
|
||||||
[$c000.word] = &membyte2
|
; [$c000.word] = &membyte2 ; @todo not yet implemented
|
||||||
[$c000.word] = [cword2]
|
[$c000.word] = [cword2]
|
||||||
[$c000.word] = memword1
|
[$c000.word] = memword1
|
||||||
[$c000.float] = 65535
|
[$c000.float] = 65535
|
||||||
@ -228,7 +230,7 @@ start:
|
|||||||
[$c112.word] = [$c223.byte]
|
[$c112.word] = [$c223.byte]
|
||||||
[$c222.word] = [$c333.word]
|
[$c222.word] = [$c333.word]
|
||||||
[$c333.word] = sin
|
[$c333.word] = sin
|
||||||
[$c333.word] = &sin
|
; [$c333.word] = &sin ; @todo not yet implemented
|
||||||
|
|
||||||
|
|
||||||
SC = 0
|
SC = 0
|
||||||
@ -264,7 +266,8 @@ start:
|
|||||||
uninitfloat = 9.8765
|
uninitfloat = 9.8765
|
||||||
uninitfloat = '@'
|
uninitfloat = '@'
|
||||||
initword1 = sin
|
initword1 = sin
|
||||||
initword1 = &sin
|
; initword1 = &sin ; @todo not yet implemented
|
||||||
|
|
||||||
|
|
||||||
membyte1 = A
|
membyte1 = A
|
||||||
membyte1 = cbyte3
|
membyte1 = cbyte3
|
||||||
@ -279,7 +282,7 @@ start:
|
|||||||
memword1 = 2233
|
memword1 = 2233
|
||||||
memfloat = 3.4567
|
memfloat = 3.4567
|
||||||
memword1 = sin
|
memword1 = sin
|
||||||
memword1 = &sin
|
; memword1 = &sin ; @todo not yet implemented
|
||||||
|
|
||||||
membyte1 = A
|
membyte1 = A
|
||||||
memword1 = A
|
memword1 = A
|
||||||
|
@ -106,7 +106,6 @@ sub goodbye ()->() {
|
|||||||
xxxxxx++
|
xxxxxx++
|
||||||
y++
|
y++
|
||||||
xxxxxx = q *4
|
xxxxxx = q *4
|
||||||
xxxxxx = qqqqq *44 ;@todo symbol error
|
|
||||||
|
|
||||||
c64scr.print_string("\nThanks for playing. Bye!\n")
|
c64scr.print_string("\nThanks for playing. Bye!\n")
|
||||||
return
|
return
|
||||||
|
Loading…
x
Reference in New Issue
Block a user