From 6d43954a3899c21fbb2c46d1aebd3d3587aa06a3 Mon Sep 17 00:00:00 2001 From: Igor Bogoslavskyi Date: Sun, 20 Oct 2024 14:08:23 +0200 Subject: [PATCH] Add lambdas animation and minor code changes --- animation/lambdas/.gitignore | 15 + animation/lambdas/package-lock.json | 1366 ++++++++++++++++++++++ animation/lambdas/package.json | 22 + animation/lambdas/src/global.css | 1 + animation/lambdas/src/motion-canvas.d.ts | 1 + animation/lambdas/src/project.meta | 31 + animation/lambdas/src/project.ts | 9 + animation/lambdas/src/scenes/code.meta | 5 + animation/lambdas/src/scenes/code.tsx | 867 ++++++++++++++ animation/lambdas/tsconfig.json | 7 + animation/lambdas/videos/travolta.mp4 | 3 + animation/lambdas/vite.config.ts | 8 + lectures/lambdas.md | 149 ++- 13 files changed, 2425 insertions(+), 59 deletions(-) create mode 100644 animation/lambdas/.gitignore create mode 100644 animation/lambdas/package-lock.json create mode 100644 animation/lambdas/package.json create mode 100644 animation/lambdas/src/global.css create mode 100644 animation/lambdas/src/motion-canvas.d.ts create mode 100644 animation/lambdas/src/project.meta create mode 100644 animation/lambdas/src/project.ts create mode 100644 animation/lambdas/src/scenes/code.meta create mode 100644 animation/lambdas/src/scenes/code.tsx create mode 100644 animation/lambdas/tsconfig.json create mode 100644 animation/lambdas/videos/travolta.mp4 create mode 100644 animation/lambdas/vite.config.ts diff --git a/animation/lambdas/.gitignore b/animation/lambdas/.gitignore new file mode 100644 index 0000000..829b1c7 --- /dev/null +++ b/animation/lambdas/.gitignore @@ -0,0 +1,15 @@ +# Generated files +node_modules +output +dist + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/animation/lambdas/package-lock.json b/animation/lambdas/package-lock.json new file mode 100644 index 0000000..dad2ff3 --- /dev/null +++ b/animation/lambdas/package-lock.json @@ -0,0 +1,1366 @@ +{ + "name": "value_semantics", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "value_semantics", + "version": "0.0.0", + "dependencies": { + "@lezer/cpp": "^1.1.2", + "@motion-canvas/2d": "^3.16.0", + "@motion-canvas/core": "^3.16.0", + "@motion-canvas/ffmpeg": "^1.1.1" + }, + "devDependencies": { + "@motion-canvas/ui": "^3.16.0", + "@motion-canvas/vite-plugin": "^3.15.1", + "typescript": "^5.2.2", + "vite": "^4.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.2.tgz", + "integrity": "sha512-kgbTYTo0Au6dCSc/TFy7fK3fpJmgHDv1sG1KNQKJXVi+xBTEeBPY/M30YXiU6mMXeH+YIDLsbrT4ZwNRdtF+SA==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.1.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/state": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz", + "integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==" + }, + "node_modules/@codemirror/view": { + "version": "6.32.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.32.0.tgz", + "integrity": "sha512-AgVNvED2QTsZp5e3syoHLsrWtwJFYWdx1Vr/m3f4h1ATQz0ax60CfXF3Htdmk69k2MlYZw8gXesnQdHtzyVmAw==", + "dependencies": { + "@codemirror/state": "^6.4.0", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@ffmpeg-installer/darwin-arm64": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/darwin-arm64/-/darwin-arm64-4.1.5.tgz", + "integrity": "sha512-hYqTiP63mXz7wSQfuqfFwfLOfwwFChUedeCVKkBtl/cliaTM7/ePI9bVzfZ2c+dWu3TqCwLDRWNSJ5pqZl8otA==", + "cpu": [ + "arm64" + ], + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@ffmpeg-installer/darwin-x64": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/darwin-x64/-/darwin-x64-4.1.0.tgz", + "integrity": "sha512-Z4EyG3cIFjdhlY8wI9aLUXuH8nVt7E9SlMVZtWvSPnm2sm37/yC2CwjUzyCQbJbySnef1tQwGG2Sx+uWhd9IAw==", + "cpu": [ + "x64" + ], + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@ffmpeg-installer/ffmpeg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/ffmpeg/-/ffmpeg-1.1.0.tgz", + "integrity": "sha512-Uq4rmwkdGxIa9A6Bd/VqqYbT7zqh1GrT5/rFwCwKM70b42W5gIjWeVETq6SdcL0zXqDtY081Ws/iJWhr1+xvQg==", + "optionalDependencies": { + "@ffmpeg-installer/darwin-arm64": "4.1.5", + "@ffmpeg-installer/darwin-x64": "4.1.0", + "@ffmpeg-installer/linux-arm": "4.1.3", + "@ffmpeg-installer/linux-arm64": "4.1.4", + "@ffmpeg-installer/linux-ia32": "4.1.0", + "@ffmpeg-installer/linux-x64": "4.1.0", + "@ffmpeg-installer/win32-ia32": "4.1.0", + "@ffmpeg-installer/win32-x64": "4.1.0" + } + }, + "node_modules/@ffmpeg-installer/linux-arm": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/linux-arm/-/linux-arm-4.1.3.tgz", + "integrity": "sha512-NDf5V6l8AfzZ8WzUGZ5mV8O/xMzRag2ETR6+TlGIsMHp81agx51cqpPItXPib/nAZYmo55Bl2L6/WOMI3A5YRg==", + "cpu": [ + "arm" + ], + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@ffmpeg-installer/linux-arm64": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/linux-arm64/-/linux-arm64-4.1.4.tgz", + "integrity": "sha512-dljEqAOD0oIM6O6DxBW9US/FkvqvQwgJ2lGHOwHDDwu/pX8+V0YsDL1xqHbj1DMX/+nP9rxw7G7gcUvGspSoKg==", + "cpu": [ + "arm64" + ], + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@ffmpeg-installer/linux-ia32": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/linux-ia32/-/linux-ia32-4.1.0.tgz", + "integrity": "sha512-0LWyFQnPf+Ij9GQGD034hS6A90URNu9HCtQ5cTqo5MxOEc7Rd8gLXrJvn++UmxhU0J5RyRE9KRYstdCVUjkNOQ==", + "cpu": [ + "ia32" + ], + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@ffmpeg-installer/linux-x64": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/linux-x64/-/linux-x64-4.1.0.tgz", + "integrity": "sha512-Y5BWhGLU/WpQjOArNIgXD3z5mxxdV8c41C+U15nsE5yF8tVcdCGet5zPs5Zy3Ta6bU7haGpIzryutqCGQA/W8A==", + "cpu": [ + "x64" + ], + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@ffmpeg-installer/win32-ia32": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/win32-ia32/-/win32-ia32-4.1.0.tgz", + "integrity": "sha512-FV2D7RlaZv/lrtdhaQ4oETwoFUsUjlUiasiZLDxhEUPdNDWcH1OU9K1xTvqz+OXLdsmYelUDuBS/zkMOTtlUAw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@ffmpeg-installer/win32-x64": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/win32-x64/-/win32-x64-4.1.0.tgz", + "integrity": "sha512-Drt5u2vzDnIONf4ZEkKtFlbvwj6rI3kxw1Ck9fpudmtgaZIHD4ucsWB2lCZBXRxJgXR+2IMSti+4rtM4C4rXgg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@ffprobe-installer/darwin-arm64": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/darwin-arm64/-/darwin-arm64-5.0.1.tgz", + "integrity": "sha512-vwNCNjokH8hfkbl6m95zICHwkSzhEvDC3GVBcUp5HX8+4wsX10SP3B+bGur7XUzTIZ4cQpgJmEIAx6TUwRepMg==", + "cpu": [ + "arm64" + ], + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@ffprobe-installer/darwin-x64": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/darwin-x64/-/darwin-x64-5.1.0.tgz", + "integrity": "sha512-J+YGscZMpQclFg31O4cfVRGmDpkVsQ2fZujoUdMAAYcP0NtqpC49Hs3SWJpBdsGB4VeqOt5TTm1vSZQzs1NkhA==", + "cpu": [ + "x64" + ], + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@ffprobe-installer/ffprobe": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/ffprobe/-/ffprobe-2.1.2.tgz", + "integrity": "sha512-ZNvwk4f2magF42Zji2Ese16SMj9BS7Fui4kRjg6gTYTxY3gWZNpg85n4MIfQyI9nimHg4x/gT6FVkp/bBDuBwg==", + "engines": { + "node": ">=14.21.2" + }, + "optionalDependencies": { + "@ffprobe-installer/darwin-arm64": "5.0.1", + "@ffprobe-installer/darwin-x64": "5.1.0", + "@ffprobe-installer/linux-arm": "5.2.0", + "@ffprobe-installer/linux-arm64": "5.2.0", + "@ffprobe-installer/linux-ia32": "5.2.0", + "@ffprobe-installer/linux-x64": "5.2.0", + "@ffprobe-installer/win32-ia32": "5.1.0", + "@ffprobe-installer/win32-x64": "5.1.0" + } + }, + "node_modules/@ffprobe-installer/linux-arm": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/linux-arm/-/linux-arm-5.2.0.tgz", + "integrity": "sha512-PF5HqEhCY7WTWHtLDYbA/+rLS+rhslWvyBlAG1Fk8VzVlnRdl93o6hy7DE2kJgxWQbFaR3ZktPQGEzfkrmQHvQ==", + "cpu": [ + "arm" + ], + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@ffprobe-installer/linux-arm64": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/linux-arm64/-/linux-arm64-5.2.0.tgz", + "integrity": "sha512-X1VvWtlLs6ScP73biVLuHD5ohKJKsMTa0vafCESOen4mOoNeLAYbxOVxDWAdFz9cpZgRiloFj5QD6nDj8E28yQ==", + "cpu": [ + "arm64" + ], + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@ffprobe-installer/linux-ia32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/linux-ia32/-/linux-ia32-5.2.0.tgz", + "integrity": "sha512-TFVK5sasXyXhbIG7LtPRDmtkrkOsInwKcL43iEvEw+D9vCS2rc//mn9/0Q+BR0UoJEiMK4+ApYr/3LLVUBPOCQ==", + "cpu": [ + "ia32" + ], + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@ffprobe-installer/linux-x64": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/linux-x64/-/linux-x64-5.2.0.tgz", + "integrity": "sha512-D3UeqTLYPNs7pBWPLUYGehPdRVqU8eACox4OZy3pZUZatxye2YKlvBwEfaLdL1v2Z4FOAlLUhms0kY8m8kqSRA==", + "cpu": [ + "x64" + ], + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@ffprobe-installer/win32-ia32": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/win32-ia32/-/win32-ia32-5.1.0.tgz", + "integrity": "sha512-5O3vOoNRxmut0/Nu9vSazTdSHasrr+zPT2B3Hm7kjmO3QVFcIfVImS6ReQnZeSy8JPJOqXts5kX5x/3KOX54XQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@ffprobe-installer/win32-x64": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/win32-x64/-/win32-x64-5.1.0.tgz", + "integrity": "sha512-jMGYeAgkrdn4e2vvYt/qakgHRE3CPju4bn5TmdPfoAm1BlX1mY9cyMd8gf5vSzI8gH8Zq5WQAyAkmekX/8TSTg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@lezer/common": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", + "integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==" + }, + "node_modules/@lezer/cpp": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@lezer/cpp/-/cpp-1.1.2.tgz", + "integrity": "sha512-macwKtyeUO0EW86r3xWQCzOV9/CF8imJLpJlPv3sDY57cPGeUZ8gXWOWNlJr52TVByMV3PayFQCA5SHEERDmVQ==", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/highlight": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz", + "integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz", + "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@motion-canvas/2d": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@motion-canvas/2d/-/2d-3.16.0.tgz", + "integrity": "sha512-8vyCSNE9ZCkGB4Wz8yS48h0xQ79mbmbCkhpxu4ARBrFtSVLqgo/6kz2yifJi4wPK4pCDFw5knABjukOKtMaPMQ==", + "dependencies": { + "@codemirror/language": "^6.10.1", + "@lezer/common": "^1.2.1", + "@lezer/highlight": "^1.2.0", + "@motion-canvas/core": "^3.16.0", + "code-fns": "^0.8.2", + "mathjax-full": "^3.2.2", + "parse-svg-path": "^0.1.2" + } + }, + "node_modules/@motion-canvas/core": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@motion-canvas/core/-/core-3.16.0.tgz", + "integrity": "sha512-egOrQjVOHWf+HMFH+AOLLSV/djf+YGGPxbz0Jbnva3C3VTH2l6MMKTdoYyGRI3w02gJO1pIo7bcePq3erlxulw==", + "dependencies": { + "@types/chroma-js": "^2.1.4", + "chroma-js": "^2.4.2" + } + }, + "node_modules/@motion-canvas/ffmpeg": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@motion-canvas/ffmpeg/-/ffmpeg-1.1.1.tgz", + "integrity": "sha512-w2d7oFfR3hYHXeYtFGoHp6goY+vVL0LoZ2h1b/veTH5KvE7jrLp2Kl/XPHsYJ5ZDRHUT0Nhl05DBLdXYqdSqgg==", + "dependencies": { + "@ffmpeg-installer/ffmpeg": "^1.1.0", + "@ffprobe-installer/ffprobe": "^2.0.0", + "fluent-ffmpeg": "^2.1.2" + }, + "peerDependencies": { + "@motion-canvas/core": "^3.7.0", + "@motion-canvas/vite-plugin": "^3.7.0", + "vite": "4.x" + } + }, + "node_modules/@motion-canvas/ui": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/@motion-canvas/ui/-/ui-3.16.0.tgz", + "integrity": "sha512-PJZnbkiJKED4nNDnN649zojfPMVRTvFOqxUExi6TdrckiLFsTJFy+dYbyMML223ekDrkmHuQU35tcs3svwfYrw==", + "dev": true, + "dependencies": { + "@motion-canvas/core": "^3.16.0", + "@preact/signals": "^1.2.1", + "preact": "^10.19.2" + } + }, + "node_modules/@motion-canvas/vite-plugin": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/@motion-canvas/vite-plugin/-/vite-plugin-3.15.1.tgz", + "integrity": "sha512-yeRMJQxTcYVZGVMnNXQPm0SySQzJXnaRrggGJ2bnDHMsqxCRJt/RfIioK0LMvBaUB+UWlPsJUTMltHuq+J64JA==", + "dependencies": { + "fast-glob": "^3.3.1", + "follow-redirects": "^1.15.2", + "mime-types": "^2.1.35", + "source-map": "^0.6.1" + }, + "peerDependencies": { + "vite": "4.x || 5.x" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@preact/signals": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@preact/signals/-/signals-1.3.0.tgz", + "integrity": "sha512-EOMeg42SlLS72dhoq6Vjq08havnLseWmPQ8A0YsgIAqMgWgx7V1a39+Pxo6i7SY5NwJtH4849JogFq3M67AzWg==", + "dev": true, + "dependencies": { + "@preact/signals-core": "^1.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + }, + "peerDependencies": { + "preact": "10.x" + } + }, + "node_modules/@preact/signals-core": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.8.0.tgz", + "integrity": "sha512-OBvUsRZqNmjzCZXWLxkZfhcgT+Fk8DDcT/8vD6a1xhDemodyy87UJRJfASMuSD8FaAIeGgGm85ydXhm7lr4fyA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/@types/chroma-js": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.4.0.tgz", + "integrity": "sha512-JklMxityrwjBTjGY2anH8JaTx3yjRU3/sEHSblLH1ba5lqcSh1LnImXJZO5peJfXyqKYWjHTGy4s5Wz++hARrw==" + }, + "node_modules/@types/hast": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", + "integrity": "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/unist": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", + "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" + }, + "node_modules/@wooorm/starry-night": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@wooorm/starry-night/-/starry-night-1.7.0.tgz", + "integrity": "sha512-ktO0nkddrovIoNW2jAUT+Cdd9n1bWjy1Ir4CdcmgTaT6E94HLlQfu7Yv62falclBEwvsuVp3bSBw23wtta1fNw==", + "dependencies": { + "@types/hast": "^2.0.0", + "import-meta-resolve": "^2.0.0", + "vscode-oniguruma": "^1.0.0", + "vscode-textmate": "^9.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==" + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chroma-js": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz", + "integrity": "sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A==" + }, + "node_modules/code-fns": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/code-fns/-/code-fns-0.8.2.tgz", + "integrity": "sha512-3VVeq3cnWxWiWKFLsVo+XWsOXBSW2gAx2uv0ViETLNmNuygEPHlCeDAv/Zy7xXqPgXtgLZyvIJZmx+ojTgOIGA==", + "dependencies": { + "@wooorm/starry-night": "^1.2.0" + } + }, + "node_modules/commander": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.2.0.tgz", + "integrity": "sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fluent-ffmpeg": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.3.tgz", + "integrity": "sha512-Be3narBNt2s6bsaqP6Jzq91heDgOEaDCJAXcE3qcma/EJBSy5FB4cvO31XBInuAuKBx8Kptf8dkhjK0IOru39Q==", + "dependencies": { + "async": "^0.2.9", + "which": "^1.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/import-meta-resolve": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-2.2.2.tgz", + "integrity": "sha512-f8KcQ1D80V7RnqVm+/lirO9zkOxjGxhaTC1IPrBGd3MEfNgmNG67tSUO9gTi2F3Blr2Az6g1vocaxzkVnWl9MA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/mathjax-full": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/mathjax-full/-/mathjax-full-3.2.2.tgz", + "integrity": "sha512-+LfG9Fik+OuI8SLwsiR02IVdjcnRCy5MufYLi0C3TdMT56L/pjB0alMVGgoWJF8pN9Rc7FESycZB9BMNWIid5w==", + "dependencies": { + "esm": "^3.2.25", + "mhchemparser": "^4.1.0", + "mj-context-menu": "^0.6.1", + "speech-rule-engine": "^4.0.6" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/mhchemparser": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/mhchemparser/-/mhchemparser-4.1.1.tgz", + "integrity": "sha512-R75CUN6O6e1t8bgailrF1qPq+HhVeFTM3XQ0uzI+mXTybmphy3b6h4NbLOYhemViQ3lUs+6CKRkC3Ws1TlYREA==" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mj-context-menu": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/mj-context-menu/-/mj-context-menu-0.6.1.tgz", + "integrity": "sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA==" + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/parse-svg-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz", + "integrity": "sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/preact": { + "version": "10.23.2", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.23.2.tgz", + "integrity": "sha512-kKYfePf9rzKnxOAKDpsWhg/ysrHPqT+yQ7UW4JjdnqjFIeNUnNcEJvhuA8fDenxAGWzUqtd51DfVg7xp/8T9NA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/speech-rule-engine": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/speech-rule-engine/-/speech-rule-engine-4.0.7.tgz", + "integrity": "sha512-sJrL3/wHzNwJRLBdf6CjJWIlxC04iYKkyXvYSVsWVOiC2DSkHmxsqOhEeMsBA9XK+CHuNcsdkbFDnoUfAsmp9g==", + "dependencies": { + "commander": "9.2.0", + "wicked-good-xpath": "1.3.0", + "xmldom-sre": "0.1.31" + }, + "bin": { + "sre": "bin/sre" + } + }, + "node_modules/style-mod": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", + "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/vite": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz", + "integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==", + "dependencies": { + "esbuild": "^0.18.10", + "postcss": "^8.4.27", + "rollup": "^3.27.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==" + }, + "node_modules/vscode-textmate": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-9.0.0.tgz", + "integrity": "sha512-Cl65diFGxz7gpwbav10HqiY/eVYTO1sjQpmRmV991Bj7wAoOAjGQ97PpQcXorDE2Uc4hnGWLY17xme+5t6MlSg==" + }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/wicked-good-xpath": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/wicked-good-xpath/-/wicked-good-xpath-1.3.0.tgz", + "integrity": "sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw==" + }, + "node_modules/xmldom-sre": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/xmldom-sre/-/xmldom-sre-0.1.31.tgz", + "integrity": "sha512-f9s+fUkX04BxQf+7mMWAp5zk61pciie+fFLC9hX9UVvCeJQfNHRHXpeo5MPcR0EUf57PYLdt+ZO4f3Ipk2oZUw==", + "engines": { + "node": ">=0.1" + } + } + } +} diff --git a/animation/lambdas/package.json b/animation/lambdas/package.json new file mode 100644 index 0000000..9955e40 --- /dev/null +++ b/animation/lambdas/package.json @@ -0,0 +1,22 @@ +{ + "name": "value_semantics", + "private": true, + "version": "0.0.0", + "scripts": { + "start": "vite", + "serve": "vite", + "build": "tsc && vite build" + }, + "dependencies": { + "@lezer/cpp": "^1.1.2", + "@motion-canvas/2d": "^3.16.0", + "@motion-canvas/core": "^3.16.0", + "@motion-canvas/ffmpeg": "^1.1.1" + }, + "devDependencies": { + "@motion-canvas/ui": "^3.16.0", + "@motion-canvas/vite-plugin": "^3.15.1", + "typescript": "^5.2.2", + "vite": "^4.0.0" + } +} diff --git a/animation/lambdas/src/global.css b/animation/lambdas/src/global.css new file mode 100644 index 0000000..201f5ff --- /dev/null +++ b/animation/lambdas/src/global.css @@ -0,0 +1 @@ +@import url('https://fonts.googleapis.com/css2?family=Fira+Mono:wght@400;500;700&display=swap'); diff --git a/animation/lambdas/src/motion-canvas.d.ts b/animation/lambdas/src/motion-canvas.d.ts new file mode 100644 index 0000000..067c6a4 --- /dev/null +++ b/animation/lambdas/src/motion-canvas.d.ts @@ -0,0 +1 @@ +/// diff --git a/animation/lambdas/src/project.meta b/animation/lambdas/src/project.meta new file mode 100644 index 0000000..e6d28f9 --- /dev/null +++ b/animation/lambdas/src/project.meta @@ -0,0 +1,31 @@ +{ + "version": 0, + "shared": { + "background": "rgb(10,20,30)", + "range": [ + 0, + null + ], + "size": { + "x": 1920, + "y": 1080 + }, + "audioOffset": 0 + }, + "preview": { + "fps": 60, + "resolutionScale": 1 + }, + "rendering": { + "fps": 30, + "resolutionScale": 2, + "colorSpace": "srgb", + "exporter": { + "name": "@motion-canvas/ffmpeg", + "options": { + "fastStart": false, + "includeAudio": true + } + } + } +} \ No newline at end of file diff --git a/animation/lambdas/src/project.ts b/animation/lambdas/src/project.ts new file mode 100644 index 0000000..f2112ba --- /dev/null +++ b/animation/lambdas/src/project.ts @@ -0,0 +1,9 @@ +import { makeProject } from '@motion-canvas/core'; + +import './global.css'; + +import code from './scenes/code?scene'; + +export default makeProject({ + scenes: [code], +}); diff --git a/animation/lambdas/src/scenes/code.meta b/animation/lambdas/src/scenes/code.meta new file mode 100644 index 0000000..f0654cf --- /dev/null +++ b/animation/lambdas/src/scenes/code.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 2771218248 +} \ No newline at end of file diff --git a/animation/lambdas/src/scenes/code.tsx b/animation/lambdas/src/scenes/code.tsx new file mode 100644 index 0000000..b0949da --- /dev/null +++ b/animation/lambdas/src/scenes/code.tsx @@ -0,0 +1,867 @@ +import { createRef } from '@motion-canvas/core/lib/utils'; +import { makeScene2D, Code, LezerHighlighter, lines } from '@motion-canvas/2d'; +import { all, waitFor, waitUntil } from '@motion-canvas/core/lib/flow'; +import { DEFAULT } from '@motion-canvas/core/lib/signals'; +import { BBox, Vector2 } from '@motion-canvas/core/lib/types'; +import { tags } from '@lezer/highlight'; +import { HighlightStyle } from '@codemirror/language'; + +import { parser as parser_css } from '@lezer/css'; +import { parser as parser_cpp } from '@lezer/cpp'; + +const MyStyle = HighlightStyle.define([ + { tag: tags.keyword, color: '#569CD6' }, // VSCode Keyword color + { tag: tags.controlKeyword, color: '#C586C0' }, // VSCode Control Keyword color + { tag: tags.operatorKeyword, color: '#C586C0' }, // VSCode Control Keyword color + { tag: tags.comment, color: 'gray' }, // VSCode Comment color + { tag: tags.className, color: '#4EC9B0' }, // VSCode Class Name color + { tag: tags.constant(tags.variableName), color: '#B5CEA8' }, // VSCode Constant color + { tag: tags.function(tags.variableName), color: '#DCDCAA' }, // VSCode Function color + { tag: tags.function(tags.propertyName), color: '#DCDCAA' }, // VSCode Function color + { tag: tags.propertyName, color: '#DCDCAA' }, // VSCode Function color + { tag: tags.number, color: '#B5CEA8' }, // VSCode Number color + { tag: tags.string, color: '#CE9178' }, // VSCode String color + { tag: tags.typeName, color: '#4EC9B0' }, // VSCode Type Name color + { tag: tags.squareBracket, color: '#C586C0' }, // VSCode Square Bracket color + { tag: tags.bracket, color: '#C586C0' }, // VSCode Bracket color + { tag: tags.brace, color: '#DDDD22' }, // VSCode Brace color + { tag: tags.processingInstruction, color: '#C586C0' }, // VSCode Brace color + { tag: tags.arithmeticOperator, color: '#D16969' }, // VSCode Arithmetic Operator color +]); + +const CssHighlighter = new LezerHighlighter(parser_css, MyStyle); +const CppHighlighter = new LezerHighlighter(parser_cpp, MyStyle); + +export default makeScene2D(function* (view) { + const codeRef = createRef(); + + yield view.add(); + + const duration = 1.0 + + const lambda_intro_1 = `\ +#include +#include + +struct Person { + std::string name; + int age; +}; + +int main() { + std::vector people{ + {"Gandalf", 55'000}, {"Frodo", 33}, {"Legolas", 2'931}, {"Gimli", 139}}; +}` + const lambda_intro_2 = `\ +#include +#include +#include + +struct Person { + std::string name; + int age; +}; + +int main() { + std::vector people{ + {"Gandalf", 55'000}, {"Frodo", 33}, {"Legolas", 2'931}, {"Gimli", 139}}; + std::sort(people.begin(), people.end()); +}` + + const lambda_intro_3 = `\ +#include +#include +#include + +struct Person { + std::string name; + int age; +}; + +int main() { + std::vector people{ + {"Gandalf", 55'000}, {"Frodo", 33}, {"Legolas", 2'931}, {"Gimli", 139}}; + // ❌ Won't compile, cannot compare Person objects. + std::sort(people.begin(), people.end()); +}` + + yield* codeRef().code(lambda_intro_1, duration).wait(duration); + yield* codeRef().code(lambda_intro_2, duration).to(lambda_intro_3, duration).wait(duration); + + + const error_message = `\ +In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algobase.h:71, + from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/algorithm:61, + from :1: +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/predefined_ops.h: In instantiation of 'constexpr bool __gnu_cxx::__ops::_Iter_less_iter::operator()(_Iterator1, _Iterator2) const [with _Iterator1 = __gnu_cxx::__normal_iterator >; _Iterator2 = __gnu_cxx::__normal_iterator >]': +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algo.h:82:17: required from 'void std::__move_median_to_first(_Iterator, _Iterator, _Iterator, _Iterator, _Compare) [with _Iterator = __gnu_cxx::__normal_iterator >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algo.h:1924:34: required from '_RandomAccessIterator std::__unguarded_partition_pivot(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algo.h:1958:38: required from 'void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator >; _Size = long int; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algo.h:1974:25: required from 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algo.h:4859:18: required from 'void std::sort(_RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator >]' +:14:41: required from here +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/predefined_ops.h:43:23: error: no match for 'operator<' (operand types are 'Person' and 'Person') + 43 | { return *__it1 < *__it2; } + | ~~~~~~~^~~~~~~~ +In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algobase.h:67, + from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/algorithm:61, + from :1: +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_iterator.h:1096:5: note: candidate: 'template bool __gnu_cxx::operator<(const __gnu_cxx::__normal_iterator<_IteratorL, _Container>&, const __gnu_cxx::__normal_iterator<_IteratorR, _Container>&)' + 1096 | operator<(const __normal_iterator<_IteratorL, _Container>& __lhs, + | ^~~~~~~~ +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_iterator.h:1096:5: note: template argument deduction/substitution failed: +In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algobase.h:71, + from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/algorithm:61, + from :1: +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/predefined_ops.h:43:23: note: 'Person' is not derived from 'const __gnu_cxx::__normal_iterator<_IteratorL, _Container>' + 43 | { return *__it1 < *__it2; } + | ~~~~~~~^~~~~~~~ +In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algobase.h:67, + from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/algorithm:61, + from :1: +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_iterator.h:1104:5: note: candidate: 'template bool __gnu_cxx::operator<(const __gnu_cxx::__normal_iterator<_Iterator, _Container>&, const __gnu_cxx::__normal_iterator<_Iterator, _Container>&)' + 1104 | operator<(const __normal_iterator<_Iterator, _Container>& __lhs, + | ^~~~~~~~ +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_iterator.h:1104:5: note: template argument deduction/substitution failed: +In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algobase.h:71, + from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/algorithm:61, + from :1: +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/predefined_ops.h:43:23: note: 'Person' is not derived from 'const __gnu_cxx::__normal_iterator<_Iterator, _Container>' + 43 | { return *__it1 < *__it2; } + | ~~~~~~~^~~~~~~~ +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/predefined_ops.h: In instantiation of 'bool __gnu_cxx::__ops::_Val_less_iter::operator()(_Value&, _Iterator) const [with _Value = Person; _Iterator = __gnu_cxx::__normal_iterator >]': +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algo.h:1826:20: required from 'void std::__unguarded_linear_insert(_RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator >; _Compare = __gnu_cxx::__ops::_Val_less_iter]' +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algo.h:1854:36: required from 'void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algo.h:1886:25: required from 'void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algo.h:1977:31: required from 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algo.h:4859:18: required from 'void std::sort(_RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator >]' +:14:41: required from here +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/predefined_ops.h:96:22: error: no match for 'operator<' (operand types are 'Person' and 'Person') + 96 | { return __val < *__it; } + | ~~~~~~^~~~~~~ +In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algobase.h:67, + from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/algorithm:61, + from :1: +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_iterator.h:1096:5: note: candidate: 'template bool __gnu_cxx::operator<(const __gnu_cxx::__normal_iterator<_IteratorL, _Container>&, const __gnu_cxx::__normal_iterator<_IteratorR, _Container>&)' + 1096 | operator<(const __normal_iterator<_IteratorL, _Container>& __lhs, + | ^~~~~~~~ +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_iterator.h:1096:5: note: template argument deduction/substitution failed: +In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algobase.h:71, + from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/algorithm:61, + from :1: +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/predefined_ops.h:96:22: note: 'Person' is not derived from 'const __gnu_cxx::__normal_iterator<_IteratorL, _Container>' + 96 | { return __val < *__it; } + | ~~~~~~^~~~~~~ +In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algobase.h:67, + from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/algorithm:61, + from :1: +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_iterator.h:1104:5: note: candidate: 'template bool __gnu_cxx::operator<(const __gnu_cxx::__normal_iterator<_Iterator, _Container>&, const __gnu_cxx::__normal_iterator<_Iterator, _Container>&)' + 1104 | operator<(const __normal_iterator<_Iterator, _Container>& __lhs, + | ^~~~~~~~ +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_iterator.h:1104:5: note: template argument deduction/substitution failed: +In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algobase.h:71, + from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/algorithm:61, + from :1: +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/predefined_ops.h:96:22: note: 'Person' is not derived from 'const __gnu_cxx::__normal_iterator<_Iterator, _Container>' + 96 | { return __val < *__it; } + | ~~~~~~^~~~~~~ +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/predefined_ops.h: In instantiation of 'bool __gnu_cxx::__ops::_Iter_less_val::operator()(_Iterator, _Value&) const [with _Iterator = __gnu_cxx::__normal_iterator >; _Value = Person]': +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_heap.h:139:48: required from 'void std::__push_heap(_RandomAccessIterator, _Distance, _Distance, _Tp, _Compare&) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator >; _Distance = long int; _Tp = Person; _Compare = __gnu_cxx::__ops::_Iter_less_val]' +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_heap.h:246:23: required from 'void std::__adjust_heap(_RandomAccessIterator, _Distance, _Distance, _Tp, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator >; _Distance = long int; _Tp = Person; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_heap.h:355:22: required from 'void std::__make_heap(_RandomAccessIterator, _RandomAccessIterator, _Compare&) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algo.h:1666:23: required from 'void std::__heap_select(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algo.h:1937:25: required from 'void std::__partial_sort(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algo.h:1953:27: required from 'void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator >; _Size = long int; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algo.h:1974:25: required from 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]' +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algo.h:4859:18: required from 'void std::sort(_RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator >]' +:14:41: required from here +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/predefined_ops.h:67:22: error: no match for 'operator<' (operand types are 'Person' and 'Person') + 67 | { return *__it < __val; } + | ~~~~~~^~~~~~~ +In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algobase.h:67, + from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/algorithm:61, + from :1: +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_iterator.h:1096:5: note: candidate: 'template bool __gnu_cxx::operator<(const __gnu_cxx::__normal_iterator<_IteratorL, _Container>&, const __gnu_cxx::__normal_iterator<_IteratorR, _Container>&)' + 1096 | operator<(const __normal_iterator<_IteratorL, _Container>& __lhs, + | ^~~~~~~~ +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_iterator.h:1096:5: note: template argument deduction/substitution failed: +In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algobase.h:71, + from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/algorithm:61, + from :1: +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/predefined_ops.h:67:22: note: 'Person' is not derived from 'const __gnu_cxx::__normal_iterator<_IteratorL, _Container>' + 67 | { return *__it < __val; } + | ~~~~~~^~~~~~~ +In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algobase.h:67, + from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/algorithm:61, + from :1: +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_iterator.h:1104:5: note: candidate: 'template bool __gnu_cxx::operator<(const __gnu_cxx::__normal_iterator<_Iterator, _Container>&, const __gnu_cxx::__normal_iterator<_Iterator, _Container>&)' + 1104 | operator<(const __normal_iterator<_Iterator, _Container>& __lhs, + | ^~~~~~~~ +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_iterator.h:1104:5: note: template argument deduction/substitution failed: +In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_algobase.h:71, + from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/algorithm:61, + from :1: +/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/predefined_ops.h:67:22: note: 'Person' is not derived from 'const __gnu_cxx::__normal_iterator<_Iterator, _Container>' + 67 | { return *__it < __val; } + | ~~~~~~^~~~~~~ +Compiler returned: 1` + + yield* all( + codeRef().highlighter(CssHighlighter, 0), + codeRef().fontSize(7, 0), + codeRef().x(-900, 0), + codeRef().y(1100, 0), + codeRef().code(error_message, 0), + ); + yield* waitFor(duration); + + yield* all( + codeRef().y(0, duration), + ); + yield* waitFor(duration); + + yield* all( + codeRef().fontSize(35, duration), + codeRef().x(-2400, duration), + codeRef().y(2000, duration), + ); + yield* waitFor(duration); + + yield* all( + codeRef().highlighter(CppHighlighter, 0), + codeRef().fontSize(25, 0), + codeRef().x(-600, 0), + codeRef().y(0, 0), + codeRef().code(lambda_intro_3, 0), + ); + yield* waitFor(duration); + + const lambda_intro_4 = `\ +#include +#include +#include + +struct Person { + std::string name; + int age; +}; + +int main() { + std::vector people{ + {"Gandalf", 55'000}, {"Frodo", 33}, {"Legolas", 2'931}, {"Gimli", 139}}; + std::sort( + people.begin(), people.end(), + [](const auto& left, const auto& right) { return left.age < right.age; }); +}` + yield* all( + codeRef().code(lambda_intro_4, duration), + ); + yield* waitFor(duration); + + const lambda_intro_5 = `\ +#include +#include +#include +#include + +struct Person { + std::string name; + int age; +}; + +void Print(const std::vector& persons, const std::string& tag) { + std::cout << tag << std::endl; + for (const auto& person : persons) { + std::cout << person.name << " " << person.age << "\\n"; + } +} + +int main() { + std::vector people{ + {"Gandalf", 55'000}, {"Frodo", 33}, {"Legolas", 2'931}, {"Gimli", 139}}; + Print(people, "> Before sorting:"); + std::sort( + people.begin(), people.end(), + [](const auto& left, const auto& right) { return left.age < right.age; }); + Print(people, "> Sorted by age ascending:"); +}` + yield* all( + codeRef().code(lambda_intro_5, duration), + ); + yield* waitFor(duration); + + yield* all( + codeRef().code('', 0), + codeRef().fontSize(70, 0), + ); + const lambda_simple_1 = `\ +int main() { + [](){}(); +}` + yield* all( + codeRef().code(lambda_simple_1, duration), + ); + yield* waitFor(duration); + + const lambda_simple_2 = `\ +// ✅ Yep, this compiles 🙃 +int main() { + [](){}(); +}` + yield* all( + codeRef().code(lambda_simple_2, duration), + ); + yield* waitFor(duration); + + yield* all( + codeRef().code(lambda_intro_5, 0), + codeRef().fontSize(25, 0), + ); + yield* waitFor(duration); + + const function_ptr = `\ +#include +#include +#include +#include + +struct Person { + std::string name; + int age; +}; + +void Print(const std::vector& persons, const std::string& tag) { + std::cout << tag << std::endl; + for (const auto& person : persons) { + std::cout << person.name << " " << person.age << "\\n"; + } +} + +bool less(const Person& p1, const Person& p2) { return p1.age < p2.age; } + +int main() { + std::vector people{ + {"Gandalf", 55'000}, {"Frodo", 33}, {"Legolas", 2'931}, {"Gimli", 139}}; + Print(people, "> Before sorting:"); + std::sort(people.begin(), people.end(), &less); + Print(people, "> Sorted by age ascending:"); +}` + yield* all( + codeRef().code(function_ptr, duration), + codeRef().fontSize(25, duration), + ); + yield* waitFor(duration); + + const function_ptr_1 = `\ +#include +#include +#include +#include + +struct Person { + std::string name; + int age; +}; + +void Print(const std::vector& persons, const std::string& tag) { + std::cout << tag << std::endl; + for (const auto& person : persons) { + std::cout << person.name << " " << person.age << "\\n"; + } +} + +bool less(const Person& p1, const Person& p2) { return p1.age < p2.age; } + +int main() { + std::vector people{ + {"Gandalf", 55'000}, {"Frodo", 33}, {"Legolas", 2'931}, {"Gimli", 139}}; + Print(people, "> Before sorting:"); + std::sort(people.begin(), people.end(), less); + Print(people, "> Sorted by age ascending:"); +}` + yield* all( + codeRef().code(function_ptr_1, duration), + codeRef().fontSize(25, duration), + ); + yield* waitFor(duration); + + const functor = `\ +#include +#include +#include +#include + +struct Person { + std::string name; + int age; +}; + +void Print(const std::vector& persons, const std::string& tag) { + std::cout << tag << std::endl; + for (const auto& person : persons) { + std::cout << person.name << " " << person.age << "\\n"; + } +} + +class ComparisonToQueryAge { + public: + explicit ComparisonToQueryAge(int query_age) : query_age_{query_age} {} + + bool operator()(const Person& p1, const Person& p2) const { + return std::abs(p1.age - query_age_) < std::abs(p2.age - query_age_); + } + + private: + int query_age_{}; +}; + +int main() { + std::vector people{ + {"Gandalf", 55'000}, {"Frodo", 33}, {"Legolas", 2'931}, {"Gimli", 139}}; + Print(people, "> Before sorting:"); + std::sort(people.begin(), people.end(), ComparisonToQueryAge{4242}); + Print(people, "> Sorted by age difference to 4242, ascending:"); +}` + yield* all( + codeRef().code(functor, duration), + codeRef().fontSize(22, duration), + ); + yield* waitFor(duration); + + const my_sort = `\ +#include +#include +#include + +struct Person { + std::string name; + int age; +}; + +void Print(const std::vector& persons, const std::string& tag) { + std::cout << tag << std::endl; + for (const auto& person : persons) { + std::cout << person.name << " " << person.age << "\\n"; + } +} + +template +void MySort(Iterator begin, Iterator end, Comparator comparator) { + // The actual algorithm is not important here. + for (Iterator i = begin + 1; i != end; ++i) { + Iterator j = i; + // We call comparator(*iter_1, *iter_2) somewhere in our algorithm. + while (j != begin && comparator(*j, *(j - 1))) { + std::iter_swap(j, j - 1); + --j; + } + } +} + +int main() { + std::vector people{ + {"Gandalf", 55'000}, {"Frodo", 33}, {"Legolas", 2'931}, {"Gimli", 139}}; + Print(people, "> Before sorting:"); +}` + + yield* all( + codeRef().code(my_sort, 0), + codeRef().fontSize(22, 0), + ); + yield* waitFor(duration); + + const my_sort_2 = `\ +#include +#include +#include + +struct Person { + std::string name; + int age; +}; + +void Print(const std::vector& persons, const std::string& tag) { + std::cout << tag << std::endl; + for (const auto& person : persons) { + std::cout << person.name << " " << person.age << "\\n"; + } +} + +bool less(const Person& p1, const Person& p2) { return p1.age < p2.age; } + +template +void MySort(Iterator begin, Iterator end, Comparator comparator) { + // The actual algorithm is not important here. + for (Iterator i = begin + 1; i != end; ++i) { + Iterator j = i; + // We call comparator(*iter_1, *iter_2) somewhere in our algorithm. + while (j != begin && comparator(*j, *(j - 1))) { + std::iter_swap(j, j - 1); + --j; + } + } +} + +int main() { + std::vector people{ + {"Gandalf", 55'000}, {"Frodo", 33}, {"Legolas", 2'931}, {"Gimli", 139}}; + Print(people, "> Before sorting:"); + MySort(people.begin(), people.end(), less); + Print(people, "> Sorted by age ascending:"); + MySort(people.begin(), people.end(), &less); + Print(people, "> Sorted by age ascending:"); +}` + + yield* all( + codeRef().code(my_sort_2, duration), + codeRef().fontSize(20, duration), + ); + yield* waitFor(duration); + + const my_sort_3 = `\ +#include +#include +#include + +struct Person { + std::string name; + int age; +}; + +void Print(const std::vector& persons, const std::string& tag) { + std::cout << tag << std::endl; + for (const auto& person : persons) { + std::cout << person.name << " " << person.age << "\\n"; + } +} + +class ComparisonToQueryAge { + public: + explicit ComparisonToQueryAge(int query_age) : query_age_{query_age} {} + + bool operator()(const Person& p1, const Person& p2) const { + return std::abs(p1.age - query_age_) < std::abs(p2.age - query_age_); + } + + private: + int query_age_{}; +}; + +bool less(const Person& p1, const Person& p2) { return p1.age < p2.age; } + +template +void MySort(Iterator begin, Iterator end, Comparator comparator) { + // The actual algorithm is not important here. + for (Iterator i = begin + 1; i != end; ++i) { + Iterator j = i; + // We call comparator(*iter_1, *iter_2) somewhere in our algorithm. + while (j != begin && comparator(*j, *(j - 1))) { + std::iter_swap(j, j - 1); + --j; + } + } +} + +int main() { + std::vector people{ + {"Gandalf", 55'000}, {"Frodo", 33}, {"Legolas", 2'931}, {"Gimli", 139}}; + Print(people, "> Before sorting:"); + MySort(people.begin(), people.end(), less); + Print(people, "> Sorted by age ascending:"); + MySort(people.begin(), people.end(), ComparisonToQueryAge{4242}); + Print(people, "> Sorted by age difference to 4242, ascending:"); + MySort(people.begin(), people.end(), &less); + Print(people, "> Sorted by age ascending:"); +}` + + yield* all( + codeRef().code(my_sort_3, duration), + codeRef().fontSize(15, duration), + ); + yield* waitFor(duration); + + yield* all( + codeRef().code(functor, 0), + codeRef().fontSize(22, 0), + ); + yield* waitFor(duration); + + const lambdas = `\ +#include +#include +#include +#include + +struct Person { + std::string name; + int age; +}; + +int main() { + const auto Print = [](const auto& persons, const auto& tag) { + std::cout << tag << std::endl; + for (const auto& person : persons) { + std::cout << person.name << " " << person.age << "\\n"; + } + }; + + std::vector people{ + {"Gandalf", 55'000}, {"Frodo", 33}, {"Legolas", 2'931}, {"Gimli", 139}}; + Print(people, "> Before sorting:"); + + std::sort(people.begin(), people.end(), + [](const auto& p1, const auto& p2) { return p1.age < p2.age; }); + Print(people, "> Sorted by age ascending:"); + + const int query_age = 4242; + std::sort(people.begin(), people.end(), + [query_age](const auto& p1, const auto& p2) -> bool { + return std::abs(p1.age - query_age) < std::abs(p2.age - query_age); + }); + Print(people, "> Sorted by age difference to 4242, ascending:"); +}` + yield* all( + codeRef().code(lambdas, duration), + ); + yield* waitFor(duration); + + const lambdas_by_ref = `\ +#include +#include +#include +#include + +struct Person { + std::string name; + int age; +}; + +int main() { + const auto Print = [](const auto& persons, const auto& tag) { + std::cout << tag << std::endl; + for (const auto& person : persons) { + std::cout << person.name << " " << person.age << "\\n"; + } + }; + + std::vector people{ + {"Gandalf", 55'000}, {"Frodo", 33}, {"Legolas", 2'931}, {"Gimli", 139}}; + Print(people, "> Before sorting:"); + + std::sort(people.begin(), people.end(), + [](const auto& p1, const auto& p2) { return p1.age < p2.age; }); + Print(people, "> Sorted by age ascending:"); + + const int query_age = 4242; + std::sort(people.begin(), people.end(), + [&query_age](const auto& p1, const auto& p2) -> bool { + return std::abs(p1.age - query_age) < std::abs(p2.age - query_age); + }); + Print(people, "> Sorted by age difference to 4242, ascending:"); +}` + yield* all( + codeRef().code(lambdas_by_ref, duration), + ); + yield* waitFor(duration); + + const lambda_capturing = `\ +#include + +int main() { + int one{}; + float two{}; + double three{}; + const auto Lambda = [&one, two, &three] { + // Do something with one, two, three. + std::cout << one << " " << two << " " << three << std::endl; + }; + Lambda(); +}` + yield* all( + codeRef().code(lambda_capturing, 0), + codeRef().fontSize(25, 0), + ); + yield* waitFor(duration); + + const lambda_capturing_all = `\ +#include + +int main() { + int one{}; + float two{}; + double three{}; + const auto Lambda = [=] { + // All variables are captured by copy. + std::cout << one << " " << two << " " << three << std::endl; + }; + Lambda(); +}` + yield* all( + codeRef().code(lambda_capturing_all, duration), + codeRef().fontSize(25, duration), + ); + yield* waitFor(duration); + + const lambda_capturing_all_with_some = `\ +#include + +int main() { + int one{}; + float two{}; + double three{}; + const auto Lambda = [=, &two] { + // two is captured by reference, all the others by copy. + std::cout << one << " " << two << " " << three << std::endl; + }; + Lambda(); +}` + yield* all( + codeRef().code(lambda_capturing_all_with_some, duration), + codeRef().fontSize(25, duration), + ); + yield* waitFor(duration); + + const lambda_capturing_all_by_ref = `\ +#include + +int main() { + int one{}; + float two{}; + double three{}; + const auto Lambda = [&] { + // All variables are captured by reference. + std::cout << one << " " << two << " " << three << std::endl; + }; + Lambda(); +}` + yield* all( + codeRef().code(lambda_capturing_all_by_ref, duration), + codeRef().fontSize(25, duration), + ); + yield* waitFor(duration); + + const lambda_capturing_all_by_ref_some_by_copy = `\ +#include + +int main() { + int one{}; + float two{}; + double three{}; + const auto Lambda = [&, two] { + // two is captured by copy, all the others by reference. + std::cout << one << " " << two << " " << three << std::endl; + }; + Lambda(); +}` + yield* all( + codeRef().code(lambda_capturing_all_by_ref_some_by_copy, duration), + codeRef().fontSize(25, duration), + ); + yield* waitFor(duration); + + const lambda_capturing_this = `\ +#include + +struct Foo { + void Bar() { + [this] { + // The whole current object is captured by reference. + std::cout << one << " " << two << " " << three << std::endl; + }(); // We call this lambda in-place for illustration purposes. + } + + int one{}; + float two{}; + double three{}; +}; + +int main() { + Foo foo{}; + foo.Bar(); +}` + yield* all( + codeRef().code(lambda_capturing_this, duration), + codeRef().fontSize(25, duration), + ); + yield* waitFor(duration); + + const sandwich_bad = `\ +#include +#include + +// 😱 Comments tend to drift out of sync with code. +Sandwich MakeGourmetSandwich() { + Sandwich sandwich{}; + + // Step 1: Prepare the bread + sandwich += "Choosing the finest sourdough...\\n"; + sandwich += "Lightly toasting it to perfection...\\n"; + sandwich += "Spreading a generous amount of garlic aioli...\\n"; + + // Step 2: Prepare the ingredients + sandwich += "Grilling marinated chicken...\\n"; + sandwich += "Adding fresh arugula and juicy tomatoes...\\n"; + sandwich += "Topping it off with caramelized onions...\\n"; + + // Step 3: Assemble the masterpiece + sandwich += "Assembling the sandwich with care...\\n"; + sandwich += "Adding a drizzle of truffle oil...\\n"; + sandwich += "Plating it elegantly...\\n"; + + return sandwich; +}` + yield* all( + codeRef().code(sandwich_bad, 0), + codeRef().fontSize(25, 0), + ); + yield* waitFor(duration); + + const sandwich_better = `\ +#include +#include + +// ✅ Every step is encapsulated in a lambda. +Sandwich MakeGourmetSandwich() { + Sandwich sandwich{}; + + const auto PrepareBread = [&sandwich]() { + sandwich += "Choosing the finest sourdough...\\n"; + sandwich += "Lightly toasting it to perfection...\\n"; + sandwich += "Spreading a generous amount of garlic aioli...\\n"; + }; + + const auto PrepareIngredients = [&sandwich]() { + sandwich += "Grilling marinated chicken...\\n"; + sandwich += "Adding fresh arugula and juicy tomatoes...\\n"; + sandwich += "Topping it off with caramelized onions...\\n"; + }; + + const auto PlateSandwich = [&sandwich]() { + sandwich += "Assembling the sandwich with care...\\n"; + sandwich += "Adding a drizzle of truffle oil...\\n"; + sandwich += "Plating it elegantly...\\n"; + }; + + PrepareBread(); + PrepareIngredients(); + PlateSandwich(); + + return sandwich; +}` + yield* all( + codeRef().code(sandwich_better, duration), + codeRef().fontSize(25, duration), + ); + yield* waitFor(duration); + + yield* waitFor(duration); + +}); diff --git a/animation/lambdas/tsconfig.json b/animation/lambdas/tsconfig.json new file mode 100644 index 0000000..789b7d1 --- /dev/null +++ b/animation/lambdas/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "@motion-canvas/2d/tsconfig.project.json", + "compilerOptions": { + "baseUrl": "src" + }, + "include": ["src"] +} diff --git a/animation/lambdas/videos/travolta.mp4 b/animation/lambdas/videos/travolta.mp4 new file mode 100644 index 0000000..9d6b4ee --- /dev/null +++ b/animation/lambdas/videos/travolta.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5b300b8896b6062071238fde2ea43584797b3bbc93280e331b219a86380b11f1 +size 1181848 diff --git a/animation/lambdas/vite.config.ts b/animation/lambdas/vite.config.ts new file mode 100644 index 0000000..4e353f3 --- /dev/null +++ b/animation/lambdas/vite.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'vite'; +import ffmpeg from '@motion-canvas/ffmpeg'; +import motionCanvas from '@motion-canvas/vite-plugin'; + +export default defineConfig({ + plugins: [motionCanvas(), ffmpeg()], + +}); diff --git a/lectures/lambdas.md b/lectures/lambdas.md index edd8bbb..822c640 100644 --- a/lectures/lambdas.md +++ b/lectures/lambdas.md @@ -171,6 +171,7 @@ error: no match for 'operator<' (operand types are 'Person' and 'Person') ``` You see, by default `std::sort` will apply the operator `<` to the provided arguments and, unless we define such operator for our `Person` class, this operator does not exist. + However, there is another overload of `std::sort` function that we can use! We can provide a **lambda expression** that compares two `Person` objects. ```cpp @@ -329,6 +330,18 @@ int main() { } ``` Once we pass an object of this class as the callable into the `std::sort`, we can see that our Tolkien characters are now sorted by their age difference to the number `4242`. +``` +> Before sorting: +Gandalf 55000 +Frodo 33 +Legolas 2931 +Gimli 139 +> Sorted by age difference to 4242, ascending: +Legolas 2931 +Gimli 139 +Frodo 33 +Gandalf 55000 +``` ## How to implement generic algorithms like `std::sort` So far so good. We already know a lot about classes so I hope that what we've just covered seems quite self-explanatory. @@ -397,6 +410,28 @@ int main() { } ``` Note though that our interest here is _not_ to implement a better sorting algorithm (so feel free to ignore the actual implementation) but to gain intuition about how we _could_ implement a generic algorithm that takes any comparator object that is "callable" with two `Person` objects, be it a function pointer or a function object. We don't have to write much code to achieve this too! And if we run this, we get the expected output. +``` +> Before sorting: +Gandalf 55000 +Frodo 33 +Legolas 2931 +Gimli 139 +> Sorted by age ascending: +Frodo 33 +Gimli 139 +Legolas 2931 +Gandalf 55000 +> Sorted by age difference to 4242, ascending: +Legolas 2931 +Gimli 139 +Frodo 33 +Gandalf 55000 +> Sorted by age ascending: +Frodo 33 +Gimli 139 +Legolas 2931 +Gandalf 55000 +``` Note also that from C++20 on this code would become more readable and safe as we could use concepts instead of raw templates. @@ -506,82 +541,79 @@ const auto Compare = [&query_age](const auto& p1, const auto& p2) -> bool { ``` We can also provide as many captured variables as we want, specifying for each if we want to capture them by copy or by reference. - -```cpp -int one{}; -float two{}; -double three{}; -const auto Lambda = [&one, two, &three] { - // Do something with one, two, three. - std::cout << one << " " << two << " " << three << std::endl; -}; ``` Here, `one` and `three` will be captured by reference, while `two` is captured by copy. Alternatively, we can capture all variables visible at the moment of lambda definition. There are three distinct cases that are worth talking about here. -If we want to capture all variables by copy, we can use `=` as the first capture. And if we want some variables to be captured by reference we can specify such variables further in the capture list. - +``` +And if we want some variables to be captured by reference we can specify such variables further in the capture list. ```cpp -int one{}; -float two{}; -double three{}; -const auto Lambda1 = [=] { - // All variables are captured by copy. - std::cout << one << " " << two << " " << three << std::endl; -}; -const auto Lambda2 = [=, &two] { - // two is captured by reference, all the others by copy. - std::cout << one << " " << two << " " << three << std::endl; -}; +#include +int main() { + int one{}; + float two{}; + double three{}; + const auto Lambda = [=, &two] { + // two is captured by reference, all the others by copy. + std::cout << one << " " << two << " " << three << std::endl; + }; + Lambda(); +} ``` -Should we want to capture all variables by reference instead, we can pass a single ampersand `&` symbol instead. Almost opposite to the previous setup, if we want _some_ variables to still be captured by copy, we can simply append them to the capture list. - +``` +Almost opposite to the previous setup, if we want _some_ variables to still be captured by copy, we can simply append them to the capture list. ```cpp -int one{}; -float two{}; -double three{}; -const auto Lambda1 = [&] { - // All variables are captured by reference. - std::cout << one << " " << two << " " << three << std::endl; -}; -const auto Lambda2 = [&, two] { - // two is captured by copy, all the others by reference. - std::cout << one << " " << two << " " << three << std::endl; -}; +#include +int main() { + int one{}; + float two{}; + double three{}; + const auto Lambda = [&, two] { + // two is captured by copy, all the others by reference. + std::cout << one << " " << two << " " << three << std::endl; + }; + Lambda(); +} ``` Finally, if a lambda appears within a class method, we might want it to have access to all the data within the current object. For that we can pass `this` into the lambda capture list and use the object data without issues: @@ -593,7 +625,7 @@ struct Foo { [this] { // The whole current object is captured by reference. std::cout << one << " " << two << " " << three << std::endl; - }(); // We call this lambda in-line for illustration purposes. + }(); // We call this lambda in-place for illustration purposes. } int one{}; @@ -610,7 +642,6 @@ Note, that just to show that this is possible, we call the lambda in-place right And, on that note, now that we've discussed most of the syntax we use for lambdas, we can see that `[](){}()` from the start of this video is just a definition of a lambda that has an empty capture list, no arguments, empty body, which is called in-place right after creation (doing nothing of course). This lambda is totally useless, apart from the entertainment it provides :wink: - ## When to use lambdas All in all, lambdas are neat and efficient. If we need a callable object to pass to some function and we don't think we'll ever want to reuse it, like in our example with sorting, lambdas should be our go-to tool.