diff --git a/backend/coreapp/asm_diff_wrapper.py b/backend/coreapp/asm_diff_wrapper.py index be26380..7991ea0 100644 --- a/backend/coreapp/asm_diff_wrapper.py +++ b/backend/coreapp/asm_diff_wrapper.py @@ -59,6 +59,11 @@ class AsmDifferWrapper: config = AsmDifferWrapper.create_config(MIPS_SETTINGS) # todo read arch from compiler config of compilation basedump = AsmDifferWrapper.run_objdump(target_assembly.object, config) mydump = AsmDifferWrapper.run_objdump(compilation.object, config) + + # Remove first few junk lines from objdump output + basedump = "\n".join(basedump.split("\n")[6:]) + mydump = "\n".join(mydump.split("\n")[6:]) + display = Display(basedump, mydump, config) return display.run_diff() diff --git a/backend/coreapp/compiler_wrapper.py b/backend/coreapp/compiler_wrapper.py index d0eccee..3f2df1c 100644 --- a/backend/coreapp/compiler_wrapper.py +++ b/backend/coreapp/compiler_wrapper.py @@ -3,6 +3,7 @@ from django.conf import settings from django.utils.crypto import get_random_string import logging import os +import re from pathlib import Path import subprocess @@ -23,6 +24,10 @@ def asm_objects_path() -> Path: def compilation_objects_path() -> Path: return Path(os.path.join(settings.LOCAL_FILE_DIR, 'compilations')) +def replace_paths(match) -> str: + s = match.group(0) + return "src" + s[-2:] + class CompilerWrapper: def base_path(): return settings.COMPILER_BASE_PATH @@ -44,14 +49,9 @@ class CompilerWrapper: result = subprocess.run(compile_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) stderr = result.stderr.decode() - stderr_lines = stderr.splitlines() - for i, line in enumerate(stderr_lines): - file_end = line.find(":") - - if file_end != -1: - stderr_lines[i] = "input.c" + line[file_end:].strip() - stderr = "\n".join(stderr_lines) + pattern = re.compile(r"[/](?:(?!\.\s+)\S)+(\.)?") + stderr = re.sub(pattern, replace_paths, stderr) if result.returncode != 0: logger.error(result.stderr.decode()) @@ -132,7 +132,7 @@ class CompilerWrapper: object_path = compilation_objects_path() / (temp_name + ".o") with open(code_path, "w", newline="\n") as f: - f.write(context + code) + f.write(context + code + "\n") # Run compiler compile_status, stderr = CompilerWrapper.run_compiler( diff --git a/backend/coreapp/views.py b/backend/coreapp/views.py index 47c46f1..963e7d2 100644 --- a/backend/coreapp/views.py +++ b/backend/coreapp/views.py @@ -76,7 +76,6 @@ def scratch(request, slug=None): asm = get_db_asm(data["target_asm"]) del data["target_asm"] - # Validate target asm compiler_config = CompilerConfiguration.objects.get(id=request.data["compiler_config"]) assembly = CompilerWrapper.assemble_asm(compiler_config, asm) @@ -98,17 +97,16 @@ def scratch(request, slug=None): if not slug: return Response({"error": "Missing slug"}, status=status.HTTP_400_BAD_REQUEST) - if "compiler_config" not in request.data: - return Response({"error": "Missing compiler_config"}, status=status.HTTP_400_BAD_REQUEST) + required_params = ["compiler_config", "source_code", "context"] - if "source_code" not in request.data: - return Response({"error": "Missing source_code"}, status=status.HTTP_400_BAD_REQUEST) - - if "context" not in request.data: - return Response({"error": "Missing context"}, status=status.HTTP_400_BAD_REQUEST) + for param in required_params: + if param not in request.data: + return Response({"error": f"Missing parameter: {param}"}, status=status.HTTP_400_BAD_REQUEST) + + compiler_config = CompilerConfiguration.objects.get(id=request.data["compiler_config"]) db_scratch = get_object_or_404(Scratch, slug=slug) - db_scratch.compiler_config = request.data["compiler_config"] + db_scratch.compiler_config = compiler_config db_scratch.source_code = request.data["source_code"] db_scratch.context = request.data["context"] db_scratch.save() @@ -116,21 +114,21 @@ def scratch(request, slug=None): @api_view(["POST"]) def compile(request, slug): - required_params = ["compiler_config", "code", "context"] + required_params = ["compiler_config", "source_code", "context"] for param in required_params: if param not in request.data: return Response({"error": f"Missing parameter: {param}"}, status=status.HTTP_400_BAD_REQUEST) compiler_config = CompilerConfiguration.objects.get(id=request.data["compiler_config"]) - code = request.data["code"] + code = request.data["source_code"] context = request.data["context"] scratch = Scratch.objects.get(slug=slug) compilation, errors = CompilerWrapper.compile_code(compiler_config, code, context) diff_output = "" - if not errors: + if compilation: diff_output = AsmDifferWrapper.diff(scratch.target_assembly, compilation) response_obj = { diff --git a/frontend/package.json b/frontend/package.json index 376e191..e21b371 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -8,6 +8,7 @@ "@monaco-editor/react": "^4.2.1", "preact": "^10.5.13", "preact-router": "^3.2.1", + "react-hot-toast": "^2.1.0", "react-simple-resizer": "^2.1.0", "swr": "^0.5.6", "use-debounce": "^7.0.0" diff --git a/frontend/src/api.js b/frontend/src/api.js index 574a584..3100d07 100644 --- a/frontend/src/api.js +++ b/frontend/src/api.js @@ -40,3 +40,26 @@ export async function post(url, body) { return await response.json() } + +export async function patch(url, body) { + if (typeof body != "string") { + body = JSON.stringify(body) + } + + console.info("PATCH", url, JSON.parse(body)) + + const response = await fetch(API_BASE + url, { + ...commonOpts, + method: "PATCH", + body, + headers: { + 'Content-Type': 'application/json', + }, + }) + + if (!response.ok) { + throw new Error(response.status) + } + + return await response.json() +} diff --git a/frontend/src/scratch/Scratch.jsx b/frontend/src/scratch/Scratch.jsx index 9ebb265..b0efa5f 100644 --- a/frontend/src/scratch/Scratch.jsx +++ b/frontend/src/scratch/Scratch.jsx @@ -2,6 +2,7 @@ import { h } from "preact" import { useEffect, useState } from "preact/hooks" import { useDebouncedCallback } from "use-debounce" import * as resizer from "react-simple-resizer" +import toast, { Toaster } from 'react-hot-toast'; import * as api from "../api" import CompilerConfigSelect from "./CompilerConfigSelect" @@ -30,7 +31,7 @@ export default function Scratch({ slug }) { const compile = async () => { const { diff_output, errors } = await api.post(`/scratch/${slug}/compile`, { compiler_config: compilerConfig, - code: cCode, + source_code: cCode, context: cContext, }) @@ -41,6 +42,19 @@ export default function Scratch({ slug }) { } } + const update = async () => { + const { errors } = await api.patch(`/scratch/${slug}`, { + compiler_config: compilerConfig, + source_code: cCode, + context: cContext, + }) + .then( + toast.success("Scratch updated!", {position: "top-right"}) + ) + + setLog(errors) + } + // Recompile automatically const debounced = useDebouncedCallback(compile, 1000) @@ -58,6 +72,7 @@ export default function Scratch({ slug }) { }) return