自己コンパイルコンパイラ[終了]


36

これは、私がしばらく前に聞いたコンパイラに関する話に基づいていますが、残念ながら、いつ、どこで思い出すことができません。

自分自身をコンパイルできる言語で最短のコンパイラを作成します。「コンパイルプログラム」命令を持たない合理的なISA(68K、x86、MIPS、ARM、SPARC、IBM BALなど)をターゲットにします(VAXの一部のバージョンが除外される場合があります)。からソースプログラムを読み取りstdin、生成されたコードをに出力しstdoutます。I / Oおよび文字列処理に標準Cライブラリを使用できます(例:)_printf。言語全体をコンパイルする必要はありません。コンパイラを含むサブセットのみをコンパイルする必要があります(つまり、アセンブリ言語のクインを印刷するだけで、印象的ですが、ソリューションとしてカウントされません)。


1
人々が入力を無視してハードコーディングされた定数出力を生成するのを防ぐために、いくつかの基準を追加する必要があります。
R.マルティーニョフェルナンデス

1
うわー、これは挑戦です。(特にPerlの場合)
ネイサンオスマン

5
実際、これはIOCCCへの提出として約3000バイトのCコードでCコンパイラを書いた人を思い起こさせます。
-FUZxxl

5
@FUZxxl:それはtccになり、かなりクールな製品です。
dmckee

3
@dmckee「サポートされているCスクリプト:#!/usr/local/bin/tcc -runCソースの最初の行に追加するだけで、コマンドラインから直接実行できます。」それはいいね。
トビア14

回答:


33

Haskellサブセット→C-18926文字

Haskellの小さなサブセットをCにコンパイルします。サポートする機能は次のとおりです。

  • パターンマッチングとガード
  • データ宣言
  • 中置演算子を選択する
  • 遅延評価

欠けている最大の機能は、ネストされた変数(ラムダ/ let / where / caseを意味しない)、型チェック、および型クラスです。結果のプログラムはメモリをリークし、システム上で自己コンパイルに約200メガバイトかかります(Boehmガベージコレクターは非常に役立ちますが、コンパイラが末尾再帰を最適化する場合のみです)。

ブートストラップするには、最初の3行のコメントを外し(スコアにはカウントされません)、GHCでコンパイルします。コンパイラは、stdinでHaskellサブセットコードを受け取り、stdoutでCコードを生成します。

言語が複雑だからではなく、怠け者だからです。 ただし、現在は最短のソリューション です。今週末は退屈しないだろうと思います。

