Example #1
0
# PigletC: a tiny C-like language compiler for PigletVM,
# see https://github.com/vkazanov/bytecode-interpreters-post
# Author: Peter Sovietov

import os
import sys
from src.main import compile

if len(sys.argv) == 2 and os.path.isfile(sys.argv[1]):
    path = sys.argv[1]
    with open(path) as f:
        src = f.read()
    c = compile(path, src)
    with open("%s.pvm" % path, "w") as f:
        f.write(c.asm)
else:
    print("usage: pigletc.py file.c")
Example #2
0
def test(path, running_aggregate_tests=False):
    global ok
    global skipped
    global output_index

    index = tests[path]
    passed = False
    output = [f"{B}> TEST {index}/{n}:{E} {path}"]

    try:
        try:
            expected_error = Path(path.replace('.px', '.err')).read_text()
        except FileNotFoundError:
            expected_error = None

        error = True
        exe_filename = True

        try:
            if running_aggregate_tests:
                exe_filename = f'./{aggregate_exe_filename}'
            else:
                exe_filename = compile(
                    path,
                    args.cpp_compiler,
                    args.opt_level,
                    mode=('executable' if args.separate else 'cpp'))
            error = False
        except NotSupportedError as e:
            skipped += 1
            output.append(f"{Y}{e}{E}")
        except PyxellError as e:
            error_message = str(e)
            if expected_error:
                if error_message.strip().endswith(expected_error):
                    output.append(f"{G}{error_message}{E}")
                    passed = True
                else:
                    output.append(
                        f"{R}{error_message}\n---\n> {expected_error}{E}")
            else:
                output.append(f"{R}{error_message}{E}")
        except subprocess.CalledProcessError as e:
            output.append(f"{R}{e.output.decode()}{E}")
        except Exception:
            output.append(f"{R}{traceback.format_exc()}{E}")

        if not error:
            if expected_error:
                output.append(
                    f"{R}Program compiled successfully, but error expected.\n---\n> {expected_error}{E}"
                )

            elif not args.separate and not running_aggregate_tests:
                aggregate_cpp_code.extend([
                    f'namespace test{index} {{',
                    re.sub('^',
                           INDENT,
                           Path(path.replace('.px', '.cpp')).read_text(),
                           flags=re.MULTILINE),
                    '}\n',
                ])
                tests_to_compile.add(path)
                # The function will be run again with running_aggregate_tests=True.
                return

            elif exe_filename is None:
                output.append(f"{G}OK{E}")
                passed = True

            else:
                with open(path.replace('.px', '.tmp'), 'w') as tmpfile:
                    t1 = timer()
                    command = [exe_filename]
                    if running_aggregate_tests:
                        command.append(path)
                    try:
                        with open(path.replace('.px', '.in'), 'r') as infile:
                            subprocess.call(command,
                                            stdin=infile,
                                            stdout=tmpfile)
                    except FileNotFoundError:
                        subprocess.call(command, stdout=tmpfile)
                    t2 = timer()

                try:
                    subprocess.check_output([
                        'diff', '--strip-trailing-cr', '--text',
                        path.replace('.px', '.tmp'),
                        path.replace('.px', '.out')
                    ],
                                            stderr=subprocess.STDOUT)
                except subprocess.CalledProcessError as e:
                    if e.returncode == 2:
                        output.append(f"{Y}{e.output.decode()}{E}")
                    else:
                        output.append(f"{R}WA: {e.output.decode()}{E}")
                else:
                    output.append(f"{G}OK{E} ({t2-t1:.3f}s)")
                    passed = True

    except Exception:
        output.append(f"{R}{traceback.format_exc()}{E}")

    # Print the output of tests in the right order.
    output_dict[index] = '\n'.join(
        output) if not passed or args.verbose else ''
    with lock:
        while output_index in output_dict:
            if output_dict[output_index]:
                print(output_dict[output_index])
            output_index += 1

    if passed:
        ok += 1
        if not args.verbose:
            os.remove(path.replace('.px', '.tmp'))
            if not error:
                os.remove(path.replace('.px', '.cpp'))
                os.remove(path.replace('.px', '.exe'))
Example #3
0
# PigletC, a tiny C-like language compiler for PigletVM,
# see https://github.com/vkazanov/bytecode-interpreters-post
# Author: Peter Sovietov

import sys
from src.main import Compiler, compile

if len(sys.argv) == 2:
    path = sys.argv[1]
    with open(path) as f:
        src = f.read()
    c = Compiler(path, src)
    compile(c)
    with open("%s.pvm" % path, "w") as f:
        f.write(c.asm)
else:
    print("usage: pigletc.py file.c")