main: split off program iteration to its own unit

This commit is contained in:
2026-03-10 21:12:10 +00:00
parent 07d9de99d7
commit 2b8a3cbda2
4 changed files with 213 additions and 150 deletions

View File

@@ -2,7 +2,7 @@
CFLAGS="-Wall -Wextra -Wpedantic -Wswitch-enum -Werror -std=c23 -ggdb"
LDFLAGS="-lm -lraylib"
SRC="src/sv.c src/vec.c src/main.c"
SRC="src/sv.c src/vec.c src/program_iter.c src/main.c"
OUT="main.out"
set -xe

View File

@@ -14,161 +14,14 @@
#include "sv.h"
#include "vec.h"
#include "program_iter.h"
struct ProgramConcat
{
sv_t A, B;
u8 tape[SIZEOF_PROGRAM * 2];
};
void program_concat(struct ProgramConcat *ret, sv_t a, sv_t b)
{
assert(a.size == SIZEOF_PROGRAM && b.size == SIZEOF_PROGRAM);
memset(ret, 0, sizeof(*ret));
ret->A = a;
ret->B = b;
memcpy(ret->tape, a.data, SIZEOF_PROGRAM);
memcpy(ret->tape + SIZEOF_PROGRAM, b.data, SIZEOF_PROGRAM);
}
u64 vec_pop(vec_t *vec)
{
u64 ret = 0;
if (vec->size < sizeof(ret))
return ret;
vec->size -= sizeof(ret);
memcpy(&ret, (typeof(ret) *)(((u8 *)vec_data(vec)) + vec->size), sizeof(ret));
return ret;
}
bool vec_in(vec_t *vec, u64 n)
{
for (u64 i = 0; i < vec->size / sizeof(n); ++i)
{
if (VEC_GET(vec, i, typeof(n)) == n)
{
return true;
}
}
return false;
}
void program_execute(struct ProgramConcat *prg)
{
vec_t cond_stack = {0};
vec_ensure_capacity(&cond_stack, sizeof(prg->tape) * sizeof(u64));
for (u64 ip = 0, head0 = 0, head1 = 0, total_iters = 0;
ip < sizeof(prg->tape) && total_iters < (1LU << 13); ++total_iters)
{
u8 opcode = prg->tape[ip];
switch (opcode)
{
case '<':
head0 = SAFE_SUB(head0, 1);
++ip;
break;
case '>':
head0++;
++ip;
break;
case '{':
head1 = SAFE_SUB(head1, 1);
++ip;
break;
case '}':
head1++;
++ip;
break;
case '-':
prg->tape[head0]--;
++ip;
break;
case '+':
prg->tape[head0]++;
++ip;
break;
case '.':
prg->tape[head1] = prg->tape[head0];
++ip;
break;
case ',':
prg->tape[head0] = prg->tape[head1];
++ip;
break;
case '[':
{
if (!vec_in(&cond_stack, ip))
{
vec_append(&cond_stack, &ip, sizeof(ip));
}
if (!prg->tape[head0])
{
// Iterate forward, trying to find a matching closed bracket
u64 square_brackets = 0;
u64 close_ip;
for (close_ip = ip + 1; close_ip < sizeof(prg->tape); ++close_ip)
{
if (prg->tape[close_ip] == '[')
{
++square_brackets;
}
else if (prg->tape[close_ip] == ']')
{
if (square_brackets == 0)
{
break;
}
--square_brackets;
}
}
if (square_brackets != 0)
{
// NOTE: as per paper, terminate.
ip = sizeof(prg->tape);
}
else
{
ip = close_ip;
}
}
break;
}
case ']':
{
if (prg->tape[head0])
{
if (cond_stack.size < sizeof(u64))
{
// NOTE: as per paper, terminate.
ip = sizeof(prg->tape);
}
else
{
ip = vec_pop(&cond_stack);
}
}
else
{
++ip;
}
break;
}
default:
++ip;
break;
}
}
vec_free(&cond_stack);
}
void program_split(struct ProgramConcat *prg)
{
assert(prg->A.data && prg->B.data);
memcpy((char *)prg->A.data, prg->tape, SIZEOF_PROGRAM);
memcpy((char *)prg->B.data, prg->tape + SIZEOF_PROGRAM, SIZEOF_PROGRAM);
}
#define WIDTH 800
#define HEIGHT 600

172
src/program_iter.c Normal file
View File

