mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +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})"
|
||||
.format(len(call.arguments.nodes), len(subdef.param_spec)), call.sourceref)
|
||||
for arg, param in zip(call.arguments.nodes, subdef.param_spec):
|
||||
if arg.name and arg.name != param[0]:
|
||||
raise ParseError("parameter name mismatch", arg.sourceref)
|
||||
if arg.name:
|
||||
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:
|
||||
# merge all ZP blocks into one
|
||||
@ -111,7 +114,7 @@ class PlyParser:
|
||||
if block.name == "ZP": # type: ignore
|
||||
if zeropage:
|
||||
# merge other ZP block into first ZP block
|
||||
for node in block.nodes:
|
||||
for node in block.scope.nodes:
|
||||
if isinstance(node, Directive):
|
||||
zeropage.scope.add_node(node, 0)
|
||||
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)
|
||||
if len(lvalue_types) == 1:
|
||||
_, 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
|
||||
else:
|
||||
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:
|
||||
if isinstance(value, LiteralValue):
|
||||
value = value.value
|
||||
if isinstance(value, bool):
|
||||
return "1" if value else "0"
|
||||
if type(value) is int:
|
||||
|
@ -73,11 +73,11 @@ class AstNode:
|
||||
if isinstance(scope, Scope):
|
||||
return scope
|
||||
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]:
|
||||
nodetypes = nodetypes or (AstNode, )
|
||||
for node in self.nodes:
|
||||
for node in list(self.nodes):
|
||||
if isinstance(node, nodetypes): # type: ignore
|
||||
yield node
|
||||
for node in self.nodes:
|
||||
@ -121,7 +121,10 @@ class Scope(AstNode):
|
||||
def save_registers(self) -> bool:
|
||||
if self._save_registers is not None:
|
||||
return self._save_registers
|
||||
return self.my_scope().save_registers
|
||||
try:
|
||||
return self.my_scope().save_registers
|
||||
except LookupError:
|
||||
return False
|
||||
|
||||
@save_registers.setter
|
||||
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
|
||||
|
||||
|
||||
@attr.s(cmp=False, slots=True)
|
||||
@attr.s(cmp=False, slots=True, repr=False)
|
||||
class CallArgument(AstNode):
|
||||
# one subnode: the value (Expression)
|
||||
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
|
||||
|
||||
@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
|
||||
|
||||
@value.setter
|
||||
def value(self, value: Union[LiteralValue, Expression]) -> None:
|
||||
assert isinstance(value, (LiteralValue, Expression))
|
||||
def value(self, value: Union[LiteralValue, Expression, AddressOf, SymbolName]) -> None:
|
||||
assert isinstance(value, (LiteralValue, Expression, AddressOf, SymbolName))
|
||||
if self.nodes:
|
||||
self.nodes[0] = value
|
||||
else:
|
||||
@ -634,8 +637,8 @@ class Assignment(AstNode):
|
||||
return self.nodes[1] # type: ignore
|
||||
|
||||
@right.setter
|
||||
def right(self, rvalue: Union[Register, LiteralValue, Expression]) -> None:
|
||||
assert isinstance(rvalue, (Register, LiteralValue, Expression))
|
||||
def right(self, rvalue: Union[Register, LiteralValue, Expression, Dereference, SymbolName, SubCall]) -> None:
|
||||
assert isinstance(rvalue, (Register, LiteralValue, Expression, Dereference, SymbolName, SubCall))
|
||||
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)
|
||||
elif isinstance(value, (Expression, SubCall)):
|
||||
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)):
|
||||
raise TypeError("cannot assign '{:s}' to {:s}".format(type(value).__name__, datatype.name.lower()), sourceref)
|
||||
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)
|
||||
return False, value
|
||||
|
||||
@ -734,6 +743,8 @@ def process_constant_expression(expr: Any, sourceref: SourceRef, symbolscope: Sc
|
||||
value = value.value
|
||||
if isinstance(value, Expression):
|
||||
raise ExpressionEvaluationError("circular reference?", expr.sourceref)
|
||||
elif isinstance(value, LiteralValue):
|
||||
return value
|
||||
elif isinstance(value, (int, float, str, bool)):
|
||||
raise TypeError("symbol value node should not be a python primitive value", expr)
|
||||
else:
|
||||
@ -1199,10 +1210,11 @@ def p_call_subroutine(p):
|
||||
"""
|
||||
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[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):
|
||||
@ -1249,7 +1261,11 @@ def p_call_argument(p):
|
||||
p[0] = CallArgument(sourceref=_token_sref(p, 1))
|
||||
p[0].nodes.append(p[1])
|
||||
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])
|
||||
|
||||
|
||||
|
@ -32,11 +32,9 @@ bar: goto $c000
|
||||
; ----
|
||||
|
||||
goto sub1
|
||||
return sub2 ( )
|
||||
return sub2 ()
|
||||
return sub2 (1 )
|
||||
return sub3 (3)
|
||||
return sub3 (XY="hello")
|
||||
return sub3 ("hello")
|
||||
return sub3 ("hello, there")
|
||||
return sub4 (string="hello, there", other = 42)
|
||||
return sub4 ("hello", 42)
|
||||
@ -77,7 +75,7 @@ bar: goto $c000
|
||||
sub1!()
|
||||
sub2!(11)
|
||||
sub3 !(3)
|
||||
sub3! (XY="hello")
|
||||
sub3! ("hello")
|
||||
sub3! ("hello, there")
|
||||
sub4! ("hello", 42)
|
||||
sub4! ("hello", other=42)
|
||||
@ -113,7 +111,7 @@ bar: goto $c000
|
||||
sub1()
|
||||
sub2(11)
|
||||
sub3 (3)
|
||||
sub3 (XY="hello")
|
||||
sub3 ("hello")
|
||||
sub3 ("hello, there")
|
||||
sub4 ("hello", 42)
|
||||
sub4 ("hello", other= 42)
|
||||
|
@ -29,6 +29,8 @@
|
||||
~ ZP {
|
||||
; will be merged with other ZP blocks!
|
||||
var zpvar1b = $88
|
||||
|
||||
; @todo should not need %noreturn because is zeropage
|
||||
}
|
||||
|
||||
|
||||
@ -190,7 +192,7 @@ start:
|
||||
XY = membyte2
|
||||
XY = memword1
|
||||
XY = sin
|
||||
XY = &sin
|
||||
; XY = &sin ; @todo not yet implemented
|
||||
|
||||
|
||||
[$c000] = A
|
||||
@ -214,7 +216,7 @@ start:
|
||||
[$c000.word] = ""
|
||||
[$c000.word] = uninitbyte1
|
||||
[$c000.word] = membyte2
|
||||
[$c000.word] = &membyte2
|
||||
; [$c000.word] = &membyte2 ; @todo not yet implemented
|
||||
[$c000.word] = [cword2]
|
||||
[$c000.word] = memword1
|
||||
[$c000.float] = 65535
|
||||
@ -228,7 +230,7 @@ start:
|
||||
[$c112.word] = [$c223.byte]
|
||||
[$c222.word] = [$c333.word]
|
||||
[$c333.word] = sin
|
||||
[$c333.word] = &sin
|
||||
; [$c333.word] = &sin ; @todo not yet implemented
|
||||
|
||||
|
||||
SC = 0
|
||||
@ -264,7 +266,8 @@ start:
|
||||
uninitfloat = 9.8765
|
||||
uninitfloat = '@'
|
||||
initword1 = sin
|
||||
initword1 = &sin
|
||||
; initword1 = &sin ; @todo not yet implemented
|
||||
|
||||
|
||||
membyte1 = A
|
||||
membyte1 = cbyte3
|
||||
@ -279,7 +282,7 @@ start:
|
||||
memword1 = 2233
|
||||
memfloat = 3.4567
|
||||
memword1 = sin
|
||||
memword1 = &sin
|
||||
; memword1 = &sin ; @todo not yet implemented
|
||||
|
||||
membyte1 = A
|
||||
memword1 = A
|
||||
|
@ -106,7 +106,6 @@ sub goodbye ()->() {
|
||||
xxxxxx++
|
||||
y++
|
||||
xxxxxx = q *4
|
||||
xxxxxx = qqqqq *44 ;@todo symbol error
|
||||
|
||||
c64scr.print_string("\nThanks for playing. Bye!\n")
|
||||
return
|
||||
|
Loading…
Reference in New Issue
Block a user