From c8bc385d039294122b295420a164137daac5f024 Mon Sep 17 00:00:00 2001 From: Igor Bogoslavskyi Date: Sat, 28 Oct 2023 15:53:43 +0200 Subject: [PATCH] Better text for static lecture --- animation/static_no_classes/.gitignore | 15 + animation/static_no_classes/package-lock.json | 759 ++++++++++++++++++ animation/static_no_classes/package.json | 19 + animation/static_no_classes/src/global.css | 1 + .../static_no_classes/src/motion-canvas.d.ts | 1 + animation/static_no_classes/src/project.meta | 32 + animation/static_no_classes/src/project.ts | 9 + .../static_no_classes/src/scenes/example.meta | 5 + .../static_no_classes/src/scenes/example.tsx | 400 +++++++++ .../static_no_classes/src/scenes/memory.meta | 5 + .../static_no_classes/src/scenes/memory.tsx | 96 +++ .../src/scenes/static_vis.meta | 5 + .../src/scenes/static_vis.tsx | 308 +++++++ animation/static_no_classes/tsconfig.json | 7 + animation/static_no_classes/vite.config.ts | 6 + animation/value_semantics/package-lock.json | 327 ++++---- animation/value_semantics/package.json | 10 +- animation/value_semantics/src/project.meta | 2 +- .../odr_violation/CMakeLists.txt | 26 + .../static_no_classes/odr_violation/main.cpp | 7 + .../odr_violation/other_lib.cpp | 5 + .../odr_violation/other_lib.hpp | 6 + .../odr_violation/our_cool_lib.cpp | 5 + .../odr_violation/our_cool_lib.hpp | 6 + lectures/namespaces_using.md | 12 +- lectures/static.md | 239 +++++- 26 files changed, 2094 insertions(+), 219 deletions(-) create mode 100644 animation/static_no_classes/.gitignore create mode 100644 animation/static_no_classes/package-lock.json create mode 100644 animation/static_no_classes/package.json create mode 100644 animation/static_no_classes/src/global.css create mode 100644 animation/static_no_classes/src/motion-canvas.d.ts create mode 100644 animation/static_no_classes/src/project.meta create mode 100644 animation/static_no_classes/src/project.ts create mode 100644 animation/static_no_classes/src/scenes/example.meta create mode 100644 animation/static_no_classes/src/scenes/example.tsx create mode 100644 animation/static_no_classes/src/scenes/memory.meta create mode 100644 animation/static_no_classes/src/scenes/memory.tsx create mode 100644 animation/static_no_classes/src/scenes/static_vis.meta create mode 100644 animation/static_no_classes/src/scenes/static_vis.tsx create mode 100644 animation/static_no_classes/tsconfig.json create mode 100644 animation/static_no_classes/vite.config.ts create mode 100644 lectures/code/static_no_classes/odr_violation/CMakeLists.txt create mode 100644 lectures/code/static_no_classes/odr_violation/main.cpp create mode 100644 lectures/code/static_no_classes/odr_violation/other_lib.cpp create mode 100644 lectures/code/static_no_classes/odr_violation/other_lib.hpp create mode 100644 lectures/code/static_no_classes/odr_violation/our_cool_lib.cpp create mode 100644 lectures/code/static_no_classes/odr_violation/our_cool_lib.hpp diff --git a/animation/static_no_classes/.gitignore b/animation/static_no_classes/.gitignore new file mode 100644 index 0000000..829b1c7 --- /dev/null +++ b/animation/static_no_classes/.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/static_no_classes/package-lock.json b/animation/static_no_classes/package-lock.json new file mode 100644 index 0000000..cdefbbe --- /dev/null +++ b/animation/static_no_classes/package-lock.json @@ -0,0 +1,759 @@ +{ + "name": "value_semantics", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "value_semantics", + "version": "0.0.0", + "dependencies": { + "@motion-canvas/2d": "^3.11.0", + "@motion-canvas/core": "^3.11.0" + }, + "devDependencies": { + "@motion-canvas/ui": "^3.11.0", + "@motion-canvas/vite-plugin": "^3.11.0", + "typescript": "^4.9.5", + "vite": "^4.1.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/@motion-canvas/2d": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@motion-canvas/2d/-/2d-3.11.0.tgz", + "integrity": "sha512-T/RPXGRxddO/xxbC2RcOXfrtBTp8lfcmnuW1fa6++0qy0chK5NFxm3bHJczCbX0ynKB2VAoqLNobTF9eD6ZP3w==", + "dependencies": { + "@motion-canvas/core": "^3.11.0", + "code-fns": "^0.8.2", + "mathjax-full": "^3.2.2", + "parse-svg-path": "^0.1.2" + } + }, + "node_modules/@motion-canvas/core": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@motion-canvas/core/-/core-3.11.0.tgz", + "integrity": "sha512-/WjdoSTqTPwCgrB2pP8YXq2T3KviYHrywVxXJ5fEjQ1gajkPKYD7aVlRcY1+kaTbwqXhCARMCh+pSjT2nfhTsw==", + "dependencies": { + "@types/chroma-js": "^2.1.4", + "chroma-js": "^2.4.2" + }, + "peerDependencies": { + "vite": "^4.1.4" + } + }, + "node_modules/@motion-canvas/ui": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@motion-canvas/ui/-/ui-3.11.0.tgz", + "integrity": "sha512-sd0GxvCkejL2lzExsvgLsC1GgHzLP/0LlMw1QE2/3pMQo3rMOVA7L1Oq6br8HqdJhzMEgW3DWC0NjDJsUfkL2A==", + "dev": true, + "dependencies": { + "@motion-canvas/core": "^3.11.0" + } + }, + "node_modules/@motion-canvas/vite-plugin": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@motion-canvas/vite-plugin/-/vite-plugin-3.11.0.tgz", + "integrity": "sha512-26ixfy5NhvFePj1DBdh7MFsgevpRrzzEKjzSyCK3FOvPcnUWFjab4wWErpsIEnu6a0p7yj4w9VKpa8USx6N95A==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.15.2", + "mime-types": "^2.1.35" + }, + "peerDependencies": { + "vite": "4.x" + } + }, + "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/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/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "dev": true, + "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/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/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/mhchemparser": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/mhchemparser/-/mhchemparser-4.1.1.tgz", + "integrity": "sha512-R75CUN6O6e1t8bgailrF1qPq+HhVeFTM3XQ0uzI+mXTybmphy3b6h4NbLOYhemViQ3lUs+6CKRkC3Ws1TlYREA==" + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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/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/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/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/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/vite": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", + "integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==", + "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/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/static_no_classes/package.json b/animation/static_no_classes/package.json new file mode 100644 index 0000000..9c5588b --- /dev/null +++ b/animation/static_no_classes/package.json @@ -0,0 +1,19 @@ +{ + "name": "value_semantics", + "private": true, + "version": "0.0.0", + "scripts": { + "serve": "vite", + "build": "tsc && vite build" + }, + "dependencies": { + "@motion-canvas/2d": "^3.11.0", + "@motion-canvas/core": "^3.11.0" + }, + "devDependencies": { + "@motion-canvas/ui": "^3.11.0", + "@motion-canvas/vite-plugin": "^3.11.0", + "typescript": "^4.9.5", + "vite": "^4.1.4" + } +} diff --git a/animation/static_no_classes/src/global.css b/animation/static_no_classes/src/global.css new file mode 100644 index 0000000..84cea14 --- /dev/null +++ b/animation/static_no_classes/src/global.css @@ -0,0 +1 @@ +@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;700&display=swap'); diff --git a/animation/static_no_classes/src/motion-canvas.d.ts b/animation/static_no_classes/src/motion-canvas.d.ts new file mode 100644 index 0000000..067c6a4 --- /dev/null +++ b/animation/static_no_classes/src/motion-canvas.d.ts @@ -0,0 +1 @@ +/// diff --git a/animation/static_no_classes/src/project.meta b/animation/static_no_classes/src/project.meta new file mode 100644 index 0000000..7b0759f --- /dev/null +++ b/animation/static_no_classes/src/project.meta @@ -0,0 +1,32 @@ +{ + "version": 0, + "shared": { + "background": "rgb(10,20,30)", + "range": [ + 0, + null + ], + "size": { + "x": 1920, + "y": 1080 + }, + "audioOffset": 0 + }, + "preview": { + "fps": 30, + "resolutionScale": 1 + }, + "rendering": { + "fps": 30, + "resolutionScale": 2, + "colorSpace": "srgb", + "exporter": { + "name": "@motion-canvas/core/image-sequence", + "options": { + "fileType": "image/png", + "quality": 100, + "groupByScene": true + } + } + } +} \ No newline at end of file diff --git a/animation/static_no_classes/src/project.ts b/animation/static_no_classes/src/project.ts new file mode 100644 index 0000000..4d3565c --- /dev/null +++ b/animation/static_no_classes/src/project.ts @@ -0,0 +1,9 @@ +import {makeProject} from '@motion-canvas/core'; + +import static_vis from './scenes/static_vis?scene'; + +import './global.css'; // <- import the css + +export default makeProject({ + scenes: [static_vis], +}); diff --git a/animation/static_no_classes/src/scenes/example.meta b/animation/static_no_classes/src/scenes/example.meta new file mode 100644 index 0000000..2d62bec --- /dev/null +++ b/animation/static_no_classes/src/scenes/example.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 1501821170 +} \ No newline at end of file diff --git a/animation/static_no_classes/src/scenes/example.tsx b/animation/static_no_classes/src/scenes/example.tsx new file mode 100644 index 0000000..5ec127c --- /dev/null +++ b/animation/static_no_classes/src/scenes/example.tsx @@ -0,0 +1,400 @@ +import {makeScene2D} from '@motion-canvas/2d/lib/scenes'; +import {createRef} from '@motion-canvas/core/lib/utils'; +import { + CodeBlock, + edit, + insert, + lines, + word, + remove, + CodeModification, +} from '@motion-canvas/2d/lib/components/CodeBlock'; +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'; + +export default makeScene2D(function* (view) { + const codeRef = createRef(); + + yield view.add(); + + + const duration = 1.5 + + const store = (...args: [TemplateStringsArray, ...any]) => args; + + function to_string([strings, ...values]: [TemplateStringsArray, ...any]): string { + return strings.reduce((acc, str, i) => { + const value = values[i] ?? ''; + return acc + str + value; + }, ' '); + } + + function append( + template_1: TemplateStringsArray, args_1: string[], + template_2: TemplateStringsArray, args_2: string[]) : [TemplateStringsArray, ...string[]] { + let new_template = Array.from(template_1); + let new_args: Array = args_1; + new_template[template_1.length - 1] += template_2[0] + new_template = new_template.concat(template_2.slice(1)) + new_args = new_args.concat(args_2) + return [new_template as unknown as TemplateStringsArray, ...new_args]; + } + + const isCodeModification = (code: any): code is CodeModification => (code as CodeModification).from !== undefined; + + function simplify( + args_in: [TemplateStringsArray, ...any]) : [TemplateStringsArray, ...string[]] { + const template = args_in[0] + const args = args_in.slice(1) + if (args.every((arg) => (typeof(arg) == "string") || isCodeModification(arg))) { + return args_in + } + let new_template: Array = []; + let new_args: Array = []; + let concatenate = false; + for (let i = 0; i <= args.length; i++) { + if (concatenate) { + concatenate = false; + new_template[new_template.length - 1] += template[i]; + } else { + new_template.push(template[i]); + } + if (i == args.length) { break; } + if (typeof(args[i]) == "string" || isCodeModification(args[i])) { + new_args.push(args[i]) + continue; + } + let simplified_arg = simplify(args[i]); + let simplified_template = simplified_arg[0] + let simplified_args = simplified_arg.slice(1) + const appended = append( + new_template as unknown as TemplateStringsArray, + new_args, + simplified_template, + simplified_args as string[]); + new_template = Array.from(appended[0]) + new_args = appended.slice(1) + concatenate = true; + } + return [new_template as unknown as TemplateStringsArray, ...new_args] + } + + + const code = (operator:any = ``, main:any = ``, operator_move:any=``) => store` + #include + #include + + struct HugeObject { + HugeObject() = default; + + explicit HugeObject(std::size_t data_length) + : length{data_length}, ptr{AllocateMemory(length)} {} + ${operator}${operator_move} + ~HugeObject() { FreeMemory(ptr); } + + std::size_t length{}; + std::byte *ptr{}; + }; + ${main} + ` + + const copy = `ptr = AllocateMemory(length); + std::copy(object.ptr, object.ptr + length, ptr);` + const steal = `ptr = object.ptr; + object.ptr = nullptr;` + + const operator_copy = ( + const_word:any = `const `, + copy_or_steal:any = copy, + ) => store` + HugeObject &operator=(${const_word}HugeObject& object) { + if (this == &object) { return *this; } + FreeMemory(ptr); + length = object.length; + ${copy_or_steal} + return *this; + } + ` + + const operator_move = ` + + HugeObject &operator=(HugeObject&& object) { + if (this == &object) { return *this; } + FreeMemory(ptr); + length = object.length; + ptr = object.ptr; + object.ptr = nullptr; + return *this; + } + ` + + const assign_fail = ` + // ❌ Does not compile. + storage.member_object = HugeObject{200};` + + const assign_int_fail = ` + // ❌ Does not compile either. + int& answer = 42;` + + const main_fn = (comment:any = ``, assign_temp:any = ``) => store` + struct HugeObjectStorage { + HugeObject member_object; + }; + + int main() { + HugeObject object{100}; + HugeObjectStorage storage{}; + storage.member_object = object;${assign_temp} + return 0; + } ${comment}` + + const comment = ` // storage and object are destroyed` + + const zoom_fn = (in_zoom: number) => new Vector2(in_zoom, in_zoom); + + yield * codeRef().edit(duration, false)(...simplify(code())); + yield * codeRef().selection([...word(7, 30, 28)], duration); + yield * waitFor(duration); + yield * codeRef().selection([...word(9, 20, 15)], duration); + yield * waitFor(duration); + yield * codeRef().edit(duration, true)(...code(edit(``, to_string(operator_copy())))); + yield * waitFor(duration); + yield * codeRef().selection([...lines(9)], duration); + yield * waitFor(duration); + yield * all( + codeRef().selection([...word(9, 26, 24)], duration), + codeRef().scale(zoom_fn(1.5), duration), + codeRef().position(new Vector2(-500, 200), duration), + ); + yield * waitFor(duration); + yield * all( + codeRef().selection([...lines(14)], duration), + codeRef().scale(zoom_fn(1.2), duration), + codeRef().position(new Vector2(50, -200), duration), + ); + yield * waitFor(duration); + yield * all( + codeRef().selection(DEFAULT, duration), + codeRef().scale(zoom_fn(0.7), duration), + codeRef().position(new Vector2(0, 0), duration), + ); + yield * waitFor(duration); + yield * all( + codeRef().position(new Vector2(0, -300), duration), + codeRef().edit(duration, true)(...simplify(code(operator_copy(), edit(``, to_string(main_fn()))))), + ); + yield * all( + codeRef().scale(zoom_fn(1.2), duration), + codeRef().position(new Vector2(400, -800), duration), + ); + yield * codeRef().selection([...lines(29)], duration); + yield * codeRef().selection([...lines(30)], duration); + yield * codeRef().selection([...lines(31)], duration); + yield * codeRef().edit(duration, true)(...simplify(code(operator_copy(), main_fn(insert(comment))))); + yield * waitFor(duration); + + // Show destructor + yield * all( + codeRef().selection(DEFAULT, duration), + codeRef().scale(zoom_fn(0.5), duration), + codeRef().position(new Vector2(0, 0), duration), + ); + yield * waitFor(duration); + yield * all( + codeRef().selection(DEFAULT, duration), + codeRef().scale(zoom_fn(1.2), duration), + codeRef().selection([...lines(18 )], duration), + codeRef().position(new Vector2(200, 0), duration), + ); + yield * waitFor(duration); + + // Show const + yield * all( + codeRef().selection(DEFAULT, duration), + codeRef().scale(zoom_fn(0.5), duration), + codeRef().position(new Vector2(0, 0), duration), + ); + yield * waitFor(duration); + yield * all( + codeRef().scale(zoom_fn(1.2), duration), + codeRef().selection([...lines(9, 16)], duration), + codeRef().position(new Vector2(50, 400), duration), + ); + yield * waitFor(duration); + yield * all( + codeRef().scale(zoom_fn(3.0), duration), + codeRef().selection([...word(9, 26, 5)], duration), + codeRef().position(new Vector2(100, 1400), duration), + ); + yield * waitFor(duration); + + // Remove const + yield * all( + codeRef().edit(duration, false)(...simplify(code(operator_copy(edit('const ', '')), main_fn(comment)))), + codeRef().selection([...word(9, 26, 12)], duration), + ); + yield * all( + codeRef().scale(zoom_fn(1.2), duration), + codeRef().position(new Vector2(50, 400), duration), + codeRef().selection([...lines(9, 16)], duration), + ); + yield *codeRef().selection([...lines(13, 14)], duration); + yield * codeRef().edit(duration, true)(...simplify(code(operator_copy('', edit(copy, steal)), main_fn(comment)))); + yield * waitFor(duration); + + // Look at the main again + yield * all( + codeRef().selection(DEFAULT, duration), + codeRef().scale(zoom_fn(0.5), duration), + codeRef().position(new Vector2(0, 0), duration), + ); + yield * waitFor(duration); + yield * all( + codeRef().scale(zoom_fn(1.2), duration), + codeRef().position(new Vector2(400, -800), duration), + ); + yield * codeRef().selection([...lines(29)], duration); + yield * codeRef().selection([...lines(30)], duration); + yield * codeRef().selection([...lines(31)], duration); + yield * codeRef().selection(DEFAULT, duration); + + yield * waitFor(duration); + // Assign temp + yield * all( + codeRef().scale(zoom_fn(1.3), duration), + codeRef().edit(duration, true)( + ...simplify( + code( + operator_copy('', steal), + main_fn(comment, insert(assign_fail))))), + codeRef().position(new Vector2(200, -1100), duration), + ); + yield * waitFor(duration); + yield * codeRef().edit(duration, true)( + ...simplify( + code( + operator_copy('', steal), + main_fn(comment, edit(assign_fail, assign_int_fail))))); + yield * waitFor(duration); + + yield * all( + codeRef().selection(DEFAULT, duration), + codeRef().scale(zoom_fn(0.5), duration), + codeRef().position(new Vector2(0, 0), duration), + codeRef().edit(duration, false)( + ...simplify( + code( + operator_copy('', steal), + main_fn(comment, remove(assign_int_fail))))), + ); + + // Add move operator + yield * waitFor(duration); + yield * all( + codeRef().scale(zoom_fn(1.0), duration), + codeRef().position([0, 260], duration), + codeRef().edit(duration, true)( + ...simplify( + code( + operator_copy(insert('const '), + edit(steal, copy)), + main_fn(comment), + insert(operator_move)))), + ); + yield * waitFor(duration); + yield * codeRef().selection([...word(9, 26, 24), ...lines(13, 14)], duration); + yield * waitFor(duration); + yield * codeRef().selection([...word(18, 26, 19), ...lines(22, 23)], duration); + yield * waitFor(duration); + + const comment_temp_bind = `// Can be bound to a temporary` + const comment_pick_overload = ` // The compiler picks Blah(int&&)` + + const blah_code = ( + comment_temp:any = ``, + comment_pick:any = ``, + blah_answer:any = ``, + blah_answer_comment:any = ``, + blah_move_answer:any = ``, + blah_move_answer_comment:any = ``, + ) => store` + #include + + void Blah(int&) { + std::cout << "&" << std::endl; + } + + void Blah(int&&) { + std::cout << "&&" << std::endl; + } + + int main() { + int&& answer = 42; ${comment_temp} + Blah(42);${comment_pick}${blah_answer}${blah_answer_comment}${blah_move_answer}${blah_move_answer_comment} + }` + + + yield * waitFor(duration); + yield * all( + codeRef().edit(duration, false)(...blah_code()), + codeRef().selection(DEFAULT, duration), + codeRef().scale(zoom_fn(1.0), 0), + codeRef().position(new Vector2(0, 0), 0), + ); + yield * waitFor(duration); + yield * codeRef().selection([...lines(11)], duration); + yield * codeRef().edit(duration, false)(...simplify(blah_code(insert(comment_temp_bind)))); + yield * waitFor(duration); + yield * codeRef().selection([...lines(12)], duration); + yield * codeRef().edit(duration, false)(...simplify(blah_code(comment_temp_bind, insert(comment_pick_overload)))); + yield * waitFor(duration); + yield * waitFor(duration); + + + const final_main = ` + int main() { + HugeObject object{100}; + HugeObjectStorage storage{}; + storage.member_object = object; + storage.member_object = HugeObject{200}; + storage.member_object = std::move(object); + return 0; + }` + + yield * codeRef().selection(DEFAULT, 0), + yield * codeRef().edit(duration, false)`${final_main}`; + yield * waitFor(duration); + yield * codeRef().selection([...lines(4)], duration); + yield * codeRef().selection([...lines(5)], duration); + yield * codeRef().selection([...lines(6)], duration); + yield * waitFor(duration); + + const rref_comment = ` // Prints "&&"` + const lref_comment = ` // Prints "&"` + const blah_answer_ref = ` + Blah(answer);` + const blah_answer_rref = ` + Blah(std::move(answer));` + + // Final rref example + yield * codeRef().selection(DEFAULT, 0), + yield * codeRef().edit(duration, false)(...blah_code()); + yield * codeRef().edit(duration, false)(...blah_code('', insert(rref_comment))); + yield * codeRef().edit(duration, false)(...blah_code('', rref_comment, insert(blah_answer_ref))); + yield * codeRef().edit(duration, false)(...blah_code( + '', rref_comment, blah_answer_ref, insert(lref_comment))); + yield * codeRef().edit(duration, false)(...blah_code( + '', rref_comment, blah_answer_ref, lref_comment, insert(blah_answer_rref))); + yield * codeRef().edit(duration, false)(...blah_code( + '', rref_comment, blah_answer_ref, lref_comment, blah_answer_rref, insert(rref_comment))); + + yield * waitFor(duration); + + yield * waitFor(duration); + +}); diff --git a/animation/static_no_classes/src/scenes/memory.meta b/animation/static_no_classes/src/scenes/memory.meta new file mode 100644 index 0000000..bdef019 --- /dev/null +++ b/animation/static_no_classes/src/scenes/memory.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 3499084582 +} \ No newline at end of file diff --git a/animation/static_no_classes/src/scenes/memory.tsx b/animation/static_no_classes/src/scenes/memory.tsx new file mode 100644 index 0000000..0a35176 --- /dev/null +++ b/animation/static_no_classes/src/scenes/memory.tsx @@ -0,0 +1,96 @@ +import {makeScene2D} from '@motion-canvas/2d/lib/scenes'; +import {Node, Circle, Rect, Grid, Line} from '@motion-canvas/2d/lib/components'; +import {all, waitFor} from '@motion-canvas/core/lib/flow'; +import {Vector2} from '@motion-canvas/core/lib/types'; +import {createRef} from '@motion-canvas/core/lib/utils'; +import {createSignal} from '@motion-canvas/core/lib/signals'; +import {CodeBlock} from '@motion-canvas/2d/lib/components/CodeBlock'; + +const RED = '#ff6470'; +const GREEN = '#99C47A'; +const BLUE = '#68ABDF'; + +export default makeScene2D(function* (view) { + const data_ref = createRef(); + const line_1 = createRef(); + const line_2 = createRef(); + + const data = ` + 1011011010110 + 1011000100100 + 0010011100000 + 1101000010001 + 0010100111111` + + const object_code = `object` + const member_object_code = `storage.member_object` + + view.add( + + {/* */} + {/* */} + + + + + + + + + + , + ); + + yield* line_1().opacity(1.0, 1.0) + yield* line_1().points([[1000, 50], [750, 300]], 2.0) + + yield * waitFor(2.0); + yield* line_1().points([[0, 50], [250, 300]], 0.0) + yield * waitFor(1.0); + yield* line_2().opacity(1.0, 1.0) + yield * waitFor(2.0); +}); diff --git a/animation/static_no_classes/src/scenes/static_vis.meta b/animation/static_no_classes/src/scenes/static_vis.meta new file mode 100644 index 0000000..5964ccf --- /dev/null +++ b/animation/static_no_classes/src/scenes/static_vis.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 2078473243 +} \ No newline at end of file diff --git a/animation/static_no_classes/src/scenes/static_vis.tsx b/animation/static_no_classes/src/scenes/static_vis.tsx new file mode 100644 index 0000000..a4672c1 --- /dev/null +++ b/animation/static_no_classes/src/scenes/static_vis.tsx @@ -0,0 +1,308 @@ +import { makeScene2D } from '@motion-canvas/2d/lib/scenes'; +import { Node, Txt, Rect, Grid, Line } from '@motion-canvas/2d/lib/components'; +import { all, waitFor } from '@motion-canvas/core/lib/flow'; +import { createRef } from '@motion-canvas/core/lib/utils'; +import { createSignal } from '@motion-canvas/core/lib/signals'; +import { + CodeBlock, + edit, + insert, + lines, + word, + remove, + CodeModification, +} from '@motion-canvas/2d/lib/components/CodeBlock'; +import { DEFAULT } from '@motion-canvas/core/lib/signals'; +import { BBox, Vector2 } from '@motion-canvas/core/lib/types'; + +const RED = '#ff6470'; +const GREEN = '#99A44A'; +const BLUE = '#68AADD'; +const WHITE = '#FFFFFF'; + +export default makeScene2D(function* (view: { add: (arg0: Node) => void; }) { + const left_half = createRef(); + const all_text_node = createRef(); + + const program_lifetime = createRef(); + const program_text = createRef(); + + const main_lifetime = createRef(); + const main_text = createRef(); + + const foo_lifetime = createRef(); + const foo_text = createRef(); + + const value_name = createRef(); + const value_lifetime = createRef(); + + const const_name = createRef(); + const const_lifetime = createRef(); + + const right_half = createRef(); + const code_ref = createRef(); + + const text_offset = 12 + const line_offset = 100 + const x_offset = 80 + + view.add( + <> + + + program + + + + main() + + + Foo() + + + local_value + + + + + kValue + + + + + + + , + ); + + const duration = 1.5 + + const store = (...args: [TemplateStringsArray, ...any]) => args; + + function to_string([strings, ...values]: [TemplateStringsArray, ...any]): string { + return strings.reduce((acc, str, i) => { + const value = values[i] ?? ''; + return acc + str + value; + }, ' '); + } + + function append( + template_1: TemplateStringsArray, args_1: string[], + template_2: TemplateStringsArray, args_2: string[]): [TemplateStringsArray, ...string[]] { + let new_template = Array.from(template_1); + let new_args: Array = args_1; + new_template[template_1.length - 1] += template_2[0] + new_template = new_template.concat(template_2.slice(1)) + new_args = new_args.concat(args_2) + return [new_template as unknown as TemplateStringsArray, ...new_args]; + } + + const isCodeModification = (code: any): code is CodeModification => (code as CodeModification).from !== undefined; + + function simplify( + args_in: [TemplateStringsArray, ...any]): [TemplateStringsArray, ...string[]] { + const template = args_in[0] + const args = args_in.slice(1) + if (args.every((arg) => (typeof (arg) == "string") || isCodeModification(arg))) { + return args_in + } + let new_template: Array = []; + let new_args: Array = []; + let concatenate = false; + for (let i = 0; i <= args.length; i++) { + if (concatenate) { + concatenate = false; + new_template[new_template.length - 1] += template[i]; + } else { + new_template.push(template[i]); + } + if (i == args.length) { break; } + if (typeof (args[i]) == "string" || isCodeModification(args[i])) { + new_args.push(args[i]) + continue; + } + let simplified_arg = simplify(args[i]); + let simplified_template = simplified_arg[0] + let simplified_args = simplified_arg.slice(1) + const appended = append( + new_template as unknown as TemplateStringsArray, + new_args, + simplified_template, + simplified_args as string[]); + new_template = Array.from(appended[0]) + new_args = appended.slice(1) + concatenate = true; + } + return [new_template as unknown as TemplateStringsArray, ...new_args] + } + + const const_value_code = ` + namespace { + constexpr int kValue{42}; + } // namespace + ` + + const foo_func = (init_value: any = ``, static_keyword: any = ``) => store` + void Foo() { + ${static_keyword}int local_value{${init_value}}; + } + ` + + const foo_call = `\n Foo();` + + const code = (func_code: any = ``, func_call: any = ``, constant_def: any = ``) => store` +${constant_def}${func_code} + int main() {${func_call} + return 0; + } + ` + + yield* code_ref().edit(duration, false)(...simplify(code())); + yield* waitFor(duration / 2); + yield* all( + program_lifetime().opacity(1.0, 0), + program_lifetime().end(0.0, 0).to(1.0, duration / 2), + program_text().opacity(0.0, 0).to(1.0, duration / 2), + ); + yield* all( + main_lifetime().opacity(1.0, 0), + main_lifetime().end(0.0, 0).to(1.0, duration / 2), + main_text().opacity(0.0, 0).to(1.0, duration / 2), + ); + yield* waitFor(duration); + + yield* code_ref().edit(duration, false)(...simplify(code(edit('', to_string(foo_func())), edit('', foo_call)))); + yield* all( + foo_lifetime().opacity(1.0, 0), + foo_lifetime().end(0.0, 0).to(1.0, duration / 2), + foo_text().opacity(0.0, 0).to(1.0, duration / 2), + ); + yield* waitFor(duration / 2); + yield* all( + code_ref().selection(lines(2), duration / 2), + value_lifetime().opacity(0.0, 0).to(1.0, duration / 2), + value_lifetime().scale.x(0.0, 0).to(1.0, duration / 2), + ); + yield* waitFor(duration); + + yield* code_ref().selection(DEFAULT, duration / 2); + yield* code_ref().edit(duration, false)(...simplify(code(foo_func(edit('', 'kValue')), foo_call, edit('', const_value_code)))); + yield* all( + all_text_node().y(0.0, 0).to(-120, duration / 2), + ); + yield* all( + const_lifetime().opacity(0.0, 0).to(1.0, duration / 2), + const_lifetime().scale.x(0.0, 0).to(1.0, duration / 2), + ); + yield* waitFor(duration); + yield* all( + code_ref().edit(duration, true)(...simplify(code(foo_func('kValue', edit('', 'static ')), foo_call, const_value_code))), + value_lifetime().width(380, duration / 2).to(550, duration / 2), + value_lifetime().fill(GREEN, duration), + ); + + yield* waitFor(duration); + + // yield* waitFor(2.0); + // yield* a_ref().edit(1.0, false)`${insert(object_code)}`; + // yield* all( + // grid_ref().height(0, 0.0).to(250, 0.5), + // grid_ref().width(0, 0.0).to(1920, 0.5), + // grid_ref().opacity(1.0, 0.1), + // ); + // yield* all( + // data_rect_ref().opacity(0.5, 1.0), + // line_1().end(1, 1.0), + // gray_line_ref().opacity(1.0, 0.5), + // gray_code_ref().opacity(1.0, 0.5), + // ); + // yield* b_ref().edit(1.0, false)`${insert(member_object_code)}`; + // yield* waitFor(1.0); + // yield* data_rect_ref().scale(1.2, 1.0); + // yield* data_rect_ref().position.x(-20, 0.2).to(20, 0.2).to(-20, 0.2).to(20, 0.2).to(0, 0.2); + // yield* data_rect_ref().scale(1.0, 0.5); + // yield* waitFor(1.0); + // yield* line_2().end(1, 1.5); + // yield* waitFor(1.0); + // yield* all( + // data_rect_ref().opacity(0.5, 1.0), + // line_1().arrowSize(0, 0.5), + // line_1().end(0, 1.0), + // a_ref().edit(1.5, false)`Data* a${insert(' = nullptr')};`, + // ); + + yield* waitFor(3.0); + +}); diff --git a/animation/static_no_classes/tsconfig.json b/animation/static_no_classes/tsconfig.json new file mode 100644 index 0000000..789b7d1 --- /dev/null +++ b/animation/static_no_classes/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "@motion-canvas/2d/tsconfig.project.json", + "compilerOptions": { + "baseUrl": "src" + }, + "include": ["src"] +} diff --git a/animation/static_no_classes/vite.config.ts b/animation/static_no_classes/vite.config.ts new file mode 100644 index 0000000..bf32088 --- /dev/null +++ b/animation/static_no_classes/vite.config.ts @@ -0,0 +1,6 @@ +import {defineConfig} from 'vite'; +import motionCanvas from '@motion-canvas/vite-plugin'; + +export default defineConfig({ + plugins: [motionCanvas()], +}); diff --git a/animation/value_semantics/package-lock.json b/animation/value_semantics/package-lock.json index 9ebec27..cdefbbe 100644 --- a/animation/value_semantics/package-lock.json +++ b/animation/value_semantics/package-lock.json @@ -8,20 +8,20 @@ "name": "value_semantics", "version": "0.0.0", "dependencies": { - "@motion-canvas/2d": "^3.4.0", - "@motion-canvas/core": "^3.4.0" + "@motion-canvas/2d": "^3.11.0", + "@motion-canvas/core": "^3.11.0" }, "devDependencies": { - "@motion-canvas/ui": "^3.4.0", - "@motion-canvas/vite-plugin": "^3.4.0", + "@motion-canvas/ui": "^3.11.0", + "@motion-canvas/vite-plugin": "^3.11.0", "typescript": "^4.9.5", "vite": "^4.1.4" } }, "node_modules/@esbuild/android-arm": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.15.tgz", - "integrity": "sha512-sRSOVlLawAktpMvDyJIkdLI/c/kdRTOqo8t6ImVxg8yT7LQDUYV5Rp2FKeEosLr6ZCja9UjYAzyRSxGteSJPYg==", + "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" ], @@ -34,9 +34,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.15.tgz", - "integrity": "sha512-0kOB6Y7Br3KDVgHeg8PRcvfLkq+AccreK///B4Z6fNZGr/tNHX0z2VywCc7PTeWp+bPvjA5WMvNXltHw5QjAIA==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", "cpu": [ "arm64" ], @@ -49,9 +49,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.15.tgz", - "integrity": "sha512-MzDqnNajQZ63YkaUWVl9uuhcWyEyh69HGpMIrf+acR4otMkfLJ4sUCxqwbCyPGicE9dVlrysI3lMcDBjGiBBcQ==", + "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" ], @@ -64,9 +64,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.15.tgz", - "integrity": "sha512-7siLjBc88Z4+6qkMDxPT2juf2e8SJxmsbNVKFY2ifWCDT72v5YJz9arlvBw5oB4W/e61H1+HDB/jnu8nNg0rLA==", + "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" ], @@ -79,9 +79,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.15.tgz", - "integrity": "sha512-NbImBas2rXwYI52BOKTW342Tm3LTeVlaOQ4QPZ7XuWNKiO226DisFk/RyPk3T0CKZkKMuU69yOvlapJEmax7cg==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", "cpu": [ "x64" ], @@ -94,9 +94,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.15.tgz", - "integrity": "sha512-Xk9xMDjBVG6CfgoqlVczHAdJnCs0/oeFOspFap5NkYAmRCT2qTn1vJWA2f419iMtsHSLm+O8B6SLV/HlY5cYKg==", + "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" ], @@ -109,9 +109,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.15.tgz", - "integrity": "sha512-3TWAnnEOdclvb2pnfsTWtdwthPfOz7qAfcwDLcfZyGJwm1SRZIMOeB5FODVhnM93mFSPsHB9b/PmxNNbSnd0RQ==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", "cpu": [ "x64" ], @@ -124,9 +124,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.15.tgz", - "integrity": "sha512-MLTgiXWEMAMr8nmS9Gigx43zPRmEfeBfGCwxFQEMgJ5MC53QKajaclW6XDPjwJvhbebv+RzK05TQjvH3/aM4Xw==", + "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" ], @@ -139,9 +139,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.15.tgz", - "integrity": "sha512-T0MVnYw9KT6b83/SqyznTs/3Jg2ODWrZfNccg11XjDehIved2oQfrX/wVuev9N936BpMRaTR9I1J0tdGgUgpJA==", + "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" ], @@ -154,9 +154,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.15.tgz", - "integrity": "sha512-wp02sHs015T23zsQtU4Cj57WiteiuASHlD7rXjKUyAGYzlOKDAjqK6bk5dMi2QEl/KVOcsjwL36kD+WW7vJt8Q==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", "cpu": [ "ia32" ], @@ -169,9 +169,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.15.tgz", - "integrity": "sha512-k7FsUJjGGSxwnBmMh8d7IbObWu+sF/qbwc+xKZkBe/lTAF16RqxRCnNHA7QTd3oS2AfGBAnHlXL67shV5bBThQ==", + "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" ], @@ -184,9 +184,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.15.tgz", - "integrity": "sha512-ZLWk6czDdog+Q9kE/Jfbilu24vEe/iW/Sj2d8EVsmiixQ1rM2RKH2n36qfxK4e8tVcaXkvuV3mU5zTZviE+NVQ==", + "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" ], @@ -199,9 +199,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.15.tgz", - "integrity": "sha512-mY6dPkIRAiFHRsGfOYZC8Q9rmr8vOBZBme0/j15zFUKM99d4ILY4WpOC7i/LqoY+RE7KaMaSfvY8CqjJtuO4xg==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", "cpu": [ "ppc64" ], @@ -214,9 +214,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.15.tgz", - "integrity": "sha512-EcyUtxffdDtWjjwIH8sKzpDRLcVtqANooMNASO59y+xmqqRYBBM7xVLQhqF7nksIbm2yHABptoioS9RAbVMWVA==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", "cpu": [ "riscv64" ], @@ -229,9 +229,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.15.tgz", - "integrity": "sha512-BuS6Jx/ezxFuHxgsfvz7T4g4YlVrmCmg7UAwboeyNNg0OzNzKsIZXpr3Sb/ZREDXWgt48RO4UQRDBxJN3B9Rbg==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", "cpu": [ "s390x" ], @@ -244,9 +244,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.15.tgz", - "integrity": "sha512-JsdS0EgEViwuKsw5tiJQo9UdQdUJYuB+Mf6HxtJSPN35vez1hlrNb1KajvKWF5Sa35j17+rW1ECEO9iNrIXbNg==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", "cpu": [ "x64" ], @@ -259,9 +259,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.15.tgz", - "integrity": "sha512-R6fKjtUysYGym6uXf6qyNephVUQAGtf3n2RCsOST/neIwPqRWcnc3ogcielOd6pT+J0RDR1RGcy0ZY7d3uHVLA==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", "cpu": [ "x64" ], @@ -274,9 +274,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.15.tgz", - "integrity": "sha512-mVD4PGc26b8PI60QaPUltYKeSX0wxuy0AltC+WCTFwvKCq2+OgLP4+fFd+hZXzO2xW1HPKcytZBdjqL6FQFa7w==", + "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" ], @@ -289,9 +289,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.15.tgz", - "integrity": "sha512-U6tYPovOkw3459t2CBwGcFYfFRjivcJJc1WC8Q3funIwX8x4fP+R6xL/QuTPNGOblbq/EUDxj9GU+dWKX0oWlQ==", + "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" ], @@ -304,9 +304,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.15.tgz", - "integrity": "sha512-W+Z5F++wgKAleDABemiyXVnzXgvRFs+GVKThSI+mGgleLWluv0D7Diz4oQpgdpNzh4i2nNDzQtWbjJiqutRp6Q==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", "cpu": [ "arm64" ], @@ -319,9 +319,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.15.tgz", - "integrity": "sha512-Muz/+uGgheShKGqSVS1KsHtCyEzcdOn/W/Xbh6H91Etm+wiIfwZaBn1W58MeGtfI8WA961YMHFYTthBdQs4t+w==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", "cpu": [ "ia32" ], @@ -334,9 +334,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.15.tgz", - "integrity": "sha512-DjDa9ywLUUmjhV2Y9wUTIF+1XsmuFGvZoCmOWkli1XcNAh5t25cc7fgsCx4Zi/Uurep3TTLyDiKATgGEg61pkA==", + "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" ], @@ -349,19 +349,20 @@ } }, "node_modules/@motion-canvas/2d": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@motion-canvas/2d/-/2d-3.4.0.tgz", - "integrity": "sha512-3CmB2v6eQiSo7763goTKdAreTC4qIM9Qx/N31/Ov7CVWVZ31nUFGR5pRkfyrnoHHI718cfuZNArITPlB86U+LA==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@motion-canvas/2d/-/2d-3.11.0.tgz", + "integrity": "sha512-T/RPXGRxddO/xxbC2RcOXfrtBTp8lfcmnuW1fa6++0qy0chK5NFxm3bHJczCbX0ynKB2VAoqLNobTF9eD6ZP3w==", "dependencies": { - "@motion-canvas/core": "^3.4.0", + "@motion-canvas/core": "^3.11.0", "code-fns": "^0.8.2", - "mathjax-full": "^3.2.2" + "mathjax-full": "^3.2.2", + "parse-svg-path": "^0.1.2" } }, "node_modules/@motion-canvas/core": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@motion-canvas/core/-/core-3.4.0.tgz", - "integrity": "sha512-qGLjnhBshnXJqTgtnx/eSJTYmXWo5PtemV4TCczkbDQhvvjNxWwVHIQDNTG4bCg7R1gzKPizFzW63L9q+bIUaw==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@motion-canvas/core/-/core-3.11.0.tgz", + "integrity": "sha512-/WjdoSTqTPwCgrB2pP8YXq2T3KviYHrywVxXJ5fEjQ1gajkPKYD7aVlRcY1+kaTbwqXhCARMCh+pSjT2nfhTsw==", "dependencies": { "@types/chroma-js": "^2.1.4", "chroma-js": "^2.4.2" @@ -371,18 +372,18 @@ } }, "node_modules/@motion-canvas/ui": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@motion-canvas/ui/-/ui-3.4.0.tgz", - "integrity": "sha512-ntgBqqlZdAiTwpySyjf9UFBYDwXgr61UQDtyAJiQzqy0HqDeO0TZKSIqSgAgkY8GCwR2ELP+ITyEW6H0Mq6ZKw==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@motion-canvas/ui/-/ui-3.11.0.tgz", + "integrity": "sha512-sd0GxvCkejL2lzExsvgLsC1GgHzLP/0LlMw1QE2/3pMQo3rMOVA7L1Oq6br8HqdJhzMEgW3DWC0NjDJsUfkL2A==", "dev": true, "dependencies": { - "@motion-canvas/core": "^3.4.0" + "@motion-canvas/core": "^3.11.0" } }, "node_modules/@motion-canvas/vite-plugin": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@motion-canvas/vite-plugin/-/vite-plugin-3.4.0.tgz", - "integrity": "sha512-tzSCw1RruDBJsF3WV6nXkMMUd5P4KMmSQ+j477qqxTIrklE+Pm4Y9Mdn3M2v3q6fr/o2b4nLa5l7QC/iZ2n9PQ==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@motion-canvas/vite-plugin/-/vite-plugin-3.11.0.tgz", + "integrity": "sha512-26ixfy5NhvFePj1DBdh7MFsgevpRrzzEKjzSyCK3FOvPcnUWFjab4wWErpsIEnu6a0p7yj4w9VKpa8USx6N95A==", "dev": true, "dependencies": { "follow-redirects": "^1.15.2", @@ -447,9 +448,9 @@ } }, "node_modules/esbuild": { - "version": "0.17.15", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.15.tgz", - "integrity": "sha512-LBUV2VsUIc/iD9ME75qhT4aJj0r75abCVS0jakhFzOtR7TQsqQA5w0tZ+KTKnwl3kXE0MhskNdHDh/I5aCR1Zw==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -458,28 +459,28 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.17.15", - "@esbuild/android-arm64": "0.17.15", - "@esbuild/android-x64": "0.17.15", - "@esbuild/darwin-arm64": "0.17.15", - "@esbuild/darwin-x64": "0.17.15", - "@esbuild/freebsd-arm64": "0.17.15", - "@esbuild/freebsd-x64": "0.17.15", - "@esbuild/linux-arm": "0.17.15", - "@esbuild/linux-arm64": "0.17.15", - "@esbuild/linux-ia32": "0.17.15", - "@esbuild/linux-loong64": "0.17.15", - "@esbuild/linux-mips64el": "0.17.15", - "@esbuild/linux-ppc64": "0.17.15", - "@esbuild/linux-riscv64": "0.17.15", - "@esbuild/linux-s390x": "0.17.15", - "@esbuild/linux-x64": "0.17.15", - "@esbuild/netbsd-x64": "0.17.15", - "@esbuild/openbsd-x64": "0.17.15", - "@esbuild/sunos-x64": "0.17.15", - "@esbuild/win32-arm64": "0.17.15", - "@esbuild/win32-ia32": "0.17.15", - "@esbuild/win32-x64": "0.17.15" + "@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": { @@ -511,9 +512,9 @@ } }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "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": [ @@ -523,22 +524,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/import-meta-resolve": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-2.2.2.tgz", @@ -548,17 +533,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/mathjax-full": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/mathjax-full/-/mathjax-full-3.2.2.tgz", @@ -618,10 +592,10 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "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", @@ -629,9 +603,9 @@ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "funding": [ { "type": "opencollective", @@ -640,10 +614,14 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -651,26 +629,10 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/rollup": { - "version": "3.20.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.2.tgz", - "integrity": "sha512-3zwkBQl7Ai7MFYQE0y1MeQ15+9jsi7XxfrqwTb/9EK8D9C9+//EBR4M+CuA1KODRaNbFez/lWxA5vhEGZp4MUg==", + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", "bin": { "rollup": "dist/bin/rollup" }, @@ -703,17 +665,6 @@ "sre": "bin/sre" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", @@ -728,14 +679,13 @@ } }, "node_modules/vite": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.2.1.tgz", - "integrity": "sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", + "integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==", "dependencies": { - "esbuild": "^0.17.5", - "postcss": "^8.4.21", - "resolve": "^1.22.1", - "rollup": "^3.18.0" + "esbuild": "^0.18.10", + "postcss": "^8.4.27", + "rollup": "^3.27.1" }, "bin": { "vite": "bin/vite.js" @@ -743,12 +693,16 @@ "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": "*", @@ -761,6 +715,9 @@ "less": { "optional": true }, + "lightningcss": { + "optional": true + }, "sass": { "optional": true }, diff --git a/animation/value_semantics/package.json b/animation/value_semantics/package.json index 4c4a6cf..9c5588b 100644 --- a/animation/value_semantics/package.json +++ b/animation/value_semantics/package.json @@ -7,13 +7,13 @@ "build": "tsc && vite build" }, "dependencies": { - "@motion-canvas/core": "^3.4.0", - "@motion-canvas/2d": "^3.4.0" + "@motion-canvas/2d": "^3.11.0", + "@motion-canvas/core": "^3.11.0" }, "devDependencies": { - "@motion-canvas/ui": "^3.4.0", - "@motion-canvas/vite-plugin": "^3.4.0", + "@motion-canvas/ui": "^3.11.0", + "@motion-canvas/vite-plugin": "^3.11.0", "typescript": "^4.9.5", "vite": "^4.1.4" } -} \ No newline at end of file +} diff --git a/animation/value_semantics/src/project.meta b/animation/value_semantics/src/project.meta index 95df883..7b0759f 100644 --- a/animation/value_semantics/src/project.meta +++ b/animation/value_semantics/src/project.meta @@ -21,7 +21,7 @@ "resolutionScale": 2, "colorSpace": "srgb", "exporter": { - "name": "image sequence", + "name": "@motion-canvas/core/image-sequence", "options": { "fileType": "image/png", "quality": 100, diff --git a/lectures/code/static_no_classes/odr_violation/CMakeLists.txt b/lectures/code/static_no_classes/odr_violation/CMakeLists.txt new file mode 100644 index 0000000..ec17201 --- /dev/null +++ b/lectures/code/static_no_classes/odr_violation/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.16..3.24) +project( + odr_violation + VERSION 0.0.1 + DESCRIPTION "Our first project" + LANGUAGES CXX) +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE + Release + CACHE STRING "" FORCE) +endif() +message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") + +add_library(cxx_setup INTERFACE) +target_compile_options(cxx_setup INTERFACE -Wall -Wpedantic -Wextra) +target_compile_features(cxx_setup INTERFACE cxx_std_17) +target_include_directories(cxx_setup INTERFACE ${PROJECT_SOURCE_DIR}) + +add_library(our_cool_lib our_cool_lib.cpp) +target_link_libraries(our_cool_lib PUBLIC cxx_setup) + +add_library(other_lib other_lib.cpp) +target_link_libraries(other_lib PUBLIC cxx_setup) + +add_executable(main main.cpp) +target_link_libraries(main PRIVATE other_lib our_cool_lib) diff --git a/lectures/code/static_no_classes/odr_violation/main.cpp b/lectures/code/static_no_classes/odr_violation/main.cpp new file mode 100644 index 0000000..fb39eee --- /dev/null +++ b/lectures/code/static_no_classes/odr_violation/main.cpp @@ -0,0 +1,7 @@ +#include "our_cool_lib.hpp" +#include "other_lib.hpp" + +int main() { + SayHello(); + return 0; +} diff --git a/lectures/code/static_no_classes/odr_violation/other_lib.cpp b/lectures/code/static_no_classes/odr_violation/other_lib.cpp new file mode 100644 index 0000000..1f712fd --- /dev/null +++ b/lectures/code/static_no_classes/odr_violation/other_lib.cpp @@ -0,0 +1,5 @@ +#include "other_lib.hpp" + +#include + +void SayHello() { std::cout << "What??? 🤯" << std::endl; } diff --git a/lectures/code/static_no_classes/odr_violation/other_lib.hpp b/lectures/code/static_no_classes/odr_violation/other_lib.hpp new file mode 100644 index 0000000..8fece9e --- /dev/null +++ b/lectures/code/static_no_classes/odr_violation/other_lib.hpp @@ -0,0 +1,6 @@ +#ifndef LECTURES_CODE_STATIC_NO_CLASSES_ODR_VIOLATION_WRONG_LIB_HPP +#define LECTURES_CODE_STATIC_NO_CLASSES_ODR_VIOLATION_WRONG_LIB_HPP + +void SayHello(); // 😱 This really should be inline + +#endif /* LECTURES_CODE_STATIC_NO_CLASSES_ODR_VIOLATION_WRONG_LIB_HPP */ diff --git a/lectures/code/static_no_classes/odr_violation/our_cool_lib.cpp b/lectures/code/static_no_classes/odr_violation/our_cool_lib.cpp new file mode 100644 index 0000000..35eaccd --- /dev/null +++ b/lectures/code/static_no_classes/odr_violation/our_cool_lib.cpp @@ -0,0 +1,5 @@ +#include "our_cool_lib.hpp" + +#include + +void SayHello() { std::cout << "Hello!" << std::endl; } diff --git a/lectures/code/static_no_classes/odr_violation/our_cool_lib.hpp b/lectures/code/static_no_classes/odr_violation/our_cool_lib.hpp new file mode 100644 index 0000000..28c2ea1 --- /dev/null +++ b/lectures/code/static_no_classes/odr_violation/our_cool_lib.hpp @@ -0,0 +1,6 @@ +#ifndef LECTURES_CODE_STATIC_NO_CLASSES_ODR_VIOLATION_OUR_COOL_LIB_HPP +#define LECTURES_CODE_STATIC_NO_CLASSES_ODR_VIOLATION_OUR_COOL_LIB_HPP + +void SayHello(); // 😱 This really should be inline + +#endif /* LECTURES_CODE_STATIC_NO_CLASSES_ODR_VIOLATION_OUR_COOL_LIB_HPP */ diff --git a/lectures/namespaces_using.md b/lectures/namespaces_using.md index df8fc59..f0bbe94 100644 --- a/lectures/namespaces_using.md +++ b/lectures/namespaces_using.md @@ -9,7 +9,7 @@ footer: ![width:80px](images/C++ForYourselfIcon.png) - Namespaces - Using `using` -### 📺 Watch the related YouTube video! +### 📺 Watch the related YouTube video! --- # Prerequisites: @@ -54,7 +54,7 @@ Style (🎨) and software design (🎓) recommendations mostly come from [Google } // namespace bar } // namespace foo ``` -- 🎨 End with comment: `// namespace ` +- 🎨 End with comment: `// namespace ` (`clang_format` will take care of this) - 🎨 Name them like variables in `snake_case` ([source](https://google.github.io/styleguide/cppguide.html#Namespace_Names)) - 🎨 Do not indent the code inside the namespace ([source](https://google.github.io/styleguide/cppguide.html#Namespace_Formatting)) @@ -101,7 +101,7 @@ int main() { return 0; } ``` ---- +--- # Use unnamed namespaces! - ✅ Use **"unnamed" namespaces** in source files ```cpp @@ -116,7 +116,7 @@ int main() { ``` - They are sometimes also called **"anonymous" namespaces** - This generates a namespace with a unique name available only in this "translation unit" (aka source file) -- Also has "linkage" implications +- Also has "[linkage](static.md#linkage)" implications (stay tuned for when we talk about `static`) - Only use them in `.cpp`, `.cc` files, never in `.h`, `.hpp` etc. (stay tuned for when we talk about headers) @@ -140,8 +140,8 @@ int main() { } ``` - :x: **Don't** use from **global scope** (unless in a `cpp` file) -- :x: **Never** use `using namespace foo;` - 😱 It's too permissive and pollutes the current namespace! +- :x: **Never** use `using namespace foo;` + 😱 It's too permissive and pollutes the current namespace! --- diff --git a/lectures/static.md b/lectures/static.md index 2084ba0..07219ed 100644 --- a/lectures/static.md +++ b/lectures/static.md @@ -1,10 +1,30 @@ -Static keyword +Keyword `static` ---

