view interps/egobf/src/optimize.c @ 12500:e48c08805365 draft default tip

<b_jonas> ` learn \'The password of the month is Cthulhuquagdonic Mothraquagdonic Narwhalicorn.\' # https://logs.esolangs.org/libera-esolangs/2024-04.html#lKE Infinite craft
author HackEso <hackeso@esolangs.org>
date Wed, 01 May 2024 06:39:10 +0000
parents 859f9b4339e6
children
line wrap: on
line source

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

#include "egobfi.h"
#include "optimize.h"

#define NEXT pptr++; CHKPSZ(pptr)

int optaddto(int cur);

void optimize()
{
    /* optimize optimizes a chunk of code at ipptr */
    int cnt, a;
    struct bfi *cur;
    
    while (iprog[ipptr]) {
        switch(iprog[ipptr]) {
            case '+':
            case '-':
                cnt = 0;
                while (iprog[ipptr] == '+' ||
                       iprog[ipptr] == '-') {
                    if (iprog[ipptr] == '+') cnt++;
                    else cnt--;
                    ipptr++;
                }
            
                cur = prog + pptr;
                cur->cmd = ADD;
                cur->arg1 = cnt;
                NEXT
                break;
            
            case '>':
            case '<':
                cnt = 0;
                while (iprog[ipptr] == '>' ||
                       iprog[ipptr] == '<') {
                    if (iprog[ipptr] == '>') cnt++;
                    else cnt--;
                    ipptr++;
                }
            
                cur = prog + pptr;
                cur->cmd = RHT;
                cur->arg1 = cnt;
                NEXT
                break;
                
            case '[':
                /* special case 1: zero */
                if (iprog[ipptr + 2] == ']' &&
                    (iprog[ipptr + 1] == '-' ||
                     (iprog[ipptr + 1] == '+' && wrapping))
                    ) {
                    prog[pptr].cmd = ZRO;
                    NEXT
                    ipptr += 3;
                    break;
                }
                    
                /* start a suboptimize */
                a = pptr;
                NEXT
                ipptr++;
                optimize();
                
                /* check for addto */
                if (pptr == a + 5 && optaddto(a)) {
                    ipptr++;
                    break;
                }
                
                /* make the jump */
                cur = prog + a;
                cur->cmd = LPO;
                cur->arg1 = pptr;
                
                cur = prog + pptr;
                cur->cmd = LPC;
                cur->arg1 = a;
                
                NEXT
                ipptr++;
                break;
                
            case ']':
                /* this optimization session is over */
                return;
                
            case '.':
                /* not much we can optimize here ... */
                prog[pptr].cmd = OUT;
                NEXT
                ipptr++;
                break;
                
            case ',':
                /* here neither ... */
                prog[pptr].cmd = INP;
                NEXT
                ipptr++;
                break;
                
            case '#':
                /* still no optimizations! */
                prog[pptr].cmd = DBG;
                NEXT
                ipptr++;
                break;
                
            default:
                ipptr++;
                break;
        }
    }
    
    /* if we finished making the optimized program, this is the end */
    prog[pptr].cmd = FIN;
    pptr = 0;
}

int optaddto(int cur)
{
    /* a = pptr of LPO,
       pptr = pptr of LPC */
    struct bfi *a = prog + cur;
    
    /* two types of add-tos:
    >x +x <x -x
    -x >x +x <x
    */
    if (a[1].cmd == RHT &&
        a[3].cmd == RHT &&
        a[1].arg1 == a[3].arg1 * -1) {
        if (a[2].cmd == ADD &&
            a[4].cmd == ADD &&
            a[4].arg1 == -1) {
            /* YAY! */
            a->cmd = ADDTO;
            a->arg1 = a[1].arg1;
            a->arg2 = a[2].arg1;
                    
            pptr = cur + 1;
            return 1;
        }
    } else if (a[2].cmd == RHT &&
               a[4].cmd == RHT &&
               a[2].arg1 == a[4].arg1 * -1) {
        if (a[1].cmd == ADD &&
            a[3].cmd == ADD &&
            a[1].arg1 == -1) {
            /* YAY! */
            a->cmd = ADDTO;
            a->arg1 = a[2].arg1;
            a->arg2 = a[3].arg1;
            
            pptr = cur + 1;
            return 1;
        }
    }
    
    return 0;
}