Skip to content

Commit 5feb18b

Browse files
authored
Add “Go” Lang #102 (#173)
1 parent 13cf35f commit 5feb18b

File tree

14 files changed

+220
-2
lines changed

14 files changed

+220
-2
lines changed

Dockerfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ FROM scratch
2727
COPY --from=codegolf/lang-bash / /langs/bash/rootfs/
2828
COPY --from=codegolf/lang-brainfuck / /langs/brainfuck/rootfs/
2929
COPY --from=codegolf/lang-c / /langs/c/rootfs/
30+
COPY --from=codegolf/lang-go / /langs/go/rootfs/
3031
COPY --from=codegolf/lang-haskell / /langs/haskell/rootfs/
3132
COPY --from=codegolf/lang-j / /langs/j/rootfs/
3233
COPY --from=codegolf/lang-javascript / /langs/javascript/rootfs/
@@ -48,6 +49,8 @@ COPY --from=0 /empty /langs/brainfuck/rootfs/proc/
4849
COPY --from=0 /empty /langs/brainfuck/rootfs/tmp/
4950
COPY --from=0 /empty /langs/c/rootfs/proc/
5051
COPY --from=0 /empty /langs/c/rootfs/tmp/
52+
COPY --from=0 /empty /langs/go/rootfs/proc/
53+
COPY --from=0 /empty /langs/go/rootfs/tmp/
5154
COPY --from=0 /empty /langs/haskell/rootfs/proc/
5255
COPY --from=0 /empty /langs/haskell/rootfs/tmp/
5356
COPY --from=0 /empty /langs/j/rootfs/proc/

assets/common.css

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,10 +366,12 @@ thead th {
366366
text-decoration: none;
367367
}
368368

369+
/* When adding a new language, update grid-template-columns for #matrix below. */
369370
#matrix input,
370371
#matrix input.bash:not(:checked) ~ .bash,
371372
#matrix input.brainfuck:not(:checked) ~ .brainfuck,
372373
#matrix input.c:not(:checked) ~ .c,
374+
#matrix input.go:not(:checked) ~ .go,
373375
#matrix input.haskell:not(:checked) ~ .haskell,
374376
#matrix input.j:not(:checked) ~ .j,
375377
#matrix input.javascript:not(:checked) ~ .javascript,
@@ -414,7 +416,8 @@ thead th {
414416
max-width: 1280px;
415417
}
416418
#matrix {
417-
grid-template-columns: 3fr repeat(17,1fr);
419+
/* Increase this number when adding a language. */
420+
grid-template-columns: 3fr repeat(18,1fr);
418421
}
419422
#matrix a {
420423
display: initial;