-- import Prelude hiding (fmap, lookup, snd, zip);import Data.Char
-- import Data.List hiding (lookup, zip);data P a b = P a b;data B = B
-- add=(+);sub=(-);showInt=show;append[]ys=ys;append(x:xs)ys=x:append xs ys
data Program = Program [[Constructor]] [Function]
data Toplevel = TD [Constructor] | TE Equation | TO
data Constructor = Constructor String Int
data Function = Function String Int [Equation]
data Equation = Equation String [Pattern] (Maybe Expression) Expression
data Pattern = PVar String | PCon String [Pattern]
data Expression = Var String | Con String | Int String | Char String | String String | Ap Expression Expression
data Environment = Environment [P String Int] [P String VarInfo]
data VarInfo = VBox String | VArg Int | VItem VarInfo Int
main = interact (compile . parse)
constructorName (Constructor name _) = name
functionName (Function name _ _) = name
equationName (Equation name _ _ _) = name
sortToplevels [] = (P [] [])
sortToplevels (TD x : xs) = applyFst ((:) x) (sortToplevels xs)
sortToplevels (TE x : xs) = applySnd ((:) x) (sortToplevels xs)
sortToplevels (TO : xs)   = sortToplevels xs
pcons x xs = PCon "Cons" [x, xs];pnil = PCon "Nil" []
ebinary op a b = Ap (Ap (Var op) a) b;ebinaryE op a b = Ap (Ap op a) b
econs x xs = Ap (Ap (Con "Cons") x) xs
enil = Con "Nil"
listEq eq [] [] = True
listEq eq (x:xs) (y:ys) | eq x y = listEq eq xs ys
listEq _ _ _ = False
snd (P a b) = b
zip = zipWith P
lookup q (P k v : _)  | listEq (==) q k = Just v
lookup q (_     : xs)                   = lookup q xs
lookup q _                              = Nothing
compose2 f g x y = f (g x y)
applyFst f (P x y) = P (f x) y
applySnd f (P x y) = P x (f y)
fMaybe f Nothing  = Nothing
fMaybe f (Just x) = Just (f x)
cond f t False = f
cond f t True = t
condList f t [] = f
condList f t xs = t xs
countFrom n = n : countFrom (add n 1)
range l h | l > h = []
range l h         = l : range (add l 1) h
parse = makeProgram . sortToplevels . concatMap parse_p . ((:) prelude) . preprocess
parse_p (P lineno line) = maybe (parse_err lineno line) snd (parseLine line)
parse_err lineno line = error (concat ["Parse error on line ", showInt lineno, ": `", line, "`"])
preprocess = filter (not . isCommentOrEmpty . snd) . zip (countFrom 1) . map (dropWhile isBlank) . lines
isCommentOrEmpty = parserSucceeds (pro (ignore (pro (parseS "--") (parseS "import "))) parseEof)
liftA2 f a b = ap (fmap f a) b
parserSucceeds p s = maybe False (const True) (p s)
fmap f p = fMaybe (applySnd f) . p
pure x s = Just (P s x)
ap1 b (P s x) = maybe Nothing (ap2 x) (b s)
ap2 x (P s y) = Just (P s (x y))
empty = (const Nothing)
pro a b s = maybe (b s) Just (a s)
ap a b = maybe Nothing (ap1 b) . a
prc = liftA2 (:)
pra = liftA2 append
prl = liftA2 const
prr = liftA2 (const id)
many p = pro (some p) (pure [])
some p = prc p (many p)
optional p = pro (fmap Just p) (pure Nothing)
choice = foldr pro (const Nothing)
parseEof = parseEof_1
parseEof_1 [] = Just (P "" B)
parseEof_1 _  = Nothing
parsePred pred = parsePred_1 pred
parsePred_1 pred (x:xs) | pred x = Just (P xs x)
parsePred_1 _    _               = Nothing
manyParsePred = justFlipSplit
justFlipSplit pred xs = Just (P (dropWhile pred xs) (takeWhile pred xs))
someParsePred pred = prc (parsePred pred) (manyParsePred pred)
parseC = parsePred . (==)
parseS = foldr (prc . parseC) (pure [])
wrapC = wrapSpace . parseC
wrapS = wrapSpace . parseS
skipPred pred = prr (parsePred pred) (pure B)
manySkipPred pred = prr (manyParsePred pred) (pure B)
preSep p sep = many (prr sep p)
sepBy1 p sep = prc p (many (prr sep p))
sepByChar p c = pro (sepByChar1 p c) (pure [])
sepByChar1 p c = sepBy1 p (wrapSpace (parseC c))
wrapSpace p = prl (prr skipSpace p) skipSpace
ignore = fmap (const B)
isBlank c | c == ' ' || c == '\t' = True
isBlank _                         = False
isDigit1 c = c >= '1' && c <= '9'
parseBetween l r p = prl (prr (parseC l) (wrapSpace p)) (parseC r)
skipSpace = manySkipPred isBlank
chainl1 f sep p = fmap (foldl1 f) (sepBy1 p sep)
chainr1 f sep p = fmap (foldr1 f) (sepBy1 p sep)
chainl f z sep p = pro (fmap (foldl f z) (sepBy1 p sep)) (pure z)
chainr f z sep p = pro (fmap (foldr f z) (sepBy1 p sep)) (pure z)
parseNonassoc ops term = liftA2 (flip ($)) term (pro (liftA2 flip (choice ops) term) (pure id))
parseVar = prc (parsePred (orUnderscore isLower)) (many (parsePred (orUnderscore isAlphaNum)))
orUnderscore p c | p c || c == '_' = True
orUnderscore _ _ = False
parseCon = prc (parsePred isUpper) (many (parsePred (orUnderscore isAlphaNum)))
parseInt = pro (parseS "0") (prc (parsePred isDigit1) (many (parsePred isDigit)))
parseEscape q (c:x:xs) | c == '\\' = Just (P xs (c:x:[]))
parseEscape q [c]      | c == '\\' = Just (P [] [c])
parseEscape q (c:xs)   | c /= q    = Just (P xs [c])
parseEscape q _                    = Nothing
parseStringLiteral q = pra (parseS [q]) (pra (fmap concat (many (parseEscape q))) (parseS [q]))
parsePattern = chainr1 pcons (wrapC ':') (pro (liftA2 PCon parseCon (preSep parsePatternPrimary skipSpace)) parsePatternPrimary)
parsePatternPrimary = choice [fmap PVar parseVar, fmap (flip PCon []) parseCon, parseBetween '(' ')' parsePattern, parseBetween '[' ']' (fmap (foldr pcons pnil) (sepByChar parsePattern ','))]
relops f = relops_1 (ops_c f)
otherops f = f ":" (Con "Cons") : otherops_1 (ops_c f)
ops_c f x y = f x (Var y)
relops_1 f   = [f "<=" "_le", f "<" "_lt", f "==" "_eq", f ">=" "_ge", f ">" "_gt", f "/=" "_ne"]
otherops_1 f = [f "$" "_apply", f "||" "_or", f "&&" "_and", f "." "_compose"]
parseRelops = parseNonassoc (relops parseRelops_f)
parseRelops_f op func = prr (wrapS op) (pure (ebinaryE func))
parseExpression = chainr1 (ebinary "_apply") (wrapC '$') $ chainr1 (ebinary "_or") (wrapS "||") $ chainr1 (ebinary "_and") (wrapS "&&") $ parseRelops $ chainr1 econs (wrapC ':') $ chainr1 (ebinary "_compose") (wrapC '.') $ chainl1 Ap skipSpace $ choice [fmap Var parseVar, fmap Con parseCon, fmap Int parseInt, fmap Char (parseStringLiteral '\''), fmap String (parseStringLiteral '"'), parseBetween '(' ')' (pro parseSection parseExpression), parseBetween '[' ']' (chainr econs enil (wrapC ',') parseExpression)]
parseSection = choice (append (relops parseSection_f) (otherops parseSection_f))
parseSection_f op func = prr (wrapS op) (pure func)
parseEquation = ap (ap (ap (fmap Equation parseVar) (many (prr skipSpace parsePatternPrimary))) (optional (prr (wrapC '|') parseExpression))) (prr (wrapC '=') parseExpression)
skipType = ignore (sepBy1 (sepBy1 skipTypePrimary skipSpace) (wrapS "->"))
skipTypePrimary = choice [ignore parseVar, ignore parseCon, parseBetween '(' ')' skipType, parseBetween '[' ']' skipType]
parseDataDecl = prr (parseS "data") (prr skipSpace (prr parseCon (prr (preSep parseVar skipSpace) (prr (wrapC '=') (sepByChar1 (liftA2 Constructor parseCon (fmap length (preSep skipTypePrimary skipSpace))) '|')))))
skipTypeSignature = prr parseVar (prr (wrapS "::") skipType)
skipTypeAlias = prr (parseS "type") (prr skipSpace (prr parseCon (prr (preSep parseVar skipSpace) (prr (wrapC '=') skipType))))
parseToplevel = choice [fmap (const TO) (pro skipTypeSignature skipTypeAlias), fmap TD parseDataDecl, fmap TE parseEquation]
parseLine = prl (prl (sepByChar1 parseToplevel ';') skipSpace) parseEof
patternCount (Equation _ ps _ _) = length ps
makeProgram (P ds es) = Program ds (makeFunctions es)
makeFunctions = map makeFunctions_f . groupBy makeFunctions_g
makeFunctions_f []     = error "Internal error: No equations in binding group"
makeFunctions_f (x:xs) = cond (error (concat ["Equations for ", equationName x, " have different numbers of arguments"])) (Function (equationName x) (patternCount x) (x:xs)) (all (((==) (patternCount x)) . patternCount) xs)
makeFunctions_g (Equation name_a _ _ _) (Equation name_b _ _ _) = listEq (==) name_a name_b
lookupCon name (Environment c _) = lookup name c
lookupVar name (Environment _ v) = lookup name v
walkPatterns f = walkPatterns_items f VArg
walkPatterns_items f base = concat . zipWith (walkPatterns_f2 f) (map base (countFrom 0))
walkPatterns_f2 f v (PCon name ps) = append (f v (PCon name ps)) (walkPatterns_items f (VItem v) ps)
walkPatterns_f2 f v p              = f v p
compile (Program decls funcs) = concat [header, declareConstructors decls, declareFunctions funcs, boxConstructors decls, boxFunctions funcs, compileConstructors decls, compileFunctions (globalEnv decls funcs) funcs]
globalEnv decls funcs = Environment (append (globalEnv_constructorTags decls) (globalEnv_builtinConstructors)) (append (map (globalEnv_f . functionName) funcs) globalEnv_builtinFunctions)
globalEnv_f name = (P name (VBox name))
globalEnv_constructorTags = concatMap (flip zip (countFrom 0) . map constructorName)
globalEnv_builtinConstructors = [P "Nil" 0, P "Cons" 1, P "P" 0]
globalEnv_builtinFunctions = map globalEnv_f ["add", "sub", "_lt", "_le", "_eq", "_ge", "_gt", "_ne", "_and", "_or", "divMod", "negate", "not", "error"]
localEnv ps (Environment t v) = Environment t (append (walkPatterns localEnv_f ps) v)
localEnv_f v (PVar name) = [P name v]
localEnv_f _ (PCon _ _)  = []
declareFunctions_f [] = ""
declareFunctions_f xs = concat ["static Function ", intercalate ", " xs, ";\n"]
declareConstructors = declareFunctions_f . map ((append "f_") . constructorName) . concat
declareFunctions = declareFunctions_f . map ((append "f_") . functionName)
boxConstructors = concatMap boxConstructors_f . concat
boxConstructors_f (Constructor name n) = boxThing name n
boxFunctions = concatMap boxFunctions_f
boxFunctions_f (Function name n _) = boxThing name n
boxThing name n | n == 0 = concat ["static Box b_", name, " = {0, f_", name, ", NULL};\n"]
boxThing name n = concat ["static Partial p_", name, " = {", showInt n, ", 0, f_", name, "};\n", "static Box b_", name, " = {1, NULL, &p_", name, "};\n"]
compileConstructors = concatMap (concat . zipWith compileConstructors_f (countFrom 0))
compileConstructors_f tag (Constructor name n) = concat ["static void *f_", name, "(Box **args)\n", "{\n", allocate n, "\tv->tag = ", showInt tag, ";\n", concatMap initialize (range 0 (sub n 1)), "\treturn v;\n", "}\n"]
allocate n | n == 0 = "\tValue *v = malloc(sizeof(Value));\n\t(void) args;\n"
allocate n = concat ["\tValue *v = malloc(sizeof(Value) + ", showInt n, " * sizeof(Box*));\n"]
initialize i = concat ["\tv->items[", showInt i, "] = args[", showInt i, "];\n"]
compileFunctions env = concatMap (compileFunction env)
compileFunction env (Function name argc equations) =  concat ["static void *f_", name, "(Box **args)\n", "{\n", concatMap (compileEquation env) equations, "\tNO_MATCH(", name, ");\n", "}\n"]
compileEquation genv (Equation _ patterns guard expr) = compileEquation_a (localEnv patterns genv) patterns guard expr
compileEquation_a env patterns guard expr = compileEquation_b (concat ["\treturn ", compileExpressionStrict env expr, ";\n"]) (append (compilePatterns env patterns) (compileGuard env guard))
compileEquation_b returnExpr preds = condList returnExpr (compileEquation_f returnExpr) preds
compileEquation_f returnExpr xs = concat ["\tif (", intercalate " && " xs, ")\n\t", returnExpr]
compilePatterns env = walkPatterns (compilePatterns_f env)
compilePatterns_f _ _ (PVar name) = []
compilePatterns_f env v (PCon name ps) = compilePatterns_h v name (lookupCon name env)
compilePatterns_h v name (Just n) = [concat ["match(", compileVarInfo v, ",", showInt n, ")"]]
compilePatterns_h v name Nothing  = error (append "Not in scope: data constructor " name)
compileGuard env Nothing     = []
compileGuard env (Just expr) = [concat ["isTrue(", compileExpressionStrict env expr, ")"]]
compileExpressionStrict env (Var name) = concat ["force(", compileVar (lookupVar name env) name, ")"]
compileExpressionStrict _   (Con name) = concat ["force(&b_", name, ")"]
compileExpressionStrict _   (Int s)    = concat ["mkInt(", s, ")"]
compileExpressionStrict _   (Char s)   = concat ["mkInt(", s, ")"]
compileExpressionStrict _   (String s) = concat ["mkString(", s, ")"]
compileExpressionStrict env (Ap f x)   = concat ["apply(", compileExpressionStrict env f, ",", compileExpressionLazy env x, ")"]
compileExpressionLazy env (Var name) = compileVar (lookupVar name env) name
compileExpressionLazy _   (Con name) = concat ["&b_", name, ""]
compileExpressionLazy _   (Int s)    = concat ["box(mkInt(", s, "))"]
compileExpressionLazy _   (Char s)   = concat ["box(mkInt(", s, "))"]
compileExpressionLazy _   (String s) = concat ["box(mkString(", s, "))"]
compileExpressionLazy env (Ap f x)   = concat ["deferApply(", compileExpressionLazy env f, ",", compileExpressionLazy env x, ")"]
compileVar (Just v) _    = compileVarInfo v
compileVar Nothing  name = error (append "Not in scope: " name)
compileVarInfo (VBox name) = append "&b_" name
compileVarInfo (VArg n)    = concat ["args[", showInt n, "]"]
compileVarInfo (VItem v n) = concat ["item(", compileVarInfo v, ",", showInt n, ")"]
header="#include <assert.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\ntypedef struct Box Box;\ntypedef struct Value Value;\ntypedef struct Partial Partial;\ntypedef void *Function(Box**);\nstruct Box{int state;Function *func;void*vc;Box*fx[];};\nstruct Value{int tag;Box *items[];};\nstruct Partial{int remaining;int applied;Function *func;Box *args[];};\n#define copy(...)memdup(&(__VA_ARGS__), sizeof(__VA_ARGS__))\n#define countof(...)(sizeof(__VA_ARGS__) / sizeof(*(__VA_ARGS__)))\n#define match(box, expectedTag)(((Value*)force(box))->tag == (expectedTag))\n#define item(box, n)(((Value*)(box)->vc)->items[n])\n#define isTrue(value)(!!*(int*)(value))\n#define NO_MATCH(func)fatal(\"Non-exhaustive patterns in function \" #func)\nstatic void fatal(const char *str){fprintf(stderr,\"*** Exception: %s\\n\", str);exit(EXIT_FAILURE);}\nstatic void *memdup(void *ptr, size_t size){void*ret=malloc(size);memcpy(ret,ptr,size);return ret;}\nstatic void *force(Box *box){switch(box->state){\ncase 0:box->state=2;box->vc=box->func(box->vc);box->state=1;\ncase 1:return box->vc;\ndefault:fatal(\"infinite loop\");}}\nstatic void *apply(Partial*f,Box*x){Partial*f2=malloc(sizeof(Partial)+(f->applied+1)*sizeof(Box*));\nmemcpy(f2->args,f->args,f->applied*sizeof(Box*));f2->args[f->applied]=x;\nif(f->remaining>1){f2->remaining=f->remaining-1;f2->applied=f->applied+1;f2->func=f->func;return f2;\n}else return f->func(f2->args);}\nstatic void*deferApply_cb(Box**a){return apply(force(a[0]),a[1]);}\nstatic Box*deferApply(Box*f,Box*x){\nBox*ret=malloc(sizeof(Box)+2*sizeof(Box*));\nret->state=0;\nret->func=deferApply_cb;\nret->vc=ret->fx;\nret->fx[0]=f;\nret->fx[1]=x;\nreturn ret;}\n\nstatic Box*defer(Function*func,void*ctx){\nBox*ret=malloc(sizeof(Box));\nret->state=0;\nret->func=func;\nret->vc=ctx;\nreturn ret;}\n\nstatic Box *box(void *value)\n{\n\tBox *ret = malloc(sizeof(Box));\n\tret->state = 1;\n\tret->func = NULL;\n\tret->vc = value;\n\treturn ret;\n}\n\nstatic int *mkInt(int n)\n{\n\tint *ret = malloc(sizeof(*ret));\n\t*ret = n;\n\treturn ret;\n}\n\nstatic Function f_Nil, f_Cons, f_P;\nstatic Box b_Nil, b_Cons, b_P, b_main;\n\n#define FUNCTION(name, argc) \\\n\tstatic Function f_##name; \\\n\tstatic Partial p_##name = {argc, 0, f_##name}; \\\n\tstatic Box b_##name = {1, NULL, &p_##name}; \\\n\tstatic void *f_##name(Box **args)\n\n#define intop(name, expr) \\\n\tFUNCTION(name, 2) \\\n\t{ \\\n\t\tint a = *(int*)force(args[0]); \\\n\t\tint b = *(int*)force(args[1]); \\\n\t\treturn mkInt(expr); \\\n\t}\n\n#define intop1(name, expr) \\\n\tFUNCTION(name, 1) \\\n\t{ \\\n\t\tint a = *(int*)force(args[0]); \\\n\t\treturn mkInt(expr); \\\n\t}\n\nintop(add,  a + b)\nintop(sub,  a - b)\n\nintop(_lt,  a <  b)\nintop(_le,  a <= b)\nintop(_eq,  a == b)\nintop(_ge,  a >= b)\nintop(_gt,  a >  b)\nintop(_ne,  a != b)\nintop(_and, a && b)\nintop(_or,  a || b)\n\nintop1(negate, -a)\nintop1(not,    !a)\n\nFUNCTION(divMod, 2)\n{\n\tint n = *(int*)force(args[0]);\n\tint d = *(int*)force(args[1]);\n\tint div = n / d;\n\tint mod = n % d;\n\t\n\tif ((mod < 0 && d > 0) || (mod > 0 && d < 0)) {\n\t\tdiv--;\n\t\tmod += d;\n\t}\n\t\n\tBox *pair[2] = {box(mkInt(div)), box(mkInt(mod))};\n\treturn f_P(pair);\n}\n\nstatic void *mkString(const char *str)\n{\n\tif (*str != '\\0') {\n\t\tBox *cons[2] =\n\t\t\t{box(mkInt(*str)), defer((Function*) mkString, (void*)(str + 1))};\n\t\treturn f_Cons(cons);\n\t} else {\n\t\treturn force(&b_Nil);\n\t}\n}\n\nstatic void putStr(Value *v, FILE *f)\n{\n\tif (v->tag == 1) {\n\t\tint c = *(int*)force(v->items[0]);\n\t\tputc(c, f);\n\t\tputStr(force(v->items[1]), f);\n\t}\n}\n\nFUNCTION(error, 1)\n{\n\tfflush(stdout);\n\tfputs(\"*** Exception: \", stderr);\n\tputStr(force(args[0]), stderr);\n\tputc('\\n', stderr);\n\texit(EXIT_FAILURE);\n}\n\nstruct mkStringFromFile\n{\n\tFILE *f;\n\tconst char *name;\n};\n\nstatic void *mkStringFromFile(struct mkStringFromFile *ctx)\n{\n\tint c = fgetc(ctx->f);\n\t\n\tif (c == EOF) {\n\t\tif (ferror(ctx->f))\n\t\t\tperror(ctx->name);\n\t\treturn force(&b_Nil);\n\t}\n\t\n\tBox *cons[2] = {box(mkInt(c)), defer((Function*) mkStringFromFile, ctx)};\n\treturn f_Cons(cons);\n}\n\nint main(void)\n{\n\tstruct mkStringFromFile c_in = {stdin, \"<stdin>\"};\n\tBox *b_in = defer((Function*) mkStringFromFile, copy(c_in));\n\tputStr(apply(force(&b_main), b_in), stdout);\n\treturn 0;\n}\n"
prelude = P 0 "_apply f x=f x;_compose f g x=f(g x);data List a=Nil|Cons a(List a);data P a b=P a b;data B=B;data Maybe a=Nothing|Just a;data Bool=False|True;id x=x;const x _=x;flip f x y=f y x;foldl f z[]=z;foldl f z(x:xs)=foldl f(f z x)xs;foldl1 f(x:xs)=foldl f x xs;foldl1 _[]=error\"foldl1: empty list\";foldr f z[]=z;foldr f z(x:xs)=f x(foldr f z xs);foldr1 f[x]=x;foldr1 f(x:xs)=f x(foldr1 f xs);foldr1 _[]=error\"foldr1: empty list\";map f[]=[];map f(x:xs)=f x:map f xs;filter p[]=[];filter p(x:xs)|p x=x:filter p xs;filter p(x:xs)=filter p xs;zipWith f(x:xs)(y:ys)=f x y:zipWith f xs ys;zipWith f _ _=[];append[]ys=ys;append(x:xs)ys=x:append xs ys;concat=foldr append[];concatMap f=concat.map f;length[]=0;length(_:l)=add 1(length l);take n _|n<=0=[];take _[]=[];take n(x:xs)=x:take(sub n 1)xs;takeWhile p[]=[];takeWhile p(x:xs)|p x=x:takeWhile p xs;takeWhile _ _=[];dropWhile p[]=[];dropWhile p(x:xs)|p x=dropWhile p xs;dropWhile p xs=xs;span p[]=P[][];span p(x:xs)|p x=span_1 x(span p xs);span p xs=P[]xs;span_1 x(P ys zs)=P(x:ys)zs;break p=span(not.p);reverse=foldl(flip(:))[];groupBy _[]=[];groupBy eq(x:xs)=groupBy_1 x eq(span(eq x)xs);groupBy_1 x eq(P ys zs)=(x:ys):groupBy eq zs;maybe n f Nothing=n;maybe n f(Just x)=f x;all p=foldr(&&)True.map p;intersperse _[]=[];intersperse _[x]=[x];intersperse sep(x:xs)=x:sep:intersperse sep xs;intercalate xs xss=concat(intersperse xs xss);isDigit c=c>='0'&&c<='9';isAlphaNum c=c>='0'&&c<='9'||c>='A'&&c<='Z'||c>='a'&&c<='z';isUpper c=c>='A'&&c<='Z';isLower c=c>='a'&&c<='z';showInt n|n<0='-':showInt(negate n);showInt n|n==0=\"0\";showInt n|n>0=reverse(map(add 48)(showInt_1 n));showInt_1 n|n==0=[];showInt_1 n=showInt_2(divMod n 10);showInt_2(P div mod)=mod:showInt_1 div;lines []=[];lines s=lines_1(break((==)'\\n')s);lines_1(P l[])=[l];lines_1(P l(_:s))=l:lines s;interact=id"

