🎉 initial commit: Nyash Programming Language完成版

🚀 主要機能:
• Everything is Box哲学による革新的アーキテクチャ
• WebAssemblyブラウザー対応プレイグラウンド
• アーティスト協同制作デモ - 複数Boxインスタンス実証
• 視覚的デバッグシステム - DebugBox完全統合
• static box Mainパターン - メモリ安全設計

 言語機能:
• NOT/AND/OR/除算演算子完全実装
• ジェネリクス/テンプレートシステム
• 非同期処理(nowait/await)
• try/catchエラーハンドリング
• Canvas統合グラフィックス

🎨 ブラウザー体験:
• 9種類のインタラクティブデモ
• リアルタイムコード実行
• WebCanvas/WebConsole/WebDisplay
• モバイル対応完了

🤖 Built with Claude Code collaboration
Ready for public release!
This commit is contained in:
Moe Charm
2025-08-09 15:14:44 +09:00
commit 0bed0c0271
129 changed files with 33189 additions and 0 deletions

View File

@ -0,0 +1,93 @@
# 🌐 Nyash WebAssembly Project
Nyash programming language running in the browser via WebAssembly!
## 🚀 Quick Start
```bash
# Install wasm-pack (if not already installed)
cargo install wasm-pack
# Build WASM module
cd /mnt/c/git/nyash
wasm-pack build --target web --out-dir projects/nyash-wasm/pkg
# Start local server
cd projects/nyash-wasm
python3 -m http.server 8000
# Open browser
# Navigate to: http://localhost:8000/nyash_playground.html
```
## 🎯 Features
- **🐱 Full Nyash Language** - Complete interpreter running in browser
- **📦 ConsoleBox** - Browser console integration
- **🔍 DebugBox** - Real-time debugging in browser
- **⚡ All Operators** - NOT/AND/OR/Division fully supported
- **🎮 Interactive Playground** - Code editor with examples
## 📁 File Structure
```
projects/nyash-wasm/
├── README.md # This file
├── nyash_playground.html # Interactive playground
├── build.sh # Build script
└── pkg/ # Generated WASM files (after build)
├── nyash_rust.js
├── nyash_rust_bg.wasm
└── ...
```
## 🎨 Example Code
```nyash
// Browser console output
console = new ConsoleBox()
console.log("Hello from Nyash in Browser!")
// Math with new operators
x = 10
y = 3
console.log("Division: " + (x / y)) // 3.333...
console.log("Logic: " + (x > 5 and y < 5)) // true
// Debugging
debug = new DebugBox()
debug.startTracking()
debug.trackBox(x, "my_number")
console.log(debug.memoryReport())
```
## 🔧 Development
### Build Process
1. Rust code compiled to WebAssembly using wasm-bindgen
2. NyashWasm struct exported with eval() method
3. ConsoleBox uses web-sys for browser console access
4. HTML playground provides interactive interface
### Architecture
```
Browser JavaScript
NyashWasm.eval(code)
NyashInterpreter (Rust)
ConsoleBox → web_sys::console
```
## 🎉 Coming Soon
- **DOMBox** - DOM manipulation from Nyash
- **CanvasBox** - Graphics and games
- **EventBox** - Mouse/keyboard event handling
- **HTTPBox** - Network requests
- **Sample Apps** - Snake game, Calculator, etc.
---
**Everything is Box, even in the browser! 🐱**

View File

@ -0,0 +1,31 @@
#!/bin/bash
# 🚀 Nyash WASM Build Script
set -e # Exit on error
echo "🐱 Building Nyash WebAssembly..."
# Check if wasm-pack is installed
if ! command -v wasm-pack &> /dev/null; then
echo "❌ wasm-pack not found! Installing..."
cargo install wasm-pack
fi
# Go to project root
cd "$(dirname "$0")/../.."
# Build WASM package
echo "🔨 Building WASM package..."
wasm-pack build --target web --out-dir projects/nyash-wasm/pkg
# Return to wasm project directory
cd projects/nyash-wasm
echo "✅ Build complete!"
echo ""
echo "🌐 To test in browser:"
echo "1. python3 -m http.server 8000"
echo "2. Open: http://localhost:8000/nyash_playground.html"
echo ""
echo "📁 Generated files in pkg/:"
ls -la pkg/ 2>/dev/null || echo " (run build first)"

View File

