Skip to content

Commit

Permalink
2024/01/29 - Some thinking on runtime/compiler differences
Browse files Browse the repository at this point in the history
  • Loading branch information
FadiShawki committed Jan 29, 2024
1 parent 84b11c3 commit 63b939b
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 89 deletions.
22 changes: 20 additions & 2 deletions environments/javascript/@orbitmines/rays/src/Ray.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
import Ray from "./Ray";
import rays from "../index";

describe("Ray", () => {

describe(".Function", () => {
describe(".Instance", () => {
test(".te", () => {
{
// "new Ray.vertex()()" vs "new Ray.vertex()"
const A = new Ray.vertex();
const B = new Ray.vertex();

A.compose(B);
}
{
const ray = Ray.size(2);
}
{
const ray = Ray.array([undefined, undefined]);

}
{
const ray = Ray.boolean();
}

});
test(".traverse", () => {
const events: any[] = [];
const ray = Ray.array([]);
Expand All @@ -15,7 +33,7 @@ describe("Ray", () => {
// ray()()()()();
//
ray.debug(
(event) => {
(event: Ray.Debug.Event) => {
events.push(event);
},
() => {
Expand Down
151 changes: 81 additions & 70 deletions environments/javascript/@orbitmines/rays/src/Ray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,6 @@ namespace Ray {
/** Storage/Movement operations which need to be implemented. */
& { [TKey in keyof Ray.Op.Impl<Ray.Any>]: Ray.Any }

export type Constructor = {
initial?: Ray.Any,
self?: Ray.Any,
terminal?: Ray.Any,

proxy?: ProxyHandler<Ray.Any>,
debug?: Debug.Listener,
}

export const New = (constructor?: Ray.Constructor): Ray.Any => Ray.Instance.New(constructor).proxy;

export namespace Debug {
export type Event = { event: string, self: Ray.Any, context: any };
export type Listener = (event: Event) => void;
Expand All @@ -48,29 +37,72 @@ namespace Ray {
*/
// export const None: Ray.FunctionConstructor<Ray.Any> = Ray.Function.CachedAfterUse(Ray.New);

export class Instance extends JS.Class.Instance<Ray.Any> {
// export class Object {
//
// // TODO: Could copy?
// get initial(): Ray.Any { return this._initial(); } set initial(initial: Ray.Any) { this._initial = initial; } protected _initial: Ray.Any;
// get self(): Ray.Any { return this._self(); } set self(self: Ray.Any) { this._self = self; } protected _self: Ray.Any;
// get terminal(): Ray.Any { return this._terminal(); } set terminal(terminal: Ray.Any) { this._terminal = terminal; } protected _terminal: Ray.Any;
//
// protected constructor({ initial, self, terminal }: { initial?: Ray.Any, self?: Ray.Any, terminal?: Ray.Any } = {}) {
//
// this._initial = initial ?? Ray.none.memoized;
// this._self = self ?? Ray.self_reference;
// this._terminal = terminal ?? Ray.none.memoized;
// }
// }

/** A simplistic compiler for Ray */
export namespace Compiler { // TODO Ray is Compiler

static New = (constructor?: Ray.Constructor): Ray.Instance => new Ray.Instance(constructor);
/**
* TODO: Compiler could have things like other composed rays which tell it cares about the other (even if that's correct or not??)
*
*
* TODO: Do I want to keep the is_equiv/is_composed pattern? Or simplify to one of the two?
*
* // TODO: NEVER DIRECTLY EXECUTE, ONLY AFTER CHAIN OF FUNCS, possibly arbitrarily LAZY
*
* TODO
* - Compose empty as first element? Disregard none to first elemn? Or not??
*
* TODO; Impl
* - Generally, return something which knows where all continuations are.
* - Generator/step function/... ; with no assumption of halting, but allow to hook into any step.
* - Cache:
* - Control of (non-/)lazyness of functions
* - None as, first time called, memoize func.
* - Perhaps locally cache (for stuff like count?) - no way to ensure globally coherence
* - a.orbit() -> a.orbit(a)
* // TODO: Should be automatic? is_orbit() or any method without arguments is a.is_orbit(a.self()) ?? not a.is_orbit(a) ; ???
*
* - .initial/.terminal can be seen as a particular connection on .self, which .self ignores?
*
* TODO: Allow hooking
*
* TODO: Testing
* - Test if references hold after equivalence/composition...
*
* TODO: After initial demo:
* - Allow mapping/finding of other implementations regarding some equiv funcs (like different ways of implementing using NAND etc...)
*
* Arbitrary.
*/
}

export type Constructor = { proxy?: ProxyHandler<Ray.Any>, debug?: Debug.Listener, }

listeners: Debug.Listener[];
export class Instance extends JS.Class.Instance<Ray.Any> {

// get initial(): Ray.Any { return this._initial.call(this.proxy); } set initial(initial: Ray.FunctionConstructor<Ray.Any>) { this._initial = Ray.Function.New(initial); } protected _initial: Ray.Function<Ray.Any>;
// get self(): Ray.Any { return this._self.call(this.proxy); } set self(self: Ray.FunctionConstructor<Ray.Any>) { this._self = Ray.Function.New(self); } protected _self: Ray.Function<Ray.Any>;
// get terminal(): Ray.Any { return this._terminal.call(this.proxy); } set terminal(terminal: Ray.FunctionConstructor<Ray.Any>) { this._terminal = Ray.Function.New(terminal); } protected _terminal: Ray.Function<Ray.Any>;
listeners: Debug.Listener[];

protected constructor({
// initial, self, terminal
constructor({
proxy,
debug,
}: Ray.Constructor = {}) {
super({ proxy: proxy ?? Ray.ProxyHandlers.Default });

this.listeners = debug ? [debug] : [];

// this._initial = Ray.Function.New(initial ?? Ray.None);
// this._self = Ray.Function.New(self ?? this.proxy);
// this._terminal = Ray.Function.New(terminal ?? Ray.None);
}

/** Used to jump out of the proxy. */
Expand All @@ -96,41 +128,6 @@ namespace Ray {

}

export class Compiler { // Ray is Compiler

/**
* TODO: Compiler could have things like other composed rays which tell it cares about the other (even if that's correct or not??)
*
*
* TODO: Do I want to keep the is_equiv/is_composed pattern? Or simplify to one of the two?
*
* // TODO: NEVER DIRECTLY EXECUTE, ONLY AFTER CHAIN OF FUNCS, possibly arbitrarily LAZY
*
* TODO
* - Compose empty as first element? Disregard none to first elemn? Or not??
*
* TODO; Impl
* - Generally, return something which knows where all continuations are.
* - Generator/step function/... ; with no assumption of halting, but allow to hook into any step.
* - Cache:
* - Control of (non-/)lazyness of functions
* - None as, first time called, memoize func.
* - Perhaps locally cache (for stuff like count?) - no way to ensure globally coherence
* - a.orbit() -> a.orbit(a)
* // TODO: Should be automatic? is_orbit() or any method without arguments is a.is_orbit(a.self()) ?? not a.is_orbit(a) ; ???
*
* - .initial/.terminal can be seen as a particular connection on .self, which .self ignores?
*
* TODO: Allow hooking
*
* TODO: Testing
* - Test if references hold after equivalence/composition...
*
* TODO: After initial demo:
* - Allow mapping/finding of other implementations regarding some equiv funcs (like different ways of implementing using NAND etc...)
*/

}

export namespace ProxyHandlers {

Expand Down Expand Up @@ -372,17 +369,13 @@ namespace Ray {
self => self.is_none().not()
);

export const self_reference = Ray.Function.Self.Impl(
self => self
);

/**
* @see "Continuations as Equivalence (can often be done in parallel - not generally)": https://orbitmines.com/papers/on-orbits-equivalence-and-inconsistencies#:~:text=Constructing%20Continuations%20%2D%20Continuations%20as%20Equivalence
*/
// @alias('merge, 'continues_with', 'compose')
export const compose = Ray.Function.Self.Binary(
(a, b) => a.terminal().equivalent(b.initial())
);
(a, b) => a.terminal().equivalent(b.initial())
);

/**
* "Composing an terminal & initial boundary"
Expand All @@ -399,7 +392,12 @@ namespace Ray {
* - TODO: If we're only doing one end: This already assumes they are connected on the other end.
* - TODO: should be a connection here, with is_composed ; or "reference.is_equivalent" so that you can drop one of the sides, or both.
*/
(a, b) => ( b.last().compose(a.first()) ).and( a.first().compose(b.last()) )
(a, b) => {
b.last().compose(a.first());
a.first().compose(b.last());

return a; // ?
}
);

/**
Expand Down Expand Up @@ -442,8 +440,6 @@ namespace Ray {
(a) => { throw new NotImplementedError(); }
);


// TODO: .next but arbitrary step??
export const next = Ray.Function.Self.Impl((self) => {
throw new NotImplementedError();
return self;
Expand Down Expand Up @@ -510,8 +506,6 @@ namespace Ray {
// TODO Relies heavily on the execution layer to copy initial/terminal etc... ; and an is_orbit check before calling copy again. - Then again on the execution layer it can lazily do this copy (by not evaluating (i.e.) traversing everywhere), or it first does this traversing directly.
);

export const none = Ray.Op.Zeroary.All.none; // TODO FOR ALL OPS, ? automatic, or just put them here.

/**
* Placing existing structure on a new Reference, Boundary or Vertex:
*/
Expand Down Expand Up @@ -550,6 +544,9 @@ namespace Ray {
return initial;
});

export const memoized = Ray.Function.Self.Impl(
self => { throw new NotImplementedError(); }
);
}
}

Expand All @@ -564,6 +561,11 @@ namespace Ray {

export const number = (number: number) => { throw new NotImplementedError(); }

export const self_reference = Ray.Function.Self.Impl(
self => self
);
export const none = Ray.Op.Zeroary.All.none; // TODO FOR ALL OPS, ? automatic, or just put them here.

// export const Boundary = { INITIAL: Type.INITIAL, TERMINAL: Type.TERMINAL }; TODO: LIST O

// TODO CAN ALSO BE ZERO-ARY..
Expand All @@ -572,8 +574,17 @@ namespace Ray {
(a, size) => { throw new NotImplementedError(); }
);
// @alias('bit')
// export const boolean = size(2);
export const boolean = size(2);

export const vertex = Ray.Function.Self.Impl(
(self) => { throw new NotImplementedError(); }
);
export const initial = Ray.Function.Self.Impl(
(self) => { throw new NotImplementedError(); }
);
export const terminal = Ray.Function.Self.Impl(
(self) => { throw new NotImplementedError(); }
);
}

export default Ray;
17 changes: 0 additions & 17 deletions orbitmines.com/src/@orbitmines/explorer/Ray2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ export class Ray {

initial_vertex.compose(terminal_vertex);

// TODO BETTER DEBUG

return Ray.directions.next(terminal_vertex);
}
private ___as_vertices = (): [Ray, Ray] => {
Expand Down Expand Up @@ -222,15 +220,6 @@ export class Ray {
return copy;
}

*traverse(step: Ray.FunctionImpl = Ray.directions.next): Generator<Ray.Any> {
// TODO: Also to ___func??

if (this.type !== RayType.VERTEX)
throw new NotImplementedError(`[${this.type}]`);

yield *this.___next({step});
}

*___next({
step = Ray.directions.next,
} = {}): Generator<Ray.Any> {
Expand Down Expand Up @@ -437,12 +426,6 @@ export class Ray {
// throw new PreventsImplementationBug(`${pointers.length} left`)
}


/**
*
* TODO:
* - This needs something much smarter at some point...
*/
all = (step: Ray.FunctionImpl = Ray.directions.next): { [key: string | symbol]: Ray.Any } & any => {
return new Proxy<Ray.Any>(this, {

Expand Down

0 comments on commit 63b939b

Please sign in to comment.