16

カスタム言語→C-(7979)

質問は自分の言語を作成することを妨げるものではないので、私はそれを試してみたいと思いました。

環境

この言語は、コールスタックとデータスタックの2つのスタックにアクセスできます。コールスタックは、ジャンプ命令のために使用されている{}データスタックは他のほとんどの命令で使用されます。呼び出しスタックは、アプリケーションに対して不透明です。

データスタックは、整数、テキスト、空の3種類の値を保持できます。整数はintptr_t型で、テキストはCスタイルの文字列として保存されます。

^命令は、Arrayへのアクセス権を持っています。配列は、長さ17のテキスト項目の定数配列です。インデックス作成スキームのソースは、少し不安定なので、おそらく表示されるはずです。

言語

#   -   Begin number    - Marks the beginning of a number, for example: #42.
.   -   End number      - Marks the end of a number and pushes it to the data stack.
^   -   Translate       - Pops a number, and pushes the corresponding text from The Array.
<   -   Write           - Pops a value, and prints it to stdout.
>   -   Read            - Reads a character from stdin and pushes it as a number. If EOF,
                          exit.
{   -   Start Loop      - Pushes the current location in the program to the call stack.
}   -   End Loop        - Go to the position specified by the top of the call stack.
+   -   Add             - Pop two numbers from the data stack, add them, push the result.
-   -   Subtract        - Pop into A, pop into B, push B - A. Both B & A must be numbers.
!   -   Duplicate       - Pop from The Data Stack, push that value twice.
_   -   Discard         - Pop from The Data Stack.
=   -   Skip if Equal   - Pop two values, if they are equal skip the next instruction
                          and pop one item from the call stack.
