Skip to content

Commit 6846aec

Browse files
committed
Merge branch 'compiler_feature_operator_overload_for_arrays' into merge_with_compiler_improved
2 parents f52c8db + ac2674d commit 6846aec

File tree

14 files changed

+5189
-5518
lines changed

14 files changed

+5189
-5518
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@
1313
"scripts": {
1414
"watch": "lerna run --parallel watch",
1515
"build": "lerna run build --stream"
16-
}
16+
},
17+
"dependencies": {}
1718
}

packages/hedgehog-core/src/output/output-item.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,4 @@ export const isMarkdownItem = (item: OutputItem): item is MarkdownItem => {
5050
return item.itemType === 'MARKDOWN';
5151
};
5252

53-
export type OutputItem =
54-
| TextItem
55-
| DrawingItem
56-
| TeXItem
57-
| FormulaItem
58-
| MarkdownItem;
53+
export type OutputItem = TextItem | DrawingItem | TeXItem | FormulaItem | MarkdownItem;

packages/hedgehog-core/src/runtime/prelude.ts

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Third party libraries
1717
*/
1818

1919
// synchrounous fetch
20+
// eslint-disable-next-line @typescript-eslint/no-var-requires
2021
const fetch = require('sync-fetch');
2122

2223
// gpu.js
@@ -69,9 +70,7 @@ export function scalar(val: number): Scalar {
6970
*/
7071
export function diff(input: Sym, varName?: Sym, times = 1): Sym {
7172
if (varName) {
72-
return new Sym(
73-
nerdamer.diff(input.toString(), varName.toString(), times).text()
74-
);
73+
return new Sym(nerdamer.diff(input.toString(), varName.toString(), times).text());
7574
}
7675
return new Sym(nerdamer.diff(input.toString(), times).text());
7776
}
@@ -81,9 +80,7 @@ export function diff(input: Sym, varName?: Sym, times = 1): Sym {
8180
*/
8281
export function integrate(input: Sym, varName?: Sym): Sym {
8382
if (varName) {
84-
return new Sym(
85-
nerdamer.integrate(input.toString(), varName.toString()).text()
86-
);
83+
return new Sym(nerdamer.integrate(input.toString(), varName.toString()).text());
8784
}
8885
return new Sym(nerdamer.integrate(input.toString()).text());
8986
}
@@ -128,9 +125,7 @@ export function acos(A: Mat | number[][] | number[] | number | Sym): Mat | Sym {
128125
}
129126
return _MathLib.acos(A);
130127
}
131-
export function acosh(
132-
A: Mat | number[][] | number[] | number | Sym
133-
): Mat | Sym {
128+
export function acosh(A: Mat | number[][] | number[] | number | Sym): Mat | Sym {
134129
if (A instanceof Sym) {
135130
return sym('acosh(' + A.expression + ')');
136131
}
@@ -157,10 +152,7 @@ export function exp(A: Mat | number[][] | number[] | number | Sym): Mat | Sym {
157152
}
158153
return _MathLib.exp(A);
159154
}
160-
export function log(
161-
A: Mat | number[][] | number[] | number | Sym,
162-
base?: number
163-
): Mat | Sym {
155+
export function log(A: Mat | number[][] | number[] | number | Sym, base?: number): Mat | Sym {
164156
if (A instanceof Sym) {
165157
return sym('log(' + A.expression + ')');
166158
}
@@ -172,9 +164,7 @@ export function asin(A: Mat | number[][] | number[] | number | Sym): Mat | Sym {
172164
}
173165
return _MathLib.asin(A);
174166
}
175-
export function asinh(
176-
A: Mat | number[][] | number[] | number | Sym
177-
): Mat | Sym {
167+
export function asinh(A: Mat | number[][] | number[] | number | Sym): Mat | Sym {
178168
if (A instanceof Sym) {
179169
return sym('asinh(' + A.expression + ')');
180170
}
@@ -186,9 +176,7 @@ export function atan(A: Mat | number[][] | number[] | number | Sym): Mat | Sym {
186176
}
187177
return _MathLib.atan(A);
188178
}
189-
export function atanh(
190-
A: Mat | number[][] | number[] | number | Sym
191-
): Mat | Sym {
179+
export function atanh(A: Mat | number[][] | number[] | number | Sym): Mat | Sym {
192180
if (A instanceof Sym) {
193181
return sym('atanh(' + A.expression + ')');
194182
}
@@ -251,9 +239,11 @@ export function lu(A: Mat): LU {
251239

252240
//tic and toc
253241
let timestamp = 0;
242+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
254243
export function tic() {
255244
timestamp = performance.now();
256245
}
246+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
257247
export function toc() {
258248
print(`Elapsed time: ${performance.now() - timestamp} milliseconds.`);
259249
}
@@ -265,16 +255,19 @@ let _OUTPUT_ITEMS_LIST_: OutputItem[] = [];
265255
export { _OUTPUT_ITEMS_LIST_ };
266256

267257
// print function is a function for user to output information
258+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
268259
export function print(data: any) {
269260
_OUTPUT_ITEMS_LIST_.push({ itemType: 'TEXT', text: data.toString() });
270261
}
271262

272263
//draw function is a function for user to draw figures using plotly.js
264+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
273265
export function draw(data: any, layout?: any) {
274266
_OUTPUT_ITEMS_LIST_.push({ itemType: 'DRAWING', data, layout });
275267
}
276268

277269
// plot2D is a wrapper for draw() function for scatter plot on 2D only
270+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
278271
export function plot2D(x_: any, y_: any) {
279272
if (x_ instanceof Mat && y_ instanceof Mat) {
280273
draw([
@@ -299,6 +292,7 @@ export function plot2D(x_: any, y_: any) {
299292
]);
300293
}
301294

295+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
302296
export function plot2DLine(x_: any, y_: any) {
303297
if (x_ instanceof Mat && y_ instanceof Mat) {
304298
draw([
@@ -324,6 +318,7 @@ export function plot2DLine(x_: any, y_: any) {
324318
}
325319

326320
// plot3D is a wrapper for draw() function for scatter plot on 3D only
321+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
327322
export function plot3D(x_: any, y_: any, z_: any) {
328323
if (x_ instanceof Mat && y_ instanceof Mat && z_ instanceof Mat){
329324
draw(
@@ -358,6 +353,7 @@ export function plot3D(x_: any, y_: any, z_: any) {
358353
);
359354
}
360355

356+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
361357
export function plot3DMesh(x_: any, y_: any, z_: any) {
362358
if (x_ instanceof Mat && y_ instanceof Mat && z_ instanceof Mat){
363359
draw(
@@ -393,16 +389,19 @@ export function plot3DMesh(x_: any, y_: any, z_: any) {
393389
}
394390

395391
// show Tex in MathJax
392+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
396393
export function tex(...inputs: any[]) {
397394
const inputTex: string = rawInputsToTex(...inputs);
398395
_OUTPUT_ITEMS_LIST_.push({ itemType: 'TEX', text: inputTex });
399396
}
400397

398+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
401399
export function formulaTex(...inputs: any[]) {
402400
const inputTex: string = rawInputsToTex(...inputs);
403401
_OUTPUT_ITEMS_LIST_.push({ itemType: 'FORMULA', text: inputTex });
404402
}
405403

404+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
406405
export function markdown(...inputs: any[]) {
407406
const inputMarkdown: string = rawInputsToTex(...inputs);
408407
_OUTPUT_ITEMS_LIST_.push({ itemType: 'MARKDOWN', text: inputMarkdown });
@@ -413,6 +412,6 @@ Synchrnous get function.
413412
Input: string, URL
414413
Output: string, text of URL
415414
*/
416-
export function get(input:string):string{
415+
export function get(input: string): string {
417416
return fetch(input).text();
418417
}

packages/hedgehog-core/src/transpiler/operator-overload.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,15 @@ function invokedTemplate(op: any) {
1919
return (sym(LEFT_ARG)[Symbol.for("${op}")](RIGHT_ARG));
2020
else if (Array.isArray(LEFT_ARG) && (RIGHT_ARG instanceof Mat))
2121
return (mat(LEFT_ARG)[Symbol.for("${op}")](RIGHT_ARG));
22+
else if (Array.isArray(LEFT_ARG) && (Array.isArray(RIGHT_ARG)))
23+
return (mat(LEFT_ARG)[Symbol.for("${op}")](mat(RIGHT_ARG)));
2224
else if ( (!isNaN(LEFT_ARG)) && (RIGHT_ARG instanceof Mat))
2325
return (scalar(LEFT_ARG)[Symbol.for("${op}")](RIGHT_ARG));
26+
else if ( (!isNaN(LEFT_ARG)) && (Array.isArray(RIGHT_ARG)))
27+
return (scalar(LEFT_ARG)[Symbol.for("${op}")](mat(RIGHT_ARG)));
28+
else if ( Array.isArray(LEFT_ARG) && (!isNaN(RIGHT_ARG)) )
29+
return (mat(LEFT_ARG)[Symbol.for("${op}")]((RIGHT_ARG)));
30+
2431
else
2532
return LEFT_ARG ${op} RIGHT_ARG;
2633
})

packages/hedgehog-core/src/transpiler/preprocessor.ts

Lines changed: 72 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ c. let my_Function_A = *import MY_PACKAGE: Function_A
1010

1111
async function preprocessor(source: string): Promise<string> {
1212
console.log('The source code after preprocessing');
13-
let result = await preprocessDFS(source, 'root');
13+
const result = await preprocessDFS(source, 'root');
1414
console.log(result);
1515
console.log('End of the source code after preprocessing');
1616
return result;
@@ -27,12 +27,14 @@ Output: The root location of the package. For example, "https://raw.githubuserco
2727
*/
2828

2929
function getPackageLocation(packageName: string, theFullListInJson: string): string {
30-
console.log("Package name: " + packageName + " , full list in json: " + theFullListInJson);
31-
let jsonObj = JSON.parse(theFullListInJson); let result: string[] = [];
32-
for (let element of jsonObj) {
33-
if (element["name"] === packageName || element["alias"] === packageName) { return element["location"]; }
30+
console.log('Package name: ' + packageName + ' , full list in json: ' + theFullListInJson);
31+
const jsonObj = JSON.parse(theFullListInJson);
32+
for (const element of jsonObj) {
33+
if (element['name'] === packageName || element['alias'] === packageName) {
34+
return element['location'];
35+
}
3436
}
35-
throw "Cannot find the package with name: " + packageName;
37+
throw 'Cannot find the package with name: ' + packageName;
3638
}
3739

3840
/*
@@ -43,60 +45,79 @@ Input: secondPart: the second part of current line splitted by "*import". For ex
4345
strCurrentCallStack: current call stack
4446
Output: A list of string, each string represents the corresponding hhs source file
4547
*/
46-
async function parseRegisterdPackage(secondPart: string, strCurrentCallStack:string): Promise<Array<string>> {
47-
let returnListOfFunctions: string[] = [];
48-
let theFullListInJson = await fetch("https://raw.githubusercontent.com/Hedgehog-Computing/Hedgehog-Package-Manager/main/hedgehog-packages.json", { method: 'get' }).then(body => body.text());
49-
let splittedResult = secondPart.split(':');
50-
if (splittedResult.length != 2) throw "Invalid importing library: " + secondPart;
48+
async function parseRegisterdPackage(
49+
secondPart: string,
50+
strCurrentCallStack: string
51+
): Promise<Array<string>> {
52+
const returnListOfFunctions: string[] = [];
53+
const theFullListInJson = await fetch(
54+
'https://raw.githubusercontent.com/Hedgehog-Computing/Hedgehog-Package-Manager/main/hedgehog-packages.json',
55+
{ method: 'get' }
56+
).then((body) => body.text());
57+
const splittedResult = secondPart.split(':');
58+
if (splittedResult.length != 2) throw 'Invalid importing library: ' + secondPart;
5159

5260
//get the right package name and HHS list string
53-
let packageName = splittedResult[0]
54-
let importedHHSListString = splittedResult[1];
61+
const packageName = splittedResult[0]
62+
const importedHHSListString = splittedResult[1];
5563

5664
//get package location
57-
let packageLocation = getPackageLocation(packageName.replace(/\s/g, ''), theFullListInJson);
65+
const packageLocation = getPackageLocation(packageName.replace(/\s/g, ''), theFullListInJson);
5866

5967
//get the package json file: package_location + hedgehog-package.json
60-
let packageJsonFile = packageLocation + "hedgehog-package.json";
68+
const packageJsonFile = packageLocation + 'hedgehog-package.json';
6169

62-
console.log("Package Json file: " + packageJsonFile);
70+
console.log('Package Json file: ' + packageJsonFile);
6371
//get the hedgehog-pacakge.json, then get the list of "includes" libraries
64-
let thePackageJsonString = await fetch(packageJsonFile, { method: 'get' }).then(body => body.text());
65-
console.log("Package Json string: " + thePackageJsonString);
66-
let thePackageJsonObj = JSON.parse(thePackageJsonString);
67-
if ("includes" in thePackageJsonObj) {
68-
let hhsCompleteList = thePackageJsonObj["includes"];
69-
let setHHSCompleteList = new Set(hhsCompleteList);
70-
let importedItemList = importedHHSListString.split(',');
71-
for (let eachItem of importedItemList) {
72-
let eachItemWithoutSpace = eachItem.replace(/\s/g, '');
72+
const thePackageJsonString = await fetch(packageJsonFile, { method: 'get' }).then((body) =>
73+
body.text()
74+
);
75+
console.log('Package Json string: ' + thePackageJsonString);
76+
const thePackageJsonObj = JSON.parse(thePackageJsonString);
77+
if ('includes' in thePackageJsonObj) {
78+
const hhsCompleteList = thePackageJsonObj['includes'];
79+
const setHHSCompleteList = new Set(hhsCompleteList);
80+
const importedItemList = importedHHSListString.split(',');
81+
for (const eachItem of importedItemList) {
82+
const eachItemWithoutSpace = eachItem.replace(/\s/g, '');
7383
if (setHHSCompleteList.has(eachItemWithoutSpace)) {
74-
let currentHHSLocation = packageLocation + eachItemWithoutSpace + ".hhs";
75-
let currentItemSourceCode = await fetch(currentHHSLocation, { method: 'get' }).then(body => body.text());
84+
const currentHHSLocation = packageLocation + eachItemWithoutSpace + ".hhs";
85+
const currentItemSourceCode = await fetch(currentHHSLocation, { method: 'get' }).then(
86+
(body) => body.text()
87+
);
7688

7789
// After get the whole hhs source file, preprocess the string via DFS preprocessor
7890
// to handle the dependencies of current source file string
79-
let preprocessedCurrentItemSourceCode = await preprocessDFS(currentItemSourceCode, strCurrentCallStack + " -> " + strCurrentCallStack + ":" + eachItemWithoutSpace);
91+
const preprocessedCurrentItemSourceCode = await preprocessDFS(
92+
currentItemSourceCode,
93+
strCurrentCallStack + ' -> ' + strCurrentCallStack + ':' + eachItemWithoutSpace
94+
);
8095
returnListOfFunctions.push(preprocessedCurrentItemSourceCode);
8196
}
8297
}
98+
} else {
99+
throw (
100+
'Cannot find "includes" key in the hedgehog-package.json configuration file! Please add a key with name "includes" with a complete list of exported libraries. Exception at ' +
101+
secondPart +
102+
'.\nCall Stack at: ' +
103+
strCurrentCallStack
104+
);
83105
}
84-
else { throw "Cannot find \"includes\" key in the hedgehog-package.json configuration file! Please add a key with name \"includes\" with a complete list of exported libraries. Exception at " + secondPart + ".\nCall Stack at: " + strCurrentCallStack}
85106
return returnListOfFunctions;
86107
}
87108

88109
// A helper function to check if a string contains URL or not. Reference: https://regexr.com/3e6m0
89110
function containsURL(code: string): boolean {
90-
let expression = /(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g;
91-
let regex = new RegExp(expression);
111+
const expression = /(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g;
112+
const regex = new RegExp(expression);
92113
if (code.match(regex)) return true;
93114
return false;
94115
}
95116

96117
// code is the string of code, and strCurrentCallStack is the full call stack
97118
async function preprocessDFS(code: string, strCurrentCallStack: string): Promise<string> {
98119
//1. split the codes into lines
99-
let vecSplittedString = code.split(/\r?\n/);
120+
const vecSplittedString = code.split(/\r?\n/);
100121

101122
//2. initialize the the chunk of string to return
102123
let returnCode = '';
@@ -106,31 +127,36 @@ async function preprocessDFS(code: string, strCurrentCallStack: string): Promise
106127
for (let i = 0; i < vecSplittedString.length; i++) {
107128
returnCode += '\n';
108129
//3.1 if current line of code doesn't contain "*import ", just append it to returnCode
109-
if (!vecSplittedString[i].includes("*import ")) { returnCode += '\n' + vecSplittedString[i]; }
130+
if (!vecSplittedString[i].includes('*import ')) {
131+
returnCode += '\n' + vecSplittedString[i];
132+
}
110133
//3.2 otherwise, split the string by "*import ", keep the first part (if it exists), then download
111134
// and fetch the second part recursively (which should be and must be a valid URL or a registered package)
112135
else {
113-
let currentString = vecSplittedString[i];
114-
let splittedResult = currentString.split("*import ");
136+
const currentString = vecSplittedString[i];
137+
const splittedResult = currentString.split("*import ");
115138
if (splittedResult.length < 2) {
116-
throw "Invalid current line of code for preprocessing: \n"
117-
+ "\nCall stack: \n" + strCurrentCallStack
118-
+ "\nCurrent line: " + currentString + "\n";
139+
throw (
140+
'Invalid current line of code for preprocessing: \n' +
141+
+ "\nCall stack: \n" + strCurrentCallStack +
142+
'\nCurrent line: ' +
143+
currentString +
144+
'\n'
145+
);
119146
}
120147
//3.2.1 add the first part
121148
returnCode += splittedResult[0];
122149
//3.2.2 Is it imported from URL or from a registered package?
123150
if (containsURL(splittedResult[1])){
124-
//3.2.2.1 download the library from URL
125-
let libraryFromUrl = await fetch(splittedResult[1], { method: 'get' })
126-
.then(function (body) {
127-
let real_library = body.text();
128-
return real_library;
129-
});
151+
//3.2.2.1 download the library from URL
152+
const libraryFromUrl = await fetch(splittedResult[1], { method: 'get' }).then((body) => {
153+
const real_library = body.text();
154+
return real_library;
155+
});
130156

131157
//3.2.3 get the current file information (get "FunctionABC.js" from URL string http://mywebsite/FunctionABC.js)
132-
let splittedURLResult = splittedResult[1].split('/');
133-
let strCallStack = strCurrentCallStack + " -> " + splittedURLResult[splittedResult.length - 1];
158+
const splittedURLResult = splittedResult[1].split('/');
159+
const strCallStack = strCurrentCallStack + " -> " + splittedURLResult[splittedResult.length - 1];
134160

135161
//3.2.4 process the big chunk of code
136162
let currentResult = await preprocessDFS(libraryFromUrl, strCallStack);

0 commit comments

Comments
 (0)