Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-

What You Want

Name: Anonymous 2013-06-07 20:15

What you want, but have never been able to put into words, is a "two-phase" C compiler.  You want compile-time C code that outputs run-time C code.

Example: Factorial function.

Naive C approach:


int factorial(int n)
{
    int i, x = 1;
    for (i = 2; i <= n; ++i) x *= i;
    return x;
}


Realization - This code is inefficient and pointless.  On 32-bit systems, passing anything larger than 12 into this function will fail.  Even with 64-bit integers, the largest acceptable value is 20.

Optimized C approach:


int factorial(int n)
{
    int f[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600 };
    return f[n];
}


Problem - The optimized function is less readable.  Calculating a factorial is a repetitive process by its nature, and we have obfuscated that for the sake of efficiency.  Further, we had to spend our precious time calculating the results for every possible input.  This would be unacceptable for most functions.

Solution - The "Two-Phase C" approach:


out <<END_TEXT
int factorial(int n)
{
    int f[] =
    {
        1
END_TEXT

int i, j = 1;
for (i = 1; i <= 12; i++)
{
    out ",";
    j *= i;
    out j;
}

out <<END_TEXT
    };
    return f[n];
}
END_TEXT


Obviously, the output of this "first-phase C" code is the "optimized C approach," shown above.  It is now explicit to the maintainer of the code how the factorial is being calculated, even though no factorial calculation needs to be performed at run-time.  Congratulations.

Name: Anonymous 2013-06-07 20:19

I'm not sure if I understand.

Name: Anonymous 2013-06-07 20:23

I don't see what this has to do with Jews.

Name: Anonymous 2013-06-07 20:27

Phase 1: Naive JavaScript

Phase 2: V8 OptiJITed Sepples

Name: Anonymous 2013-06-07 20:44

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "libtcc.h"

int main(int argc, char *argv[]) {
    TCCState *s;
    int (*func)(int);
    char code[256], tmp[32];
    int i, j;
    sprintf(code, "int factorial(int n) {\n\tint f[] = { 1");
    for(i = 1, j = 1; i <= 12; i++) {
        j *= i;
        sprintf(tmp, ", %d", j);
        strcat(code, tmp);
    }
    strcat(code, "};\n\treturn f[n];\n}\n");
    //printf("code =\n%s\n", code);
    s = tcc_new();
    if(!s) {
        fprintf(stderr, "Could not create tcc state\n");
        exit(1);
    }
    tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
    if(tcc_compile_string(s, code) == -1) {
        return 1;
    }
    if(tcc_relocate(s, TCC_RELOCATE_AUTO) < 0) {
        return 1;
    }
    func = tcc_get_symbol(s, "factorial");
    if(!func) {
        return 1;
    }
    printf("result =\n%d\n", func(8));
    tcc_delete(s);
    return 0;
}


This is more or less example code from TCC.

Name: Anonymous 2013-06-08 0:32

Show me a situation where this works for anything useful and I'll consider it.  As is, this is just an obfuscated way to say ``if you write code that has a tiny number of inputs and which does not depend on run time, you might as well precompute it!''.  Sepples already does this.

In practice, nobody would ever use that factorial function, precisely because it doesn't work for large numbers.  So if you really cared about factorials, you'd be using gmp or something.  Assuming that libraries work with this approach, you can't generate an array for all representable factorials at compile time, and if you did I would hate you, since you would be throwing pointless shit into my .data that I'm probably never going to use.  The answer is to either precompute all possible output value or write a better algorithm in the first place, and I can do either one of those things without being cute and adding layers of abstraction.

Furthermore, your goddamn Two Phase factorial example is idiotic. It's less clear than simply declaring the array to begin with, especially since it's bending over backwards to pretend it's C in the first place, which makes it blend in with the output it's trying to give. Fuck you, if I want to use that approach I'd use Perl or Lisp or some other text-shuffling language that could be easily taught to tokenize and refactor C.

In conclusion, IHBT

Name: Anonymous 2013-06-08 0:34

>>27
hey fuck you asshole

Name: Anonymous 2013-06-08 0:37

Name: Anonymous 2013-06-08 0:41

