Skip to content

Commit 74f33a3

Browse files
committed
Add preliminary package support
1 parent 68e6bfe commit 74f33a3

File tree

9 files changed

+84
-39
lines changed

9 files changed

+84
-39
lines changed

InMemoryCompilers/CSharp/test.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
example content

InMemoryCompilers/Java/test.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
example content

InMemoryCompilers/Python/jsonrepl.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ def resp(result):
2121
original_stdout = sys.stdout
2222
sys.stdout = result_stdout = StringIO()
2323
try:
24-
sys.modules["one"] = imp.new_module("one")
25-
if "stdlibCode" in request:
26-
exec(request["stdlibCode"], sys.modules["one"].__dict__)
24+
for pkgSource in request["packageSources"]:
25+
name = pkgSource["fileName"].replace(".py", "")
26+
sys.modules[name] = imp.new_module(name)
27+
exec(pkgSource["code"], sys.modules[name].__dict__)
2728
exec(request["code"], {})
2829
finally:
2930
sys.stdout = original_stdout

InMemoryCompilers/Python/test.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
example content

InMemoryCompilers/Ruby/jsonrepl.rb

+14-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,20 @@ def resp(result)
1414
begin
1515
$stdout = StringIO.new
1616
request = JSON.parse(requestLine)
17-
eval request['stdlibCode'] if request['stdlibCode']
18-
result = eval request['code'].sub(/require 'one'/, "")
17+
fileNames = request["packageSources"].map{|x| x["fileName"].sub(".rb", "")}
18+
19+
def evalCode(code, fileNames)
20+
for fn in fileNames do
21+
code = code.sub("require '#{fn}'", "")
22+
end
23+
eval code
24+
end
25+
26+
evalCode(request['stdlibCode'], fileNames) if request['stdlibCode']
27+
for pkgSource in request["packageSources"] do
28+
evalCode(pkgSource["code"], fileNames)
29+
end
30+
result = evalCode(request['code'], fileNames)
1931
resp({ :result => $stdout.string })
2032
rescue Exception
2133
resp({ :exceptionText => "#{$@.first}: #{$!.message} (#{$!.class})" + $@.drop(1).map{|s| "\n\t#{s}"}.join("") })

InMemoryCompilers/Ruby/test.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
example content

InMemoryCompilers/TypeScript/jsonrepl.js

