From 3663c4fe15219ec68a3df32e8b3c68f4f4089f6d Mon Sep 17 00:00:00 2001 From: cjvth Date: Mon, 22 Jan 2024 05:39:26 +0700 Subject: [PATCH 1/3] [cocas] Change debug export format --- cocas/debug_export.py | 35 +++++++++++++++++++++++++++++++++++ cocas/main.py | 9 ++++----- 2 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 cocas/debug_export.py diff --git a/cocas/debug_export.py b/cocas/debug_export.py new file mode 100644 index 00000000..7d6e8a99 --- /dev/null +++ b/cocas/debug_export.py @@ -0,0 +1,35 @@ +import bisect +import json +import re + +from cocas.location import CodeLocation + + +def default_json_(o, files): + # if some json object should be in one line, without \n, wrap it with these __no_breaks + # do not cascade __no_breaks, regex will break (e.g. {begin, {begin, ..., end}, end} + if isinstance(o, CodeLocation): + return { + "__no_breaks_begin": [], + "f": bisect.bisect_left(files, o.file), "l": o.line, "c": o.column, + "__no_breaks_end": [] + } + else: + raise TypeError(f'Object of type {o.__class__.__name__} ' + f'is not JSON serializable') + + +def default_json(files): + return lambda x: default_json_(x, files) + + +def code_location_json(files, cl: CodeLocation): + return {"f": bisect.bisect_left(files, cl.file), "l": cl.line, "c": cl.column} + + +def debug_export(code_locations: dict[int, CodeLocation]) -> str: + files = sorted(set(map(lambda x: x.file, code_locations.values()))) + dump = json.dumps({"files": files, "codeLocations": code_locations}, default=default_json(files), indent=4) + pattern = re.compile(r"{\n\s+\"__no_breaks_begin\": \[],\n\s+([\S\s]+?),\n\s+\"__no_breaks_end\": \[]\s+}") + dump = re.sub(pattern, lambda m: "{" + re.sub(r"\n\s+", " ", m.group(1)) + "}", dump) + return dump diff --git a/cocas/main.py b/cocas/main.py index f02bb27e..1c9c1d49 100755 --- a/cocas/main.py +++ b/cocas/main.py @@ -1,11 +1,9 @@ import argparse import codecs import importlib -import json import os import pathlib import pkgutil -from dataclasses import asdict from typing import Union import antlr4 @@ -13,6 +11,7 @@ from cocas.assembler import assemble from cocas.ast_builder import build_ast +from cocas.debug_export import debug_export from cocas.error import CdmException, CdmExceptionTag, CdmLinkException, log_error from cocas.linker import link from cocas.macro_processor import process_macros, read_mlb @@ -254,11 +253,11 @@ def main(): handle_os_error(e) if args.debug: - code_locations = {key: asdict(loc) for key, loc in code_locations.items()} - json_locations = json.dumps(code_locations, indent=4, sort_keys=True) + code_locations = {key: value for (key, value) in sorted(code_locations.items())} + debug_info = debug_export(code_locations) try: with open(args.debug, 'w') as f: - f.write(json_locations) + f.write(debug_info) except OSError as e: handle_os_error(e) From e656cdd5128ed89ed6ef08b4ac760ee0fe71687d Mon Sep 17 00:00:00 2001 From: cjvth Date: Mon, 22 Jan 2024 17:47:37 +0700 Subject: [PATCH 2/3] [cocas] Fix non-ascii characters in debug information --- cocas/debug_export.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cocas/debug_export.py b/cocas/debug_export.py index 7d6e8a99..22dfb63d 100644 --- a/cocas/debug_export.py +++ b/cocas/debug_export.py @@ -29,7 +29,8 @@ def code_location_json(files, cl: CodeLocation): def debug_export(code_locations: dict[int, CodeLocation]) -> str: files = sorted(set(map(lambda x: x.file, code_locations.values()))) - dump = json.dumps({"files": files, "codeLocations": code_locations}, default=default_json(files), indent=4) + dump = json.dumps({"files": files, "codeLocations": code_locations}, + default=default_json(files), indent=4, ensure_ascii=False) pattern = re.compile(r"{\n\s+\"__no_breaks_begin\": \[],\n\s+([\S\s]+?),\n\s+\"__no_breaks_end\": \[]\s+}") dump = re.sub(pattern, lambda m: "{" + re.sub(r"\n\s+", " ", m.group(1)) + "}", dump) return dump From 14069c5787af6cb3e6a53e5c75c7852c4d04bf7e Mon Sep 17 00:00:00 2001 From: Timofey X Date: Fri, 26 Jan 2024 17:41:37 +0700 Subject: [PATCH 3/3] [cocas] Take prefix for .dbg.json file from -o if another name not given --- cocas/main.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/cocas/main.py b/cocas/main.py index 1c9c1d49..48ab1564 100755 --- a/cocas/main.py +++ b/cocas/main.py @@ -66,7 +66,7 @@ def main(): parser.add_argument('-m', '--merge', action='store_true', help='merge object files into one') parser.add_argument('-o', '--output', type=str, help='specify output file name') debug_group = parser.add_argument_group('debug') - debug_group.add_argument('--debug', type=str, nargs='?', const='out.dbg.json', help='export debug information') + debug_group.add_argument('--debug', type=str, nargs='?', const=True, help='export debug information') debug_path_group = debug_group.add_mutually_exclusive_group() debug_path_group.add_argument('--relative-path', type=pathlib.Path, help='convert source files paths to relative in debug info and object files') @@ -253,10 +253,17 @@ def main(): handle_os_error(e) if args.debug: + if args.debug is True: + if args.output: + filename = pathlib.Path(args.output).with_suffix('.dbg.json') + else: + filename = 'out.dbg.json' + else: + filename = args.debug code_locations = {key: value for (key, value) in sorted(code_locations.items())} debug_info = debug_export(code_locations) try: - with open(args.debug, 'w') as f: + with open(filename, 'w') as f: f.write(debug_info) except OSError as e: handle_os_error(e)