assets/hole.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
/* include vendor/codemirror-bash.js */
88
/* include vendor/codemirror-brainfuck.js */
9+
/* include vendor/codemirror-go.js */
910
/* include vendor/codemirror-haskell.js */
1011
/* include vendor/codemirror-javascript.js */
1112
/* include vendor/codemirror-julia.js */
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
// CodeMirror, copyright (c) by Marijn Haverbeke and others
2+
// Distributed under an MIT license: https://codemirror.net/LICENSE
3+
4+
(function(mod) {
5+
mod(CodeMirror);
6+
})(function(CodeMirror) {
7+
"use strict";
8+
9+
CodeMirror.defineMode("go", function(config) {
10+
var indentUnit = config.indentUnit;
11+
12+
var keywords = {
13+
"break":true, "case":true, "chan":true, "const":true, "continue":true,
14+
"default":true, "defer":true, "else":true, "fallthrough":true, "for":true,
15+
"func":true, "go":true, "goto":true, "if":true, "import":true,
16+
"interface":true, "map":true, "package":true, "range":true, "return":true,
17+
"select":true, "struct":true, "switch":true, "type":true, "var":true,
18+
"bool":true, "byte":true, "complex64":true, "complex128":true,
19+
"float32":true, "float64":true, "int8":true, "int16":true, "int32":true,
20+
"int64":true, "string":true, "uint8":true, "uint16":true, "uint32":true,
21+
"uint64":true, "int":true, "uint":true, "uintptr":true, "error": true,
22+
"rune":true
23+
};
24+
25+
var atoms = {
26+
"true":true, "false":true, "iota":true, "nil":true, "append":true,
27+
"cap":true, "close":true, "complex":true, "copy":true, "delete":true, "imag":true,
28+
"len":true, "make":true, "new":true, "panic":true, "print":true,
29+
"println":true, "real":true, "recover":true
30+
};
31+
32+
var isOperatorChar = /[+\-*&^%:=<>!|\/]/;
33+
34+
var curPunc;
35+
36+
function tokenBase(stream, state) {
37+
var ch = stream.next();
38+
if (ch == '"' || ch == "'" || ch == "`") {
39+
state.tokenize = tokenString(ch);
40+
return state.tokenize(stream, state);
41+
}
42+
if (/[\d\.]/.test(ch)) {
43+
if (ch == ".") {
44+
stream.match(/^[0-9]+([eE][\-+]?[0-9]+)?/);
45+
} else if (ch == "0") {
46+
stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/);
47+
} else {
48+
stream.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/);
49+
}
50+
return "number";
51+
}
52+
if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
53+
curPunc = ch;
54+
return null;
55+
}
56+
if (ch == "/") {
57+
if (stream.eat("*")) {
58+
state.tokenize = tokenComment;
59+
return tokenComment(stream, state);
60+
}
61+
if (stream.eat("/")) {
62+
stream.skipToEnd();
63+
return "comment";
64+
}
65+
}
66+
if (isOperatorChar.test(ch)) {
67+
stream.eatWhile(isOperatorChar);
68+
return "operator";
69+
}
70+
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
71+
var cur = stream.current();
72+
if (keywords.propertyIsEnumerable(cur)) {
73+
if (cur == "case" || cur == "default") curPunc = "case";
74+
return "keyword";
75+
}
76+
if (atoms.propertyIsEnumerable(cur)) return "atom";
77+
return "variable";
78+
}
79+
80+
function tokenString(quote) {
81+
return function(stream, state) {
82+
var escaped = false, next, end = false;
83+
while ((next = stream.next()) != null) {
84+
if (next == quote && !escaped) {end = true; break;}
85+
escaped = !escaped && quote != "`" && next == "\\";
86+
}
87+
if (end || !(escaped || quote == "`"))
88+
state.tokenize = tokenBase;
89+
return "string";
90+
};
91+
}
92+
93+
function tokenComment(stream, state) {
94+
var maybeEnd = false, ch;
95+
while (ch = stream.next()) {
96+
if (ch == "/" && maybeEnd) {
97+
state.tokenize = tokenBase;
98+
break;
99+
}
100+
maybeEnd = (ch == "*");
101+
}
102+
return "comment";
103+
}
104+
105+
function Context(indented, column, type, align, prev) {
106+
this.indented = indented;
107+
this.column = column;
108+
this.type = type;
109+
this.align = align;
110+
this.prev = prev;
111+
}
112+
function pushContext(state, col, type) {
113+
return state.context = new Context(state.indented, col, type, null, state.context);
114+
}
115+
function popContext(state) {
116+
if (!state.context.prev) return;
117+
var t = state.context.type;
118+
if (t == ")" || t == "]" || t == "}")
119+
state.indented = state.context.indented;
120+
return state.context = state.context.prev;
121+
}
122+
123+
// Interface
124+
125+
return {
126+
startState: function(basecolumn) {
127+
return {
128+
tokenize: null,
129+
context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
130+
indented: 0,
131+
startOfLine: true
132+
};
133+
},
134+
135+
token: function(stream, state) {
136+
var ctx = state.context;
137+
if (stream.sol()) {
138+
if (ctx.align == null) ctx.align = false;
139+
state.indented = stream.indentation();
140+
state.startOfLine = true;
141+
if (ctx.type == "case") ctx.type = "}";
142+
}
143+
if (stream.eatSpace()) return null;
144+
curPunc = null;
145+
var style = (state.tokenize || tokenBase)(stream, state);
146+
if (style == "comment") return style;
147+
if (ctx.align == null) ctx.align = true;
148+
149+
if (curPunc == "{") pushContext(state, stream.column(), "}");
150+
else if (curPunc == "[") pushContext(state, stream.column(), "]");
151+
else if (curPunc == "(") pushContext(state, stream.column(), ")");
152+
else if (curPunc == "case") ctx.type = "case";
153+
else if (curPunc == "}" && ctx.type == "}") popContext(state);
154+
else if (curPunc == ctx.type) popContext(state);
155+
state.startOfLine = false;
156+
return style;
157+
},
158+
159+
indent: function(state, textAfter) {
160+
if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
161+
var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
162+
if (ctx.type == "case" && /^(?:case|default)\b/.test(textAfter)) {
163+
state.context.type = "}";
164+
return ctx.indented;
165+
}
166+
var closing = firstChar == ctx.type;
167+
if (ctx.align) return ctx.column + (closing ? 0 : 1);
168+
else return ctx.indented + (closing ? 0 : indentUnit);
169+
},
170+
171+
electricChars: "{}):",
172+
closeBrackets: "()[]{}''\"\"``",
173+
fold: "brace",
174+
blockCommentStart: "/*",
175+
blockCommentEnd: "*/",
176+
lineComment: "//"
177+
};
178+
});
179+
});

