From 2ce8e9ec68e119d74a853e28c87c9876889c46e4 Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Fri, 22 Nov 2024 19:42:30 +0900 Subject: [PATCH 1/3] Add jit for general array --- server/src/jit/jit-code-generator.ts | 29 ++++--- server/src/jit/utils.ts | 29 ++++++- server/tests/jit/jit-code-generator.test.ts | 85 ++++++++++++++++++++- server/tests/transpiler/transpile.test.ts | 12 +-- 4 files changed, 125 insertions(+), 30 deletions(-) diff --git a/server/src/jit/jit-code-generator.ts b/server/src/jit/jit-code-generator.ts index 8dc149a..330141c 100644 --- a/server/src/jit/jit-code-generator.ts +++ b/server/src/jit/jit-code-generator.ts @@ -72,39 +72,38 @@ function specializedFunctionBodyName(name: string) { // returns '(' or '(' // '(' is returned if the type cannot be checked. -function checkType(type?: StaticType) { +function checkType(name: string, type?: StaticType): string|undefined { if (type instanceof ArrayType) { if (type.elementType === Integer) - return 'gc_is_intarray('; + return `gc_is_intarray(${name})`; if (type.elementType === Float) - return 'gc_is_floatarray('; + return `gc_is_floatarray(${name})`; if (type.elementType === BooleanT) - return 'gc_is_boolarray('; + return `gc_is_boolarray(${name})`; if (type.elementType === Any) - return 'gc_is_anyarray('; + return `gc_is_anyarray(${name})`; else - throw new JITCompileError('Unknown array type.'); + return `gc_is_instance_of_array(${name}) && ${checkType(name, type.elementType)}` } if (type instanceof InstanceType) { - return `gc_is_instance_of(&${classNameInC(type.name())}.clazz, `; + return `gc_is_instance_of(&${classNameInC(type.name())}.clazz, ${name})`; } switch (type) { case Integer: - return 'is_int_value('; + return `is_int_value(${name})`; case Float: - return 'is_float_value('; + return `is_float_value(${name})`; case BooleanT: - return 'is_bool_value('; + return `is_bool_value(${name})`; case StringT: - return `gc_is_string_object(`; + return `gc_is_string_object(${name})`; default: return undefined; } } - export class JitCodeGenerator extends CodeGenerator{ private profiler: Profiler; private bsSrc: string[]; @@ -310,10 +309,10 @@ export class JitCodeGenerator extends CodeGenerator{ const paramName = (node.params[i] as AST.Identifier).name const info = fenv.table.lookup(paramName) if (info !== undefined) { - const check = checkType(targetParamTypes[i]); + const name = info.transpiledName(paramName) + const check = checkType(name, targetParamTypes[i]); if (check) { - const name = info.transpiledName(paramName) - paramSig.push(`${check}${name})`); + paramSig.push(check); } } } diff --git a/server/src/jit/utils.ts b/server/src/jit/utils.ts index dbbaa20..520c5e8 100644 --- a/server/src/jit/utils.ts +++ b/server/src/jit/utils.ts @@ -30,8 +30,8 @@ export function typeStringToStaticType(typeString: string, gvnt?: GlobalVariable return new ArrayType('float') } else if (typeString === 'Array') { return new ArrayType('boolean') - } else if (typeString === 'Array') { - return 'any' + } else if (isArray(typeString)) { + return getArrayType(typeString, gvnt) } else if (typeString === 'Function') { return 'any' } else { @@ -42,6 +42,30 @@ export function typeStringToStaticType(typeString: string, gvnt?: GlobalVariable } } +function isArray(typeString: string) { + return /\[\]$/.test(typeString) +} + +function getArrayType(typeString: string, gvnt?: GlobalVariableNameTable):StaticType { + const matches = typeString.match(/(\[\])+$/); + let ndim = matches ? matches[0].length / 2 : 0; + const className = typeString.replace(/(\[\])+$/, ""); + let arr: StaticType|undefined; + if (className === 'string') + arr = 'string' + else { + arr = gvnt === undefined ? undefined : gvnt.lookup(className)?.type + if (arr === undefined || !(arr instanceof InstanceType)) + throw new ProfileError(`Cannot find the profiled class: ${className}`) + } + + while (ndim > 0) { + arr = new ArrayType(arr) + ndim -= 1 + } + return arr +} + function staticTypeToTSType(type: StaticType): AST.TSType { if (type === Integer || type === Float) return tsTypeReference(identifier(type)); @@ -76,7 +100,6 @@ function staticTypeToTSType(type: StaticType): AST.TSType { return tsAnyKeyword(); } - function staticTypeToNode(type: StaticType):AST.TSTypeAnnotation { return tsTypeAnnotation(staticTypeToTSType(type)); } diff --git a/server/tests/jit/jit-code-generator.test.ts b/server/tests/jit/jit-code-generator.test.ts index 0f18bc2..29eefb3 100644 --- a/server/tests/jit/jit-code-generator.test.ts +++ b/server/tests/jit/jit-code-generator.test.ts @@ -140,6 +140,41 @@ print(area(rect)); .toEqual("Rectangle, undefined, undefined, undefined\n44\n") }) +test('profile: class array', () => { + const src = ` +class Rectangle { + x: integer + y: integer + + constructor(x:integer, y:integer) { + this.x = x; + this.y = y; + } +} + +function areas(rects) { + let sum = 0 + for (let i = 0; i < rects.length; i++) { + sum += rects[i].x * rects[i].y + } + return sum +} + +let rects = [new Rectangle(11, 4), new Rectangle(11, 4), new Rectangle(11, 4)] +for(let i = 0; i < 15; i++) { + areas(rects); +} +print(areas(rects)); + ` + const profiler = new Profiler() + const file0 = tempCFilePath('file0') + const result0 = initialCompile(file0); + const file1 = tempCFilePath('file1') + const result1 = compile(0, src, profiler, file1, result0.names) + expect(execute([file0, file1], [result1.main], tempCFilePath('file2'), tempExecutableFilePath('bscript'))) + .toEqual("Rectangle[], undefined, undefined, undefined\n132\n") +}) + test('profile: not profile function with function return type', () => { const src = ` function func(a:()=>integer) { @@ -355,7 +390,7 @@ print(aarr0(aarr, arr)); const func = profiler.getFunctionProfileById(0); if (func === undefined) throw new Error(`Cannot fined func.`) - profiler.setFuncSpecializedType(0, ["Array", "Array", "undefined", "undefined"].map(t => typeStringToStaticType(t, result1.names))) + profiler.setFuncSpecializedType(0, ["Array", "string[]", "undefined", "undefined"].map(t => typeStringToStaticType(t, result1.names))) const file2 = tempCFilePath('file2') const result2 = compile(1, func.src, profiler, file2, result1.names) @@ -410,6 +445,54 @@ print(area(new Rectangle(3, 4))) .toEqual(`12\n12\n`) }) +test('jit compile: class array', () => { + const src1 = ` + +class Rectangle { + x: integer + y: integer + + constructor(x:integer, y:integer) { + this.x = x; + this.y = y; + } +} + +function areas(rects) { + let sum = 0 + for (let i = 0; i < rects.length; i++) { + sum += rects[i].x * rects[i].y + } + return sum +} + +print(areas([new Rectangle(11, 4), new Rectangle(11, 4), new Rectangle(11, 4)])) + ` + + const src3 = ` +print(areas([new Rectangle(11, 4), new Rectangle(11, 4), new Rectangle(11, 4)])) + ` + + const profiler = new Profiler() + const file0 = tempCFilePath('file0') + const result0 = initialCompile(file0); + const file1 = tempCFilePath('file1') + const result1 = compile(0, src1, profiler, file1, result0.names) + + const func = profiler.getFunctionProfileById(0); + if (func === undefined) + throw new Error(`Cannot fined func.`) + profiler.setFuncSpecializedType(0, ["Rectangle[]", "undefined", "undefined", "undefined"].map(t => typeStringToStaticType(t, result1.names))) + + const file2 = tempCFilePath('file2') + const result2 = compile(1, func.src, profiler, file2, result1.names) + + const file3 = tempCFilePath('file3') + const result3 = compile(2, src3, profiler, file3, result2.names) + expect(execute([file0, file1, file2, file3], [result1.main, result2.main, result3.main], tempCFilePath('file4'), tempExecutableFilePath('bscript'))) + .toEqual(`132\n132\n`) +}) + test('jit compile: function redefinition after jit compile', () => { const src1 = ` function add(a, b) { diff --git a/server/tests/transpiler/transpile.test.ts b/server/tests/transpiler/transpile.test.ts index 52abfe5..42cebbf 100644 --- a/server/tests/transpiler/transpile.test.ts +++ b/server/tests/transpiler/transpile.test.ts @@ -10,17 +10,7 @@ test("transpile", () => { }) const bsSrc = ` -class GPIO { - pinNum:integer; - - constructor(pinNum: integer) { - this.pinNum = pinNum; - } - - set(level: integer) { - this.pinNum + 1 - } -} +let sarr: any[][] = [[]] ` test("playground", () => { From 2b62e4dff2482c91615888195b9393b701b4243e Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Fri, 22 Nov 2024 21:09:16 +0900 Subject: [PATCH 2/3] Fix --- notebook/src/hooks/repl-context.tsx | 55 ++++++++++++--------- notebook/src/hooks/use-memory.ts | 4 +- server/src/jit/jit-code-generator.ts | 34 +++++++------ server/src/server/session.ts | 8 +-- server/tests/jit/jit-code-generator.test.ts | 16 +++--- server/tests/jit/test-jit-utils.ts | 1 + server/tests/transpiler/transpile.test.ts | 2 +- 7 files changed, 68 insertions(+), 52 deletions(-) diff --git a/notebook/src/hooks/repl-context.tsx b/notebook/src/hooks/repl-context.tsx index 330717a..70aec2c 100644 --- a/notebook/src/hooks/repl-context.tsx +++ b/notebook/src/hooks/repl-context.tsx @@ -56,7 +56,15 @@ export default function ReplProvider({children}: {children: ReactNode}) { const dram = useMemory('DRAM') const bluetooth = useRef(new Bluetooth()) - let onExecutionComplete = useRef((executionTime: number) => {}) + // let onExecutionComplete = useRef((executionTime: number) => {}) + // To use these variables in callbacks + const latestCellRef = useRef(latestCell) + latestCellRef.current = latestCell + const iramRef = useRef(iram) + const dramRef = useRef(dram) + iramRef.current = iram + dramRef.current = dram + useEffect(() => { bluetooth.current.setNotificationHandler(onReceiveNotification); @@ -75,10 +83,9 @@ export default function ReplProvider({children}: {children: ReactNode}) { } const executeLatestCell = async () => { - let updatedLatestCell:CellT = {...latestCell, compileError: '', state: 'compiling'} - setLatestCell(updatedLatestCell) + setLatestCell({...latestCell, compileError: '', state: 'compiling'}) try { - const compileResult = useJIT ? await network.compileWithProfiling(updatedLatestCell.code) : await network.compile(updatedLatestCell.code) + const compileResult = useJIT ? await network.compileWithProfiling(latestCell.code) : await network.compile(latestCell.code) const iramBuffer = Buffer.from(compileResult.iram.data, "hex") const dramBuffer = Buffer.from(compileResult.dram.data, "hex") const flashBuffer = Buffer.from(compileResult.flash.data, "hex") @@ -89,26 +96,12 @@ export default function ReplProvider({children}: {children: ReactNode}) { .loadToFlash(compileResult.flash.address, flashBuffer) .jump(compileResult.entryPoint) .generate() - updatedLatestCell = {...updatedLatestCell, state: 'sending'} - setLatestCell(updatedLatestCell) + setLatestCell({...latestCell, compileError: '', state: 'sending'}) iram.actions.setUsedSegment(compileResult.iram.address, iramBuffer.length) dram.actions.setUsedSegment(compileResult.dram.address, dramBuffer.length) const bluetoothTime = await bluetooth.current.sendBuffers(bytecodeBuffer) const compileTime = compileResult.compileTime - updatedLatestCell = {...updatedLatestCell, state: 'executing', time: {compile: compileTime, bluetooth: bluetoothTime}} - setLatestCell(updatedLatestCell) - onExecutionComplete.current = (executionTime: number) => { - if (updatedLatestCell.time !== undefined && updatedLatestCell.time?.execution === undefined) { - updatedLatestCell.time.execution = executionTime - updatedLatestCell.state = 'done' - const nextCellId = updatedLatestCell.id + 1 - setPostExecutionCells((cells) => - [...cells, updatedLatestCell] - ) - setLatestCell({id: nextCellId, code: '', state: 'user-writing'}) - } - - } + setLatestCell({...latestCell, state: 'executing', time: {compile: compileTime, bluetooth: bluetoothTime}}) } catch (error: any) { if (error instanceof CompileError) { setLatestCell({...latestCell, state: 'user-writing', compileError: error.toString()}) @@ -145,13 +138,29 @@ export default function ReplProvider({children}: {children: ReactNode}) { }); } + const onExecutionComplete = (executionTime: number) => { + if (latestCellRef.current.time !== undefined && latestCellRef.current.time?.execution === undefined) { + latestCellRef.current.time.execution = executionTime + latestCellRef.current.state = 'done' + const nextCellId = latestCellRef.current.id + 1 + setPostExecutionCells((cells) => + [...cells, latestCellRef.current] + ) + setLatestCell({id: nextCellId, code: '', state: 'user-writing'}) + } + } + const jitCompile = (fid: number, paramtypes: string[]) => { network.jitCompile(fid, paramtypes).then((compileResult) => { console.log(compileResult) + const iramBuffer = Buffer.from(compileResult.iram.data, "hex") + const dramBuffer = Buffer.from(compileResult.dram.data, "hex") + iramRef.current.actions.setUsedSegment(compileResult.iram.address, iramBuffer.length) + dramRef.current.actions.setUsedSegment(compileResult.dram.address, dramBuffer.length) const bytecodeBuffer = new BytecodeBufferBuilder(MAX_MTU) - .loadToRAM(compileResult.iram.address, Buffer.from(compileResult.iram.data, "hex")) - .loadToRAM(compileResult.dram.address, Buffer.from(compileResult.dram.data, "hex")) + .loadToRAM(compileResult.iram.address, iramBuffer) + .loadToRAM(compileResult.dram.address, dramBuffer) .loadToFlash(compileResult.flash.address, Buffer.from(compileResult.flash.data, "hex")) .jump(compileResult.entryPoint) .generate() @@ -175,7 +184,7 @@ export default function ReplProvider({children}: {children: ReactNode}) { onDeviceResetComplete(parseResult.meminfo) break; case BYTECODE.RESULT_EXECTIME: - onExecutionComplete.current(parseResult.exectime) + onExecutionComplete(parseResult.exectime) break; case BYTECODE.RESULT_PROFILE: { console.log("receive profile", parseResult.fid, parseResult.paramtypes); diff --git a/notebook/src/hooks/use-memory.ts b/notebook/src/hooks/use-memory.ts index 7afe528..1879ed3 100644 --- a/notebook/src/hooks/use-memory.ts +++ b/notebook/src/hooks/use-memory.ts @@ -21,11 +21,11 @@ export const MemoryDummry = { name: '', size: 0, usedSize: 0, - buffer: [], + buffer: [false], unitSize: UNIT_SIZE }, actions: { - reset: (size: number) => {}, + reset: (size: number, address: number) => {}, setUsedSegment: (start: number, size: number) => {}, } } diff --git a/server/src/jit/jit-code-generator.ts b/server/src/jit/jit-code-generator.ts index 330141c..5bada34 100644 --- a/server/src/jit/jit-code-generator.ts +++ b/server/src/jit/jit-code-generator.ts @@ -72,33 +72,33 @@ function specializedFunctionBodyName(name: string) { // returns '(' or '(' // '(' is returned if the type cannot be checked. -function checkType(name: string, type?: StaticType): string|undefined { +function checkType(env: VariableEnv, type?: StaticType): string|undefined { if (type instanceof ArrayType) { if (type.elementType === Integer) - return `gc_is_intarray(${name})`; + return 'gc_is_intarray('; if (type.elementType === Float) - return `gc_is_floatarray(${name})`; + return 'gc_is_floatarray('; if (type.elementType === BooleanT) - return `gc_is_boolarray(${name})`; + return 'gc_is_boolarray('; if (type.elementType === Any) - return `gc_is_anyarray(${name})`; + return 'gc_is_anyarray('; else - return `gc_is_instance_of_array(${name}) && ${checkType(name, type.elementType)}` + return `gc_is_instance_of(&${env.useArrayType(type)[0]}.clazz, `; } if (type instanceof InstanceType) { - return `gc_is_instance_of(&${classNameInC(type.name())}.clazz, ${name})`; + return `gc_is_instance_of(&${classNameInC(type.name())}.clazz, `; } switch (type) { case Integer: - return `is_int_value(${name})`; + return 'is_int_value('; case Float: - return `is_float_value(${name})`; + return 'is_float_value('; case BooleanT: - return `is_bool_value(${name})`; + return 'is_bool_value('; case StringT: - return `gc_is_string_object(${name})`; + return 'gc_is_string_object('; default: return undefined; } @@ -249,6 +249,9 @@ export class JitCodeGenerator extends CodeGenerator{ this.result.write(') {') this.result.right().nl() + // For test + this.result.write(`#ifdef TEST64`).nl().write('puts("Execute specialized function");').nl().write('#endif').nl() + this.result.write('return '); this.functionCall(node, fenv, specializedFuncName, specializedType, funcType.paramTypes, 'self') @@ -256,6 +259,9 @@ export class JitCodeGenerator extends CodeGenerator{ this.result.write('} else {') this.result.right().nl() + // For test + this.result.write(`#ifdef TEST64`).nl().write('puts("Execute original function");').nl().write('#endif').nl() + this.result.write('return '); this.functionCall(node, fenv, originalFuncName, funcType, funcType.paramTypes, 'self') this.signatures += this.makeFunctionStruct(originalFuncName, funcType, false) @@ -309,10 +315,10 @@ export class JitCodeGenerator extends CodeGenerator{ const paramName = (node.params[i] as AST.Identifier).name const info = fenv.table.lookup(paramName) if (info !== undefined) { - const name = info.transpiledName(paramName) - const check = checkType(name, targetParamTypes[i]); + const check = checkType(fenv, targetParamTypes[i]); if (check) { - paramSig.push(check); + const name = info.transpiledName(paramName) + paramSig.push(`${check}${name})`); } } } diff --git a/server/src/server/session.ts b/server/src/server/session.ts index 2960a84..f27c206 100644 --- a/server/src/server/session.ts +++ b/server/src/server/session.ts @@ -61,7 +61,6 @@ export default class Session { public executeWithProfiling(tsString: string) { this.currentCodeId += 1; - const ast = runBabelParser(tsString, 1) const codeGenerator = (initializerName: string, codeId: number, moduleId: number) => { return new JitCodeGenerator(initializerName, codeId, moduleId, this.profiler, tsString); @@ -72,7 +71,10 @@ export default class Session { } const start = performance.now(); + // Transpile + const ast = runBabelParser(tsString, 1); + convertAst(ast, this.profiler); const tResult = jitTranspile(this.currentCodeId, ast, typeChecker, codeGenerator, this.nameTable, undefined) const entryPointName = tResult.main; const cString = cProlog + tResult.code; @@ -105,11 +107,9 @@ export default class Session { } // Transpile - const ast = runBabelParser(func.src, 1); const start = performance.now(); - + const ast = runBabelParser(func.src, 1); convertAst(ast, this.profiler); - // const tResult = transpile(0, func.src, this.nameTable, undefined, -1, ast, codeGenerator); const tResult = jitTranspile(this.currentCodeId, ast, typeChecker, codeGenerator, this.nameTable, undefined) const entryPointName = tResult.main; const cString = cProlog + tResult.code; diff --git a/server/tests/jit/jit-code-generator.test.ts b/server/tests/jit/jit-code-generator.test.ts index 29eefb3..16e263e 100644 --- a/server/tests/jit/jit-code-generator.test.ts +++ b/server/tests/jit/jit-code-generator.test.ts @@ -288,7 +288,7 @@ print(add(1, 5.5, false)) const func = profiler.getFunctionProfileById(0); if (func === undefined) throw new Error(`Cannot fine func.`) - profiler.setFuncSpecializedType(0, ["integer", "integer", "undefined", "undefined"].map(t => typeStringToStaticType(t, result1.names))) + profiler.setFuncSpecializedType(0, ["integer", "float", "boolean", "undefined"].map(t => typeStringToStaticType(t, result1.names))) const file2 = tempCFilePath('file2') const result2 = compile(1, func.src, profiler, file2, result1.names) @@ -296,7 +296,7 @@ print(add(1, 5.5, false)) const file3 = tempCFilePath('file3') const result3 = compile(2, src3, profiler, file3, result2.names) expect(execute([file0, file1, file2, file3], [result1.main, result2.main, result3.main], tempCFilePath('file4'), tempExecutableFilePath('bscript'))) - .toEqual(`5.400000\n12.000000\n`) + .toEqual(`5.400000\nExecute specialized function\n12.000000\n`) }) test('jit compile: string', () => { @@ -329,7 +329,7 @@ printStr("world"); const file3 = tempCFilePath('file3') const result3 = compile(2, src3, profiler, file3, result2.names) expect(execute([file0, file1, file2, file3], [result1.main, result2.main, result3.main], tempCFilePath('file4'), tempExecutableFilePath('bscript'))) - .toEqual(`hello\nworld\n`) + .toEqual(`hello\nExecute specialized function\nworld\n`) }) test('jit compile: intarray, floatarray, boolarray', () => { @@ -362,7 +362,7 @@ print(add0([1, 3], [1.1, 4.4], [false, false])); const file3 = tempCFilePath('file3') const result3 = compile(2, src3, profiler, file3, result2.names) expect(execute([file0, file1, file2, file3], [result1.main, result2.main, result3.main], tempCFilePath('file4'), tempExecutableFilePath('bscript'))) - .toEqual(`2.100000\n3.200000\n`) + .toEqual(`2.100000\nExecute specialized function\n3.200000\n`) }) test('jit compile: anyarray, array', () => { @@ -398,7 +398,7 @@ print(aarr0(aarr, arr)); const file3 = tempCFilePath('file3') const result3 = compile(2, src3, profiler, file3, result2.names) expect(execute([file0, file1, file2, file3], [result1.main, result2.main, result3.main], tempCFilePath('file4'), tempExecutableFilePath('bscript'))) - .toEqual(`1\n1\n`) + .toEqual(`1\nExecute specialized function\n1\n`) }) test('jit compile: class', () => { @@ -442,7 +442,7 @@ print(area(new Rectangle(3, 4))) const file3 = tempCFilePath('file3') const result3 = compile(2, src3, profiler, file3, result2.names) expect(execute([file0, file1, file2, file3], [result1.main, result2.main, result3.main], tempCFilePath('file4'), tempExecutableFilePath('bscript'))) - .toEqual(`12\n12\n`) + .toEqual(`12\nExecute specialized function\n12\n`) }) test('jit compile: class array', () => { @@ -490,7 +490,7 @@ print(areas([new Rectangle(11, 4), new Rectangle(11, 4), new Rectangle(11, 4)])) const file3 = tempCFilePath('file3') const result3 = compile(2, src3, profiler, file3, result2.names) expect(execute([file0, file1, file2, file3], [result1.main, result2.main, result3.main], tempCFilePath('file4'), tempExecutableFilePath('bscript'))) - .toEqual(`132\n132\n`) + .toEqual(`132\nExecute specialized function\n132\n`) }) test('jit compile: function redefinition after jit compile', () => { @@ -533,5 +533,5 @@ print(add(4, 5)) const file4 = tempCFilePath('file4') const result4 = compile(3, src4, profiler, file4, result3.names) expect(execute([file0, file1, file2, file3, file4], [result1.main, result2.main, result3.main, result4.main], tempCFilePath('file5'), tempExecutableFilePath('bscript'))) - .toEqual(`9\n9\n11\n`) + .toEqual(`9\nExecute specialized function\n9\nExecute specialized function\n11\n`) }) \ No newline at end of file diff --git a/server/tests/jit/test-jit-utils.ts b/server/tests/jit/test-jit-utils.ts index 37868c7..efae49a 100644 --- a/server/tests/jit/test-jit-utils.ts +++ b/server/tests/jit/test-jit-utils.ts @@ -20,6 +20,7 @@ function performance_now(): integer { return 0 } const prologCcode = `/* To compile, cc -DTEST64 this_file.c c-runtime.c */ #include "../../microcontroller/core/include/c-runtime.h" #include "../../microcontroller/core/include/profiler.h" +#include ` const prologCcode2 = ` diff --git a/server/tests/transpiler/transpile.test.ts b/server/tests/transpiler/transpile.test.ts index 42cebbf..03a51af 100644 --- a/server/tests/transpiler/transpile.test.ts +++ b/server/tests/transpiler/transpile.test.ts @@ -10,7 +10,7 @@ test("transpile", () => { }) const bsSrc = ` -let sarr: any[][] = [[]] +let sarr: string[] = ['hello'] ` test("playground", () => { From e6545576532a979cbaaa70fc038e753d6ae40654 Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Fri, 22 Nov 2024 21:11:34 +0900 Subject: [PATCH 3/3] Patch --- notebook/src/hooks/repl-context.tsx | 3 +-- server/src/server/session.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/notebook/src/hooks/repl-context.tsx b/notebook/src/hooks/repl-context.tsx index 70aec2c..a4c5aef 100644 --- a/notebook/src/hooks/repl-context.tsx +++ b/notebook/src/hooks/repl-context.tsx @@ -56,7 +56,7 @@ export default function ReplProvider({children}: {children: ReactNode}) { const dram = useMemory('DRAM') const bluetooth = useRef(new Bluetooth()) - // let onExecutionComplete = useRef((executionTime: number) => {}) + // To use these variables in callbacks const latestCellRef = useRef(latestCell) latestCellRef.current = latestCell @@ -195,7 +195,6 @@ export default function ReplProvider({children}: {children: ReactNode}) { } } - return (