?   -   Loop            - Pop one number, subtract one, if it's less than one, pop one
                          item from the call stack and skip the next instruction.
@   -   Array Separator - Marks the end of an array item.
$   -   Program End     - Marks the end of the program.

コンパイラ

これはコンパイラです。それはゴルフではなく、かなり削減できると期待しています。マシンコードを直接使用してdos COMファイルを出力することは可能ですが、まだそのことに触れていません。これはCプログラムのように見えますが、実際のコンパイラの実装は最後にダウンしています。

現在、コンパイラはstderrで多くのデバッグ情報を生成します。

#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <setjmp.h>
#include <stdbool.h>

const char* position;
const char* array[] = {"@"};

void die(const char* reason)
{
    fprintf(stderr, "%s\n", reason);
    exit(1);
}

//
// Stack Functions
//

#define T_EMPTY     (0)
#define T_NUMBER    (1)
#define T_TEXT      (2)

typedef struct {
    unsigned char type;
    union {
        const char* text;
        intptr_t number;
    };
} stack_entry;

#define STACK_MAX   (1024)
stack_entry stack[STACK_MAX];
size_t stack_position = 0;

stack_entry* _push()
{
    if (stack_position >= STACK_MAX) {
        die("out of stack space");
    }
    return &stack[stack_position++];
}

