From 780443ddab3b0b84b830adff7392a9ab03433127 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 11 Feb 2018 14:18:22 +0100 Subject: [PATCH] character literals (strings of len 1) are no longer automatically converted to byte integers --- il65/compile.py | 16 +++++++++++----- il65/emit/generate.py | 4 ++-- il65/emit/variables.py | 11 ++++++----- il65/plyparse.py | 10 ++++------ tests/test_parser.py | 10 +++++----- todo.ill | 9 ++------- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/il65/compile.py b/il65/compile.py index b6c11074d..61b4b3a5c 100644 --- a/il65/compile.py +++ b/il65/compile.py @@ -58,6 +58,7 @@ class PlyParser: def lexer_error(self, sourceref: SourceRef, fmtstring: str, *args: str) -> None: self.parse_errors += 1 + self.print_error_sourceline(sourceref) print_bold("ERROR: {}: {}".format(sourceref, fmtstring.format(*args))) def _check_last_statement_is_return(self, last_stmt: AstNode) -> None: @@ -508,15 +509,20 @@ class PlyParser: print("Error (in imported file):", str(exc), file=out) else: print("Error:", str(exc), file=out) - sourcetext = linecache.getline(exc.sourceref.file, exc.sourceref.line).rstrip() - if sourcetext: - print(" " + sourcetext.expandtabs(8), file=out) - if exc.sourceref.column: - print(' ' * (1+exc.sourceref.column) + '^', file=out) + self.print_error_sourceline(exc.sourceref) if out.isatty(): print("\x1b[0m", file=out, end="", flush=True) raise exc # XXX temporary to see where the error occurred + def print_error_sourceline(self, sref: SourceRef) -> None: + if not sref: + return + sourcetext = linecache.getline(sref.file, sref.line).rstrip() + if sourcetext: + print(" " + sourcetext.expandtabs(8)) + if sref.column: + print(' ' * (1+sref.column) + '^') + class Zeropage: SCRATCH_B1 = 0x02 diff --git a/il65/emit/generate.py b/il65/emit/generate.py index dd40cb0fe..f4f8ff01f 100644 --- a/il65/emit/generate.py +++ b/il65/emit/generate.py @@ -9,8 +9,8 @@ import os import datetime from typing import TextIO, Callable, no_type_check from ..plylex import print_bold -from ..plyparse import Module, Scope, ProgramFormat, Block, Directive, VarDef, Label, Subroutine, AstNode, ZpOptions, \ - InlineAssembly, Return, Register, Goto, SubCall, Assignment, AugAssignment, IncrDecr, AssignmentTargets +from ..plyparse import (Module, ProgramFormat, Block, Directive, VarDef, Label, Subroutine, ZpOptions, + InlineAssembly, Return, Register, Goto, SubCall, Assignment, AugAssignment, IncrDecr, AssignmentTargets) from . import CodeError, to_hex, to_mflpt5, Context from .variables import generate_block_init, generate_block_vars from .assignment import generate_assignment, generate_aug_assignment diff --git a/il65/emit/variables.py b/il65/emit/variables.py index 8501f014e..72c1afe1f 100644 --- a/il65/emit/variables.py +++ b/il65/emit/variables.py @@ -7,8 +7,8 @@ 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, AddressOf -from ..datatypes import DataType, STRING_DATATYPES +from ..plyparse import Block, VarDef, LiteralValue, AddressOf +from ..datatypes import DataType, VarType, STRING_DATATYPES from . import to_hex, to_mflpt5, CodeError @@ -173,12 +173,13 @@ def generate_block_vars(out: Callable, block: Block, zeropage: bool=False) -> No for vardef in vars_by_vartype.get(VarType.VAR, []): if vardef.datatype.isnumeric(): assert vardef.size == [1] + assert isinstance(vardef.value, LiteralValue) if vardef.datatype == DataType.BYTE: - out("{:s}\v.byte ?".format(vardef.name)) + out("{:s}\v.byte ?\t; {:s}".format(vardef.name, to_hex(vardef.value.value))) elif vardef.datatype == DataType.WORD: - out("{:s}\v.word ?".format(vardef.name)) + out("{:s}\v.word ?\t; {:s}".format(vardef.name, to_hex(vardef.value.value))) elif vardef.datatype == DataType.FLOAT: - out("{:s}\v.fill 5\t\t; float".format(vardef.name)) + out("{:s}\v.fill 5\t\t; float {}".format(vardef.name, vardef.value.value)) else: raise CodeError("weird datatype") elif vardef.datatype in (DataType.BYTEARRAY, DataType.WORDARRAY): diff --git a/il65/plyparse.py b/il65/plyparse.py index 7a89d53ea..0b77f982a 100644 --- a/il65/plyparse.py +++ b/il65/plyparse.py @@ -14,8 +14,8 @@ from typing import Union, Generator, Tuple, List, Optional, Dict, Any, no_type_c import attr from ply.yacc import yacc from .plylex import SourceRef, tokens, lexer, find_tok_column, print_warning -from .datatypes import DataType, VarType, REGISTER_SYMBOLS, REGISTER_BYTES, REGISTER_WORDS, \ - char_to_bytevalue, FLOAT_MAX_NEGATIVE, FLOAT_MAX_POSITIVE +from .datatypes import (DataType, VarType, REGISTER_SYMBOLS, REGISTER_BYTES, REGISTER_WORDS, + FLOAT_MAX_NEGATIVE, FLOAT_MAX_POSITIVE, char_to_bytevalue) __all__ = ["ProgramFormat", "ZpOptions", "math_functions", "builtin_functions", "ParseError", "ExpressionEvaluationError", @@ -1224,9 +1224,7 @@ def p_literal_value(p): | CHARACTER | BOOLEAN""" tok = p.slice[-1] - if tok.type == "CHARACTER": - p[1] = char_to_bytevalue(p[1]) # character literals are converted to byte value. - elif tok.type == "BOOLEAN": + if tok.type == "BOOLEAN": p[1] = int(p[1]) # boolean literals are converted to integer form (true=1, false=0). p[0] = LiteralValue(value=p[1], sourceref=_token_sref(p, 1)) @@ -1659,7 +1657,6 @@ def p_empty(p): def p_error(p): 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)) if p: sref = SourceRef(p.lexer.source_filename, p.lineno, find_tok_column(p)) if p.value in ("", "\n"): @@ -1668,6 +1665,7 @@ def p_error(p): p.lexer.error_function(sref, "syntax error before or at '{:.20s}'", str(p.value).rstrip()) else: lexer.error_function(None, "syntax error at end of input", lexer.source_filename) + # print('\n[ERROR DEBUG: parser state={:d} stack: {} . {} ]'.format(parser.state, stack_state_str, p)) def _token_sref(p, token_idx): diff --git a/tests/test_parser.py b/tests/test_parser.py index 7ddaf454b..03cea620c 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -252,13 +252,13 @@ def test_char_string(): result = parse_source(test_source_4) block = result.scope.nodes[0] var1, var2, var3, assgn1, assgn2, assgn3, = block.scope.nodes - assert var1.value.value == 64 - assert var2.value.value == 126 + assert var1.value.value == '@' + assert var2.value.value == 'π' assert var3.value.value == "abc" - assert assgn1.right.value == 64 - assert assgn2.right.value == 126 + assert assgn1.right.value == '@' + assert assgn2.right.value == 'π' assert assgn3.right.value == "abc" - + # note: the actual one-charactor-to-bytevalue conversion is done at the very latest, when issuing an assignment statement test_source_5 = """ diff --git a/todo.ill b/todo.ill index da345a2c3..44912ce2d 100644 --- a/todo.ill +++ b/todo.ill @@ -1,12 +1,7 @@ -%output basic -%import c64lib - ~ main { - var .float flt - var bytevar = 22 + 23 ; @todo bytevar in source should show its initial value in a comment - var .text guess1 = "?X" * 40 ; @todo constant-fold before semantic check - var .text guess2 = "?" * 40 ; @todo string result instead of int! + var .float flt = -9.87e-21 + var bytevar = 22 + 23 const .word border = $d020 var .word border2 = $d020 memory screenm = $d021