Skip to content

Instantly share code, notes, and snippets.

@jduey
Created June 24, 2024 12:41
Show Gist options
  • Save jduey/e6c8ca2516f943e1b6028dcee3c4fa85 to your computer and use it in GitHub Desktop.
Save jduey/e6c8ca2516f943e1b6028dcee3c4fa85 to your computer and use it in GitHub Desktop.
//#include <dlfcn.h>
#include <inttypes.h>
#include <math.h>
#include <pthread.h>
#include <stdatomic.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Integers
// --------
typedef uint8_t bool;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef int64_t i64;
typedef uint64_t u64;
typedef double f64;
typedef _Atomic(u8) a8;
typedef _Atomic(u16) a16;
typedef _Atomic(u32) a32;
typedef _Atomic(u64) a64;
// Configuration
// -------------
// Threads per CPU
#ifndef TPC_L2
#define TPC_L2 4 // 16 cores
#endif
#define TPC (1ul << TPC_L2)
// Types
// -----
// Local Types
typedef u8 Tag; // Tag ::= 3-bit (rounded up to u8)
typedef u64 Val; // Val ::= 29-bit (rounded up to u32)
#define MAG 0x00000141
// Constants
#define NONE -1
#define FREE 0
typedef u64 Port; // Port ::= Tag + Val (fits a u32)
typedef struct {Port fst; Port snd;} Pair; // Pair ::= Port + Port (fits a u64)
Pair emptyPair = {0, 0};
static inline u8 isEmpty(Pair p) {
return p.fst == 0 && p.snd == 0;
}
typedef _Atomic(Port) APort; // atomic Port
typedef _Atomic(Pair) APair; // atomic Pair
// Numbs
typedef u64 Numb; // Numb ::= 60-bit (rounded up to u64)
// Tags
#define VAR 0x0 // variable
#define REF 0x1 // reference
#define ERA 0x2 // eraser
#define NUM 0x3 // number
#define CON 0x4 // constructor
#define DUP 0x5 // duplicator
#define OPR 0x6 // operator
#define SWI 0x7 // switch
Port erase = ERA;
// Numbers
static const u64 U24_MAX = ((u64)1 << 56) - 1;
static const u64 U24_MIN = 0.0;
static const i64 I24_MAX = ((i64)1 << 55) - 1;
static const i64 I24_MIN = (i64) ((u64)-1 << 55);
#define TY_SYM 0x00
#define TY_U24 0x01
#define TY_I24 0x02
#define TY_F24 0x03
#define OP_ADD 0x04
#define OP_SUB 0x05
#define FP_SUB 0x06
#define OP_MUL 0x07
#define OP_DIV 0x08
#define FP_DIV 0x09
#define OP_REM 0x0A
#define FP_REM 0x0B
#define OP_EQ 0x0C
#define OP_NEQ 0x0D
#define OP_LT 0x0E
#define OP_GT 0x0F
#define OP_AND 0x10
#define OP_OR 0x11
#define OP_XOR 0x12
#define OP_SHL 0x13
#define FP_SHL 0x14
#define OP_SHR 0x15
#define FP_SHR 0x16
// Global Net
#define HLEN (1ul << 16) // max 16k high-priority redexes
#define RLEN (1ul << 24) // max 16m low-priority redexes
#define G_NODE_LEN (1ul << 29) // max 536m nodes
#define G_VARS_LEN (1ul << 29) // max 536m vars
#define G_RBAG_LEN (TPC * RLEN)
typedef struct Net {
APair node_buf[G_NODE_LEN]; // global node buffer
APort vars_buf[G_VARS_LEN]; // global vars buffer
APair rbag_buf[G_RBAG_LEN]; // global rbag buffer
a64 itrs; // interaction count
a32 idle; // idle thread counter
} Net;
Net *globalNet;
// Local Thread Memory
typedef struct TM {
u32 tid; // thread id
u32 itrs; // interaction count
u32 nput; // next node allocation attempt index
u32 vput; // next vars allocation attempt index
u32 hput; // next hbag push index
u32 rput; // next rbag push index
u32 sidx; // steal index
Pair hbag_buf[HLEN]; // high-priority redexes
} TM;
typedef bool (*interactionFn)(TM* tm, Port a, Port b);
// Booleans
#define TRUE 1
#define FALSE 0
// Debugger
// --------
typedef struct {
char x[13];
} Show;
void put_u16(char* B, u16 val);
Show show_port(Port port);
//void print_rbag(RBag* rbag);
void pretty_print_numb(Numb word);
void pretty_print_port(Port port);
// Port: Constructor and Getters
// -----------------------------
static inline Port new_num(Port val) {
return (val << 3) | NUM;
}
static inline Val get_num(Port port) {
return port >> 3;
}
static inline Port new_port(Tag tag, Port val) {
return (u64)val | tag;
}
// Keep for type checking
static inline Port new_ref(interactionFn val) {
return (u64)val | REF;
}
static inline Tag get_tag(Port port) {
return port & 7;
}
// Pair: Constructor and Getters
// -----------------------------
static inline const Pair new_pair(Port fst, Port snd) {
return (Pair){fst, snd};
}
// Utils
// -----
// Swaps two ports.
static inline void swap(Port *a, Port *b) {
Port x = *a; *a = *b; *b = x;
}
inline u64 min(u64 a, u64 b) {
return (a < b) ? a : b;
}
f64 clamp(f64 x, f64 min, f64 max) {
const f64 t = x < min ? min : x;
return (t > max) ? max : t;
}
// A simple spin-wait barrier using atomic operations
a64 a_reached = 0; // number of threads that reached the current barrier
a64 a_barrier = 0; // number of barriers passed during this program
void sync_threads() {
u64 barrier_old = atomic_load_explicit(&a_barrier, memory_order_relaxed);
if (atomic_fetch_add_explicit(&a_reached, 1, memory_order_relaxed) == (TPC - 1)) {
// Last thread to reach the barrier resets the counter and advances the barrier
atomic_store_explicit(&a_reached, 0, memory_order_relaxed);
atomic_store_explicit(&a_barrier, barrier_old + 1, memory_order_release);
} else {
u32 tries = 0;
while (atomic_load_explicit(&a_barrier, memory_order_acquire) == barrier_old) {
sched_yield();
}
}
}
// TODO: write a time64() function that returns the time as fast as possible as a u64
static inline u64 time64() {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (u64)ts.tv_sec * 1000000000ULL + (u64)ts.tv_nsec;
}
// Ports / Pairs / Rules
// ---------------------
// Should we swap ports A and B before reducing this rule?
static inline bool should_swap(Port A, Port B) {
return get_tag(B) < get_tag(A);
}
// Gets a rule's priority
u8 interactionPriority[8][8] = {
//VAR REF ERA NUM CON DUP OPR SWI
{TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE}, // VAR
{TRUE, TRUE, TRUE, TRUE, FALSE,FALSE,FALSE,FALSE}, // REF
{TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE}, // ERA
{TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE,FALSE}, // NUM
{TRUE, FALSE,TRUE, TRUE, TRUE, FALSE,FALSE,FALSE}, // CON
{TRUE, FALSE,TRUE, TRUE, FALSE,TRUE, FALSE,FALSE}, // DUP
{TRUE, FALSE,TRUE, FALSE,FALSE,FALSE,TRUE, FALSE}, // OPR
{TRUE, FALSE,TRUE, FALSE,FALSE,FALSE,FALSE,TRUE} // SWI
};
static inline bool is_high_priority(Pair AB) {
return interactionPriority[get_tag(AB.fst)][get_tag(AB.snd)];
}
// Numbs
// -----
// Constructor and getters for SYM (operation selector)
static inline Numb new_sym(u64 val) {
return (val << 5) | TY_SYM;
}
static inline u64 get_sym(Numb word) {
return (word >> 5);
}
// Constructor and getters for U24 (unsigned 24-bit integer)
static inline Numb new_u24(u64 val) {
return (val << 5) | TY_U24;
}
static inline u64 get_u24(Numb word) {
return word >> 5;
}
// Constructor and getters for I24 (signed 24-bit integer)
static inline Numb new_i24(i64 val) {
return ((u64)val << 5) | TY_I24;
}
static inline i64 get_i24(Numb word) {
return ((i64)word) << 3 >> 8;
}
// Constructor and getters for F24 (24-bit float)
static inline Numb new_f24(float val) {
u64 bits = *(u64*)&val;
u64 shifted_bits = bits >> 8;
u64 lost_bits = bits & 0xFF;
// round ties to even
shifted_bits += (!isnan(val)) & ((lost_bits - ((lost_bits >> 7) & !shifted_bits)) >> 7);
// ensure NaNs don't become infinities
shifted_bits |= isnan(val);
return (shifted_bits << 5) | TY_F24;
}
static inline f64 get_f24(Numb word) {
u64 bits = (word << 3) & 0xFFFFFFFFFFFFFF00;
return *(f64*)&bits;
}
// Flip flag
static inline Tag get_typ(Numb word) {
return word & 0x1F;
}
static inline bool is_num(Numb word) {
return get_typ(word) >= TY_U24 && get_typ(word) <= TY_F24;
}
static inline bool is_cast(Numb word) {
return get_typ(word) == TY_SYM && get_sym(word) >= TY_U24 && get_sym(word) <= TY_F24;
}
// Partial application
static inline Numb partial(Numb a, Numb b) {
return (b & ~0x1F) | get_sym(a);
}
// Cast a number to another type.
// The semantics are meant to spiritually resemble rust's numeric casts:
// - i24 <-> u24: is just reinterpretation of bits
// - f24 -> i24,
// f24 -> u24: casts to the "closest" integer representing this float,
// saturating if out of range and 0 if NaN
// - i24 -> f24,
// u24 -> f24: casts to the "closest" float representing this integer.
static inline Numb cast(Numb a, Numb b) {
if (get_sym(a) == TY_U24 && get_typ(b) == TY_U24) return b;
if (get_sym(a) == TY_U24 && get_typ(b) == TY_I24) {
// reinterpret bits
i64 val = get_i24(b);
return new_u24(*(u64*) &val);
}
if (get_sym(a) == TY_U24 && get_typ(b) == TY_F24) {
f64 val = get_f24(b);
if (isnan(val)) {
return new_u24(0);
}
return new_u24((u64) clamp(val, U24_MIN, U24_MAX));
}
if (get_sym(a) == TY_I24 && get_typ(b) == TY_U24) {
// reinterpret bits
u64 val = get_u24(b);
return new_i24(*(i64*) &val);
}
if (get_sym(a) == TY_I24 && get_typ(b) == TY_I24) return b;
if (get_sym(a) == TY_I24 && get_typ(b) == TY_F24) {
f64 val = get_f24(b);
if (isnan(val)) {
return new_i24(0);
}
return new_i24((i64) clamp(val, I24_MIN, I24_MAX));
}
if (get_sym(a) == TY_F24 && get_typ(b) == TY_U24) return new_f24((f64) get_u24(b));
if (get_sym(a) == TY_F24 && get_typ(b) == TY_I24) return new_f24((f64) get_i24(b));
if (get_sym(a) == TY_F24 && get_typ(b) == TY_F24) return b;
return new_u24(0);
}
// Operate function
static inline Numb operate(Port aP, Port bP) {
Numb a = aP >> 3;
Numb b = bP >> 3;
Tag at = get_typ(a);
Tag bt = get_typ(b);
if (at == TY_SYM && bt == TY_SYM) {
return new_u24(0);
}
if (is_cast(a) && is_num(b)) {
return cast(a, b);
}
if (is_cast(b) && is_num(a)) {
return cast(b, a);
}
if (at == TY_SYM && bt != TY_SYM) {
return partial(a, b);
}
if (at != TY_SYM && bt == TY_SYM) {
return partial(b, a);
}
if (at >= OP_ADD && bt >= OP_ADD) {
return new_u24(0);
}
if (at < OP_ADD && bt < OP_ADD) {
return new_u24(0);
}
Tag op, ty;
Numb swp;
if (at >= OP_ADD) {
op = at; ty = bt;
} else {
op = bt; ty = at; swp = a; a = b; b = swp;
}
switch (ty) {
case TY_U24: {
u64 av = get_u24(a);
u64 bv = get_u24(b);
switch (op) {
case OP_ADD: return new_u24(av + bv);
case OP_SUB: return new_u24(av - bv);
case FP_SUB: return new_u24(bv - av);
case OP_MUL: return new_u24(av * bv);
case OP_DIV: return new_u24(av / bv);
case FP_DIV: return new_u24(bv / av);
case OP_REM: return new_u24(av % bv);
case FP_REM: return new_u24(bv % av);
case OP_EQ: return new_u24(av == bv);
case OP_NEQ: return new_u24(av != bv);
case OP_LT: return new_u24(av < bv);
case OP_GT: return new_u24(av > bv);
case OP_AND: return new_u24(av & bv);
case OP_OR: return new_u24(av | bv);
case OP_XOR: return new_u24(av ^ bv);
case OP_SHL: return new_u24(av << (bv & 63));
case FP_SHL: return new_u24(bv << (av & 63));
case OP_SHR: return new_u24(av >> (bv & 63));
case FP_SHR: return new_u24(bv >> (av & 63));
default: return new_u24(0);
}
}
case TY_I24: {
i64 av = get_i24(a);
i64 bv = get_i24(b);
switch (op) {
case OP_ADD: return new_i24(av + bv);
case OP_SUB: return new_i24(av - bv);
case FP_SUB: return new_i24(bv - av);
case OP_MUL: return new_i24(av * bv);
case OP_DIV: return new_i24(av / bv);
case FP_DIV: return new_i24(bv / av);
case OP_REM: return new_i24(av % bv);
case FP_REM: return new_i24(bv % av);
case OP_EQ: return new_u24(av == bv);
case OP_NEQ: return new_u24(av != bv);
case OP_LT: return new_u24(av < bv);
case OP_GT: return new_u24(av > bv);
case OP_AND: return new_i24(av & bv);
case OP_OR: return new_i24(av | bv);
case OP_XOR: return new_i24(av ^ bv);
default: return new_i24(0);
}
}
case TY_F24: {
float av = get_f24(a);
float bv = get_f24(b);
switch (op) {
case OP_ADD: return new_f24(av + bv);
case OP_SUB: return new_f24(av - bv);
case FP_SUB: return new_f24(bv - av);
case OP_MUL: return new_f24(av * bv);
case OP_DIV: return new_f24(av / bv);
case FP_DIV: return new_f24(bv / av);
case OP_REM: return new_f24(fmodf(av, bv));
case FP_REM: return new_f24(fmodf(bv, av));
case OP_EQ: return new_u24(av == bv);
case OP_NEQ: return new_u24(av != bv);
case OP_LT: return new_u24(av < bv);
case OP_GT: return new_u24(av > bv);
case OP_AND: return new_f24(atan2f(av, bv));
case OP_OR: return new_f24(logf(bv) / logf(av));
case OP_XOR: return new_f24(powf(av, bv));
default: return new_f24(0);
}
}
default: return new_u24(0);
}
}
// RBag
// ----
// FIXME: what about some bound checks?
static inline void push_redex(TM* tm, Pair redex) {
if (is_high_priority(redex)) {
tm->hbag_buf[tm->hput++] = redex;
} else {
atomic_store_explicit(&globalNet->rbag_buf[tm->tid*(G_RBAG_LEN/TPC) + (tm->rput++)], redex, memory_order_relaxed);
}
}
static inline Pair pop_redex(TM* tm) {
if (tm->hput > 0) {
return tm->hbag_buf[--tm->hput];
} else if (tm->rput > 0) {
return atomic_exchange_explicit(&globalNet->rbag_buf[tm->tid*(G_RBAG_LEN/TPC) + (--tm->rput)],
emptyPair,
memory_order_relaxed);
} else {
return emptyPair;
}
}
static inline u32 rbag_len(TM* tm) {
return tm->rput + tm->hput;
}
// TM
// --
static TM* tm[TPC];
TM* tm_new(u32 tid) {
TM* tm = malloc(sizeof(TM));
tm->tid = tid;
tm->itrs = 0;
tm->nput = 1;
tm->vput = 1;
tm->rput = 0;
tm->hput = 0;
tm->sidx = 0;
return tm;
}
void alloc_static_tms() {
for (u32 t = 0; t < TPC; ++t) {
tm[t] = tm_new(t);
}
}
void free_static_tms() {
for (u32 t = 0; t < TPC; ++t) {
free(tm[t]);
}
}
// Net
// ----
// Stores a new node on global.
static inline void node_create(Port loc, Pair val) {
atomic_store_explicit((APair*)((u64)loc & ~7), val, memory_order_relaxed);
}
// Stores a var on global.
static inline void vars_create(Port var, Port val) {
atomic_store_explicit((APort*)((u64)var & ~7), val, memory_order_relaxed);
}
// Reads a node from global.
static inline Pair node_load(Port loc) {
return atomic_load_explicit((APair*)((u64)loc & ~7), memory_order_relaxed);
}
// Reads a var from global.
static inline Port vars_load(Port var) {
return atomic_load_explicit((APort*)((u64)var & ~7), memory_order_relaxed);
}
// Stores a node on global.
static inline void node_store(Port loc, Pair val) {
atomic_store_explicit((APair*)((u64)loc & ~7), val, memory_order_relaxed);
}
// Exchanges a node on global by a value. Returns old.
static inline Pair node_exchange(Port loc, Pair val) {
return atomic_exchange_explicit((APair*)((u64)loc & ~7), val, memory_order_relaxed);
}
// Exchanges a var on global by a value. Returns old.
static inline Port vars_exchange(Port var, Port val) {
return atomic_exchange_explicit((APort*)((u64)var & ~7), val, memory_order_relaxed);
}
// Takes a node.
static inline Pair node_take(Port loc) {
return node_exchange(loc, emptyPair);
}
// Takes a var.
static inline Port vars_take(Port var) {
return vars_exchange(var, 0);
}
// Net
// ---
// Initializes a net.
static inline void net_init() {
// is that needed?
atomic_store(&globalNet->itrs, 0);
atomic_store(&globalNet->idle, 0);
}
// Allocator
// ---------
Port node_alloc(TM* tm, u32* lps) {
while (TRUE) {
u32 lc = tm->tid*(G_NODE_LEN/TPC) + (tm->nput%(G_NODE_LEN/TPC));
Pair* elem = (Pair *)&globalNet->node_buf[lc];
tm->nput += 1;
if (lc > 0 && isEmpty(*elem)) {
return (Port)elem;
}
// FIXME: check this decently
if (++(*lps) >= G_NODE_LEN/TPC) printf("OOM\n");
}
}
Port vars_alloc(TM* tm, u32* lps) {
while (TRUE) {
u32 lc = tm->tid*(G_NODE_LEN/TPC) + (tm->vput%(G_NODE_LEN/TPC));
Port* elem = (Port*)&globalNet->vars_buf[lc];
tm->vput += 1;
if (lc > 0 && *elem == 0) {
return (Port)elem;
}
// FIXME: check this decently
if (++(*lps) >= G_NODE_LEN/TPC) printf("OOM\n");
}
}
// Linking
// -------
// Finds a variable's value.
static inline Port enter(Port var) {
// While `B` is VAR: extend it (as an optimization)
while (get_tag(var) == VAR) {
// Takes the current `var` substitution as `val`
Port val = vars_exchange(var, NONE);
// If there was no `val`, stop, as there is no extension
if (val == NONE || val == 0) {
break;
}
// Otherwise, delete `B` (we own both) and continue
vars_take(var);
var = val;
}
return var;
}
// Atomically Links `A ~ B`.
static inline void link(TM* tm, Port A, Port B) {
//printf("LINK %s ~> %s\n", show_port(A).x, show_port(B).x);
// Attempts to directionally point `A ~> B`
while (TRUE) {
// If `A` is NODE: swap `A` and `B`, and continue
if (get_tag(A) != VAR && get_tag(B) == VAR) {
Port X = A; A = B; B = X;
}
// If `A` is NODE: create the `A ~ B` redex
if (get_tag(A) != VAR) {
push_redex(tm, new_pair(A, B)); // TODO: move global ports to local
break;
}
// Extends B (as an optimization)
B = enter(B);
// Since `A` is VAR: point `A ~> B`.
if (TRUE) {
// Stores `A -> B`, taking the current `A` subst as `A'`
Port A_ = vars_exchange(A, B);
// If there was no `A'`, stop, as we lost B's ownership
if (A_ == NONE) {
break;
}
//if (A_ == 0) { ? } // FIXME: must handle on the move-to-global algo
// Otherwise, delete `A` (we own both) and link `A' ~ B`
vars_take(A);
A = A_;
}
}
}
// Links `A ~ B` (as a pair).
static inline void link_pair(TM* tm, Pair AB) {
//printf("link_pair %016llx\n", AB);
link(tm, AB.fst, AB.snd);
}
// Interactions
// ------------
// The Link Interaction.
bool LINK(TM* tm, Port a, Port b) {
// Links.
link_pair(tm, new_pair(a, b));
return TRUE;
}
bool CALL(TM *tm, Port a, Port b) {
interactionFn fnPtr;
fnPtr = (interactionFn)(a & ~3);
return fnPtr(tm, a, b);
}
// The Void Interaction.
static inline bool VOID(TM* tm, Port a, Port b) {
return TRUE;
}
// The Eras Interaction.
static inline bool ERAS(TM* tm, Port a, Port b) {
// Checks availability
if (isEmpty(node_load(b))) {
//printf("[%04x] unavailable0: %s\n", tid, show_port(b).x);
return FALSE;
}
// Loads ports.
Pair B = node_exchange(b, emptyPair);
Port B1 = B.fst;
Port B2 = B.snd;
//if (B == 0) printf("[%04x] ERROR2: %s\n", tid, show_port(b).x);
// Links.
link_pair(tm, new_pair(a, B1));
link_pair(tm, new_pair(a, B2));
return TRUE;
}
// The Anni Interaction.
static inline bool ANNI(TM* tm, Port a, Port b) {
// Checks availability
if (isEmpty(node_load(a)) || isEmpty(node_load(b))) {
//printf("[%04x] unavailable1: %s | %s\n", tid, show_port(a).x, show_port(b).x);
//printf("BBB\n");
return FALSE;
}
// Loads ports.
Pair A = node_take(a);
Port A1 = A.fst;
Port A2 = A.snd;
Pair B = node_take(b);
Port B1 = B.fst;
Port B2 = B.snd;
//if (A == 0) printf("[%04x] ERROR3: %s\n", tid, show_port(a).x);
//if (B == 0) printf("[%04x] ERROR4: %s\n", tid, show_port(b).x);
// Links.
link_pair(tm, new_pair(A1, B1));
link_pair(tm, new_pair(A2, B2));
return TRUE;
}
// The Comm Interaction.
static inline bool COMM(TM* tm, Port a, Port b) {
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port v2 = vars_alloc(tm, &vl);
Port v3 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
Port n3 = node_alloc(tm, &nl);
// Checks availability
if (isEmpty(node_load(a)) || isEmpty(node_load(b))) {
//printf("[%04x] unavailable2: %s | %s\n", tid, show_port(a).x, show_port(b).x);
return FALSE;
}
// Loads ports.
Pair A = node_take(a);
Port A1 = A.fst;
Port A2 = A.snd;
Pair B = node_take(b);
Port B1 = B.fst;
Port B2 = B.snd;
//if (A == 0) printf("[%04x] ERROR5: %s\n", tid, show_port(a).x);
//if (B == 0) printf("[%04x] ERROR6: %s\n", tid, show_port(b).x);
// Stores new vars.
vars_create(v0, NONE);
vars_create(v1, NONE);
vars_create(v2, NONE);
vars_create(v3, NONE);
// Stores new nodes.
node_create(n0, new_pair(new_port(VAR, v0), new_port(VAR, v1)));
node_create(n1, new_pair(new_port(VAR, v2), new_port(VAR, v3)));
node_create(n2, new_pair(new_port(VAR, v0), new_port(VAR, v2)));
node_create(n3, new_pair(new_port(VAR, v1), new_port(VAR, v3)));
// Links.
link_pair(tm, new_pair(new_port(get_tag(b), n0), A1));
link_pair(tm, new_pair(new_port(get_tag(b), n1), A2));
link_pair(tm, new_pair(new_port(get_tag(a), n2), B1));
link_pair(tm, new_pair(new_port(get_tag(a), n3), B2));
return TRUE;
}
// The Oper Interaction.
static inline bool OPER(TM* tm, Port a, Port b) {
//printf("OPER %08x %08x\n", a, b);
// Allocates needed nodes and vars.
u32 nl = 0;
Port n0 = node_alloc(tm, &nl);
// Checks availability
if (isEmpty(node_load(b))) {
return FALSE;
}
// Loads ports.
Pair B = node_take(b);
Port B1 = B.fst;
Port B2 = enter(B.snd);
// Performs operation.
if (get_tag(B1) == NUM) {
Numb cv = operate(a, B1);
link_pair(tm, new_pair(new_num(cv), B2));
} else {
node_create(n0, new_pair(a, B2));
link_pair(tm, new_pair(B1, new_port(OPR, n0)));
}
return TRUE;
}
// The Swit Interaction.
static inline bool SWIT(TM* tm, Port a, Port b) {
u32 nl = 0;
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
// Checks availability
if (isEmpty(node_load(b))) {
return FALSE;
}
// Loads ports.
u64 av = get_u24(get_num(a));
Pair B = node_take(b);
Port B1 = B.fst;
Port B2 = B.snd;
// Stores new nodes.
if (av == 0) {
node_create(n0, new_pair(B2, erase));
link_pair(tm, new_pair(new_port(CON, n0), B1));
} else {
node_create(n0, new_pair(erase, new_port(CON, n1)));
node_create(n1, new_pair(new_num(new_u24(av-1)), B2));
link_pair(tm, new_pair(new_port(CON, n0), B1));
}
return TRUE;
}
interactionFn interactions[8][8] = {
//VAR REF ERA NUM CON DUP OPR SWI
{&LINK,&LINK,&LINK,&LINK,&LINK,&LINK,&LINK,&LINK}, // VAR
{&LINK,&VOID,&VOID,&VOID,&CALL,&CALL,&CALL,&CALL}, // REF
{&LINK,&VOID,&VOID,&VOID,&ERAS,&ERAS,&ERAS,&ERAS}, // ERA
{&LINK,&VOID,&VOID,&VOID,&ERAS,&ERAS,&OPER,&SWIT}, // NUM
{&LINK,&CALL,&ERAS,&ERAS,&ANNI,&COMM,&COMM,&COMM}, // CON
{&LINK,&CALL,&ERAS,&ERAS,&COMM,&ANNI,&COMM,&COMM}, // DUP
{&LINK,&CALL,&ERAS,&OPER,&COMM,&COMM,&ANNI,&COMM}, // OPR
{&LINK,&CALL,&ERAS,&SWIT,&COMM,&COMM,&COMM,&ANNI} // SWI
};
interactionFn get_rule(Port a, Port b) {
return interactions[get_tag(a)][get_tag(b)];
}
// Pops a local redex and performs a single interaction.
static inline bool interact(TM* tm) {
// Pops a redex.
Pair redex = pop_redex(tm);
// If there is no redex, stop.
if (!isEmpty(redex)) {
// Gets redex ports A and B.
Port a = redex.fst;
Port b = redex.snd;
// Gets the rule type.
interactionFn rule = get_rule(a, b);
// Swaps ports if necessary.
if (should_swap(a,b)) {
swap(&a, &b);
}
// If error, pushes redex back.
if (!rule(tm, a, b)) {
push_redex(tm, redex);
return FALSE;
// Else, increments the interaction count.
} else if (rule != LINK) {
tm->itrs += 1;
}
}
return TRUE;
}
// Evaluator
// ---------
void evaluator(TM* tm) {
// Initializes the global idle counter
atomic_store_explicit(&globalNet->idle, TPC - 1, memory_order_relaxed);
sync_threads();
// Performs some interactions
u32 tick = 0;
bool busy = tm->tid == 0;
while (TRUE) {
tick += 1;
//if (tm->tid == 1) printf("think %d\n", rbag_len(net, tm));
// If we have redexes...
if (rbag_len(tm) > 0) {
// Update global idle counter
if (!busy) atomic_fetch_sub_explicit(&globalNet->idle, 1, memory_order_relaxed);
busy = TRUE;
// Perform an interaction
interact(tm);
// If we have no redexes...
} else {
// Update global idle counter
if (busy) atomic_fetch_add_explicit(&globalNet->idle, 1, memory_order_relaxed);
busy = FALSE;
//// Peeks a redex from target
u32 sid = (tm->tid - 1) % TPC;
u32 idx = sid*(G_RBAG_LEN/TPC) + (tm->sidx++);
// Steal Parallel: this will only steal parallel redexes
//Pair trg = atomic_load_explicit(&net->rbag_buf[idx], memory_order_relaxed);
//// If we're ahead of target, reset
//if (trg == 0) {
//tm->sidx = 0;
//// If the redex is parallel, attempt to steal it
//} else if (get_par_flag(trg)) {
//bool stolen = atomic_compare_exchange_weak_explicit(&net->rbag_buf[idx], &trg, 0, memory_order_relaxed, memory_order_relaxed);
//if (stolen) {
//push_redex(tm, trg);
//} else {
//// do nothing: will sched_yield
//}
//// If we see a non-stealable redex, try the next one
//} else {
//continue;
//}
// Stealing Everything: this will steal all redexes
Pair got = atomic_exchange_explicit(&globalNet->rbag_buf[idx], emptyPair, memory_order_relaxed);
if (!isEmpty(got)) {
//printf("[%04x] stolen one task from %04x | itrs=%d idle=%d | %s ~ %s\n", tm->tid, sid, tm->itrs, atomic_load_explicit(&net->idle, memory_order_relaxed),show_port(got)).x, show_port(got).snd.x.fst;
push_redex(tm, got);
continue;
} else {
//printf("[%04x] failed to steal from %04x | itrs=%d idle=%d |\n", tm->tid, sid, tm->itrs, atomic_load_explicit(&net->idle, memory_order_relaxed));
tm->sidx = 0;
}
// Chill...
sched_yield();
// Halt if all threads are idle
if (tick % 256 == 0) {
if (atomic_load_explicit(&globalNet->idle, memory_order_relaxed) == TPC) {
break;
}
}
}
}
sync_threads();
atomic_fetch_add(&globalNet->itrs, tm->itrs);
tm->itrs = 0;
}
// Normalizer
// ----------
// Thread data
typedef struct {
TM* tm;
} ThreadArg;
void* thread_func(void* arg) {
ThreadArg* data = (ThreadArg*)arg;
evaluator(data->tm);
return NULL;
}
// Evaluates all redexes.
// TODO: cache threads to avoid spawning overhead
void normalize() {
// Inits thread_arg objects
ThreadArg thread_arg[TPC];
for (u32 t = 0; t < TPC; ++t) {
thread_arg[t].tm = tm[t];
}
// Spawns the evaluation threads
pthread_t threads[TPC];
for (u32 t = 0; t < TPC; ++t) {
pthread_create(&threads[t], NULL, thread_func, &thread_arg[t]);
}
// Wait for the threads to finish
for (u32 t = 0; t < TPC; ++t) {
pthread_join(threads[t], NULL);
}
}
// Debug Printing
// --------------
void pretty_print_numb(Numb word) {
switch (get_typ(word)) {
case TY_SYM: {
switch (get_sym(word)) {
// types
case TY_U24: printf("[u24]"); break;
case TY_I24: printf("[i24]"); break;
case TY_F24: printf("[f24]"); break;
// operations
case OP_ADD: printf("[+]"); break;
case OP_SUB: printf("[-]"); break;
case FP_SUB: printf("[:-]"); break;
case OP_MUL: printf("[*]"); break;
case OP_DIV: printf("[/]"); break;
case FP_DIV: printf("[:/]"); break;
case OP_REM: printf("[%%]"); break;
case FP_REM: printf("[:%%]"); break;
case OP_EQ: printf("[=]"); break;
case OP_NEQ: printf("[!]"); break;
case OP_LT: printf("[<]"); break;
case OP_GT: printf("[>]"); break;
case OP_AND: printf("[&]"); break;
case OP_OR: printf("[|]"); break;
case OP_XOR: printf("[^]"); break;
case OP_SHL: printf("[<<]"); break;
case FP_SHL: printf("[:<<]"); break;
case OP_SHR: printf("[>>]"); break;
case FP_SHR: printf("[:>>]"); break;
default: printf("[?]"); break;
}
break;
}
case TY_U24: {
printf("%lu", get_u24(word));
break;
}
case TY_I24: {
printf("%+ld", get_i24(word));
break;
}
case TY_F24: {
if (isinf(get_f24(word))) {
if (signbit(get_f24(word))) {
printf("-inf");
} else {
printf("+inf");
}
} else if (isnan(get_f24(word))) {
printf("+NaN");
} else {
printf("%.7e", get_f24(word));
}
break;
}
default: {
switch (get_typ(word)) {
case OP_ADD: printf("[+0x%07lX]", get_u24(word)); break;
case OP_SUB: printf("[-0x%07lX]", get_u24(word)); break;
case FP_SUB: printf("[:-0x%07lX]", get_u24(word)); break;
case OP_MUL: printf("[*0x%07lX]", get_u24(word)); break;
case OP_DIV: printf("[/0x%07lX]", get_u24(word)); break;
case FP_DIV: printf("[:/0x%07lX]", get_u24(word)); break;
case OP_REM: printf("[%%0x%07lX]", get_u24(word)); break;
case FP_REM: printf("[:%%0x%07lX]", get_u24(word)); break;
case OP_EQ: printf("[=0x%07lX]", get_u24(word)); break;
case OP_NEQ: printf("[!0x%07lX]", get_u24(word)); break;
case OP_LT: printf("[<0x%07lX]", get_u24(word)); break;
case OP_GT: printf("[>0x%07lX]", get_u24(word)); break;
case OP_AND: printf("[&0x%07lX]", get_u24(word)); break;
case OP_OR: printf("[|0x%07lX]", get_u24(word)); break;
case OP_XOR: printf("[^0x%07lX]", get_u24(word)); break;
case OP_SHL: printf("[<<0x%07lX]", get_u24(word)); break;
case FP_SHL: printf("[:<<0x%07lX]", get_u24(word)); break;
case OP_SHR: printf("[>>0x%07lX]", get_u24(word)); break;
case FP_SHR: printf("[:>>0x%07lX]", get_u24(word)); break;
default: printf("[?0x%07lX]", get_u24(word)); break;
}
break;
}
}
}
void pretty_print_port(Port port) {
Port stack[256];
stack[0] = port;
u32 len = 1;
u32 num = 0;
while (len > 0) {
Port cur = stack[--len];
switch (get_tag(cur)) {
case CON: {
Pair node = node_load(cur);
Port p2 = node.snd;
Port p1 = node.fst;
printf("(");
stack[len++] = new_num((u32)(')'));
stack[len++] = p2;
stack[len++] = new_num((u32)(' '));
stack[len++] = p1;
break;
}
case ERA: {
if ((cur & ~7) != 0) {
printf("%c", (char)cur & ~7);
} else {
printf("*");
}
break;
}
case VAR: {
Port got = vars_load(cur);
if (got != NONE) {
stack[len++] = got;
} else {
printf("x%lx", cur & ~7);
}
break;
}
case NUM: {
pretty_print_numb(get_num(cur));
break;
}
case DUP: {
Pair node = node_load(cur);
Port p2 = node.snd;
Port p1 = node.fst;
printf("{");
stack[len++] = new_num((u32)('}'));
stack[len++] = p2;
stack[len++] = new_num((u32)(' '));
stack[len++] = p1;
break;
}
case OPR: {
Pair node = node_load(cur);
Port p2 = node.snd;
Port p1 = node.fst;
printf("$(");
stack[len++] = new_num((u32)(')'));
stack[len++] = p2;
stack[len++] = new_num((u32)(' '));
stack[len++] = p1;
break;
}
case SWI: {
Pair node = node_load(cur);
Port p2 = node.snd;
Port p1 = node.fst;
printf("?(");
stack[len++] = new_num((u32)(')'));
stack[len++] = p2;
stack[len++] = new_num((u32)(' '));
stack[len++] = p1;
break;
}
}
}
}
// Main
// ----
// The Call Interaction.
bool CALL_main__C1(TM *tm, Port a, Port b);
bool CALL_sum(TM *tm, Port a, Port b);
bool CALL_main(TM *tm, Port a, Port b) {
if (get_tag(b) == DUP) {
return ERAS(tm, a, b);
}
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
if (0 || !v0 || !n0 || !n1) {
return FALSE;
}
vars_create(v0, NONE);
if (b != NONE) {
link(tm, new_port(VAR,v0), b);
} else {
b = new_port(VAR,v0);
}
node_create(n1, new_pair(new_ref(CALL_main__C1),new_port(VAR,v0)));
node_create(n0, new_pair(new_num(MAG),new_port(CON,n1)));
link(tm, new_ref(CALL_sum), new_port(CON,n0));
return TRUE;
}
bool CALL_down__C0(TM *tm, Port a, Port b);
bool CALL_down(TM *tm, Port a, Port b) {
if (get_tag(b) == DUP) {
return ERAS(tm, a, b);
}
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port v2 = vars_alloc(tm, &vl);
Port v3 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
Port n3 = node_alloc(tm, &nl);
Port n4 = node_alloc(tm, &nl);
Port n5 = node_alloc(tm, &nl);
Port n6 = node_alloc(tm, &nl);
Port n7 = node_alloc(tm, &nl);
Port n8 = node_alloc(tm, &nl);
if (0 || !v0 || !v1 || !v2 || !v3 || !n0 || !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8) {
return FALSE;
}
vars_create(v0, NONE);
vars_create(v1, NONE);
vars_create(v2, NONE);
vars_create(v3, NONE);
bool k1 = 0;
Pair k2 = emptyPair;
Port k3 = NONE;
Port k4 = NONE;
// fast anni
if (get_tag(b) == CON && !isEmpty(node_load(b))) {
tm->itrs += 1;
k1 = 1;
k2 = node_take(b);
k3 = k2.fst;
k4 = k2.snd;
}
bool k5 = 0;
Pair k6 = emptyPair;
Port k7 = NONE;
Port k8 = NONE;
// fast anni
if (get_tag(k4) == CON && !isEmpty(node_load(k4))) {
tm->itrs += 1;
k5 = 1;
k6 = node_take(k4);
k7 = k6.fst;
k8 = k6.snd;
}
bool k9 = 0;
Pair k10 = emptyPair;
Port k11 = NONE;
Port k12 = NONE;
// fast anni
if (get_tag(k8) == CON && !isEmpty(node_load(k8))) {
tm->itrs += 1;
k9 = 1;
k10 = node_take(k8);
k11 = k10.fst;
k12 = k10.snd;
}
if (k12 != NONE) {
link(tm, new_port(VAR,v3), k12);
} else {
k12 = new_port(VAR,v3);
}
if (k11 != NONE) {
link(tm, new_port(VAR,v1), k11);
} else {
k11 = new_port(VAR,v1);
}
if (!k9) {
node_create(n8, new_pair(k11,k12));
if (k8 != NONE) {
link(tm, new_port(CON,n8), k8);
} else {
k8 = new_port(CON,n8);
}
}
if (k7 != NONE) {
link(tm, new_port(VAR,v2), k7);
} else {
k7 = new_port(VAR,v2);
}
if (!k5) {
node_create(n7, new_pair(k7,k8));
if (k4 != NONE) {
link(tm, new_port(CON,n7), k4);
} else {
k4 = new_port(CON,n7);
}
}
node_create(n4, new_pair(erase,new_port(VAR,v0)));
node_create(n3, new_pair(new_port(VAR,v0),new_port(CON,n4)));
node_create(n2, new_pair(new_port(CON,n3),new_ref(CALL_down__C0)));
node_create(n6, new_pair(new_port(VAR,v2),new_port(VAR,v3)));
node_create(n5, new_pair(new_port(VAR,v1),new_port(CON,n6)));
node_create(n1, new_pair(new_port(CON,n2),new_port(CON,n5)));
if (k3 != NONE) {
link(tm, new_port(SWI,n1), k3);
} else {
k3 = new_port(SWI,n1);
}
if (!k1) {
node_create(n0, new_pair(k3,k4));
if (b != NONE) {
link(tm, new_port(CON,n0), b);
} else {
b = new_port(CON,n0);
}
}
return TRUE;
}
bool CALL_flow(TM *tm, Port a, Port b);
bool CALL_down__C0(TM *tm, Port a, Port b) {
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port v2 = vars_alloc(tm, &vl);
Port v3 = vars_alloc(tm, &vl);
Port v4 = vars_alloc(tm, &vl);
Port v5 = vars_alloc(tm, &vl);
Port v6 = vars_alloc(tm, &vl);
Port v7 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
Port n3 = node_alloc(tm, &nl);
Port n4 = node_alloc(tm, &nl);
Port n5 = node_alloc(tm, &nl);
Port n6 = node_alloc(tm, &nl);
Port n7 = node_alloc(tm, &nl);
Port n8 = node_alloc(tm, &nl);
Port n9 = node_alloc(tm, &nl);
Port na = node_alloc(tm, &nl);
Port nb = node_alloc(tm, &nl);
Port nc = node_alloc(tm, &nl);
if (0 || !v0 || !v1 || !v2 || !v3 || !v4 || !v5 || !v6 || !v7 || !n0 || !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n9 || !na || !nb || !nc) {
return FALSE;
}
vars_create(v0, NONE);
vars_create(v1, NONE);
vars_create(v2, NONE);
vars_create(v3, NONE);
vars_create(v4, NONE);
vars_create(v5, NONE);
vars_create(v6, NONE);
vars_create(v7, NONE);
bool k1 = 0;
Pair k2 = emptyPair;
Port k3 = NONE;
Port k4 = NONE;
// fast anni
if (get_tag(b) == CON && !isEmpty(node_load(b))) {
tm->itrs += 1;
k1 = 1;
k2 = node_take(b);
k3 = k2.fst;
k4 = k2.snd;
}
bool k5 = 0;
Pair k6 = emptyPair;
Port k7 = NONE;
Port k8 = NONE;
// fast anni
if (get_tag(k4) == CON && !isEmpty(node_load(k4))) {
tm->itrs += 1;
k5 = 1;
k6 = node_take(k4);
k7 = k6.fst;
k8 = k6.snd;
}
bool k9 = 0;
Pair k10 = emptyPair;
Port k11 = NONE;
Port k12 = NONE;
// fast anni
if (get_tag(k8) == CON && !isEmpty(node_load(k8))) {
tm->itrs += 1;
k9 = 1;
k10 = node_take(k8);
k11 = k10.fst;
k12 = k10.snd;
}
bool k13 = 0;
Pair k14 = emptyPair;
Port k15 = NONE;
Port k16 = NONE;
// fast anni
if (get_tag(k12) == CON && !isEmpty(node_load(k12))) {
tm->itrs += 1;
k13 = 1;
k14 = node_take(k12);
k15 = k14.fst;
k16 = k14.snd;
}
if (k16 != NONE) {
link(tm, new_port(VAR,v7), k16);
} else {
k16 = new_port(VAR,v7);
}
if (k15 != NONE) {
link(tm, new_port(VAR,v6), k15);
} else {
k15 = new_port(VAR,v6);
}
if (!k13) {
node_create(n6, new_pair(k15,k16));
if (k12 != NONE) {
link(tm, new_port(CON,n6), k12);
} else {
k12 = new_port(CON,n6);
}
}
bool k17 = 0;
Port k18 = NONE;
Port k19 = NONE;
// fast copy
if (get_tag(k11) == NUM) {
tm->itrs += 1;
k17 = 1;
k18 = k11;
k19 = k11;
}
if (k19 != NONE) {
link(tm, new_port(VAR,v5), k19);
} else {
k19 = new_port(VAR,v5);
}
if (k18 != NONE) {
link(tm, new_port(VAR,v4), k18);
} else {
k18 = new_port(VAR,v4);
}
if (!k17) {
node_create(n5, new_pair(k18,k19));
if (k11 != NONE) {
link(tm, new_port(DUP,n5), k11);
} else {
k11 = new_port(DUP,n5);
}
}
if (!k9) {
node_create(n4, new_pair(k11,k12));
if (k8 != NONE) {
link(tm, new_port(CON,n4), k8);
} else {
k8 = new_port(CON,n4);
}
}
bool k20 = 0;
Pair k21 = emptyPair;
Port k22 = NONE;
Port k23 = NONE;
// fast anni
if (get_tag(k7) == CON && !isEmpty(node_load(k7))) {
tm->itrs += 1;
k20 = 1;
k21 = node_take(k7);
k22 = k21.fst;
k23 = k21.snd;
}
if (k23 != NONE) {
link(tm, new_port(VAR,v3), k23);
} else {
k23 = new_port(VAR,v3);
}
if (k22 != NONE) {
link(tm, new_port(VAR,v2), k22);
} else {
k22 = new_port(VAR,v2);
}
if (!k20) {
node_create(n3, new_pair(k22,k23));
if (k7 != NONE) {
link(tm, new_port(CON,n3), k7);
} else {
k7 = new_port(CON,n3);
}
}
if (!k5) {
node_create(n2, new_pair(k7,k8));
if (k4 != NONE) {
link(tm, new_port(CON,n2), k4);
} else {
k4 = new_port(CON,n2);
}
}
bool k24 = 0;
Port k25 = NONE;
Port k26 = NONE;
// fast copy
if (get_tag(k3) == NUM) {
tm->itrs += 1;
k24 = 1;
k25 = k3;
k26 = k3;
}
if (k26 != NONE) {
link(tm, new_port(VAR,v1), k26);
} else {
k26 = new_port(VAR,v1);
}
if (k25 != NONE) {
link(tm, new_port(VAR,v0), k25);
} else {
k25 = new_port(VAR,v0);
}
if (!k24) {
node_create(n1, new_pair(k25,k26));
if (k3 != NONE) {
link(tm, new_port(DUP,n1), k3);
} else {
k3 = new_port(DUP,n1);
}
}
if (!k1) {
node_create(n0, new_pair(k3,k4));
if (b != NONE) {
link(tm, new_port(CON,n0), b);
} else {
b = new_port(CON,n0);
}
}
node_create(n9, new_pair(new_port(VAR,v2),new_port(VAR,v6)));
node_create(n8, new_pair(new_port(VAR,v4),new_port(CON,n9)));
node_create(n7, new_pair(new_port(VAR,v0),new_port(CON,n8)));
link(tm, new_ref(CALL_flow), new_port(CON,n7));
node_create(nc, new_pair(new_port(VAR,v3),new_port(VAR,v7)));
node_create(nb, new_pair(new_port(VAR,v5),new_port(CON,nc)));
node_create(na, new_pair(new_port(VAR,v1),new_port(CON,nb)));
link(tm, new_ref(CALL_flow), new_port(CON,na));
return TRUE;
}
bool CALL_flow__C0(TM *tm, Port a, Port b);
bool CALL_flow(TM *tm, Port a, Port b) {
if (get_tag(b) == DUP) {
return ERAS(tm, a, b);
}
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port v2 = vars_alloc(tm, &vl);
Port v3 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
Port n3 = node_alloc(tm, &nl);
Port n4 = node_alloc(tm, &nl);
Port n5 = node_alloc(tm, &nl);
Port n6 = node_alloc(tm, &nl);
Port n7 = node_alloc(tm, &nl);
Port n8 = node_alloc(tm, &nl);
if (0 || !v0 || !v1 || !v2 || !v3 || !n0 || !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8) {
return FALSE;
}
vars_create(v0, NONE);
vars_create(v1, NONE);
vars_create(v2, NONE);
vars_create(v3, NONE);
bool k1 = 0;
Pair k2 = emptyPair;
Port k3 = NONE;
Port k4 = NONE;
// fast anni
if (get_tag(b) == CON && !isEmpty(node_load(b))) {
tm->itrs += 1;
k1 = 1;
k2 = node_take(b);
k3 = k2.fst;
k4 = k2.snd;
}
bool k5 = 0;
Pair k6 = emptyPair;
Port k7 = NONE;
Port k8 = NONE;
// fast anni
if (get_tag(k4) == CON && !isEmpty(node_load(k4))) {
tm->itrs += 1;
k5 = 1;
k6 = node_take(k4);
k7 = k6.fst;
k8 = k6.snd;
}
bool k9 = 0;
Pair k10 = emptyPair;
Port k11 = NONE;
Port k12 = NONE;
// fast anni
if (get_tag(k8) == CON && !isEmpty(node_load(k8))) {
tm->itrs += 1;
k9 = 1;
k10 = node_take(k8);
k11 = k10.fst;
k12 = k10.snd;
}
if (k12 != NONE) {
link(tm, new_port(VAR,v3), k12);
} else {
k12 = new_port(VAR,v3);
}
if (k11 != NONE) {
link(tm, new_port(VAR,v1), k11);
} else {
k11 = new_port(VAR,v1);
}
if (!k9) {
node_create(n8, new_pair(k11,k12));
if (k8 != NONE) {
link(tm, new_port(CON,n8), k8);
} else {
k8 = new_port(CON,n8);
}
}
if (k7 != NONE) {
link(tm, new_port(VAR,v2), k7);
} else {
k7 = new_port(VAR,v2);
}
if (!k5) {
node_create(n7, new_pair(k7,k8));
if (k4 != NONE) {
link(tm, new_port(CON,n7), k4);
} else {
k4 = new_port(CON,n7);
}
}
node_create(n4, new_pair(erase,new_port(VAR,v0)));
node_create(n3, new_pair(new_port(VAR,v0),new_port(CON,n4)));
node_create(n2, new_pair(new_port(CON,n3),new_ref(CALL_flow__C0)));
node_create(n6, new_pair(new_port(VAR,v2),new_port(VAR,v3)));
node_create(n5, new_pair(new_port(VAR,v1),new_port(CON,n6)));
node_create(n1, new_pair(new_port(CON,n2),new_port(CON,n5)));
if (k3 != NONE) {
link(tm, new_port(SWI,n1), k3);
} else {
k3 = new_port(SWI,n1);
}
if (!k1) {
node_create(n0, new_pair(k3,k4));
if (b != NONE) {
link(tm, new_port(CON,n0), b);
} else {
b = new_port(CON,n0);
}
}
return TRUE;
}
bool CALL_warp(TM *tm, Port a, Port b);
bool CALL_flow__C0(TM *tm, Port a, Port b) {
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port v2 = vars_alloc(tm, &vl);
Port v3 = vars_alloc(tm, &vl);
Port v4 = vars_alloc(tm, &vl);
Port v5 = vars_alloc(tm, &vl);
Port v6 = vars_alloc(tm, &vl);
Port v7 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
Port n3 = node_alloc(tm, &nl);
Port n4 = node_alloc(tm, &nl);
Port n5 = node_alloc(tm, &nl);
Port n6 = node_alloc(tm, &nl);
Port n7 = node_alloc(tm, &nl);
Port n8 = node_alloc(tm, &nl);
Port n9 = node_alloc(tm, &nl);
Port na = node_alloc(tm, &nl);
Port nb = node_alloc(tm, &nl);
Port nc = node_alloc(tm, &nl);
Port nd = node_alloc(tm, &nl);
if (0 || !v0 || !v1 || !v2 || !v3 || !v4 || !v5 || !v6 || !v7 || !n0 || !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n9 || !na || !nb || !nc || !nd) {
return FALSE;
}
vars_create(v0, NONE);
vars_create(v1, NONE);
vars_create(v2, NONE);
vars_create(v3, NONE);
vars_create(v4, NONE);
vars_create(v5, NONE);
vars_create(v6, NONE);
vars_create(v7, NONE);
bool k1 = 0;
Pair k2 = emptyPair;
Port k3 = NONE;
Port k4 = NONE;
// fast anni
if (get_tag(b) == CON && !isEmpty(node_load(b))) {
tm->itrs += 1;
k1 = 1;
k2 = node_take(b);
k3 = k2.fst;
k4 = k2.snd;
}
bool k5 = 0;
Pair k6 = emptyPair;
Port k7 = NONE;
Port k8 = NONE;
// fast anni
if (get_tag(k4) == CON && !isEmpty(node_load(k4))) {
tm->itrs += 1;
k5 = 1;
k6 = node_take(k4);
k7 = k6.fst;
k8 = k6.snd;
}
bool k9 = 0;
Pair k10 = emptyPair;
Port k11 = NONE;
Port k12 = NONE;
// fast anni
if (get_tag(k8) == CON && !isEmpty(node_load(k8))) {
tm->itrs += 1;
k9 = 1;
k10 = node_take(k8);
k11 = k10.fst;
k12 = k10.snd;
}
if (k12 != NONE) {
link(tm, new_port(VAR,v6), k12);
} else {
k12 = new_port(VAR,v6);
}
bool k13 = 0;
Port k14 = NONE;
Port k15 = NONE;
// fast copy
if (get_tag(k11) == NUM) {
tm->itrs += 1;
k13 = 1;
k14 = k11;
k15 = k11;
}
if (k15 != NONE) {
link(tm, new_port(VAR,v5), k15);
} else {
k15 = new_port(VAR,v5);
}
if (k14 != NONE) {
link(tm, new_port(VAR,v4), k14);
} else {
k14 = new_port(VAR,v4);
}
if (!k13) {
node_create(n6, new_pair(k14,k15));
if (k11 != NONE) {
link(tm, new_port(DUP,n6), k11);
} else {
k11 = new_port(DUP,n6);
}
}
if (!k9) {
node_create(n5, new_pair(k11,k12));
if (k8 != NONE) {
link(tm, new_port(CON,n5), k8);
} else {
k8 = new_port(CON,n5);
}
}
bool k16 = 0;
Pair k17 = emptyPair;
Port k18 = NONE;
Port k19 = NONE;
// fast anni
if (get_tag(k7) == CON && !isEmpty(node_load(k7))) {
tm->itrs += 1;
k16 = 1;
k17 = node_take(k7);
k18 = k17.fst;
k19 = k17.snd;
}
if (k19 != NONE) {
link(tm, new_port(VAR,v3), k19);
} else {
k19 = new_port(VAR,v3);
}
if (k18 != NONE) {
link(tm, new_port(VAR,v2), k18);
} else {
k18 = new_port(VAR,v2);
}
if (!k16) {
node_create(n4, new_pair(k18,k19));
if (k7 != NONE) {
link(tm, new_port(CON,n4), k7);
} else {
k7 = new_port(CON,n4);
}
}
if (!k5) {
node_create(n3, new_pair(k7,k8));
if (k4 != NONE) {
link(tm, new_port(CON,n3), k4);
} else {
k4 = new_port(CON,n3);
}
}
bool k20 = 0;
Port k21 = NONE;
Port k22 = NONE;
// fast copy
if (get_tag(k3) == NUM) {
tm->itrs += 1;
k20 = 1;
k21 = k3;
k22 = k3;
}
if (k22 != NONE) {
link(tm, new_port(VAR,v1), k22);
} else {
k22 = new_port(VAR,v1);
}
bool k23 = 0;
Port k24 = NONE;
// fast oper
if (get_tag(k21) == NUM && get_tag(new_num(0x00000024)) == NUM) {
tm->itrs += 1;
k23 = 1;
k24 = new_num(operate(k21, new_num(0x00000024)));
}
if (k24 != NONE) {
link(tm, new_port(VAR,v0), k24);
} else {
k24 = new_port(VAR,v0);
}
if (!k23) {
node_create(n2, new_pair(new_num(0x00000024),k24));
if (k21 != NONE) {
link(tm, new_port(OPR, n2), k21);
} else {
k21 = new_port(OPR, n2);
}
}
if (!k20) {
node_create(n1, new_pair(k21,k22));
if (k3 != NONE) {
link(tm, new_port(DUP,n1), k3);
} else {
k3 = new_port(DUP,n1);
}
}
if (!k1) {
node_create(n0, new_pair(k3,k4));
if (b != NONE) {
link(tm, new_port(CON,n0), b);
} else {
b = new_port(CON,n0);
}
}
node_create(n9, new_pair(new_port(VAR,v7),new_port(VAR,v6)));
node_create(n8, new_pair(new_port(VAR,v4),new_port(CON,n9)));
node_create(n7, new_pair(new_port(VAR,v0),new_port(CON,n8)));
link(tm, new_ref(CALL_down), new_port(CON,n7));
node_create(nd, new_pair(new_port(VAR,v3),new_port(VAR,v7)));
node_create(nc, new_pair(new_port(VAR,v2),new_port(CON,nd)));
node_create(nb, new_pair(new_port(VAR,v5),new_port(CON,nc)));
node_create(na, new_pair(new_port(VAR,v1),new_port(CON,nb)));
link(tm, new_ref(CALL_warp), new_port(CON,na));
return TRUE;
}
bool CALL_gen__bend0(TM *tm, Port a, Port b);
bool CALL_gen(TM *tm, Port a, Port b) {
if (get_tag(b) == DUP) {
return ERAS(tm, a, b);
}
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
if (0 || !v0 || !v1 || !n0 || !n1 || !n2) {
return FALSE;
}
vars_create(v0, NONE);
vars_create(v1, NONE);
bool k1 = 0;
Pair k2 = emptyPair;
Port k3 = NONE;
Port k4 = NONE;
// fast anni
if (get_tag(b) == CON && !isEmpty(node_load(b))) {
tm->itrs += 1;
k1 = 1;
k2 = node_take(b);
k3 = k2.fst;
k4 = k2.snd;
}
if (k4 != NONE) {
link(tm, new_port(VAR,v1), k4);
} else {
k4 = new_port(VAR,v1);
}
if (k3 != NONE) {
link(tm, new_port(VAR,v0), k3);
} else {
k3 = new_port(VAR,v0);
}
if (!k1) {
node_create(n0, new_pair(k3,k4));
if (b != NONE) {
link(tm, new_port(CON,n0), b);
} else {
b = new_port(CON,n0);
}
}
node_create(n2, new_pair(new_num(0x00000001),new_port(VAR,v1)));
node_create(n1, new_pair(new_port(VAR,v0),new_port(CON,n2)));
link(tm, new_ref(CALL_gen__bend0), new_port(CON,n1));
return TRUE;
}
bool CALL_gen__bend0__C0(TM *tm, Port a, Port b);
bool CALL_gen__bend0(TM *tm, Port a, Port b) {
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port v2 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
Port n3 = node_alloc(tm, &nl);
Port n4 = node_alloc(tm, &nl);
Port n5 = node_alloc(tm, &nl);
Port n6 = node_alloc(tm, &nl);
if (0 || !v0 || !v1 || !v2 || !n0 || !n1 || !n2 || !n3 || !n4 || !n5 || !n6) {
return FALSE;
}
vars_create(v0, NONE);
vars_create(v1, NONE);
vars_create(v2, NONE);
bool k1 = 0;
Pair k2 = emptyPair;
Port k3 = NONE;
Port k4 = NONE;
// fast anni
if (get_tag(b) == CON && !isEmpty(node_load(b))) {
tm->itrs += 1;
k1 = 1;
k2 = node_take(b);
k3 = k2.fst;
k4 = k2.snd;
}
if (k4 != NONE) {
link(tm, new_port(VAR,v2), k4);
} else {
k4 = new_port(VAR,v2);
}
bool k5 = 0;
Port k6 = NONE;
Port k7 = NONE;
// fast copy
if (get_tag(k3) == NUM) {
tm->itrs += 1;
k5 = 1;
k6 = k3;
k7 = k3;
}
if (k7 != NONE) {
link(tm, new_port(VAR,v1), k7);
} else {
k7 = new_port(VAR,v1);
}
node_create(n5, new_pair(new_port(VAR,v0),new_port(VAR,v0)));
node_create(n4, new_pair(erase,new_port(CON,n5)));
node_create(n3, new_pair(new_port(CON,n4),new_ref(CALL_gen__bend0__C0)));
node_create(n6, new_pair(new_port(VAR,v1),new_port(VAR,v2)));
node_create(n2, new_pair(new_port(CON,n3),new_port(CON,n6)));
if (k6 != NONE) {
link(tm, new_port(SWI,n2), k6);
} else {
k6 = new_port(SWI,n2);
}
if (!k5) {
node_create(n1, new_pair(k6,k7));
if (k3 != NONE) {
link(tm, new_port(DUP,n1), k3);
} else {
k3 = new_port(DUP,n1);
}
}
if (!k1) {
node_create(n0, new_pair(k3,k4));
if (b != NONE) {
link(tm, new_port(CON,n0), b);
} else {
b = new_port(CON,n0);
}
}
return TRUE;
}
bool CALL_gen__bend0__C0(TM *tm, Port a, Port b) {
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port v2 = vars_alloc(tm, &vl);
Port v3 = vars_alloc(tm, &vl);
Port v4 = vars_alloc(tm, &vl);
Port v5 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
Port n3 = node_alloc(tm, &nl);
Port n4 = node_alloc(tm, &nl);
Port n5 = node_alloc(tm, &nl);
Port n6 = node_alloc(tm, &nl);
Port n7 = node_alloc(tm, &nl);
Port n8 = node_alloc(tm, &nl);
Port n9 = node_alloc(tm, &nl);
Port na = node_alloc(tm, &nl);
Port nb = node_alloc(tm, &nl);
Port nc = node_alloc(tm, &nl);
Port nd = node_alloc(tm, &nl);
Port ne = node_alloc(tm, &nl);
if (0 || !v0 || !v1 || !v2 || !v3 || !v4 || !v5 || !n0 || !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n9 || !na || !nb || !nc || !nd || !ne) {
return FALSE;
}
vars_create(v0, NONE);
vars_create(v1, NONE);
vars_create(v2, NONE);
vars_create(v3, NONE);
vars_create(v4, NONE);
vars_create(v5, NONE);
bool k1 = 0;
Pair k2 = emptyPair;
Port k3 = NONE;
Port k4 = NONE;
// fast anni
if (get_tag(b) == CON && !isEmpty(node_load(b))) {
tm->itrs += 1;
k1 = 1;
k2 = node_take(b);
k3 = k2.fst;
k4 = k2.snd;
}
bool k5 = 0;
Pair k6 = emptyPair;
Port k7 = NONE;
Port k8 = NONE;
// fast anni
if (get_tag(k4) == CON && !isEmpty(node_load(k4))) {
tm->itrs += 1;
k5 = 1;
k6 = node_take(k4);
k7 = k6.fst;
k8 = k6.snd;
}
bool k9 = 0;
Pair k10 = emptyPair;
Port k11 = NONE;
Port k12 = NONE;
// fast anni
if (get_tag(k8) == CON && !isEmpty(node_load(k8))) {
tm->itrs += 1;
k9 = 1;
k10 = node_take(k8);
k11 = k10.fst;
k12 = k10.snd;
}
bool k13 = 0;
Pair k14 = emptyPair;
Port k15 = NONE;
Port k16 = NONE;
// fast anni
if (get_tag(k12) == CON && !isEmpty(node_load(k12))) {
tm->itrs += 1;
k13 = 1;
k14 = node_take(k12);
k15 = k14.fst;
k16 = k14.snd;
}
if (k16 != NONE) {
link(tm, new_port(VAR,v5), k16);
} else {
k16 = new_port(VAR,v5);
}
if (k15 != NONE) {
link(tm, new_port(VAR,v4), k15);
} else {
k15 = new_port(VAR,v4);
}
if (!k13) {
node_create(na, new_pair(k15,k16));
if (k12 != NONE) {
link(tm, new_port(CON,na), k12);
} else {
k12 = new_port(CON,na);
}
}
bool k17 = 0;
Port k18 = NONE;
Port k19 = NONE;
// fast copy
if (get_tag(k11) == NUM) {
tm->itrs += 1;
k17 = 1;
k18 = k11;
k19 = k11;
}
bool k20 = 0;
Port k21 = NONE;
// fast oper
if (get_tag(k19) == NUM && get_tag(new_num(0x00000047)) == NUM) {
tm->itrs += 1;
k20 = 1;
k21 = new_num(operate(k19, new_num(0x00000047)));
}
if (k21 != NONE) {
link(tm, new_port(VAR,v3), k21);
} else {
k21 = new_port(VAR,v3);
}
if (!k20) {
node_create(n9, new_pair(new_num(0x00000047),k21));
if (k19 != NONE) {
link(tm, new_port(OPR, n9), k19);
} else {
k19 = new_port(OPR, n9);
}
}
bool k22 = 0;
Port k23 = NONE;
// fast oper
if (get_tag(k18) == NUM && get_tag(new_num(0x00000047)) == NUM) {
tm->itrs += 1;
k22 = 1;
k23 = new_num(operate(k18, new_num(0x00000047)));
}
bool k24 = 0;
Port k25 = NONE;
// fast oper
if (get_tag(k23) == NUM && get_tag(new_num(0x00000024)) == NUM) {
tm->itrs += 1;
k24 = 1;
k25 = new_num(operate(k23, new_num(0x00000024)));
}
if (k25 != NONE) {
link(tm, new_port(VAR,v2), k25);
} else {
k25 = new_port(VAR,v2);
}
if (!k24) {
node_create(n8, new_pair(new_num(0x00000024),k25));
if (k23 != NONE) {
link(tm, new_port(OPR, n8), k23);
} else {
k23 = new_port(OPR, n8);
}
}
if (!k22) {
node_create(n7, new_pair(new_num(0x00000047),k23));
if (k18 != NONE) {
link(tm, new_port(OPR, n7), k18);
} else {
k18 = new_port(OPR, n7);
}
}
if (!k17) {
node_create(n6, new_pair(k18,k19));
if (k11 != NONE) {
link(tm, new_port(DUP,n6), k11);
} else {
k11 = new_port(DUP,n6);
}
}
if (!k9) {
node_create(n5, new_pair(k11,k12));
if (k8 != NONE) {
link(tm, new_port(CON,n5), k8);
} else {
k8 = new_port(CON,n5);
}
}
bool k26 = 0;
Port k27 = NONE;
Port k28 = NONE;
// fast copy
if (get_tag(k7) == NUM) {
tm->itrs += 1;
k26 = 1;
k27 = k7;
k28 = k7;
}
bool k29 = 0;
Port k30 = NONE;
// fast oper
if (get_tag(k28) == NUM && get_tag(new_num(0x00000026)) == NUM) {
tm->itrs += 1;
k29 = 1;
k30 = new_num(operate(k28, new_num(0x00000026)));
}
if (k30 != NONE) {
link(tm, new_port(VAR,v1), k30);
} else {
k30 = new_port(VAR,v1);
}
if (!k29) {
node_create(n4, new_pair(new_num(0x00000026),k30));
if (k28 != NONE) {
link(tm, new_port(OPR, n4), k28);
} else {
k28 = new_port(OPR, n4);
}
}
bool k31 = 0;
Port k32 = NONE;
// fast oper
if (get_tag(k27) == NUM && get_tag(new_num(0x00000026)) == NUM) {
tm->itrs += 1;
k31 = 1;
k32 = new_num(operate(k27, new_num(0x00000026)));
}
if (k32 != NONE) {
link(tm, new_port(VAR,v0), k32);
} else {
k32 = new_port(VAR,v0);
}
if (!k31) {
node_create(n3, new_pair(new_num(0x00000026),k32));
if (k27 != NONE) {
link(tm, new_port(OPR, n3), k27);
} else {
k27 = new_port(OPR, n3);
}
}
if (!k26) {
node_create(n2, new_pair(k27,k28));
if (k7 != NONE) {
link(tm, new_port(DUP,n2), k7);
} else {
k7 = new_port(DUP,n2);
}
}
if (!k5) {
node_create(n1, new_pair(k7,k8));
if (k4 != NONE) {
link(tm, new_port(CON,n1), k4);
} else {
k4 = new_port(CON,n1);
}
}
// fast void
if (get_tag(k3) == ERA || get_tag(k3) == NUM) {
tm->itrs += 1;
} else {
if (k3 != NONE) {
link(tm, erase, k3);
} else {
k3 = erase;
}
}
if (!k1) {
node_create(n0, new_pair(k3,k4));
if (b != NONE) {
link(tm, new_port(CON,n0), b);
} else {
b = new_port(CON,n0);
}
}
node_create(nc, new_pair(new_port(VAR,v2),new_port(VAR,v4)));
node_create(nb, new_pair(new_port(VAR,v0),new_port(CON,nc)));
link(tm, new_ref(CALL_gen__bend0), new_port(CON,nb));
node_create(ne, new_pair(new_port(VAR,v3),new_port(VAR,v5)));
node_create(nd, new_pair(new_port(VAR,v1),new_port(CON,ne)));
link(tm, new_ref(CALL_gen__bend0), new_port(CON,nd));
return TRUE;
}
bool CALL_main__C0(TM *tm, Port a, Port b) {
if (get_tag(b) == DUP) {
return ERAS(tm, a, b);
}
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
if (0 || !v0 || !n0) {
return FALSE;
}
vars_create(v0, NONE);
if (b != NONE) {
link(tm, new_port(VAR,v0), b);
} else {
b = new_port(VAR,v0);
}
node_create(n0, new_pair(new_num(MAG),new_port(VAR,v0)));
link(tm, new_ref(CALL_gen), new_port(CON,n0));
return TRUE;
}
bool CALL_sort(TM *tm, Port a, Port b);
bool CALL_main__C1(TM *tm, Port a, Port b) {
if (get_tag(b) == DUP) {
return ERAS(tm, a, b);
}
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
if (0 || !v0 || !n0 || !n1 || !n2) {
return FALSE;
}
vars_create(v0, NONE);
if (b != NONE) {
link(tm, new_port(VAR,v0), b);
} else {
b = new_port(VAR,v0);
}
node_create(n2, new_pair(new_ref(CALL_main__C0),new_port(VAR,v0)));
node_create(n1, new_pair(new_num(0x00000001),new_port(CON,n2)));
node_create(n0, new_pair(new_num(MAG),new_port(CON,n1)));
link(tm, new_ref(CALL_sort), new_port(CON,n0));
return TRUE;
}
bool CALL_sort__C0(TM *tm, Port a, Port b);
bool CALL_sort(TM *tm, Port a, Port b) {
if (get_tag(b) == DUP) {
return ERAS(tm, a, b);
}
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port v2 = vars_alloc(tm, &vl);
Port v3 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
Port n3 = node_alloc(tm, &nl);
Port n4 = node_alloc(tm, &nl);
Port n5 = node_alloc(tm, &nl);
Port n6 = node_alloc(tm, &nl);
Port n7 = node_alloc(tm, &nl);
Port n8 = node_alloc(tm, &nl);
if (0 || !v0 || !v1 || !v2 || !v3 || !n0 || !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8) {
return FALSE;
}
vars_create(v0, NONE);
vars_create(v1, NONE);
vars_create(v2, NONE);
vars_create(v3, NONE);
bool k1 = 0;
Pair k2 = emptyPair;
Port k3 = NONE;
Port k4 = NONE;
// fast anni
if (get_tag(b) == CON && !isEmpty(node_load(b))) {
tm->itrs += 1;
k1 = 1;
k2 = node_take(b);
k3 = k2.fst;
k4 = k2.snd;
}
bool k5 = 0;
Pair k6 = emptyPair;
Port k7 = NONE;
Port k8 = NONE;
// fast anni
if (get_tag(k4) == CON && !isEmpty(node_load(k4))) {
tm->itrs += 1;
k5 = 1;
k6 = node_take(k4);
k7 = k6.fst;
k8 = k6.snd;
}
bool k9 = 0;
Pair k10 = emptyPair;
Port k11 = NONE;
Port k12 = NONE;
// fast anni
if (get_tag(k8) == CON && !isEmpty(node_load(k8))) {
tm->itrs += 1;
k9 = 1;
k10 = node_take(k8);
k11 = k10.fst;
k12 = k10.snd;
}
if (k12 != NONE) {
link(tm, new_port(VAR,v3), k12);
} else {
k12 = new_port(VAR,v3);
}
if (k11 != NONE) {
link(tm, new_port(VAR,v1), k11);
} else {
k11 = new_port(VAR,v1);
}
if (!k9) {
node_create(n8, new_pair(k11,k12));
if (k8 != NONE) {
link(tm, new_port(CON,n8), k8);
} else {
k8 = new_port(CON,n8);
}
}
if (k7 != NONE) {
link(tm, new_port(VAR,v2), k7);
} else {
k7 = new_port(VAR,v2);
}
if (!k5) {
node_create(n7, new_pair(k7,k8));
if (k4 != NONE) {
link(tm, new_port(CON,n7), k4);
} else {
k4 = new_port(CON,n7);
}
}
node_create(n4, new_pair(erase,new_port(VAR,v0)));
node_create(n3, new_pair(new_port(VAR,v0),new_port(CON,n4)));
node_create(n2, new_pair(new_port(CON,n3),new_ref(CALL_sort__C0)));
node_create(n6, new_pair(new_port(VAR,v2),new_port(VAR,v3)));
node_create(n5, new_pair(new_port(VAR,v1),new_port(CON,n6)));
node_create(n1, new_pair(new_port(CON,n2),new_port(CON,n5)));
if (k3 != NONE) {
link(tm, new_port(SWI,n1), k3);
} else {
k3 = new_port(SWI,n1);
}
if (!k1) {
node_create(n0, new_pair(k3,k4));
if (b != NONE) {
link(tm, new_port(CON,n0), b);
} else {
b = new_port(CON,n0);
}
}
return TRUE;
}
bool CALL_sort__C0(TM *tm, Port a, Port b) {
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port v2 = vars_alloc(tm, &vl);
Port v3 = vars_alloc(tm, &vl);
Port v4 = vars_alloc(tm, &vl);
Port v5 = vars_alloc(tm, &vl);
Port v6 = vars_alloc(tm, &vl);
Port v7 = vars_alloc(tm, &vl);
Port v8 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
Port n3 = node_alloc(tm, &nl);
Port n4 = node_alloc(tm, &nl);
Port n5 = node_alloc(tm, &nl);
Port n6 = node_alloc(tm, &nl);
Port n7 = node_alloc(tm, &nl);
Port n8 = node_alloc(tm, &nl);
Port n9 = node_alloc(tm, &nl);
Port na = node_alloc(tm, &nl);
Port nb = node_alloc(tm, &nl);
Port nc = node_alloc(tm, &nl);
Port nd = node_alloc(tm, &nl);
Port ne = node_alloc(tm, &nl);
Port nf = node_alloc(tm, &nl);
Port n10 = node_alloc(tm, &nl);
if (0 || !v0 || !v1 || !v2 || !v3 || !v4 || !v5 || !v6 || !v7 || !v8 || !n0 || !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n9 || !na || !nb || !nc || !nd || !ne || !nf || !n10) {
return FALSE;
}
vars_create(v0, NONE);
vars_create(v1, NONE);
vars_create(v2, NONE);
vars_create(v3, NONE);
vars_create(v4, NONE);
vars_create(v5, NONE);
vars_create(v6, NONE);
vars_create(v7, NONE);
vars_create(v8, NONE);
bool k1 = 0;
Pair k2 = emptyPair;
Port k3 = NONE;
Port k4 = NONE;
// fast anni
if (get_tag(b) == CON && !isEmpty(node_load(b))) {
tm->itrs += 1;
k1 = 1;
k2 = node_take(b);
k3 = k2.fst;
k4 = k2.snd;
}
bool k5 = 0;
Pair k6 = emptyPair;
Port k7 = NONE;
Port k8 = NONE;
// fast anni
if (get_tag(k4) == CON && !isEmpty(node_load(k4))) {
tm->itrs += 1;
k5 = 1;
k6 = node_take(k4);
k7 = k6.fst;
k8 = k6.snd;
}
bool k9 = 0;
Pair k10 = emptyPair;
Port k11 = NONE;
Port k12 = NONE;
// fast anni
if (get_tag(k8) == CON && !isEmpty(node_load(k8))) {
tm->itrs += 1;
k9 = 1;
k10 = node_take(k8);
k11 = k10.fst;
k12 = k10.snd;
}
if (k12 != NONE) {
link(tm, new_port(VAR,v6), k12);
} else {
k12 = new_port(VAR,v6);
}
if (k11 != NONE) {
link(tm, new_port(VAR,v5), k11);
} else {
k11 = new_port(VAR,v5);
}
if (!k9) {
node_create(n6, new_pair(k11,k12));
if (k8 != NONE) {
link(tm, new_port(CON,n6), k8);
} else {
k8 = new_port(CON,n6);
}
}
bool k13 = 0;
Pair k14 = emptyPair;
Port k15 = NONE;
Port k16 = NONE;
// fast anni
if (get_tag(k7) == CON && !isEmpty(node_load(k7))) {
tm->itrs += 1;
k13 = 1;
k14 = node_take(k7);
k15 = k14.fst;
k16 = k14.snd;
}
if (k16 != NONE) {
link(tm, new_port(VAR,v4), k16);
} else {
k16 = new_port(VAR,v4);
}
if (k15 != NONE) {
link(tm, new_port(VAR,v3), k15);
} else {
k15 = new_port(VAR,v3);
}
if (!k13) {
node_create(n5, new_pair(k15,k16));
if (k7 != NONE) {
link(tm, new_port(CON,n5), k7);
} else {
k7 = new_port(CON,n5);
}
}
if (!k5) {
node_create(n4, new_pair(k7,k8));
if (k4 != NONE) {
link(tm, new_port(CON,n4), k4);
} else {
k4 = new_port(CON,n4);
}
}
bool k17 = 0;
Port k18 = NONE;
Port k19 = NONE;
// fast copy
if (get_tag(k3) == NUM) {
tm->itrs += 1;
k17 = 1;
k18 = k3;
k19 = k3;
}
bool k20 = 0;
Port k21 = NONE;
Port k22 = NONE;
// fast copy
if (get_tag(k19) == NUM) {
tm->itrs += 1;
k20 = 1;
k21 = k19;
k22 = k19;
}
if (k22 != NONE) {
link(tm, new_port(VAR,v2), k22);
} else {
k22 = new_port(VAR,v2);
}
if (k21 != NONE) {
link(tm, new_port(VAR,v1), k21);
} else {
k21 = new_port(VAR,v1);
}
if (!k20) {
node_create(n3, new_pair(k21,k22));
if (k19 != NONE) {
link(tm, new_port(DUP,n3), k19);
} else {
k19 = new_port(DUP,n3);
}
}
bool k23 = 0;
Port k24 = NONE;
// fast oper
if (get_tag(k18) == NUM && get_tag(new_num(0x00000024)) == NUM) {
tm->itrs += 1;
k23 = 1;
k24 = new_num(operate(k18, new_num(0x00000024)));
}
if (k24 != NONE) {
link(tm, new_port(VAR,v0), k24);
} else {
k24 = new_port(VAR,v0);
}
if (!k23) {
node_create(n2, new_pair(new_num(0x00000024),k24));
if (k18 != NONE) {
link(tm, new_port(OPR, n2), k18);
} else {
k18 = new_port(OPR, n2);
}
}
if (!k17) {
node_create(n1, new_pair(k18,k19));
if (k3 != NONE) {
link(tm, new_port(DUP,n1), k3);
} else {
k3 = new_port(DUP,n1);
}
}
if (!k1) {
node_create(n0, new_pair(k3,k4));
if (b != NONE) {
link(tm, new_port(CON,n0), b);
} else {
b = new_port(CON,n0);
}
}
node_create(na, new_pair(new_port(VAR,v7),new_port(VAR,v8)));
node_create(n9, new_pair(new_port(CON,na),new_port(VAR,v6)));
node_create(n8, new_pair(new_port(VAR,v5),new_port(CON,n9)));
node_create(n7, new_pair(new_port(VAR,v0),new_port(CON,n8)));
link(tm, new_ref(CALL_flow), new_port(CON,n7));
node_create(nd, new_pair(new_port(VAR,v3),new_port(VAR,v7)));
node_create(nc, new_pair(new_num(0x00000001),new_port(CON,nd)));
node_create(nb, new_pair(new_port(VAR,v1),new_port(CON,nc)));
link(tm, new_ref(CALL_sort), new_port(CON,nb));
node_create(n10, new_pair(new_port(VAR,v4),new_port(VAR,v8)));
node_create(nf, new_pair(new_num(0x00000021),new_port(CON,n10)));
node_create(ne, new_pair(new_port(VAR,v2),new_port(CON,nf)));
link(tm, new_ref(CALL_sort), new_port(CON,ne));
return TRUE;
}
bool CALL_sum__C0(TM *tm, Port a, Port b);
bool CALL_sum(TM *tm, Port a, Port b) {
if (get_tag(b) == DUP) {
return ERAS(tm, a, b);
}
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
Port n3 = node_alloc(tm, &nl);
if (0 || !v0 || !v1 || !n0 || !n1 || !n2 || !n3) {
return FALSE;
}
vars_create(v0, NONE);
vars_create(v1, NONE);
bool k1 = 0;
Pair k2 = emptyPair;
Port k5 = NONE;
Port k3 = NONE;
Port k4 = NONE;
//fast switch
if (get_tag(b) == CON) {
k2 = node_load(b);
k5 = enter(k2.fst);
if (get_tag(k5) == NUM) {
tm->itrs += 3;
vars_take(v1);
k1 = 1;
if (get_u24(get_num(k5)) == 0) {
node_take(b);
k3 = k2.snd;
k4 = erase;
} else {
node_store(b, new_pair(new_num(new_u24(get_u24(get_num(k5))-1)), k2.snd));
k3 = erase;
k4 = b;
}
} else {
node_store(b, new_pair(k5,k2.snd));
}
}
bool k6 = 0;
Pair k7 = emptyPair;
Port k8 = NONE;
Port k9 = NONE;
// fast anni
if (get_tag(k3) == CON && !isEmpty(node_load(k3))) {
tm->itrs += 1;
k6 = 1;
k7 = node_take(k3);
k8 = k7.fst;
k9 = k7.snd;
}
if (k9 != NONE) {
link(tm, new_port(VAR,v0), k9);
} else {
k9 = new_port(VAR,v0);
}
if (k8 != NONE) {
link(tm, new_port(VAR,v0), k8);
} else {
k8 = new_port(VAR,v0);
}
if (!k6) {
node_create(n3, new_pair(k8,k9));
if (k3 != NONE) {
link(tm, new_port(CON,n3), k3);
} else {
k3 = new_port(CON,n3);
}
}
if (k4 != NONE) {
link(tm, new_ref(CALL_sum__C0), k4);
} else {
k4 = new_ref(CALL_sum__C0);
}
if (!k1) {
node_create(n0, new_pair(new_port(SWI,n1),new_port(VAR,v1)));
node_create(n1, new_pair(new_port(CON,n2),new_port(VAR,v1)));
node_create(n2, new_pair(k3,k4));
if (b != NONE) {
link(tm, new_port(CON, n0), b);
} else {
b = new_port(CON, n0);
}
}
return TRUE;
}
bool CALL_sum__C0(TM *tm, Port a, Port b) {
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port v2 = vars_alloc(tm, &vl);
Port v3 = vars_alloc(tm, &vl);
Port v4 = vars_alloc(tm, &vl);
Port v5 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
Port n3 = node_alloc(tm, &nl);
Port n4 = node_alloc(tm, &nl);
Port n5 = node_alloc(tm, &nl);
Port n6 = node_alloc(tm, &nl);
Port n7 = node_alloc(tm, &nl);
Port n8 = node_alloc(tm, &nl);
Port n9 = node_alloc(tm, &nl);
if (0 || !v0 || !v1 || !v2 || !v3 || !v4 || !v5 || !n0 || !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n9) {
return FALSE;
}
vars_create(v0, NONE);
vars_create(v1, NONE);
vars_create(v2, NONE);
vars_create(v3, NONE);
vars_create(v4, NONE);
vars_create(v5, NONE);
bool k1 = 0;
Pair k2 = emptyPair;
Port k3 = NONE;
Port k4 = NONE;
// fast anni
if (get_tag(b) == CON && !isEmpty(node_load(b))) {
tm->itrs += 1;
k1 = 1;
k2 = node_take(b);
k3 = k2.fst;
k4 = k2.snd;
}
bool k5 = 0;
Pair k6 = emptyPair;
Port k7 = NONE;
Port k8 = NONE;
// fast anni
if (get_tag(k4) == CON && !isEmpty(node_load(k4))) {
tm->itrs += 1;
k5 = 1;
k6 = node_take(k4);
k7 = k6.fst;
k8 = k6.snd;
}
if (k8 != NONE) {
link(tm, new_port(VAR,v4), k8);
} else {
k8 = new_port(VAR,v4);
}
bool k9 = 0;
Pair k10 = emptyPair;
Port k11 = NONE;
Port k12 = NONE;
// fast anni
if (get_tag(k7) == CON && !isEmpty(node_load(k7))) {
tm->itrs += 1;
k9 = 1;
k10 = node_take(k7);
k11 = k10.fst;
k12 = k10.snd;
}
if (k12 != NONE) {
link(tm, new_port(VAR,v3), k12);
} else {
k12 = new_port(VAR,v3);
}
if (k11 != NONE) {
link(tm, new_port(VAR,v2), k11);
} else {
k11 = new_port(VAR,v2);
}
if (!k9) {
node_create(n3, new_pair(k11,k12));
if (k7 != NONE) {
link(tm, new_port(CON,n3), k7);
} else {
k7 = new_port(CON,n3);
}
}
if (!k5) {
node_create(n2, new_pair(k7,k8));
if (k4 != NONE) {
link(tm, new_port(CON,n2), k4);
} else {
k4 = new_port(CON,n2);
}
}
bool k13 = 0;
Port k14 = NONE;
Port k15 = NONE;
// fast copy
if (get_tag(k3) == NUM) {
tm->itrs += 1;
k13 = 1;
k14 = k3;
k15 = k3;
}
if (k15 != NONE) {
link(tm, new_port(VAR,v1), k15);
} else {
k15 = new_port(VAR,v1);
}
if (k14 != NONE) {
link(tm, new_port(VAR,v0), k14);
} else {
k14 = new_port(VAR,v0);
}
if (!k13) {
node_create(n1, new_pair(k14,k15));
if (k3 != NONE) {
link(tm, new_port(DUP,n1), k3);
} else {
k3 = new_port(DUP,n1);
}
}
if (!k1) {
node_create(n0, new_pair(k3,k4));
if (b != NONE) {
link(tm, new_port(CON,n0), b);
} else {
b = new_port(CON,n0);
}
}
node_create(n7, new_pair(new_port(VAR,v5),new_port(VAR,v4)));
node_create(n6, new_pair(new_num(0x00000080),new_port(OPR,n7)));
node_create(n5, new_pair(new_port(VAR,v2),new_port(OPR,n6)));
node_create(n4, new_pair(new_port(VAR,v0),new_port(CON,n5)));
link(tm, new_ref(CALL_sum), new_port(CON,n4));
node_create(n9, new_pair(new_port(VAR,v3),new_port(VAR,v5)));
node_create(n8, new_pair(new_port(VAR,v1),new_port(CON,n9)));
link(tm, new_ref(CALL_sum), new_port(CON,n8));
return TRUE;
}
bool CALL_swap__C0(TM *tm, Port a, Port b);
bool CALL_swap__C1(TM *tm, Port a, Port b);
bool CALL_swap(TM *tm, Port a, Port b) {
if (get_tag(b) == DUP) {
return ERAS(tm, a, b);
}
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port v2 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
Port n3 = node_alloc(tm, &nl);
Port n4 = node_alloc(tm, &nl);
Port n5 = node_alloc(tm, &nl);
Port n6 = node_alloc(tm, &nl);
if (0 || !v0 || !v1 || !v2 || !n0 || !n1 || !n2 || !n3 || !n4 || !n5 || !n6) {
return FALSE;
}
vars_create(v0, NONE);
vars_create(v1, NONE);
vars_create(v2, NONE);
bool k1 = 0;
Pair k2 = emptyPair;
Port k3 = NONE;
Port k4 = NONE;
// fast anni
if (get_tag(b) == CON && !isEmpty(node_load(b))) {
tm->itrs += 1;
k1 = 1;
k2 = node_take(b);
k3 = k2.fst;
k4 = k2.snd;
}
bool k5 = 0;
Pair k6 = emptyPair;
Port k7 = NONE;
Port k8 = NONE;
// fast anni
if (get_tag(k4) == CON && !isEmpty(node_load(k4))) {
tm->itrs += 1;
k5 = 1;
k6 = node_take(k4);
k7 = k6.fst;
k8 = k6.snd;
}
bool k9 = 0;
Pair k10 = emptyPair;
Port k11 = NONE;
Port k12 = NONE;
// fast anni
if (get_tag(k8) == CON && !isEmpty(node_load(k8))) {
tm->itrs += 1;
k9 = 1;
k10 = node_take(k8);
k11 = k10.fst;
k12 = k10.snd;
}
if (k12 != NONE) {
link(tm, new_port(VAR,v2), k12);
} else {
k12 = new_port(VAR,v2);
}
if (k11 != NONE) {
link(tm, new_port(VAR,v0), k11);
} else {
k11 = new_port(VAR,v0);
}
if (!k9) {
node_create(n6, new_pair(k11,k12));
if (k8 != NONE) {
link(tm, new_port(CON,n6), k8);
} else {
k8 = new_port(CON,n6);
}
}
if (k7 != NONE) {
link(tm, new_port(VAR,v1), k7);
} else {
k7 = new_port(VAR,v1);
}
if (!k5) {
node_create(n5, new_pair(k7,k8));
if (k4 != NONE) {
link(tm, new_port(CON,n5), k4);
} else {
k4 = new_port(CON,n5);
}
}
node_create(n2, new_pair(new_ref(CALL_swap__C0),new_ref(CALL_swap__C1)));
node_create(n4, new_pair(new_port(VAR,v1),new_port(VAR,v2)));
node_create(n3, new_pair(new_port(VAR,v0),new_port(CON,n4)));
node_create(n1, new_pair(new_port(CON,n2),new_port(CON,n3)));
if (k3 != NONE) {
link(tm, new_port(SWI,n1), k3);
} else {
k3 = new_port(SWI,n1);
}
if (!k1) {
node_create(n0, new_pair(k3,k4));
if (b != NONE) {
link(tm, new_port(CON,n0), b);
} else {
b = new_port(CON,n0);
}
}
return TRUE;
}
bool CALL_swap__C0(TM *tm, Port a, Port b) {
if (get_tag(b) == DUP) {
return ERAS(tm, a, b);
}
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
if (0 || !v0 || !v1 || !n0 || !n1 || !n2) {
return FALSE;
}
vars_create(v0, NONE);
vars_create(v1, NONE);
bool k1 = 0;
Pair k2 = emptyPair;
Port k3 = NONE;
Port k4 = NONE;
// fast anni
if (get_tag(b) == CON && !isEmpty(node_load(b))) {
tm->itrs += 1;
k1 = 1;
k2 = node_take(b);
k3 = k2.fst;
k4 = k2.snd;
}
bool k5 = 0;
Pair k6 = emptyPair;
Port k7 = NONE;
Port k8 = NONE;
// fast anni
if (get_tag(k4) == CON && !isEmpty(node_load(k4))) {
tm->itrs += 1;
k5 = 1;
k6 = node_take(k4);
k7 = k6.fst;
k8 = k6.snd;
}
bool k9 = 0;
Pair k10 = emptyPair;
Port k11 = NONE;
Port k12 = NONE;
// fast anni
if (get_tag(k8) == CON && !isEmpty(node_load(k8))) {
tm->itrs += 1;
k9 = 1;
k10 = node_take(k8);
k11 = k10.fst;
k12 = k10.snd;
}
if (k12 != NONE) {
link(tm, new_port(VAR,v0), k12);
} else {
k12 = new_port(VAR,v0);
}
if (k11 != NONE) {
link(tm, new_port(VAR,v1), k11);
} else {
k11 = new_port(VAR,v1);
}
if (!k9) {
node_create(n2, new_pair(k11,k12));
if (k8 != NONE) {
link(tm, new_port(CON,n2), k8);
} else {
k8 = new_port(CON,n2);
}
}
if (k7 != NONE) {
link(tm, new_port(VAR,v1), k7);
} else {
k7 = new_port(VAR,v1);
}
if (!k5) {
node_create(n1, new_pair(k7,k8));
if (k4 != NONE) {
link(tm, new_port(CON,n1), k4);
} else {
k4 = new_port(CON,n1);
}
}
if (k3 != NONE) {
link(tm, new_port(VAR,v0), k3);
} else {
k3 = new_port(VAR,v0);
}
if (!k1) {
node_create(n0, new_pair(k3,k4));
if (b != NONE) {
link(tm, new_port(CON,n0), b);
} else {
b = new_port(CON,n0);
}
}
return TRUE;
}
bool CALL_swap__C1(TM *tm, Port a, Port b) {
if (get_tag(b) == DUP) {
return ERAS(tm, a, b);
}
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
Port n3 = node_alloc(tm, &nl);
if (0 || !v0 || !v1 || !n0 || !n1 || !n2 || !n3) {
return FALSE;
}
vars_create(v0, NONE);
vars_create(v1, NONE);
bool k1 = 0;
Pair k2 = emptyPair;
Port k3 = NONE;
Port k4 = NONE;
// fast anni
if (get_tag(b) == CON && !isEmpty(node_load(b))) {
tm->itrs += 1;
k1 = 1;
k2 = node_take(b);
k3 = k2.fst;
k4 = k2.snd;
}
bool k5 = 0;
Pair k6 = emptyPair;
Port k7 = NONE;
Port k8 = NONE;
// fast anni
if (get_tag(k4) == CON && !isEmpty(node_load(k4))) {
tm->itrs += 1;
k5 = 1;
k6 = node_take(k4);
k7 = k6.fst;
k8 = k6.snd;
}
bool k9 = 0;
Pair k10 = emptyPair;
Port k11 = NONE;
Port k12 = NONE;
// fast anni
if (get_tag(k8) == CON && !isEmpty(node_load(k8))) {
tm->itrs += 1;
k9 = 1;
k10 = node_take(k8);
k11 = k10.fst;
k12 = k10.snd;
}
bool k13 = 0;
Pair k14 = emptyPair;
Port k15 = NONE;
Port k16 = NONE;
// fast anni
if (get_tag(k12) == CON && !isEmpty(node_load(k12))) {
tm->itrs += 1;
k13 = 1;
k14 = node_take(k12);
k15 = k14.fst;
k16 = k14.snd;
}
if (k16 != NONE) {
link(tm, new_port(VAR,v1), k16);
} else {
k16 = new_port(VAR,v1);
}
if (k15 != NONE) {
link(tm, new_port(VAR,v0), k15);
} else {
k15 = new_port(VAR,v0);
}
if (!k13) {
node_create(n3, new_pair(k15,k16));
if (k12 != NONE) {
link(tm, new_port(CON,n3), k12);
} else {
k12 = new_port(CON,n3);
}
}
if (k11 != NONE) {
link(tm, new_port(VAR,v1), k11);
} else {
k11 = new_port(VAR,v1);
}
if (!k9) {
node_create(n2, new_pair(k11,k12));
if (k8 != NONE) {
link(tm, new_port(CON,n2), k8);
} else {
k8 = new_port(CON,n2);
}
}
if (k7 != NONE) {
link(tm, new_port(VAR,v0), k7);
} else {
k7 = new_port(VAR,v0);
}
if (!k5) {
node_create(n1, new_pair(k7,k8));
if (k4 != NONE) {
link(tm, new_port(CON,n1), k4);
} else {
k4 = new_port(CON,n1);
}
}
// fast void
if (get_tag(k3) == ERA || get_tag(k3) == NUM) {
tm->itrs += 1;
} else {
if (k3 != NONE) {
link(tm, erase, k3);
} else {
k3 = erase;
}
}
if (!k1) {
node_create(n0, new_pair(k3,k4));
if (b != NONE) {
link(tm, new_port(CON,n0), b);
} else {
b = new_port(CON,n0);
}
}
return TRUE;
}
bool CALL_warp__C0(TM *tm, Port a, Port b);
bool CALL_warp__C1(TM *tm, Port a, Port b);
bool CALL_warp(TM *tm, Port a, Port b) {
if (get_tag(b) == DUP) {
return ERAS(tm, a, b);
}
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port v2 = vars_alloc(tm, &vl);
Port v3 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
Port n3 = node_alloc(tm, &nl);
Port n4 = node_alloc(tm, &nl);
Port n5 = node_alloc(tm, &nl);
Port n6 = node_alloc(tm, &nl);
Port n7 = node_alloc(tm, &nl);
Port n8 = node_alloc(tm, &nl);
if (0 || !v0 || !v1 || !v2 || !v3 || !n0 || !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8) {
return FALSE;
}
vars_create(v0, NONE);
vars_create(v1, NONE);
vars_create(v2, NONE);
vars_create(v3, NONE);
bool k1 = 0;
Pair k2 = emptyPair;
Port k3 = NONE;
Port k4 = NONE;
// fast anni
if (get_tag(b) == CON && !isEmpty(node_load(b))) {
tm->itrs += 1;
k1 = 1;
k2 = node_take(b);
k3 = k2.fst;
k4 = k2.snd;
}
bool k5 = 0;
Pair k6 = emptyPair;
Port k7 = NONE;
Port k8 = NONE;
// fast anni
if (get_tag(k4) == CON && !isEmpty(node_load(k4))) {
tm->itrs += 1;
k5 = 1;
k6 = node_take(k4);
k7 = k6.fst;
k8 = k6.snd;
}
bool k9 = 0;
Pair k10 = emptyPair;
Port k11 = NONE;
Port k12 = NONE;
// fast anni
if (get_tag(k8) == CON && !isEmpty(node_load(k8))) {
tm->itrs += 1;
k9 = 1;
k10 = node_take(k8);
k11 = k10.fst;
k12 = k10.snd;
}
bool k13 = 0;
Pair k14 = emptyPair;
Port k15 = NONE;
Port k16 = NONE;
// fast anni
if (get_tag(k12) == CON && !isEmpty(node_load(k12))) {
tm->itrs += 1;
k13 = 1;
k14 = node_take(k12);
k15 = k14.fst;
k16 = k14.snd;
}
if (k16 != NONE) {
link(tm, new_port(VAR,v3), k16);
} else {
k16 = new_port(VAR,v3);
}
if (k15 != NONE) {
link(tm, new_port(VAR,v0), k15);
} else {
k15 = new_port(VAR,v0);
}
if (!k13) {
node_create(n8, new_pair(k15,k16));
if (k12 != NONE) {
link(tm, new_port(CON,n8), k12);
} else {
k12 = new_port(CON,n8);
}
}
if (k11 != NONE) {
link(tm, new_port(VAR,v1), k11);
} else {
k11 = new_port(VAR,v1);
}
if (!k9) {
node_create(n7, new_pair(k11,k12));
if (k8 != NONE) {
link(tm, new_port(CON,n7), k8);
} else {
k8 = new_port(CON,n7);
}
}
if (k7 != NONE) {
link(tm, new_port(VAR,v2), k7);
} else {
k7 = new_port(VAR,v2);
}
if (!k5) {
node_create(n6, new_pair(k7,k8));
if (k4 != NONE) {
link(tm, new_port(CON,n6), k4);
} else {
k4 = new_port(CON,n6);
}
}
node_create(n2, new_pair(new_ref(CALL_warp__C0),new_ref(CALL_warp__C1)));
node_create(n5, new_pair(new_port(VAR,v2),new_port(VAR,v3)));
node_create(n4, new_pair(new_port(VAR,v1),new_port(CON,n5)));
node_create(n3, new_pair(new_port(VAR,v0),new_port(CON,n4)));
node_create(n1, new_pair(new_port(CON,n2),new_port(CON,n3)));
if (k3 != NONE) {
link(tm, new_port(SWI,n1), k3);
} else {
k3 = new_port(SWI,n1);
}
if (!k1) {
node_create(n0, new_pair(k3,k4));
if (b != NONE) {
link(tm, new_port(CON,n0), b);
} else {
b = new_port(CON,n0);
}
}
return TRUE;
}
bool CALL_warp__C0(TM *tm, Port a, Port b) {
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port v2 = vars_alloc(tm, &vl);
Port v3 = vars_alloc(tm, &vl);
Port v4 = vars_alloc(tm, &vl);
Port v5 = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
Port n3 = node_alloc(tm, &nl);
Port n4 = node_alloc(tm, &nl);
Port n5 = node_alloc(tm, &nl);
Port n6 = node_alloc(tm, &nl);
Port n7 = node_alloc(tm, &nl);
Port n8 = node_alloc(tm, &nl);
Port n9 = node_alloc(tm, &nl);
Port na = node_alloc(tm, &nl);
Port nb = node_alloc(tm, &nl);
if (0 || !v0 || !v1 || !v2 || !v3 || !v4 || !v5 || !n0 || !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n9 || !na || !nb) {
return FALSE;
}
vars_create(v0, NONE);
vars_create(v1, NONE);
vars_create(v2, NONE);
vars_create(v3, NONE);
vars_create(v4, NONE);
vars_create(v5, NONE);
bool k1 = 0;
Pair k2 = emptyPair;
Port k3 = NONE;
Port k4 = NONE;
// fast anni
if (get_tag(b) == CON && !isEmpty(node_load(b))) {
tm->itrs += 1;
k1 = 1;
k2 = node_take(b);
k3 = k2.fst;
k4 = k2.snd;
}
bool k5 = 0;
Pair k6 = emptyPair;
Port k7 = NONE;
Port k8 = NONE;
// fast anni
if (get_tag(k4) == CON && !isEmpty(node_load(k4))) {
tm->itrs += 1;
k5 = 1;
k6 = node_take(k4);
k7 = k6.fst;
k8 = k6.snd;
}
bool k9 = 0;
Pair k10 = emptyPair;
Port k11 = NONE;
Port k12 = NONE;
// fast anni
if (get_tag(k8) == CON && !isEmpty(node_load(k8))) {
tm->itrs += 1;
k9 = 1;
k10 = node_take(k8);
k11 = k10.fst;
k12 = k10.snd;
}
if (k12 != NONE) {
link(tm, new_port(VAR,v5), k12);
} else {
k12 = new_port(VAR,v5);
}
bool k13 = 0;
Port k14 = NONE;
// fast oper
if (get_tag(k11) == NUM && get_tag(new_num(0x00000080)) == NUM) {
tm->itrs += 1;
k13 = 1;
k14 = new_num(operate(k11, new_num(0x00000080)));
}
bool k15 = 0;
Port k16 = NONE;
// fast oper
if (get_tag(k14) == NUM && get_tag(new_port(VAR,v2)) == NUM) {
tm->itrs += 1;
k15 = 1;
k16 = new_num(operate(k14, new_port(VAR,v2)));
}
if (k16 != NONE) {
link(tm, new_port(VAR,v4), k16);
} else {
k16 = new_port(VAR,v4);
}
if (!k15) {
node_create(n8, new_pair(new_port(VAR,v2),k16));
if (k14 != NONE) {
link(tm, new_port(OPR, n8), k14);
} else {
k14 = new_port(OPR, n8);
}
}
if (!k13) {
node_create(n7, new_pair(new_num(0x00000080),k14));
if (k11 != NONE) {
link(tm, new_port(OPR, n7), k11);
} else {
k11 = new_port(OPR, n7);
}
}
if (!k9) {
node_create(n6, new_pair(k11,k12));
if (k8 != NONE) {
link(tm, new_port(CON,n6), k8);
} else {
k8 = new_port(CON,n6);
}
}
bool k17 = 0;
Port k18 = NONE;
Port k19 = NONE;
// fast copy
if (get_tag(k7) == NUM) {
tm->itrs += 1;
k17 = 1;
k18 = k7;
k19 = k7;
}
if (k19 != NONE) {
link(tm, new_port(VAR,v3), k19);
} else {
k19 = new_port(VAR,v3);
}
bool k20 = 0;
Port k21 = NONE;
// fast oper
if (get_tag(k18) == NUM && get_tag(new_num(0x000001e0)) == NUM) {
tm->itrs += 1;
k20 = 1;
k21 = new_num(operate(k18, new_num(0x000001e0)));
}
bool k22 = 0;
Port k23 = NONE;
// fast oper
if (get_tag(k21) == NUM && get_tag(new_port(VAR,v0)) == NUM) {
tm->itrs += 1;
k22 = 1;
k23 = new_num(operate(k21, new_port(VAR,v0)));
}
if (k23 != NONE) {
link(tm, new_port(VAR,v2), k23);
} else {
k23 = new_port(VAR,v2);
}
if (!k22) {
node_create(n5, new_pair(new_port(VAR,v0),k23));
if (k21 != NONE) {
link(tm, new_port(OPR, n5), k21);
} else {
k21 = new_port(OPR, n5);
}
}
if (!k20) {
node_create(n4, new_pair(new_num(0x000001e0),k21));
if (k18 != NONE) {
link(tm, new_port(OPR, n4), k18);
} else {
k18 = new_port(OPR, n4);
}
}
if (!k17) {
node_create(n3, new_pair(k18,k19));
if (k7 != NONE) {
link(tm, new_port(DUP,n3), k7);
} else {
k7 = new_port(DUP,n3);
}
}
if (!k5) {
node_create(n2, new_pair(k7,k8));
if (k4 != NONE) {
link(tm, new_port(CON,n2), k4);
} else {
k4 = new_port(CON,n2);
}
}
bool k24 = 0;
Port k25 = NONE;
Port k26 = NONE;
// fast copy
if (get_tag(k3) == NUM) {
tm->itrs += 1;
k24 = 1;
k25 = k3;
k26 = k3;
}
if (k26 != NONE) {
link(tm, new_port(VAR,v1), k26);
} else {
k26 = new_port(VAR,v1);
}
if (k25 != NONE) {
link(tm, new_port(VAR,v0), k25);
} else {
k25 = new_port(VAR,v0);
}
if (!k24) {
node_create(n1, new_pair(k25,k26));
if (k3 != NONE) {
link(tm, new_port(DUP,n1), k3);
} else {
k3 = new_port(DUP,n1);
}
}
if (!k1) {
node_create(n0, new_pair(k3,k4));
if (b != NONE) {
link(tm, new_port(CON,n0), b);
} else {
b = new_port(CON,n0);
}
}
node_create(nb, new_pair(new_port(VAR,v1),new_port(VAR,v5)));
node_create(na, new_pair(new_port(VAR,v3),new_port(CON,nb)));
node_create(n9, new_pair(new_port(VAR,v4),new_port(CON,na)));
link(tm, new_ref(CALL_swap), new_port(CON,n9));
return TRUE;
}
bool CALL_warp__C1(TM *tm, Port a, Port b) {
u32 vl = 0;
u32 nl = 0;
Port v0 = vars_alloc(tm, &vl);
Port v1 = vars_alloc(tm, &vl);
Port v2 = vars_alloc(tm, &vl);
Port v3 = vars_alloc(tm, &vl);
Port v4 = vars_alloc(tm, &vl);
Port v5 = vars_alloc(tm, &vl);
Port v6 = vars_alloc(tm, &vl);
Port v7 = vars_alloc(tm, &vl);
Port v8 = vars_alloc(tm, &vl);
Port v9 = vars_alloc(tm, &vl);
Port va = vars_alloc(tm, &vl);
Port vb = vars_alloc(tm, &vl);
Port n0 = node_alloc(tm, &nl);
Port n1 = node_alloc(tm, &nl);
Port n2 = node_alloc(tm, &nl);
Port n3 = node_alloc(tm, &nl);
Port n4 = node_alloc(tm, &nl);
Port n5 = node_alloc(tm, &nl);
Port n6 = node_alloc(tm, &nl);
Port n7 = node_alloc(tm, &nl);
Port n8 = node_alloc(tm, &nl);
Port n9 = node_alloc(tm, &nl);
Port na = node_alloc(tm, &nl);
Port nb = node_alloc(tm, &nl);
Port nc = node_alloc(tm, &nl);
Port nd = node_alloc(tm, &nl);
Port ne = node_alloc(tm, &nl);
Port nf = node_alloc(tm, &nl);
Port n10 = node_alloc(tm, &nl);
Port n11 = node_alloc(tm, &nl);
Port n12 = node_alloc(tm, &nl);
Port n13 = node_alloc(tm, &nl);
Port n14 = node_alloc(tm, &nl);
if (0 || !v0 || !v1 || !v2 || !v3 || !v4 || !v5 || !v6 || !v7 || !v8 || !v9 || !va || !vb || !n0 || !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n9 || !na || !nb || !nc || !nd || !ne || !nf || !n10 || !n11 || !n12 || !n13 || !n14) {
return FALSE;
}
vars_create(v0, NONE);
vars_create(v1, NONE);
vars_create(v2, NONE);
vars_create(v3, NONE);
vars_create(v4, NONE);
vars_create(v5, NONE);
vars_create(v6, NONE);
vars_create(v7, NONE);
vars_create(v8, NONE);
vars_create(v9, NONE);
vars_create(va, NONE);
vars_create(vb, NONE);
bool k1 = 0;
Pair k2 = emptyPair;
Port k3 = NONE;
Port k4 = NONE;
// fast anni
if (get_tag(b) == CON && !isEmpty(node_load(b))) {
tm->itrs += 1;
k1 = 1;
k2 = node_take(b);
k3 = k2.fst;
k4 = k2.snd;
}
bool k5 = 0;
Pair k6 = emptyPair;
Port k7 = NONE;
Port k8 = NONE;
// fast anni
if (get_tag(k4) == CON && !isEmpty(node_load(k4))) {
tm->itrs += 1;
k5 = 1;
k6 = node_take(k4);
k7 = k6.fst;
k8 = k6.snd;
}
bool k9 = 0;
Pair k10 = emptyPair;
Port k11 = NONE;
Port k12 = NONE;
// fast anni
if (get_tag(k8) == CON && !isEmpty(node_load(k8))) {
tm->itrs += 1;
k9 = 1;
k10 = node_take(k8);
k11 = k10.fst;
k12 = k10.snd;
}
bool k13 = 0;
Pair k14 = emptyPair;
Port k15 = NONE;
Port k16 = NONE;
// fast anni
if (get_tag(k12) == CON && !isEmpty(node_load(k12))) {
tm->itrs += 1;
k13 = 1;
k14 = node_take(k12);
k15 = k14.fst;
k16 = k14.snd;
}
bool k17 = 0;
Pair k18 = emptyPair;
Port k19 = NONE;
Port k20 = NONE;
// fast anni
if (get_tag(k16) == CON && !isEmpty(node_load(k16))) {
tm->itrs += 1;
k17 = 1;
k18 = node_take(k16);
k19 = k18.fst;
k20 = k18.snd;
}
bool k21 = 0;
Pair k22 = emptyPair;
Port k23 = NONE;
Port k24 = NONE;
// fast anni
if (get_tag(k20) == CON && !isEmpty(node_load(k20))) {
tm->itrs += 1;
k21 = 1;
k22 = node_take(k20);
k23 = k22.fst;
k24 = k22.snd;
}
if (k24 != NONE) {
link(tm, new_port(VAR,vb), k24);
} else {
k24 = new_port(VAR,vb);
}
if (k23 != NONE) {
link(tm, new_port(VAR,va), k23);
} else {
k23 = new_port(VAR,va);
}
if (!k21) {
node_create(na, new_pair(k23,k24));
if (k20 != NONE) {
link(tm, new_port(CON,na), k20);
} else {
k20 = new_port(CON,na);
}
}
bool k25 = 0;
Pair k26 = emptyPair;
Port k27 = NONE;
Port k28 = NONE;
// fast anni
if (get_tag(k19) == CON && !isEmpty(node_load(k19))) {
tm->itrs += 1;
k25 = 1;
k26 = node_take(k19);
k27 = k26.fst;
k28 = k26.snd;
}
if (k28 != NONE) {
link(tm, new_port(VAR,v9), k28);
} else {
k28 = new_port(VAR,v9);
}
if (k27 != NONE) {
link(tm, new_port(VAR,v8), k27);
} else {
k27 = new_port(VAR,v8);
}
if (!k25) {
node_create(n9, new_pair(k27,k28));
if (k19 != NONE) {
link(tm, new_port(CON,n9), k19);
} else {
k19 = new_port(CON,n9);
}
}
if (!k17) {
node_create(n8, new_pair(k19,k20));
if (k16 != NONE) {
link(tm, new_port(CON,n8), k16);
} else {
k16 = new_port(CON,n8);
}
}
bool k29 = 0;
Port k30 = NONE;
Port k31 = NONE;
// fast copy
if (get_tag(k15) == NUM) {
tm->itrs += 1;
k29 = 1;
k30 = k15;
k31 = k15;
}
if (k31 != NONE) {
link(tm, new_port(VAR,v7), k31);
} else {
k31 = new_port(VAR,v7);
}
if (k30 != NONE) {
link(tm, new_port(VAR,v6), k30);
} else {
k30 = new_port(VAR,v6);
}
if (!k29) {
node_create(n7, new_pair(k30,k31));
if (k15 != NONE) {
link(tm, new_port(DUP,n7), k15);
} else {
k15 = new_port(DUP,n7);
}
}
if (!k13) {
node_create(n6, new_pair(k15,k16));
if (k12 != NONE) {
link(tm, new_port(CON,n6), k12);
} else {
k12 = new_port(CON,n6);
}
}
bool k32 = 0;
Pair k33 = emptyPair;
Port k34 = NONE;
Port k35 = NONE;
// fast anni
if (get_tag(k11) == CON && !isEmpty(node_load(k11))) {
tm->itrs += 1;
k32 = 1;
k33 = node_take(k11);
k34 = k33.fst;
k35 = k33.snd;
}
if (k35 != NONE) {
link(tm, new_port(VAR,v5), k35);
} else {
k35 = new_port(VAR,v5);
}
if (k34 != NONE) {
link(tm, new_port(VAR,v4), k34);
} else {
k34 = new_port(VAR,v4);
}
if (!k32) {
node_create(n5, new_pair(k34,k35));
if (k11 != NONE) {
link(tm, new_port(CON,n5), k11);
} else {
k11 = new_port(CON,n5);
}
}
if (!k9) {
node_create(n4, new_pair(k11,k12));
if (k8 != NONE) {
link(tm, new_port(CON,n4), k8);
} else {
k8 = new_port(CON,n4);
}
}
bool k36 = 0;
Pair k37 = emptyPair;
Port k38 = NONE;
Port k39 = NONE;
// fast anni
if (get_tag(k7) == CON && !isEmpty(node_load(k7))) {
tm->itrs += 1;
k36 = 1;
k37 = node_take(k7);
k38 = k37.fst;
k39 = k37.snd;
}
if (k39 != NONE) {
link(tm, new_port(VAR,v3), k39);
} else {
k39 = new_port(VAR,v3);
}
if (k38 != NONE) {
link(tm, new_port(VAR,v2), k38);
} else {
k38 = new_port(VAR,v2);
}
if (!k36) {
node_create(n3, new_pair(k38,k39));
if (k7 != NONE) {
link(tm, new_port(CON,n3), k7);
} else {
k7 = new_port(CON,n3);
}
}
if (!k5) {
node_create(n2, new_pair(k7,k8));
if (k4 != NONE) {
link(tm, new_port(CON,n2), k4);
} else {
k4 = new_port(CON,n2);
}
}
bool k40 = 0;
Port k41 = NONE;
Port k42 = NONE;
// fast copy
if (get_tag(k3) == NUM) {
tm->itrs += 1;
k40 = 1;
k41 = k3;
k42 = k3;
}
if (k42 != NONE) {
link(tm, new_port(VAR,v1), k42);
} else {
k42 = new_port(VAR,v1);
}
if (k41 != NONE) {
link(tm, new_port(VAR,v0), k41);
} else {
k41 = new_port(VAR,v0);
}
if (!k40) {
node_create(n1, new_pair(k41,k42));
if (k3 != NONE) {
link(tm, new_port(DUP,n1), k3);
} else {
k3 = new_port(DUP,n1);
}
}
if (!k1) {
node_create(n0, new_pair(k3,k4));
if (b != NONE) {
link(tm, new_port(CON,n0), b);
} else {
b = new_port(CON,n0);
}
}
node_create(nf, new_pair(new_port(VAR,v9),new_port(VAR,vb)));
node_create(ne, new_pair(new_port(VAR,v3),new_port(CON,nf)));
node_create(nd, new_pair(new_port(VAR,v5),new_port(CON,ne)));
node_create(nc, new_pair(new_port(VAR,v7),new_port(CON,nd)));
node_create(nb, new_pair(new_port(VAR,v1),new_port(CON,nc)));
link(tm, new_ref(CALL_warp), new_port(CON,nb));
node_create(n14, new_pair(new_port(VAR,v8),new_port(VAR,va)));
node_create(n13, new_pair(new_port(VAR,v2),new_port(CON,n14)));
node_create(n12, new_pair(new_port(VAR,v4),new_port(CON,n13)));
node_create(n11, new_pair(new_port(VAR,v6),new_port(CON,n12)));
node_create(n10, new_pair(new_port(VAR,v0),new_port(CON,n11)));
link(tm, new_ref(CALL_warp), new_port(CON,n10));
return TRUE;
}
void hvm_c(u64* book_buffer) {
Port answer = NONE;
// Creates static TMs
alloc_static_tms();
// Starts the timer
u64 start = time64();
// GMem
globalNet = malloc(sizeof(Net));
net_init();
// Creates an initial redex that calls main
CALL_main(tm[0], new_ref(CALL_main), new_port(VAR, (Port)&answer));
// Normalizes and runs IO
normalize();
// Prints the result
printf("Result: ");
pretty_print_port(enter(new_port(VAR, (Port)&answer)));
printf("\n");
// Stops the timer
double duration = (time64() - start) / 1000000000.0; // seconds
// Prints interactions and time
u64 itrs = atomic_load(&globalNet->itrs);
printf("- ITRS: %" PRIu64 "\n", itrs);
printf("- TIME: %.2fs\n", duration);
printf("- MIPS: %.2f\n", (double)itrs / duration / 1000000.0);
// Frees everything
free_static_tms();
free(globalNet);
}
int main() {
printf("Port size: %lu\n", sizeof(Port));
hvm_c((u64*)NULL);
return 0;
}
@jduey
Copy link
Author

jduey commented Jun 24, 2024

A 64-bit HVM implementation. The biggest change is that Ports are now 64-bits wide. This means they can hold a machine pointer. So instead of holding an index into the node or var arrays, a Port now points directly to the node or var. Also, I defined the interactionFn type, so REF Ports point directly to the function that should be called instead of to an index that needs to be switched to look up which function to call. Numbers are also 56 bits wide.

@jduey
Copy link
Author

jduey commented Jun 24, 2024

Compile it using:

clang -g -march=native -lpthread -latomic -lm bitonic.c

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment