diff options
Diffstat (limited to 'html/kgame/script.js')
-rw-r--r-- | html/kgame/script.js | 162 |
1 files changed, 110 insertions, 52 deletions
diff --git a/html/kgame/script.js b/html/kgame/script.js index a11d5f5..ed71eeb 100644 --- a/html/kgame/script.js +++ b/html/kgame/script.js @@ -74,7 +74,7 @@ document.addEventListener('DOMContentLoaded', () => { code = code.replace(/\s+/g, ' ').trim(); // Define all operators and special characters - const operators = ['+', '-', '*', '/', '%', '(', ')', '!', '@', ':', '=', '<', '>', "'"]; + const operators = ['+', '-', '*', '/', '%', '(', ')', '!', '@', ':', '=', '<', '>', "'", '|', '$', '#', '~']; // Add spaces around all operators operators.forEach(op => { @@ -102,10 +102,9 @@ document.addEventListener('DOMContentLoaded', () => { function parseAtom() { let token = tokens.shift(); if (!token) throw new Error("Unexpected end of expression"); - console.log('Parsing atom:', token, 'Remaining tokens:', tokens); if (token === '(') { - const value = parseAddSub(); // Start parsing inside parenthesis + const value = parseAddSub(); if (tokens.length === 0) { throw new Error("Missing closing parenthesis"); } @@ -119,49 +118,26 @@ document.addEventListener('DOMContentLoaded', () => { if (typeof operand !== 'number' || !Number.isInteger(operand) || operand < 0) { throw new Error("Operand for ! (iota) must be a non-negative integer"); } - // Only generate indices that fit within our grid const maxIndex = GRID_SIZE * GRID_SIZE; - return Array.from({length: Math.min(operand, maxIndex)}, (_, i) => i); - } else if (token === "'") { // Each adverb - const operand = parseAtom(); - if (!Array.isArray(operand)) { - throw new Error("Each adverb (') requires an array operand"); - } - return operand.map(x => Array.isArray(x) ? x.map(y => y) : x); - } else if (token === '/') { // Over adverb - const operand = parseAtom(); - if (!Array.isArray(operand)) { - throw new Error("Over adverb (/) requires an array operand"); - } - return operand.reduce((a, b) => { - if (Array.isArray(a) && Array.isArray(b)) { - return a.map((x, i) => x + b[i]); - } - return a + b; - }); - } else if (token === 'G') { - // Return the grid as a flat array of [row,col] pairs - const result = []; - for (let row = 0; row < GRID_SIZE; row++) { - for (let col = 0; col < GRID_SIZE; col++) { - result.push([row, col]); - } - } + const result = Array.from({length: Math.min(operand, maxIndex)}, (_, i) => i); + console.log(`Iota generated array of length ${result.length}, first few values:`, result.slice(0, 5)); return result; - } else if (token === 'where') { - if (tokens.shift() !== 'G') throw new Error("Expected 'G' after 'where'"); - if (tokens.shift() !== '=') throw new Error("Expected '=' after 'where G'"); - if (tokens.shift() !== '1') throw new Error("Expected '1' after 'where G='"); - // Find all coordinates where G[row][col] === 1 - const indices = []; - for(let row = 0; row < GRID_SIZE; row++) { - for(let col = 0; col < GRID_SIZE; col++) { - if (G[row][col] === 1) { - indices.push(row * GRID_SIZE + col); // Convert to 1D index - } - } + } else if (token === '~') { // Not operator + const operand = parseAtom(); + if (Array.isArray(operand)) { + const result = operand.map(x => { + const val = x === 0 ? 1 : 0; + console.log(`Not operation: ${x} -> ${val}`); + return val; + }); + console.log(`Not operation on array, first few results:`, result.slice(0, 5)); + console.log(`Input array first few values:`, operand.slice(0, 5)); + return result; + } else { + const result = operand === 0 ? 1 : 0; + console.log(`Not operation (scalar): ${operand} -> ${result}`); + return result; } - return indices; } else if (/^-?\d+$/.test(token)) { return parseInt(token, 10); } else { @@ -169,6 +145,47 @@ document.addEventListener('DOMContentLoaded', () => { } } + function parseUnary() { + let token = tokens[0]; + if (token === '|' || token === '$' || token === '#') { + tokens.shift(); + const operand = parseUnary(); + let result; + switch (token) { + case '|': + result = [...operand].reverse(); + break; + case '$': + if (!Array.isArray(operand)) { + throw new Error("Rotate operator ($) requires an array operand"); + } + const size = Math.sqrt(operand.length); + if (size * size !== operand.length) { + throw new Error("Rotate operator ($) requires a square array"); + } + result = []; + for (let col = 0; col < size; col++) { + for (let row = size - 1; row >= 0; row--) { + result.push(operand[row * size + col]); + } + } + break; + case '#': + if (!Array.isArray(operand)) { + throw new Error("Reshape operator (#) requires an array operand"); + } + result = []; + for (let i = 0; i < GRID_SIZE; i++) { + result.push(operand.slice(i * GRID_SIZE, (i + 1) * GRID_SIZE)); + } + result = result.flat(); + break; + } + return result; + } + return parseAtom(); + } + function applyOperation(a, b, op) { const isAList = Array.isArray(a); const isBList = Array.isArray(b); @@ -180,13 +197,12 @@ document.addEventListener('DOMContentLoaded', () => { case '-': result = x - y; break; case '*': result = x * y; break; case '%': result = y === 0 ? 0 : x % y; break; - case '/': result = y === 0 ? 0 : Math.floor(x / y); break; // Use integer division + case '/': result = y === 0 ? 0 : Math.floor(x / y); break; case '<': result = x < y ? 1 : 0; break; case '>': result = x > y ? 1 : 0; break; case '=': result = x === y ? 1 : 0; break; default: throw new Error(`Unknown operator: ${op}`); } - console.log(`Operation ${op}: ${x} ${op} ${y} = ${result}`); return result; }; @@ -198,29 +214,59 @@ document.addEventListener('DOMContentLoaded', () => { // Handle array operations const arrayOp = (arr, val) => { if (Array.isArray(arr)) { - return arr.map(x => arrayOp(x, val)); + const result = arr.map(x => arrayOp(x, val)); + if (op === '/' || op === '%') { + console.log(`Array operation ${op} with ${val}, first few results:`, result.slice(0, 5)); + } + return result; } return scalarOp(arr, val); }; if (isAList && !isBList) { - return arrayOp(a, b); + const result = arrayOp(a, b); + if (op === '+') { + console.log(`Array + scalar operation, first few values:`, { + array: a.slice(0, 5), + scalar: b, + result: result.slice(0, 5) + }); + } + return result; } else if (!isAList && isBList) { - return arrayOp(b, a); + const result = arrayOp(b, a); + if (op === '+') { + console.log(`Scalar + array operation, first few values:`, { + scalar: a, + array: b.slice(0, 5), + result: result.slice(0, 5) + }); + } + return result; } else { // Both are arrays if (a.length !== b.length) { throw new Error(`List length mismatch for operator ${op}: ${a.length} vs ${b.length}`); } - return a.map((x, i) => arrayOp(x, b[i])); + const result = a.map((x, i) => { + const val = arrayOp(x, b[i]); + if (op === '+') { + console.log(`Adding values at index ${i}: ${x} + ${b[i]} = ${val}`); + } + return val; + }); + if (op === '+') { + console.log(`Array addition, first few results:`, result.slice(0, 5)); + } + return result; } } function parseMulDivMod() { - let left = parseAtom(); + let left = parseUnary(); while (tokens.length > 0 && (tokens[0] === '*' || tokens[0] === '%' || tokens[0] === '/')) { const op = tokens.shift(); - const right = parseAtom(); + const right = parseUnary(); left = applyOperation(left, right, op); } return left; @@ -246,7 +292,16 @@ document.addEventListener('DOMContentLoaded', () => { return left; } - return parseComparison(); + function parseNot() { + let left = parseComparison(); + while (tokens.length > 0 && tokens[0] === '~') { + tokens.shift(); + left = Array.isArray(left) ? left.map(x => x === 0 ? 1 : 0) : (left === 0 ? 1 : 0); + } + return left; + } + + return parseNot(); } // Main execution function @@ -297,6 +352,9 @@ document.addEventListener('DOMContentLoaded', () => { if (row >= 0 && row < GRID_SIZE && col >= 0 && col < GRID_SIZE) { const valueToAssign = valuesArray[i % valuesArray.length]; + if (count < 5) { // Only log first few assignments + console.log(`Assignment [${row},${col}]: ${valueToAssign} (from index ${idx})`); + } G[row][col] = valueToAssign % 2; return count + 1; } |