aboutsummaryrefslogtreecommitdiffstats
path: root/lib/types.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/types.js')
-rw-r--r--lib/types.js324
1 files changed, 0 insertions, 324 deletions
diff --git a/lib/types.js b/lib/types.js
deleted file mode 100644
index 3fbb1c9..0000000
--- a/lib/types.js
+++ /dev/null
@@ -1,324 +0,0 @@
-//Gods-awful type-checking logic.
-
-//TypeName: string, Params: Array<string>
-function Type(TypeName,Params=[]) {
- if (!Type.all) Type.all = {};
- this.typename = "";
- this.mode = "";
-
- if (TypeName instanceof Type) {
- const t = TypeName.copy();
- for (const k in t) {
- this[k] = t[k];
- }
- return;
- }
-
- //Union/Tuple
- if (/^\(.+\)$/.test(TypeName)) {
- const types = [];
- var depth = 0;
- var workspace = "";
- for (const c of /^\((.+)\)$/.exec(TypeName)[1]) {
- switch (c) {
- case '(':
- case '<':
- depth++;
- break;
- case ')':
- case '>':
- depth--;
- break;
- case ',':
- if (depth == 0) {
- this.mode = "tuple";
- types.push(workspace);
- workspace = "";
- continue;
- }
- break;
- case '|':
- if (depth == 0) {
- this.mode = "union";
- types.push(workspace);
- workspace = "";
- continue;
- }
- break;
- }
- workspace += c;
- }
- if (workspace) types.push(workspace);
- this.template = types.map(t => t.trim()).map(t => Params.includes(t) ? Type.any : new Type(t, Params));
- }
- //Template
- else if (/^[^<]+<.+>$/.test(TypeName)) {
- this.typename = /^([^<]+)</.exec(TypeName)[1];
- this.mode = "templated";
- const types = [];
- var depth = 0;
- var workspace = "";
- for (const c of /^[^<]+<(.+)>$/.exec(TypeName)[1]) {
- switch (c) {
- case '(':
- case '<':
- depth++;
- break;
- case ')':
- case '>':
- depth--;
- break;
- case ',':
- if (depth == 0) {
- types.push(workspace);
- workspace = "";
- continue;
- }
- break;
- }
- workspace += c;
- }
- if (workspace) types.push(workspace);
- this.template = types.map(t => t.trim()).map(t => Params.includes(t) ? Type.any : new Type(t, Params));
- Type.all[this.typename] = () => new Type(TypeName, Array.from(Params));
- }
- //Standard Type, or Template Param
- else if (/^[^()|<>,]+$/.test(TypeName)) {
- if (!Params.includes(TypeName)) {
- this.typename = TypeName;
- this.mode = (TypeName == 'any') ? "any" : "standard";
- if (this.mode == "standard") Type.all[this.typename] = () => new Type(TypeName);
- } else {
- this.mode = "param";
- this.typename = TypeName;
- this.template = Type.any;
- }
- }
-}
-
-Type.prototype.toString = function() {
- switch (this.mode) {
- case "tuple":
- return `(${this.template.join(',')})`;
- case "union":
- return `(${this.template.join('|')})`;
- case "templated":
- return `${this.typename}<${this.template.join(',')}>`;
- case "any":
- case "standard":
- return this.typename;
- case "param":
- return this.template.toString();
- }
-}
-
-Type.prototype._resolve = function(key, val) {
- if (this.mode != "param") {
- if (val === undefined && this.template?.length === 1) {
- val = key;
- key = 0;
- }
- if (this.template?.length) this.template = this.template.map(t => t.resolve(key, val));
- } else {
- if (this.typename == key) this.template = new Type(val)
- }
-}
-
-Type.prototype.resolve = function(key, val) {
- const t = this.copy();
- t._resolve(key, val);
- return t;
-}
-
-Type.prototype.copy = function() {
- if (this.mode != "param") {
- const t = new Type(this.toString());
- for (const k in this.template)
- t.template[k] = this.template[k].copy();
- return t;
- } else {
- const t = new Type(this.typename, [this.typename]);
- t._resolve(this.typename, this.toString())
- return t;
- }
-}
-
-Type.prototype.getClasses = function() {
- if (this.mode == "param") return this.template.getClasses();
- const ret = new Set();
- switch (this.mode) {
- case 'standard':
- switch (this.typename) {
- case 'bool':
- case 'int':
- case 'float':
- case 'string':
- ret.add(this.typename);
- break;
- default:
- ret.add('special');
- break;
- }
- break;
- case 'templated':
- if (this.template.length == 1) {
- if (this.typename == "List") ret.add("list");
- this.template[0].getClasses().forEach(ret.add.bind(ret));
- } else {
- ret.add('any');
- }
-
- break;
- case 'union':
- case 'tuple':
- case 'any':
- ret.add('any');
- break;
- }
- return Array.from(ret);
-}
-
-//just makes my life that much easier when writing code. Type.any is nicer than new Type('any')
-Type.typeDef = (function(typename, name, params=[]) {
- Object.defineProperty(this, typename, {
- get: () => new Type(name, params)
- })
-}).bind(Type)
-Type.QuickTD = (function(name, params=[]) {
- Object.defineProperty(this, (new Type(name, params)).typename, {
- get: () => new Type(name, params)
- })
-}).bind(Type)
-
-Type.QuickTD("any");
-Type.QuickTD("int");
-Type.QuickTD("float");
-Type.QuickTD("string");
-Type.QuickTD("bool");
-Type.QuickTD("Vector3");
-Type.typeDef("list", "List<T>", ["T"]);
-
-function intersect(type1, type2) {
- const T1 = new Type(type1.toString());
- const T2 = new Type(type2.toString());
-
- if(T1 == T2) return T1;
-
- if (T1.mode == "any") return T2;
- if (T2.mode == "any") return T1;
- if (T1.mode == T2.mode) {
- switch (T1.mode) {
- case "standard":
- return (String(T1) == String(T2)) ? T1 : null;
- case "templated":
- case "tuple":
- if (
- T1.typename != T2.typename ||
- T1.template.length != T2.template.length
- ) return null;
- var t = T1.copy();
- for (const k in T1.template)
- t.template[k] = intersect(T1.template[k], T2.template[k]);
- if (t.template.includes(null))
- return null;
- else return t;
- case "union":
- const rettempl = Array.from(
- new Set(
- T1.template.map(
- t => T2.template
- .map(t2 => intersect(t,t2))
- .filter(t => t ?? false))
- .flat().map(String)
- )).map(n => new Type(n));
- if (rettempl.length > 1) {
- const ret = T1.copy();
- ret.template = rettempl;
- return ret;
- }
- else if (rettempl.length) return rettempl[0];
- return null
- }
- } else if ([T1.mode,T2.mode].includes("union")) {
- const UT = (T1.mode == "union") ? T1 : T2;
- const ST = (T1.mode == "union") ? T2 : T1;
- const isect = Array.from(
- new Set(
- UT.template
- .map(t => intersect(ST, t))
- .filter(t => t ?? false)
- .map(String)
- )).map(n => new Type(n));
- if (isect.length > 1) {
- const ret = UT.copy();
- ret.template = isect;
- return ret;
- }
- else if (isect.length) return isect[0];
- }
- return null;
-}
-function intersectParams(type1, type2) {
- const sect = intersect(type1, type2);
- if (!(sect ?? false)) return null;
-
- function walkDown(t, tres) {
- const ret = {};
- if (t.mode == "param") {
- ret[t.typename] = tres;
- }
- else if (
- t.mode == tres.mode &&
- t.typename == tres.typename &&
- t.template?.length == tres.template?.length
- ) {
- for (const p in t.template)
- ret = {...ret, ...walkDown(t.template[p], tres.template[p])};
- }
- return ret;
- }
- const resolution1 = walkDown(type1, sect);
- const resolution2 = walkDown(type2, sect);
- return [resolution1, resolution2];
-}
-
-function Chip(Entry) {
- this.types = [];
- if (Entry.ChipNameSource != "FirstNodeDesc") throw new TypeError("Chip is not FirstNodeDesc mode!");
-
- const cur = Entry.NodeDescs[0];
- const params = cur.ReadonlyTypeParams;
- const passed = Object.keys(params)
-
- this.root = newEl('div', 'chip');
- const header = newEl('div', 'chipheader');
- header.innerText = cur.Name;
- const input = newEl('div', 'input');
- const output = newEl('div', 'output');
- this.root.append(header, input, output);
- const genPort = (port) => {
- let classes,name;
- if (port.ReadonlyType != "exec") {
- const type = Object.entries(params).reduce((t,[k,v])=>t.resolve(k,v),new Type(port.ReadonlyType, passed));
- Object.entries(params).forEach(t => type.resolve(t[0], t[1]));
- classes = type.getClasses();
- name = type.toString();
- this.types.push(type);
- } else {
- classes = ["exec"];
- name = "exec";
- }
-
- const ret = newEl('div', '');
- ret.innerHTML = port.Name + "&nbsp;";
- classes.forEach(p => ret.classList.add(p))
-
- const tooltip = newEl('div', 'type');
- tooltip.innerText = name;
-
- return [ret, tooltip];
- }
-
- input.append(...cur.Inputs.map(genPort).flat());
- output.append(...cur.Outputs.map(genPort).flat());
-} \ No newline at end of file