void push(stack_entry v)
{
    if (v.type == T_EMPTY) {
        fprintf(stderr, "\tpushed: None\n");
    } else if (v.type == T_TEXT) {
        fprintf(stderr, "\tpushed: %s\n", v.text);
    } else {
        fprintf(stderr, "\tpushed: %d\n", v.number);
    }
    stack_entry* entry = _push();
    *entry = v;
}

void push_empty()
{
    fprintf(stderr, "\tpushed: None\n");
    stack_entry* entry = _push();
    entry->type = T_EMPTY;
    entry->number = 0;
}

void push_number(intptr_t number)
{
    fprintf(stderr, "\tpushed: %d\n", number);
    stack_entry* entry = _push();
    entry->type = T_NUMBER;
    entry->number = number;
}

void push_text(const char* text)
{
    fprintf(stderr, "\tpushed: %s\n", text);
    stack_entry* entry = _push();
    entry->type = T_TEXT;
    entry->text = text;
}

// Polymorphic Push (for literals)
#define PUSH0()     do { fprintf(stderr, "literal:\n"); push_empty(); } while (0)
#define PUSH1(a)    do { fprintf(stderr, "literal:\n"); push_number(a); } while (0)

#define GET_MACRO(_0, _1, NAME, ...) NAME
#define PUSH(...) GET_MACRO(_0, ##__VA_ARGS__, PUSH1, PUSH0)(__VA_ARGS__)

stack_entry pop()
{
    if (stack_position <= 0) {
        fprintf(stderr, "\tpopped: None\n");
        return (stack_entry) {.type = T_EMPTY, .number = 0};
    }

    stack_entry v = stack[--stack_position];
    if (v.type == T_EMPTY) {
        fprintf(stderr, "\tpopped: None\n");
    } else if (v.type == T_TEXT) {
        fprintf(stderr, "\tpopped: %s\n", v.text);
    } else {
        fprintf(stderr, "\tpopped: %d\n", v.number);
    }
    return v;
}

stack_entry peek()
{
    if (stack_position <= 0) {
        return (stack_entry) {.type = T_EMPTY, .number = 0};
    }

    return stack[stack_position-1];
}

//
// Jump Functions
//

#define JUMP_MAX    (1024)
jmp_buf jump[JUMP_MAX];
size_t jump_position = 0;

#define start()                                     \
    do {                                            \
    if (jump_position >= JUMP_MAX) {                \
        die("out of jump space");                   \
    }                                               \
    fprintf(stderr, "start: %d\n", jump_position);  \
    setjmp(jump[jump_position++]);                  \
    } while (0)

void pop_jump() {
    if (jump_position <= 0) {
        die("empty jump stack");
    }
    jump_position -= 1;
}

#define end()                                       \
    do {                                            \
    if (jump_position <= 0) {                       \
        die("empty jump stack");                    \
    }                                               \
    fprintf(stderr, "end: %d\n", jump_position-1);  \
    longjmp(jump[jump_position-1],1);               \
    } while (0)

//
// Program functions
//