sagergseghsdthrthsrtdfgsddgasergeaergaeergteasrfasddfgsdfgergwesthshrhrstgskhnrfsdknfghnknknl;knji;ioujhioh;h;lkj;jhiuioliuhsdtgthrfgsdhawqwerty564

Name: Anonymous 2013-06-08 0:52

y8tgik;ubhnnnnnnnnnnnnnnnnnnnllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll

Name: Anonymous 2013-06-08 1:04

LISP

Name: Anonymous 2013-06-08 1:12

>>6
IHBT
Absorutery. It should have been obvious at at least one point:
Problem - The optimized function is less readable.
It's not. As long as the function name is factorial it's obvious what it does.
For me it was at least a little fun fiddling around with TCC but what's your excuse for replying?

Name: Anonymous 2013-06-08 1:17

>>12
A dark, sneaking suspicion that if I didn't reply, it might be taken seriously.

Name: Anonymous 2013-06-08 6:18


(define (products n)
  (let loop ((i 1) (acc 1))
    (if (<= i n)
      (cons acc (loop (+ i 1) (* acc i)))
      '())))

(define fast-factorial
  (let* ((max-factorial 12)
         (factorial-array (apply vector (products (+ 1 max-factorial)))))
    (lambda (n)
      (vector-ref factorial-array n))))

Name: Anonymous 2013-06-08 10:31

))))))))))))))

Name: Anonymous 2013-06-08 10:37

>>15
Please unload your stream of parens on me

Name: Anonymous 2013-06-08 10:38

>>16
*grabs dick*
)))))))))))))))))))

Name: Anonymous 2013-06-08 11:00

>>14
Symta:
products N => let loop I 1 Acc 1:
                if I <or N: [Acc @(loop I+1 Acc*I)]
                else []


Expands into:

("to" (:HEAD ("products" "N"))
 ("let" (:HEAD ("loop" "I" 1 "Acc" 1))
  ("if" (:HEAD ("I" "<or" "N"))
   (("list" "Acc" ("@" ("loop" ("+" "I" 1) ("*" "Acc" "I")))) "else"
    ("list")))))

Name: Anonymous 2013-06-08 13:57

>>15


($ define (products n)
  $ let loop ((i 1) (acc 1))
    $ if (<= i n)
      (cons acc $ loop (+ i 1) $ * acc i)
      $ list)


(define fast-factorial
  $ let* ((max-factorial 12)
         (factorial-array $ apply vector $ products $ + 1 max-factorial))
    $ lambda (n)
      $ vector-ref factorial-array n)

Name: Anonymous 2013-06-08 14:21

>>19
this looks even uglier than >>14 doesn't it.

Name: L. A. Calculus !!wKyoNUUHDOmjW7I 2013-06-08 18:03

>>1
YAINT RED DA FUCKIN STANDARD, HAVE YA?

Name: Anonymous 2013-06-08 19:12

>>6
Show me a situation where this works for anything useful and I'll consider it.
Whatever approach/language it is that you use, if you don't understand the need to perform calculations at compile-time, then you're in the wrong...  oh, no, wait, you're in exactly the right place.  Carry on.

Name: Anonymous 2013-06-08 19:54

>>22
LLLLLLLLLEEEEEEEEEEEEEEEeLLLLLLLLLLLLLLLLLLLLLLLLLLLLL

Name: Anonymous 2013-08-31 7:08


Would you guys recommend the old Kamen Rider shows (i.e., unhandsome Riders, I suppose), or old Super Sentai series? I thought about just watching some of the newer ones, but then I figured I might as well also watch something a little older.

Name: Anonymous 2013-08-31 7:52


 That's right; I'm BREAKING the NYPA trend and i'll be your PA! Of course, i'd appreciate others to participate in the thread as well.

Name: Anonymous 2013-08-31 8:38




    You can refactor in Haskell a lot. The types ensure your large scale changes will be safe, if you're using types wisely. This will help your codebase scale. Make sure that your refactorings will cause type errors until complete.

Name: Anonymous 2013-08-31 9:23



ちなみに

誤:海鮮問屋
正:廻船問屋

Don't change these.
Name: Email:
Entire Thread Thread List