mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 01:29:28 +00:00
character literals (strings of len 1) are no longer automatically converted to byte integers
This commit is contained in:
parent
780443ddab
commit
fb1a4aa4ea
@ -146,8 +146,7 @@ def _generate_aug_reg_int(out: Callable, lvalue: Register, operator: str, rvalue
|
|||||||
elif operator == "<<=":
|
elif operator == "<<=":
|
||||||
_gen_aug_shiftleft_reg_int(lvalue, out, rname, rvalue, scope)
|
_gen_aug_shiftleft_reg_int(lvalue, out, rname, rvalue, scope)
|
||||||
else:
|
else:
|
||||||
# @todo implement more operators such as *= /=
|
raise ValueError("invalid operator: " + operator, str(lvalue.sourceref)) # @todo implement more operators such as *=, /=
|
||||||
raise ValueError("invalid operator: " + operator, str(lvalue.sourceref))
|
|
||||||
|
|
||||||
|
|
||||||
def _generate_aug_reg_reg(out: Callable, lvalue: Register, operator: str, rvalue: Register, scope: Scope) -> None:
|
def _generate_aug_reg_reg(out: Callable, lvalue: Register, operator: str, rvalue: Register, scope: Scope) -> None:
|
||||||
@ -166,8 +165,7 @@ def _generate_aug_reg_reg(out: Callable, lvalue: Register, operator: str, rvalue
|
|||||||
elif operator == "<<=":
|
elif operator == "<<=":
|
||||||
_gen_aug_shiftleft_reg_reg(lvalue, out, rvalue, scope)
|
_gen_aug_shiftleft_reg_reg(lvalue, out, rvalue, scope)
|
||||||
else:
|
else:
|
||||||
# @todo implement more operators such as *= /=
|
raise ValueError("invalid operator: " + operator, str(lvalue.sourceref)) # @todo implement more operators such as *=, /=
|
||||||
raise ValueError("invalid operator: " + operator, str(lvalue.sourceref))
|
|
||||||
|
|
||||||
|
|
||||||
def _gen_aug_shiftleft_reg_int(lvalue: Register, out: Callable, rname: str, rvalue: int, scope: Scope) -> None:
|
def _gen_aug_shiftleft_reg_int(lvalue: Register, out: Callable, rname: str, rvalue: int, scope: Scope) -> None:
|
||||||
|
@ -111,8 +111,8 @@ class Optimizer:
|
|||||||
incrdecrs.append(node)
|
incrdecrs.append(node)
|
||||||
target = node.target
|
target = node.target
|
||||||
|
|
||||||
def _same_target(self, node1: Union[TargetRegisters, Register, SymbolName, Dereference],
|
def _same_target(self, node1: Union[Register, SymbolName, Dereference],
|
||||||
node2: Union[TargetRegisters, Register, SymbolName, Dereference]) -> bool:
|
node2: Union[Register, SymbolName, Dereference]) -> bool:
|
||||||
if isinstance(node1, Register) and isinstance(node2, Register) and node1.name == node2.name:
|
if isinstance(node1, Register) and isinstance(node2, Register) and node1.name == node2.name:
|
||||||
return True
|
return True
|
||||||
if isinstance(node1, SymbolName) and isinstance(node2, SymbolName) and node1.name == node2.name:
|
if isinstance(node1, SymbolName) and isinstance(node2, SymbolName) and node1.name == node2.name:
|
||||||
@ -240,9 +240,9 @@ class Optimizer:
|
|||||||
return new_assignment
|
return new_assignment
|
||||||
|
|
||||||
@no_type_check
|
@no_type_check
|
||||||
def _make_aug_assign(self, old_assign: Assignment, target: Union[TargetRegisters, Register, SymbolName, Dereference],
|
def _make_aug_assign(self, old_assign: Assignment, target: Union[Register, SymbolName, Dereference],
|
||||||
value: Union[int, float], operator: str) -> AugAssignment:
|
value: Union[int, float], operator: str) -> AugAssignment:
|
||||||
assert isinstance(target, (TargetRegisters, Register, SymbolName, Dereference))
|
assert isinstance(target, (Register, SymbolName, Dereference))
|
||||||
a = AugAssignment(operator=operator, sourceref=old_assign.sourceref)
|
a = AugAssignment(operator=operator, sourceref=old_assign.sourceref)
|
||||||
a.nodes.append(target)
|
a.nodes.append(target)
|
||||||
target.parent = a
|
target.parent = a
|
||||||
@ -253,9 +253,9 @@ class Optimizer:
|
|||||||
return a
|
return a
|
||||||
|
|
||||||
@no_type_check
|
@no_type_check
|
||||||
def _make_incrdecr(self, old_stmt: AstNode, target: Union[TargetRegisters, Register, SymbolName, Dereference],
|
def _make_incrdecr(self, old_stmt: AstNode, target: Union[Register, SymbolName, Dereference],
|
||||||
howmuch: Union[int, float], operator: str) -> IncrDecr:
|
howmuch: Union[int, float], operator: str) -> IncrDecr:
|
||||||
assert isinstance(target, (TargetRegisters, Register, SymbolName, Dereference))
|
assert isinstance(target, (Register, SymbolName, Dereference))
|
||||||
a = IncrDecr(operator=operator, howmuch=howmuch, sourceref=old_stmt.sourceref)
|
a = IncrDecr(operator=operator, howmuch=howmuch, sourceref=old_stmt.sourceref)
|
||||||
a.nodes.append(target)
|
a.nodes.append(target)
|
||||||
target.parent = a
|
target.parent = a
|
||||||
|
@ -22,7 +22,7 @@ __all__ = ["ProgramFormat", "ZpOptions", "math_functions", "builtin_functions",
|
|||||||
"UndefinedSymbolError", "AstNode", "Directive", "Scope", "Block", "Module", "Label", "Expression",
|
"UndefinedSymbolError", "AstNode", "Directive", "Scope", "Block", "Module", "Label", "Expression",
|
||||||
"Register", "Subroutine", "LiteralValue", "AddressOf", "SymbolName", "Dereference", "IncrDecr",
|
"Register", "Subroutine", "LiteralValue", "AddressOf", "SymbolName", "Dereference", "IncrDecr",
|
||||||
"ExpressionWithOperator", "Goto", "SubCall", "VarDef", "Return", "Assignment", "AugAssignment",
|
"ExpressionWithOperator", "Goto", "SubCall", "VarDef", "Return", "Assignment", "AugAssignment",
|
||||||
"InlineAssembly", "TargetRegisters", "AssignmentTargets",
|
"InlineAssembly", "AssignmentTargets",
|
||||||
"parse_file", "coerce_constant_value", "datatype_of", "check_symbol_definition"]
|
"parse_file", "coerce_constant_value", "datatype_of", "check_symbol_definition"]
|
||||||
|
|
||||||
|
|
||||||
@ -390,15 +390,6 @@ class PreserveRegs(AstNode):
|
|||||||
# no subnodes.
|
# no subnodes.
|
||||||
|
|
||||||
|
|
||||||
@attr.s(cmp=False)
|
|
||||||
class TargetRegisters(AstNode):
|
|
||||||
# subnodes is is a list of 1 or more registers.
|
|
||||||
# In it's multiple-register form it is only used to be able to parse
|
|
||||||
# the result of a subroutine call such as A,X = sub().
|
|
||||||
# It will be replaced by a regular Register node if it contains just one register.
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@attr.s(cmp=False, repr=False)
|
@attr.s(cmp=False, repr=False)
|
||||||
class InlineAssembly(AstNode):
|
class InlineAssembly(AstNode):
|
||||||
# no subnodes.
|
# no subnodes.
|
||||||
@ -545,21 +536,19 @@ class Dereference(Expression):
|
|||||||
@attr.s(cmp=False)
|
@attr.s(cmp=False)
|
||||||
class IncrDecr(AstNode):
|
class IncrDecr(AstNode):
|
||||||
# increment or decrement something by a CONSTANT value (1 or more)
|
# increment or decrement something by a CONSTANT value (1 or more)
|
||||||
# one subnode: target (TargetRegisters, Register, SymbolName, or Dereference).
|
# one subnode: target (Register, SymbolName, or Dereference).
|
||||||
operator = attr.ib(type=str, validator=attr.validators.in_(["++", "--"]))
|
operator = attr.ib(type=str, validator=attr.validators.in_(["++", "--"]))
|
||||||
howmuch = attr.ib(default=1)
|
howmuch = attr.ib(default=1)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target(self) -> Union[TargetRegisters, Register, SymbolName, Dereference]:
|
def target(self) -> Union[Register, SymbolName, Dereference]:
|
||||||
return self.nodes[0] # type: ignore
|
return self.nodes[0] # type: ignore
|
||||||
|
|
||||||
@target.setter
|
@target.setter
|
||||||
def target(self, target: Union[TargetRegisters, Register, SymbolName, Dereference]) -> None:
|
def target(self, target: Union[Register, SymbolName, Dereference]) -> None:
|
||||||
if isinstance(target, Register):
|
if isinstance(target, Register):
|
||||||
if target.name not in REGISTER_BYTES | REGISTER_WORDS:
|
if target.name not in REGISTER_BYTES | REGISTER_WORDS:
|
||||||
raise ParseError("cannot incr/decr that register", self.sourceref)
|
raise ParseError("cannot incr/decr that register", self.sourceref)
|
||||||
if isinstance(target, TargetRegisters):
|
|
||||||
raise ParseError("cannot incr/decr multiple registers at once", self.sourceref)
|
|
||||||
assert isinstance(target, (Register, SymbolName, Dereference))
|
assert isinstance(target, (Register, SymbolName, Dereference))
|
||||||
self.nodes.clear()
|
self.nodes.clear()
|
||||||
self.nodes.append(target)
|
self.nodes.append(target)
|
||||||
@ -842,7 +831,7 @@ class Return(AstNode):
|
|||||||
|
|
||||||
@attr.s(cmp=False, slots=True, repr=False)
|
@attr.s(cmp=False, slots=True, repr=False)
|
||||||
class AssignmentTargets(AstNode):
|
class AssignmentTargets(AstNode):
|
||||||
# a list of one or more assignment targets (TargetRegisters, Register, SymbolName, or Dereference).
|
# a list of one or more assignment targets (Register, SymbolName, or Dereference).
|
||||||
nodes = attr.ib(type=list, init=True) # requires nodes in __init__
|
nodes = attr.ib(type=list, init=True) # requires nodes in __init__
|
||||||
|
|
||||||
def has_memvalue(self) -> bool:
|
def has_memvalue(self) -> bool:
|
||||||
@ -862,9 +851,7 @@ class AssignmentTargets(AstNode):
|
|||||||
for t1, t2 in zip(self.nodes, other.nodes):
|
for t1, t2 in zip(self.nodes, other.nodes):
|
||||||
if type(t1) is not type(t2):
|
if type(t1) is not type(t2):
|
||||||
return False
|
return False
|
||||||
if isinstance(t1, TargetRegisters):
|
if isinstance(t1, Register):
|
||||||
pass
|
|
||||||
elif isinstance(t1, Register):
|
|
||||||
if t1 != t2: # __eq__ is defined
|
if t1 != t2: # __eq__ is defined
|
||||||
return False
|
return False
|
||||||
elif isinstance(t1, SymbolName):
|
elif isinstance(t1, SymbolName):
|
||||||
@ -909,11 +896,11 @@ class Assignment(AstNode):
|
|||||||
|
|
||||||
@attr.s(cmp=False, slots=True, repr=False)
|
@attr.s(cmp=False, slots=True, repr=False)
|
||||||
class AugAssignment(AstNode):
|
class AugAssignment(AstNode):
|
||||||
# has two subnodes: left (=TargetRegisters, Register, SymbolName, or Dereference) and right (=Expression)
|
# has two subnodes: left (=Register, SymbolName, or Dereference) and right (=Expression)
|
||||||
operator = attr.ib(type=str)
|
operator = attr.ib(type=str)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def left(self) -> Union[TargetRegisters, Register, SymbolName, Dereference]:
|
def left(self) -> Union[Register, SymbolName, Dereference]:
|
||||||
return self.nodes[0] # type: ignore
|
return self.nodes[0] # type: ignore
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -936,9 +923,6 @@ def datatype_of(targetnode: AstNode, scope: Scope) -> DataType:
|
|||||||
symdef = scope.lookup(targetnode.name)
|
symdef = scope.lookup(targetnode.name)
|
||||||
if isinstance(symdef, VarDef):
|
if isinstance(symdef, VarDef):
|
||||||
return symdef.datatype
|
return symdef.datatype
|
||||||
elif isinstance(targetnode, TargetRegisters):
|
|
||||||
if len(targetnode.nodes) == 1:
|
|
||||||
return datatype_of(targetnode.nodes[0], scope)
|
|
||||||
raise TypeError("cannot determine datatype", targetnode)
|
raise TypeError("cannot determine datatype", targetnode)
|
||||||
|
|
||||||
|
|
||||||
@ -1625,38 +1609,19 @@ def p_expression_value(p):
|
|||||||
|
|
||||||
def p_assignment_target(p):
|
def p_assignment_target(p):
|
||||||
"""
|
"""
|
||||||
assignment_target : target_registers
|
assignment_target : register
|
||||||
| symbolname
|
| symbolname
|
||||||
| dereference
|
| dereference
|
||||||
"""
|
"""
|
||||||
if isinstance(p[1], TargetRegisters):
|
|
||||||
# if the target registers is just a single register, use that instead
|
|
||||||
if len(p[1].nodes) == 1:
|
|
||||||
assert isinstance(p[1].nodes[0], Register)
|
|
||||||
p[1] = p[1].nodes[0]
|
|
||||||
p[0] = p[1]
|
p[0] = p[1]
|
||||||
|
|
||||||
|
|
||||||
def p_target_registers(p):
|
|
||||||
"""
|
|
||||||
target_registers : register
|
|
||||||
| target_registers ',' register
|
|
||||||
"""
|
|
||||||
if len(p) == 2:
|
|
||||||
p[0] = TargetRegisters(sourceref=_token_sref(p, 1))
|
|
||||||
p[0].nodes.append(p[1])
|
|
||||||
else:
|
|
||||||
p[1].nodes.append(p[3])
|
|
||||||
p[0] = p[1]
|
|
||||||
|
|
||||||
|
|
||||||
def p_empty(p):
|
def p_empty(p):
|
||||||
"""empty :"""
|
"""empty :"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def p_error(p):
|
def p_error(p):
|
||||||
stack_state_str = ' '.join([symbol.type for symbol in parser.symstack][1:])
|
|
||||||
if p:
|
if p:
|
||||||
sref = SourceRef(p.lexer.source_filename, p.lineno, find_tok_column(p))
|
sref = SourceRef(p.lexer.source_filename, p.lineno, find_tok_column(p))
|
||||||
if p.value in ("", "\n"):
|
if p.value in ("", "\n"):
|
||||||
@ -1665,6 +1630,7 @@ def p_error(p):
|
|||||||
p.lexer.error_function(sref, "syntax error before or at '{:.20s}'", str(p.value).rstrip())
|
p.lexer.error_function(sref, "syntax error before or at '{:.20s}'", str(p.value).rstrip())
|
||||||
else:
|
else:
|
||||||
lexer.error_function(None, "syntax error at end of input", lexer.source_filename)
|
lexer.error_function(None, "syntax error at end of input", lexer.source_filename)
|
||||||
|
# stack_state_str = ' '.join([symbol.type for symbol in parser.symstack][1:])
|
||||||
# print('\n[ERROR DEBUG: parser state={:d} stack: {} . {} ]'.format(parser.state, stack_state_str, p))
|
# print('\n[ERROR DEBUG: parser state={:d} stack: {} . {} ]'.format(parser.state, stack_state_str, p))
|
||||||
|
|
||||||
|
|
||||||
|
46
todo.ill
46
todo.ill
@ -1,40 +1,28 @@
|
|||||||
~ main {
|
~ main {
|
||||||
|
|
||||||
var .float flt = -9.87e-21
|
var .float flt = -9.87e-21
|
||||||
var bytevar = 22 + 23
|
const .word border = $0099
|
||||||
const .word border = $d020
|
|
||||||
var .word border2 = $d020
|
|
||||||
memory screenm = $d021
|
|
||||||
|
|
||||||
start:
|
start:
|
||||||
; @todo float incrdecr/augassign
|
; @todo float augassign
|
||||||
; flt += 0.1
|
flt += 1000.1
|
||||||
; flt += 1.1
|
flt *= 2.34
|
||||||
; flt += 10.1
|
flt *= flt
|
||||||
; flt += 100.1
|
|
||||||
; flt += 1000.1
|
|
||||||
; flt *= 2.34
|
|
||||||
|
|
||||||
screenm ++
|
;[border] &= 2 ; @todo augassign on dereference
|
||||||
screenm ++
|
|
||||||
border2 ++
|
|
||||||
border2 ++
|
|
||||||
screenm --
|
|
||||||
border2 --
|
|
||||||
|
|
||||||
[$55 .float] ++
|
XY*=3 ; @todo operator
|
||||||
[screenm .float]--
|
XY=XY/0 ; @todo zerodiv (during expression to code generation) @todo operator
|
||||||
|
XY=XY//0 ; @todo zerodiv (during expression to code generation) @todo operator
|
||||||
|
|
||||||
|
; @todo incr by more than 1
|
||||||
|
[AX]++
|
||||||
|
[AX]++
|
||||||
|
A=0
|
||||||
|
; @todo decr by more than 1
|
||||||
|
[AX]--
|
||||||
|
[AX]--
|
||||||
|
|
||||||
[border] ++
|
|
||||||
[border] ++
|
|
||||||
[border] --
|
|
||||||
[$d020] ++
|
|
||||||
[$d020] ++
|
|
||||||
[$d020] --
|
|
||||||
[border2 .word] ++
|
|
||||||
[border2 .float] ++
|
|
||||||
[border2] --
|
|
||||||
[XY] ++
|
|
||||||
|
|
||||||
return 44.123
|
return 44.123
|
||||||
}
|
}
|
||||||
|
111
todo2.ill
111
todo2.ill
@ -1,111 +0,0 @@
|
|||||||
%output basic
|
|
||||||
%import c64lib
|
|
||||||
|
|
||||||
|
|
||||||
~ main {
|
|
||||||
var .byte v1t = true
|
|
||||||
var .byte v1f = false
|
|
||||||
var .word v2t = true
|
|
||||||
var .word v2f = false
|
|
||||||
var .float v3t = true
|
|
||||||
var .float v3f = false
|
|
||||||
var .text v4t = true
|
|
||||||
var .text v4f = false
|
|
||||||
var .array(3) v5t = true
|
|
||||||
var .array(3) v5f = false
|
|
||||||
var .array(10) v6t = true
|
|
||||||
var .array(10) v6f = false
|
|
||||||
var .wordarray(3) v7t = true
|
|
||||||
var .wordarray(3) v7f = false
|
|
||||||
var .wordarray(10) v8t = true
|
|
||||||
var .wordarray(10) v8f = false
|
|
||||||
var .matrix(2,2) v9t = true
|
|
||||||
var .matrix(2,2) v9f = false
|
|
||||||
var .matrix(5,5) v10t = true
|
|
||||||
var .matrix(5,5) v10f = false
|
|
||||||
|
|
||||||
const .byte c1t=true
|
|
||||||
const .byte c1f=false
|
|
||||||
const .word c2t=true
|
|
||||||
const .word c2f=false
|
|
||||||
const .float c3t=true
|
|
||||||
const .float c3f=false
|
|
||||||
|
|
||||||
memory border = $d020
|
|
||||||
|
|
||||||
|
|
||||||
start:
|
|
||||||
%breakpoint abc,def
|
|
||||||
|
|
||||||
X += border
|
|
||||||
XY += border ; @todo .word augassign register
|
|
||||||
XY -= 234+3 ; @todo .word augassign register
|
|
||||||
|
|
||||||
X += [c2f]
|
|
||||||
XY += [c2f]
|
|
||||||
Y += [XY]
|
|
||||||
|
|
||||||
XY+=255
|
|
||||||
XY+=254
|
|
||||||
XY+=253
|
|
||||||
XY-=255
|
|
||||||
XY-=254
|
|
||||||
XY-=253
|
|
||||||
|
|
||||||
v3t++
|
|
||||||
;v3t+=1 ; @todo non-reg augassign
|
|
||||||
;v3t+=1 ; @todo? (optimize) join with previous
|
|
||||||
;v3t+=0 ; is removed by optimizer
|
|
||||||
;v3t+=1 ; @todo? (optimize) join with previous
|
|
||||||
;v3t+=1 ; @todo? (optimize) join with previous
|
|
||||||
;v3t=2.23424 ; @todo store as constant float with generated name, replace value node
|
|
||||||
;v3t=2.23411 ; @todo store as constant float with generated name, replace value node
|
|
||||||
;v3t=1.23411 + 1; @todo store as constant float with generated name, replace value node
|
|
||||||
;v3t+=2.23424 ; @todo store as constant float with generated name, replace value node
|
|
||||||
;v3t+=2.23424 ; @todo store as constant float with generated name, replace value node
|
|
||||||
;v3t+=2.23411 ; @todo store as constant float with generated name, replace value node
|
|
||||||
;v3t+=2.23411 ; @todo store as constant float with generated name, replace value node
|
|
||||||
;v3t=2.23424 * v3t ; @todo store as constant float with generated name, replace value node
|
|
||||||
;XY*=2 ; @todo operator
|
|
||||||
;XY*=3 ; @todo operator
|
|
||||||
X=3 ; @todo optimize consecutive assignments
|
|
||||||
X=4
|
|
||||||
X=5
|
|
||||||
X=A=6
|
|
||||||
A=X=6
|
|
||||||
X=A=6
|
|
||||||
X=A=9
|
|
||||||
X=A=10
|
|
||||||
v3t=1 ; @todo optimize consecutive assignments
|
|
||||||
v3t=2
|
|
||||||
v3t=3
|
|
||||||
border = 0 ; @todo do not optimize consecucutive assignments to a memory var
|
|
||||||
border = 1
|
|
||||||
border = 2
|
|
||||||
|
|
||||||
;XY=XY/0 ; @todo zerodiv (during expression to code generation) @todo operator
|
|
||||||
;XY=XY//0 ; @todo zerodiv (during expression to code generation) @todo operator
|
|
||||||
;XY*=2.23424 ; @todo store as constant float with generated name, replace value node @todo operator
|
|
||||||
;XY*=2.23424 * v3t ; @todo store as constant float with generated name, replace value node @todo operator
|
|
||||||
;v3t*=2.23424 * v3t ; @todo store as constant float with generated name, replace value node @todo operator, non-register
|
|
||||||
A++
|
|
||||||
X--
|
|
||||||
A+=1
|
|
||||||
X-=2
|
|
||||||
[AX]++
|
|
||||||
[AX .byte]++
|
|
||||||
[AX .word]++
|
|
||||||
[AX .float]++
|
|
||||||
[$ccc0]++
|
|
||||||
[$ccc0 .byte]++
|
|
||||||
[$ccc0 .word]++
|
|
||||||
[$ccc0 .float]++
|
|
||||||
A+=2
|
|
||||||
A+=3
|
|
||||||
XY+=6
|
|
||||||
XY+=222
|
|
||||||
XY+=11
|
|
||||||
|
|
||||||
return 44
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user