void translate()
{
    fprintf(stderr, "translate:\n");
    stack_entry entry = pop();
    if (entry.type == T_TEXT) {
        die("translating text");
    } else if (entry.type == T_EMPTY) {
        push_empty();
    } else {
        switch (entry.number) {
            case 0:
            case 1:
                push_text(array[entry.number]);
                break;
            case 64:
                push_text(array[2]);
                break;
            case 94:
                push_text(array[3]);
                break;
            case 45:
                push_text(array[4]);
                break;
            case 43:
                push_text(array[5]);
                break;
            case 62:
                push_text(array[6]);
                break;
            case 60:
                push_text(array[7]);
                break;
            case 33:
                push_text(array[8]);
                break;
            case 95:
                push_text(array[9]);
                break;
            case 61:
                push_text(array[10]);
                break;
            case 63:
                push_text(array[11]);
                break;
            case 123:
                push_text(array[12]);
                break;
            case 125:
                push_text(array[13]);
                break;
            case 35:
                push_text(array[14]);
                break;
            case 46:
                push_text(array[15]);
                break;
            case 36:
                push_text(array[16]);
                break;
            default:
                push_empty();
                break;
        }
    }
}

void subtract()
{
    fprintf(stderr, "subtract:\n");
    stack_entry v1 = pop();
    stack_entry v2 = pop();

    if (v1.type != T_NUMBER || v2.type != T_NUMBER) {
        die("not a number");
    }

    push_number(v2.number - v1.number);
}

void add()
{
    fprintf(stderr, "add:\n");
    stack_entry v1 = pop();
    stack_entry v2 = pop();

    if (v1.type != T_NUMBER || v2.type != T_NUMBER) {
        die("not a number");
    }

    push_number(v2.number + v1.number);
}

void read()
{
    fprintf(stderr, "read:\n");
    int in = getchar();

    if (in >= 0) {
        push_number(in);
    } else {
        die("end of input");
    }
}

void write()
{
    fprintf(stderr, "write:\n");
    stack_entry v = pop();

    if (v.type == T_NUMBER) {
        putchar(v.number);
    } else if (v.type == T_TEXT) {
        const char* x = v.text;
        char y;
        while (0 != (y=*(x++))) {
            y -= 128;
            putchar(y);
        }
    }
}

void duplicate()
{
    fprintf(stderr, "duplicate:\n");
    stack_entry v = pop();
    push(v);
    push(v);
}

void discard()
{
    fprintf(stderr, "discard:\n");
    pop();
}

bool equals()
{
    fprintf(stderr, "equals:\n");
    stack_entry x = pop();
    stack_entry y = pop();

    bool skip;

    if (x.type != y.type) {
        skip = false;
    } else if (x.type == T_EMPTY) {
        skip = true;
    } else if (x.type == T_NUMBER) {
        skip = x.number == y.number;
    } else {
        skip = strcmp(x.text, y.text) == 0;
    }

    if (skip) {
        pop_jump();
    }

    return !skip;
}

bool question()
{
    fprintf(stderr, "question:\n");
    stack_entry x = pop();

    intptr_t value;

    if (x.type == T_EMPTY) {
        value = 0;
    } else if (x.type == T_NUMBER) {
        value = x.number;
    } else {
        die("it is bad form to question text");
    }

    value -= 1;

    if (value < 1) {
        pop_jump();
        return false;
    } else {
        push_number(value);
        return true;
    }
}

int main()
{
@","@translate();@subtract();@add();@read();@write();@duplicate();@discard();@if(equals())@if(question())@start();@end();@PUSH(@);@return 0;}@

#0.^<                           Emit the preface

#17.{                           Loop for as many array slots exist
    #.{<>#128.+!#192.=}         Copy characters, adding 128 until reaching an at sign
    #128.-
    ^<                          Emit the code between array items
?}                              Return to start

#1.^<                           Emit the prologue


{{
>!^<                            Read character, translate it, and print it
!#35.=}                         Check if we have a literal
#.{<>!#46.=}^<                  If so, verbatim copy characters until a period
}                               Continue executing
$

生成されたCコードをコンパイルするには:

gcc -finput-charset=CP437 -fexec-charset=CP437 -std=gnu11

コンパイラは128を追加して特殊文字をエスケープするため、文字セットが必要です。

ブートストラップ

最初のコンパイラーをコンパイルするために、言語用のPythonインタープリターを作成しました。

import sys
from collections import defaultdict
KEYS = [0,1] + map(ord, ['@','^','-','+','>','<','!','_','=','?','{','}','#','.','$'])

# Read the source file
with file(sys.argv[1]) as f:
    data = f.read()
pos = 0

# Initialize the environment
array = defaultdict(str)
jmp = []
stk = []

def log(x):
    sys.stderr.write(x + '\n')

def read():
    global pos,data
    pos += 1
    return data[pos-1]

def pop():
    global stk
    try:
        x = stk.pop()
    except IndexError:
        x = None
    log('\tpopped ' + repr(x))
    return x

def push(value):
    global stk
    log('\tpushing ' + repr(value))
    stk.append(value)

# Read the array initialization section
for key in KEYS:
    while True:
        c = read()
        if c == '@':
            break
        array[key] += c

# Execute the program
while pos < len(data):
    c = read()
    if c == '^':
        log('translate:')
        push(array.get(pop(), None))
    elif c == '-':
        log('subtract:')
        x = pop()
        y = pop()
        push(y - x)
    elif c == '+':
        log('add:')
        x = pop()
        y = pop()
        push(y + x)
    elif c == '>':
        log('read:')
        push(ord(sys.stdin.read(1)))
    elif c == '<':
        log('write:')
        v = pop()
        if isinstance(v, int):
            sys.stdout.write(chr(v))
        elif v is not None:
            sys.stdout.write(v)
    elif c == '!':
        log('duplicate:')
        x = pop()
        push(x)
        push(x)
    elif c == '_':
        log('discard:')
        pop()
    elif c == '=':
        log('skip if equal:')
        x,y = pop(),pop()
        if x == y:
            pos += 1
            jmp.pop()
    elif c == '?':
        log('loop:')
        x = pop()
        x -= 1
        if x < 1:
            pos += 1
            jmp.pop()
        else:
            push(x)
    elif c == '{':
        log('start: ' + repr(pos))
        jmp.append(pos)
    elif c == '}':
        log('end:')
        pos = jmp[-1]
    elif c == '#':
        literal = ''
        while True:
            c = read()
            if c == '.':
                log('literal: ' + repr(literal))
                if literal == '':
                    push(None)
                else:
                    push(int(literal))
                break
            else:
                literal += c

すべてを一緒に入れて

コンパイラをas compiler.cmp、ブートストラップをas として保存した場合、コンパイラbootstrap.pyをビルドし、それを使用して自分自身をコンパイルする方法は次のとおりです。

$ cat compiler.cmp |
  python bootstrap.py compiler.cmp 2> trace-bootstrap |
  gcc -finput-charset=CP437 -fexec-charset=CP437 -std=gnu11 -o result -xc -
$ cat compiler.cmp | ./result 2> trace-final

したがって、私はCプログラマーではなく、言語デザイナーでもないため、これを改善するための提案は大歓迎です!

サンプルプログラム

こんにちは世界!

Hello, World!@@@@@@@@@@@@@@@@@#0.^<$

1
これは印象的ですが、ヘルプセンターで定義されているコードゴルフ規則に違反しています
イスジ14

1
修正、ルールはここのcode-golfタグwiki およびMetaにあります。
イスジ14

7
@Iszi私は以前にそのページに出くわしたことはありませんでしたし、あなたは完全に正しいです...しかし、量刑を検討する前に、いくつかの緩和事実を提供したいと思います:この言語は一般的な目的であり、「1つの文字を提供しませんソリューション」、そして、言語の実装をソリューションに含めた場合、それ自体が実装されているため、私のスコアは変わりません(確かに、ソリューションがCをコンパイルすると主張できなかったため、元の問題は解決しませんでした) 。)
tecywiz121

