Adding the Pascal programming language to the question

Adding the Pascal programming language to the question

by Pavel Mul -
Number of replies: 2

Hi Richard, I need help.
I am trying to add a new Pascal programming language to the task according to the instructions (13 Supporting or implementing new languages).

Full code for question

""" The template for a "write a program" question type that accepts answers
    in C, C++, Pascal, Java or Python3 according to the value in the language select
    dropdown menu.
"""

import subprocess
import re
student_answer = """{{ STUDENT_ANSWER | e('py') }}"""
language = """{{ ANSWER_LANGUAGE | e('py') }}""".lower()
language_extension_map = {'c':'c', 'cpp':'cpp',  'pascal':'pas', 'java':'java', 'python3':'py'}

if language not in language_extension_map.keys():
    raise Exception('Error in question. Unknown/unexpected language ({})'.format(language))

if language == 'java':
   
# Need to determine public class name in order to name output file. Sigh.
    # The best I can be bothered to do is to use a regular expression match.
    match = re.search(r'public\s+class\s+([_a-zA-Z][_a-zA-Z0-9]*)', student_answer, re.DOTALL | re.MULTILINE)
    if match is None:
        raise Exception("Unable to determine class name. Does the file include 'public class name'?")
    classname = match.group(1)
    filename = classname + '.java'
else:   
    filename = 'prog.' + language_extension_map[language]

# Write the student code to a file

with open(filename, "w") as src:
    print(student_answer, file=src)

# Compile C, C++ and Java
if language == 'c':
    cflags = "-std=c99 -Wall -Werror -Wno-unused-variable -Wno-unused-value"
    return_code = subprocess.call("gcc {0} -o prog prog.c".format(cflags).split())
    if return_code != 0:
        raise Exception("** Compilation failed. Testing aborted **")
    exec_command = ["./prog"]
elif language == 'cpp':
    cppflags = "-std=c++11 -Wall -Werror -Wno-unused-variable -Wno-unused-value"
    return_code = subprocess.call("g++ {0} -o prog prog.cpp".format(cppflags).split())
    if return_code != 0:
        raise Exception("** Compilation failed. Testing aborted **")
    exec_command = ["./prog"]
elif language == 'pascal':
    pasflags = " -vew -Se"
    return_code = subprocess.call("fpc {0} prog.pas".format(pasflags).split())
    if return_code != 0:
        raise Exception("** Compilation failed. Testing aborted **")
    exec_command = ["./prog"]     
  
elif language == 'java':
    return_code = subprocess.call(['javac', filename])
    if return_code != 0:
        raise Exception("** Compilation failed. Testing aborted **")
    exec_command = ["java", classname]
else: # Python doesn't need a compile phase
    exec_command = ["python3", "./prog.py"]
   
# Now run the code. Since this is a per-test template,
# stdin is already set up for the stdin text specified in the test case,
# so we can run the compiled program directly.

try:
    output = subprocess.check_output(exec_command, universal_newlines=True)
    print(output)
except subprocess.CalledProcessError as e:
    if e.returncode > 0:
        # Ignore non-zero positive return codes
        if e.output:
            print(e.output)
    else:
        # But negative return codes are signals - abort
        if e.output:
            print(e.output, file=sys.stderr)
        if e.returncode < 0:
            print("Task failed with signal", -e.returncode, file=sys.stderr)
        print("** Further testing aborted **", file=sys.stderr)

But there was a problem with the conclusion.

4 langunge

Error output

Error output Pascal

Pascal programm

var
  a,b: real;
begin
  readln(a,b);
  writeln(sqrt(a*a+b*b):0:3);
end.

Error Output

Free Pascal Compiler version 3.0.0+dfsg-2 [2016/01/28] for x86_64
Copyright (c) 1993-2015 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling prog.pas
Linking prog
7 lines compiled, 0.0 sec
5.000


***Error***
/usr/bin/ld.bfd: warning: link.res contains output sections; did you forget -T?

Please help me.

In reply to Pavel Mul

Re: Adding the Pascal programming language to the question

by Richard Lobb -

Your addition is essentially working OK, as evidenced by the 5.000. The only problem is that fpc generates extraneous output, including a spurious ld error (see here).

To compile, you currently have 

return_code = subprocess.call("fpc {0} prog.pas".format(pasflags).split())

but that prints the compiler output and also the spurious ld output.

You'll have to replace that with a different subprocess method, such as subprocess.check_output() as used later in the script, which captures the standard output rather than printing it. You may need to capture standard error as well. You should then print that output (possibly after editing it) only if the compile failed - probably that's indicated by the return code from the command being non-zero?

Richard

In reply to Pavel Mul

Re: Adding the Pascal programming language to the question

by Andrew Rogov -

Have you done this work?

For PascalABC this work:

elif language == 'pascal':
return_code = subprocess.check_output("pabcnetcclear tester.pas".split())
if return_code != b'OK\n':
raise Exception("
Compilation failed. Testing aborted ") exec_command = ["mono", "./tester.exe"]