-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Get first c++ judgements up and running
- Loading branch information
Showing
13 changed files
with
590 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
from pathlib import Path | ||
import re | ||
|
||
from tested.languages.c.config import C | ||
from tested.languages.language import CallbackResult | ||
from tested.languages.preparation import PreparedExecutionUnit | ||
from tested.languages.utils import executable_name | ||
|
||
|
||
class CPP(C): | ||
def initial_dependencies(self) -> list[str]: | ||
return ["values.h", "values.cpp", "evaluation_result.h", "evaluation_result.cpp"] | ||
|
||
def file_extension(self) -> str: | ||
return "cpp" | ||
|
||
def compilation(self, files: list[str]) -> CallbackResult: | ||
main_file = files[-1] | ||
exec_file = Path(main_file).stem | ||
result = executable_name(exec_file) | ||
return ( | ||
[ | ||
"g++", | ||
"-std=c++11", | ||
"-Wall", | ||
"-O3" if self.config.options.compiler_optimizations else "-O0", | ||
"evaluation_result.cpp", | ||
"values.cpp", | ||
main_file, | ||
"-o", | ||
result, | ||
], | ||
[result], | ||
) | ||
|
||
def generate_execution_unit(self, execution_unit: "PreparedExecutionUnit") -> str: | ||
from tested.languages.cpp import generators | ||
return generators.convert_execution_unit(execution_unit) | ||
|
||
def generate_selector(self, contexts: list[str]) -> str: | ||
from tested.languages.cpp import generators | ||
|
||
return generators.convert_selector(contexts) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
import json | ||
|
||
from tested.languages.c.generators import convert_statement | ||
from tested.languages.preparation import PreparedExecutionUnit, PreparedContext, \ | ||
PreparedTestcase, PreparedTestcaseStatement | ||
from tested.languages.utils import is_special_void_call | ||
from tested.testsuite import MainInput | ||
|
||
|
||
def _generate_internal_context(ctx: PreparedContext, pu: PreparedExecutionUnit) -> str: | ||
result = f""" | ||
{ctx.before} | ||
int exit_code; | ||
""" | ||
|
||
# Generate code for each testcase | ||
tc: PreparedTestcase | ||
for tc in ctx.testcases: | ||
result += f"{pu.unit.name}_write_separator();\n" | ||
|
||
if tc.testcase.is_main_testcase(): | ||
assert isinstance(tc.input, MainInput) | ||
wrapped = [json.dumps(a) for a in tc.input.arguments] | ||
result += f'string string_args[] = {{"{pu.submission_name}", ' | ||
result += ", ".join(wrapped) | ||
result += "};\n" | ||
result += f""" | ||
// convert string to char** | ||
const int argc = {len(tc.input.arguments) + 1}; | ||
char** args = new char*[argc]; | ||
for (int i = 0; i < argc; i++) {{ | ||
args[i] = new char[string_args[i].size() + 1]; | ||
strcpy(args[i], string_args[i].c_str()); | ||
}} | ||
""" | ||
result += ( | ||
f"exit_code = solution_main(argc, args);\n" | ||
) | ||
else: | ||
assert isinstance(tc.input, PreparedTestcaseStatement) | ||
result += "exit_code = 0;\n" | ||
if is_special_void_call(tc.input, pu.language): | ||
# The method has a "void" return type, so don't wrap it. | ||
result += ( | ||
" " * 4 | ||
+ convert_statement(tc.input.unwrapped_input_statement()) | ||
+ ";\n" | ||
) | ||
result += " " * 4 + convert_statement(tc.input.no_value_call()) + ";\n" | ||
else: | ||
result += convert_statement(tc.input.input_statement()) + ";\n" | ||
|
||
result += ctx.after + "\n" | ||
result += "return exit_code;\n" | ||
return result | ||
|
||
|
||
def convert_execution_unit(pu: PreparedExecutionUnit) -> str: | ||
result = f""" | ||
#include "values.h" | ||
#include "{pu.submission_name}.cpp" | ||
using namespace std; | ||
""" | ||
|
||
# Import functions | ||
for name in pu.evaluator_names: | ||
result += f'#include "{name}.cpp"\n' | ||
|
||
result += f""" | ||
static FILE* {pu.unit.name}_value_file = NULL; | ||
static FILE* {pu.unit.name}_exception_file = NULL; | ||
static void {pu.unit.name}_write_separator() {{ | ||
fprintf({pu.unit.name}_value_file, "--{pu.testcase_separator_secret}-- SEP"); | ||
fprintf({pu.unit.name}_exception_file, "--{pu.testcase_separator_secret}-- SEP"); | ||
fprintf(stdout, "--{pu.testcase_separator_secret}-- SEP"); | ||
fprintf(stderr, "--{pu.testcase_separator_secret}-- SEP"); | ||
}} | ||
static void {pu.unit.name}_write_context_separator() {{ | ||
fprintf({pu.unit.name}_value_file, "--{pu.context_separator_secret}-- SEP"); | ||
fprintf({pu.unit.name}_exception_file, "--{pu.context_separator_secret}-- SEP"); | ||
fprintf(stdout, "--{pu.context_separator_secret}-- SEP"); | ||
fprintf(stderr, "--{pu.context_separator_secret}-- SEP"); | ||
}} | ||
#undef send_value | ||
#define send_value(value) write_value({pu.unit.name}_value_file, value) | ||
#undef send_specific_value | ||
#define send_specific_value(value) write_evaluated({pu.unit.name}_value_file, value) | ||
""" | ||
|
||
# Generate code for each context. | ||
ctx: PreparedContext | ||
for i, ctx in enumerate(pu.contexts): | ||
result += f""" | ||
int {pu.unit.name}_context_{i}(void) {{ | ||
{_generate_internal_context(ctx, pu)} | ||
}} | ||
""" | ||
|
||
result += f""" | ||
int {pu.unit.name}() {{ | ||
{pu.unit.name}_value_file = fopen("{pu.value_file}", "w"); | ||
{pu.unit.name}_exception_file = fopen("{pu.exception_file}", "w"); | ||
int exit_code; | ||
""" | ||
|
||
for i, ctx in enumerate(pu.contexts): | ||
result += " " * 4 + f"{pu.unit.name}_write_context_separator();\n" | ||
result += " " * 4 + f"exit_code = {pu.unit.name}_context_{i}();\n" | ||
|
||
result += f""" | ||
fclose({pu.unit.name}_value_file); | ||
fclose({pu.unit.name}_exception_file); | ||
return exit_code; | ||
}} | ||
#ifndef INCLUDED | ||
int main() {{ | ||
return {pu.unit.name}(); | ||
}} | ||
#endif | ||
""" | ||
return result | ||
|
||
|
||
def convert_selector(contexts: list[str]) -> str: | ||
result = """ | ||
#include <string.h> | ||
#include <stdio.h> | ||
#define INCLUDED true | ||
""" | ||
|
||
for ctx in contexts: | ||
result += f""" | ||
#if __has_include("{ctx}.cpp") | ||
#include "{ctx}.cpp" | ||
#endif | ||
""" | ||
|
||
result += """ | ||
int main(int argc, const char* argv[]) { | ||
if (argc < 1) { | ||
fprintf(stderr, "No context selected."); | ||
return -2; | ||
} | ||
const char* name = argv[1]; | ||
""" | ||
for ctx in contexts: | ||
result += f""" | ||
#if __has_include("{ctx}.cpp") | ||
if (strcmp("{ctx}", name) == 0) {{ | ||
return {ctx}(); | ||
}} | ||
#endif | ||
""" | ||
|
||
result += """ | ||
fprintf(stderr, "Non-existing context '%s' selected.", name); | ||
return -1; | ||
} | ||
""" | ||
return result |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
#include <iostream> | ||
#include <vector> | ||
#include <string> | ||
|
||
#include "evaluation_result.h" | ||
|
||
// Define the Message constructor | ||
Message::Message(const std::string &desc, const std::string &fmt, const std::string &perm) | ||
: description(desc), format(fmt.empty() ? "text" : fmt), permission(perm) {} | ||
|
||
// Define the EvaluationResult constructor | ||
EvaluationResult::EvaluationResult(size_t nrOfMessages) { | ||
messages.reserve(nrOfMessages); | ||
} | ||
|
||
// Define the EvaluationResult destructor | ||
EvaluationResult::~EvaluationResult() { | ||
for (auto message : messages) { | ||
delete message; | ||
} | ||
} | ||
|
||
// Function to create an EvaluationResult object | ||
EvaluationResult* create_result(size_t nrOfMessages) { | ||
return new EvaluationResult(nrOfMessages); | ||
} | ||
|
||
// Function to free an EvaluationResult object | ||
void free_result(EvaluationResult *result) { | ||
delete result; | ||
} | ||
|
||
// Function to create a Message object | ||
Message* create_message(const std::string &description, const std::string &format, const std::string &permission) { | ||
return new Message(description, format, permission); | ||
} | ||
|
||
// Function to free a Message object | ||
void free_message(Message *message) { | ||
delete message; | ||
} | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#ifndef EVALUATION_RESULT_H | ||
#define EVALUATION_RESULT_H | ||
|
||
#include <iostream> | ||
#include <vector> | ||
#include <string> | ||
|
||
using namespace std; | ||
|
||
// Define the Message structure | ||
struct Message { | ||
string description; | ||
string format; | ||
string permission; | ||
|
||
Message(const string &desc, const string &fmt, const string &perm); | ||
}; | ||
|
||
// Define the EvaluationResult structure | ||
struct EvaluationResult { | ||
vector<Message*> messages; | ||
bool result; | ||
string readableExpected; | ||
string readableActual; | ||
|
||
EvaluationResult(size_t nrOfMessages); | ||
~EvaluationResult(); | ||
}; | ||
|
||
|
||
// Function to create an EvaluationResult object | ||
EvaluationResult* create_result(size_t nrOfMessages); | ||
|
||
// Function to free an EvaluationResult object | ||
void free_result(EvaluationResult *result); | ||
|
||
// Function to create a Message object | ||
Message* create_message(const string &description, const string &format, const string &permission); | ||
|
||
// Function to free a Message object | ||
void free_message(Message *message); | ||
|
||
#endif //EVALUATION_RESULT_H |
Oops, something went wrong.