@@ -0,0 +1,172 @@
/* program_iter.c: Program iteration implementation
* Created: 2026-03-10
* Author: Aryadev Chavali
* License: See end of file
*/
#include <string.h>
#include "program_iter.h"
#include "vec.h"
void program_concat(struct ProgramConcat *ret, sv_t a, sv_t b)
{
assert(a.size == SIZEOF_PROGRAM && b.size == SIZEOF_PROGRAM);
memset(ret, 0, sizeof(*ret));
ret->A = a;
ret->B = b;
memcpy(ret->tape, a.data, SIZEOF_PROGRAM);
memcpy(ret->tape + SIZEOF_PROGRAM, b.data, SIZEOF_PROGRAM);
}
u64 vec_pop(vec_t *vec)
{
u64 ret = 0;
if (vec->size < sizeof(ret))
return ret;
vec->size -= sizeof(ret);
memcpy(&ret, (typeof(ret) *)(((u8 *)vec_data(vec)) + vec->size), sizeof(ret));
return ret;
}
bool vec_in(vec_t *vec, u64 n)
{
for (u64 i = 0; i < vec->size / sizeof(n); ++i)
{
if (VEC_GET(vec, i, typeof(n)) == n)
{
return true;
}
}
return false;
}
void program_execute(struct ProgramConcat *prg)
{
vec_t cond_stack = {0};
vec_ensure_capacity(&cond_stack, sizeof(prg->tape) * sizeof(u64));
for (u64 ip = 0, head0 = 0, head1 = 0, total_iters = 0;
ip < sizeof(prg->tape) && total_iters < (1LU << 13); ++total_iters)
{
u8 opcode = prg->tape[ip];
switch (opcode)
{
case '<':
head0 = SAFE_SUB(head0, 1);
++ip;
break;
case '>':
head0++;
++ip;
break;
case '{':
head1 = SAFE_SUB(head1, 1);
++ip;
break;
case '}':
head1++;
++ip;
break;
case '-':
prg->tape[head0]--;
++ip;
break;
case '+':
prg->tape[head0]++;
++ip;
break;
case '.':
prg->tape[head1] = prg->tape[head0];
++ip;
break;
case ',':
prg->tape[head0] = prg->tape[head1];
++ip;
break;
case '[':
{
if (!vec_in(&cond_stack, ip))
{
vec_append(&cond_stack, &ip, sizeof(ip));
}
if (!prg->tape[head0])
{
// Iterate forward, trying to find a matching closed bracket
u64 square_brackets = 0;
u64 close_ip;
for (close_ip = ip + 1; close_ip < sizeof(prg->tape); ++close_ip)
{
if (prg->tape[close_ip] == '[')
{
++square_brackets;
}
else if (prg->tape[close_ip] == ']')
{
if (square_brackets == 0)
{
break;
}
--square_brackets;
}
}
if (square_brackets != 0)
{
// NOTE: as per paper, terminate.
ip = sizeof(prg->tape);
}
else
{
ip = close_ip;
}
}
break;
}
case ']':
{
if (prg->tape[head0])
{
if (cond_stack.size < sizeof(u64))
{
// NOTE: as per paper, terminate.
ip = sizeof(prg->tape);
}
else
{
ip = vec_pop(&cond_stack);
}
}
else
{
++ip;
}
break;
}
default:
++ip;
break;
}
}
vec_free(&cond_stack);
}
void program_split(struct ProgramConcat *prg)
{
assert(prg->A.data && prg->B.data);
memcpy((char *)prg->A.data, prg->tape, SIZEOF_PROGRAM);
memcpy((char *)prg->B.data, prg->tape + SIZEOF_PROGRAM, SIZEOF_PROGRAM);
}
/* Copyright (C) 2026 Aryadev Chavali
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License Version 2 for
* details.
* You may distribute and modify this code under the terms of the GNU General
* Public License Version 2, which you should have received a copy of along with
* this program. If not, please go to <https://www.gnu.org/licenses/>.
*/

38
src/program_iter.h Normal file
View File

@@ -0,0 +1,38 @@
/* program_iter.h: Program iteration procedure
* Created: 2026-03-10
* Author: Aryadev Chavali
* License: See end of file
*/
#ifndef PROGRAM_ITER_H
#define PROGRAM_ITER_H
#include "base.h"
#include "sv.h"
// Result of concatenating two programs. Maintains a concatenated tape of the
// two programs fed for ease of use.
struct ProgramConcat
{
sv_t A, B;
u8 tape[SIZEOF_PROGRAM * 2];
};
void program_concat(struct ProgramConcat *, sv_t, sv_t);
void program_execute(struct ProgramConcat *);
void program_split(struct ProgramConcat *);
#endif
/* Copyright (C) 2026 Aryadev Chavali
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License Version 2 for
* details.
* You may distribute and modify this code under the terms of the GNU General
* Public License Version 2, which you should have received a copy of along with
* this program. If not, please go to <https://www.gnu.org/licenses/>.
*/