build-langs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ declare -A urls=(
1111
["Bash"]="//www.gnu.org/software/bash/"
1212
["Brainfuck"]="//github.com/code-golf/code-golf/tree/master/langs/brainfuck/"
1313
["C"]="//bellard.org/tcc/"
14+
["Go"]="//golang.org"
1415
["Haskell"]="//www.haskell.org/ghc/"
1516
["J"]="http://jsoftware.com"
1617
["JavaScript"]="//v8.dev"
@@ -64,6 +65,8 @@ for name in "${sorted_names[@]}"; do
6465
ver=${ver#The Glorious }
6566
ver=${ver#This is }
6667
ver=${ver#rustc }
68+
ver=${ver/go version go/}
69+
ver=${ver/ linux\/amd64/}
6770
ver=${ver/ation/er}
6871
ver=${ver/built /}
6972
ver=${ver/System, /}

db/0.schema.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ CREATE TYPE hole AS ENUM (
1414
);
1515

1616
CREATE TYPE lang AS ENUM (
17-
'bash', 'brainfuck', 'c', 'haskell', 'j', 'javascript', 'julia', 'lisp',
17+
'bash', 'brainfuck', 'c', 'go', 'haskell', 'j', 'javascript', 'julia', 'lisp',
1818
'lua', 'nim', 'perl', 'php', 'python', 'raku', 'ruby', 'rust', 'swift'
1919
);
2020

hole/hole.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ func Play(ctx context.Context, holeID, langID, code string) (score Scorecard) {
8585
cmd.Args = []string{"/usr/bin/bash", "-s", "-"}
8686
case "c":
8787
cmd.Args = []string{"/usr/bin/tcc", "-run", "-"}
88+
case "go":
89+
cmd.Args = []string{"/usr/bin/run-go"}
8890
case "haskell", "javascript", "php":
8991
cmd.Args = []string{"/usr/bin/" + langID, "--"}
9092
case "j":

langs/go/.dockerignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*
2+
!/run-go

langs/go/Dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM golang:1.14.2-alpine as builder
2+
3+
FROM scratch
4+
5+
COPY --from=0 / /
6+
7+
COPY run-go /usr/bin/run-go
8+
9+
ENTRYPOINT ["/usr/local/go/bin/go", "version"]

langs/go/run-go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/sh -e
2+
3+
# Separate compile and link relies on environment variables less than "go run" does.
4+
# "go run" also doesn't support reading the file from stdin.
5+
cat - > /tmp/code.go
6+
/usr/local/go/bin/go tool compile -o /tmp/code.o /tmp/code.go
7+
/usr/local/go/bin/go tool link -o /tmp/code /tmp/code.o
8+
rm /tmp/code.go /tmp/code.o
9+
/tmp/code "$@"

0 commit comments

Comments
 (0)