Skip to content

Commit

Permalink
Merge pull request #103 from calcit-lang/keyword-idx
Browse files Browse the repository at this point in the history
add index number in keyword in js for fast comparing
  • Loading branch information
soyaine authored Oct 11, 2021
2 parents 57767ce + 7b39692 commit 6e6b1bf
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 64 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "calcit_runner"
version = "0.5.0-a4"
version = "0.5.0-a5"
authors = ["jiyinyiyong <jiyinyiyong@gmail.com>"]
edition = "2018"
license = "MIT"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@calcit/procs",
"version": "0.5.0-a4",
"version": "0.5.0-a5",
"main": "./lib/calcit.procs.js",
"devDependencies": {
"@types/node": "^16.9.6",
Expand Down
21 changes: 18 additions & 3 deletions ts-src/calcit-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,31 @@ import { CalcitTuple } from "./js-tuple";
// we have to inject cache in a dirty way in some cases
const calcit_dirty_hash_key = "_calcit_cached_hash";

let keywordIdx = 0;

export class CalcitKeyword {
value: string;
cachedHash: Hash;
// use keyword for fast comparing
idx: number;
constructor(x: string) {
this.value = x;
this.idx = keywordIdx;
keywordIdx++;
this.cachedHash = null;
}
toString() {
return `:${this.value}`;
}
cmp(other: CalcitKeyword): number {
if (this.idx < other.idx) {
return -1;
} else if (this.idx > other.idx) {
return 1;
} else {
return 0;
}
}
}

export class CalcitSymbol {
Expand Down Expand Up @@ -121,9 +136,9 @@ export function findInFields(xs: Array<CalcitKeyword>, y: CalcitKeyword): number
while (upper - lower > 1) {
let pos = (lower + upper) >> 1;
let v = xs[pos];
if (y.value < v.value) {
if (y.idx < v.idx) {
upper = pos - 1;
} else if (y.value > v.value) {
} else if (y.idx > v.idx) {
lower = pos + 1;
} else {
return pos;
Expand Down Expand Up @@ -202,7 +217,7 @@ let hashFunction = (x: CalcitValue): Hash => {
}

if (x instanceof CalcitKeyword) {
let h = mergeValueHash(defaultHash_keyword, x.value);
let h = mergeValueHash(defaultHash_keyword, x.idx);
x.cachedHash = h;
return h;
}
Expand Down
9 changes: 5 additions & 4 deletions ts-src/calcit.procs.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// CALCIT VERSION
export const calcit_version = "0.5.0-a4";
export const calcit_version = "0.5.0-a5";

import { overwriteComparator, initTernaryTreeMap } from "@calcit/ternary-tree";
import { parse, ICirruNode } from "@cirru/parser.ts";
Expand Down Expand Up @@ -950,7 +950,7 @@ export let turn_keyword = (x: CalcitValue): CalcitKeyword => {
throw new Error("Unexpected data for keyword");
};

export let turn_symbol = (x: CalcitValue): CalcitKeyword => {
export let turn_symbol = (x: CalcitValue): CalcitSymbol => {
if (typeof x === "string") {
return new CalcitSymbol(x);
}
Expand Down Expand Up @@ -1325,6 +1325,7 @@ let rawCompare = (x: any, y: any): number => {
};

export let _$n_compare = (a: CalcitValue, b: CalcitValue): number => {
if (a === b) return 0;
let ta = typeAsInt(a);
let tb = typeAsInt(b);
if (ta === tb) {
Expand All @@ -1335,9 +1336,9 @@ export let _$n_compare = (a: CalcitValue, b: CalcitValue): number => {
return rawCompare(a, b);
case PseudoTypeIndex.number:
return rawCompare(a, b);
case PseudoTypeIndex.symbol:
return rawCompare(a, b);
case PseudoTypeIndex.keyword:
return (a as CalcitKeyword).cmp(b as CalcitKeyword);
case PseudoTypeIndex.symbol:
return rawCompare(a, b);
case PseudoTypeIndex.string:
return rawCompare(a, b);
Expand Down
8 changes: 1 addition & 7 deletions ts-src/js-cirru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,7 @@ export let extract_cirru_edn = (x: CirruEdnFormat): CalcitValue => {
}
});
entries.sort((a, b) => {
if (a[0] < b[0]) {
return -1;
} else if (a[0] > b[0]) {
return 1;
} else {
return 0;
}
return a[0].cmp(b[0]);
});
let fields: Array<CalcitKeyword> = [];
let values: Array<CalcitValue> = [];
Expand Down
83 changes: 36 additions & 47 deletions ts-src/js-record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ export class CalcitRecord {

export let new_record = (name: CalcitValue, ...fields: Array<CalcitValue>): CalcitValue => {
let fieldNames = fields.map(castKwd).sort((x, y) => {
if (x.value < y.value) {
if (x.idx < y.idx) {
return -1;
} else if (x.value > y.value) {
} else if (x.idx > y.idx) {
return 1;
} else {
throw new Error(`Unexpected duplication in record fields: ${x.toString()}`);
Expand All @@ -76,16 +76,6 @@ export let new_record = (name: CalcitValue, ...fields: Array<CalcitValue>): Calc
return new CalcitRecord(castKwd(name), fieldNames);
};

let fieldPairOrder = (a: [string, CalcitValue], b: [string, CalcitValue]) => {
if (a[0] < b[0]) {
return -1;
} else if (a[0] > b[0]) {
return 1;
} else {
return 0;
}
};

export let fieldsEqual = (xs: Array<CalcitKeyword>, ys: Array<CalcitKeyword>): boolean => {
if (xs === ys) {
return true; // special case, referential equal
Expand Down Expand Up @@ -146,46 +136,44 @@ export let _$n_record_$o_get_name = (x: CalcitRecord): CalcitKeyword => {
};

export let _$n_record_$o_from_map = (proto: CalcitValue, data: CalcitValue): CalcitValue => {
if (proto instanceof CalcitRecord) {
if (data instanceof CalcitRecord) {
if (fieldsEqual(proto.fields, data.fields)) {
return new CalcitRecord(proto.name, proto.fields, data.values);
} else {
let values: Array<CalcitValue> = [];
for (let field of proto.fields) {
let idx = findInFields(data.fields, field);
if (idx < 0) {
throw new Error(`Cannot find field ${field} among ${data.fields}`);
}
values.push(data.values[idx]);
}
return new CalcitRecord(proto.name, proto.fields, values);
}
} else if (data instanceof CalcitMap) {
let pairs: Array<[string, CalcitValue]> = [];
for (let [k, v] of data.pairs()) {
pairs.push([getStringName(k), v]);
}
// mutable sort
pairs.sort(fieldPairOrder);
if (!(proto instanceof CalcitRecord)) throw new Error("Expected prototype to be record");

if (data instanceof CalcitRecord) {
if (fieldsEqual(proto.fields, data.fields)) {
return new CalcitRecord(proto.name, proto.fields, data.values);
} else {
let values: Array<CalcitValue> = [];
outerLoop: for (let field of proto.fields) {
for (let idx = 0; idx < pairs.length; idx++) {
let pair = pairs[idx];
if (pair[0] === field.value) {
values.push(pair[1]);
continue outerLoop; // dirty code for performance
}
for (let field of proto.fields) {
let idx = findInFields(data.fields, field);
if (idx < 0) {
throw new Error(`Cannot find field ${field} among ${data.fields}`);
}
throw new Error(`Cannot find field ${field} among ${pairs}`);
values.push(data.values[idx]);
}
return new CalcitRecord(proto.name, proto.fields, values);
} else {
throw new Error("Expected record or data for making a record");
}
} else if (data instanceof CalcitMap) {
let pairs: Array<[CalcitKeyword, CalcitValue]> = [];
for (let [k, v] of data.pairs()) {
pairs.push([castKwd(k), v]);
}
// mutable sort
pairs.sort((pair1, pair2) => pair1[0].cmp(pair2[0]));

let values: Array<CalcitValue> = [];
outerLoop: for (let field of proto.fields) {
for (let idx = 0; idx < pairs.length; idx++) {
let pair = pairs[idx];
if (pair[0] === field) {
values.push(pair[1]);
continue outerLoop; // dirty code for performance
}
}
throw new Error(`Cannot find field ${field} among ${pairs}`);
}
return new CalcitRecord(proto.name, proto.fields, values);
} else {
throw new Error("Expected prototype to be record");
throw new Error("Expected record or data for making a record");
}
};

Expand Down Expand Up @@ -230,13 +218,14 @@ export function _$n_record_$o_extend_as(obj: CalcitValue, new_name: CalcitValue,
new_fields.push(k);
new_values.push(obj.values[i]);
} else {
if (field.value < k.value) {
let ordering = field.cmp(k);
if (ordering === -1) {
new_fields.push(field);
new_values.push(new_value);

new_fields.push(k);
new_values.push(obj.values[i]);
} else if (field.value > k.value) {
} else if (ordering === 1) {
new_fields.push(k);
new_values.push(obj.values[i]);
} else {
Expand Down

0 comments on commit 6e6b1bf

Please sign in to comment.