+11-9
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,28 @@ function resp(result) {
2222

2323
readline.createInterface({ input: process.stdin, output: process.stdout, terminal: false }).on('line', requestLine => {
2424
try {
25+
//console.error(requestLine);
2526
const requestJson = JSON.parse(requestLine);
2627

2728
let code = requestJson.code;
2829
let stdlibCode = requestJson.stdlibCode || "";
29-
if (requestJson.lang === "TypeScript") {
30+
if (requestJson.lang === "typescript") {
3031
code = "// TS CODE\n" + tsCompile(code);
3132
stdlibCode = tsCompile(stdlibCode);
3233
}
3334

3435
let result = "";
3536
const script = new vm.Script(code);
3637
const context = new vm.createContext({
37-
console: {
38-
log: (...args) => result += (util.format(...args) + '\n'),
39-
},
40-
require: (...args) => {
41-
if (args[0] === 'one')
42-
return requireFromString(stdlibCode, 'one.js');
43-
else
44-
return require(...args);
38+
console: {
39+
log: (...args) => result += (util.format(...args) + '\n'),
40+
},
41+
require: (...args) => {
42+
const fullFn = `${args[0]}.js`;
43+
const pkgSource = requestJson.packageSources.find(x => `${x.packageName}/${x.fileName}` === fullFn);
44+
const result = pkgSource ? requireFromString(pkgSource.code, fullFn) : require(...args);
45+
console.error(`require: "${fullFn}" ->`, result);
46+
return result;
4547
}
4648
});
4749

InMemoryCompilers/TypeScript/test.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
example content

compiler_backend.py

+50-25
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from SocketServer import ThreadingMixIn
1818
from BaseHTTPServer import HTTPServer
1919

20+
ALLOW_CACHE = True
2021
PORT = 11111
2122
TEST_SERVERS = False
2223
TMP_DIR = "tmp/"
@@ -81,6 +82,8 @@ class Program {
8182
}
8283
""",
8384
"cmd": "csc Program.cs StdLib.cs > /dev/null && ./Program.exe",
85+
"compileCmd": "csc -recurse:src/*.cs -out:bin/Program.exe",
86+
"runCmd": "mono Program.exe",
8487
"mainFn": "Program.cs",
8588
"stdlibFn": "StdLib.cs",
8689
"versionCmd": "dotnet --info; echo CSC version: `csc -version`",
@@ -99,7 +102,7 @@ class Program {
99102
"ext": "cpp",
100103
"mainFn": "main.cpp",
101104
"stdlibFn": "one.hpp",
102-
"cmd": "g++ -std=c++17 main.cpp -I. -o binary && ./binary",
105+
"cmd": "g++ -std=c++17 main.cpp one_packages/*/*.cpp -I. -Ione_packages -o binary && ./binary",
103106
"versionCmd": "g++ -v",
104107
},
105108
"go": {
@@ -120,7 +123,7 @@ class Program {
120123
"ext": "swift",
121124
"mainFn": "main.swift",
122125
"stdlibFn": "one.swift",
123-
"cmd": "cat one.swift main.swift | swift -",
126+
"cmd": "cat main.swift | swift -",
124127
"versionCmd": "swift --version",
125128
}
126129
}
@@ -210,7 +213,7 @@ def log_message(self, format, *args):
210213
pass
211214

212215
def resp(self, statusCode, result):
213-
result["controllerVersion"] = "one:v1:20180122"
216+
result["controllerVersion"] = "one:v2:20200218"
214217
responseBody = json.dumps(result)
215218
self.send_response(statusCode)
216219
self.send_header("Content-Length", "%d" % len(responseBody))
@@ -229,50 +232,72 @@ def end_headers(self):
229232
def api_compile(self):
230233
requestJson = self.rfile.read(int(self.headers.getheader('content-length')))
231234
useCache = self.queryParams.get("useCache")
232-
if useCache:
235+
if ALLOW_CACHE:
233236
requestHash = hashlib.sha256(requestJson).hexdigest()[0:12]
234237
cacheFn = "%s/compilecache_%s_resp.json" % (TMP_DIR, requestHash)
235-
if os.path.exists(cacheFn):
238+
if useCache and os.path.exists(cacheFn):
236239
with open(cacheFn, "rt") as f:
237240
response = json.loads(f.read())
238241
response["fromCache"] = True
242+
response["cacheId"] = requestHash
239243
self.resp(200, response)
240244
return
241245

242246
request = json.loads(requestJson)
243247
request["cmd"] = "compile"
244248
langName = request["lang"]
249+
mode = request["mode"] if "mode" in request else "auto"
245250
lang = LANGS[langName]
246251

247252
start = time.time()
248-
if "jsonRepl" in lang:
253+
if mode == "jsonRepl" or (mode == "auto" and "jsonRepl" in lang):
249254
response = lang["jsonRepl"].request(request)
250-
elif "server" in lang:
255+
elif mode == "server" or (mode == "auto" and "server" in lang):
251256
responseJson = postRequest("http://127.0.0.1:%d" % lang["port"], requestJson)
252257
response = json.loads(responseJson)
253-
else:
254-
dateStr = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
255-
outDir = "%s%s_%s/" % (TMP_DIR, dateStr, langName)
256-
257-
with open(providePath(outDir + lang["mainFn"]), "wt") as f: f.write(request["code"])
258-
259-
if "stdlibCode" in request:
260-
with open(providePath(outDir + lang["stdlibFn"]), "wt") as f: f.write(request["stdlibCode"])
261-
262-
for pkgSrc in request["packageSources"]:
263-
with open(providePath(outDir + pkgSrc["fileName"]), "wt") as f: f.write(pkgSrc["code"])
258+
elif mode == "native" or mode == "auto":
259+
dateStr = datetime.datetime.now().strftime("%Y%m%d_%H%M%S_%f")
260+
dirName = "%s_%s" % (dateStr, langName)
261+
if "name" in request:
262+
dirName += "_" + request["name"]
263+
outDir = "%s%s/" % (TMP_DIR, dirName)
264+
binDir = outDir+"/bin/"
265+
mkdir_p(binDir)
266+
267+
response = { "tmpDir": dirName, "success": False }
268+
269+
for (filename, code) in request["files"].items():
270+
with open(providePath(outDir + "src/" + filename), "wt") as f: f.write(code)
271+
272+
#with open(providePath(outDir + lang["mainFn"]), "wt") as f: f.write(request["code"])
273+
#if "stdlibCode" in request:
274+
# with open(providePath(outDir + lang["stdlibFn"]), "wt") as f: f.write(request["stdlibCode"])
275+
#for pkgSrc in request["packageSources"]:
276+
# with open(providePath(outDir + "one_packages/" + pkgSrc["packageName"] + "/" + pkgSrc["fileName"]), "wt") as f: f.write(pkgSrc["code"])
264277

265-
pipes = subprocess.Popen(lang["cmd"], shell=True, cwd=outDir, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
278+
pipes = subprocess.Popen(lang["compileCmd"], shell=True, cwd=outDir, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
266279
stdout, stderr = pipes.communicate()
280+
success = pipes.returncode == 0 and stderr == ""
281+
response["compilation"] = { "stdout": stdout, "stderr": stderr, "exitCode": pipes.returncode, "success": success }
267282

268-
response = { "result": stdout }
269-
270-
if pipes.returncode != 0 or len(stderr) > 0:
271-
response["exceptionText"] = stderr
283+
if not success:
284+
response["error"] = "Program run failed with exitCode %d\nStderr:\n%s\nStdout:\n%s" % (pipes.returncode, stderr, stdout)
272285
else:
273-
shutil.rmtree(outDir)
286+
pipes = subprocess.Popen(lang["runCmd"], shell=True, cwd=binDir, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
287+
stdout, stderr = pipes.communicate()
288+
success = pipes.returncode == 0 and stderr == ""
289+
response["run"] = { "stdout": stdout, "stderr": stderr, "exitCode": pipes.returncode, "success": success }
290+
291+
if not success:
292+
response["error"] = "Program run failed with exitCode %d\nStderr:\n%s\nStdout:\n%s" % (pipes.returncode, stderr, stdout)
293+
else:
294+
response["success"] = True
295+
shutil.rmtree(outDir)
296+
else:
297+
response = { "error": "Unknown mode '%s'" % mode, "success": False }
274298

275-
if useCache:
299+
# cache should be overwritten even when useCache is False, otherwise a broken version stays there forever
300+
if ALLOW_CACHE:
276301
with open(cacheFn, "wt") as f: f.write(json.dumps(response))
277302

278303
response["elapsedMs"] = int((time.time() - start) * 1000)

0 commit comments

Comments
 (0)