Video

+ +- [Keyword `static`](#keyword-static) +- [Storage duration](#storage-duration) + - [Automatic storage duration](#automatic-storage-duration) + - [Static storage duration at namespace scope](#static-storage-duration-at-namespace-scope) + - [Static storage duration at function scope](#static-storage-duration-at-function-scope) + - [Summary of controlling storage duration with static](#summary-of-controlling-storage-duration-with-static) +- [Linkage](#linkage) + - [What is linkage](#what-is-linkage) + - [Levels of linkage](#levels-of-linkage) + - [Why we need external linkage](#why-we-need-external-linkage) + - [What went wrong?](#what-went-wrong) + - [How to fix this?](#how-to-fix-this) + - [Why `inline` is better than `static` for linkage](#why-inline-is-better-than-static-for-linkage) + - [The data](#the-data) +- [Conclusion and a rule of thumb](#conclusion-and-a-rule-of-thumb) + - [For functions and variables at namespace scope](#for-functions-and-variables-at-namespace-scope) + - [For variables at local scopes](#for-variables-at-local-scopes) + - [Final words](#final-words) + The keyword [`static`](https://en.cppreference.com/w/cpp/keyword/static) is a very important keyword in C++ and is used a lot. Honestly, probably, because of a very general name, it is a bit overused. Largely speaking, it can be used inside and outside classes and these two cases are very different. Today we focus on the latter - using `static` outside of classes. If you are interested in how and when to use `static` _inside_ of classes, I will link this lecture here when it's out. Anyway, as for using `static` _outside_ of classes, I have good news for you. If you follow my advices from before then the rule-of-thumb for using `static` outside of classes in modern C++ (that is at least C++17) is very simple - don't! **Don't use `static` at all!** @@ -25,7 +45,16 @@ Now, what do these words mean? ## Storage duration ### Automatic storage duration -Every object declared in C++ has a certain lifetime, or, in other words, a _storage duration_. Lots of objects live within a single scope and their memory gets freed upon the end of their scope. These objects are usually said to have **automatic storage duration**. But what if there is no scope? What happens with those variables declared outside of class or function scope? +Every object declared in C++ has a certain lifetime, or, in other words, a _storage duration_. Lots of objects live within a single scope and their memory gets freed upon the end of their scope. These objects are usually said to have **automatic storage duration**. Looking at a simple example: +```cpp +void Foo() { + int bar = 42; // bar has automatic storage duration +} +``` +the variable `bar` will exist until the end of the scope and will be freed afterwards. + + +But what if there is no scope? What happens with those variables declared outside of class or function scope? ### Static storage duration at namespace scope These variables are said to be declared at **namespace scope**. Their data gets allocated at the start of the program and gets freed when the program terminates, which is to say that these data have the **static storage duration**. I believe that this is what inspired the name `static` back when it was introduced in C. Anyway, we _can_ use `static` for an object declaration at namespace scope to indicate that it has the static storage duration but we don't have to, as any such object has this storage duration by default. So the following definitions are equivalent in terms of storage duration: @@ -69,52 +98,218 @@ int main() { } ``` -Now this is where I lied to you a bit about _never_ needing to use `static`. There _are_ situations when you might want to create a static object within a function. However the ones that come to mind are hard to come by if we follow a good style. For completeness, I can think of using such method to deal with the "static initialization order fiasco" and for implementing a singleton design pattern. We will talk about the singleton pattern later (and why you probably don't want to use it) but I will skip "static initialization order fiasco" here. It should not hit you as long as you only create that rely only on values within the same cpp file and not across cpp files. +Now this is where I lied to you a bit about _never_ needing to use `static`. There _are_ situations when you might want to create a static object within a function. Notice how we return a non-const reference, so what we essentially model here is a global variable that will live for the rest of the program lifetime. This is also very similar to the Singleton design pattern and we will talk why you probably don't want to use it later in the course. Anyway, if you remember what we talked about before, you will know that using global variables tends to wreak havoc and we probably don't want to do this. + +For completeness, another use for such a method with a `static` variable inside of it is to deal with the "static initialization order fiasco". It should not hit you as long as you only create variables that rely only on values within the same cpp file and not across translation unit boundaries. ```cpp const int kAnswer = 42; // ✅ this is ok. const int kValue = kValueFromOtherCppFile; // ❌ not ok! ``` -But tell me in the comments if you are interested to learn more about it! +I won't go into details here, but tell me in the comments if you are interested to learn more about it! -### Summary -Let's sum up where `static` can be used and what it gives us. Generally speaking, when used outside of classes, `static` can be used in two places: +### Summary of controlling storage duration with static +Let's sum up where `static` can be used and what it gives us in terms of changing the storage duration of variables. Generally speaking, when used outside of classes, `static` can be used in two places: - outside of functions which adds nothing as any such variables or functions declared at namespace scope already have static storage duration. - inside of functions to extend the local variable's automatic storage duration to static storage duration, which we mostly don't want to do. +:bulb: So, all in all, there is really **no good reason** to use static to change storage duration of our variables! + ## Linkage Now it's time to talk about the second thing that `static` controls - linkage. We touched upon linkage before, when we talked about [libraries](headers_and_libraries.md), and especially the `inline` keyword. -First, let me explain what linkage is real quick. Any name that denotes some entity, be it an object, function, namespace, type, etc., _can_ have linkage but doesn't have to have it. There might be other entities that have the same name introduced by a declaration in some other scope. Linkage controls if these names should refer to the same entity. If the linkage is insufficient, multiple entities are generated. +If you don't want to go into detail here, just remember this rule: +> 🚨 Don't use `static` on functions and data in the namespace scope to avoid linkage problems, use `inline` instead! + +If you _do_ want to understand why, then let me tell you a story of linkage. :wink: + +### What is linkage +First, let me explain what linkage is. Any name that denotes some entity, be it an object, function, namespace, type, etc., _can_ have linkage but doesn't have to have it. So if we have a program that consists of multiple translation units, there might be different entities that have the same name introduced by a declaration in one or another scope. Linkage controls if these names refer to the same entity. + +### Levels of linkage +To decide this, we use the "levels" of linkage. So, any name of some entity can have one of the following three options: +- **No linkage** - a name can only be referred to from the same scope. Any mentions of the same name from other scopes will refer to other entities. You might have guessed that any local variable that lives within some local scope (say, of a function or a class) usually has this linkage. +- **Internal linkage** - a name can be referred to from any scope within the same translation unit (think, same cpp file). Other translation units can have their own separate entities with the same name without issues. Largely speaking, any constant defined at namespace scope, as well as functions and even non-const data that are declared either as `static` will also have internal linkage, more on that in a minute. Oh, and everything declared in an [unnamed namespace](namespaces_using.md#use-unnamed-namespaces) (remember we talked about those?) will too have internal linkage! +- **External linkage** - a name can be referred to from other translation units, i.e., it is globally visible. The typical examples are everything that does not fit to the previous categories, i.e., non-`static` functions and non-`const`, non-`static` variables at namespace scopes, enums, and a bunch of stuff related to classes that we will discuss in the next video. Oh, and also, `inline` data and functions. + +Intuitively speaking, if we want some name to be available only in the current scope, it should have **no linkage**. If it should be available **only** from within the same translation unit - it should have **internal linkage**. Finally, **external linkage** is needed for symbols that need to be available globally throughout the program. + +In the cases of **no linkage** and **internal linkage** it is relatively hard to do anything wrong on our side. But using **external linkage** requires some care. So let's reiterate why we want to have things with external linkage in the first place, what can go wrong and what is the best way to protect ourselves against the typical pitfalls. + + + +### Why we need external linkage +Let's start with a pretty naive [example](code/static_no_classes/odr_violation/). + +Say we have a large project and in it we write a library that has a declaration of a function `SayHello` in a header file `our_cool_lib.hpp` which prints "Hello!" to the terminal when we call it: + +`our_cool_lib.hpp` +```cpp +void SayHello(); // 😱 This really should be inline +``` + +We further write a definition of our function in a corresponding source file `our_cool_lib.cpp`: +```cpp +#include "our_cool_lib.hpp" + +#include + +void SayHello() { std::cout << "Hello!" << std::endl; } +``` + +And we also add another file `main.cpp` that calls this function in the `main` function: +```cpp +#include "our_cool_lib.hpp" + +int main() { + SayHello(); + return 0; +} +``` + +Now, we just need instruct the compiler and linker on how to build this code and we do that using CMake. Remember, we implement this as part of some large project so we also link to some `other_lib` that might link to other libraries too. +```cmake +# Omitting CMake boilerplate and creation of other_lib + +add_library(our_cool_lib our_cool_lib.cpp) +target_link_libraries(our_cool_lib PUBLIC cxx_setup) + +add_executable(main main.cpp) +target_link_libraries(main PRIVATE other_lib our_cool_lib) +``` + +So far so goo. Now, we build it and run it (the `λ ›` part is just an artifact of how my terminal is setup): +```cmd +λ › cmake -S . -B build +λ › cmake --build build -j 12 +λ › ./build/main +What??? 🤯 +``` + +#### What went wrong? +Wait... What? Why did it not print "Hello!" as we expected? + +Well, there are two things that we have to know to explain this. + +The first one is the code in that `other_lib` that we linked against. Somehow, somebody had a header `other_lib.h` that had exactly the same declaration of the `SayHello` function as we did! +```cpp +void SayHello(); // 😱 This really should be inline +``` + +However, in the corresponding source file `other_lib.cpp` they had a different printout! +```cpp +#include "other_lib.hpp" + +#include + +void SayHello() { std::cout << "What??? 🤯" << std::endl; } +``` + +Ok, so we start getting the feeling that something _might_ go wrong here, but why does it? + +The reason for this is that the linkage of the `SayHello` function is **external**, and we get into trouble because of the [One Definition Rule (ODR)](https://en.cppreference.com/w/cpp/language/definition) violations. That rule states roughly this: that any symbol must have exactly one definition in the entire program, i.e., across all of its translation units. Only `inline` symbols can have more than one definition which are then all assumed to be exactly the same. + +So, here is a slightly simplified explanation of what happens when we compile our code. First, the compiler sees the declaration of the function in our `our_cool_lib.hpp` file, understands that the linkage of the `SayHello` symbol is external and calmly continues, knowing that the linker will take care of finding where the implementation of `SayHello` lives. Which the linker does. The issue arises because the linked sees the `SayHello` symbol from the `other_lib` first. As that symbol also has external linkage and expecting that we know about ODR, it happily links these symbols together and stops. So we end up calling a wrong function! + +:bulb: Note that _which_ function is called in such a situation is pure luck as the way the linker will search for the proper symbol is implementation defined. Which is to say, that we are firmly in the "Undefined behavior land" 🌈🦄 + +Oh, and ODR is simply assumed to be followed, nobody checks that we actually do, which is why it is so important to have the right muscle memory when writing C++ code to never end up in such a situation! + +#### How to fix this? +Now that we understand _what_ went wrong, how can we fix this? + +And this is where `static` historically, that is before C++11, has been used. Remember how I mentioned that `static` functions have **internal** linkage? We can make use of this. + +First, let's consider what would happen if we added `static` before the declaration and the definition of _our_ `SayHello` function? + +`our_cool_lib.hpp` +```cpp +static void SayHello(); // 😱 This really should be inline +``` + +`our_cool_lib.cpp`: +```cpp +#include "our_cool_lib.hpp" + +#include + +static void SayHello() { std::cout << "Hello!" << std::endl; } +``` + +If we try to compile this, we get a couple of warnings and an error (note that I'm using clang so if you are using gcc your error might be different): +```cmd +λ › cmake --build build -j 12 static_no_classes/odr_violation static +Consolidate compiler generated dependencies of target our_cool_lib +[ 33%] Built target other_lib +[ 50%] Building CXX object CMakeFiles/our_cool_lib.dir/our_cool_lib.cpp.o +/Users/igor/Documents/C++ Course/Slides/lectures/code/static_no_classes/odr_violation/our_cool_lib.cpp:5:13: warning: unused function 'SayHello' [-Wunused-function] +static void SayHello() { std::cout << "Hello!" << std::endl; } + ^ +1 warning generated. +[ 66%] Linking CXX static library libour_cool_lib.a +warning: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib: archive library: libour_cool_lib.a the table of contents is empty (no object file members in the library define global symbols) +[ 66%] Built target our_cool_lib +Consolidate compiler generated dependencies of target main +[ 83%] Building CXX object CMakeFiles/main.dir/main.cpp.o +In file included from /Users/igor/Documents/C++ Course/Slides/lectures/code/static_no_classes/odr_violation/main.cpp:1: +/Users/igor/Documents/C++ Course/Slides/lectures/code/static_no_classes/odr_violation/our_cool_lib.hpp:5:13: warning: function 'SayHello' has internal linkage but is not defined [-Wundefined-internal] +static void SayHello(); // 😱 This really should be inline + ^ +/Users/igor/Documents/C++ Course/Slides/lectures/code/static_no_classes/odr_violation/main.cpp:4:3: note: used here + SayHello(); + ^ +1 warning generated. +[100%] Linking CXX executable main +ld: Undefined symbols: + SayHello(), referenced from: + _main in main.cpp.o +clang: error: linker command failed with exit code 1 (use -v to see invocation) +make[2]: *** [main] Error 1 +make[1]: *** [CMakeFiles/main.dir/all] Error 2 +make: *** [all] Error 2 +``` + +Overall, the important thing to note here is that our `main` executable sees that there is a function `SayHello` declared as `static`. Which is to say that its linkage is **internal**. So the linker tries to find the definition of this function **within the same translation unit**, aka `main.cpp`. But our definition lives in a **different** translation unit `our_cool_lib.cpp`. So in that translation unit our function is unused, while there is no implementation for the `static SayHello()` function within the `main.cpp`. Therefore the linker fails. + +So the typical thing that people used to do before C++11 is to move the implementation of the function into the header file `our_cool_lib.hpp`: +```cpp +#include +// 😱 Should really be inline instead +static void SayHello() { std::cout << "Hello!" << std::endl; } +``` + +In addition to that, we don't need the `our_cool_lib` target in CMake anymore and just include this file into `main.cpp` directly. -What does it mean to have an "insufficient" linkage? Well, there is a couple of "levels" of linkage. Any entity can have: -- **No linkage** - a name can only be referred to from the same scope. Any mentions of the same name from other scopes will refer to other entities. -- **Internal linkage** - a name can be referred to from any scope within the same translation unit (think, same cpp file). Mentioning the same name from the same translation unit means that we want to reference the same entity. Other translation units can have their own entities with the same name without issues. -- **External linkage** - a name can be referred to from other translation units, i.e., it is globally visible. +If we now build our code it will build without issues and when we run it, we get the correct output. -When we declare data or functions at namespace scope we care about the linkage of these data or functions. If the linkage is external, we might get into trouble because of the [One Definition Rule (ODR)](https://en.cppreference.com/w/cpp/language/definition) violations. That rule states roughly this: that any symbol must have exactly one definition in the entire program, i.e., across all of its translation units. Only `inline` symbols can have more than one definition which are then all assumed to be exactly the same by the compiler. So, you see, if the linkage of a symbol is not _external_ there is no way to violate ODR with it. +Seems like we've solved everything, right? Well, technically yes, but there is a minor issue with using `static` like this which might or might not be important to us depending on the application. -Now, let's get back to talking about `static` and what it has to do with linkage. +#### Why `inline` is better than `static` for linkage +The issue with `static` is that it enforces internal linkage. That is to say, that in our example, if we include our `our_cool_lib.hpp` file into multiple translation units, we will have a **copy** of the compiled binary code of the `SayHello` function in every single translation unit. This takes space which might become problematic on constrained hardware. -By default, if we declare a function or a non-const variable _at namespace scope_, they get **external linkage**. Meaning that if we do this in a header file and include this file into two different cpp files that get linked together, we will technically violate ODR. +This is where `inline` comes to the rescue! It implies **external** linkage but, as stated in the ODR formulation, multiple definitions _are_ allowed for `inline` functions (🔼 C++11) and data (🔼 C++17). So in our case, if we replace `static` with `inline` for our `SayHello` function, we will only ever have one instance of the compiled binary code for this function that the linker will happily link everywhere. -However, when using `static`, any variable or function declared _at namespace scope_ will get **internal linkage**, meaning that they will only be available from within the translation unit in which they are declared. So now if we declare them in a header file and include this header file into two different cpp files, we will get different symbols for our variables or functions. So despite having the same name they won't cause an ODR violation all the definitions are only visible within their own translation unit. +This is the best way to declare functions and data that should be visible globally in modern C++. So, you see, there is no reason to mark functions as `static` anymore due to linkage reasons. -Sounds good, right? So why did I suggest not to use `static` then? Well, because there is no need to! +> :bulb: Note that in the example above, we still have the `other_lib` which is implemented in a bad way and we still technically violate ODR. Which is why it is so important to maintain high coding standards. If the function `SayHello` in the `other_lib.hpp` would be declared as `inline` and we would try to include both headers into our `main.cpp` we would get a "redefinition" error for this function. ### The data -Well, it turns out that if we declare const (or constexpr) objects at namespace scope they _also_ get **internal linkage** by default. The only ones getting external linkage are the non-const data declared at namespace scope. And we talked about it before, right? We should only have const global data. So if we follow the guidelines from before, we can safely skip the `static` keyword and nothing will change. +But what about the data, I hear you ask! Here, the situation is a bit simpler. We cannot declare data without definition, unless we use the keyword `extern`, which we did not discuss and should avoid in most cases. The fact that we cannot _declare_ data removes most of the issues that we discussed above. -That being said, with C++17 there is an even better option. If we declare our variables `const` or `constexpr`, they are guaranteed to not cause us trouble with ODR but there will be a copy of them in each translation unit they are included into. Sometimes we want to avoid this and we want to have a single symbol instead. That is where `inline` comes to our aid. If we add it to our constant definition, it's linkage will become **external** making it visible to any translation unit, but the `inline` keyword will protect us against ODR violations as it tells the compiler that it's ok to have multiple definitions of this symbol and to assume that they are all the same. This allows us to reuse the value across multiple translation units. +Furthermore, if we define `const` (or `constexpr`) data at namespace scope they get **internal linkage** by default. So, you see, there is no need for `static` at all. -### The functions -The situation is very similar for functions. By default, functions declared at namespace scope have **external linkage** which causes all the same issues with ODR violations that we've just discussed. Same as with variables, declaring a function `static` changes it's linkage to **internal**, which allows us to avoid the ODR violations but causes multiple instances of the function definition to be present in various translation units. And, just as before, using `inline` is a better solution as it keeps the function's **external linkage** while allowing for multiple definitions of this function as long as we guarantee that they are all the same. +Still, the best way with C++17 and onward is, similarly to functions, to define our data as `const` or `constexpr` `inline` with exactly the same reasoning. ## Conclusion and a rule of thumb So, I hope that by now you see that there is no need to use `static` outside of classes at all in modern C++. Here is a guideline to follow along with this: ### For functions and variables at namespace scope -- When declaring variables at namespace scope always declare them as `inline` `constexpr` or `const`. Do **not** declare them as `static`! +- When defining variables at namespace scope always declare them as `inline` `constexpr` or `const`. Do **not** define them as `static`! - When declaring functions at namespace scope, declare (and define) them as `inline`. Do **not** declare them as `static`! This will guarantee their external linkage, i.e., visibility across the whole program, while not violating the ODR. @@ -123,4 +318,4 @@ This will guarantee their external linkage, i.e., visibility across the whole pr - When declaring a variable at local scope, do not declare it as `static` unless you are explicitly implementing a singleton-like design pattern (which you probably shouldn't do anyway) ### Final words -Understanding the key role that ODR plays here is key to understanding why `static` was introduced into the language in the first place. It was in the times when `inline` meant something different and could not be used as it can be now. So it was the only way to provide a definition of a function or a variable directly in the header. Thankfully, we live in better times now, which makes `static` close to obsolete when used outside of classes. Now if you want to know how to use `static` in classes you can see a video about that once it's ready and maybe also go back and refresh how `inline` plays a huge role in creating libraries in C++. +Understanding the key role that ODR plays here is crucial to understanding why `static` was introduced into the language in the first place. It was in the times when `inline` meant something different and could not be used as it can be now. So it was the only way to provide a definition of a function or a variable directly in the header. Thankfully, we live in better times now, which makes `static` close to obsolete when used outside of classes. Now if you want to know how to use `static` in classes you can see a video about that once it's ready and maybe also go back and refresh how `inline` plays a huge role in creating libraries in C++.