diff --git a/package-lock.json b/package-lock.json index 0f970b7..38d8530 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "@uiw/react-codemirror": "^4.19.9", "aos": "^2.3.4", "axios": "^1.4.0", + "codemirror": "^5.65.18", "framer-motion": "^10.3.1", "gsap": "^3.11.5", "prop-types": "^15.8.1", @@ -4234,25 +4235,6 @@ "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@testing-library/dom": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.2.0.tgz", - "integrity": "sha512-xTEnpUKiV/bMyEsE5bT4oYA0x0Z/colMtxzUY8bKyPXBNLn/e0V4ZjBZkEhms0xE4pv9QsPfSRu9AWS4y5wGvA==", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "^5.0.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/@testing-library/jest-dom": { "version": "5.16.5", "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", @@ -6987,10 +6969,9 @@ } }, "node_modules/codemirror": { - "version": "5.65.12", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.12.tgz", - "integrity": "sha512-z2jlHBocElRnPYysN2HAuhXbO3DNB0bcSKmNz3hcWR2Js2Dkhc1bEOxG93Z3DeUrnm+qx56XOY5wQmbP5KY0sw==", - "peer": true + "version": "5.65.18", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.18.tgz", + "integrity": "sha512-Gaz4gHnkbHMGgahNt3CA5HBk5lLQBqmD/pBgeB4kQU6OedZmqMBjlRF0LSrp2tJ4wlLNPm2FfaUd1pDy0mdlpA==" }, "node_modules/collect-v8-coverage": { "version": "1.0.1", @@ -17198,35 +17179,6 @@ "wl-msg-reader": "^0.2.0" } }, - "node_modules/react-doc-viewer/node_modules/react": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", - "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-doc-viewer/node_modules/react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - }, - "peerDependencies": { - "react": "^16.14.0" - } - }, "node_modules/react-doc-viewer/node_modules/react-pdf": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-5.0.0.tgz", @@ -17248,16 +17200,6 @@ "react-dom": "^16.3.0" } }, - "node_modules/react-doc-viewer/node_modules/scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -20771,19 +20713,6 @@ "is-typedarray": "^1.0.0" } }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, "node_modules/ua-parser-js": { "version": "1.0.35", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.35.tgz", @@ -23871,14 +23800,12 @@ "@csstools/postcss-unset-value": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", - "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", - "requires": {} + "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==" }, "@csstools/selector-specificity": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", - "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", - "requires": {} + "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==" }, "@cyntler/react-doc-viewer": { "version": "1.13.0", @@ -24042,8 +23969,7 @@ "@emotion/use-insertion-effect-with-fallbacks": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz", - "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==", - "requires": {} + "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==" }, "@emotion/utils": { "version": "1.2.0", @@ -25003,8 +24929,7 @@ "@mui/types": { "version": "7.2.4", "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.4.tgz", - "integrity": "sha512-LBcwa8rN84bKF+f5sDyku42w1NTxaPgPyYKODsh01U1fVstTClbUoSA96oyRBnSNyEiAVjKm6Gwx9vjR+xyqHA==", - "requires": {} + "integrity": "sha512-LBcwa8rN84bKF+f5sDyku42w1NTxaPgPyYKODsh01U1fVstTClbUoSA96oyRBnSNyEiAVjKm6Gwx9vjR+xyqHA==" }, "@mui/utils": { "version": "5.12.0", @@ -25292,22 +25217,6 @@ "loader-utils": "^2.0.0" } }, - "@testing-library/dom": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.2.0.tgz", - "integrity": "sha512-xTEnpUKiV/bMyEsE5bT4oYA0x0Z/colMtxzUY8bKyPXBNLn/e0V4ZjBZkEhms0xE4pv9QsPfSRu9AWS4y5wGvA==", - "peer": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "^5.0.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - } - }, "@testing-library/jest-dom": { "version": "5.16.5", "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", @@ -26229,14 +26138,12 @@ "acorn-import-assertions": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "requires": {} + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==" }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "requires": {} + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==" }, "acorn-walk": { "version": "7.2.0", @@ -26279,8 +26186,7 @@ "ajv-errors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "requires": {} + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" }, "ajv-formats": { "version": "2.1.1", @@ -26311,8 +26217,7 @@ "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "requires": {} + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" }, "ansi-escapes": { "version": "4.3.2", @@ -26723,8 +26628,7 @@ "babel-plugin-named-asset-import": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz", - "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==", - "requires": {} + "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==" }, "babel-plugin-polyfill-corejs2": { "version": "0.3.3", @@ -27495,10 +27399,9 @@ } }, "codemirror": { - "version": "5.65.12", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.12.tgz", - "integrity": "sha512-z2jlHBocElRnPYysN2HAuhXbO3DNB0bcSKmNz3hcWR2Js2Dkhc1bEOxG93Z3DeUrnm+qx56XOY5wQmbP5KY0sw==", - "peer": true + "version": "5.65.18", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.18.tgz", + "integrity": "sha512-Gaz4gHnkbHMGgahNt3CA5HBk5lLQBqmD/pBgeB4kQU6OedZmqMBjlRF0LSrp2tJ4wlLNPm2FfaUd1pDy0mdlpA==" }, "collect-v8-coverage": { "version": "1.0.1", @@ -27868,8 +27771,7 @@ "css-declaration-sorter": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.0.tgz", - "integrity": "sha512-jDfsatwWMWN0MODAFuHszfjphEXfNw9JUAhmY4pLu3TyTU+ohUpsbVtbU+1MZn4a47D9kqh03i4eyOm+74+zew==", - "requires": {} + "integrity": "sha512-jDfsatwWMWN0MODAFuHszfjphEXfNw9JUAhmY4pLu3TyTU+ohUpsbVtbU+1MZn4a47D9kqh03i4eyOm+74+zew==" }, "css-has-pseudo": { "version": "3.0.4", @@ -27952,8 +27854,7 @@ "css-prefers-color-scheme": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", - "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", - "requires": {} + "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==" }, "css-select": { "version": "4.3.0", @@ -28067,8 +27968,7 @@ "cssnano-utils": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "requires": {} + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==" }, "csso": { "version": "4.2.0", @@ -29057,8 +28957,7 @@ "eslint-plugin-react-hooks": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "requires": {} + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==" }, "eslint-plugin-testing-library": { "version": "5.10.3", @@ -30464,8 +30363,7 @@ "icss-utils": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "requires": {} + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==" }, "idb": { "version": "7.1.1", @@ -31740,8 +31638,7 @@ "jest-pnp-resolver": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "requires": {} + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==" }, "jest-regex-util": { "version": "27.5.1", @@ -34132,8 +34029,7 @@ "postcss-browser-comments": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz", - "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==", - "requires": {} + "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==" }, "postcss-calc": { "version": "8.2.4", @@ -34231,26 +34127,22 @@ "postcss-discard-comments": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", - "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", - "requires": {} + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==" }, "postcss-discard-duplicates": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", - "requires": {} + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==" }, "postcss-discard-empty": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", - "requires": {} + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==" }, "postcss-discard-overridden": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", - "requires": {} + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==" }, "postcss-double-position-gradients": { "version": "3.1.2", @@ -34272,8 +34164,7 @@ "postcss-flexbugs-fixes": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", - "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", - "requires": {} + "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==" }, "postcss-focus-visible": { "version": "6.0.4", @@ -34294,14 +34185,12 @@ "postcss-font-variant": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", - "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", - "requires": {} + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==" }, "postcss-gap-properties": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", - "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", - "requires": {} + "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==" }, "postcss-image-set-function": { "version": "4.0.7", @@ -34324,8 +34213,7 @@ "postcss-initial": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", - "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", - "requires": {} + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==" }, "postcss-js": { "version": "4.0.1", @@ -34366,14 +34254,12 @@ "postcss-logical": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", - "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", - "requires": {} + "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==" }, "postcss-media-minmax": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", - "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", - "requires": {} + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==" }, "postcss-merge-longhand": { "version": "5.1.7", @@ -34434,8 +34320,7 @@ "postcss-modules-extract-imports": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "requires": {} + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==" }, "postcss-modules-local-by-default": { "version": "4.0.0", @@ -34493,8 +34378,7 @@ "postcss-normalize-charset": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", - "requires": {} + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==" }, "postcss-normalize-display-values": { "version": "5.1.0", @@ -34565,8 +34449,7 @@ "postcss-opacity-percentage": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz", - "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==", - "requires": {} + "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==" }, "postcss-ordered-values": { "version": "5.1.3", @@ -34588,8 +34471,7 @@ "postcss-page-break": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", - "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", - "requires": {} + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==" }, "postcss-place": { "version": "7.0.5", @@ -34683,8 +34565,7 @@ "postcss-replace-overflow-wrap": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", - "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", - "requires": {} + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==" }, "postcss-selector-not": { "version": "6.0.1", @@ -35072,8 +34953,7 @@ "react-codemirror2": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/react-codemirror2/-/react-codemirror2-7.2.1.tgz", - "integrity": "sha512-t7YFmz1AXdlImgHXA9Ja0T6AWuopilub24jRaQdPVbzUJVNKIYuy3uCFZYa7CE5S3UW6SrSa5nAqVQvtzRF9gw==", - "requires": {} + "integrity": "sha512-t7YFmz1AXdlImgHXA9Ja0T6AWuopilub24jRaQdPVbzUJVNKIYuy3uCFZYa7CE5S3UW6SrSa5nAqVQvtzRF9gw==" }, "react-dev-utils": { "version": "12.0.1", @@ -35124,29 +35004,6 @@ "wl-msg-reader": "^0.2.0" }, "dependencies": { - "react": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", - "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2" - } - }, - "react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - } - }, "react-pdf": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-5.0.0.tgz", @@ -35160,16 +35017,6 @@ "prop-types": "^15.6.2", "worker-loader": "^3.0.0" } - }, - "scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } } } }, @@ -35212,8 +35059,7 @@ "pdfjs-dist": { "version": "2.12.313", "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.12.313.tgz", - "integrity": "sha512-1x6iXO4Qnv6Eb+YFdN5JdUzt4pAkxSp3aLAYPX93eQCyg/m7QFzXVWJHJVtoW48CI8HCXju4dSkhQZwoheL5mA==", - "requires": {} + "integrity": "sha512-1x6iXO4Qnv6Eb+YFdN5JdUzt4pAkxSp3aLAYPX93eQCyg/m7QFzXVWJHJVtoW48CI8HCXju4dSkhQZwoheL5mA==" } } }, @@ -37246,8 +37092,7 @@ "style-loader": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.2.tgz", - "integrity": "sha512-RHs/vcrKdQK8wZliteNK4NKzxvLBzpuHMqYmUVWeKa6MkaIQ97ZTOS0b+zapZhy6GcrgWnvWYCMHRirC3FsUmw==", - "requires": {} + "integrity": "sha512-RHs/vcrKdQK8wZliteNK4NKzxvLBzpuHMqYmUVWeKa6MkaIQ97ZTOS0b+zapZhy6GcrgWnvWYCMHRirC3FsUmw==" }, "style-mod": { "version": "4.0.3", @@ -37903,12 +37748,6 @@ "is-typedarray": "^1.0.0" } }, - "typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "peer": true - }, "ua-parser-js": { "version": "1.0.35", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.35.tgz", @@ -38107,8 +37946,7 @@ "use-isomorphic-layout-effect": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", - "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", - "requires": {} + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==" }, "util": { "version": "0.11.1", @@ -38647,8 +38485,7 @@ "ws": { "version": "8.13.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "requires": {} + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==" } } }, @@ -39105,8 +38942,7 @@ "ws": { "version": "7.5.9", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "requires": {} + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==" }, "xml-name-validator": { "version": "3.0.0", diff --git a/package.json b/package.json index b222668..ab4521c 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@uiw/react-codemirror": "^4.19.9", "aos": "^2.3.4", "axios": "^1.4.0", + "codemirror": "^5.65.18", "framer-motion": "^10.3.1", "gsap": "^3.11.5", "prop-types": "^15.8.1", diff --git a/src/App.js b/src/App.js index 88a99bc..f95e844 100644 --- a/src/App.js +++ b/src/App.js @@ -47,6 +47,7 @@ function App() { + }/> }/> }/> }/> diff --git a/src/Emulator.zip b/src/Emulator.zip new file mode 100644 index 0000000..82d84a1 Binary files /dev/null and b/src/Emulator.zip differ diff --git a/src/Emulator/ALU.js b/src/Emulator/ALU.js index 1792340..be643c8 100644 --- a/src/Emulator/ALU.js +++ b/src/Emulator/ALU.js @@ -124,7 +124,6 @@ class Alu{ subBinary(size){ //get the two's complement of the content of the RUAL2: - console.log("RUAL2 Value befor anything "+this.Rual2.value); //than the one's complement of the result : let i=this.Rual2.value.length-1; @@ -136,19 +135,14 @@ class Alu{ i--; } this.Rual2.setvalue(b); - console.log("Ones complement of RUAL2 "+this.Rual2.value); - - //first we add (RAL2)+1 + //first we add (RAL2)+1 let x=1; let res1=parseInt(this.Rual2.getvalue(),2); res1=res1+x; this.Rual2.setvalue(fullzero(size,res1.toString(2))); b=this.Rual2.getvalue()//very important on overflow detection - console.log("Tows complement of RUAL2 "+this.Rual2.value); //then the simple binary addition between RUAL1 and RUAL2: - this.addBinary(size) - console.log("The result of subsrtaction "+ this.Acc.getvalue()); - + this.addBinary(size) //overflow detection: if (this.Rual1.getvalue()[0]!=b[0]) { if (b[0]==this.Acc.getvalue()[0]) { @@ -165,9 +159,7 @@ class Alu{ binaryMultiply(size) { - let binaryString1=(this.Rual1.getvalue()).substring(0,size); - console.log("string1 :"+binaryString1); - + let binaryString1=(this.Rual1.getvalue()).substring(0,size); //two's complement of the abs part of a if(this.Rual1.getvalue()[0]=='1'){ let i=size; @@ -186,9 +178,7 @@ class Alu{ } } let binaryString2=this.Rual2.getvalue().substring(0,size);//verifier - console.log("string2 :"+binaryString2); - - //two's complement of the abs part of b + //two's complement of the abs part of b if(this.Rual2.getvalue()[0]=='1'){ let i=size; let find1=false @@ -207,18 +197,13 @@ class Alu{ } let int1 = parseInt(binaryString1, 2) - console.log(int1) let int2 = parseInt(binaryString2, 2) - console.log(int2) let res= (int1 * int2).toString(2); - console.log(res); if(res.length>=16 ){res=fullzero(32,res)} else{ res=fullzero(16,res)} if (this.Rual1.getvalue()[0]==this.Rual2.getvalue()[0]) { - console.log("positive result") }else{ - console.log("negative result"); let find1=false for (let i = res.length; i >=0; i--) { if(find1==true){ @@ -234,7 +219,6 @@ class Alu{ } } - console.log(res); if(res.length>16){ let resacc=res.substring(16,32); this.Acc.setvalue(resacc); @@ -261,9 +245,7 @@ class Alu{ DivBinary(size){ - let binaryString1=(this.Rual1.getvalue()).substring(1,size); - console.log("string1 :"+binaryString1); - + let binaryString1=(this.Rual1.getvalue()).substring(1,size); //two's complement of the abs part of a if(this.Rual1.getvalue()[0]=='1'){ let i=size; @@ -282,8 +264,6 @@ class Alu{ } } let binaryString2=this.Rual2.getvalue().substring(1,size); - console.log("string2 :"+binaryString2); - //two's complement of the abs part of b if(this.Rual2.getvalue()[0]=='1'){ let i=size; @@ -303,21 +283,15 @@ class Alu{ } let int1 = parseInt(binaryString1, 2) - console.log(int1) let int2 = parseInt(binaryString2, 2) - console.log(int2) let q= (Math.floor(int1 / int2)).toString(2); - console.log("le quotient en valeur absolue :"+q); let r=(int1 % int2).toString(2) q=fullzero(size,q); - console.log("quotient before two's complement "+q); r=fullzero(size,r); //positive or negativ quotient if (this.Rual1.getvalue()[0]==this.Rual2.getvalue()[0]) { - console.log("positive quotient ") - + }else{ - console.log("negative quotient"); let find1=false for (let i =q.length; i >=0; i--) { if(find1==true){ @@ -337,9 +311,7 @@ class Alu{ //positive or negative reste if(this.Rual1.getvalue()[0]=='0') { - console.log("positive reste ") - }else{ - console.log("negative rete"); + }else{ let find1=false for (let i =r.length; i >=0; i--) { if(find1==true){ @@ -361,13 +333,8 @@ class Alu{ //this.Flags[2]=carry.toString();//carry let figure="1" this.Flags[3] = ((this.Acc.value.match(new RegExp(figure, "g")) || []).length %2).toString();//parity - this.Flags[4]=this.Acc.getvalue()[size-1];//p/imp - - console.log("le quotient :" +q); - - console.log("le reste en valeur absolue: "+r); - - this.Acc.setvalue(q); + this.Flags[4]=this.Acc.getvalue()[size-1];//p/imp + this.Acc.setvalue(q); return r; diff --git a/src/Emulator/IO_Unit.js b/src/Emulator/IO_Unit.js index c2d7062..5dc0c5d 100644 --- a/src/Emulator/IO_Unit.js +++ b/src/Emulator/IO_Unit.js @@ -1,15 +1,63 @@ +import { generalPurposeRegister } from "./Register.js"; + class IOUnit { - constructor(buffer) { - this.buffer = buffer; + constructor() { + // Buffer with 50 slots, initially empty + this.buffer = new Array(50).fill(null).map(() => ({ value: null, filled: false })); + + this.ioController = { + status: "idle", + transferInProgress: false, + }; } - getBuffer() { - return this.buffer; + + // Write data into the buffer + writeToBuffer(index, value) { + if (index < 0 || index >= this.buffer.length) { + console.error(`Invalid index: ${index}. Must be between 0 and ${this.buffer.length - 1}`); + return; + } + + this.buffer[index].value = value; + this.buffer[index].filled = true; + + console.log(`Value "${value}" written to buffer slot ${index}`); } - setBuffer(buffer) { - this.buffer = buffer; + + // Read data while ignoring truly empty slots + readFromBuffer() { + const bufferString = this.buffer + .filter(slot => slot.filled) // Keep only filled slots + .map(slot => slot.value) // Extract values + .join(""); + + console.log(`Buffer content (excluding empty columns): "${bufferString}"`); + return bufferString; } - write() { - console.log(this.buffer); + convertCharToASCII(index) { + if (index >= 0 && index < this.buffer.length) { + const asciiValue = this.buffer[index].toString().charCodeAt(0) || 0; + console.log(`Character at index ${index}: ${this.buffer[index]}, ASCII: ${asciiValue}`); + return asciiValue; + } else { + console.error("Index out of bounds"); + return null; } + } + writeASCIIToBuffer(asciiValue, index) { + if (index >= 0 && index < this.buffer.length) { + this.buffer[index] = String.fromCharCode(asciiValue); + console.log(`Stored character '${this.buffer[index]}' at index ${index} from ASCII ${asciiValue}`); + } else { + console.error("Index out of bounds"); + } + } + emptyBuffer() { + this.buffer.forEach(slot => { + slot.value = 0; // Reset value to 0 + slot.filled = false; // Mark as empty + }); + +} } export default IOUnit; \ No newline at end of file diff --git a/src/Emulator/Instruction.js b/src/Emulator/Instruction.js index 407819b..ca93993 100644 --- a/src/Emulator/Instruction.js +++ b/src/Emulator/Instruction.js @@ -1,11 +1,74 @@ -import { Registers, memory, Alu1, IP ,queue } from "../pages/Ide"; +import { Registers, memory, Alu1, IP ,queue } from "../pages/Ide/index.jsx"; import { TwosComplement } from "./ALU.js"; import { gsap } from "gsap"; +import IOUnit from "./IO_Unit.js"; +import { Register } from "./Register.js"; // import { Register } from "./Register.js"; //////////////////////////////////////////////// function Dec2bin(dec){ return ("00000000" + (parseInt(dec, 10)).toString(2)).substr(-8); } +function binaryToDecimalNumber(binaryStr) { + return parseInt(binaryStr, 2); +} +// Ensure receiveWriteValue is globally accessible +// Ensure receiveWriteValue is globally accessible +function showWritePopup() { + return new Promise((resolve) => { + let popup = window.open("", "Write to Register", "width=400,height=300"); + + popup.document.write(` +

Write to Register

+ + + + + + `); + + // Store resolve function globally so it can return the value to the main window + window.resolveWriteValue = (value) => { + console.log("🟢 Received input from user:", value); + resolve(parseInt(value, 10) || 0); // Convert input to number (default 0 if empty) + }; + }); +} + + + + +window.receiveWriteValue = function(value) { + console.log("✅ Main Window: Received value from pop-up:", value); + + const ioUnit = memory.ioUnit; + + if (!isNaN(value)) { + value = parseInt(value, 10); + ioUnit.writeToBuffer(0, value); + console.log(`✅ Stored ${value} in I/O buffer register 0.`); + + // Resume instruction execution + if (typeof window.writeCallback === "function") { + console.log("🟢 Resuming instruction after user input..."); + window.writeCallback(); + window.writeCallback = null; // Clear the callback after execution + } + } else { + console.log("❌ Invalid input. Please enter a number."); + } +}; + + /////////////////animations to test//////////////////// const IounitToBus={ @@ -18,6 +81,22 @@ const IounitToBus={ gsap.to(".ball",{opacity:"0" ,duration:1,delay:2}); }, } +const BusToIO = { + value: "", + target: ".ball", + time: 3000, + anim: (val, h, w) => { + gsap.fromTo(".ball", + { height: "2.812%", width: "1.4%", borderRadius: "50%", x: w * 0.221, y: h * 0.46, opacity: "0" }, + { opacity: "1", duration: 1 } + ); + gsap.fromTo(".ball", + { x: w * 0.221, y: h * 0.46 }, + { y: h * 0.39, duration: 1, delay: 1 } // Moves upward, opposite of IOTOBUS + ); + gsap.to(".ball", { opacity: "0", duration: 1, delay: 2 }); + }, +}; const BusToRual1={ value:"", @@ -4359,5 +4438,140 @@ class InstructionPOPA{ this.buildanim=function(){} } } +class InstructionREAD { + constructor() { + this.value1 = 0; + this.value2 = 0; + this.addresse1 = 0; + this.register1 = 0; + this.addresse2 = 0; + this.register2 = 0; + this.taille = 0; + this.stepsNum = 1; + this.name = "READ"; + + this.steps = [ + () => { + const ioUnit = memory.ioUnit; // Access I/O Unit + + if (!ioUnit.ioController.busy) { + ioUnit.ioController.busy = true; // Mark I/O as busy + + let value = this.value1; // Read from CPU register (e.g., R1) + ioUnit.writeToBuffer(0, value); + let popup = window.open("", "Buffer Contents", "width=400,height=300"); + popup.document.write(`

Buffer Contents

${ioUnit.readFromBuffer(0)}

`); + // alert("Buffer Contents: " + ioUnit.readFromBuffer(0));// Store in I/O buffer register 0 + + console.log(`CPU to IO: Moved data ${value} from CPU register R${this.register1} to I/O buffer.`); + ioUnit.displayValue(); + ioUnit.ioController.busy = false; + } else { + console.log("I/O Unit busy, READ delayed"); + return false; // Delay execution if busy + } + }, + ]; + this.buildanim = function () { + return [ + { + value: "READ", + target: addanim.target, + time: addanim.time, + anim: addanim.anim, + }, + { + value: this.value1, + target: RegistersToBus.target, + time: RegistersToBus.time, + anim: RegistersToBus.anim, + }, + { + value: this.value1, + target: BusToIO.target, + time: BusToIO.time, + anim: BusToIO.anim, + }, + + + ]; + }; + } +} + +class InstructionWRITE { + constructor() { + this.value1 = 0; + this.value2 = 0; + this.addresse1 = 0; + this.register1 = 0; + this.addresse2 = 0; + this.register2 = 0; + this.taille = 0; + this.stepsNum = 1; + this.name = "WRITE"; + + this.steps = [ + async () => { + const ioUnit = memory.ioUnit; + + if (!ioUnit.ioController.busy) { + ioUnit.ioController.busy = true; + + console.log("🟢 InstructionWRITE: Waiting for user input..."); + + // Wait for user input asynchronously before proceeding + const value = await showWritePopup(); + + ioUnit.writeToBuffer(0, value); + console.log(`✅ User input received: ${value}. Stored in I/O buffer register 0.`); + + // Resume execution + this.resume(); + } else { + console.log("🔴 InstructionWRITE: I/O Unit busy, WRITE delayed"); + return false; + } + } + ]; + + // Animation sequence + this.buildanim = function () { + const ioUnit = memory.ioUnit; + return [ + { + value: "WRITE", + target: addanim.target, + time: addanim.time, + anim: addanim.anim, + }, + { + value: ioUnit.readFromBuffer(0), + target: IounitToBus.target, + time: IounitToBus.time, + anim: IounitToBus.anim, + }, + { + value: ioUnit.readFromBuffer(0), + target: BusToRegisters.target, + time: BusToRegisters.time, + anim: BusToRegisters.anim, + }, + ]; + }; + } + + resume() { + const ioUnit = memory.ioUnit; + + let value = ioUnit.readFromBuffer(0); + let register = parseInt(this.register1, 2); + Registers[register].setvalue(TwosComplement(value, 16)); + + ioUnit.ioController.busy = false; + console.log(`✅ IO to CPU: Moved data ${value} from I/O buffer to CPU register R${register}.`); + } +} + -export {InstructionADD,InstructionMOV00,InstructionMOV01,InstructionMOV10,InstructionMOV11,InstructionSUB,InstructionMUL,InstructionDIV,InstructionBSE,InstructionBIE,InstructionBI,InstructionBS,InstructionBNE,InstructionBE,InstructionBR,InstructionPOP,InstructionPUSH,InstructionAND,InstructionOR,InstructionNAND,InstructionNOR,InstructionXOR,InstructionNEG,InstructionNOT,InstructionROL,InstructionROR,InstructionSHL,InstructionSHR,InstructionPOPA,InstructionPUSHA} +export {InstructionADD,InstructionMOV00,InstructionMOV01,InstructionMOV10,InstructionMOV11,InstructionSUB,InstructionMUL,InstructionDIV,InstructionBSE,InstructionBIE,InstructionBI,InstructionBS,InstructionBNE,InstructionBE,InstructionBR,InstructionPOP,InstructionPUSH,InstructionAND,InstructionOR,InstructionNAND,InstructionNOR,InstructionXOR,InstructionNEG,InstructionNOT,InstructionROL,InstructionROR,InstructionSHL,InstructionSHR,InstructionPOPA,InstructionPUSHA,InstructionREAD, InstructionWRITE} \ No newline at end of file diff --git a/src/Emulator/MC.js b/src/Emulator/MC.js index 46b1c8b..1fbf6a9 100644 --- a/src/Emulator/MC.js +++ b/src/Emulator/MC.js @@ -1,49 +1,69 @@ -import { Register } from "./Register.js" +/* eslint-disable eqeqeq */ +import { Register } from "./Register.js"; +import IOUnit from "./IO_Unit.js"; // 🔥 Import IOUnit + class MC { - constructor(){ - this.rim=new Register() - this.ram=new Register() - this.stack = new Array(100)//size à revoir - this.data = new Array (100) - this.code = new Array(100) + constructor() { + this.rim = new Register(); + this.ram = new Register(); + this.mar = new Register(); + this.stack = new Array(100); // size à revoir + this.data = new Array(100); + this.code = new Array(100); + this.ioUnit = new IOUnit(); // ✅ Add IOUnit instance } - setcode(code){ - this.code=code; + + setcode(code) { + this.code = code; } - setRim (val){//val in hexa - this.rim=val; + + setRim(val) { // val in hexa + this.rim = val; } - setRam (adr){//val in decimal - this.ram=adr; + + setRam(adr) { // val in decimal + this.ram = adr; } - getRam(){ - return this.ram; + + getRam() { + return this.ram; } - getRim (){ - return this.rim + + getRim() { + return this.rim; } - read(iscode){ - if(iscode==true){ - this.rim=this.code[parseInt(this.ram,2)] + + read(iscode) { + if (iscode == true) { + this.rim = this.code[parseInt(this.ram, 2)]; + } else { + this.rim = this.data[parseInt(this.ram, 2)]; + } } - else{ - this.rim=this.data[parseInt(this.ram,2)] + + write() { + this.data[parseInt(this.ram, 2)] = this.rim; } + + popval() { + this.rim = this.stack.pop(); } - write(){ - this.data[parseInt(this.ram,2)]=this.rim; + + pushval() { + this.stack.push(this.rim); } - popval(){ - this.rim=this.stack.pop(); - } - pushval(){ - this.stack.push(this.rim); - } - getData(){ + + getData() { return this.data; } - getstack(){ + + getstack() { return this.stack; } + + getIOUnit() { // ✅ Helper method to get IOUnit + return this.ioUnit; + } } -export default MC; \ No newline at end of file + +export default MC; diff --git a/src/Emulator/Opcodes.js b/src/Emulator/Opcodes.js index 0227590..0a08928 100644 --- a/src/Emulator/Opcodes.js +++ b/src/Emulator/Opcodes.js @@ -1,4 +1,4 @@ -import { InstructionADD,InstructionMOV00,InstructionMOV01,InstructionMOV10,InstructionMOV11,InstructionSUB,InstructionMUL,InstructionDIV, InstructionPUSH, InstructionBR, InstructionNOR, InstructionNEG, InstructionROR, InstructionROL, InstructionSHL, InstructionSHR, InstructionBE, InstructionBS, InstructionBSE, InstructionBI, InstructionBIE, InstructionBNE, InstructionNOT, InstructionOR, InstructionAND, InstructionNAND, InstructionXOR } from "./Instruction.js"; +import { InstructionADD,InstructionMOV00,InstructionMOV01,InstructionMOV10,InstructionMOV11,InstructionSUB,InstructionMUL,InstructionDIV, InstructionPUSH, InstructionBR, InstructionNOR, InstructionNEG, InstructionROR, InstructionROL, InstructionSHL, InstructionSHR, InstructionBE, InstructionBS, InstructionBSE, InstructionBI, InstructionBIE, InstructionBNE, InstructionNOT, InstructionOR, InstructionAND, InstructionNAND, InstructionXOR, InstructionREAD, InstructionWRITE } from "./Instruction.js"; function hash(key){ if(key=="0000000"){ @@ -55,7 +55,12 @@ function hash(key){ return 25; }else if(key=="0000110"){//XOR return 26; + } else if(key=="1000"){ // Opcode for READ + return 27; + } else if(key=="1001"){ // Opcode for WRITE + return 28; } + } let ADDinst=new InstructionADD(); let MOV00inst=new InstructionMOV00(); @@ -84,6 +89,8 @@ let ORinst = new InstructionOR(); let ANDinst = new InstructionAND(); let NANDinst = new InstructionNAND(); let XORinst = new InstructionXOR(); +let READinst = new InstructionREAD(); +let WRITEinst = new InstructionWRITE(); let hashmap=[{ key:"00", instrObject:ADDinst, @@ -192,5 +199,13 @@ let hashmap=[{ key:"0c", instrObject:XORinst, }, +{ + key:"8", + instrObject:READinst +}, +{ + key:"9", + instrObject:WRITEinst +} ]; -export {hash,hashmap}; \ No newline at end of file +export {hash,hashmap}; diff --git a/src/Emulator/Queue.js b/src/Emulator/Queue.js index 6b3db03..5ef8dbd 100644 --- a/src/Emulator/Queue.js +++ b/src/Emulator/Queue.js @@ -1,4 +1,4 @@ -import { memory,IP } from "../pages/Ide"; +import { memory,IP } from "../pages/Ide/index.jsx"; import { TwosComplement } from "./ALU.js"; import { gsap } from "gsap"; @@ -220,6 +220,7 @@ class Queue { let mdrval=instruction+instructionpart2; ////// this.instructionBytes.push(instruction); + console.log("something here <3 : \n"+this.instructionBytes) IP.setvalue(TwosComplement(parseInt(IP.getvalue(),2)+1,16)); //animation: if(is_animated){ diff --git a/src/Emulator/Sequencer.js b/src/Emulator/Sequencer.js index 1b56151..d9b3959 100644 --- a/src/Emulator/Sequencer.js +++ b/src/Emulator/Sequencer.js @@ -1,5 +1,6 @@ +/* eslint-disable no-unused-vars */ import { Register } from "./Register.js"; -import { queue, Registers, addressingModes } from "../pages/Ide"; +import { queue, Registers, addressingModes } from "../pages/Ide/index.jsx"; import { hash, hashmap } from "./Opcodes.js"; import { gsap } from "gsap"; // import Console from "../Console.jsx";____conflict!!!!!!!!!! @@ -538,13 +539,11 @@ class Sequenceur{ let Inshex=queue.shift(); let Ins=hex2bin(Inshex); this.RI.setvalue(Ins); - console.log(`this is RI here${this.RI.getvalue()}`) - //the animation for this instruction goes here + //the animation for this instruction goes here /////those 2 animations must be at the same time___________________ if(is_animated){ let key=hex2bin(Inshex).substring(0,4); - console.log(key); - if(key>="0010"){//instructions with 1 general byte + if(key>="0010"){//instructions with 1 general byte animations.push({ value:"", nom:"QueueToIr", @@ -2069,7 +2068,7 @@ class Sequenceur{ }) } instrObject.value1=value1; - ///animation from the register to RUAL1 + ///animation from the register to RUAL1 instrObject.value2=value2; }else if(Ind=='10'){ this.getinstrbyte(animations,false,Contextarray); @@ -2375,7 +2374,7 @@ class Sequenceur{ } instrObject.value1=value1; instrObject.value2=value2; - ///animation from the register to RUAL1 + ///animation from the register to RUAL1 }else if(Ind=='11'){ this.getinstrbyte(animations,false,Contextarray); let adresse1=this.RI.getvalue(); @@ -2439,14 +2438,13 @@ class Sequenceur{ } } - return instrObject;} + return instrObject;} } execute(instrObject,is_animated,animations){ let res; for (let i = 0; i < instrObject.stepsNum ; i++) { res = instrObject.steps[i](animations); } - console.log(instrObject); let animationSteps= instrObject.buildanim(); if(is_animated===1 & animationSteps.length>0){ for (let i = 0; i < animationSteps.length; i++) { diff --git a/src/assembler/Assembler.js b/src/assembler/Assembler.js index 7863042..7046c3c 100644 --- a/src/assembler/Assembler.js +++ b/src/assembler/Assembler.js @@ -1,10 +1,23 @@ +/* eslint-disable no-unused-vars */ +/* eslint-disable no-const-assign */ +/* eslint-disable no-useless-escape */ +/* eslint-disable eqeqeq */ +/* eslint-disable no-unreachable */ +/* eslint-disable no-fallthrough */ +/* eslint-disable default-case */ +/* eslint-disable no-redeclare */ import { Lexer } from './Lexer.js'; import {Errorcalm} from './Errorcalm.js' import {SemanticAnalysis} from './SemanticAnalysis.js' +import { element } from 'prop-types'; +import { preprocessing } from './preprocessing.js'; +import MC from '../Emulator/MC.js'; +import { memory } from '../pages/Ide/index.jsx'; + export const FuncInterface ={ adrmap : (txt,size,dep)=>{ - var adr=''; + var adr='' switch(txt){ case 0: adr = '000'; @@ -189,7 +202,6 @@ while (hexString.length < size) { // binaryToHex: (binaryString,size)=>{ // // Convert decimal to hexadecimal string - // console.log("____________________________"+binaryString+" "+size) // let hexString = parseInt(binaryString, 2).toString(16); // // Pad the hexadecimal string with leading zeros to 4 bytes (8 characters) // while (hexString.length < size) { @@ -202,28 +214,25 @@ while (hexString.length < size) { Label_To_Num : (labelname,linenumber)=>{ var labelobj = false ; - Assembler.Labellist.forEach(element => { - if(element.name === labelname){ - labelobj = element - } + labelobj = Assembler.Labellist.find(element => { + return element.name === labelname; }); - //console.log(labelobj) + if (!(labelobj == null)){ if (labelobj == false) { //error Errorcalm.set_SemanticError(new Errorcalm("Label not found",null,linenumber)); return {type: 'ERROR', value: null}; }else{ - //return the address return {type: 'NUMBER', value: labelobj.address} - }}, + }} +}, confirmationfunction : (input) => { var errormsg = [] var err = false ; - //console.log(input) // check Errorcalm.SemanticError first else do the thing you where doing if (Errorcalm.SemanticError.length > 0) { Errorcalm.printError(); @@ -243,7 +252,6 @@ while (hexString.length < size) { addrmod : (listofpar,line) => { - console.log(listofpar); // go through the list of instructions if listofpar[index].value is different then , then add this element.value to the list 1 // go throught an if there is an element.type='TEXT' you use Labeltonum to make it a number listofpar.forEach((element,index) => { @@ -258,7 +266,8 @@ while (hexString.length < size) { var lastindex ; var index = 0; - + console.log("listlength:",listofpar.length) + console.log("listofpar:",listofpar) while (index < listofpar.length && listofpar[index].value !== ',') { list1.push(listofpar[index]); lastindex = index; @@ -417,8 +426,6 @@ while (hexString.length < size) { } } - - export class Assembler{ static MAXNUM = 65535; @@ -433,26 +440,28 @@ export class Assembler{ constructor(input){ + let lexicalList = input.map((t,index)=> {return new Lexer(t,index).LexicalList} ) if (Errorcalm.LexicalError.length > 0) { - Errorcalm.printError(); + const errorMSG = Errorcalm.printError(); + this.input = {error: errorMSG} }else{ + console.log("lexicalList fjlsjdflsjflsjfs",lexicalList) this.input = lexicalList; - console.log("\nLexicalList:\n",lexicalList) this.toAssemble = new SemanticAnalysis(this.input); - let ret = FuncInterface.confirmationfunction(this.toAssemble.Semanticlist); - if (!ret.status) { - console.log("\nThere are errors in your code cannot assemble:\n"); - console.log(ret.errors); - }} + // let ret= functinterface.cofirmationfunction(this.input); + } } static assemble(input){ //turn instruction object to 8 octet hexa represented as a string // input is one line of code var index = 0; + console.log("input",input) + const element = input[index]; - switch(element.type){ + console.log("input",input[index]) + switch(element.type){ case 'INST2': var opcode='' ; @@ -514,22 +523,16 @@ export class Assembler{ ind = '00'; regmod1 = FuncInterface.regmap(input[1].value); regmod2 = FuncInterface.regmap(input[2].value); - code = opcode + ind + regmod1 + regmod2 - - //return {codehex:FuncInterface.binaryToHex(code,code.length/4),codebin:code}; return FuncInterface.binaryToHex(code,code.length/4) - - break; - + break; break; case 'REGISTER,NUMBER': ind = '01'; regmod1 = FuncInterface.regmap(input[1].value); regmod2 = FuncInterface.adrmap(input[2].adrmode,size, typeof input[2].depl =='undefined' ? 0 : input[2].depl>255 ? '1' :'0' ); - //console.log(regmod2) - + //console.log(regmod2) switch (regmod2) { case '000': let long = size == 0 ? 8 : 16; @@ -629,7 +632,6 @@ export class Assembler{ case '111': dep1 = FuncInterface.decimalTobinByte(input[1].depl, input[1].depl > 255 ? 16 : 8 ); op1 = FuncInterface.decimalTobinByte(input[1].value,16); - console.log("dep1 here",FuncInterface.binaryToHex(dep1,4)) break; case '011': case '100': @@ -656,13 +658,11 @@ export class Assembler{ case '110': dep2 = FuncInterface.decimalTobinByte(input[2].depl, input[2].depl > 255 ? 16 : 8 ); op2 = FuncInterface.decimalTobinByte(input[2].value,16); - console.log("dep2 here size 0-----------",dep2) break; case '111': dep2 = FuncInterface.decimalTobinByte(input[2].depl , input[2].depl > 255 ? 16 : 8 ); op2 = FuncInterface.decimalTobinByte(input[2].value, 16 ); - console.log("dep2 here size 2",FuncInterface.binaryToHex(dep2,4)) case '011': case '100': @@ -686,9 +686,7 @@ export class Assembler{ //console.log(dep1) //console.log(FuncInterface.binaryToHex(dep1,4)) //console.log(FuncInterface.binaryToHex(code,code.length/4)) - console.log("code here",code) - console.log("code here",FuncInterface.binaryToHex(code,code.length/4)) - return FuncInterface.binaryToHex(code,code.length/4) + return FuncInterface.binaryToHex(code,code.length/4) break; default: @@ -857,33 +855,62 @@ export class Assembler{ break; } let instcode=oppcode+adr; - return instcode; - + return instcode; } - } - - } - static assemblecode(input){ - let output = new Assembler(input) ; + static assemblecode(input){ + let input2 = preprocessing.preprocessor(input) + if(input2.error !== ''){ + return {code: input2.code, memory: input2.data, error: input2.error} + } + // again, this needs a fix + //this is safe + MC.data = Array(100).fill().map((_, i) => FuncInterface.binaryToHexoneByte(input2.data[i] ?? "00000000")) + + console.log("MC.data:",MC.data) + Assembler.Labellist.push(...input2.varList) + let output = new Assembler(input2.code); + // if semantic analysis returns any error we return it from here + if(output.input?.error){ + return {code: [], memory: MC.data, error: output.error} + } var assembledcode = []; var toassmb = (output && output.toAssemble && output.toAssemble.Semanticlist) ? output.toAssemble.Semanticlist : "Semanticlist is undefined"; - console.log("\nSemantic list: \n",toassmb) - if ( Errorcalm.SemanticError.length ===0 ) { - + var ipTrack = 0; + var i=0; + var lines = (Assembler.Labellist.length === 0 ) ? toassmb.length : Assembler.Labellist[i].linedeclared; + // two pass first pass stays as it is with adding a delimater at each label and then re apply the semantic analysis for the labels and then reassemble the code + if ( Errorcalm.SemanticError.length === 0 ) { for (let index = 0; index < toassmb.length; index++) { - - assembledcode.push(Assembler.assemble(toassmb[index])) - + if (index >= lines && Assembler.Labellist.labeltype) { + Assembler.Labellist[i].address = ipTrack; + i++; + if (i < Assembler.Labellist.length) { + lines = Assembler.Labellist[i].linedeclared - Assembler.Labellist[i-1].linedeclared-1+index; + }else{ + lines = toassmb.length; + } + } + ipTrack = ipTrack+(Assembler.assemble(toassmb[index]).length/2) } - console.log("\nAssembled code: \n",assembledcode) - return assembledcode; + SemanticAnalysis.labeling = false; + output = new Assembler(input2.code) + // if semantic analysis returns any error we return it from here + if(output.input?.error){ + return {code: [], memory: MC.data, error: output.error} + } + toassmb = (output && output.toAssemble && output.toAssemble.Semanticlist) ? output.toAssemble.Semanticlist : "Semanticlist is undefined"; + console.log("toassmb",toassmb) + for (let index = 0; index < toassmb.length; index++) { + assembledcode.push(Assembler.assemble(toassmb[index])) + } + return {code: assembledcode, memory: memory.data, error: input2.error}; // here put the return in case of success }else{ //here put the return in case of error - return "error"; + return {code: assembledcode, memory: memory.data, error: `${Errorcalm.SemanticError[0].message} at line ${Errorcalm.SemanticError[0].line}`}; } } @@ -894,7 +921,6 @@ export class Assembler{ - //var input = ["MOV 0,0"] //console.log("\nInput: \n", Assembler.assemblecode(input)) @@ -907,8 +933,6 @@ let output = new Assembler(input) ; -console.log("\nLabel list: \n",Assembler.Labellist) - //console.log("\nSemantic list: \n", output?.toAssemble?.Semanticlist ?? "Semanticlist is undefined"); console.log("\nSemantic list: \n", (output && output.toAssemble && output.toAssemble.Semanticlist) ? output.toAssemble.Semanticlist : "Semanticlist is undefined"); var toassmb = (output && output.toAssemble && output.toAssemble.Semanticlist) ? output.toAssemble.Semanticlist : "Semanticlist is undefined"; diff --git a/src/assembler/Errorcalm.js b/src/assembler/Errorcalm.js index b834f85..b8207d6 100644 --- a/src/assembler/Errorcalm.js +++ b/src/assembler/Errorcalm.js @@ -1,3 +1,6 @@ +/* eslint-disable no-useless-concat */ +/* eslint-disable no-unused-vars */ +/* eslint-disable eqeqeq */ import { Assembler,FuncInterface } from "./Assembler.js"; import { SemanticAnalysis } from "./SemanticAnalysis.js"; import { Lexer } from "./Lexer.js"; @@ -42,8 +45,8 @@ export class Errorcalm{ numerr ==1 ? theError="\nThere is 1 error in your code:\n" : theError=`\nThere are ${numerr} errors in your code cannot assemble:\n`; Errorcalm.LexicalError.length == 0 ? theError+=" Semantic Errors:\n"+" "+Errorcalm.SemanticError[0].message+"\n the line : "+Errorcalm.SemanticError[0].linenum : theError+="Lexical Errors \n"+" "+Errorcalm.LexicalError[0].message+"\n the line :"+Errorcalm.LexicalError[0].line; Errorcalm.errorr=1; - console.log(this.SemanticError); - return theError;} + return theError; + } } static addtoSemanticError(errs){ Errorcalm.SemanticError= errs.concat(Errorcalm.SemanticError); } diff --git a/src/assembler/Lexer.js b/src/assembler/Lexer.js index e21bd31..632ccad 100644 --- a/src/assembler/Lexer.js +++ b/src/assembler/Lexer.js @@ -1,151 +1,159 @@ +/* eslint-disable eqeqeq */ +/* eslint-disable no-useless-escape */ +/* eslint-disable no-unused-vars */ import { Assembler } from './Assembler.js'; import { Errorcalm } from './Errorcalm.js'; import { SemanticAnalysis } from './SemanticAnalysis.js'; + export class Lexer { static Errors = []; - + static isValidString(str) { // Check if the string contains any special characters if (/[^a-zA-Z0-9_]/.test(str)) { return false; - }else{ - - // Check if the string begins with a number - if (/^\d/.test(str)) { - return false; - }else{ - // Check if the string is in the excluded list - if (Assembler.excludedStrings.includes(str)) { - return false; - }else{ - // If none of the above conditions are met, the string is valid ; - //console.log("valid string") - return true; + } else { + // Check if the string begins with a number + if (/^\d/.test(str)) { + return false; + } else { + // Check if the string is in the excluded list + if (Assembler.excludedStrings.includes(str)) { + return false; + } else { + // If none of the above conditions are met, the string is valid + return true; + } + } } - }} } - constructor(code,line) { - //console.log(code.match(/([a-zA-Z0-9]+\d*(?:[a-zA-Z09]+)?|\*|,|\+)/g)) - this.LexicalList = code.match(/([a-zA-Z0-9]+\d*(?:[a-zA-Z0-9]+)?|\*|,|\+,,|\~|,|\`|,|\!|,|\@|,|\#|,|\$|,|\-|,|\%|,|\^|,|\&|,|\*|,|\(|,|\)|,|\_|,|\=|,|\+|,|\[|,|\]|,|\{|,|\}|,|\;|,|\:|,|\'|,|\"|,|\,|,|\.|,|\<|,|\>|,|\?|,|\\|)/g).filter(function (t) { - return t.length > 0; - }).map((t,index)=> { - if (isNaN(t)) { - switch (t) { - case 'R1': - case 'R2': - case 'R3': - case 'R4': - case 'ACC': - case 'BR': - case 'IDR': - case 'SR': - case 'R1R': - case 'R2R': - case 'R3R': - case 'ACCR': - case 'R1L': - case 'R2L': - case 'R3L': - case 'ACCL': - return { - type: 'REGISTER', - value: t - }; - case 'RET': - case 'PUSHA': - case 'POPA': - return{ - type: 'INST0', - value: t - }; - case 'NEG': - case 'NOT': - case 'SHL': - case 'SHR': - case 'READ': - case 'WRITE': - case 'PUSH': - case 'POP': - case 'ROR': - case 'ROL': - case 'CALL': - case 'BE': - case 'BNE': - case 'BS': - case 'BI': - case 'BIE': - case 'BSE': - case 'BRI': - return { - type: 'INST1', - value: t - }; - case 'NAND': - case 'CMP': - case 'MOV': - case 'ADD': - case 'SUB': - case 'MUL': - case 'DIV': - case 'AND': - case 'OR': - case 'XOR': - case 'NOR': - return{ - type: 'INST2', - value: t - }; - case '*': - case ',': - case '+': - case '-': - return { - type: 'SPECIAL CHARACTER', - value: t - }; - case 'LABEL': - return { - type: 'LABEL' - }; - break; + + constructor(code, line) { + this.LexicalList = code.match(/([a-zA-Z0-9]+\d*(?:[a-zA-Z0-9]+)?)(:?)|\*|,|\+,,|\~|,|\|,|\!|,|\@|,|\#|,|\$|,|\-|,|\%|,|\^|,|\&|,|\*|,|\(|,|\)|,|\_|,|\=|,|\+|,|\[|,|\]|,|\{|,|\}|,|\;|,|\:|,|\'|,|\"|,|\,|,|\.|,|\<|,|\>|,|\?|,|\\|/g).filter(function (t) { + return t.length > 0; + }).flatMap((t, index) => { + if (isNaN(t)) { + switch (t) { + case 'R1': + case 'R2': + case 'R3': + case 'R4': + case 'ACC': + case 'BR': + case 'IDR': + case 'SR': + case 'R1R': + case 'R2R': + case 'R3R': + case 'ACCR': + case 'R1L': + case 'R2L': + case 'R3L': + case 'ACCL': + return [{ + type: 'REGISTER', + value: t + }]; + case 'RET': + case 'PUSHA': + case 'POPA': + return [{ + type: 'INST0', + value: t + }]; + case 'NEG': + case 'NOT': + case 'SHL': + case 'SHR': + case 'READ': + case 'WRITE': + case 'PUSH': + case 'POP': + case 'ROR': + case 'ROL': + case 'CALL': + case 'BE': + case 'BNE': + case 'BS': + case 'BI': + case 'BIE': + case 'BSE': + case 'BRI': + return [{ + type: 'INST1', + value: t + }]; + case 'NAND': + case 'CMP': + case 'MOV': + case 'ADD': + case 'SUB': + case 'MUL': + case 'DIV': + case 'AND': + case 'OR': + case 'XOR': + case 'NOR': + return [{ + type: 'INST2', + value: t + }]; + case '*': + case ',': + case '+': + case '-': + return [{ + type: 'SPECIAL CHARACTER', + value: t + }]; + case 'LABEL': + return [{ + type: 'LABEL' + }]; default: - if (Lexer.isValidString(t)) { - return { - type: 'TEXT', - value: t - }; - }else{ - Lexer.Errors.push(new Errorcalm("Invalid string", "LEXER", line)) ; //change this 0 to the line number - Errorcalm.set_LexicalError(new Errorcalm("Invalid string", "LEXER", line)); - } - } - } else { - return { - type: 'NUMBER', - value: t - }; + if (t.endsWith(':')) { + let labelText = t.slice(0, -1).trim(); // Extract label text + + return [ + { type: 'LABEL' }, + { type: 'TEXTT', value: labelText }, + { type: 'NUMBER', value: line.toString() } + ]; + } + else if (Lexer.isValidString(t)) { + return [{ type: 'TEXT', value: t }]; + } else { + Lexer.Errors.push(new Errorcalm("Invalid string", "LEXER", line)); + Errorcalm.set_LexicalError(new Errorcalm("Invalid string", "LEXER", line)); + return []; + } } - }); - let lexlist= this.LexicalList - lexlist.forEach((element,index,lexlist) => { - if (element.type =='NUMBER') { - if ( lexlist[index-1].value=='-' && lexlist[index-1].type=='SPECIAL CHARACTER' ){ - console.log( '-'+element.value ) - lexlist.splice(index-1, 1); - if( parseInt('-'+element.value,10) < -32768){ - Lexer.Errors.push(new Errorcalm("Number out of range", "LEXER", line)) ; //change this 0 to the line number - Errorcalm.set_LexicalError(new Errorcalm("Number out of range", "LEXER", line)); - }else{ - lexlist[index-1]={ - type: 'NUMBER' - ,value: `-${element.value}` - }} + } else { + return [{ + type: 'NUMBER', + value: t + }]; + } + }); + // Flatten the array of arrays into a single array + let lexlist = this.LexicalList.flat(); + lexlist.forEach((element, index, lexlist) => { + if (element.type == 'NUMBER') { + if (lexlist[index - 1].value == '-' && lexlist[index - 1].type == 'SPECIAL CHARACTER') { + console.log('-' + element.value); + lexlist.splice(index - 1, 1); + if (parseInt('-' + element.value, 10) < -32768) { + Lexer.Errors.push(new Errorcalm("Number out of range", "LEXER", line)); + Errorcalm.set_LexicalError(new Errorcalm("Number out of range", "LEXER", line)); + } else { + lexlist[index - 1] = { + type: 'NUMBER', + value: `-${element.value}` + }; + } } } - - }); - this.LexicalList = lexlist; - - } - - } \ No newline at end of file + }); + this.LexicalList = lexlist; + } +} \ No newline at end of file diff --git a/src/assembler/SemanticAnalysis.js b/src/assembler/SemanticAnalysis.js index c5845d0..c65f882 100644 --- a/src/assembler/SemanticAnalysis.js +++ b/src/assembler/SemanticAnalysis.js @@ -1,3 +1,5 @@ +/* eslint-disable default-case */ +/* eslint-disable no-loop-func */ import { Lexer } from './Lexer.js'; import { Errorcalm } from './Errorcalm.js'; import { Assembler,FuncInterface } from "./Assembler.js"; @@ -5,10 +7,60 @@ import { Assembler,FuncInterface } from "./Assembler.js"; export class SemanticAnalysis { Semanticlist = [] - + static labeling = true; constructor(input) { - let lexicalList = input; + if(SemanticAnalysis.labeling){ + for(let i = 0; i < lexicalList.length; i++){ + let firstword = lexicalList[i][0] + let firstwordtype = firstword.type + if (firstwordtype == 'LABEL') { + if (lexicalList[i].length == 3) { + if (lexicalList[i][2].type == 'NUMBER') { + if( lexicalList[i][2].value < Assembler.MAXNUM){ + if(lexicalList[i][1].type == 'TEXT' || lexicalList[i][1].type == 'TEXTT'){ + if(Lexer.isValidString(lexicalList[i][1].value)){ + // filters for text standards and validity of the text + // check if label already existing + var found = false ; + var labelname = lexicalList[i][1].value ; + Assembler.Labellist.forEach(element => { + if((element.name === labelname)){ + console.log(element.name + " " + labelname + " " + SemanticAnalysis.labeltype + " " + element.label) + found = true + } + }); + if (!found) { + if (lexicalList[i][1].type === 'TEXTT') { + Assembler.Labellist.push({ name: labelname, address: parseInt(lexicalList[i][2].value), linedeclared:i, label: true }) + } + else if (lexicalList[i][1].type === 'TEXT') { + Assembler.Labellist.push({ name: labelname, address: parseInt(lexicalList[i][2].value), linedeclared:i, label: false }) + + } + }else{ + this.Semanticlist.push(new Errorcalm("LABEL already declared",null,i)) + } + }else{ this.Semanticlist.push(new Errorcalm("LABEL name is not valid",null,i)) } + }else{ + this.Semanticlist.push(new Errorcalm("LABEL name not defined",null,i)) + } + }else{ + this.Semanticlist.push(new Errorcalm("Number size is bigger then MAXNUM",null,i)) + } + }else{ + this.Semanticlist.push(new Errorcalm("LABEL must be a number",null,i)) + } + }else{ + if (Lexer.isValidString(lexicalList[i][2].value )) { + this.Semanticlist.push(new Errorcalm("LABEL must have only two operands",null,i)) + }else + { + this.Semanticlist.push(new Errorcalm("LABEL name is not valid",null,i)) + } + } + } + }} for(let i = 0; i < lexicalList.length; i++){ // here operation with each line of code // we must check if it is a label or an instruction @@ -17,54 +69,8 @@ export class SemanticAnalysis { let firstword = lexicalList[i][0] let firstwordtype = firstword.type - - switch (firstwordtype) { - - case 'LABEL': - const functLABEL = ()=> { - if (lexicalList[i].length == 3) { - if (lexicalList[i][2].type == 'NUMBER') { - if( lexicalList[i][2].value < Assembler.MAXNUM){ - if(lexicalList[i][1].type == 'TEXT'){ - if(Lexer.isValidString(lexicalList[i][1].value)){ - // filters for text standards and validity of the text - // check if label already existing - var found = false ; - var labelname = firstword.value ; - Assembler.Labellist.forEach(element => { - if(element.name === labelname){ - found = true - } - }); - if (!found) { - //this.Semanticlist.push(lexicalList[i]); - //stop pushing here because we don't need it - Assembler.Labellist.push({ name: lexicalList[i][1].value, address: lexicalList[i][2].value, linedeclared:i }) - }else{ - this.Semanticlist.push(new Errorcalm("LABEL already declared",null,i)) - } - }else{ this.Semanticlist.push(new Errorcalm("LABEL name is not valid",null,i)) } - }else{ - this.Semanticlist.push(new Errorcalm("LABEL name not defined",null,i)) - } - }else{ - this.Semanticlist.push(new Errorcalm("Number size is bigger then MAXNUM",null,i)) - }}else{ - this.Semanticlist.push(new Errorcalm("LABEL must be a number",null,i)) - } - }else{ - if (Lexer.isValidString(lexicalList[i][2].value )) { - this.Semanticlist.push(new Errorcalm("LABEL must have only two operands",null,i)) - }else - { - this.Semanticlist.push(new Errorcalm("LABEL name is not valid",null,i)) - } - } - } - - functLABEL(); - break; - + + switch (firstwordtype) { case 'INST0': // No params instructions: INST0 ::= RET, PUSHA, POPA // We must have no op after it @@ -142,6 +148,12 @@ export class SemanticAnalysis { switch (lexicalList[i].length) { case 2: + const labelType = FuncInterface.Label_To_Num(firstparam.value,i) + if(labelType.type === 'ERROR'){ + this.Semanticlist.push(new Errorcalm("LABEL not declared",null,i)) + // we shall fix this later if needed + return + } this.Semanticlist.push([{type:lexicalList[i][0].type, value:lexicalList[i][0].value, adrmode:0 },{type:FuncInterface.Label_To_Num(firstparam.value,i).type, value:FuncInterface.Label_To_Num(firstparam.value,i).value}]); break; @@ -192,6 +204,7 @@ export class SemanticAnalysis { // check also for first operand based ind and second indexed or based or opposite // check if size of first list == size of second list and assign it to the size of the instruction var list1,list2 =[]; + console.log("lexicalList[i]",lexicalList[i]) list1 = FuncInterface.addrmod(lexicalList[i].slice(1),i).list1 ; //console.log("list1",list1[0].type) list2 = FuncInterface.addrmod(lexicalList[i].slice(1),i).list2 ; @@ -232,7 +245,7 @@ export class SemanticAnalysis { } - } + }} @@ -268,8 +281,6 @@ export class SemanticAnalysis { // Label instformat LABEL num check this num if it is valid.; -} - /* const MAXNUM =6000 // max adress for label diff --git a/src/assembler/preprocessing.js b/src/assembler/preprocessing.js new file mode 100644 index 0000000..38759e2 --- /dev/null +++ b/src/assembler/preprocessing.js @@ -0,0 +1,435 @@ +/* eslint-disable no-loop-func */ +import { FuncInterface } from './Assembler.js' +import {Errorcalm} from './Errorcalm.js' +export class preprocessing{ + //this should include all reserved words, or if there is a global object serving the same purpose + static reservedWords = new Set(['R1', 'R2', 'R3', 'R4', 'ACC', 'BR', 'IDR', 'SR', 'R1R', 'R2R', 'R3R', 'ACCR', 'R1L', 'R2L', 'R3L', 'ACCL' + , 'PUSHA', 'POPA', 'RET', 'NEG', 'NOT', 'SHL', 'SHR', 'READ', 'WRITE', 'PUSH', 'POP', 'ROR', 'ROL', 'CALL', 'BE', 'BNE', 'BS', 'BI', 'BIE', 'BSE', 'BRI' + , 'NAND', 'CMP', 'MOV', 'ADD', 'SUB', 'MUL', 'DIV', 'AND', 'OR', 'XOR', 'NOR', 'MACRO', 'ENDM', 'START', 'END','SDATA', 'ENDS']) + static macroKeyWords = ['MACRO', 'ENDM'] + static DataKeyword = ['SDATA', 'ENDS'] + + constructor(){ + this.MACROS = [] + this.macroKeyWord = new Set() + this.labelSymbolList = [] + this.dataSegment = [] + this.errors = [] + this.varList = [] + this.data = [] + } + + getDataSegment(code){ + const n = code.length + let i = 0 + while( i < n && code[i].toUpperCase() !== 'START'){ + if(code[i].toUpperCase() === 'SDATA'){ + i += 1 + let endOfSeg = false + while(!endOfSeg){ + + if(i === n){ + console.log("no end of data segment") + //error segment not closed + this.errors.push(new Errorcalm("Data segment not closed", "PREPROCESSING", i)) + return + } + if(code[i].toUpperCase() === 'ENDS'){ + endOfSeg = true + continue + } + + this.dataSegment.push(code[i++]) + } + break + } + i += 1 + } + } + + // allocate space in memory, to get addresses of variables + allocateData(){ + if(this.dataSegment.length === 0){ + // no data segment, no need to allocate + console.log("no data") + return + } + // here, we first should decide whether we compact the memory or not, so we either work from 0 or from the end of stack segment at @ = 256 + let curAddress = 0 + let n = this.dataSegment.length + for(let i = 0; i < n; i++){ + let line = this.dataSegment[i].split(' ') + // we want to get an array in this form [label, length, value(s)] + // for example [X, db, 15] + if(line.length < 3){ + // throw error, wrong variable declaration + this.errors.push(new Errorcalm("Wrong variable declaration", "PREPROCESSING", i)) + return + } + if(this.varList.includes(line[0].toUpperCase())){ + // throw error, variable already declared + this.errors.push(new Errorcalm("Variable already declared", "PREPROCESSING", i)) + return + } + if(!isNaN(Number(line[0][0]))){ + // throw error, variable name cannot start with a number + this.errors.push(new Errorcalm("Variable name cannot start with a number", "PREPROCESSING", i)) + return + } + + let varHolder = {} + // assign the name of the var to the corresponding object + varHolder.label = false + varHolder.linedeclared = i + varHolder.name = line[0].toUpperCase() + varHolder.address ??= curAddress + this.varList.push(varHolder) + if(!(['DB', 'DW']).includes(line[1].toUpperCase())){ + // throw error, wrong variable length declaration + this.errors.push(new Errorcalm("Wrong variable type", "PREPROCESSING", i)) + return + } + let length = line[1].toUpperCase() === 'DB' ? 0 : 1 // data on one byte or on two bytes if line[0] === 'DW' + varHolder.length = length + let value = line.filter((_,index) => index >= 2).join(" ").match(/"[^"]*"|[^,]+/g) + + console.log(value) + // parsing value(s) of the variable + // we should include the number of bytes to calculate the current address + + //console.log(value) + value = value.map((val,index) => { + curAddress += length === 1 ? 2 : 1 + // we should check if we have numbers or strings + if(!isNaN(Number(val)) && val.trim() !== ''){ + + // verify size of number compared to length of space allocated for it + //but before, make sure it falls within range 8 / 16 bits I'll verify that later + val = Number(val) + if(length === 1){ + if(val <= Math.abs(Math.pow(2,16))){ + // use 2s complement instead of this expression + console.log(val) + val = FuncInterface.decimalTobinByte(val,16) + + return [String(val).substring(0,Math.floor(val.length / 2)), String(val).substring(Math.floor(val.length / 2))] + } else { + this.errors.push(new Errorcalm("value out of bounds", "PREPROCESSING", index)) + return null + } + } else { + if(val <= Math.abs(Math.pow(2,8))){ + // use 2s complement instead of this expression + return FuncInterface.decimalTobinByte(val,8) + } else { + this.errors.push(new Errorcalm("value out of bounds", "PREPROCESSING", index)) + return null + } + } + } else{ + if (val[0] !== '"' || val[val.length - 1] !== '"') { + // throw error, string not closed + this.errors.push(new Errorcalm("String must be unclosed within in a pair of \"\"", "PREPROCESSING", index)) + return null; + + } + // we have a string I guess, we convert to ascii and we pad when we write binary string in the memory + if(length === 0){ + return val.split('').filter(char => char !== '"').map(char => char.charCodeAt(0).toString(2).padStart(8,'0')) + } + //ascii characters are positive integers between 0 and 255 + + return val.split('').filter(char => char !== '"').map(char => ['00000000', char.charCodeAt(0).toString(2).padStart(8,'0')]).flat() + } + }).flat() // flatten to get a 1 dimensional array just in case if we have a string in the object + //we have to work on this + this.data.push(...value) + } + console.log(this.data) + + } + // we suppose the code is given to use as + extractMacro(input /*it should be the whole code */){ + // input is the whole code which we divided into an array of strings + let curLine = 0 + let n = input.length + // we allow macro declaration only before code starts + while(curLine < n && input[curLine] !== 'START' ){ + // tokenize each line to get components of each line {instructions, labels, operands...} + let line = input[curLine].match(/([a-zA-Z_][a-zA-Z0-9_]*|[,:])/g) + if(line[0] === 'ENDM'){ + // throw error, macro not declared + this.errors.push(new Errorcalm("Macro not declared", "PREPROCESSING", curLine)) + return + } + if(line[0] === 'MACRO'){ + let macroClosed = false + if(line.length < 2){ + // throw error, no macro name provided + this.errors.push(new Errorcalm("No macro name provided", "PREPROCESSING", curLine)) + return + } + + if(preprocessing.reservedWords.has(line[1])){ + // a macro instruction cannot be a reserved word + this.errors.push(new Errorcalm("Macro instruction cannot be a reserved word (register or instruction)", "PREPROCESSING", curLine)) + return + } + + if([',',':','/','\\','.'].includes(line[1])){ + // macro name cannot be a special character + this.errors.push(new Errorcalm("Macro name cannot be a special character", "PREPROCESSING", curLine)) + return + } + + if(!isNaN(Number(line[1][0]))){ + // macro name cannot start with a number or be a number + this.errors.push(new Errorcalm("Macro name cannot start with a number or be a number", "PREPROCESSING", curLine)) + return + } + + if(this.macroKeyWord.has(line[1])){ + // macro already declared + this.errors.push(new Errorcalm("Macro already declared", "PREPROCESSING", curLine)) + return + } + + this.macroKeyWord.add(line[1]) + let macroHolder = {keyWord: line[1], instruction: line.slice(1), body : []} + curLine += 1 + // now we extract the body of the macro and store it in the macroHolder, we also handle possible errors + + while(!macroClosed){ + if(!input[curLine]){ + // console.log("not closed, and main function not declared") + // end of code without any end of macro or beginning of code + this.errors.push(new Errorcalm("Macro not closed", "PREPROCESSING", curLine)) + return + } + + if(input[curLine] === 'START'){ + // code starts and macro not closed + this.errors.push(new Errorcalm("Macro not closed", "PREPROCESSING", curLine)) + return + } + + if(input[curLine] === 'ENDM'){ + // if we reach the end skip this iteration,loop will be quit also in the next condition checking + macroClosed = true + continue + } + + // making sure no sort of label is declared inside a macro + line = input[curLine++].match(/[a-zA-Z_][a-zA-Z0-9_*]*|[,:+-]|\d+/g) + if(line[0] === 'MACRO'){ + // throw error, no macros allowed inside a macro + this.errors.push(new Errorcalm("No macros allowed inside a macro", "PREPROCESSING", curLine)) + return + } + + if(line[0][line[0].length - 1] === ':'){ + // throw error, no labels allowed inside a macro + this.errors.push(new Errorcalm("No labels allowed inside a macro", "PREPROCESSING", curLine)) + return + } + macroHolder.body.push(line) + } + this.MACROS.push(macroHolder) + } + + curLine += 1 // move to next line + } + //this.MACROS.forEach(macro => console.log("that's a macro: ",macro)) + } + + + // this method should remove extra text from top as well as macros and start / end keywords? + // this comment shouldn't be here + + + replaceMacro(input /*it should be also the whole code */){ + let output = [] // new code will be returned here + let curLine = 0 + let endOfCode = false + while(input[curLine] !== 'START'){ + curLine += 1 + if(!input[curLine]){ + // throw error + this.errors.push(new Errorcalm("no START keyword detected", "PREPROCESSING", curLine)) + return + } + } + curLine += 1 + while(!endOfCode){ + if(!input[curLine]){ + // throw error and quit + this.errors.push(new Errorcalm("no END keyword detected", "PREPROCESSING", curLine)) + //console.log("does'nt work") + return {error: "this thing doesn't work"} + } + if(input[curLine] === 'END'){ + endOfCode = true + continue + } + let line = input[curLine++].match(/[a-zA-Z_][a-zA-Z0-9_*]*|[,:+-]|\d+/g) + + if(line[0][line[0].length - 1] === ':'){ + if(this.macroKeyWord.has(line[1])){ + // expand macro + // replaceMacro(line,output) // pushes directly in the output code + output.push( ...this.expandMacro(line,line[1],true)) + //output.push('this is a macro') + } else { + output.push(input[curLine - 1]) + } + } else if(this.macroKeyWord.has(line[0])){ + // replace again + output.push( ...this.expandMacro(line,line[0])) + //output.push('this is a macro') + } else { + output.push(input[curLine - 1]) + } + } + return output + } + + + expandMacro(line,keyWord,label = false){ + + const [ expandedMacroTemplate ]= this.MACROS.filter(macro => macro.keyWord === keyWord) + let body = expandedMacroTemplate.body.map(line => line.join(' ')) + let newLine = line + // now we check the line, and replace args where needed + if(label){ + // handle when there is a label + // this will work the opposite way + body[0] = line[0] + ' ' + body[0] + newLine = line.filter(word => word[word.length - 1] !== ':') + } + if(newLine.length !== expandedMacroTemplate.instruction.length){ + //throw error, different number of args + this.errors.push(new Errorcalm(`Different number of arguments for macro ${newLine[0][newLine.length - 1] === ':' ? newLine[1]: newLine[0]}`, "PREPROCESSING", newLine)) + return ["error here"] + } + //there is no label, direct matching + for(let i = newLine.length - 1; i >= 1; i--){ + + const wordToReplace = expandedMacroTemplate.instruction[i]; + const regex = new RegExp(`\\b${wordToReplace}\\*?\\b`, "g"); + + body = body.map(inst => inst.replace(regex, newLine[i])); + + } + return body + } + // no errors are handled here + // no spaces allowed between labelName and : + + // detectLabels(code){ + // console.log(code) + // let n = code.length + // for(let i = 0; i < n; i++){ + // let line = code[i].match(/([a-zA-Z_][a-zA-Z0-9_]*:?|\d+|,)/g) + // if(line[0][line[0].length - 1] === ":"){ + // if(line[0].length === 1){ + // // throw error + // console.log("error, empty label") + // return + // } + + // if(preprocessing.reservedWords.has(line[0].slice(0,-1)) || this.macroKeyWord.has(line[0].slice(0,-1))){ + // // reserved word cannot be a label + // this.errors.push(new Errorcalm("Reserved word cannot be a label", "PREPROCESSING", i)) + // console.log("reserved") + // return + // } + // //label does not start with a number + // if(!isNaN(Number(line[0][0]))){ + // // label cannot start with a number + // this.errors.push(new Errorcalm("Label cannot start with a number", "PREPROCESSING", i)) + // console.log("number") + // return + // } + + // this.labelSymbolList.push({label: line[0].slice(0,-1), line: i + 1}) + // } + // } + // console.log(this.labelSymbolList) + // } + + // removeAndReplaceLabels(code){ + // // replace labels with their line numbers I guess + // let n = code.length + // let output = [] + // for(let i = 0; i < n; i++){ + // //check in each line if there is a use of the label, if definition, we remove it, if use, replace with line number + // let line = code[i].match(/([a-zA-Z_][a-zA-Z0-9_]*:?|\d+|,)/g) + // console.log(line) + // if(line[0][line[0].length - 1] === ":"){ + + // output.push(line.filter(word => word[word.length - 1] !== ':').join(' ')) + // } + // else{ + // output.push(line.join(' ')) + // } + // } + // return output + // } + static preprocessor(code){ + const preprocessor = new preprocessing(); + let str = code + try{ + + preprocessor.getDataSegment(str) + console.log(preprocessor.errors.length) + console.log(preprocessor.errors) + if(preprocessor.errors.length > 0){ + return {code: [], labels: [], data: [], varList: [], error: `Error: ${preprocessor.errors[0].message}\n${preprocessor.errors[0].type}`} + } + str = str.map(line => line.toUpperCase()) + preprocessor.allocateData() + if(preprocessor.errors.length > 0){ + return {code: [], labels: [], data: [], varList: [], error: `Error: ${preprocessor.errors[preprocessor.errors.length - 1].message}\n${preprocessor.errors[preprocessor.errors.length - 1].type} in line ${preprocessor.errors[preprocessor.errors.length - 1].linenum} in data segment`} + } + preprocessor.extractMacro(str) + + if(preprocessor.errors.length > 0){ + return {code: [], labels: [], data: [], varList: [], error: `Error: ${preprocessor.errors[preprocessor.errors.length - 1].message}\n${preprocessor.errors[preprocessor.errors.length - 1].type} in line ${preprocessor.errors[preprocessor.errors.length - 1].linenum} in macro declaration`} + } + str = preprocessor.replaceMacro(str) + if(preprocessor.errors.length > 0){ + return {code: [], labels: [], data: [], varList: [], error: `Error: ${preprocessor.errors[preprocessor.errors.length - 1].message}\n${preprocessor.errors[preprocessor.errors.length - 1].type} in line ${preprocessor.errors[preprocessor.errors.length - 1].linenum} in code segment`} + } + return {code: str || [], labels: preprocessor.labelSymbolList, data: preprocessor.data, varList: preprocessor.varList, error: ''} + + }catch(err){ + return {code: [], labels: [], data: [], varList: [], error: `Something went wrong, inner issue!`} + } + + + + + + console.log("code 2 here:"+str) + if(preprocessor.errors.length > 0){ + Errorcalm.printError(preprocessor.errors) + // force exit + return + } + // preprocessor.detectLabels(str) + + // console.log("code 2 here:"+str) + // if(preprocessor.errors.length > 0){ + // Errorcalm.printError(preprocessor.errors) + // // force exit + // return + // } + // str = preprocessor.removeAndReplaceLabels(str) + + console.log("code 4 here:"+str) + + + + } + +} \ No newline at end of file diff --git a/src/assets/Group16.png b/src/assets/Group16.png new file mode 100644 index 0000000..9770ad5 Binary files /dev/null and b/src/assets/Group16.png differ diff --git a/src/codemirror/mode/myLang/assembly.js b/src/codemirror/mode/myLang/assembly.js index 526754e..6b30980 100644 --- a/src/codemirror/mode/myLang/assembly.js +++ b/src/codemirror/mode/myLang/assembly.js @@ -1,5 +1,5 @@ import define from 'requirejs' -import CodeMirror from 'codemirror' +import CodeMirror from 'codemirror' (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS @@ -14,11 +14,18 @@ import CodeMirror from 'codemirror' })(function(CodeMirror) { CodeMirror.defineMode("8086", function(config, parserConfig) { - var keywords = ["mov", "add", "sub", "mul", "div", "jmp", "call", "ret", "push", "pop", "label", "bri", "be", "bne", "bs", "bi", "bse", "bie", "ror", "rol", "shr", "shl"]; - var registers = ["r1", "r2", "r3", "r4", "idr", "br", "sr", "acc", "r1l", "r1h", "r2l", "r2h", "r3l", "r3h", "accl", "acch"]; + var keywords = ["mov", "add", "sub", "mul", "div", "jmp", "call", "ret", "push", "pop", + "label", "bri", "be", "bne", "bs", "bi", "bse", "bie", "ror", "rol", + "shr", "shl", "read", "write"]; // Added "read" and "write" + + var registers = ["r1", "r2", "r3", "r4", "idr", "br", "sr", "acc", "r1l", "r1h", "r2l", + "r2h", "r3l", "r3h", "accl", "acch"]; + var number = /-?(?:0x[0-9a-f]+|\d+)/i; + function tokenBase(stream, state) { var ch = stream.next(); + if (ch === "/") { if (stream.eat("")) { state.tokenize = tokenComment; @@ -29,69 +36,68 @@ import CodeMirror from 'codemirror' return "comment"; } } + if (ch === ";" || ch === "#") { stream.skipToEnd(); return "comment"; } + if (/[a-zA-Z_]/.test(ch)) { stream.eatWhile(/[\w.]/); var cur = stream.current().toLowerCase(); - if (keywords.indexOf(cur) >= 0) { - return "key"; - } - if (registers.indexOf(cur) >= 0) { - return "reg"; - } - + if (keywords.indexOf(cur) >= 0) { + return "key"; // READ & WRITE will now be highlighted as instructions + } + if (registers.indexOf(cur) >= 0) { + return "reg"; } - if (/\d/.test(ch)) { + } + + if (/\d/.test(ch)) { stream.match(number); return "num"; - } + } if(/[@*]/.test(ch)){ return "opadr"; } if(/[[]]/.test(ch)){ - return "opadr" + return "opadr"; } + return null; + } - return null; - } - - function tokenComment(stream, state) { - let maybeEnd = false, ch; + function tokenComment(stream, state) { + let maybeEnd = false, ch; - while ((ch = stream.next())) { - if (ch === "/" && maybeEnd) { - state.tokenize = null; - break; + while ((ch = stream.next())) { + if (ch === "/" && maybeEnd) { + state.tokenize = null; + break; + } + maybeEnd = ch === ""; } - maybeEnd = ch === ""; + return "comment"; } - return "comment"; - } - - return { - startState: function() { - return { - tokenize: null, - }; - }, + return { + startState: function() { + return { + tokenize: null, + }; + }, - token: function(stream, state) { - if (state.tokenize) { - return state.tokenize(stream, state); - } - - return tokenBase(stream, state); - }, - }; + token: function(stream, state) { + if (state.tokenize) { + return state.tokenize(stream, state); + } + return tokenBase(stream, state); + }, + }; }); -}); \ No newline at end of file +}); diff --git a/src/components/AdressingModeListing/index.jsx b/src/components/AdressingModeListing/index.jsx index af31173..9887747 100644 --- a/src/components/AdressingModeListing/index.jsx +++ b/src/components/AdressingModeListing/index.jsx @@ -4,7 +4,6 @@ import "./style.css" const AdressingModeListing = ({name, imagePath, open}) => { - console.log(imagePath); return ( <> { const handleSubmit = (e) => { //prevent the form from reloading the page e.preventDefault(); - console.log(document.querySelector('.auth-button').disabled); document.querySelector('.auth-button').disabled = true; //get the form error div const formError = document.getElementById('form-error') @@ -37,8 +36,7 @@ const AuthForm = ({currentRoute, redirectRoute, updateCurrentUser}) => { navitage('/check-email'); return; } - console.log(user) - + if(currentRoute === '/login' && !user.confirmed){ formError.innerText = "Confirm your email first!" return; @@ -55,7 +53,6 @@ const AuthForm = ({currentRoute, redirectRoute, updateCurrentUser}) => { }) .catch(err => { //show the error in the front - console.log(err) if(!err.response.data.message){ formError.innerText = "Unknown Server error"; } diff --git a/src/components/ComponentsListing/index.jsx b/src/components/ComponentsListing/index.jsx index f4d4853..d650e1a 100644 --- a/src/components/ComponentsListing/index.jsx +++ b/src/components/ComponentsListing/index.jsx @@ -2,8 +2,7 @@ import React from "react"; import {motion} from "framer-motion"; import "./style.css" const ComponentsListing = ({ name, imagepath, imageHeight, open }) => { - console.log(imagepath) - + return ( <> - +
diff --git a/src/components/Exercices/Level2/level2.jsx b/src/components/Exercices/Level2/level2.jsx index f4bc83b..1f91bea 100755 --- a/src/components/Exercices/Level2/level2.jsx +++ b/src/components/Exercices/Level2/level2.jsx @@ -231,7 +231,7 @@ function Level2() { return (
- +
diff --git a/src/components/Exercices/Level3/level3.jsx b/src/components/Exercices/Level3/level3.jsx index 33bcfcd..09584f2 100755 --- a/src/components/Exercices/Level3/level3.jsx +++ b/src/components/Exercices/Level3/level3.jsx @@ -116,7 +116,7 @@ function Level3() { return (
- +
diff --git a/src/components/Exercices/Level4/level4.jsx b/src/components/Exercices/Level4/level4.jsx index db4be51..e9fe740 100755 --- a/src/components/Exercices/Level4/level4.jsx +++ b/src/components/Exercices/Level4/level4.jsx @@ -115,7 +115,7 @@ function Level4() { }; return (
- +
diff --git a/src/components/NavBar/index.jsx b/src/components/NavBar/index.jsx index d2a57dc..13267b1 100644 --- a/src/components/NavBar/index.jsx +++ b/src/components/NavBar/index.jsx @@ -1,27 +1,51 @@ -import { Link } from "react-router-dom"; -import logo from "../../assets/images/logos/logo.png" +import { Link , useNavigate} from "react-router-dom"; +import logo from "../../assets/Group16.png" +import pic from "../../pages/Profile/sample.jpg" import "./style.css"; +const NavBar = (props) => { + // we need to be redirected to signup / login forms or profile on click + const navigate = useNavigate(); -const NavBar = () => { + const handleLoginClick = () => { + navigate('/login'); + } + + const handleSignUpClick = () => { + navigate('/register'); + } - return ( + const handleProfile = () => { + navigate("/profile") + } + if(!props.isLoggedIn){ + return ( + + + ) + } else { + return ( - - ); } export default NavBar; \ No newline at end of file diff --git a/src/components/NavBar/style.css b/src/components/NavBar/style.css index 1f49513..2a06e47 100644 --- a/src/components/NavBar/style.css +++ b/src/components/NavBar/style.css @@ -1,64 +1,140 @@ -.navbar{ +body{ + font-family: lato, sans-serif; + align-items: center; + justify-content: center; + background-color: #0B1215; +} +.navbar-container{ display: flex; + flex-direction: row; + position: relative; + justify-self: center; + align-self: center; align-items: center; - flex-wrap: wrap; - gap: 25%; - background-color: #1BE985; - padding: 0 3.1rem; - box-shadow: 0 5px 15px #000, 0 30px 30px rgba(0, 0, 0, 0.08), - 0 15px 15px rgba(0, 0, 0, 0.08), 0 10px 8px rgba(0, 0, 0.08), - 0 4px 4px rgba(0, 0, 0, 0.08), 0 2px 2px rgba(0, 0, 0, 0.08); - border-radius: 2.5rem; - margin: 1% auto; - + justify-content: center; + border-radius: 72px; + border: 2px solid #000; + background: #1BE985; + width: 90%; + height: 70px; + flex-shrink: 0; position: sticky; - top: 1%; - width: 75%; + top: 2%; z-index: 10; } +.website-logo{ + position: absolute; + left: 2%; + top: 50%; + transform: translate(0, -50%); + width: 15%; + height: auto; +} -.links{ - width: 60%; +.website-logo img{ + width: 80%; + height: auto; + justify-self: end; + align-self: center; +} +.navbar-container ul{ + justify-self: center; + align-self: center; + display: flex; + flex-direction: row; + list-style-type: none; + margin: 1%; + padding: 1%; + gap: 20px; } -.links ul{ +.navbar-container ul li { + margin: 0 30px; + text-decoration: none; display: flex; + flex-direction: column; + height: 100%; align-items: center; - justify-content: space-between; } -.a { - text-decoration: none; - list-style: none; - position: relative; - display: block; + +.navbar-container ul li, li:focus, li:active, li::before, li::after { + outline: none; + border: none; +} + +/*we should fix this later, Idk how it works*/ +.navbar-container ul li .circle{ + border-radius: 50%; + background-color: #000000; + width: 0px; + height: 0px; + margin-top: -5px; + opacity: 0; + transform: scale(0); + transition: all 0.5s ease-in-out; +} + +.navbar-container ul li a{ font-size: 1.25rem; - font-weight: 900; - color: #24292E; - font-family: 'Mona Sans', system-ui; + font-weight: bold; + color: rgb(0, 0, 0); + text-decoration: none; + transition: 0.5s ease-in-out; +} + +.navbar-container ul li a:active, a::after{ + text-decoration: none; + color: rgb(0, 0, 0); } -.a :after{ - content: ""; - width: 0%; - height: 2px; - display: block; - margin-top: auto; - align-items: center; - transition: 0.5s; +.navbar-container ul li a:hover{ + color: #000000; + text-decoration: none; + + font-size: calc(1.25rem + 0.5vw); } -.a :hover::after{ - width: 100%; - background:#24292E; + +/* here we should add the circles that appear below the option hovered over*/ +.navbar-container ul li:hover .circle{ + height: 8px; + width: 8px; + visibility: visible; + transition: all 0.5s ease-in-out; + opacity: 1; + transform: scale(1); } -.a li{ - display: inline-block; - font-weight: 900; - font-size: 1.875rem; - transition: 1s; + +.navbar-container .signup{ + position: absolute; + right: 1%; + border-radius: 72px; + height: calc(100% - 19px); + width: calc(10% - 20px); + border: 2px solid #272626; + background: #D2F6E3; + backdrop-filter: blur(50px); + + font-size: 1.15rem; + font-weight: bold; +} + +.navbar-container .signup:hover{ + cursor: pointer; } -.a li:hover{ - transform: scale(1.3,1.3); + +.navbar-container .login{ + position: absolute; + right: 11%; + background-color: transparent; + border: none; + font-size: 1.2rem; + font-weight: bold; +} + +.navbar-container .login:hover{ + cursor: pointer; + } diff --git a/src/components/ProgramContainer/index.jsx b/src/components/ProgramContainer/index.jsx index df76ded..81f8187 100644 --- a/src/components/ProgramContainer/index.jsx +++ b/src/components/ProgramContainer/index.jsx @@ -6,7 +6,6 @@ import './style.css' import { useNavigate } from 'react-router-dom' const ProgramContainer = ({userId, program, removeProgram}) => { - console.log("program",program) const navigate = useNavigate(); const handleDeleteProgram = (e) => { @@ -16,11 +15,9 @@ const ProgramContainer = ({userId, program, removeProgram}) => { axios.delete(URL) .then(response => { - console.log(response); - removeProgram(program); + removeProgram(program); }) .catch(err => { - console.log(err); alert("Failed to delete program!") }) } diff --git a/src/components/SaveCodeButton/index.jsx b/src/components/SaveCodeButton/index.jsx index d788bf8..f72af60 100644 --- a/src/components/SaveCodeButton/index.jsx +++ b/src/components/SaveCodeButton/index.jsx @@ -13,19 +13,16 @@ const SaveCodeButton = ({code, currentUser, editMode}) => { return; } - console.log("Saving your code..."); - // console.log(code) isEditMode + // console.log(code) isEditMode const URL = process.env.REACT_APP_API_URL+`/user/${currentUser.id}/code` + (editMode.isEditMode === true ? "/edit" : "/add") if(editMode.isEditMode === true){ axios.put(URL, {id: editMode.programId,code}) .then(res => { - console.log(res); alert(`Program "${editMode.programName}" updated successfully`); }) .catch(err => { - console.log(err); alert("Program update failed!"); }) }else{ @@ -38,11 +35,9 @@ const SaveCodeButton = ({code, currentUser, editMode}) => { axios.post(URL, {code, name: programName}) .then(res => { - console.log(res) alert("Your code has been saved successfully!") }) .catch(err => { - console.log(err); alert("Program save failed!"); }) } diff --git a/src/components/loginForm/index.jsx b/src/components/loginForm/index.jsx new file mode 100644 index 0000000..9c637ba --- /dev/null +++ b/src/components/loginForm/index.jsx @@ -0,0 +1,91 @@ +import NavBar from "../NavBar/index.jsx" +import "./login.css" +import { useState } from "react" +import { useNavigate } from "react-router-dom" +function LoginForm(){ + const [email, setEmail] = useState("") + const [password, setPassword] = useState("") + const navigate = useNavigate() + const submitInfo = async (e) => { + + const emailField = document.getElementById("email") + const passwordField = document.getElementById("password") + e.preventDefault() + // if one of the fields is empty, set the border to red and return + if(email === "" || password === ""){ + + emailField.style.border = "1px solid red" + passwordField.style.border = "1px solid red" + alert("Please fill in all fields") + return + + } else { + emailField.style.border = "1px solid black" + passwordField.style.border = "1px solid black" + } + // now we can send the data to the server + // first verify if we have a valid email + const isEmail = (val) => { + const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return regex.test(val); + } + if(!isEmail(email)){ + emailField.style.border = "1px solid red" + alert("Please enter a valid email") + return + } + // now we are ready to send the data to the server + const res = await fetch("http://localhost:5000/login", { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ + email: email, + password: password + }) + }) + if(!res.ok){ + const err = await res.json() + alert(err.error) + emailField.style.border = "1px solid red" + passwordField.style.border = "1px solid red" + return + } + // now we have a valid response, we shall parse it and navigate to profile + const data = await res.json() + console.log(data) + // fetch here + + //get result, store token in local storage, then redirect to profile + //then store in local storage + data.modified ??= false + localStorage.setItem("user", JSON.stringify({data: data, isLoggedIn: true})) + localStorage.setItem("loginState", JSON.stringify(true)) + //navigate to profile page or wherever + navigate("/profile") + } + + + return( + <> + +
+

Login

+
+ + setEmail(e.target.value)}> +
+
+ + setPassword(e.target.value)}> +
+

+ + +
+ + ) +} + +export default LoginForm \ No newline at end of file diff --git a/src/components/loginForm/login.css b/src/components/loginForm/login.css new file mode 100644 index 0000000..061d687 --- /dev/null +++ b/src/components/loginForm/login.css @@ -0,0 +1,72 @@ + +#loginForm{ + + justify-self: center; + align-self: center; + background-color: white; + margin: 50px 5px; + border: 2px solid black; + color: black; + /*border-radius: 10px; */ + width: 400px; + height: 450px; + padding: 30px 15px; + position: relative; + display: flex; + flex-direction: column; + justify-content: center; + +} + +.infoContainer{ + display: flex; + flex-direction: column; + justify-content: center; + text-align: left; + margin: 20px 0 0 0; +} +#loginForm h1{ + align-self: center; + margin: 25px 30px; +} + +#loginForm label{ + margin-left: 15%; +} + +#loginForm input{ + height: 45px; + width: 70%; + + align-self: center; + +} + +#loginForm button{ + width: 65%; + height: 45px; + align-self: center; + margin-top: auto; + margin-bottom: 30px; + border: none; + font-size: 18px; + padding: 5px 8px; + color: white; + background-color: #12b264; + transition: all ease-in-out .5s; +} + +#loginForm button:hover{ + background-color:hsl(151, 86%, 22%); + cursor: pointer; + +} + +#loginForm input { + outline: none; + border: 1px solid grey; + border-radius: 4px; + margin: 8px 8px; + font-size: 1.05rem; + padding: 3px 3px; +} diff --git a/src/components/profileNav/index.jsx b/src/components/profileNav/index.jsx new file mode 100644 index 0000000..f71f917 --- /dev/null +++ b/src/components/profileNav/index.jsx @@ -0,0 +1,22 @@ +import "./profileNav.css" +import logo from "../../assets/Group16.png" +import { Link } from "react-router-dom" +function ProfileNav(props){ + return( + <> + + + ) +} + +export default ProfileNav \ No newline at end of file diff --git a/src/components/profileNav/profileNav.css b/src/components/profileNav/profileNav.css new file mode 100644 index 0000000..aa44e03 --- /dev/null +++ b/src/components/profileNav/profileNav.css @@ -0,0 +1,71 @@ +.vertical-navbar{ + margin: 3%; + position: relative; + width: 296px; + height: auto; + flex-shrink: 0; + border-radius: 24px; + border: 2px solid #000; + background: #1BE985; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + +} + +.vertical-navbar .calM-logo img{ + position: absolute; + margin: 20px 10px; + width: 80%; + height: auto; + align-self: center; + left: 50%; + top: 5%; + transform: translate(-50%, -50%); +} + +.vertical-navbar ul{ + list-style: none; + padding: 10% 50%; +} +.vertical-navbar ul{ + margin-top: 30%; +} +.vertical-navbar ul li{ + display: flex; + align-items: center; + padding: 0 8px; + margin: 40px 0; + height: 45px; + width: 100%; + transform: all 0.5s ease-in-out; + border-radius: 8px; +} + +.vertical-navbar ul li a{ + margin: 50px 0; + font-size: 1.2rem; + font-weight: bold; + color: #000; + text-decoration: none; + cursor: pointer; + transition: all 0.5s ease-in-out; + + } + + /* change and fix colors here later*/ + +.vertical-navbar ul li:hover{ + background: rgba(11, 18, 21, 0.17); + cursor: pointer; + transition: all 0.5s ease-in-out; + +} + + .vertical-navbar ul li a:active, a::after{ + color: #000; + text-decoration: none; + cursor: pointer; + transition: all 0.3s ease-in-out; +} \ No newline at end of file diff --git a/src/components/signUpForm/index.jsx b/src/components/signUpForm/index.jsx new file mode 100644 index 0000000..3e63172 --- /dev/null +++ b/src/components/signUpForm/index.jsx @@ -0,0 +1,118 @@ +import "./signup.css" +import NavBar from "../NavBar/index.jsx" +import { useState } from "react" +import { use } from "react" +function SignUpForm(){ + const [name, setName] = useState("") + const [lastName, setLastName] = useState("") + const [age, setAge] = useState("") + const [email, setEmail] = useState("") + const [username, setUsername] = useState("") + const [password, setPassword] = useState("") + const [confirmPassword, setConfirmPassword] = useState("") + const [gender, setGender] = useState("") + + + const handleNameChange = (e) => setName(e.target.value) + const handleLastNameChange = (e) => setLastName(e.target.value) + const handleAgeChange = (e) => setAge(e.target.value) + const handleEmailChange = (e) => setEmail(e.target.value) + const handleUsernameChange = (e) => setUsername(e.target.value) + const handlePasswordChange = (e) => setPassword(e.target.value) + const handleConfirmPasswordChange = (e) => setConfirmPassword(e.target.value) + const handleGenderChange = (e) => setGender(e.target.value) + + const isEmail = (val) => { + const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return regex.test(val); + } + + const submitInfo = async (e) => { + e.preventDefault() + if(name === "" || lastName === "" || age === "" || email === "" || username === "" || password === "" || confirmPassword === ""){ + alert("Please fill in all fields") + // I might probably highlight the fields that are empty in red + return + } + + if(!isEmail(email)){ + alert("Please enter a valid email address") + return + } + + if(password !== confirmPassword){ + alert("Passwords do not match") + return + } + if(password.length < 8){ + alert("Password must be at least 8 characters long") + return + } + + + const data = { + name: name, + lastName: lastName, + age: Number(age), + email: email, + username: username, + password: password, + confirmPassword: confirmPassword, + } + + console.log(data) + + const res = await fetch("http://localhost:5000/signup", { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(data) + }) + if(!res.ok){ + alert("Error signing up") + return + } + const genData = await res.json() + + genData.modified ??= false + + localStorage.setItem("user", JSON.stringify(genData)) + localStorage.setItem("loginState", JSON.stringify(true)) + // verify email + + //after verification is done, redirect to profile page + } + + + + return ( + <> + +
+

Sign Up

+
+ + + +
+ +
+ + + + + +
+ + +
+ + ) +} + +export default SignUpForm \ No newline at end of file diff --git a/src/components/signUpForm/signup.css b/src/components/signUpForm/signup.css new file mode 100644 index 0000000..51a7a96 --- /dev/null +++ b/src/components/signUpForm/signup.css @@ -0,0 +1,85 @@ + + +#signUpForm{ + border: 2px solid black; + background-color: white; + align-self: center; + justify-content: center; + width: 60%; + align-self: center; + justify-self: center; + text-align: center; + margin-top: 50px; + border-radius: 5px; + color: black; +} + + +#signUpForm .inputs{ + align-items: center; + justify-content: center; + display: grid; + grid-template-columns: repeat(2, 1fr); + width: 100%; + height: auto; +} + +#signUpForm .inputs input, .gender{ + width: 80%; + height: 45px; + margin: 10px auto; + border-radius: 5px; + border: 1px solid grey; + outline: none; + padding: 3px 10px; +} + +#signUpForm .inputs input:focus{ + border: 1px solid black; +} + + +#signUpForm button{ + width: 20%; + height: 45px; + align-self: center; + margin-top: auto; + margin-bottom: 30px; + border: none; + font-size: 18px; + padding: 5px 8px; + color: white; + background-color: #12b264; + + margin-top: 30px; + transition: all ease-in-out .5s; +} + +#signUpForm .gender{ + display: flex; + justify-content: left; +} + +#signUpForm .inputs select { + width: 100%; + height: 100%; + margin: 10px auto; + border-radius: 5px; + border: 1px solid grey; + outline: none; + padding: 0; + border: none; + outline: none; + justify-self: center; + align-self: center; +} + +#signUpForm button:hover{ + background-color:#0a713f; + cursor: pointer; + + +} + + + diff --git a/src/index.css b/src/index.css index 83b564d..897a869 100644 --- a/src/index.css +++ b/src/index.css @@ -1,9 +1,9 @@ @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@500&display=swap'); @import url('https://fonts.cdnfonts.com/css/mona-sans'); @import url('https://fonts.cdnfonts.com/css/hubot-sans'); - +@import url('https://fonts.googleapis.com/css2?family=Cairo:wght@200..1000&family=Gugi&family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&family=Noto+Serif+JP:wght@200..900&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap'); @font-face { - font-family: "Mona Sans"; + font-family: 'lato',"Mona Sans"; src: url("assets/font/Mona-Sans.woff2") format("woff2 supports variations"), url("assets/font/Mona-Sans.woff2") format("woff2-variations"); font-weight: 200 900; font-stretch: 75% 125%; diff --git a/src/pages/Arch/index.jsx b/src/pages/Arch/index.jsx index e93825c..328db75 100644 --- a/src/pages/Arch/index.jsx +++ b/src/pages/Arch/index.jsx @@ -16,7 +16,8 @@ let [IPval,setipval]=useState(0); let [AluVal,setAluVal]=useState(""); let [MCVal,setMCVal]=useState(""); -let MC=props.mem.getData(); +let MC= props.mem.getData(); +console.log("yokosooooo hereeee's",MC) let tablec=[]; MC.forEach((element,index) => { tablec.push( @@ -66,7 +67,7 @@ MC.forEach((element,index) => { //decalage par 1 gsap.fromTo(".queuearrow",{top:"60%",left:"83%",opacity:"0"},{top:"60%",left:"73%",opacity:"1",duration:0.3}); gsap.to(".queuearrow",{opacity:"0",duration:"0.1",delay:"0.3"}); - if(animqueuelen()==6){ + if(animqueuelen() == 6){ gsap.to(".queue6",{opacity:"0",duration:0.4}) gsap.to(".queue5",{opacity:"1",duration:0.4}) gsap.to(".queue4",{opacity:"1",duration:0.4}) diff --git a/src/pages/ExamplesPage/index.jsx b/src/pages/ExamplesPage/index.jsx index cfb1de0..b0f4fcc 100644 --- a/src/pages/ExamplesPage/index.jsx +++ b/src/pages/ExamplesPage/index.jsx @@ -36,7 +36,7 @@ const ExamplesPage = () => { return ( <> - +
diff --git a/src/pages/ExercicesPage/index.jsx b/src/pages/ExercicesPage/index.jsx index 1432396..2ebd4bf 100644 --- a/src/pages/ExercicesPage/index.jsx +++ b/src/pages/ExercicesPage/index.jsx @@ -14,7 +14,7 @@ import Bot from "../../components/ChatBot"; function ExercicesPage(props) { return ( <> - + {/*
</main> */} diff --git a/src/pages/Hero/index.jsx b/src/pages/Hero/index.jsx index b6fe03c..76bdd4c 100644 --- a/src/pages/Hero/index.jsx +++ b/src/pages/Hero/index.jsx @@ -25,6 +25,7 @@ import { useNavigate } from "react-router-dom"; const Hero = () => { + console.log(JSON.parse(localStorage.getItem("loginState")) || false) const Part1 = () => { return ( <section className="slogan-container"> @@ -222,7 +223,7 @@ const Hero = () => { }) let navigate = useNavigate(); return < > - <NavBar/> + <NavBar isLoggedIn={true}/> <main id="get-started-container" style={{position: "relative", height: "10%"}}> <Title/> diff --git a/src/pages/Ide/index.jsx b/src/pages/Ide/index.jsx index e18c69d..1942f08 100644 --- a/src/pages/Ide/index.jsx +++ b/src/pages/Ide/index.jsx @@ -5,7 +5,7 @@ import UAParser from 'ua-parser-js'; import "./style.css" ///// import components ////// -import { NavBar, HelpSection, SaveCodeButton } from "../../components" +import { NavBar, HelpSection, SaveCodeButton } from "../../components/index.js" ////// import machine components ////// @@ -24,10 +24,10 @@ import "../../codemirror/theme/material.css"; import "../../codemirror/mode/myLang/assembly.js" /////import assembler modules////////// -import { Assembler } from "../../assembler/Assembler"; -import {helpDescription} from "../../Constants/HelpDescription"; -import {HexaToCode} from "../../HexaToCode/HexaToCode" -import { Errorcalm } from "../../assembler/Errorcalm"; +import { Assembler } from "../../assembler/Assembler.js"; +import {helpDescription} from "../../Constants/HelpDescription.js"; +import {HexaToCode} from "../../HexaToCode/HexaToCode.js" +import { Errorcalm } from "../../assembler/Errorcalm.js"; import { useLocation } from 'react-router-dom'; import { useEffect } from 'react'; @@ -37,7 +37,7 @@ let animations=[]; let Contextarray=[]; ////////////////machine declarations//////////////////////////////// -let memory=new MC(); +let memory = new MC(); let sequenceur=new Sequenceur(); let queue = new Queue(); let addressingModes=new AddressingModes(); @@ -60,7 +60,7 @@ const handleRefresh = () => { function convertStrings(arr) { const result = [] ; for (let i = 0; i < arr.length; i++) { - for (let j = 0; j < arr[i].length; j += 2) { + for (let j = 0; j < arr[i]?.length || 0; j += 2) { result.push(arr[i][j] + arr[i][j+1]); } } @@ -75,7 +75,7 @@ const Ide = ({currentUser})=>{ let [simul,setsimul]=useState(false) let [memo,setmemo]=useState(false); let [reg,setreg]=useState(false); - let [stk,setstk]=useState(false);//for showing stack + let [stk,setstk]=useState(false); //for showing stack let [isHexa,setIsHexa]=useState(false); let [iscode,setIsCode]=useState(true); let [iserr,seterr]=useState(false); @@ -107,6 +107,7 @@ const Ide = ({currentUser})=>{ console.log(queue.getinstwithoutshift()) let instrobject={}; + memory.data = MC.data while(instrobject.name!=="stop"){ sequenceur.getinstrbyte(animations,true,Contextarray); instrobject={...sequenceur.decode(animations,Contextarray)}; @@ -121,6 +122,7 @@ const Ide = ({currentUser})=>{ let [checktest,setChecktest]=useState(false); /////////////////////returning the component////////////////// + let tablec=[]; memory.getData().forEach( (element,index) => { tablec.push( @@ -169,7 +171,7 @@ const Ide = ({currentUser})=>{ const handleStoreCode = () => { const editor = codeMirrorRef.current.editor; const code = editor.getValue(); // Get the current content of the editor - + // Split the code into lines const lines = code.split('\n'); @@ -194,7 +196,7 @@ const Ide = ({currentUser})=>{ if (lineWithoutComment !== '') { // If the line without comments is not empty, store it in codeArray - codeArray.push(lineWithoutComment.toUpperCase()); + codeArray.push(lineWithoutComment); } }); @@ -252,7 +254,7 @@ const Ide = ({currentUser})=>{ <> {!simul && <> - <NavBar/> + <NavBar isLoggedIn={true}/> <div style={{display:"flex"}} className="ide_container"> <div className='codeContainer' id="cont"> @@ -332,24 +334,40 @@ const Ide = ({currentUser})=>{ className='ide-exec-button' onClick={()=>{ setdone(true); - let inputouter=[]; + let inputouter; if(iscode){ + console.log(handleStoreCode) inputouter=Assembler.assemblecode(handleStoreCode()) + }else{ inputouter=handleStoreCode(); } - let input=convertStrings(inputouter); + console.log("inputouter",inputouter); + console.log(inputouter.error) + //here I must check for errors, if there are any, we must quit, but quitting is causing an undefined return from somewhere!! + // we shall figure out a solution and put this block back once again + if(inputouter.error !== ''){ + setresult(inputouter.error); + seterr(true); + return + } + + let input=convertStrings(inputouter.code); + // not checked yet + memory.data = inputouter.memory; input.push("ff"); - try { - if (Errorcalm.errorr === 0) { + console.log("drsas") traitement(input); - + }else{ + console.log("SIks") setresult(Errorcalm.printError()); + + seterr(true); } @@ -360,7 +378,7 @@ const Ide = ({currentUser})=>{ setresult("this is not hexa code"); } - + }}> execute </button> @@ -385,10 +403,8 @@ const Ide = ({currentUser})=>{ console.log(arr); console.log("old arr=",arr); localStorage.setItem('arr', JSON.stringify(arr)); - console.log("current local storage : ",localStorage.getItem('arr')) window.location.reload(); }}>re-write</button> - {!iserr &&< button className='ide-exec-button' onClick={()=>{ diff --git a/src/pages/LearnPage/index.jsx b/src/pages/LearnPage/index.jsx index 0eef369..550c8f2 100644 --- a/src/pages/LearnPage/index.jsx +++ b/src/pages/LearnPage/index.jsx @@ -17,7 +17,7 @@ import Bot from "../../components/ChatBot"; function LearnPage() { return ( <> - <NavBar/> + <NavBar /> <img src={LearnTitle} className="learnTitle" alt="" /> <div className="globalContainerLearn"> diff --git a/src/pages/Login/index.jsx b/src/pages/Login/index.jsx index 5b06f05..5477782 100644 --- a/src/pages/Login/index.jsx +++ b/src/pages/Login/index.jsx @@ -1,9 +1,11 @@ import React from 'react' import {AuthForm} from '../../components/' +import LoginForm from '../../components/loginForm/index.jsx' const Login = ({updateCurrentUser}) => { return ( - <AuthForm currentRoute='/login' redirectRoute='/register' updateCurrentUser={updateCurrentUser}/> + + <LoginForm /> ) } diff --git a/src/pages/Profile/index.jsx b/src/pages/Profile/index.jsx index 0e60baa..7464ec2 100644 --- a/src/pages/Profile/index.jsx +++ b/src/pages/Profile/index.jsx @@ -1,125 +1,171 @@ -import React, { useEffect, useState } from 'react' -import { Link } from "react-router-dom"; -import { NavBar } from '../../components' -import './style.css' -import axios from 'axios' -import { useNavigate } from 'react-router-dom' -import { ProgramContainer } from '../../components'; -import { motion } from 'framer-motion'; -import {Footer} from "../../containers"; - -const Profile = ({currentUser, updateCurrentUser}) => { - const navigate = useNavigate(); - const [programs, setPrograms] = useState(null); +import "./profile.css" +import ProfileNav from "../../components/profileNav/index.jsx" +import pic from "./sample.jpg" +import { useState } from "react" +import { color } from "framer-motion" +import { red } from "@mui/material/colors" +function Profile(){ + const user = localStorage.getItem('user') + const {data} = JSON.parse(user) - useEffect( () => { - if(currentUser === null) return; - - const URL = process.env.REACT_APP_API_URL + `/user/${currentUser.id}/code/all`; + const [hoveredOverConfirm,setHoveredOverConfirm] = useState(false) + const [hoveredOverCancel,setHoveredOverCancel] = useState(false) + const Hover = (e) => { + if(e === 1){ + setHoveredOverConfirm(true) + } else { + setHoveredOverCancel(true) + } - axios.get(URL) - .then((response) => { - console.log(response.data.data); - setPrograms(response.data.data); - }) - .catch((error) => { - console.error(error); - alert("Failed to load programs... Please try again"); - }); - }, [currentUser]); + } + const unhover = (e) => { + if(e === 1){ + setHoveredOverConfirm(false) + } else { + setHoveredOverCancel(false) + } + } + const [name, setName] = useState(data.name) + const [username, setUsername] = useState(data.username) + const [age, setAge] = useState(data.age) + const [email, setEmail] = useState(data.email) + const [lastName, setLastName] = useState(data.lastName) + const [gender, setGender] = useState(data.gender) + const [university, setUniversity] = useState("") + const [yearOfStudy, setYearOfStudy] = useState("") + const [popUp, setPopUp] = useState(false) + const [attribute, setAttribute] = useState("") + const [type, setType] = useState("text") + const editName = () => { + setAttribute("Name") + setType("text") + setPopUp(true) - const handlePasswordResetRequest = (e) => { - const URL = process.env.REACT_APP_API_URL + `/reset-password/request/${currentUser.id}`; + } - axios.post(URL) - .then(response =>{ - navigate('/reset-password/email-sent'); - }) - .catch(error =>{ - console.log(error); - alert("Request failed, please try again."); - }) + const editLastName = () => { + setAttribute("last name") + setType("text") + setPopUp(true) } - const logout = () => { - const URL = process.env.REACT_APP_API_URL + '/logout'; - axios.post(URL) - .then(res => { - updateCurrentUser(null); - localStorage.removeItem('user'); - navigate('/'); - }) - .catch(err => { - console.log(err); - alert("Logout Failed, server isn't responding"); - }) + const editAge = () => { + setAttribute("age") + setType("number") + + setPopUp(true) } - const removeProgram = (targetProgram) => { - setPrograms(programs.filter(program => program.id !== targetProgram.id)) + const editEmail = () => { + setAttribute("email") + setType("email") + setPopUp(true) + // then verify!! + } - return ( - <> - <NavBar /> - <div className='profile-container'> - {!currentUser - ? - <> - <h1 className='profile-title'>No user is logged in</h1> - <p>You can login <Link to="/login">here</Link></p> - </> - : - <> + const editUniversity = () => { + setAttribute("university") + setType("text") + setPopUp(true) + } - <div className="profile-info-container"> - <h1 className='profile-title'>Profile Information</h1> - <div style={{ padding: "1rem"}}> - <p>Email: {currentUser.email}</p> - <p>Score: {currentUser.score}</p> + const editUsername = () => { + setAttribute("university") + setType("text") + setPopUp(true) + //requires verifying uniqueness + } - </div> - <p>Saved Programs</p> - {programs === null - ? <p>Loading programs...</p> - : programs.length === 0 - ? - <p>No programs saved for this profile!</p> - : - <div className="program-container"> - { - programs.slice(0).reverse().map(program => - <ProgramContainer key={program.id} program={program} - removeProgram={removeProgram} userId={currentUser.id}/> - ) - } - </div> - } - </div> - + const editYearOfStudy = () => { + setAttribute("university") + setType("text") + setPopUp(true) + } + const Done = () => { + // save changes then close + setPopUp(false) + } + const Cancel = () => { + setPopUp(false) + } + const Logout = async () => { + // handle logout here + } - <div className='buttons-container'> - <motion.button className='profile-button' - onClick={handlePasswordResetRequest} - whileHover={{scale: 1.1}} - whileTap={{scale: 0.9}} - transition={{type: "spring", stiffness: 400, damping: 17}} - >Reset Password</motion.button> - <motion.button - whileHover={{scale: 1.1}} - whileTap={{scale: 0.9}} - transition={{type: "spring", stiffness: 400, damping: 17}} - className='profile-button' - onClick={logout}>Logout</motion.button> - </div> - </> - } - - + return( + <div className="container-profile"> + <ProfileNav className="navbar" home = "/"/> + <div className="personal-information"> + <div className="profile-picture" > + <img alt="profile picture" src={pic}></img> + <div className="personal-title"> + <h2>{`${name} ${lastName}` || "Full name"}</h2> + <h4>calM-ID: { ` ${username}` || " "}</h4> + </div> + <button id="logout-button" onClick={ Logout }>Logout</button> </div> - <Footer/> - </> + + <div className="basic-info"> + <h1>Basic information</h1> + <table> + <tbody> + <tr> + <td>Name:</td> + <td><p className="information">{`${name }` || "Lorem ipsum"}</p></td> + <td><button className="edit" onClick={editName}>Edit</button></td> + </tr> + <tr> + <td>LastName:</td> + <td><p className="information">{`${lastName}` || "Lorem ipsum"}</p></td> + <td><button className="edit" onClick={editLastName}>Edit</button></td> + </tr> + <tr> + <td>Username:</td> + <td><p className="information" >{username || "Lorem ipsum"}</p></td> + <td><button className="edit" onClick={editUsername}>Edit</button></td> + </tr> + <tr> + <td>Gender:</td> + <td><p className="information" >{gender || "Lorem ipsum"}</p></td> + </tr> + <tr> + <td>Age:</td> + <td><p className="information" >{age || "Lorem ipsum"}</p></td> + <td><button className="edit" onClick={editAge}>Edit</button></td> + </tr> + <tr> + <td>University:</td> + <td><p className="information" >{university || "Lorem ipsum"}</p></td> + <td><button className="edit" onClick={editUniversity}>Edit</button></td> + </tr> + <tr> + <td>Year of Study: </td> + <td><p className="information" >{yearOfStudy || "Lorem ipsum"}</p></td> + <td><button className="edit" onClick={editYearOfStudy}>Edit</button></td> + </tr> + <tr> + <td>Email: </td> + <td><p className="information">{email || "Lorem ipsum"}</p></td> + <td><button className="edit" onClick={editEmail}>Edit</button></td> + </tr> + </tbody> + </table> + </div> + </div> + { popUp &&( + <div className="edit-popUp"> + <label>Enter your new {attribute}:</label> + <input type={type} min={ type === "number" ? 10:""}></input> + <div className="confirm-buttons"> + <button onClick={Cancel} style={{backgroundColor: hoveredOverCancel ? "darkred":"red"}} onMouseEnter={() => Hover(0)} onMouseLeave={() => unhover(0)}>Cancel</button> + <button onClick={Done} style={{backgroundColor:hoveredOverConfirm ? "darkgreen":"#12b264"}} onMouseEnter={() => Hover(1)} onMouseLeave={() => unhover(1)}>Save changes</button> + </div> + </div> + )} + </div> + ) } -export default Profile +export default Profile \ No newline at end of file diff --git a/src/pages/Profile/profile.css b/src/pages/Profile/profile.css new file mode 100644 index 0000000..ac03c1d --- /dev/null +++ b/src/pages/Profile/profile.css @@ -0,0 +1,168 @@ + +.container-profile{ + width: 100%; + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; + color: black; + margin-bottom: 30px; +} + +.container-profile .personal-information{ + margin-top: 5%; + display: flex; + flex-direction: column; + border-radius: 10px; + align-items: center; + background-color: #C3F9DF; + width: 70%; + height: auto; + z-index: 10; +} + +.container-profile .personal-information .profile-picture{ + height: 15%; + width: 100%; + justify-content: flex-start; + display: flex; + flex-direction: row; + margin: 10px; + padding: 15px; +} + +.container-profile .personal-information .profile-picture img{ + border-radius: 10%; + width: calc(20% - 50px); + height: auto; + margin: 10px; + margin-left: 5%; + border: 2px solid #000; +} + +.container-profile .personal-information .profile-picture .personal-title{ + display: flex; + justify-self: center; + + flex-direction: column; + justify-content: flex-start; + align-items: center; + margin-right: auto; + margin-left: 10%; +} +.container-profile .personal-information .profile-picture .personal-title h2{ + font-size: 2rem; + margin-bottom: 5px; + +} + +.container-profile .personal-information .basic-info{ + width: 100%; + + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; + text-align: left; + +} +.container-profile .personal-information .basic-info h1{ + margin-left: 5%; +} + +.container-profile .personal-information .basic-info table,.container .personal-information .basic-info tbody{ + width: 100%; + border-collapse: collapse; + margin: 10px 0; + padding: 0 5%; +} + +.container-profile .personal-information .basic-info table tbody tr{ + width: 95%; + display: table-row; + justify-content: space-between; + align-items: center; + width: 100%; + padding: 10px 5%; + +} +.container-profile .personal-information .basic-info table tbody tr td{ + padding: 0 5%; + +} +.container-profile .personal-information .basic-info table tbody tr td button{ + background-color: transparent; + border: none; + color: rgba(0, 120, 62, 0.47); + font-size: 1.2rem; + margin-right: 5%; + margin-left: 15px; + cursor: pointer; +} + +.container-profile .personal-information .profile-picture #logout-button{ + background-color: red; + color: white; + width: 100px; + height: 45px; + margin: auto 5% auto 5%; + border: none; + font-size: 18px; + font-weight: semibold; + cursor: pointer; + align-self: center; + border-radius: 5px; + transition: all ease-in-out .5s; +} + +.container-profile .personal-information .profile-picture #logout-button:hover{ + background-color: hsl(0, 64%, 40%); + cursor: pointer; + transition: all ease-in-out .5s; +} + +.container-profile .edit-popUp{ + color: #0B1215; + position: absolute; + height: 30%; + width: 30%; + display: flex; + flex-direction: column; + background-color: white; + z-index: 200; + border-radius: 10px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + justify-content: center; + align-items: center; + box-shadow: 0 0px 50px 2px rgba(0, 0, 0, 0.5); +} +.container-profile .edit-popUp .confirm-buttons{ + display: flex; + flex-direction: row; + width: 100; + margin: 10% auto -5% auto; + +} +.container-profile .edit-popUp .confirm-buttons button{ + margin: 0 10px 0 10px; + border: none; + font-weight: 600; + height: 40px; + width: auto; + padding: auto 5px auto 5px; + color: white; + cursor: pointer; + border-radius: 5px; + transition: all ease-in-out .5s; +} +.container-profile .edit-popUp input{ + border-radius: 5px; + height: 30px; + width: 50%; + margin-top: 5px; + outline: none; + border: 1px solid black; + padding: 2px; +} diff --git a/src/pages/Profile/sample.jpg b/src/pages/Profile/sample.jpg new file mode 100644 index 0000000..0f9ff54 Binary files /dev/null and b/src/pages/Profile/sample.jpg differ diff --git a/src/pages/Profile/style.css b/src/pages/Profile/style.css deleted file mode 100644 index d59f6f6..0000000 --- a/src/pages/Profile/style.css +++ /dev/null @@ -1,154 +0,0 @@ -.profile-title { - align-self: center; - top: -1.85rem; - font-size: 2rem; - font-weight: 850; - color: white; - background-color: rgb(48, 54, 61); - border-radius: 1.5rem; - width: 20rem; - height: 3.5rem; - text-align: center; - line-height: 3.5rem; - border: 2px solid #1BE985; -} - -.program-card { - width: 50%; - display: flex; - justify-content: space-around; - height: fit-content; - align-self: center; - background-color: #263238; - margin-bottom: 2rem; - - border-radius: 2rem; - - box-shadow: 0 0 0 1px #000, 0 30px 30px rgba(0, 0, 0, 0.08), - 0 15px 15px rgba(0, 0, 0, 0.08), 0 10px 8px rgba(0, 0, 0.08), - 0 4px 4px rgba(0, 0, 0, 0.08), 0 2px 2px rgba(0, 0, 0, 0.08); - padding: 0.5rem; - border: 1px solid black; -} - -.profile-info-container{ - margin-top: 2rem; - display: flex; - flex-direction: column; - position: relative; - align-items: center; - justify-content: space-around; - width: 100%; - padding-top: 3rem; - border-radius: 2.5rem; - background-color: #24292e; - box-shadow: 0 0 0 0.5px #000, 0 30px 30px rgba(0, 0, 0, 0.08), - 0 15px 15px rgba(0, 0, 0, 0.08), 0 10px 8px rgba(0, 0, 0.08), - 0 4px 4px rgba(0, 0, 0, 0.08), 0 2px 2px rgba(0, 0, 0, 0.08); - - border: 2px solid #1BE985; - -} - -.program-container{ - display: flex; - flex-direction: column; - align-items: center; - justify-content: flex-start; - width: 100%; - height: 90%; - max-height: 25rem; - overflow-y: auto; - padding-top: 1rem; - - border-radius: 2.5rem; -} - -.program-container::-webkit-scrollbar { - width: 0.5rem; - height: 70%; -} - -.program-container::-webkit-scrollbar-track { - - border-radius: 0.5rem; - background-color: #e7e7e7; - border: 1px solid #cacaca; - margin-bottom: 2.5rem; -} - -.program-container::-webkit-scrollbar-thumb { - border-radius: 0.5rem; - background-color: #1BE985; - border: 1px solid #1b1f24; - -} - -.delete-image{ - width: 2rem; - height: 2rem; - align-self: center; - cursor: pointer; -} -.delete-image:hover{ - transition: 0.3s; - transform: scale(1.01); - filter: invert(20%) sepia(32%) saturate(2127%) hue-rotate(90deg) brightness(100%) contrast(100%); -} - -.buttons-container { - align-self: center; - display: flex; - justify-content: space-around; - margin-top: 1rem; - width: 30%; -} - -.profile-button { - width: fit-content; - appearance: none; - background-color: #15c871; - border: 2px solid #1A1A1A; - border-radius: 1.4rem; - color: #FFFFFF; - cursor: pointer; - font-size: 1rem; - font-weight: 600; - min-height: 60px; - padding: 1rem 24px; - text-align: center; - text-decoration: none; - transition: all 300ms cubic-bezier(.23, 1, 0.32, 1); - touch-action: manipulation; - will-change: transform; - - box-shadow: 0 0 0 1px #000, 0 30px 30px rgba(0, 0, 0, 0.07), - 0 15px 15px rgba(0, 0, 0, 0.06), 0 10px 8px rgba(0, 0, 0, 0.05), - 0 4px 4px rgba(0, 0, 0, 0.04), 0 2px 2px rgba(0, 0, 0, 0.03); -} - -.profile-button:hover { - box-shadow: rgba(0, 0, 0, 0.25) 0 8px 15px; - transform: translateY(-2px); -} - -.profile-button:active { - box-shadow: none; - transform: translateY(0); -} - -.profile-container{ - display: flex; - flex-direction: column; - width: 75%; - height: 70%; - justify-content: center; - align-self: center; - -} -.profile-container p{ - text-align: left; - font-size: 1.5rem; - font-weight: 600; - margin: 0.5rem 0; -} \ No newline at end of file diff --git a/src/pages/Register/index.jsx b/src/pages/Register/index.jsx index 3f238ab..c4aa597 100644 --- a/src/pages/Register/index.jsx +++ b/src/pages/Register/index.jsx @@ -1,9 +1,9 @@ import React from 'react' import {AuthForm} from '../../components/' - +import SignUpForm from '../../components/signUpForm' const Register = ({updateCurrentUser}) => { return ( - <AuthForm currentRoute='/register' redirectRoute='/login' updateCurrentUser={updateCurrentUser}/> + <SignUpForm /> ) }