あなたの言語は何と呼ばれていますか?
ベータ崩壊14


14

拡張Brainfuck v0.9:618バイト(必要な改行をカウントしない)

:c:n:z:g:i:t:w:a:p++++++++[->++++++++<]>[->>>>>>>[>>>>>>>>]+[<<<<<<<<]>]>>>>>>>[->>>>>>>>]@i
$i,[[-$t+$w+$i]$t[-$i+$t]+$a+++[-$w-----------$a]$w---[$a++[-$w-----------$a]$w[--[--[--[$i.
$t+++++++[-$w++++++++$t]$w[-]]$t[-$p[-]$i.$n,.[-<[<<]+[>>]<]@n$c[<<]>[-<<<+>>>>[>>]@z$p+$c[<
<]>]<<<[->>>+<<<]>>>>[->>]@z$t]$w]$t[-$i.$p+$t]$w]$t[-$i.$p-$t]$w]$t[$i.$n,.[-<[<<]+[>>]<]@n
$g[-$t+$c[<<]>+>[>>]@z>]$c[<<]>>[->>]@z$t[-$g+$t]$t]$w]$t[-$i.[-]$n,.[-<[<<]+[>>]<]@n$c[<<]>
[-<<<+>>>>[>>]@z$i+$a+$c[<<]>]<<<[->>>+<<<]>>>>[->>]@z<++++++[->++++++++++<]$w+$p[$a[-$w-]<[
@w-$p[-$z.$p]+$t]$w+$p-]$z++$w-$a[-$z.$a]$z[-]$i[-$p+$i]$t]$w$i,]

これは私の最初のバージョンのEBFのゴルフ版で、変数の削除をサポートするコメントとデッドコードのサポートが削除されています。

基本的に、変数を使用するBrainFuckです。:x変数xを作成します。コンパイラはあなたがどこにいるかを知っているので$y、その位置に到達するために<と>を生成します。非対称ループが必要な場合があり、コンパイラーにどこにいるのかを伝える必要があります@x。現在のEBFとして、Brainfuckにコンパイルされます。

この最初のバージョンにはchar変数名が1つしかありませんでしたが、このバージョンを使用して次のバージョンをコンパイルし、現在のバージョンが印象的な機能セットを持つようになるまで続けました。githubソースからコンパイルするとき、実際にハンドコンパイルされたバイナリをダウンロードして、現在のバージョンを作成するために6つの中間ebfバージョンをブートストラップします。

それをブートストラップするには、EBF gitリポジトリ内のこの最初の唯一のバイナリを使用できます。

wget -nv https://raw.githubusercontent.com/westerp/ebf-compiler/34c378c8347aafa5dbf37f4973461d42c8120ea4/ebf-handcompiled.bf
beef ebf-handcompiled.bf < ebf09.ebf > ebf09a.bf
beef ebf09a.bf < ebf09.ebf > ebf09b.bf
diff -s ebf09a.bf ebf09b.bf # Files ebf09a.bf and ebf09b.bf are identical

Brainfuckにはいくつかのハードウェア実装があります。これこれこれにいくつか言及します。しかし、ほとんどの場合、実装が非常に簡単なので、どのシステムにもインタープリターを実際に実装できます。私は、EBFで書かれたZozotez LISPがおそらく最もポータブルなLISPであると冗談を言っています。


8

16進数、550バイト

これは、特にLinuxを実行しているx86_64システムを対象としています。

7f454c4602010100000000000000000002003e0001000000780040000000000040000000000000000000000000000000000000004000380001004000000000000100000005000000000000000000000000004000000000000000400000000000130100000000000013010000000000000000200000000000e81700000085c07c0b31ff01c7e879000000ebec31c089c7b03c0f05e84c0000004885c07c203c2178f2741b89c7e825000000c0e00450e83100000089c7e8150000005900c8c3e8210000003c0d7ff774ca3c0a75f1ebc489f831c93c400f9cc148ffc980e12780c13028c8c36a004889e631c089c2fec289c70f0531c985c0580f95c148ffc94809c8c3574889e631c0fec089c289c70f0558c3

この言語では、ソースコードは2つの小文字の16進数で表されるバイトで構成されます[0-9a-f][0-9a-f]。これらのバイトには周囲の空白がいくらあってもかまいませんが、1バイトを形成する数字の間に何も起こらない場合があります。さらに、'!'は行コメント文字です。これは無視され、その'\n'文字と次の文字の間のすべても無視されます。

x86アセンブリを理解している場合、ソースコードのはるかに読みやすいバージョンを以下に示します。

! ELF Header !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7f 45 4c 46                !e_ident[EI_MAG0] (0x7F "ELF")
02                         !e_ident[EI_CLASS] (64-bit)
01                         !e_ident[EI_DATA] (little-endian)
01                         !e_ident[EI_VERSION] (ELF v1)
00                         !e_ident[EI_OSABI] (System V ABI)
00                         !e_ident[EI_ABIVERSION] (version 0)
00 00 00 00 00 00 00       !e_ident [EI_PAD]
02 00                      !e_type (executable)
3e 00                      !e_machine (x86_64)
01 00 00 00                !e_version (ELF v1)
78 00 40 00 00 00 00 00    !e_entry (0x40078)
40 00 00 00 00 00 00 00    !e_phoff (0x   40)
00 00 00 00 00 00 00 00    !e_shoff (0x    0)
00 00 00 00                !e_flags
40 00                      !e_ehsize (ELF header size = 64 bytes)
38 00                      !e_phentsize (Program headers = 56 bytes)
01 00                      !e_phnum (1 program header)
40 00                      !e_shentsize (Section headers = 64 bytes)
00 00                      !e_shnum (no section headers)
00 00                      !e_shstrndx (section names, not useful here)

