character literals (strings of len 1) are no longer automatically converted to byte integers

This commit is contained in:
Irmen de Jong 2018-02-11 15:11:14 +01:00
parent 780443ddab
commit fb1a4aa4ea
5 changed files with 35 additions and 194 deletions

View File

@ -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:

View File

@ -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

View File

@ -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))

View File

@ -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
View File

@ -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
}