// File: /workspace/github_c_makefile_star2_O1/creationix[P]color-control/src/compile.c
// Function: main
int main() {

  mpc_parser_t *State  = mpc_new("statement");
  mpc_parser_t *Ident  = mpc_new("ident");
  mpc_parser_t *Number  = mpc_new("number");
  mpc_parser_t *Hex  = mpc_new("hex");
  mpc_parser_t *Dec  = mpc_new("decimal");
  mpc_parser_t *Bool  = mpc_new("boolean");
  mpc_parser_t *For  = mpc_new("for");
  mpc_parser_t *Range  = mpc_new("range");
  mpc_parser_t *By  = mpc_new("by");
  mpc_parser_t *If  = mpc_new("if");
  mpc_parser_t *Assign  = mpc_new("assign");
  mpc_parser_t *Expr  = mpc_new("expression");
  mpc_parser_t *Call  = mpc_new("call");
  mpc_parser_t *Not  = mpc_new("not");
  mpc_parser_t *Or  = mpc_new("or");
  mpc_parser_t *And  = mpc_new("and");
  mpc_parser_t *Equal  = mpc_new("equality");
  mpc_parser_t *Comp  = mpc_new("comparison");
  mpc_parser_t *Sum  = mpc_new("sum");
  mpc_parser_t *Prod  = mpc_new("product");
  mpc_parser_t *Value = mpc_new("value");
  mpc_parser_t *Block = mpc_new("block");
  mpc_parser_t *Prog = mpc_new("program");

  mpc_err_t* err = mpca_lang(MPCA_LANG_DEFAULT,
    "statement: <for> | <if> | <assign> | <expression>;"
    "for : \"for\" <ident> \"in\" <number> <range>? <by>? <block>;"
    "range: /\\.\\.\\.?/ <number>;"
    "by: \"by\" <number>;"
    "if : \"if\" <expression> <block>;"
    "assign : <ident> '=' <expression>;"
    "expression: <or>;"
    "ident: /[a-zA-Z_][a-zA-Z_0-9]*/;"
    "number: <boolean> | <hex> | <decimal>;"
    "hex: /0x[0-9a-f]+/;"
    "decimal: /[0-9]+/;"
    "boolean: \"true\" | \"false\";"
    "or : <and> ( \"||\" <and> )*;"
    "and : <equality> ( \"&&\" <equality> )*;"
    "equality : <comparison> ( (\"==\" | \"!=\") <comparison> )*;"
    "comparison : <sum> ( (\"<=\" | \">=\" | '<' | '>') <sum> )*;"
    "sum : <product> ( ('+' | '-') <product> )*;"
    "product : <not> ( ('*' | '/' | '%') <not> )*;"
    "not: '!' <value> | <value>;"
    "call:  <ident> '(' <statement>? (',' <statement>)* ')';"
    "value : <number> | <call> | <ident> | '(' <statement> ')';"
    "block: '{' <statement>* '}';"
    "program : /^/ <statement>* /$/;",
    State, Ident, Number, Hex, Dec, Bool, For, Range, By, If, Assign, Expr, Call, Not, Or, And, Equal, Comp, Sum, Prod, Value, Block, Prog, NULL);

  if (err) {
    mpc_err_print_to(err, stderr);
    return -1;
  }

  uint8_t* input = stdin_read(NULL);

  // replace comments with white space as preprocessor.
  {
    size_t i = 0;
    bool comment = false;
    uint8_t c;
    while ((c = input[i])) {
      if (comment) {
        if (c == '\n') comment = false;
        else input[i] = ' ';
      }
      else {
        if (c == '#') {
          comment = true;
          input[i] = ' ';
        }
      }
      i++;
    }
  }

  // fprintf(stderr, "\n## Source with comments stripped ##\n\n%s\n", input);

  mpc_result_t r;
  if (mpc_parse("input", (char*)input, Prog, &r)) {
    // mpc_ast_print_to(r.output, stderr);
    generate_block(r.output);
    mpc_ast_delete(r.output);
  } else {
    mpc_err_print_to(r.error, stderr);
    mpc_err_delete(r.error);
  }
  stdin_free(input);

  mpc_cleanup(21, State, Ident, Number, Hex, Dec, Bool, For, Range, By, If, Assign, Expr, Call, Not, Or, And, Equal, Comp, Sum, Prod, Value, Block, Prog);

  // Tag ends with marker bytes so we can tell apart from random serial stuff.
  output[0] = '(';
  output[1] = ']';
  output[output_len++] = '[';
  output[output_len++] = ')';
  // Write full length (including header/trailer as big-endian uint16_t)
  output[2] = output_len >> 8;
  output[3] = output_len & 0xff;

  write(1, output, output_len);

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xc8, %rsp
leaq 0x311d(%rip), %rdi      # 0xd6c5
callq 0x3f2f
movq %rax, 0x18(%rsp)
leaq 0x3116(%rip), %rdi      # 0xd6cf
callq 0x3f2f
movq %rax, 0x78(%rsp)
leaq 0x2f84(%rip), %rdi      # 0xd54e
callq 0x3f2f
movq %rax, 0x68(%rsp)
leaq 0x30fa(%rip), %rdi      # 0xd6d5
callq 0x3f2f
movq %rax, 0x8(%rsp)
leaq 0x2f5a(%rip), %rdi      # 0xd546
callq 0x3f2f
movq %rax, 0x60(%rsp)
leaq 0x30dc(%rip), %rdi      # 0xd6d9
callq 0x3f2f
movq %rax, 0xc0(%rsp)
leaq 0x30d0(%rip), %rdi      # 0xd6e1
callq 0x3f2f
movq %rax, 0xb8(%rsp)
leaq 0x2f5f(%rip), %rdi      # 0xd584
callq 0x3f2f
movq %rax, 0x70(%rsp)
leaq 0x30af(%rip), %rdi      # 0xd6e5
callq 0x3f2f
movq %rax, 0x10(%rsp)
leaq 0x30a1(%rip), %rdi      # 0xd6e8
callq 0x3f2f
movq %rax, 0x58(%rsp)
leaq 0x3093(%rip), %rdi      # 0xd6eb
callq 0x3f2f
movq %rax, 0x50(%rsp)
leaq 0x3089(%rip), %rdi      # 0xd6f2
callq 0x3f2f
movq %rax, 0x48(%rsp)
leaq 0x3083(%rip), %rdi      # 0xd6fd
callq 0x3f2f
movq %rax, 0x40(%rsp)
leaq 0x3077(%rip), %rdi      # 0xd702
callq 0x3f2f
movq %rax, 0x38(%rsp)
leaq 0x3046(%rip), %rdi      # 0xd6e2
callq 0x3f2f
movq %rax, 0x30(%rsp)
leaq 0x36b1(%rip), %rdi      # 0xdd5e
callq 0x3f2f
movq %rax, 0x28(%rsp)
leaq 0x3048(%rip), %rdi      # 0xd706
callq 0x3f2f
movq %rax, %r13
leaq 0x3042(%rip), %rdi      # 0xd70f
callq 0x3f2f
movq %rax, %rbp
leaq 0x303e(%rip), %rdi      # 0xd71a
callq 0x3f2f
movq %rax, %rbx
leaq 0x3033(%rip), %rdi      # 0xd71e
callq 0x3f2f
movq %rax, %r15
leaq 0x302c(%rip), %rdi      # 0xd726
callq 0x3f2f
movq %rax, %r12
leaq 0x3023(%rip), %rdi      # 0xd72c
callq 0x3f2f
movq %rax, %r14
leaq 0x301a(%rip), %rdi      # 0xd732
callq 0x3f2f
movq %rax, %r10
leaq 0x3013(%rip), %rsi      # 0xd73a
xorl %edi, %edi
movq 0x18(%rsp), %rdx
movq 0x78(%rsp), %rcx
movq 0x68(%rsp), %r8
movq 0x8(%rsp), %r9
xorl %eax, %eax
pushq $0x0
movq %r10, 0x28(%rsp)
pushq %r10
movq %r14, 0x98(%rsp)
pushq %r14
movq %r12, 0xa8(%rsp)
pushq %r12
movq %r15, 0xb8(%rsp)
pushq %r15
movq %rbx, 0xc8(%rsp)
pushq %rbx
movq 0xa0(%rsp), %r10
movq %rbp, 0xd8(%rsp)
pushq %rbp
movq %r13, 0xe8(%rsp)
pushq %r13
movq 0xf8(%rsp), %r13
pushq 0x68(%rsp)
pushq 0x78(%rsp)
movq 0x110(%rsp), %r12
pushq 0x88(%rsp)
pushq 0x98(%rsp)
pushq 0xa8(%rsp)
pushq 0xb8(%rsp)
pushq 0xc8(%rsp)
pushq 0x88(%rsp)
pushq %r10
pushq %r13
pushq %r12
pushq 0xf8(%rsp)
callq 0x9af6
addq $0xa0, %rsp
testq %rax, %rax
jne 0xa98d
xorl %edi, %edi
callq 0xa405
movq %rax, %rbp
movb (%rax), %dl
testb %dl, %dl
je 0xa82d
movq %rbp, %rax
incq %rax
xorl %ecx, %ecx
testb $0x1, %cl
je 0xa816
movl %ecx, %esi
cmpb $0xa, %dl
jne 0xa81e
xorl %ecx, %ecx
jmp 0xa824
movb $0x1, %sil
cmpb $0x23, %dl
jne 0xa824
movb $0x20, -0x1(%rax)
movl %esi, %ecx
movb (%rax), %dl
incq %rax
testb %dl, %dl
jne 0xa806
leaq 0x2bdd(%rip), %rdi      # 0xd411
movq %rbp, %rsi
callq 0x3980
movq %rax, %rbx
leaq 0x80(%rsp), %r14
movq %rax, %rdi
movq 0x20(%rsp), %rsi
movq %r14, %rdx
callq 0x27b4
movl %eax, %r15d
movq %rbx, %rdi
callq 0x3a42
movq (%r14), %rdi
testl %r15d, %r15d
je 0xa99c
callq 0xa9ae
movq 0x80(%rsp), %rdi
callq 0x7875
movq 0x18(%rsp), %rbx
movq 0x10(%rsp), %r14
movq 0x8(%rsp), %r15
movq %rbp, %rdi
callq 0x2280
xorl %ebp, %ebp
movl $0x15, %edi
movq %rbx, %rsi
movq 0x78(%rsp), %rdx
movq 0x68(%rsp), %rcx
movq %r15, %r8
movq 0x60(%rsp), %r9
xorl %eax, %eax
pushq 0x20(%rsp)
pushq 0x90(%rsp)
pushq 0xa0(%rsp)
pushq 0xb0(%rsp)
pushq 0xc0(%rsp)
pushq 0xd0(%rsp)
pushq 0xe0(%rsp)
pushq 0x60(%rsp)
pushq 0x70(%rsp)
pushq 0x80(%rsp)
pushq 0x90(%rsp)
pushq 0xa0(%rsp)
pushq 0xb0(%rsp)
pushq 0xc0(%rsp)
pushq %r14
pushq 0xe8(%rsp)
pushq %r13
pushq %r12
callq 0x4356
addq $0x90, %rsp
movw $0x5d28, 0x88d0(%rip)   # imm = 0x5D28
leaq 0x88c9(%rip), %rsi      # 0x13200
movzwl 0x88a2(%rip), %eax      # 0x131e0
leal 0x1(%rax), %ecx
movw %cx, 0x8898(%rip)       # 0x131e0
movb $0x5b, (%rax,%rsi)
leal 0x2(%rax), %edx
movw %dx, 0x888a(%rip)       # 0x131e0
movl $0xffff, %eax           # imm = 0xFFFF
andl %eax, %ecx
movb $0x29, (%rcx,%rsi)
movb %dh, 0x889b(%rip)       # 0x13202
movb %dl, 0x8896(%rip)       # 0x13203
andl %eax, %edx
movl $0x1, %edi
callq 0x2090
movl %ebp, %eax
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rdi
callq 0x2290
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
jmp 0xa979
leaq 0x80(%rsp), %rsi
callq 0x22c0
jmp 0xa880