! Program Headers !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
01 00 00 00                !p_type (LOAD)
05 00 00 00                !p_flags (R+E)
00 00 00 00 00 00 00 00    !p_offset (file-loc 0)
00 00 40 00 00 00 00 00    !p_vaddr (vmem-loc 0x40000)
00 00 40 00 00 00 00 00    !p_paddr (pmem-loc 0x40000)
13 01 00 00 00 00 00 00    !p_filesz (length 0x113 bytes)
13 01 00 00 00 00 00 00    !p_memsz (allocate 0x113 bytes)
00 00 20 00 00 00 00 00    !p_align (align pages in 0x20000 increments)


! Program Code !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! _start: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      e8 17 00 00 00 ! callq _gethx
               85 c0 ! test %eax,%eax
               7c 0b ! jl .+11
               31 ff ! xor %edi,%edi
               01 c7 ! add %eax,%eax
      e8 79 00 00 00 ! callq _putch
               eb ec ! jmp .-20
               31 c0 ! xor %eax,%eax
               89 c7 ! mov %eax,%edi
               b0 3c ! mov $0x3c,%al
               0f 05 ! syscall

!! _gethx: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      e8 4c 00 00 00 ! callq _getch
            48 85 c0 ! test %rax,%rax
               7c 20 ! jl _gethx+42
               3c 21 ! cmp $0x21,al
               78 f2 ! js _gethx
               74 1b ! je _gethx+43
               89 c7 ! mov %eax,%edi
      e8 25 00 00 00 ! callq _h2d
            c0 e0 04 ! sal $4,%al
                  50 ! push %rax
      e8 31 00 00 00 ! callq _getch
               89 c7 ! mov %eax,%edi
      e8 15 00 00 00 ! callq _h2d
                  59 ! pop %rcx
               00 c8 ! add %cl,%al
                  c3 ! retq
      e8 21 00 00 00 ! callq _getch
               3c 0d ! cmp $0xd,%al
               7f f7 ! jg _gethx+43
               74 ca ! je _gethx
               3c 0a ! cmp $0xa,%al
               75 f1 ! jne _gethx+43
               eb c4 ! jmp _gethx

!! _h2d: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
               89 f8 ! mov %edi,%eax
               31 c9 ! xor %ecx,%ecx
               3c 40 ! cmp $0x40,%al
            0f 9c c1 ! setl %cl
            48 ff c9 ! dec %rcx
            80 e1 27 ! and $0x27,%cl
            80 c1 30 ! add $0x30,%cl
               28 c8 ! sub %cl,%al
                  c3 ! retq

!! _getch: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
               6a 00 ! push $0
            48 89 e6 ! mov %rsp,%rsi
               31 c0 ! xor %eax,%eax
               89 c2 ! mov %eax,%edx
               fe c2 ! inc %dl
               89 c7 ! mov %eax,%edi
               0f 05 ! syscall
               31 c9 ! xor %ecx,%ecx
               85 c0 ! test %eax,%eax
                  58 ! pop %rax
            0f 95 c1 ! setne %cl
            48 ff c9 ! dec %rcx
            48 09 c8 ! or %rcx,%rax
                  c3 ! retq

!! _putch: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                  57 ! push %rdi
            48 89 e6 ! mov %rsp,%rsi
               31 c0 ! xor %eax,%eax
               fe c0 ! inc %al
               89 c2 ! mov %eax,%edx
               89 c7 ! mov %eax,%edi
               0f 05 ! syscall
                  58 ! pop %rax
                  c3 ! retq

以下のコメントからアセンブリ言語を抽出する! Program Codeと、Hexコンパイラをアセンブルして実行できます。入力と出力は、stdinとstdoutを使用します。


Hex言語ではありません。
TuxCrafting

@TùxCräftîñgそれは正確には真実ではありません。ウィキペディアのページはありませんが、この質問を知っている前に、この実装でこの形式で存在していました(当時は無名でした)。私のsvnから:lutras-hacking.ddns.net/websvn/listing.php?repname=sasm アイデアは、何もないところからアセンブラーを構築することでしたが、そこまで到達することはできませんでした。
フォックス

ああ、ごめんなさい> _> ...
TuxCrafting

あまり知られていない
エソラン

@TuxCopter私は、「アセンブリのx86 Linuxは、」言語の名前であることを、仮定
ЕвгенийНовиков

3

Javascriptサブセット-> Java、504バイト

document.write("public class Generated{public static void main(String[]args){"+prompt().replace(RegExp("[r]eplace(,"g"),"replaceAll(").replace(RegExp("[v]ar","g"),"double")+"}static class document{static void write(String s){System.out.print(s);}}static void prompt(){return javax.swing.JOptionPane.showInputDialog(\"\");}static void alert(String a){JOptionPane.showMessageDialog(null,a);}static double Number(String a){return Double.parseDouble(a);}static String RegExp(String a,String b){return a;}}");


0

木材、0バイト

Lumberは、Prologコードのわずか10行で記述されたUnrelated Stringによって発明された完全な難解なプログラミング言語です。

信じられない?これらのプログラムではコメントが削除され、インタープリターのソースがより簡潔になりました。

lumber_corefuncs.pl:

:- use_module(lumber_types).

lumber_types.pl

:- module(lumber_types,
          []).

lumber_corefuncs.plはライブラリlumber_typesを取り込みます。そして、このライブラリは、何も含まれていないモジュールを定義します。したがって、Lumberは任意の入力に対して何も行いません。これは、自己コンパイラです。



2
@A__ただ、それは技術的に有効な回答だから、(3つのdownvotesと同じ言い訳を使用して、既存の答えはすでにあります場合は特に)、それは怠惰か、むしろ無意味である場合は特に、それは良いものだという意味ではありません
ジョー・キング

また、Perlではなく、Prologです。(また、この10年のいつか、Lumberでこれに対する正当な答えがあるでしょう)
無関係な文字列

-1

なし、0バイト

信じられないほど、チューリング完全ではありませんが、Nil言語は、多くの「適切な」言語よりもはるかに簡潔に、インタープリターを実装するのに十分な表現力を持っています。ここで紹介する例は単純な実装ですが、高度な圧縮技術を使用して、Nil開発者はわずか0行のコードで動作するインタープリターを作成できました。


@ØrjanJohansencodegolf.meta.stackexchange.com/ a
l4m2

2
ああ!現在メタに関連するものを思い出すのは難しすぎます。
Ørjanヨハンセン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.