@ -0,0 +1,649 @@
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🎨 Nyash Canvas Playground - Everything is Box</title>
<style>
body {
font-family: 'Monaco', 'Consolas', monospace;
margin: 20px;
background: linear-gradient(135deg, #1e3c72, #2a5298);
color: #ffffff;
min-height: 100vh;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
h1 {
color: #fff;
text-align: center;
margin-bottom: 10px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.subtitle {
text-align: center;
color: #b3d9ff;
margin-bottom: 30px;
font-size: 18px;
}
.demo-section {
background: rgba(255,255,255,0.1);
backdrop-filter: blur(10px);
border-radius: 15px;
padding: 25px;
margin-bottom: 30px;
border: 1px solid rgba(255,255,255,0.2);
}
.demo-title {
color: #ffeb3b;
font-size: 24px;
margin-bottom: 15px;
display: flex;
align-items: center;
gap: 10px;
}
.demo-description {
color: #e0e0e0;
margin-bottom: 20px;
line-height: 1.6;
}
.canvas-container {
display: flex;
gap: 20px;
align-items: flex-start;
flex-wrap: wrap;
}
.canvas-wrapper {
background: white;
border-radius: 10px;
padding: 10px;
box-shadow: 0 8px 32px rgba(0,0,0,0.3);
}
canvas {
border: 2px solid #4ecdc4;
border-radius: 8px;
display: block;
}
.canvas-info {
flex: 1;
min-width: 300px;
}
.feature-list {
list-style: none;
padding: 0;
}
.feature-list li {
background: rgba(76, 175, 80, 0.2);
margin: 8px 0;
padding: 10px 15px;
border-radius: 8px;
border-left: 4px solid #4caf50;
}
.controls {
margin-top: 20px;
}
.btn {
background: linear-gradient(45deg, #ff6b6b, #ff8e8e);
color: white;
border: none;
padding: 12px 24px;
border-radius: 25px;
cursor: pointer;
font-size: 16px;
margin: 5px;
transition: transform 0.2s;
box-shadow: 0 4px 15px rgba(255, 107, 107, 0.3);
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(255, 107, 107, 0.4);
}
.stats {
background: rgba(0,0,0,0.3);
padding: 15px;
border-radius: 8px;
margin-top: 15px;
font-family: monospace;
}
.philosophy {
text-align: center;
font-size: 20px;
color: #ffeb3b;
margin: 40px 0;
font-weight: bold;
text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
}
</style>
</head>
<body>
<div class="container">
<h1>🎨 Nyash Canvas Playground</h1>
<div class="subtitle">Everything is Box - WebCanvasBox in Action</div>
<div class="philosophy">
"すべては Box である" - Canvas も粒子も複素数も、みんな Box
</div>
<!-- パーティクル爆発システム -->
<div class="demo-section">
<div class="demo-title">
🌟 Particle Explosion System
</div>
<div class="demo-description">
各粒子が独立した ParticleBox として動作する美しい爆発エフェクト。物理演算、重力、空気抵抗、寿命システムを完備。虹色パーティクルが舞い踊る Everything is Box の究極実証!
</div>
<div class="canvas-container">
<div class="canvas-wrapper">
<canvas id="particle-canvas" width="800" height="600"></canvas>
</div>
<div class="canvas-info">
<ul class="feature-list">
<li>🎆 各粒子が独立した ParticleBox</li>
<li>🌈 虹色ランダムカラーシステム</li>
<li>⚡ リアルタイム物理演算</li>
<li>💨 重力・空気抵抗・寿命管理</li>
<li>✨ 美しいトレイルエフェクト</li>
<li>🎮 自動連続爆発システム</li>
</ul>
<div class="controls">
<button class="btn" onclick="createBigExplosion()">💥 大爆発!</button>
<button class="btn" onclick="createRandomExplosions()">🎆 連続爆発</button>
<button class="btn" onclick="clearParticles()">🧹 クリア</button>
</div>
<div class="stats" id="particle-stats">
アクティブ粒子: 0<br>
総爆発回数: 0<br>
Everything is Box!
</div>
</div>
</div>
</div>
<!-- フラクタル -->
<div class="demo-section">
<div class="demo-title">
📊 Mandelbrot Fractal Generator
</div>
<div class="demo-description">
ComplexBox による複素数計算でマンデルブロ集合を描画。MathBox との完璧な統合により、数学的美しさをWebCanvas上に実現。Everything is Box の数学的表現!
</div>
<div class="canvas-container">
<div class="canvas-wrapper">
<canvas id="fractal-canvas" width="400" height="400"></canvas>
</div>
<div class="canvas-info">
<ul class="feature-list">
<li>🔢 ComplexBox による複素数演算</li>
<li>🌀 マンデルブロ集合の完全計算</li>
<li>🎨 美しいカラーグラデーション</li>
<li>🔍 ズーム・中心移動機能</li>
<li>⚡ 高速反復計算アルゴリズム</li>
<li>📐 MathBox との統合</li>
</ul>
<div class="controls">
<button class="btn" onclick="renderBasicFractal()">🌀 基本フラクタル</button>
<button class="btn" onclick="renderZoomedFractal()">🔍 ズーム版</button>
<button class="btn" onclick="renderColorfulFractal()">🌈 カラフル版</button>
</div>
<div class="stats" id="fractal-stats">
ズーム: 1.0x<br>
反復計算: 50回<br>
Complex Mathematics!
</div>
</div>
</div>
</div>
<!-- Game of Life -->
<div class="demo-section">
<div class="demo-title">
🧬 Conway's Game of Life
</div>
<div class="demo-description">
各セルが独立した CellBox として生命活動をシミュレート。セルラーオートマトンの美しい進化過程をリアルタイム可視化。生命の神秘を Everything is Box で表現!
</div>
<div class="canvas-container">
<div class="canvas-wrapper">
<canvas id="life-canvas" width="400" height="300"></canvas>
</div>
<div class="canvas-info">
<ul class="feature-list">
<li>🔬 各セルが独立した CellBox</li>
<li>🌱 Conway の 4つの生命ルール</li>
<li>🎮 グライダー・点滅等のパターン</li>
<li>📈 世代追跡・統計表示</li>
<li>🎲 ランダム初期化機能</li>
<li>⏱️ リアルタイム進化</li>
</ul>
<div class="controls">
<button class="btn" onclick="startLife('random')">🎲 ランダム開始</button>
<button class="btn" onclick="startLife('glider')">✈️ グライダー</button>
<button class="btn" onclick="startLife('blinker')">💫 点滅パターン</button>
<button class="btn" onclick="pauseLife()">⏸️ 一時停止</button>
</div>
<div class="stats" id="life-stats">
世代: 0<br>
生存セル: 0<br>
Cellular Automaton!
</div>
</div>
</div>
</div>
<div class="philosophy">
🐱 Everything is Box, Everything is Beautiful! 🎨✨
</div>
</div>
<script type="module">
// WebCanvasBox シミュレーション
class WebCanvasBox {
constructor(canvasId, width, height) {
this.canvas = document.getElementById(canvasId);
this.ctx = this.canvas.getContext('2d');
this.width = width;
this.height = height;
}
setFillStyle(color) {
this.ctx.fillStyle = color;
}
setStrokeStyle(color) {
this.ctx.strokeStyle = color;
}
setLineWidth(width) {
this.ctx.lineWidth = width;
}
fillRect(x, y, width, height) {
this.ctx.fillRect(x, y, width, height);
}
strokeRect(x, y, width, height) {
this.ctx.strokeRect(x, y, width, height);
}
beginPath() {
this.ctx.beginPath();
}
arc(x, y, radius, startAngle, endAngle) {
this.ctx.arc(x, y, radius, startAngle, endAngle);
}
fill() {
this.ctx.fill();
}
stroke() {
this.ctx.stroke();
}
fillText(text, x, y) {
this.ctx.fillText(text, x, y);
}
clear() {
this.ctx.clearRect(0, 0, this.width, this.height);
}
}
// パーティクルシステム
class ParticleBox {
constructor(x, y) {
this.x = x;
this.y = y;
this.vx = (Math.random() - 0.5) * 10;
this.vy = Math.random() * -8 - 2;
this.size = Math.random() * 4 + 2;
this.color = ['red', 'orange', 'yellow', 'lime', 'cyan', 'magenta'][Math.floor(Math.random() * 6)];
this.life = 100;
this.maxLife = 100;
this.gravity = 0.1;
}
update() {
this.vy += this.gravity;
this.x += this.vx;
this.y += this.vy;
this.vx *= 0.99;
this.vy *= 0.98;
this.life--;
this.size *= 0.995;
return this.life > 0;
}
draw(canvas) {
if (this.life > 0) {
canvas.setFillStyle(this.color);
canvas.beginPath();
canvas.arc(this.x, this.y, this.size, 0, Math.PI * 2);
canvas.fill();
if (this.life > this.maxLife * 0.8) {
canvas.setFillStyle('white');
canvas.beginPath();
canvas.arc(this.x, this.y, this.size * 0.3, 0, Math.PI * 2);
canvas.fill();
}
}
}
}
// パーティクルシステム管理
let particles = [];
let explosionCount = 0;
let animationId;
const particleCanvas = new WebCanvasBox('particle-canvas', 800, 600);
function createExplosion(x, y, count = 30) {
for (let i = 0; i < count; i++) {
particles.push(new ParticleBox(x, y));
}
explosionCount++;
}
function animateParticles() {
// 背景(トレイルエフェクト)
particleCanvas.setFillStyle('rgba(0,0,0,0.1)');
particleCanvas.fillRect(0, 0, 800, 600);
// パーティクル更新・描画
particles = particles.filter(particle => {
if (particle.update()) {
particle.draw(particleCanvas);
return true;
}
return false;
});
// 統計更新
document.getElementById('particle-stats').innerHTML = `
アクティブ粒子: ${particles.length}<br>
総爆発回数: ${explosionCount}<br>
Everything is Box!
`;
animationId = requestAnimationFrame(animateParticles);
}
// 自動爆発開始
particleCanvas.setFillStyle('black');
particleCanvas.fillRect(0, 0, 800, 600);
animateParticles();
// 定期的な自動爆発
setInterval(() => {
if (Math.random() < 0.3) {
const x = Math.random() * 700 + 50;
const y = Math.random() * 500 + 50;
createExplosion(x, y, 20);
}
}, 2000);
// パーティクル制御関数
window.createBigExplosion = () => {
createExplosion(400, 300, 60);
};
window.createRandomExplosions = () => {
for (let i = 0; i < 5; i++) {
setTimeout(() => {
const x = Math.random() * 600 + 100;
const y = Math.random() * 400 + 100;
createExplosion(x, y, 25);
}, i * 300);
}
};
window.clearParticles = () => {
particles = [];
};
// フラクタル描画
const fractalCanvas = new WebCanvasBox('fractal-canvas', 400, 400);
function mandelbrot(c_real, c_imag, max_iter = 50) {
let z_real = 0, z_imag = 0;
let iter = 0;
while (iter < max_iter) {
const z_real_temp = z_real * z_real - z_imag * z_imag + c_real;
z_imag = 2 * z_real * z_imag + c_imag;
z_real = z_real_temp;
if (z_real * z_real + z_imag * z_imag > 4) {
return iter;
}
iter++;
}
return max_iter;
}
function getColor(iterations, maxIter) {
if (iterations === maxIter) return 'black';
const ratio = iterations / maxIter;
if (ratio < 0.25) return 'blue';
if (ratio < 0.5) return 'cyan';
if (ratio < 0.75) return 'yellow';
return 'red';
}
function renderFractal(zoom = 1, centerX = -0.5, centerY = 0) {
fractalCanvas.clear();
for (let y = 0; y < 400; y += 2) {
for (let x = 0; x < 400; x += 2) {
const real = (x - 200) / (200 / 2) / zoom + centerX;
const imag = (y - 200) / (200 / 2) / zoom + centerY;
const iterations = mandelbrot(real, imag);
const color = getColor(iterations, 50);
fractalCanvas.setFillStyle(color);
fractalCanvas.fillRect(x, y, 2, 2);
}
}
fractalCanvas.setFillStyle('white');
fractalCanvas.fillText(`Zoom: ${zoom}x`, 10, 20);
fractalCanvas.fillText('Mandelbrot Set', 10, 40);
}
window.renderBasicFractal = () => {
renderFractal(1, -0.5, 0);
document.getElementById('fractal-stats').innerHTML = `
ズーム: 1.0x<br>
中心: (-0.5, 0.0)<br>
Complex Mathematics!
`;
};
window.renderZoomedFractal = () => {
renderFractal(3, -0.8, 0.156);
document.getElementById('fractal-stats').innerHTML = `
ズーム: 3.0x<br>
中心: (-0.8, 0.156)<br>
Zoomed Beauty!
`;
};
window.renderColorfulFractal = () => {
renderFractal(2, -0.235125, 0.827215);
document.getElementById('fractal-stats').innerHTML = `
ズーム: 2.0x<br>
中心: (-0.235125, 0.827215)<br>
Colorful Patterns!
`;
};
// 初期フラクタル描画
renderBasicFractal();
// Game of Life
const lifeCanvas = new WebCanvasBox('life-canvas', 400, 300);
let lifeGrid = [];
let lifeRunning = false;
let lifeGeneration = 0;
const GRID_WIDTH = 40;
const GRID_HEIGHT = 30;
const CELL_SIZE = 10;
function initLife() {
lifeGrid = [];
for (let y = 0; y < GRID_HEIGHT; y++) {
lifeGrid[y] = [];
for (let x = 0; x < GRID_WIDTH; x++) {
lifeGrid[y][x] = false;
}
}
lifeGeneration = 0;
}
function setPattern(pattern) {
initLife();
if (pattern === 'random') {
for (let y = 0; y < GRID_HEIGHT; y++) {
for (let x = 0; x < GRID_WIDTH; x++) {
lifeGrid[y][x] = Math.random() < 0.3;
}
}
} else if (pattern === 'glider') {
const centerX = Math.floor(GRID_WIDTH / 2);
const centerY = Math.floor(GRID_HEIGHT / 2);
lifeGrid[centerY][centerX + 1] = true;
lifeGrid[centerY + 1][centerX + 2] = true;
lifeGrid[centerY + 2][centerX] = true;
lifeGrid[centerY + 2][centerX + 1] = true;
lifeGrid[centerY + 2][centerX + 2] = true;
} else if (pattern === 'blinker') {
const centerX = Math.floor(GRID_WIDTH / 2);
const centerY = Math.floor(GRID_HEIGHT / 2);
lifeGrid[centerY][centerX - 1] = true;
lifeGrid[centerY][centerX] = true;
lifeGrid[centerY][centerX + 1] = true;
}
}
function countNeighbors(x, y) {
let count = 0;
for (let dy = -1; dy <= 1; dy++) {
for (let dx = -1; dx <= 1; dx++) {
if (dx === 0 && dy === 0) continue;
const nx = x + dx;
const ny = y + dy;
if (nx >= 0 && nx < GRID_WIDTH && ny >= 0 && ny < GRID_HEIGHT) {
if (lifeGrid[ny][nx]) count++;
}
}
}
return count;
}
function updateLife() {
const newGrid = [];
for (let y = 0; y < GRID_HEIGHT; y++) {
newGrid[y] = [];
for (let x = 0; x < GRID_WIDTH; x++) {
const neighbors = countNeighbors(x, y);
const alive = lifeGrid[y][x];
if (alive) {
newGrid[y][x] = neighbors === 2 || neighbors === 3;
} else {
newGrid[y][x] = neighbors === 3;
}
}
}
lifeGrid = newGrid;
lifeGeneration++;
}
function drawLife() {
lifeCanvas.setFillStyle('white');
lifeCanvas.fillRect(0, 0, 400, 300);
let aliveCount = 0;
for (let y = 0; y < GRID_HEIGHT; y++) {
for (let x = 0; x < GRID_WIDTH; x++) {
if (lifeGrid[y][x]) {
lifeCanvas.setFillStyle('lime');
aliveCount++;
} else {
lifeCanvas.setFillStyle('black');
}
lifeCanvas.fillRect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE);
lifeCanvas.setStrokeStyle('gray');
lifeCanvas.strokeRect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE);
}
}
lifeCanvas.setFillStyle('blue');
lifeCanvas.fillText(`Generation: ${lifeGeneration}`, 10, 20);
lifeCanvas.fillText(`Alive: ${aliveCount}`, 10, 40);
document.getElementById('life-stats').innerHTML = `
世代: ${lifeGeneration}<br>
生存セル: ${aliveCount}<br>
Cellular Automaton!
`;
}
function animateLife() {
if (lifeRunning) {
updateLife();
drawLife();
setTimeout(animateLife, 200);
}
}
window.startLife = (pattern) => {
setPattern(pattern);
lifeRunning = true;
animateLife();
};
window.pauseLife = () => {
lifeRunning = false;
};
// 初期化
initLife();
drawLife();
</script>
</body>
</html>

View File

@ -0,0 +1,807 @@
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🚀 Nyash Ultimate Playground - Everything is Box</title>
<style>
body {
font-family: 'Monaco', 'Consolas', monospace;
margin: 0;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #ffffff;
min-height: 100vh;
}
.container {
max-width: 1600px;
margin: 0 auto;
padding: 20px;
}
h1 {
color: #fff;
text-align: center;
font-size: 3em;
margin-bottom: 10px;
text-shadow: 3px 3px 6px rgba(0,0,0,0.4);
}
.subtitle {
text-align: center;
color: #e3f2fd;
margin-bottom: 40px;
font-size: 1.3em;
}
.demo-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 30px;
margin-bottom: 40px;
}
.demo-card {
background: rgba(255,255,255,0.15);
backdrop-filter: blur(15px);
border-radius: 20px;
padding: 25px;
border: 1px solid rgba(255,255,255,0.2);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.demo-card:hover {
transform: translateY(-5px);
box-shadow: 0 15px 40px rgba(0,0,0,0.3);
}
.demo-title {
color: #ffeb3b;
font-size: 1.8em;
margin-bottom: 15px;
display: flex;
align-items: center;
gap: 10px;
}
.demo-description {
color: #e8eaf6;
margin-bottom: 20px;
line-height: 1.6;
}
.demo-area {
background: rgba(0,0,0,0.3);
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
min-height: 300px;
position: relative;
overflow: hidden;
}
.btn {
background: linear-gradient(45deg, #ff6b6b, #ffa726);
color: white;
border: none;
padding: 12px 24px;
border-radius: 25px;
cursor: pointer;
font-size: 14px;
margin: 5px;
transition: all 0.3s;
box-shadow: 0 4px 15px rgba(255, 107, 107, 0.3);
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(255, 107, 107, 0.4);
}
.btn.secondary {
background: linear-gradient(45deg, #42a5f5, #26c6da);
}
canvas {
border: 2px solid rgba(255,255,255,0.3);
border-radius: 8px;
background: white;
}
.box-visualizer {
position: relative;
background: #1a237e;
border-radius: 10px;
overflow: hidden;
width: 100%;
height: 250px;
border: 2px solid #fff;
/* デバッグ用 */
min-height: 250px;
display: block;
}
.box-visualizer::before {
content: "Everything is Box Canvas";
position: absolute;
top: 10px;
left: 10px;
color: rgba(255,255,255,0.5);
font-size: 12px;
z-index: 1;
}
.box-element {
position: absolute;
background: linear-gradient(45deg, #ff4081, #f06292);
border-radius: 8px;
padding: 8px 12px;
color: white;
font-size: 12px;
font-weight: bold;
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
transition: all 0.5s ease;
cursor: pointer;
}
.box-element.integer {
background: linear-gradient(45deg, #4caf50, #66bb6a);
}
.box-element.string {
background: linear-gradient(45deg, #ff9800, #ffb74d);
}
.box-element.result {
background: linear-gradient(45deg, #e91e63, #ec407a);
border: 2px solid #fff;
}
.code-editor {
background: #263238;
border-radius: 8px;
padding: 15px;
font-family: 'Courier New', monospace;
color: #fff;
border: none;
width: 100%;
min-height: 150px;
resize: vertical;
}
.output-area {
background: #000;
color: #00ff00;
font-family: monospace;
padding: 15px;
border-radius: 8px;
min-height: 100px;
overflow-y: auto;
white-space: pre-wrap;
}
.lisp-demo {
display: flex;
gap: 15px;
}
.lisp-input, .lisp-output {
flex: 1;
}
.async-timeline {
height: 200px;
position: relative;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.1), transparent);
}
.async-event {
position: absolute;
background: #00bcd4;
color: white;
padding: 8px 12px;
border-radius: 15px;
font-size: 12px;
animation: slideRight 3s ease-in-out;
}
@keyframes slideRight {
0% { left: 0; opacity: 0; }
50% { opacity: 1; }
100% { left: 80%; opacity: 0.7; }
}
.philosophy-banner {
text-align: center;
font-size: 2em;
color: #ffeb3b;
margin: 50px 0;
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
background: rgba(255,235,59,0.1);
padding: 30px;
border-radius: 20px;
border: 2px solid rgba(255,235,59,0.3);
}
.stats-panel {
position: fixed;
top: 20px;
right: 20px;
background: rgba(0,0,0,0.8);
padding: 15px;
border-radius: 10px;
font-family: monospace;
font-size: 12px;
z-index: 1000;
}
.audio-visualizer {
width: 100%;
height: 100px;
background: #000;
border-radius: 8px;
}
.full-width {
grid-column: 1 / -1;
}
</style>
</head>
<body>
<div class="container">
<h1>🚀 Nyash Ultimate Playground</h1>
<div class="subtitle">Everything is Box - 究極のプログラミング哲学を体験せよ</div>
<div class="philosophy-banner">
🐱 "すべてはBoxである" - 数字も文字も関数も、みんなBox 🎨
</div>
<!-- 統計パネル -->
<div class="stats-panel" id="global-stats">
Total Boxes: 0<br>
Active Animations: 0<br>
Everything is Box!
</div>
<div class="demo-grid">
<!-- Everything is Box ビジュアライザー -->
<div class="demo-card">
<div class="demo-title">
🎨 Everything is Box Visualizer
</div>
<div class="demo-description">
Nyashコードの実行過程を視覚化IntegerBox、StringBox等がリアルタイムでやりとりする様子を見よう。
</div>
<div class="demo-area">
<div class="box-visualizer" id="box-canvas"></div>
</div>
<div>
<button class="btn" onclick="demoBasicMath()">🔢 基本計算</button>
<button class="btn" onclick="demoStringConcat()">📝 文字結合</button>
<button class="btn" onclick="demoComplexOp()">⚡ 複雑演算</button>
<button class="btn secondary" onclick="clearBoxes()">🧹 クリア</button>
</div>
</div>
<!-- ライブサウンドジェネレーター -->
<div class="demo-card">
<div class="demo-title">
🎵 Live Sound Generator
</div>
<div class="demo-description">
SoundBoxで音楽を生成コードを変更すると即座に音が変化する驚きの体験。
</div>
<div class="demo-area">
<textarea class="code-editor" id="sound-code" placeholder="// Nyash音楽コード例
Sound.play(440, 'sine')
Sound.chord([440, 554, 659], 'triangle')
Sound.sequence([220, 440, 880], 0.5)">// SoundBox デモ
freq = 440
Sound.play(freq, "sine")
Sound.delay(1000)
Sound.play(freq * 1.5, "triangle")</textarea>
<canvas class="audio-visualizer" id="audio-canvas" width="400" height="100"></canvas>
</div>
<div>
<button class="btn" onclick="playSound()">🎵 演奏開始</button>
<button class="btn" onclick="stopSound()">⏹️ 停止</button>
<button class="btn secondary" onclick="loadMelody()">🎼 メロディ例</button>
</div>
</div>
<!-- 非同期デモ -->
<div class="demo-card">
<div class="demo-title">
⚡ Async Box Communication
</div>
<div class="demo-description">
ChannelBoxによる非同期通信複数のBoxが並行して動作し、メッセージをやりとりする様子を観察。
</div>
<div class="demo-area">
<div class="async-timeline" id="async-timeline"></div>
<div class="output-area" id="async-output">非同期処理の結果がここに表示されます...</div>
</div>
<div>
<button class="btn" onclick="demoBasicAsync()">📤 基本通信</button>
<button class="btn" onclick="demoParallelAsync()">🔄 並列処理</button>
<button class="btn" onclick="demoPipeline()">⚡ パイプライン</button>
</div>
</div>
<!-- Lispインタープリター -->
<div class="demo-card">
<div class="demo-title">
🧠 Live Lisp Interpreter
</div>
<div class="demo-description">
NyashのLispインタープリターがリアルタイムで動作S式の評価過程を視覚的に追跡。
</div>
<div class="demo-area">
<div class="lisp-demo">
<div class="lisp-input">
<textarea class="code-editor" id="lisp-code" placeholder="Lisp式を入力...">(+ 1 2 3)
(* 4 5)
(define square (lambda (x) (* x x)))
(square 7)</textarea>
</div>
<div class="lisp-output">
<div class="output-area" id="lisp-output">結果がここに表示されます...</div>
</div>
</div>
</div>
<div>
<button class="btn" onclick="evalLisp()">🚀 実行</button>
<button class="btn" onclick="stepEval()">👣 ステップ実行</button>
<button class="btn secondary" onclick="loadLispExample()">📚 例を読込</button>
</div>
</div>
<!-- Canvas統合デモ (既存) -->
<div class="demo-card full-width">
<div class="demo-title">
🎆 Ultimate Canvas Integration
</div>
<div class="demo-description">
パーティクル、フラクタル、Game of Lifeが同時動作複数のCanvasBoxが協調する究極のデモ。
</div>
<div class="demo-area" style="min-height: 400px;">
<div style="display: flex; gap: 15px; flex-wrap: wrap; justify-content: center;">
<canvas id="mini-particles" width="200" height="150"></canvas>
<canvas id="mini-fractal" width="200" height="150"></canvas>
<canvas id="mini-life" width="200" height="150"></canvas>
</div>
</div>
<div style="text-align: center;">
<button class="btn" onclick="startUltimateDemo()">🌟 究極デモ開始</button>
<button class="btn" onclick="pauseAllCanvas()">⏸️ 一時停止</button>
<button class="btn secondary" onclick="resetAllCanvas()">🔄 リセット</button>
</div>
</div>
</div>
<div class="philosophy-banner">
🌟 Everything is Box, Everything is Beautiful, Everything is Nyash! 🚀
</div>
</div>
<script type="module">
// グローバル状態
let boxCount = 0;
let animationCount = 0;
let audioContext = null;
let audioNodes = [];
// 統計更新
function updateStats() {
document.getElementById('global-stats').innerHTML = `
Total Boxes: ${boxCount}<br>
Active Animations: ${animationCount}<br>
Everything is Box!
`;
}
// 1. Everything is Box ビジュアライザー
class BoxVisualizer {
constructor(containerId) {
this.container = document.getElementById(containerId);
console.log('BoxVisualizer container:', this.container);
this.boxes = [];
this.nextId = 1;
}
createBox(type, value, x, y) {
console.log(`Creating box: ${type}(${value}) at (${x}, ${y})`);
if (!this.container) {
console.error('Container not found!');
return null;
}
const box = document.createElement('div');
box.className = `box-element ${type}`;
box.textContent = `${type.toUpperCase()}(${value})`;
box.style.left = `${x}px`;
box.style.top = `${y}px`;
box.style.position = 'absolute';
box.dataset.id = this.nextId++;
this.container.appendChild(box);
this.boxes.push(box);
boxCount++;
updateStats();
console.log('Box created and added to container');
return box;
}
animateInteraction(box1, box2, result) {
animationCount++;
updateStats();
// Box1とBox2が中央に移動
const centerX = this.container.offsetWidth / 2 - 40;
const centerY = this.container.offsetHeight / 2 - 20;
box1.style.transform = `translate(${centerX - parseInt(box1.style.left)}px, ${centerY - parseInt(box1.style.top)}px)`;
box2.style.transform = `translate(${centerX + 20 - parseInt(box2.style.left)}px, ${centerY - parseInt(box2.style.top)}px)`;
setTimeout(() => {
// 結果Boxを表示
const resultBox = this.createBox('result', result, centerX, centerY + 40);
setTimeout(() => {
box1.style.opacity = '0.5';
box2.style.opacity = '0.5';
animationCount--;
updateStats();
}, 1000);
}, 800);
}
clear() {
this.container.innerHTML = '';
this.boxes = [];
boxCount = 0;
updateStats();
}
}
const boxViz = new BoxVisualizer('box-canvas');
window.demoBasicMath = () => {
console.log('demoBasicMath called');
boxViz.clear();
const box1 = boxViz.createBox('integer', '5', 50, 50);
const box2 = boxViz.createBox('integer', '3', 200, 50);
console.log('Boxes created:', box1, box2);
setTimeout(() => {
if (box1 && box2) {
boxViz.animateInteraction(box1, box2, '8');
}
}, 500);
};
window.demoStringConcat = () => {
boxViz.clear();
const box1 = boxViz.createBox('string', '"Hello"', 30, 100);
const box2 = boxViz.createBox('string', '"World"', 180, 100);
setTimeout(() => boxViz.animateInteraction(box1, box2, '"HelloWorld"'), 500);
};
window.demoComplexOp = () => {
boxViz.clear();
// 複数のBoxが連鎖的に相互作用
const boxes = [
boxViz.createBox('integer', '2', 20, 30),
boxViz.createBox('integer', '3', 120, 30),
boxViz.createBox('integer', '4', 220, 30)
];
setTimeout(() => boxViz.animateInteraction(boxes[0], boxes[1], '6'), 500);
setTimeout(() => {
const resultBox = boxViz.createBox('result', '6', 150, 100);
boxViz.animateInteraction(resultBox, boxes[2], '24');
}, 2000);
};
window.clearBoxes = () => boxViz.clear();
// 2. サウンドジェネレーター
function initAudio() {
if (!audioContext) {
audioContext = new (window.AudioContext || window.webkitAudioContext)();
}
}
function playTone(frequency, duration = 0.3, type = 'sine') {
initAudio();
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.frequency.value = frequency;
oscillator.type = type;
gainNode.gain.setValueAtTime(0.3, audioContext.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + duration);
oscillator.start(audioContext.currentTime);
oscillator.stop(audioContext.currentTime + duration);
audioNodes.push(oscillator);
}
window.playSound = () => {
const code = document.getElementById('sound-code').value;
// 簡単なSound API エミュレーション
const lines = code.split('\n');
let delay = 0;
lines.forEach(line => {
if (line.includes('Sound.play')) {
const match = line.match(/Sound\.play\((\d+)/);
if (match) {
const freq = parseInt(match[1]);
setTimeout(() => playTone(freq), delay);
delay += 400;
}
}
});
};
window.stopSound = () => {
audioNodes.forEach(node => {
try { node.stop(); } catch(e) {}
});
audioNodes = [];
};
window.loadMelody = () => {
document.getElementById('sound-code').value = `// 🎼 Beautiful Melody
Sound.play(262, "sine") // C
Sound.delay(300)
Sound.play(294, "sine") // D
Sound.delay(300)
Sound.play(330, "sine") // E
Sound.delay(300)
Sound.play(349, "sine") // F
Sound.chord([262, 330, 392], "triangle")`;
};
// 3. 非同期デモ
let asyncEventId = 0;
function createAsyncEvent(message, delay = 0) {
setTimeout(() => {
const timeline = document.getElementById('async-timeline');
const event = document.createElement('div');
event.className = 'async-event';
event.textContent = message;
event.style.top = `${20 + (asyncEventId % 8) * 20}px`;
timeline.appendChild(event);
const output = document.getElementById('async-output');
output.textContent += `[${new Date().toLocaleTimeString()}] ${message}\n`;
output.scrollTop = output.scrollHeight;
setTimeout(() => event.remove(), 3000);
asyncEventId++;
}, delay);
}
window.demoBasicAsync = () => {
document.getElementById('async-output').textContent = '';
createAsyncEvent('📤 ChannelBox created');
createAsyncEvent('✉️ Message sent: "Hello"', 500);
createAsyncEvent('📬 Message received', 1000);
createAsyncEvent('✅ Async operation complete', 1500);
};
window.demoParallelAsync = () => {
document.getElementById('async-output').textContent = '';
createAsyncEvent('🚀 Worker1 started');
createAsyncEvent('🚀 Worker2 started', 100);
createAsyncEvent('🚀 Worker3 started', 200);
createAsyncEvent('⚡ Worker1 result: 42', 800);
createAsyncEvent('⚡ Worker2 result: "OK"', 1200);
createAsyncEvent('⚡ Worker3 result: [1,2,3]', 1600);
createAsyncEvent('🎯 All results combined', 2000);
};
window.demoPipeline = () => {
document.getElementById('async-output').textContent = '';
createAsyncEvent('📥 Input: raw data');
createAsyncEvent('🔄 Stage1: parse', 300);
createAsyncEvent('🔄 Stage2: transform', 700);
createAsyncEvent('🔄 Stage3: validate', 1100);
createAsyncEvent('📤 Output: processed', 1500);
};
// 4. Lispインタープリター
class SimpleLisp {
eval(expr) {
if (typeof expr === 'number') return expr;
if (typeof expr === 'string') return expr;
if (!Array.isArray(expr)) return expr;
const [op, ...args] = expr;
switch (op) {
case '+':
return args.reduce((sum, arg) => sum + this.eval(arg), 0);
case '*':
return args.reduce((prod, arg) => prod * this.eval(arg), 1);
case '-':
const [first, ...rest] = args.map(arg => this.eval(arg));
return rest.length === 0 ? -first : rest.reduce((diff, val) => diff - val, first);
default:
return `Unknown operator: ${op}`;
}
}
parse(code) {
// 簡単なS式パーサー
try {
return JSON.parse(code.replace(/\(/g, '[').replace(/\)/g, ']').replace(/(\w+)/g, '"$1"'));
} catch {
return code;
}
}
}
const lisp = new SimpleLisp();
window.evalLisp = () => {
const code = document.getElementById('lisp-code').value;
const output = document.getElementById('lisp-output');
try {
const lines = code.split('\n').filter(line => line.trim());
let result = '';
lines.forEach(line => {
if (line.trim()) {
const expr = lisp.parse(line.trim());
const value = lisp.eval(expr);
result += `${line} => ${value}\n`;
}
});
output.textContent = result;
} catch (error) {
output.textContent = `Error: ${error.message}`;
}
};
window.stepEval = () => {
// ステップバイステップ評価のデモ
const output = document.getElementById('lisp-output');
output.textContent = 'Step-by-step evaluation:\n';
output.textContent += '1. Parse: (+ 1 2 3)\n';
output.textContent += '2. Evaluate args: 1, 2, 3\n';
output.textContent += '3. Apply +: 1 + 2 + 3\n';
output.textContent += '4. Result: 6\n';
};
window.loadLispExample = () => {
document.getElementById('lisp-code').value = `(+ 1 2 3 4 5)
(* 6 7)
(- 100 25)
(+ (* 2 3) (* 4 5))`;
};
// 5. Canvas統合デモ (簡略版)
window.startUltimateDemo = () => {
// 各Canvasで簡単なアニメーション
const particleCanvas = document.getElementById('mini-particles');
const fractalCanvas = document.getElementById('mini-fractal');
const lifeCanvas = document.getElementById('mini-life');
// 簡単なパーティクルアニメーション
const pCtx = particleCanvas.getContext('2d');
const particles = [];
for (let i = 0; i < 10; i++) {
particles.push({
x: Math.random() * 200,
y: Math.random() * 150,
vx: (Math.random() - 0.5) * 4,
vy: (Math.random() - 0.5) * 4,
color: ['red', 'lime', 'cyan', 'yellow'][Math.floor(Math.random() * 4)]
});
}
function animateParticles() {
pCtx.fillStyle = 'rgba(0,0,0,0.1)';
pCtx.fillRect(0, 0, 200, 150);
particles.forEach(p => {
p.x += p.vx;
p.y += p.vy;
if (p.x < 0 || p.x > 200) p.vx *= -1;
if (p.y < 0 || p.y > 150) p.vy *= -1;
pCtx.fillStyle = p.color;
pCtx.beginPath();
pCtx.arc(p.x, p.y, 3, 0, Math.PI * 2);
pCtx.fill();
});
requestAnimationFrame(animateParticles);
}
animateParticles();
// 簡単なフラクタル
const fCtx = fractalCanvas.getContext('2d');
for (let y = 0; y < 150; y += 2) {
for (let x = 0; x < 200; x += 2) {
const real = (x - 100) / 50;
const imag = (y - 75) / 50;
const c = Math.sqrt(real * real + imag * imag);
const hue = (c * 180) % 360;
fCtx.fillStyle = `hsl(${hue}, 100%, 50%)`;
fCtx.fillRect(x, y, 2, 2);
}
}
// 簡単なLifeパターン
const lCtx = lifeCanvas.getContext('2d');
lCtx.fillStyle = 'black';
lCtx.fillRect(0, 0, 200, 150);
lCtx.fillStyle = 'lime';
// グライダーパターン
const pattern = [[1,0],[2,1],[0,2],[1,2],[2,2]];
pattern.forEach(([x, y]) => {
lCtx.fillRect((x + 5) * 8, (y + 5) * 8, 8, 8);
});
};
window.pauseAllCanvas = () => {
// アニメーション停止のプレースホルダー
};
window.resetAllCanvas = () => {
// Canvas リセットのプレースホルダー
['mini-particles', 'mini-fractal', 'mini-life'].forEach(id => {
const canvas = document.getElementById(id);
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
});
};
// 初期化
updateStats();
// 初期状態でBoxVisualizer動作確認
setTimeout(() => {
console.log('Testing box visualizer...');
const testBox = boxViz.createBox('integer', '42', 100, 100);
console.log('Test box created:', testBox);
}, 500);
// 自動デモンストレーション
setTimeout(() => {
console.log('Starting auto demo...');
demoBasicMath();
}, 2000);
setTimeout(() => {
demoBasicAsync();
}, 5000);
</script>
</body>
</html>

View File

@ -0,0 +1,751 @@
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🐱 Nyash Browser Playground</title>
<style>
body {
font-family: 'Monaco', 'Consolas', monospace;
margin: 20px;
background: linear-gradient(135deg, #1e1e1e 0%, #2d2d2d 100%);
color: #ffffff;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
h1 {
color: #ff6b6b;
text-align: center;
margin-bottom: 5px;
text-shadow: 0 0 10px rgba(255, 107, 107, 0.5);
}
.subtitle {
text-align: center;
color: #4ecdc4;
margin-bottom: 30px;
font-size: 18px;
font-weight: bold;
}
.philosophy {
text-align: center;
color: #888;
margin-bottom: 30px;
font-style: italic;
background: rgba(78, 205, 196, 0.1);
padding: 15px;
border-radius: 10px;
border: 2px solid rgba(78, 205, 196, 0.3);
}
.demo-selector {
text-align: center;
margin-bottom: 30px;
}
.demo-btn {
background: linear-gradient(45deg, #ff6b6b, #ffa726);
color: white;
border: none;
padding: 10px 20px;
margin: 5px;
border-radius: 20px;
cursor: pointer;
font-size: 14px;
transition: transform 0.2s, box-shadow 0.2s;
box-shadow: 0 4px 15px rgba(255, 107, 107, 0.3);
}
.demo-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(255, 107, 107, 0.4);
}
.demo-btn.active {
background: linear-gradient(45deg, #4caf50, #66bb6a);
}
.editor-container {
display: flex;
gap: 20px;
height: 75vh;
}
.left-panel, .right-panel {
flex: 1;
display: flex;
flex-direction: column;
}
label {
color: #4ecdc4;
margin-bottom: 10px;
font-weight: bold;
}
#editor {
flex: 1;
background: #2d2d2d;
color: #f8f8f2;
border: 2px solid #4ecdc4;
border-radius: 8px;
padding: 15px;
font-family: 'Monaco', 'Consolas', monospace;
font-size: 14px;
resize: none;
outline: none;
}
#output {
background: #000;
color: #00ff00;
border: 2px solid #666;
border-radius: 8px;
padding: 15px;
font-family: 'Monaco', 'Consolas', monospace;
font-size: 14px;
overflow-y: auto;
white-space: pre-wrap;
word-break: break-all;
height: 180px;
}
.right-panel-content {
height: 100%;
display: flex;
flex-direction: column;
}
.controls {
display: flex;
gap: 10px;
margin: 20px 0;
justify-content: center;
}
button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 12px 24px;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
font-weight: bold;
transition: all 0.3s ease;
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
}
button:active {
transform: translateY(0);
}
.examples {
margin-top: 20px;
display: flex;
gap: 10px;
flex-wrap: wrap;
justify-content: center;
}
.example-btn {
background: #444;
color: #ccc;
font-size: 12px;
padding: 8px 16px;
}
.example-btn:hover {
background: #555;
}
.loading {
text-align: center;
color: #4ecdc4;
margin: 20px 0;
}
.error {
color: #ff6b6b;
background: #2d1b1b;
border: 1px solid #ff6b6b;
border-radius: 4px;
padding: 10px;
margin: 10px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>🐱 Nyash Browser Playground</h1>
<p class="subtitle">Everything is Box in your browser! - Rust WASM powered</p>
<div class="philosophy">
<strong>🎯 Everything is Box哲学:</strong> Nyashでは、すべての値・関数・メインプログラムまでがBoxです。
これにより統一的で美しく、メモリ安全な世界を実現しています。
</div>
<div class="loading" id="loading">
🚀 Loading Nyash WebAssembly module...
</div>
<div id="playground" style="display: none;">
<div class="editor-container">
<div class="left-panel">
<label for="editor">📝 Nyash Code:</label>
<textarea id="editor" placeholder="// Nyashコードをここに書くにゃ
// 🎯 正統派Nyashスタイル - static box Main!
static box Main {
init { console, x, y, result }
main() {
me.console = new WebConsoleBox(\"output\")
me.console.log(\"🎉 Hello from Nyash!\")
me.x = 42
me.y = 58
me.result = me.x + me.y
me.console.log(\"x + y = \" + me.result)
return \"Success!\"
}
}"></textarea>
</div>
<div class="right-panel">
<div class="right-panel-content">
<!-- ログ出力エリア(固定) -->
<div style="margin-bottom: 20px;">
<label for="output" style="color: #4ecdc4; font-weight: bold;">📺 Output:</label>
<div id="output"></div>
</div>
<!-- Canvas エリア -->
<div style="flex: 1;">
<label for="game-canvas" style="color: #4ecdc4; font-weight: bold; margin-bottom: 10px; display: block;">🎨 Canvas:</label>
<canvas id="game-canvas" width="400" height="250" style="border: 2px solid #4ecdc4; border-radius: 8px; background: black; display: block;"></canvas>
</div>
</div>
</div>
</div>
<div class="controls">
<button onclick="runNyash()">🚀 実行!</button>
<button onclick="clearOutput()">🧹 クリア</button>
<button onclick="showVersion()">📋 Version</button>
<button onclick="showHelp()">❓ ヘルプ</button>
</div>
<div class="examples">
<button class="example-btn" onclick="loadExample('hello')">Hello World</button>
<button class="example-btn" onclick="loadExample('math')">数学計算</button>
<button class="example-btn" onclick="loadExample('async')">⚡ 計算処理</button>
<button class="example-btn" onclick="loadExample('artists')">🎨 協同制作</button>
<button class="example-btn" onclick="loadExample('debug')">デバッグ</button>
<button class="example-btn" onclick="loadExample('webdisplay')">🌐 WebDisplay</button>
<button class="example-btn" onclick="loadExample('webcanvas')">🎨 WebCanvas</button>
<button class="example-btn" onclick="loadExample('canvas_advanced')">🎨 Canvas高度</button>
<button class="example-btn" onclick="loadExample('operators')">演算子テスト</button>
</div>
</div>
</div>
<script type="module">
import init, { NyashWasm } from './pkg/nyash_rust.js';
let nyash;
async function initializeNyash() {
try {
// Initialize WASM module
await init();
// Create Nyash interpreter instance
nyash = new NyashWasm();
// Show playground and hide loading
document.getElementById('loading').style.display = 'none';
document.getElementById('playground').style.display = 'block';
// Show version info in output
const output = document.getElementById('output');
output.textContent = '🎉 Nyash WASM initialized successfully!\\n' +
nyash.version() + '\\n\\n' +
'Ready to execute Nyash code...\\n';
} catch (error) {
document.getElementById('loading').innerHTML =
'<div class="error">❌ Failed to load Nyash WASM: ' + error.message + '</div>';
}
}
// Global functions for buttons
window.runNyash = function() {
if (!nyash) {
alert('Nyash is not loaded yet!');
return;
}
const code = document.getElementById('editor').value;
const output = document.getElementById('output');
// Web出力Boxを使用しているかチェック
const usesWebOutputBox = code.includes('WebDisplayBox') || code.includes('WebConsoleBox') || code.includes('WebCanvasBox');
try {
const result = nyash.eval(code);
if (usesWebOutputBox) {
// Web出力Boxが制御するので、JavaScriptは何もしない
console.log('Web output box is controlling the output panel');
} else {
// Web出力Boxを使わない場合は、通常通りJavaScriptで出力
output.textContent += '> ' + result + '\\n';
output.scrollTop = output.scrollHeight;
}
} catch (error) {
output.textContent += '❌ Error: ' + error.message + '\\n';
output.scrollTop = output.scrollHeight;
}
};
window.clearOutput = function() {
document.getElementById('output').textContent = '';
};
window.showVersion = function() {
if (nyash) {
const output = document.getElementById('output');
output.textContent += '📋 ' + nyash.version() + '\\n';
output.textContent += '🎯 Static Box Mainパターン: ✅ 実装済み\\n';
output.textContent += '🔒 変数宣言厳密性: ✅ 有効\\n';
output.textContent += '⚡ 演算子(AND/OR/NOT/除算): ✅ 対応済み\\n';
output.textContent += '🌐 WebCanvasBox + WebConsoleBox: ✅ 利用可能\\n\\n';
output.scrollTop = output.scrollHeight;
}
};
window.showHelp = function() {
const output = document.getElementById('output');
output.textContent += `📚 Nyash クイックヘルプ:
🎯 正統派Nyashスタイル:
static box Main {
init { field1, field2 } // フィールド宣言
main() {
me.field1 = "値" // me.fieldで参照
local temp // local変数宣言
temp = 42
return "成功!"
}
}
⚡ 利用可能演算子:
- 算術: +, -, *, /
- 比較: ==, !=, <, >, <=, >=
- 論理: not, and, or
🎨 特殊Box:
- WebConsoleBox("output") - HTML出力
- WebCanvasBox("game-canvas", w, h) - グラフィック
- DebugBox() - メモリ追跡
💡 Tips:
- すべての変数は宣言必須 (init {} または local)
- フィールドアクセスは me.field
- Everything is Box - main()でさえも!
`;
output.scrollTop = output.scrollHeight;
};
window.loadExample = function(type) {
const editor = document.getElementById('editor');
const examples = {
hello: `// 🐱 Hello World Example (正統派Nyashスタイル)
static box Main {
init { console }
main() {
me.console = new WebConsoleBox("output")
me.console.log("🎉 Hello from 正統派 Nyash!")
me.console.log("Everything is Box philosophy!")
me.console.log("🎊 Static box Mainパターン動作中")
return "Hello World完了"
}
}`,
math: `// 🧮 Math Example (正統派Nyashスタイル)
static box Main {
init { console, a, b }
main() {
me.console = new WebConsoleBox("output")
me.console.group("🔢 数学演算テスト")
me.a = 10
me.b = 5
me.console.info("値: a = " + me.a + ", b = " + me.b)
me.console.log("加算: a + b = " + (me.a + me.b))
me.console.log("減算: a - b = " + (me.a - me.b))
me.console.log("乗算: a * b = " + (me.a * me.b))
me.console.log("除算: a / b = " + (me.a / me.b))
me.console.separator()
me.console.info("🔍 論理演算:")
me.console.log("a > b: " + (me.a > me.b))
me.console.log("not (a < b): " + not (me.a < me.b))
me.console.log("a > 8 and b < 8: " + (me.a > 8 and me.b < 8))
me.console.groupEnd()
return "数学演算完了!"
}
}`,
debug: `// 🔍 Debug Example (正統派Nyashスタイル)
static box Main {
init { console, debug, x, memoryInfo }
main() {
me.console = new WebConsoleBox("output")
me.debug = new DebugBox()
me.console.group("🔍 デバッグセッション")
me.debug.startTracking()
me.console.log("🚀 デバッグ追跡開始!")
me.x = 100
me.debug.trackBox(me.x, "重要な値")
me.console.info("追跡中: x = " + me.x)
me.console.separator()
me.memoryInfo = me.debug.memoryReport()
me.console.debug("💾 メモリレポート:")
me.console.log(me.memoryInfo)
me.console.groupEnd()
return "デバッグ完了!"
}
}`,
webdisplay: `// 🌐 WebDisplayBox Example (正統派Nyashスタイル)
static box Main {
init { display }
main() {
me.display = new WebDisplayBox("output")
me.display.clear()
me.display.setHTML("<h2>🌟 WebDisplayBox デモ</h2>")
me.display.setCSS("color", "lime")
me.display.appendHTML("<p><strong>緑色のテキスト</strong> - 直接HTML制御</p>")
me.display.setCSS("color", "cyan")
me.display.appendHTML("<p><em>シアンのスタイリング</em> - CSS操作</p>")
me.display.setCSS("color", "white")
me.display.appendHTML("<h3>🎨 機能:</h3>")
me.display.appendHTML("<ul>")
me.display.appendHTML("<li>直接HTML出力</li>")
me.display.appendHTML("<li>リアルタイムCSS制御</li>")
me.display.appendHTML("<li>リッチコンテンツ描画</li>")
me.display.appendHTML("</ul>")
me.display.appendHTML("<p><strong>🌐 Everything is Box がブラウザで!</strong></p>")
return "WebDisplay デモ完了!"
}
}`,
webcanvas: `// 🎨 WebCanvasBox Basic Example (正統派Nyashスタイル)
static box Main {
init { canvas, console }
main() {
me.canvas = new WebCanvasBox("game-canvas", 400, 250)
me.console = new WebConsoleBox("output")
me.console.group("🎨 Canvas描画デモ")
me.console.log("Canvas作成: 400x250")
// 背景をクリアして描画
me.canvas.clear()
me.canvas.fillRect(0, 0, 400, 250, "black")
// 基本図形
me.canvas.fillRect(30, 30, 60, 50, "red")
me.canvas.strokeRect(120, 30, 60, 50, "blue", 3)
me.canvas.fillCircle(250, 60, 25, "green")
me.canvas.strokeCircle(330, 60, 25, "yellow", 4)
me.console.log("基本図形描画完了!")
// 線とテキスト
me.canvas.drawLine(50, 120, 350, 120, "white", 2)
me.canvas.fillText("Hello Canvas!", 80, 160, "20px Arial", "magenta")
me.canvas.fillText("Nyash WebCanvas!", 100, 200, "16px Arial", "cyan")
me.console.log("線とテキスト追加完了!")
me.console.groupEnd()
return "Canvas描画完了"
}
}`,
canvas_advanced: `// 🎨 WebCanvasBox Advanced Example (正統派Nyashスタイル)
static box Main {
init { canvas, console, cellSize, x, y, i, j }
main() {
me.canvas = new WebCanvasBox("game-canvas", 400, 250)
me.console = new WebConsoleBox("output")
me.console.group("🎮 高度なCanvas デモ")
// セットアップ
me.canvas.clear()
me.canvas.fillRect(0, 0, 400, 250, "navy")
me.console.log("🎨 カラフルなパターン描画中...")
// 虹色のグリッドパターン
me.cellSize = 12
me.i = 0
loop(me.i < 10) {
me.j = 0
loop(me.j < 8) {
me.x = 30 + me.i * me.cellSize
me.y = 50 + me.j * me.cellSize
// 色を計算 (rainbow効果)
if me.i + me.j == 0 {
me.canvas.fillRect(me.x, me.y, me.cellSize - 2, me.cellSize - 2, "red")
}
if me.i + me.j == 2 {
me.canvas.fillRect(me.x, me.y, me.cellSize - 2, me.cellSize - 2, "orange")
}
if me.i + me.j == 4 {
me.canvas.fillRect(me.x, me.y, me.cellSize - 2, me.cellSize - 2, "yellow")
}
if me.i + me.j == 6 {
me.canvas.fillRect(me.x, me.y, me.cellSize - 2, me.cellSize - 2, "lime")
}
if me.i + me.j == 8 {
me.canvas.fillRect(me.x, me.y, me.cellSize - 2, me.cellSize - 2, "cyan")
}
if me.i + me.j == 10 {
me.canvas.fillRect(me.x, me.y, me.cellSize - 2, me.cellSize - 2, "blue")
}
if me.i + me.j == 12 {
me.canvas.fillRect(me.x, me.y, me.cellSize - 2, me.cellSize - 2, "magenta")
}
me.j = me.j + 1
}
me.i = me.i + 1
}
me.console.log("🌈 虹色グリッド完成!")
// ゲーム要素 - プレイヤーとエネミー
me.canvas.fillCircle(80, 200, 15, "gold")
me.canvas.strokeCircle(80, 200, 15, "orange", 3)
me.canvas.fillText("Player", 60, 235, "12px Arial", "white")
me.canvas.fillRect(200, 185, 30, 30, "red")
me.canvas.strokeRect(200, 185, 30, 30, "darkred", 2)
me.canvas.fillText("Enemy", 195, 235, "12px Arial", "white")
me.canvas.fillCircle(320, 200, 12, "lime")
me.canvas.fillText("Goal", 300, 235, "12px Arial", "white")
// パワーアップアイテム
me.i = 0
loop(me.i < 3) {
me.x = 250 + me.i * 30
me.canvas.fillCircle(me.x, 100, 8, "hotpink")
me.canvas.strokeCircle(me.x, 100, 8, "purple", 2)
me.i = me.i + 1
}
me.canvas.fillText("Power-ups", 230, 125, "10px Arial", "white")
// タイトルとUI
me.canvas.fillText("🎮 Nyash Game World", 20, 25, "16px Arial", "white")
me.canvas.fillText("Everything is Interactive!", 20, 45, "12px Arial", "cyan")
me.console.log("🎮 ゲーム要素配置完了!")
me.console.info("🎯 ゲーム開発準備完了!")
me.console.groupEnd()
return "高度なCanvas完了"
}
}`,
operators: `// ⚡ Operators Example (正統派Nyashスタイル)
static box Main {
init { console, isActive, x, y, canAccess }
main() {
me.console = new WebConsoleBox("output")
me.console.group("⚡ 全演算子デモ")
me.isActive = true
me.x = 10
me.y = 20
me.console.info("📊 テスト値: x=" + me.x + ", y=" + me.y + ", flag=" + me.isActive)
me.console.separator()
// NOT演算子
me.console.info("❌ NOT演算子:")
me.console.log("not isActive = " + not me.isActive)
me.console.separator()
// AND/OR演算子
me.console.info("🔗 AND/OR演算子:")
me.console.log("x > 5 and y < 30 = " + (me.x > 5 and me.y < 30))
me.console.log("x > 15 or y > 15 = " + (me.x > 15 or me.y > 15))
me.console.separator()
// 複合条件
me.canAccess = (me.x > 5 and me.y > 10) or not me.isActive
me.console.info("🎯 複合条件:")
me.console.log("(x > 5 and y > 10) or not isActive = " + me.canAccess)
me.console.groupEnd()
return "全演算子テスト完了!"
}
}`,
async: `// ⚡ 計算処理デモ (WASM版 - 同期処理)
static box Main {
init { console }
main() {
me.console = new WebConsoleBox("output")
me.console.group("⚡ 計算処理デモ")
me.console.log("🚀 重い計算処理開始...")
me.console.log("💡 注意: WASM版では同期処理で実行されます")
// ローカル変数宣言
local result1, result2, total
// 計算処理実行
me.console.separator()
me.console.log("📊 計算1実行中 (3000回)...")
result1 = heavyComputation(3000)
me.console.log("📊 計算2実行中 (2000回)...")
result2 = heavyComputation(2000)
me.console.separator()
me.console.info("🎉 計算結果:")
me.console.log("結果1 (3000回): " + result1)
me.console.log("結果2 (2000回): " + result2)
total = result1 + result2
me.console.log("合計結果: " + total)
me.console.log("✨ 計算処理完了!")
me.console.separator()
me.console.debug("💡 非同期版はローカル版で試してください:")
me.console.debug(" ./target/debug/nyash test_async_demo.nyash")
me.console.groupEnd()
return "計算デモ成功!"
}
}
// 重い計算処理をシミュレート
function heavyComputation(iterations) {
local result, i
result = 0
i = 0
loop(i < iterations) {
result = result + i * i
i = i + 1
}
return result
}`,
artists: `// 🎨 アーティスト協同制作 - 複数Boxインスタンス版
static box Main {
init { console, canvas, artist1, artist2, artist3 }
main() {
me.console = new WebConsoleBox("output")
me.console.group("🎨 アーティスト協同制作")
// Canvas準備
me.canvas = new WebCanvasBox("game-canvas", 400, 250)
me.canvas.clear()
me.canvas.fillRect(0, 0, 400, 250, "lightgray")
// エリア境界線
me.canvas.fillRect(133, 0, 2, 250, "gray")
me.canvas.fillRect(267, 0, 2, 250, "gray")
me.console.log("🖼️ キャンバス準備完了")
// 3人のアーティストを雇用
me.artist1 = new Artist("抽象画家ピカソ", "red")
me.artist2 = new Artist("幾何学者ガウス", "blue")
me.artist3 = new Artist("自然派モネ", "green")
me.console.info("👩‍🎨 アーティスト登場:")
me.console.log("• " + me.artist1.name + " (" + me.artist1.color + ")")
me.console.log("• " + me.artist2.name + " (" + me.artist2.color + ")")
me.console.log("• " + me.artist3.name + " (" + me.artist3.color + ")")
me.console.separator()
me.console.log("🎨 各アーティストが創作開始...")
// 各アーティストが独自エリアで作品制作(シンプルバージョン)
me.artist1.paintInArea(me.canvas, 10, 20, 113, 210)
me.artist2.paintInArea(me.canvas, 143, 20, 114, 210)
me.artist3.paintInArea(me.canvas, 277, 20, 113, 210)
// アーティスト名表示
me.canvas.fillRect(20, 5, 90, 12, "white")
me.canvas.fillRect(150, 5, 90, 12, "white")
me.canvas.fillRect(285, 5, 90, 12, "white")
me.console.separator()
me.console.info("🎉 協同アート作品完成!")
me.console.log("3つの異なるスタイルで表現されました")
me.console.groupEnd()
return "アーティスト協同制作成功!"
}
}
box Artist {
init { name, color }
Artist(n, c) {
me.name = n
me.color = c
}
paintInArea(canvas, x, y, width, height) {
// シンプルな描画(ネストループ回避)
canvas.fillRect(x + 10, y + 10, 30, 30, me.color)
canvas.fillRect(x + 50, y + 30, 25, 25, me.color)
canvas.fillRect(x + 20, y + 70, 40, 20, me.color)
canvas.fillRect(x + 70, y + 60, 20, 35, me.color)
canvas.fillRect(x + 30, y + 110, 35, 15, me.color)
canvas.fillRect(x + 15, y + 140, 50, 25, me.color)
canvas.fillRect(x + 75, y + 120, 25, 40, me.color)
}
}`
};
if (examples[type]) {
editor.value = examples[type];
}
};
// Initialize when page loads
initializeNyash();
</script>
</body>
</html>

View File

@ -0,0 +1,703 @@
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🐱 Nyash Browser Playground - Everything is Box!</title>
<style>
body {
font-family: 'Monaco', 'Consolas', monospace;
margin: 20px;
background: linear-gradient(135deg, #1e1e1e 0%, #2d2d2d 100%);
color: #ffffff;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
h1 {
color: #ff6b6b;
text-align: center;
margin-bottom: 5px;
text-shadow: 0 0 10px rgba(255, 107, 107, 0.5);
}
.subtitle {
text-align: center;
color: #4ecdc4;
margin-bottom: 30px;
font-size: 18px;
font-weight: bold;
}
.philosophy {
text-align: center;
color: #888;
margin-bottom: 30px;
font-style: italic;
background: rgba(78, 205, 196, 0.1);
padding: 15px;
border-radius: 10px;
border: 2px solid rgba(78, 205, 196, 0.3);
}
.learning-path {
text-align: center;
margin-bottom: 30px;
}
.learning-step {
display: inline-block;
background: linear-gradient(45deg, #667eea, #764ba2);
color: white;
padding: 8px 16px;
margin: 5px;
border-radius: 20px;
font-size: 14px;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
}
.learning-step:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
}
.learning-step.active {
background: linear-gradient(45deg, #4caf50, #66bb6a);
}
.editor-container {
display: flex;
gap: 20px;
height: 75vh;
}
.left-panel, .right-panel {
flex: 1;
display: flex;
flex-direction: column;
}
label {
color: #4ecdc4;
margin-bottom: 10px;
font-weight: bold;
}
#editor {
flex: 1;
background: #2d2d2d;
color: #f8f8f2;
border: 2px solid #4ecdc4;
border-radius: 8px;
padding: 15px;
font-family: 'Monaco', 'Consolas', monospace;
font-size: 14px;
resize: none;
outline: none;
}
#output {
background: #000;
color: #00ff00;
border: 2px solid #666;
border-radius: 8px;
padding: 15px;
font-family: 'Monaco', 'Consolas', monospace;
font-size: 14px;
overflow-y: auto;
white-space: pre-wrap;
word-break: break-all;
height: 180px;
}
.right-panel-content {
height: 100%;
display: flex;
flex-direction: column;
}
.controls {
display: flex;
gap: 10px;
margin: 20px 0;
justify-content: center;
}
button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 12px 24px;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
font-weight: bold;
transition: all 0.3s ease;
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
}
button:active {
transform: translateY(0);
}
.examples {
margin-top: 20px;
display: flex;
gap: 10px;
flex-wrap: wrap;
justify-content: center;
}
.example-btn {
background: #444;
color: #ccc;
font-size: 12px;
padding: 8px 16px;
}
.example-btn:hover {
background: #555;
}
.loading {
text-align: center;
color: #4ecdc4;
margin: 20px 0;
}
.error {
color: #ff6b6b;
background: #2d1b1b;
border: 1px solid #ff6b6b;
border-radius: 4px;
padding: 10px;
margin: 10px 0;
}
.features {
display: flex;
justify-content: space-around;
margin: 20px 0;
flex-wrap: wrap;
}
.feature {
text-align: center;
color: #4ecdc4;
margin: 10px;
}
.feature-icon {
font-size: 24px;
margin-bottom: 5px;
}
</style>
</head>
<body>
<div class="container">
<h1>🐱 Nyash Browser Playground</h1>
<p class="subtitle">Everything is Box in your browser! - Rust WASM powered</p>
<div class="philosophy">
<strong>🎯 The Philosophy:</strong> In Nyash, Everything is Box!
Each value, function, and even the main program lives inside a Box.
This creates a unified, memory-safe, and beautifully consistent world.
</div>
<div class="features">
<div class="feature">
<div class="feature-icon">🎯</div>
<div>Static Box Main</div>
<small>Entry point philosophy</small>
</div>
<div class="feature">
<div class="feature-icon">🔒</div>
<div>Memory Safety</div>
<small>Explicit declarations</small>
</div>
<div class="feature">
<div class="feature-icon">🌐</div>
<div>WASM Ready</div>
<small>Browser native</small>
</div>
<div class="feature">
<div class="feature-icon"></div>
<div>Rich Operators</div>
<small>AND/OR/NOT/Division</small>
</div>
</div>
<div class="learning-path">
<h3 style="color: #4ecdc4; margin-bottom: 15px;">📚 Learning Path - Choose Your Journey:</h3>
<span class="learning-step" onclick="loadExample('simple')">1⃣ First Steps</span>
<span class="learning-step" onclick="loadExample('hello')">2⃣ Hello World</span>
<span class="learning-step" onclick="loadExample('math')">3⃣ Math & Logic</span>
<span class="learning-step" onclick="loadExample('webcanvas')">4⃣ Graphics</span>
<span class="learning-step" onclick="loadExample('canvas_advanced')">5⃣ Advanced</span>
<span class="learning-step" onclick="loadExample('debug')">6⃣ Debugging</span>
</div>
<div class="loading" id="loading">
🚀 Loading Nyash WebAssembly module...
</div>
<div id="playground" style="display: none;">
<div class="editor-container">
<div class="left-panel">
<label for="editor">📝 Nyash Code - Write Everything is Box:</label>
<textarea id="editor" placeholder="// Welcome to Nyash - Everything is Box!
// Click on Learning Path buttons above to try examples
// Or write your own code here...
static box Main {
init { console }
main() {
me.console = new WebConsoleBox(\"output\")
me.console.log(\"🎉 Hello from Nyash!\")
return \"Success!\"
}
}"></textarea>
</div>
<div class="right-panel">
<div class="right-panel-content">
<!-- ログ出力エリア -->
<div style="margin-bottom: 20px;">
<label for="output" style="color: #4ecdc4; font-weight: bold;">📺 Output Console:</label>
<div id="output"></div>
</div>
<!-- Canvas エリア -->
<div style="flex: 1;">
<label for="game-canvas" style="color: #4ecdc4; font-weight: bold; margin-bottom: 10px; display: block;">🎨 Graphics Canvas:</label>
<canvas id="game-canvas" width="400" height="250"
style="border: 2px solid #4ecdc4; border-radius: 8px;
background: black; display: block;"></canvas>
</div>
</div>
</div>
</div>
<div class="controls">
<button onclick="runNyash()">🚀 Run Code</button>
<button onclick="clearOutput()">🧹 Clear Output</button>
<button onclick="showVersion()">📋 Version Info</button>
<button onclick="showHelp()">❓ Help</button>
</div>
<div class="examples">
<button class="example-btn" onclick="loadExample('operators')">⚡ All Operators</button>
<button class="example-btn" onclick="loadExample('webdisplay')">🌐 HTML Control</button>
<button class="example-btn" onclick="loadExample('oldstyle')">🌍 GlobalBox Style</button>
</div>
</div>
</div>
<script type="module">
import init, { NyashWasm } from './pkg/nyash_rust.js';
let nyash;
async function initializeNyash() {
try {
await init();
nyash = new NyashWasm();
document.getElementById('loading').style.display = 'none';
document.getElementById('playground').style.display = 'block';
const output = document.getElementById('output');
output.textContent = '🎉 Nyash WASM initialized successfully!\\n' +
nyash.version() + '\\n\\n' +
'Ready to execute Nyash code...\\n';
// Load default example
loadExample('simple');
} catch (error) {
document.getElementById('loading').innerHTML =
'<div class="error">❌ Failed to load Nyash WASM: ' + error.message + '</div>';
}
}
window.runNyash = function() {
if (!nyash) {
alert('Nyash is not loaded yet!');
return;
}
const code = document.getElementById('editor').value;
const output = document.getElementById('output');
if (!code.trim()) {
output.textContent += '⚠️ Please enter some Nyash code to run.\\n';
return;
}
output.textContent += '🚀 Executing Nyash code...\\n';
try {
const result = nyash.eval(code);
if (result.includes('Error:')) {
output.textContent += '❌ ' + result + '\\n\\n';
} else {
output.textContent += '✅ Execution complete! Result: ' + result + '\\n\\n';
}
output.scrollTop = output.scrollHeight;
} catch (error) {
output.textContent += '❌ JavaScript Error: ' + error.message + '\\n\\n';
output.scrollTop = output.scrollHeight;
}
};
window.clearOutput = function() {
document.getElementById('output').textContent = '';
// Clear canvas
const canvas = document.getElementById('game-canvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);
};
window.showVersion = function() {
if (nyash) {
const output = document.getElementById('output');
output.textContent += '📋 ' + nyash.version() + '\\n';
output.textContent += '🎯 Static Box Main Pattern: ✅ Implemented\\n';
output.textContent += '🔒 Variable Declaration Strictness: ✅ Active\\n';
output.textContent += '⚡ Operators (AND/OR/NOT/Division): ✅ Ready\\n';
output.textContent += '🌐 WebCanvasBox + WebConsoleBox: ✅ Available\\n\\n';
output.scrollTop = output.scrollHeight;
}
};
window.showHelp = function() {
const output = document.getElementById('output');
output.textContent += `📚 Nyash Quick Help:
🎯 Proper Nyash Style:
static box Main {
init { field1, field2 } // Declare fields
main() {
me.field1 = "value" // Use me.field
local temp // Declare local vars
temp = 42
return "Success!"
}
}
⚡ Available Operators:
- Arithmetic: +, -, *, /
- Comparison: ==, !=, <, >, <=, >=
- Logical: not, and, or
🎨 Special Boxes:
- WebConsoleBox("output") - HTML output
- WebCanvasBox("game-canvas", w, h) - Graphics
- DebugBox() - Memory tracking
💡 Tips:
- All variables must be declared (init {} or local)
- Use me.field for accessing fields
- Everything is Box - even main()!
`;
output.scrollTop = output.scrollHeight;
};
window.loadExample = function(type) {
const editor = document.getElementById('editor');
// Update active learning step
document.querySelectorAll('.learning-step').forEach(step => {
step.classList.remove('active');
});
document.querySelectorAll('.learning-step').forEach(step => {
if (step.textContent.includes(getStepNumber(type))) {
step.classList.add('active');
}
});
const examples = {
simple: \`// 🚀 First Steps - Welcome to Nyash!
static box Main {
init { console, name, result }
main() {
me.console = new WebConsoleBox("output")
me.console.log("🎉 Welcome to Nyash!")
me.console.log("Everything is Box philosophy!")
me.name = "New Programmer"
me.console.log("Hello, " + me.name + "!")
local answer
answer = 6 * 7
me.console.log("The answer to everything: " + answer)
return "First steps completed!"
}
}\`,
hello: \`// 🎯 Hello World - Proper Nyash Style!
static box Main {
init { console, message, greeting }
main() {
me.console = new WebConsoleBox("output")
me.console.log("🌟 Hello World - Nyash Style!")
me.message = "Everything is Box"
me.greeting = "Welcome to the Box world!"
me.console.log(me.message)
me.console.log(me.greeting)
me.console.log("🎊 Static box Main pattern working!")
return "Hello World completed!"
}
}\`,
math: \`// 🧮 Math & Logic Operations
static box Main {
init { console, a, b, result }
main() {
me.console = new WebConsoleBox("output")
me.console.group("🔢 Math Operations")
me.a = 42
me.b = 18
me.console.info("Values: a = " + me.a + ", b = " + me.b)
me.console.log("Addition: a + b = " + (me.a + me.b))
me.console.log("Subtraction: a - b = " + (me.a - me.b))
me.console.log("Multiplication: a * b = " + (me.a * me.b))
me.console.log("Division: a / b = " + (me.a / me.b))
me.console.separator()
me.console.info("🔍 Logic Operations:")
me.console.log("a > b: " + (me.a > me.b))
me.console.log("not (a < b): " + not (me.a < me.b))
me.console.log("a > 30 and b < 30: " + (me.a > 30 and me.b < 30))
me.console.log("a < 30 or b > 10: " + (me.a < 30 or me.b > 10))
me.console.groupEnd()
return "Math operations completed!"
}
}\`,
webcanvas: \`// 🎨 Graphics with WebCanvasBox
static box Main {
init { canvas, console }
main() {
me.canvas = new WebCanvasBox("game-canvas", 400, 250)
me.console = new WebConsoleBox("output")
me.console.group("🎨 Canvas Drawing")
me.console.log("Drawing colorful shapes...")
// Clear and background
me.canvas.clear()
me.canvas.fillRect(0, 0, 400, 250, "navy")
// Colorful shapes
me.canvas.fillRect(50, 50, 80, 60, "red")
me.canvas.strokeRect(160, 50, 80, 60, "yellow", 4)
me.canvas.fillCircle(300, 80, 30, "lime")
// Text and lines
me.canvas.drawLine(50, 150, 350, 150, "white", 3)
me.canvas.fillText("Hello Canvas!", 120, 180, "24px Arial", "cyan")
me.canvas.fillText("🎨 Nyash Graphics", 110, 210, "18px Arial", "orange")
me.console.log("🎉 Canvas drawing completed!")
me.console.groupEnd()
return "Graphics demo finished!"
}
}\`,
canvas_advanced: \`// 🎮 Advanced Canvas - Game Patterns
static box Main {
init { canvas, console, cellSize, x, y, i }
main() {
me.canvas = new WebCanvasBox("game-canvas", 400, 250)
me.console = new WebConsoleBox("output")
me.console.group("🎮 Advanced Graphics")
me.canvas.clear()
me.canvas.fillRect(0, 0, 400, 250, "black")
// Draw game grid pattern
me.cellSize = 10
me.console.log("Creating game world...")
// Create a pattern
me.i = 0
loop(me.i < 15) {
me.x = me.i * me.cellSize * 2 + 50
me.y = 80
me.canvas.fillRect(me.x, me.y, me.cellSize, me.cellSize, "lime")
me.canvas.fillRect(me.x + me.cellSize, me.y + me.cellSize, me.cellSize, me.cellSize, "cyan")
me.i = me.i + 1
}
// Add decorative elements
me.canvas.fillCircle(200, 50, 20, "gold")
me.canvas.fillCircle(200, 180, 15, "magenta")
me.canvas.fillText("🎮 Game Development Ready!", 50, 220, "16px Arial", "white")
me.console.log("🌟 Game world created!")
me.console.info("✨ Ready for game logic!")
me.console.groupEnd()
return "Advanced canvas completed!"
}
}\`,
debug: \`// 🔍 Debug & Memory Tracking
static box Main {
init { console, debug, testData, memoryInfo }
main() {
me.console = new WebConsoleBox("output")
me.debug = new DebugBox()
me.console.group("🔍 Debug Session")
me.debug.startTracking()
me.console.log("🚀 Debug tracking started!")
me.testData = "Critical Information"
me.debug.trackBox(me.testData, "important_data")
me.console.info("📊 Tracking: " + me.testData)
me.console.separator()
me.memoryInfo = me.debug.memoryReport()
me.console.debug("💾 Memory Report:")
me.console.log(me.memoryInfo)
me.console.separator()
me.console.info("🎯 Debug features available:")
me.console.log("- Memory tracking")
me.console.log("- Box lifecycle monitoring")
me.console.log("- Performance analysis")
me.console.groupEnd()
return "Debug session completed!"
}
}\`,
webdisplay: \`// 🌐 Rich HTML Control with WebDisplayBox
static box Main {
init { display }
main() {
me.display = new WebDisplayBox("output")
me.display.clear()
me.display.setHTML("<h2>🌟 WebDisplayBox Demo</h2>")
me.display.setCSS("color", "lime")
me.display.appendHTML("<p><strong>Green text</strong> - Direct HTML control!</p>")
me.display.setCSS("color", "cyan")
me.display.appendHTML("<p><em>Cyan styling</em> - CSS manipulation!</p>")
me.display.setCSS("color", "white")
me.display.appendHTML("<h3>🎨 Features:</h3>")
me.display.appendHTML("<ul>")
me.display.appendHTML("<li>Direct HTML output</li>")
me.display.appendHTML("<li>Real-time CSS styling</li>")
me.display.appendHTML("<li>Rich content rendering</li>")
me.display.appendHTML("</ul>")
me.display.appendHTML("<p><strong>🌐 Everything is Box in your browser!</strong></p>")
return "WebDisplay demo completed!"
}
}\`,
operators: \`// ⚡ Complete Operators Showcase
static box Main {
init { console, x, y, flag, result }
main() {
me.console = new WebConsoleBox("output")
me.console.group("⚡ All Operators Demo")
me.x = 50
me.y = 20
me.flag = true
me.console.info("📊 Test values: x=" + me.x + ", y=" + me.y + ", flag=" + me.flag)
me.console.separator()
// Arithmetic
me.console.info("🧮 Arithmetic:")
me.console.log("x + y = " + (me.x + me.y))
me.console.log("x - y = " + (me.x - me.y))
me.console.log("x * y = " + (me.x * me.y))
me.console.log("x / y = " + (me.x / me.y))
me.console.separator()
// Comparison
me.console.info("🔍 Comparison:")
me.console.log("x > y: " + (me.x > me.y))
me.console.log("x < y: " + (me.x < me.y))
me.console.log("x == y: " + (me.x == me.y))
me.console.log("x != y: " + (me.x != me.y))
me.console.separator()
// Logical
me.console.info("🔗 Logical:")
me.console.log("not flag: " + not me.flag)
me.console.log("x > 30 and y < 30: " + (me.x > 30 and me.y < 30))
me.console.log("x < 30 or flag: " + (me.x < 30 or me.flag))
me.console.separator()
// Complex
me.result = (me.x > 40 and me.y > 10) or not me.flag
me.console.info("🎯 Complex: (x > 40 and y > 10) or not flag = " + me.result)
me.console.groupEnd()
return "All operators tested!"
}
}\`,
oldstyle: \`// 🌍 GlobalBox Style (Legacy but functional)
// Note: This uses implicit GlobalBox variables
// Recommended: Use static box Main pattern above!
console = new WebConsoleBox("output")
console.log("🌍 This is the legacy GlobalBox style")
console.log("It still works, but proper Nyash uses:")
console.log(" static box Main { main() { ... } }")
local temp
temp = "Legacy code"
console.log("Local variable works: " + temp)
console.separator()
console.info("💡 For new code, prefer static box Main pattern!")
console.info("✨ It's more explicit and follows Everything is Box!"
\`
};
if (examples[type]) {
editor.value = examples[type];
}
};
function getStepNumber(type) {
const steps = {
simple: '1⃣',
hello: '2⃣',
math: '3⃣',
webcanvas: '4⃣',
canvas_advanced: '5⃣',
debug: '6⃣'
};
return steps[type] || '';
}
initializeNyash();
</script>
</body>
</html>