зеркало из https://github.com/xamarin/IronJS.git
3-4 weeks worth of assorted work on off hours, on the buss, etc.
This commit is contained in:
Родитель
67ac4eadbd
Коммит
388e56331b
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
159
LICENSE.txt
159
LICENSE.txt
|
@ -1,46 +1,133 @@
|
|||
Microsoft Public License (Ms-PL)
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
This license governs use of the accompanying software. If you use the software, you
|
||||
accept this license. If you do not accept the license, do not use the software.
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions
|
||||
The terms "reproduce," "reproduction," "derivative works," and "distribution" have the
|
||||
same meaning here as under U.S. copyright law.
|
||||
1. Definitions.
|
||||
|
||||
A "contribution" is the original software, or any additions or changes to the software.
|
||||
A "contributor" is any person that distributes its contribution under this license.
|
||||
"Licensed patents" are a contributor's patent claims that read directly on its contribution.
|
||||
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1
|
||||
through 9 of this document.
|
||||
|
||||
2. Grant of Rights
|
||||
(A) Copyright Grant- Subject to the terms of this license, including the license conditions
|
||||
and limitations in section 3, each contributor grants you a non-exclusive, worldwide,
|
||||
royalty-free copyright license to reproduce its contribution, prepare derivative works of
|
||||
its contribution, and distribute its contribution or any derivative works that you create.
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
|
||||
|
||||
(B) Patent Grant- Subject to the terms of this license, including the license conditions
|
||||
and limitations in section 3, each contributor grants you a non-exclusive, worldwide,
|
||||
royalty-free license under its licensed patents to make, have made, use, sell, offer for
|
||||
sale, import, and/or otherwise dispose of its contribution in the software or derivative
|
||||
works of the contribution in the software.
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or
|
||||
are under common control with that entity. For the purposes of this definition, "control" means (i) the power,
|
||||
direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii)
|
||||
ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
3. Conditions and Limitations
|
||||
(A) No Trademark License- This license does not grant you rights to use any contributors'
|
||||
name, logo, or trademarks.
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
|
||||
|
||||
(B) If you bring a patent claim against any contributor over patents that you claim are
|
||||
infringed by the software, your patent license from such contributor to the
|
||||
software ends automatically.
|
||||
"Source" form shall mean the preferred form for making modifications, including but not limited to software source
|
||||
code, documentation source, and configuration files.
|
||||
|
||||
(C) If you distribute any portion of the software, you must retain all copyright, patent,
|
||||
trademark, and attribution notices that are present in the software.
|
||||
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form,
|
||||
including but not limited to compiled object code, generated documentation, and conversions to other media types.
|
||||
|
||||
(D) If you distribute any portion of the software in source code form, you may do so only
|
||||
under this license by including a complete copy of this license with your distribution.
|
||||
If you distribute any portion of the software in compiled or object code form, you may only
|
||||
do so under a license that complies with this license.
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as
|
||||
indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix
|
||||
below).
|
||||
|
||||
(E) The software is licensed "as-is." You bear the risk of using it. The contributors give
|
||||
no express warranties, guarantees or conditions. You may have additional consumer rights
|
||||
under your local laws which this license cannot change. To the extent permitted under your
|
||||
local laws, the contributors exclude the implied warranties of merchantability, fitness
|
||||
for a particular purpose and non-infringement.
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the
|
||||
Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole,
|
||||
an original work of authorship. For the purposes of this License, Derivative Works shall not include works that
|
||||
remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications
|
||||
or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in
|
||||
the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright
|
||||
owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written
|
||||
communication sent to the Licensor or its representatives, including but not limited to communication on electronic
|
||||
mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously
|
||||
marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been
|
||||
received by Licensor and subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide,
|
||||
non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or
|
||||
Object form.
|
||||
|
||||
3. Grant of Patent License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide,
|
||||
non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have
|
||||
made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those
|
||||
patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by
|
||||
combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute
|
||||
patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any
|
||||
patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is
|
||||
filed.
|
||||
|
||||
4. Redistribution.
|
||||
|
||||
You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You meet the following conditions:
|
||||
|
||||
1. You must give any other recipients of the Work or Derivative Works a copy of this License; and
|
||||
|
||||
2. You must cause any modified files to carry prominent notices stating that You changed the files; and
|
||||
|
||||
3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent,
|
||||
trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to
|
||||
any part of the Derivative Works; and
|
||||
|
||||
4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You
|
||||
distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding
|
||||
those notices that do not pertain to any part of the Derivative Works, in at least one of the following places:
|
||||
within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if
|
||||
provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever
|
||||
such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do
|
||||
not modify the License. You may add Your own attribution notices within Derivative Works that You distribute,
|
||||
alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices
|
||||
cannot be construed as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and may provide additional or different license terms
|
||||
and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a
|
||||
whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated
|
||||
in this License.
|
||||
|
||||
5. Submission of Contributions.
|
||||
|
||||
Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to
|
||||
the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you
|
||||
may have executed with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks.
|
||||
|
||||
This License does not grant permission to use the trade names, trademarks, service marks, or product names of the
|
||||
Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing
|
||||
the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides
|
||||
its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
||||
including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing
|
||||
the Work and assume any risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability.
|
||||
|
||||
In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless
|
||||
required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any
|
||||
Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential
|
||||
damages of any character arising as a result of this License or out of the use or inability to use the Work
|
||||
(including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any
|
||||
and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such
|
||||
damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability.
|
||||
|
||||
While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance
|
||||
of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However,
|
||||
in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of
|
||||
any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any
|
||||
liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or
|
||||
additional liability.
|
|
@ -0,0 +1,69 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution.
|
||||
|
||||
You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
|
||||
|
||||
1. You must give any other recipients of the Work or Derivative Works a copy of this License; and
|
||||
|
||||
2. You must cause any modified files to carry prominent notices stating that You changed the files; and
|
||||
|
||||
3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
|
||||
|
||||
4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions.
|
||||
|
||||
Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks.
|
||||
|
||||
This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability.
|
||||
|
||||
In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability.
|
||||
|
||||
While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
|
Двоичный файл не отображается.
|
@ -0,0 +1,69 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution.
|
||||
|
||||
You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
|
||||
|
||||
1. You must give any other recipients of the Work or Derivative Works a copy of this License; and
|
||||
|
||||
2. You must cause any modified files to carry prominent notices stating that You changed the files; and
|
||||
|
||||
3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
|
||||
|
||||
4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions.
|
||||
|
||||
Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks.
|
||||
|
||||
This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability.
|
||||
|
||||
In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability.
|
||||
|
||||
While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
|
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -1,337 +0,0 @@
|
|||
// 3D Cube Rotation
|
||||
// http://www.speich.net/computer/moztesting/3d.htm
|
||||
// Created by Simon Speich
|
||||
|
||||
var Q = new Array();
|
||||
var MTrans = new Array(); // transformation matrix
|
||||
var MQube = new Array(); // position information of qube
|
||||
var I = new Array(); // entity matrix
|
||||
var Origin = new Object();
|
||||
var Testing = new Object();
|
||||
var LoopTimer;
|
||||
|
||||
var DisplArea = new Object();
|
||||
DisplArea.Width = 300;
|
||||
DisplArea.Height = 300;
|
||||
|
||||
function DrawLine(From, To) {
|
||||
var x1 = From.V[0];
|
||||
var x2 = To.V[0];
|
||||
var y1 = From.V[1];
|
||||
var y2 = To.V[1];
|
||||
var dx = Math.abs(x2 - x1);
|
||||
var dy = Math.abs(y2 - y1);
|
||||
var x = x1;
|
||||
var y = y1;
|
||||
var IncX1, IncY1;
|
||||
var IncX2, IncY2;
|
||||
var Den;
|
||||
var Num;
|
||||
var NumAdd;
|
||||
var NumPix;
|
||||
|
||||
if (x2 >= x1) { IncX1 = 1; IncX2 = 1; }
|
||||
else { IncX1 = -1; IncX2 = -1; }
|
||||
if (y2 >= y1) { IncY1 = 1; IncY2 = 1; }
|
||||
else { IncY1 = -1; IncY2 = -1; }
|
||||
if (dx >= dy) {
|
||||
IncX1 = 0;
|
||||
IncY2 = 0;
|
||||
Den = dx;
|
||||
Num = dx / 2;
|
||||
NumAdd = dy;
|
||||
NumPix = dx;
|
||||
}
|
||||
else {
|
||||
IncX2 = 0;
|
||||
IncY1 = 0;
|
||||
Den = dy;
|
||||
Num = dy / 2;
|
||||
NumAdd = dx;
|
||||
NumPix = dy;
|
||||
}
|
||||
|
||||
NumPix = Math.round(Q.LastPx + NumPix);
|
||||
|
||||
var i = Q.LastPx;
|
||||
for (; i < NumPix; i++) {
|
||||
Num += NumAdd;
|
||||
if (Num >= Den) {
|
||||
Num -= Den;
|
||||
x += IncX1;
|
||||
y += IncY1;
|
||||
}
|
||||
x += IncX2;
|
||||
y += IncY2;
|
||||
}
|
||||
Q.LastPx = NumPix;
|
||||
}
|
||||
|
||||
function CalcCross(V0, V1) {
|
||||
var Cross = new Array();
|
||||
Cross[0] = V0[1]*V1[2] - V0[2]*V1[1];
|
||||
Cross[1] = V0[2]*V1[0] - V0[0]*V1[2];
|
||||
Cross[2] = V0[0]*V1[1] - V0[1]*V1[0];
|
||||
return Cross;
|
||||
}
|
||||
|
||||
function CalcNormal(V0, V1, V2) {
|
||||
var A = new Array(); var B = new Array();
|
||||
for (var i = 0; i < 3; i++) {
|
||||
A[i] = V0[i] - V1[i];
|
||||
B[i] = V2[i] - V1[i];
|
||||
}
|
||||
A = CalcCross(A, B);
|
||||
var Length = Math.sqrt(A[0]*A[0] + A[1]*A[1] + A[2]*A[2]);
|
||||
for (var i = 0; i < 3; i++) A[i] = A[i] / Length;
|
||||
A[3] = 1;
|
||||
return A;
|
||||
}
|
||||
|
||||
function CreateP(X,Y,Z) {
|
||||
this.V = [X,Y,Z,1];
|
||||
}
|
||||
|
||||
// multiplies two matrices
|
||||
function MMulti(M1, M2) {
|
||||
var M = [[],[],[],[]];
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
for (; i < 4; i++) {
|
||||
j = 0;
|
||||
for (; j < 4; j++) M[i][j] = M1[i][0] * M2[0][j] + M1[i][1] * M2[1][j] + M1[i][2] * M2[2][j] + M1[i][3] * M2[3][j];
|
||||
}
|
||||
return M;
|
||||
}
|
||||
|
||||
//multiplies matrix with vector
|
||||
function VMulti(M, V) {
|
||||
var Vect = new Array();
|
||||
var i = 0;
|
||||
for (;i < 4; i++) Vect[i] = M[i][0] * V[0] + M[i][1] * V[1] + M[i][2] * V[2] + M[i][3] * V[3];
|
||||
return Vect;
|
||||
}
|
||||
|
||||
function VMulti2(M, V) {
|
||||
var Vect = new Array();
|
||||
var i = 0;
|
||||
for (;i < 3; i++) Vect[i] = M[i][0] * V[0] + M[i][1] * V[1] + M[i][2] * V[2];
|
||||
return Vect;
|
||||
}
|
||||
|
||||
// add to matrices
|
||||
function MAdd(M1, M2) {
|
||||
var M = [[],[],[],[]];
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
for (; i < 4; i++) {
|
||||
j = 0;
|
||||
for (; j < 4; j++) M[i][j] = M1[i][j] + M2[i][j];
|
||||
}
|
||||
return M;
|
||||
}
|
||||
|
||||
function Translate(M, Dx, Dy, Dz) {
|
||||
var T = [
|
||||
[1,0,0,Dx],
|
||||
[0,1,0,Dy],
|
||||
[0,0,1,Dz],
|
||||
[0,0,0,1]
|
||||
];
|
||||
return MMulti(T, M);
|
||||
}
|
||||
|
||||
function RotateX(M, Phi) {
|
||||
var a = Phi;
|
||||
a *= Math.PI / 180;
|
||||
var Cos = Math.cos(a);
|
||||
var Sin = Math.sin(a);
|
||||
var R = [
|
||||
[1,0,0,0],
|
||||
[0,Cos,-Sin,0],
|
||||
[0,Sin,Cos,0],
|
||||
[0,0,0,1]
|
||||
];
|
||||
return MMulti(R, M);
|
||||
}
|
||||
|
||||
function RotateY(M, Phi) {
|
||||
var a = Phi;
|
||||
a *= Math.PI / 180;
|
||||
var Cos = Math.cos(a);
|
||||
var Sin = Math.sin(a);
|
||||
var R = [
|
||||
[Cos,0,Sin,0],
|
||||
[0,1,0,0],
|
||||
[-Sin,0,Cos,0],
|
||||
[0,0,0,1]
|
||||
];
|
||||
return MMulti(R, M);
|
||||
}
|
||||
|
||||
function RotateZ(M, Phi) {
|
||||
var a = Phi;
|
||||
a *= Math.PI / 180;
|
||||
var Cos = Math.cos(a);
|
||||
var Sin = Math.sin(a);
|
||||
var R = [
|
||||
[Cos,-Sin,0,0],
|
||||
[Sin,Cos,0,0],
|
||||
[0,0,1,0],
|
||||
[0,0,0,1]
|
||||
];
|
||||
return MMulti(R, M);
|
||||
}
|
||||
|
||||
function DrawQube() {
|
||||
// calc current normals
|
||||
var CurN = new Array();
|
||||
var i = 5;
|
||||
Q.LastPx = 0;
|
||||
for (; i > -1; i--) CurN[i] = VMulti2(MQube, Q.Normal[i]);
|
||||
if (CurN[0][2] < 0) {
|
||||
if (!Q.Line[0]) { DrawLine(Q[0], Q[1]); Q.Line[0] = true; };
|
||||
if (!Q.Line[1]) { DrawLine(Q[1], Q[2]); Q.Line[1] = true; };
|
||||
if (!Q.Line[2]) { DrawLine(Q[2], Q[3]); Q.Line[2] = true; };
|
||||
if (!Q.Line[3]) { DrawLine(Q[3], Q[0]); Q.Line[3] = true; };
|
||||
}
|
||||
if (CurN[1][2] < 0) {
|
||||
if (!Q.Line[2]) { DrawLine(Q[3], Q[2]); Q.Line[2] = true; };
|
||||
if (!Q.Line[9]) { DrawLine(Q[2], Q[6]); Q.Line[9] = true; };
|
||||
if (!Q.Line[6]) { DrawLine(Q[6], Q[7]); Q.Line[6] = true; };
|
||||
if (!Q.Line[10]) { DrawLine(Q[7], Q[3]); Q.Line[10] = true; };
|
||||
}
|
||||
if (CurN[2][2] < 0) {
|
||||
if (!Q.Line[4]) { DrawLine(Q[4], Q[5]); Q.Line[4] = true; };
|
||||
if (!Q.Line[5]) { DrawLine(Q[5], Q[6]); Q.Line[5] = true; };
|
||||
if (!Q.Line[6]) { DrawLine(Q[6], Q[7]); Q.Line[6] = true; };
|
||||
if (!Q.Line[7]) { DrawLine(Q[7], Q[4]); Q.Line[7] = true; };
|
||||
}
|
||||
if (CurN[3][2] < 0) {
|
||||
if (!Q.Line[4]) { DrawLine(Q[4], Q[5]); Q.Line[4] = true; };
|
||||
if (!Q.Line[8]) { DrawLine(Q[5], Q[1]); Q.Line[8] = true; };
|
||||
if (!Q.Line[0]) { DrawLine(Q[1], Q[0]); Q.Line[0] = true; };
|
||||
if (!Q.Line[11]) { DrawLine(Q[0], Q[4]); Q.Line[11] = true; };
|
||||
}
|
||||
if (CurN[4][2] < 0) {
|
||||
if (!Q.Line[11]) { DrawLine(Q[4], Q[0]); Q.Line[11] = true; };
|
||||
if (!Q.Line[3]) { DrawLine(Q[0], Q[3]); Q.Line[3] = true; };
|
||||
if (!Q.Line[10]) { DrawLine(Q[3], Q[7]); Q.Line[10] = true; };
|
||||
if (!Q.Line[7]) { DrawLine(Q[7], Q[4]); Q.Line[7] = true; };
|
||||
}
|
||||
if (CurN[5][2] < 0) {
|
||||
if (!Q.Line[8]) { DrawLine(Q[1], Q[5]); Q.Line[8] = true; };
|
||||
if (!Q.Line[5]) { DrawLine(Q[5], Q[6]); Q.Line[5] = true; };
|
||||
if (!Q.Line[9]) { DrawLine(Q[6], Q[2]); Q.Line[9] = true; };
|
||||
if (!Q.Line[1]) { DrawLine(Q[2], Q[1]); Q.Line[1] = true; };
|
||||
}
|
||||
Q.Line = [false,false,false,false,false,false,false,false,false,false,false,false];
|
||||
Q.LastPx = 0;
|
||||
}
|
||||
|
||||
function Loop() {
|
||||
if (Testing.LoopCount > Testing.LoopMax) return;
|
||||
var TestingStr = String(Testing.LoopCount);
|
||||
while (TestingStr.length < 3) TestingStr = "0" + TestingStr;
|
||||
MTrans = Translate(I, -Q[8].V[0], -Q[8].V[1], -Q[8].V[2]);
|
||||
MTrans = RotateX(MTrans, 1);
|
||||
MTrans = RotateY(MTrans, 3);
|
||||
MTrans = RotateZ(MTrans, 5);
|
||||
MTrans = Translate(MTrans, Q[8].V[0], Q[8].V[1], Q[8].V[2]);
|
||||
MQube = MMulti(MTrans, MQube);
|
||||
var i = 8;
|
||||
for (; i > -1; i--) {
|
||||
Q[i].V = VMulti(MTrans, Q[i].V);
|
||||
}
|
||||
DrawQube();
|
||||
Testing.LoopCount++;
|
||||
Loop();
|
||||
}
|
||||
|
||||
function Init(CubeSize) {
|
||||
// init/reset vars
|
||||
Origin.V = [150,150,20,1];
|
||||
Testing.LoopCount = 0;
|
||||
Testing.LoopMax = 50;
|
||||
Testing.TimeMax = 0;
|
||||
Testing.TimeAvg = 0;
|
||||
Testing.TimeMin = 0;
|
||||
Testing.TimeTemp = 0;
|
||||
Testing.TimeTotal = 0;
|
||||
Testing.Init = false;
|
||||
|
||||
// transformation matrix
|
||||
MTrans = [
|
||||
[1,0,0,0],
|
||||
[0,1,0,0],
|
||||
[0,0,1,0],
|
||||
[0,0,0,1]
|
||||
];
|
||||
|
||||
// position information of qube
|
||||
MQube = [
|
||||
[1,0,0,0],
|
||||
[0,1,0,0],
|
||||
[0,0,1,0],
|
||||
[0,0,0,1]
|
||||
];
|
||||
|
||||
// entity matrix
|
||||
I = [
|
||||
[1,0,0,0],
|
||||
[0,1,0,0],
|
||||
[0,0,1,0],
|
||||
[0,0,0,1]
|
||||
];
|
||||
|
||||
// create qube
|
||||
Q[0] = new CreateP(-CubeSize,-CubeSize, CubeSize);
|
||||
Q[1] = new CreateP(-CubeSize, CubeSize, CubeSize);
|
||||
Q[2] = new CreateP( CubeSize, CubeSize, CubeSize);
|
||||
Q[3] = new CreateP( CubeSize,-CubeSize, CubeSize);
|
||||
Q[4] = new CreateP(-CubeSize,-CubeSize,-CubeSize);
|
||||
Q[5] = new CreateP(-CubeSize, CubeSize,-CubeSize);
|
||||
Q[6] = new CreateP( CubeSize, CubeSize,-CubeSize);
|
||||
Q[7] = new CreateP( CubeSize,-CubeSize,-CubeSize);
|
||||
|
||||
// center of gravity
|
||||
Q[8] = new CreateP(0, 0, 0);
|
||||
|
||||
// anti-clockwise edge check
|
||||
Q.Edge = [[0,1,2],[3,2,6],[7,6,5],[4,5,1],[4,0,3],[1,5,6]];
|
||||
|
||||
// calculate squad normals
|
||||
Q.Normal = new Array();
|
||||
for (var i = 0; i < Q.Edge.length; i++) Q.Normal[i] = CalcNormal(Q[Q.Edge[i][0]].V, Q[Q.Edge[i][1]].V, Q[Q.Edge[i][2]].V);
|
||||
|
||||
// line drawn ?
|
||||
Q.Line = [false,false,false,false,false,false,false,false,false,false,false,false];
|
||||
|
||||
// create line pixels
|
||||
Q.NumPx = 9 * 2 * CubeSize;
|
||||
for (var i = 0; i < Q.NumPx; i++) CreateP(0,0,0);
|
||||
|
||||
MTrans = Translate(MTrans, Origin.V[0], Origin.V[1], Origin.V[2]);
|
||||
MQube = MMulti(MTrans, MQube);
|
||||
|
||||
var i = 0;
|
||||
for (; i < 9; i++) {
|
||||
Q[i].V = VMulti(MTrans, Q[i].V);
|
||||
}
|
||||
DrawQube();
|
||||
Testing.Init = true;
|
||||
Loop();
|
||||
}
|
||||
|
||||
for ( var i = 20; i <= 160; i *= 2 ) {
|
||||
Init(i);
|
||||
}
|
||||
|
||||
Q = null;
|
||||
MTrans = null;
|
||||
MQube = null;
|
||||
I = null;
|
||||
Origin = null;
|
||||
Testing = null;
|
||||
LoopTime = null;
|
||||
DisplArea = null;
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
var loops = 15
|
||||
var nx = 120
|
||||
var nz = 120
|
||||
|
||||
function morph(a, f) {
|
||||
var PI2nx = Math.PI * 8/nx
|
||||
var sin = Math.sin
|
||||
var f30 = -(50 * sin(f*Math.PI*2))
|
||||
|
||||
for (var i = 0; i < nz; ++i) {
|
||||
for (var j = 0; j < nx; ++j) {
|
||||
a[3*(i*nx+j)+1] = sin((j-1) * PI2nx ) * -f30
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var a = Array()
|
||||
for (var i=0; i < nx*nz*3; ++i)
|
||||
a[i] = 0
|
||||
|
||||
for (var i = 0; i < loops; ++i) {
|
||||
morph(a, i/loops)
|
||||
}
|
||||
|
||||
testOutput = 0;
|
||||
for (var i = 0; i < nx; i++)
|
||||
testOutput += a[3*(i*nx+i)+1];
|
||||
a = null;
|
|
@ -1,441 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
function createVector(x,y,z) {
|
||||
return new Array(x,y,z);
|
||||
}
|
||||
|
||||
function sqrLengthVector(self) {
|
||||
return self[0] * self[0] + self[1] * self[1] + self[2] * self[2];
|
||||
}
|
||||
|
||||
function lengthVector(self) {
|
||||
return Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]);
|
||||
}
|
||||
|
||||
function addVector(self, v) {
|
||||
self[0] += v[0];
|
||||
self[1] += v[1];
|
||||
self[2] += v[2];
|
||||
return self;
|
||||
}
|
||||
|
||||
function subVector(self, v) {
|
||||
self[0] -= v[0];
|
||||
self[1] -= v[1];
|
||||
self[2] -= v[2];
|
||||
return self;
|
||||
}
|
||||
|
||||
function scaleVector(self, scale) {
|
||||
self[0] *= scale;
|
||||
self[1] *= scale;
|
||||
self[2] *= scale;
|
||||
return self;
|
||||
}
|
||||
|
||||
function normaliseVector(self) {
|
||||
var len = Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]);
|
||||
self[0] /= len;
|
||||
self[1] /= len;
|
||||
self[2] /= len;
|
||||
return self;
|
||||
}
|
||||
|
||||
function add(v1, v2) {
|
||||
return new Array(v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]);
|
||||
}
|
||||
|
||||
function sub(v1, v2) {
|
||||
return new Array(v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]);
|
||||
}
|
||||
|
||||
function scalev(v1, v2) {
|
||||
return new Array(v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]);
|
||||
}
|
||||
|
||||
function dot(v1, v2) {
|
||||
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
|
||||
}
|
||||
|
||||
function scale(v, scale) {
|
||||
return [v[0] * scale, v[1] * scale, v[2] * scale];
|
||||
}
|
||||
|
||||
function cross(v1, v2) {
|
||||
return [v1[1] * v2[2] - v1[2] * v2[1],
|
||||
v1[2] * v2[0] - v1[0] * v2[2],
|
||||
v1[0] * v2[1] - v1[1] * v2[0]];
|
||||
|
||||
}
|
||||
|
||||
function normalise(v) {
|
||||
var len = lengthVector(v);
|
||||
return [v[0] / len, v[1] / len, v[2] / len];
|
||||
}
|
||||
|
||||
function transformMatrix(self, v) {
|
||||
var vals = self;
|
||||
var x = vals[0] * v[0] + vals[1] * v[1] + vals[2] * v[2] + vals[3];
|
||||
var y = vals[4] * v[0] + vals[5] * v[1] + vals[6] * v[2] + vals[7];
|
||||
var z = vals[8] * v[0] + vals[9] * v[1] + vals[10] * v[2] + vals[11];
|
||||
return [x, y, z];
|
||||
}
|
||||
|
||||
function invertMatrix(self) {
|
||||
var temp = new Array(16);
|
||||
var tx = -self[3];
|
||||
var ty = -self[7];
|
||||
var tz = -self[11];
|
||||
for (h = 0; h < 3; h++)
|
||||
for (v = 0; v < 3; v++)
|
||||
temp[h + v * 4] = self[v + h * 4];
|
||||
for (i = 0; i < 11; i++)
|
||||
self[i] = temp[i];
|
||||
self[3] = tx * self[0] + ty * self[1] + tz * self[2];
|
||||
self[7] = tx * self[4] + ty * self[5] + tz * self[6];
|
||||
self[11] = tx * self[8] + ty * self[9] + tz * self[10];
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
// Triangle intersection using barycentric coord method
|
||||
function Triangle(p1, p2, p3) {
|
||||
var edge1 = sub(p3, p1);
|
||||
var edge2 = sub(p2, p1);
|
||||
var normal = cross(edge1, edge2);
|
||||
if (Math.abs(normal[0]) > Math.abs(normal[1]))
|
||||
if (Math.abs(normal[0]) > Math.abs(normal[2]))
|
||||
this.axis = 0;
|
||||
else
|
||||
this.axis = 2;
|
||||
else
|
||||
if (Math.abs(normal[1]) > Math.abs(normal[2]))
|
||||
this.axis = 1;
|
||||
else
|
||||
this.axis = 2;
|
||||
var u = (this.axis + 1) % 3;
|
||||
var v = (this.axis + 2) % 3;
|
||||
var u1 = edge1[u];
|
||||
var v1 = edge1[v];
|
||||
|
||||
var u2 = edge2[u];
|
||||
var v2 = edge2[v];
|
||||
this.normal = normalise(normal);
|
||||
this.nu = normal[u] / normal[this.axis];
|
||||
this.nv = normal[v] / normal[this.axis];
|
||||
this.nd = dot(normal, p1) / normal[this.axis];
|
||||
var det = u1 * v2 - v1 * u2;
|
||||
this.eu = p1[u];
|
||||
this.ev = p1[v];
|
||||
this.nu1 = u1 / det;
|
||||
this.nv1 = -v1 / det;
|
||||
this.nu2 = v2 / det;
|
||||
this.nv2 = -u2 / det;
|
||||
this.material = [0.7, 0.7, 0.7];
|
||||
}
|
||||
|
||||
Triangle.prototype.intersect = function(orig, dir, near, far) {
|
||||
var u = (this.axis + 1) % 3;
|
||||
var v = (this.axis + 2) % 3;
|
||||
var d = dir[this.axis] + this.nu * dir[u] + this.nv * dir[v];
|
||||
var t = (this.nd - orig[this.axis] - this.nu * orig[u] - this.nv * orig[v]) / d;
|
||||
if (t < near || t > far)
|
||||
return null;
|
||||
var Pu = orig[u] + t * dir[u] - this.eu;
|
||||
var Pv = orig[v] + t * dir[v] - this.ev;
|
||||
var a2 = Pv * this.nu1 + Pu * this.nv1;
|
||||
if (a2 < 0)
|
||||
return null;
|
||||
var a3 = Pu * this.nu2 + Pv * this.nv2;
|
||||
if (a3 < 0)
|
||||
return null;
|
||||
|
||||
if ((a2 + a3) > 1)
|
||||
return null;
|
||||
return t;
|
||||
}
|
||||
|
||||
function Scene(a_triangles) {
|
||||
this.triangles = a_triangles;
|
||||
this.lights = [];
|
||||
this.ambient = [0,0,0];
|
||||
this.background = [0.8,0.8,1];
|
||||
}
|
||||
var zero = new Array(0,0,0);
|
||||
|
||||
Scene.prototype.intersect = function(origin, dir, near, far) {
|
||||
var closest = null;
|
||||
for (i = 0; i < this.triangles.length; i++) {
|
||||
var triangle = this.triangles[i];
|
||||
var d = triangle.intersect(origin, dir, near, far);
|
||||
if (d == null || d > far || d < near)
|
||||
continue;
|
||||
far = d;
|
||||
closest = triangle;
|
||||
}
|
||||
|
||||
if (!closest)
|
||||
return [this.background[0],this.background[1],this.background[2]];
|
||||
|
||||
var normal = closest.normal;
|
||||
var hit = add(origin, scale(dir, far));
|
||||
if (dot(dir, normal) > 0)
|
||||
normal = [-normal[0], -normal[1], -normal[2]];
|
||||
|
||||
var colour = null;
|
||||
if (closest.shader) {
|
||||
colour = closest.shader(closest, hit, dir);
|
||||
} else {
|
||||
colour = closest.material;
|
||||
}
|
||||
|
||||
// do reflection
|
||||
var reflected = null;
|
||||
if (colour.reflection > 0.001) {
|
||||
var reflection = addVector(scale(normal, -2*dot(dir, normal)), dir);
|
||||
reflected = this.intersect(hit, reflection, 0.0001, 1000000);
|
||||
if (colour.reflection >= 0.999999)
|
||||
return reflected;
|
||||
}
|
||||
|
||||
var l = [this.ambient[0], this.ambient[1], this.ambient[2]];
|
||||
for (var i = 0; i < this.lights.length; i++) {
|
||||
var light = this.lights[i];
|
||||
var toLight = sub(light, hit);
|
||||
var distance = lengthVector(toLight);
|
||||
scaleVector(toLight, 1.0/distance);
|
||||
distance -= 0.0001;
|
||||
if (this.blocked(hit, toLight, distance))
|
||||
continue;
|
||||
var nl = dot(normal, toLight);
|
||||
if (nl > 0)
|
||||
addVector(l, scale(light.colour, nl));
|
||||
}
|
||||
l = scalev(l, colour);
|
||||
if (reflected) {
|
||||
l = addVector(scaleVector(l, 1 - colour.reflection), scaleVector(reflected, colour.reflection));
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
Scene.prototype.blocked = function(O, D, far) {
|
||||
var near = 0.0001;
|
||||
var closest = null;
|
||||
for (i = 0; i < this.triangles.length; i++) {
|
||||
var triangle = this.triangles[i];
|
||||
var d = triangle.intersect(O, D, near, far);
|
||||
if (d == null || d > far || d < near)
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// this camera code is from notes i made ages ago, it is from *somewhere* -- i cannot remember where
|
||||
// that somewhere is
|
||||
function Camera(origin, lookat, up) {
|
||||
var zaxis = normaliseVector(subVector(lookat, origin));
|
||||
var xaxis = normaliseVector(cross(up, zaxis));
|
||||
var yaxis = normaliseVector(cross(xaxis, subVector([0,0,0], zaxis)));
|
||||
var m = new Array(16);
|
||||
m[0] = xaxis[0]; m[1] = xaxis[1]; m[2] = xaxis[2];
|
||||
m[4] = yaxis[0]; m[5] = yaxis[1]; m[6] = yaxis[2];
|
||||
m[8] = zaxis[0]; m[9] = zaxis[1]; m[10] = zaxis[2];
|
||||
invertMatrix(m);
|
||||
m[3] = 0; m[7] = 0; m[11] = 0;
|
||||
this.origin = origin;
|
||||
this.directions = new Array(4);
|
||||
this.directions[0] = normalise([-0.7, 0.7, 1]);
|
||||
this.directions[1] = normalise([ 0.7, 0.7, 1]);
|
||||
this.directions[2] = normalise([ 0.7, -0.7, 1]);
|
||||
this.directions[3] = normalise([-0.7, -0.7, 1]);
|
||||
this.directions[0] = transformMatrix(m, this.directions[0]);
|
||||
this.directions[1] = transformMatrix(m, this.directions[1]);
|
||||
this.directions[2] = transformMatrix(m, this.directions[2]);
|
||||
this.directions[3] = transformMatrix(m, this.directions[3]);
|
||||
}
|
||||
|
||||
Camera.prototype.generateRayPair = function(y) {
|
||||
rays = new Array(new Object(), new Object());
|
||||
rays[0].origin = this.origin;
|
||||
rays[1].origin = this.origin;
|
||||
rays[0].dir = addVector(scale(this.directions[0], y), scale(this.directions[3], 1 - y));
|
||||
rays[1].dir = addVector(scale(this.directions[1], y), scale(this.directions[2], 1 - y));
|
||||
return rays;
|
||||
}
|
||||
|
||||
function renderRows(camera, scene, pixels, width, height, starty, stopy) {
|
||||
for (var y = starty; y < stopy; y++) {
|
||||
var rays = camera.generateRayPair(y / height);
|
||||
for (var x = 0; x < width; x++) {
|
||||
var xp = x / width;
|
||||
var origin = addVector(scale(rays[0].origin, xp), scale(rays[1].origin, 1 - xp));
|
||||
var dir = normaliseVector(addVector(scale(rays[0].dir, xp), scale(rays[1].dir, 1 - xp)));
|
||||
var l = scene.intersect(origin, dir);
|
||||
pixels[y][x] = l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Camera.prototype.render = function(scene, pixels, width, height) {
|
||||
var cam = this;
|
||||
var row = 0;
|
||||
renderRows(cam, scene, pixels, width, height, 0, height);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function raytraceScene()
|
||||
{
|
||||
var startDate = new Date().getTime();
|
||||
var numTriangles = 2 * 6;
|
||||
var triangles = new Array();//numTriangles);
|
||||
var tfl = createVector(-10, 10, -10);
|
||||
var tfr = createVector( 10, 10, -10);
|
||||
var tbl = createVector(-10, 10, 10);
|
||||
var tbr = createVector( 10, 10, 10);
|
||||
var bfl = createVector(-10, -10, -10);
|
||||
var bfr = createVector( 10, -10, -10);
|
||||
var bbl = createVector(-10, -10, 10);
|
||||
var bbr = createVector( 10, -10, 10);
|
||||
|
||||
// cube!!!
|
||||
// front
|
||||
var i = 0;
|
||||
|
||||
triangles[i++] = new Triangle(tfl, tfr, bfr);
|
||||
triangles[i++] = new Triangle(tfl, bfr, bfl);
|
||||
// back
|
||||
triangles[i++] = new Triangle(tbl, tbr, bbr);
|
||||
triangles[i++] = new Triangle(tbl, bbr, bbl);
|
||||
// triangles[i-1].material = [0.7,0.2,0.2];
|
||||
// triangles[i-1].material.reflection = 0.8;
|
||||
// left
|
||||
triangles[i++] = new Triangle(tbl, tfl, bbl);
|
||||
// triangles[i-1].reflection = 0.6;
|
||||
triangles[i++] = new Triangle(tfl, bfl, bbl);
|
||||
// triangles[i-1].reflection = 0.6;
|
||||
// right
|
||||
triangles[i++] = new Triangle(tbr, tfr, bbr);
|
||||
triangles[i++] = new Triangle(tfr, bfr, bbr);
|
||||
// top
|
||||
triangles[i++] = new Triangle(tbl, tbr, tfr);
|
||||
triangles[i++] = new Triangle(tbl, tfr, tfl);
|
||||
// bottom
|
||||
triangles[i++] = new Triangle(bbl, bbr, bfr);
|
||||
triangles[i++] = new Triangle(bbl, bfr, bfl);
|
||||
|
||||
//Floor!!!!
|
||||
var green = createVector(0.0, 0.4, 0.0);
|
||||
var grey = createVector(0.4, 0.4, 0.4);
|
||||
grey.reflection = 1.0;
|
||||
var floorShader = function(tri, pos, view) {
|
||||
var x = ((pos[0]/32) % 2 + 2) % 2;
|
||||
var z = ((pos[2]/32 + 0.3) % 2 + 2) % 2;
|
||||
if (x < 1 != z < 1) {
|
||||
//in the real world we use the fresnel term...
|
||||
// var angle = 1-dot(view, tri.normal);
|
||||
// angle *= angle;
|
||||
// angle *= angle;
|
||||
// angle *= angle;
|
||||
//grey.reflection = angle;
|
||||
return grey;
|
||||
} else
|
||||
return green;
|
||||
}
|
||||
var ffl = createVector(-1000, -30, -1000);
|
||||
var ffr = createVector( 1000, -30, -1000);
|
||||
var fbl = createVector(-1000, -30, 1000);
|
||||
var fbr = createVector( 1000, -30, 1000);
|
||||
triangles[i++] = new Triangle(fbl, fbr, ffr);
|
||||
triangles[i-1].shader = floorShader;
|
||||
triangles[i++] = new Triangle(fbl, ffr, ffl);
|
||||
triangles[i-1].shader = floorShader;
|
||||
|
||||
var _scene = new Scene(triangles);
|
||||
_scene.lights[0] = createVector(20, 38, -22);
|
||||
_scene.lights[0].colour = createVector(0.7, 0.3, 0.3);
|
||||
_scene.lights[1] = createVector(-23, 40, 17);
|
||||
_scene.lights[1].colour = createVector(0.7, 0.3, 0.3);
|
||||
_scene.lights[2] = createVector(23, 20, 17);
|
||||
_scene.lights[2].colour = createVector(0.7, 0.7, 0.7);
|
||||
_scene.ambient = createVector(0.1, 0.1, 0.1);
|
||||
// _scene.background = createVector(0.7, 0.7, 1.0);
|
||||
|
||||
var size = 30;
|
||||
var pixels = new Array();
|
||||
for (var y = 0; y < size; y++) {
|
||||
pixels[y] = new Array();
|
||||
for (var x = 0; x < size; x++) {
|
||||
pixels[y][x] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
var _camera = new Camera(createVector(-40, 40, 40), createVector(0, 0, 0), createVector(0, 1, 0));
|
||||
_camera.render(_scene, pixels, size, size);
|
||||
|
||||
return pixels;
|
||||
}
|
||||
|
||||
function arrayToCanvasCommands(pixels)
|
||||
{
|
||||
var s = '<canvas id="renderCanvas" width="30px" height="30px"></canvas><scr' + 'ipt>\nvar pixels = [';
|
||||
var size = 30;
|
||||
for (var y = 0; y < size; y++) {
|
||||
s += "[";
|
||||
for (var x = 0; x < size; x++) {
|
||||
s += "[" + pixels[y][x] + "],";
|
||||
}
|
||||
s+= "],";
|
||||
}
|
||||
s += '];\n var canvas = document.getElementById("renderCanvas").getContext("2d");\n\
|
||||
\n\
|
||||
\n\
|
||||
var size = 30;\n\
|
||||
canvas.fillStyle = "red";\n\
|
||||
canvas.fillRect(0, 0, size, size);\n\
|
||||
canvas.scale(1, -1);\n\
|
||||
canvas.translate(0, -size);\n\
|
||||
\n\
|
||||
if (!canvas.setFillColor)\n\
|
||||
canvas.setFillColor = function(r, g, b, a) {\n\
|
||||
this.fillStyle = "rgb("+[Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)]+")";\n\
|
||||
}\n\
|
||||
\n\
|
||||
for (var y = 0; y < size; y++) {\n\
|
||||
for (var x = 0; x < size; x++) {\n\
|
||||
var l = pixels[y][x];\n\
|
||||
canvas.setFillColor(l[0], l[1], l[2], 1);\n\
|
||||
canvas.fillRect(x, y, 1, 1);\n\
|
||||
}\n\
|
||||
}</scr' + 'ipt>';
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
testOutput = arrayToCanvasCommands(raytraceScene());
|
|
@ -1,50 +0,0 @@
|
|||
/* The Great Computer Language Shootout
|
||||
http://shootout.alioth.debian.org/
|
||||
contributed by Isaac Gouy */
|
||||
|
||||
function TreeNode(left,right,item){
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
TreeNode.prototype.itemCheck = function(){
|
||||
if (this.left==null) return this.item;
|
||||
else return this.item + this.left.itemCheck() - this.right.itemCheck();
|
||||
}
|
||||
|
||||
function bottomUpTree(item,depth){
|
||||
if (depth>0){
|
||||
return new TreeNode(
|
||||
bottomUpTree(2*item-1, depth-1)
|
||||
,bottomUpTree(2*item, depth-1)
|
||||
,item
|
||||
);
|
||||
}
|
||||
else {
|
||||
return new TreeNode(null,null,item);
|
||||
}
|
||||
}
|
||||
|
||||
var ret;
|
||||
|
||||
for ( var n = 4; n <= 7; n += 1 ) {
|
||||
var minDepth = 4;
|
||||
var maxDepth = Math.max(minDepth + 2, n);
|
||||
var stretchDepth = maxDepth + 1;
|
||||
|
||||
var check = bottomUpTree(0,stretchDepth).itemCheck();
|
||||
|
||||
var longLivedTree = bottomUpTree(0,maxDepth);
|
||||
for (var depth=minDepth; depth<=maxDepth; depth+=2){
|
||||
var iterations = 1 << (maxDepth - depth + minDepth);
|
||||
|
||||
check = 0;
|
||||
for (var i=1; i<=iterations; i++){
|
||||
check += bottomUpTree(i,depth).itemCheck();
|
||||
check += bottomUpTree(-i,depth).itemCheck();
|
||||
}
|
||||
}
|
||||
|
||||
ret = longLivedTree.itemCheck();
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
/* The Great Computer Language Shootout
|
||||
http://shootout.alioth.debian.org/
|
||||
contributed by Isaac Gouy */
|
||||
|
||||
function fannkuch(n) {
|
||||
var check = 0;
|
||||
var perm = Array(n);
|
||||
var perm1 = Array(n);
|
||||
var count = Array(n);
|
||||
var maxPerm = Array(n);
|
||||
var maxFlipsCount = 0;
|
||||
var m = n - 1;
|
||||
|
||||
for (var i = 0; i < n; i++) perm1[i] = i;
|
||||
var r = n;
|
||||
|
||||
while (true) {
|
||||
// write-out the first 30 permutations
|
||||
if (check < 30){
|
||||
var s = "";
|
||||
for(var i=0; i<n; i++) s += (perm1[i]+1).toString();
|
||||
check++;
|
||||
}
|
||||
|
||||
while (r != 1) { count[r - 1] = r; r--; }
|
||||
if (!(perm1[0] == 0 || perm1[m] == m)) {
|
||||
for (var i = 0; i < n; i++) perm[i] = perm1[i];
|
||||
|
||||
var flipsCount = 0;
|
||||
var k;
|
||||
|
||||
while (!((k = perm[0]) == 0)) {
|
||||
var k2 = (k + 1) >> 1;
|
||||
for (var i = 0; i < k2; i++) {
|
||||
var temp = perm[i]; perm[i] = perm[k - i]; perm[k - i] = temp;
|
||||
}
|
||||
flipsCount++;
|
||||
}
|
||||
|
||||
if (flipsCount > maxFlipsCount) {
|
||||
maxFlipsCount = flipsCount;
|
||||
for (var i = 0; i < n; i++) maxPerm[i] = perm1[i];
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (r == n) return maxFlipsCount;
|
||||
var perm0 = perm1[0];
|
||||
var i = 0;
|
||||
while (i < r) {
|
||||
var j = i + 1;
|
||||
perm1[i] = perm1[j];
|
||||
i = j;
|
||||
}
|
||||
perm1[r] = perm0;
|
||||
|
||||
count[r] = count[r] - 1;
|
||||
if (count[r] > 0) break;
|
||||
r++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var n = 8;
|
||||
var ret = fannkuch(n);
|
||||
|
|
@ -1,169 +0,0 @@
|
|||
/* The Great Computer Language Shootout
|
||||
http://shootout.alioth.debian.org/
|
||||
contributed by Isaac Gouy */
|
||||
|
||||
var PI = 3.141592653589793;
|
||||
var SOLAR_MASS = 4 * PI * PI;
|
||||
var DAYS_PER_YEAR = 365.24;
|
||||
|
||||
function Body(x,y,z,vx,vy,vz,mass){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.vx = vx;
|
||||
this.vy = vy;
|
||||
this.vz = vz;
|
||||
this.mass = mass;
|
||||
}
|
||||
|
||||
Body.prototype.offsetMomentum = function(px,py,pz) {
|
||||
this.vx = -px / SOLAR_MASS;
|
||||
this.vy = -py / SOLAR_MASS;
|
||||
this.vz = -pz / SOLAR_MASS;
|
||||
return this;
|
||||
}
|
||||
|
||||
function Jupiter(){
|
||||
return new Body(
|
||||
4.84143144246472090e+00,
|
||||
-1.16032004402742839e+00,
|
||||
-1.03622044471123109e-01,
|
||||
1.66007664274403694e-03 * DAYS_PER_YEAR,
|
||||
7.69901118419740425e-03 * DAYS_PER_YEAR,
|
||||
-6.90460016972063023e-05 * DAYS_PER_YEAR,
|
||||
9.54791938424326609e-04 * SOLAR_MASS
|
||||
);
|
||||
}
|
||||
|
||||
function Saturn(){
|
||||
return new Body(
|
||||
8.34336671824457987e+00,
|
||||
4.12479856412430479e+00,
|
||||
-4.03523417114321381e-01,
|
||||
-2.76742510726862411e-03 * DAYS_PER_YEAR,
|
||||
4.99852801234917238e-03 * DAYS_PER_YEAR,
|
||||
2.30417297573763929e-05 * DAYS_PER_YEAR,
|
||||
2.85885980666130812e-04 * SOLAR_MASS
|
||||
);
|
||||
}
|
||||
|
||||
function Uranus(){
|
||||
return new Body(
|
||||
1.28943695621391310e+01,
|
||||
-1.51111514016986312e+01,
|
||||
-2.23307578892655734e-01,
|
||||
2.96460137564761618e-03 * DAYS_PER_YEAR,
|
||||
2.37847173959480950e-03 * DAYS_PER_YEAR,
|
||||
-2.96589568540237556e-05 * DAYS_PER_YEAR,
|
||||
4.36624404335156298e-05 * SOLAR_MASS
|
||||
);
|
||||
}
|
||||
|
||||
function Neptune(){
|
||||
return new Body(
|
||||
1.53796971148509165e+01,
|
||||
-2.59193146099879641e+01,
|
||||
1.79258772950371181e-01,
|
||||
2.68067772490389322e-03 * DAYS_PER_YEAR,
|
||||
1.62824170038242295e-03 * DAYS_PER_YEAR,
|
||||
-9.51592254519715870e-05 * DAYS_PER_YEAR,
|
||||
5.15138902046611451e-05 * SOLAR_MASS
|
||||
);
|
||||
}
|
||||
|
||||
function Sun(){
|
||||
return new Body(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_MASS);
|
||||
}
|
||||
|
||||
|
||||
function NBodySystem(bodies){
|
||||
this.bodies = bodies;
|
||||
var px = 0.0;
|
||||
var py = 0.0;
|
||||
var pz = 0.0;
|
||||
var size = this.bodies.length;
|
||||
for (var i=0; i<size; i++){
|
||||
var b = this.bodies[i];
|
||||
var m = b.mass;
|
||||
px += b.vx * m;
|
||||
py += b.vy * m;
|
||||
pz += b.vz * m;
|
||||
}
|
||||
this.bodies[0].offsetMomentum(px,py,pz);
|
||||
}
|
||||
|
||||
NBodySystem.prototype.advance = function(dt){
|
||||
var dx, dy, dz, distance, mag;
|
||||
var size = this.bodies.length;
|
||||
|
||||
for (var i=0; i<size; i++) {
|
||||
var bodyi = this.bodies[i];
|
||||
for (var j=i+1; j<size; j++) {
|
||||
var bodyj = this.bodies[j];
|
||||
dx = bodyi.x - bodyj.x;
|
||||
dy = bodyi.y - bodyj.y;
|
||||
dz = bodyi.z - bodyj.z;
|
||||
|
||||
distance = Math.sqrt(dx*dx + dy*dy + dz*dz);
|
||||
mag = dt / (distance * distance * distance);
|
||||
|
||||
bodyi.vx -= dx * bodyj.mass * mag;
|
||||
bodyi.vy -= dy * bodyj.mass * mag;
|
||||
bodyi.vz -= dz * bodyj.mass * mag;
|
||||
|
||||
bodyj.vx += dx * bodyi.mass * mag;
|
||||
bodyj.vy += dy * bodyi.mass * mag;
|
||||
bodyj.vz += dz * bodyi.mass * mag;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i=0; i<size; i++) {
|
||||
var body = this.bodies[i];
|
||||
body.x += dt * body.vx;
|
||||
body.y += dt * body.vy;
|
||||
body.z += dt * body.vz;
|
||||
}
|
||||
}
|
||||
|
||||
NBodySystem.prototype.energy = function(){
|
||||
var dx, dy, dz, distance;
|
||||
var e = 0.0;
|
||||
var size = this.bodies.length;
|
||||
|
||||
for (var i=0; i<size; i++) {
|
||||
var bodyi = this.bodies[i];
|
||||
|
||||
e += 0.5 * bodyi.mass *
|
||||
( bodyi.vx * bodyi.vx
|
||||
+ bodyi.vy * bodyi.vy
|
||||
+ bodyi.vz * bodyi.vz );
|
||||
|
||||
for (var j=i+1; j<size; j++) {
|
||||
var bodyj = this.bodies[j];
|
||||
dx = bodyi.x - bodyj.x;
|
||||
dy = bodyi.y - bodyj.y;
|
||||
dz = bodyi.z - bodyj.z;
|
||||
|
||||
distance = Math.sqrt(dx*dx + dy*dy + dz*dz);
|
||||
e -= (bodyi.mass * bodyj.mass) / distance;
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
var ret;
|
||||
|
||||
for ( var n = 3; n <= 24; n *= 2 ) {
|
||||
(function(){
|
||||
var bodies = new NBodySystem( Array(
|
||||
Sun(),Jupiter(),Saturn(),Uranus(),Neptune()
|
||||
));
|
||||
var max = n * 100;
|
||||
|
||||
ret = bodies.energy();
|
||||
for (var i=0; i<max; i++){
|
||||
bodies.advance(0.01);
|
||||
}
|
||||
ret = bodies.energy();
|
||||
})();
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
// The Great Computer Language Shootout
|
||||
// http://shootout.alioth.debian.org/
|
||||
//
|
||||
// modified by Isaac Gouy
|
||||
|
||||
function pad(number,width){
|
||||
var s = number.toString();
|
||||
var prefixWidth = width - s.length;
|
||||
if (prefixWidth>0){
|
||||
for (var i=1; i<=prefixWidth; i++) s = " " + s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function nsieve(m, isPrime){
|
||||
var i, k, count;
|
||||
|
||||
for (i=2; i<=m; i++) { isPrime[i] = true; }
|
||||
count = 0;
|
||||
|
||||
for (i=2; i<=m; i++){
|
||||
if (isPrime[i]) {
|
||||
for (k=i+i; k<=m; k+=i) isPrime[k] = false;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
function sieve() {
|
||||
for (var i = 1; i <= 3; i++ ) {
|
||||
var m = (1<<i)*10000;
|
||||
var flags = Array(m+1);
|
||||
nsieve(m, flags);
|
||||
}
|
||||
}
|
||||
|
||||
sieve();
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright (c) 2004 by Arthur Langereis (arthur_ext at domain xfinitegames, tld com
|
||||
|
||||
// 1 op = 6 ANDs, 3 SHRs, 3 SHLs, 4 assigns, 2 ADDs
|
||||
// O(1)
|
||||
function fast3bitlookup(b) {
|
||||
var c, bi3b = 0xE994; // 0b1110 1001 1001 0100; // 3 2 2 1 2 1 1 0
|
||||
c = 3 & (bi3b >> ((b << 1) & 14));
|
||||
c += 3 & (bi3b >> ((b >> 2) & 14));
|
||||
c += 3 & (bi3b >> ((b >> 5) & 6));
|
||||
return c;
|
||||
|
||||
/*
|
||||
lir4,0xE994; 9 instructions, no memory access, minimal register dependence, 6 shifts, 2 adds, 1 inline assign
|
||||
rlwinmr5,r3,1,28,30
|
||||
rlwinmr6,r3,30,28,30
|
||||
rlwinmr7,r3,27,29,30
|
||||
rlwnmr8,r4,r5,30,31
|
||||
rlwnmr9,r4,r6,30,31
|
||||
rlwnmr10,r4,r7,30,31
|
||||
addr3,r8,r9
|
||||
addr3,r3,r10
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
function TimeFunc(func) {
|
||||
var x, y, t;
|
||||
for(var x=0; x<500; x++)
|
||||
for(var y=0; y<256; y++) func(y);
|
||||
}
|
||||
|
||||
TimeFunc(fast3bitlookup);
|
|
@ -1,21 +0,0 @@
|
|||
// Copyright (c) 2004 by Arthur Langereis (arthur_ext at domain xfinitegames, tld com)
|
||||
|
||||
|
||||
// 1 op = 2 assigns, 16 compare/branches, 8 ANDs, (0-8) ADDs, 8 SHLs
|
||||
// O(n)
|
||||
function bitsinbyte(b) {
|
||||
var m = 1, c = 0;
|
||||
while(m<0x100) {
|
||||
if(b & m) c++;
|
||||
m <<= 1;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
function TimeFunc(func) {
|
||||
var x, y, t;
|
||||
for(var x=0; x<350; x++)
|
||||
for(var y=0; y<256; y++) func(y);
|
||||
}
|
||||
|
||||
TimeFunc(bitsinbyte);
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
bitwiseAndValue = 4294967296;
|
||||
for (var i = 0; i < 600000; i++)
|
||||
bitwiseAndValue = bitwiseAndValue & i;
|
|
@ -1,32 +0,0 @@
|
|||
// The Great Computer Language Shootout
|
||||
// http://shootout.alioth.debian.org
|
||||
//
|
||||
// Contributed by Ian Osgood
|
||||
|
||||
function pad(n,width) {
|
||||
var s = n.toString();
|
||||
while (s.length < width) s = ' ' + s;
|
||||
return s;
|
||||
}
|
||||
|
||||
function primes(isPrime, n) {
|
||||
var i, count = 0, m = 10000<<n, size = m+31>>5;
|
||||
|
||||
for (i=0; i<size; i++) isPrime[i] = 0xffffffff;
|
||||
|
||||
for (i=2; i<m; i++)
|
||||
if (isPrime[i>>5] & 1<<(i&31)) {
|
||||
for (var j=i+i; j<m; j+=i)
|
||||
isPrime[j>>5] &= ~(1<<(j&31));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
function sieve() {
|
||||
for (var i = 4; i <= 4; i++) {
|
||||
var isPrime = new Array((10000<<i)+31>>5);
|
||||
primes(isPrime, i);
|
||||
}
|
||||
}
|
||||
|
||||
sieve();
|
|
@ -1,25 +0,0 @@
|
|||
// The Computer Language Shootout
|
||||
// http://shootout.alioth.debian.org/
|
||||
// contributed by Isaac Gouy
|
||||
|
||||
function ack(m,n){
|
||||
if (m==0) { return n+1; }
|
||||
if (n==0) { return ack(m-1,1); }
|
||||
return ack(m-1, ack(m,n-1) );
|
||||
}
|
||||
|
||||
function fib(n) {
|
||||
if (n < 2){ return 1; }
|
||||
return fib(n-2) + fib(n-1);
|
||||
}
|
||||
|
||||
function tak(x,y,z) {
|
||||
if (y >= x) return z;
|
||||
return tak(tak(x-1,y,z), tak(y-1,z,x), tak(z-1,x,y));
|
||||
}
|
||||
|
||||
for ( var i = 3; i <= 5; i++ ) {
|
||||
ack(3,i);
|
||||
fib(17.0+i);
|
||||
tak(3*i+3,2*i+2,i+1);
|
||||
}
|
|
@ -1,422 +0,0 @@
|
|||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
/*
|
||||
* AES Cipher function: encrypt 'input' with Rijndael algorithm
|
||||
*
|
||||
* takes byte-array 'input' (16 bytes)
|
||||
* 2D byte-array key schedule 'w' (Nr+1 x Nb bytes)
|
||||
*
|
||||
* applies Nr rounds (10/12/14) using key schedule w for 'add round key' stage
|
||||
*
|
||||
* returns byte-array encrypted value (16 bytes)
|
||||
*/
|
||||
function Cipher(input, w) { // main Cipher function [§5.1]
|
||||
var Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
|
||||
var Nr = w.length/Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
|
||||
|
||||
var state = [[],[],[],[]]; // initialise 4xNb byte-array 'state' with input [§3.4]
|
||||
for (var i=0; i<4*Nb; i++) state[i%4][Math.floor(i/4)] = input[i];
|
||||
|
||||
state = AddRoundKey(state, w, 0, Nb);
|
||||
|
||||
for (var round=1; round<Nr; round++) {
|
||||
state = SubBytes(state, Nb);
|
||||
state = ShiftRows(state, Nb);
|
||||
state = MixColumns(state, Nb);
|
||||
state = AddRoundKey(state, w, round, Nb);
|
||||
}
|
||||
|
||||
state = SubBytes(state, Nb);
|
||||
state = ShiftRows(state, Nb);
|
||||
state = AddRoundKey(state, w, Nr, Nb);
|
||||
|
||||
var output = new Array(4*Nb); // convert state to 1-d array before returning [§3.4]
|
||||
for (var i=0; i<4*Nb; i++) output[i] = state[i%4][Math.floor(i/4)];
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
function SubBytes(s, Nb) { // apply SBox to state S [§5.1.1]
|
||||
for (var r=0; r<4; r++) {
|
||||
for (var c=0; c<Nb; c++) s[r][c] = Sbox[s[r][c]];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
function ShiftRows(s, Nb) { // shift row r of state S left by r bytes [§5.1.2]
|
||||
var t = new Array(4);
|
||||
for (var r=1; r<4; r++) {
|
||||
for (var c=0; c<4; c++) t[c] = s[r][(c+r)%Nb]; // shift into temp copy
|
||||
for (var c=0; c<4; c++) s[r][c] = t[c]; // and copy back
|
||||
} // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
|
||||
return s; // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
|
||||
}
|
||||
|
||||
|
||||
function MixColumns(s, Nb) { // combine bytes of each col of state S [§5.1.3]
|
||||
for (var c=0; c<4; c++) {
|
||||
var a = new Array(4); // 'a' is a copy of the current column from 's'
|
||||
var b = new Array(4); // 'b' is a•{02} in GF(2^8)
|
||||
for (var i=0; i<4; i++) {
|
||||
a[i] = s[i][c];
|
||||
b[i] = s[i][c]&0x80 ? s[i][c]<<1 ^ 0x011b : s[i][c]<<1;
|
||||
}
|
||||
// a[n] ^ b[n] is a•{03} in GF(2^8)
|
||||
s[0][c] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3]; // 2*a0 + 3*a1 + a2 + a3
|
||||
s[1][c] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3]; // a0 * 2*a1 + 3*a2 + a3
|
||||
s[2][c] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3]; // a0 + a1 + 2*a2 + 3*a3
|
||||
s[3][c] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3]; // 3*a0 + a1 + a2 + 2*a3
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
function AddRoundKey(state, w, rnd, Nb) { // xor Round Key into state S [§5.1.4]
|
||||
for (var r=0; r<4; r++) {
|
||||
for (var c=0; c<Nb; c++) state[r][c] ^= w[rnd*4+c][r];
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
function KeyExpansion(key) { // generate Key Schedule (byte-array Nr+1 x Nb) from Key [§5.2]
|
||||
var Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
|
||||
var Nk = key.length/4 // key length (in words): 4/6/8 for 128/192/256-bit keys
|
||||
var Nr = Nk + 6; // no of rounds: 10/12/14 for 128/192/256-bit keys
|
||||
|
||||
var w = new Array(Nb*(Nr+1));
|
||||
var temp = new Array(4);
|
||||
|
||||
for (var i=0; i<Nk; i++) {
|
||||
var r = [key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]];
|
||||
w[i] = r;
|
||||
}
|
||||
|
||||
for (var i=Nk; i<(Nb*(Nr+1)); i++) {
|
||||
w[i] = new Array(4);
|
||||
for (var t=0; t<4; t++) temp[t] = w[i-1][t];
|
||||
if (i % Nk == 0) {
|
||||
temp = SubWord(RotWord(temp));
|
||||
for (var t=0; t<4; t++) temp[t] ^= Rcon[i/Nk][t];
|
||||
} else if (Nk > 6 && i%Nk == 4) {
|
||||
temp = SubWord(temp);
|
||||
}
|
||||
for (var t=0; t<4; t++) w[i][t] = w[i-Nk][t] ^ temp[t];
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
function SubWord(w) { // apply SBox to 4-byte word w
|
||||
for (var i=0; i<4; i++) w[i] = Sbox[w[i]];
|
||||
return w;
|
||||
}
|
||||
|
||||
function RotWord(w) { // rotate 4-byte word w left by one byte
|
||||
w[4] = w[0];
|
||||
for (var i=0; i<4; i++) w[i] = w[i+1];
|
||||
return w;
|
||||
}
|
||||
|
||||
|
||||
// Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [§5.1.1]
|
||||
var Sbox = [0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
|
||||
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
|
||||
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
|
||||
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
|
||||
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
|
||||
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
|
||||
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
|
||||
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
|
||||
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
|
||||
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
|
||||
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
|
||||
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
|
||||
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
|
||||
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
|
||||
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
|
||||
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16];
|
||||
|
||||
// Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [§5.2]
|
||||
var Rcon = [ [0x00, 0x00, 0x00, 0x00],
|
||||
[0x01, 0x00, 0x00, 0x00],
|
||||
[0x02, 0x00, 0x00, 0x00],
|
||||
[0x04, 0x00, 0x00, 0x00],
|
||||
[0x08, 0x00, 0x00, 0x00],
|
||||
[0x10, 0x00, 0x00, 0x00],
|
||||
[0x20, 0x00, 0x00, 0x00],
|
||||
[0x40, 0x00, 0x00, 0x00],
|
||||
[0x80, 0x00, 0x00, 0x00],
|
||||
[0x1b, 0x00, 0x00, 0x00],
|
||||
[0x36, 0x00, 0x00, 0x00] ];
|
||||
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
/*
|
||||
* Use AES to encrypt 'plaintext' with 'password' using 'nBits' key, in 'Counter' mode of operation
|
||||
* - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||
* for each block
|
||||
* - outputblock = cipher(counter, key)
|
||||
* - cipherblock = plaintext xor outputblock
|
||||
*/
|
||||
function AESEncryptCtr(plaintext, password, nBits) {
|
||||
if (!(nBits==128 || nBits==192 || nBits==256)) return ''; // standard allows 128/192/256 bit keys
|
||||
|
||||
// for this example script, generate the key by applying Cipher to 1st 16/24/32 chars of password;
|
||||
// for real-world applications, a more secure approach would be to hash the password e.g. with SHA-1
|
||||
var nBytes = nBits/8; // no bytes in key
|
||||
var pwBytes = new Array(nBytes);
|
||||
for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
|
||||
var key = Cipher(pwBytes, KeyExpansion(pwBytes));
|
||||
key = key.concat(key.slice(0, nBytes-16)); // key is now 16/24/32 bytes long
|
||||
|
||||
// initialise counter block (NIST SP800-38A §B.2): millisecond time-stamp for nonce in 1st 8 bytes,
|
||||
// block counter in 2nd 8 bytes
|
||||
var blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
|
||||
var counterBlock = new Array(blockSize); // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
|
||||
var nonce = (new Date()).getTime(); // milliseconds since 1-Jan-1970
|
||||
|
||||
// encode nonce in two stages to cater for JavaScript 32-bit limit on bitwise ops
|
||||
for (var i=0; i<4; i++) counterBlock[i] = (nonce >>> i*8) & 0xff;
|
||||
for (var i=0; i<4; i++) counterBlock[i+4] = (nonce/0x100000000 >>> i*8) & 0xff;
|
||||
|
||||
// generate key schedule - an expansion of the key into distinct Key Rounds for each round
|
||||
var keySchedule = KeyExpansion(key);
|
||||
|
||||
var blockCount = Math.ceil(plaintext.length/blockSize);
|
||||
var ciphertext = new Array(blockCount); // ciphertext as array of strings
|
||||
|
||||
for (var b=0; b<blockCount; b++) {
|
||||
// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
|
||||
// again done in two stages for 32-bit ops
|
||||
for (var c=0; c<4; c++) counterBlock[15-c] = (b >>> c*8) & 0xff;
|
||||
for (var c=0; c<4; c++) counterBlock[15-c-4] = (b/0x100000000 >>> c*8)
|
||||
|
||||
var cipherCntr = Cipher(counterBlock, keySchedule); // -- encrypt counter block --
|
||||
|
||||
// calculate length of final block:
|
||||
var blockLength = b<blockCount-1 ? blockSize : (plaintext.length-1)%blockSize+1;
|
||||
|
||||
var ct = '';
|
||||
for (var i=0; i<blockLength; i++) { // -- xor plaintext with ciphered counter byte-by-byte --
|
||||
var plaintextByte = plaintext.charCodeAt(b*blockSize+i);
|
||||
var cipherByte = plaintextByte ^ cipherCntr[i];
|
||||
ct += String.fromCharCode(cipherByte);
|
||||
}
|
||||
// ct is now ciphertext for this block
|
||||
|
||||
ciphertext[b] = escCtrlChars(ct); // escape troublesome characters in ciphertext
|
||||
}
|
||||
|
||||
// convert the nonce to a string to go on the front of the ciphertext
|
||||
var ctrTxt = '';
|
||||
for (var i=0; i<8; i++) ctrTxt += String.fromCharCode(counterBlock[i]);
|
||||
ctrTxt = escCtrlChars(ctrTxt);
|
||||
|
||||
// use '-' to separate blocks, use Array.join to concatenate arrays of strings for efficiency
|
||||
return ctrTxt + '-' + ciphertext.join('-');
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Use AES to decrypt 'ciphertext' with 'password' using 'nBits' key, in Counter mode of operation
|
||||
*
|
||||
* for each block
|
||||
* - outputblock = cipher(counter, key)
|
||||
* - cipherblock = plaintext xor outputblock
|
||||
*/
|
||||
function AESDecryptCtr(ciphertext, password, nBits) {
|
||||
if (!(nBits==128 || nBits==192 || nBits==256)) return ''; // standard allows 128/192/256 bit keys
|
||||
|
||||
var nBytes = nBits/8; // no bytes in key
|
||||
var pwBytes = new Array(nBytes);
|
||||
for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
|
||||
var pwKeySchedule = KeyExpansion(pwBytes);
|
||||
var key = Cipher(pwBytes, pwKeySchedule);
|
||||
key = key.concat(key.slice(0, nBytes-16)); // key is now 16/24/32 bytes long
|
||||
|
||||
var keySchedule = KeyExpansion(key);
|
||||
|
||||
ciphertext = ciphertext.split('-'); // split ciphertext into array of block-length strings
|
||||
|
||||
// recover nonce from 1st element of ciphertext
|
||||
var blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
|
||||
var counterBlock = new Array(blockSize);
|
||||
var ctrTxt = unescCtrlChars(ciphertext[0]);
|
||||
for (var i=0; i<8; i++) counterBlock[i] = ctrTxt.charCodeAt(i);
|
||||
|
||||
var plaintext = new Array(ciphertext.length-1);
|
||||
|
||||
for (var b=1; b<ciphertext.length; b++) {
|
||||
// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
|
||||
for (var c=0; c<4; c++) counterBlock[15-c] = ((b-1) >>> c*8) & 0xff;
|
||||
for (var c=0; c<4; c++) counterBlock[15-c-4] = ((b/0x100000000-1) >>> c*8) & 0xff;
|
||||
|
||||
var cipherCntr = Cipher(counterBlock, keySchedule); // encrypt counter block
|
||||
|
||||
ciphertext[b] = unescCtrlChars(ciphertext[b]);
|
||||
|
||||
var pt = '';
|
||||
for (var i=0; i<ciphertext[b].length; i++) {
|
||||
// -- xor plaintext with ciphered counter byte-by-byte --
|
||||
var ciphertextByte = ciphertext[b].charCodeAt(i);
|
||||
var plaintextByte = ciphertextByte ^ cipherCntr[i];
|
||||
pt += String.fromCharCode(plaintextByte);
|
||||
}
|
||||
// pt is now plaintext for this block
|
||||
|
||||
plaintext[b-1] = pt; // b-1 'cos no initial nonce block in plaintext
|
||||
}
|
||||
|
||||
return plaintext.join('');
|
||||
}
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
function escCtrlChars(str) { // escape control chars which might cause problems handling ciphertext
|
||||
return str.replace(/[\0\t\n\v\f\r\xa0'"!-]/g, function(c) { return '!' + c.charCodeAt(0) + '!'; });
|
||||
} // \xa0 to cater for bug in Firefox; include '-' to leave it free for use as a block marker
|
||||
|
||||
function unescCtrlChars(str) { // unescape potentially problematic control characters
|
||||
return str.replace(/!\d\d?\d?!/g, function(c) { return String.fromCharCode(c.slice(1,-1)); });
|
||||
}
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
/*
|
||||
* if escCtrlChars()/unescCtrlChars() still gives problems, use encodeBase64()/decodeBase64() instead
|
||||
*/
|
||||
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
function encodeBase64(str) { // http://tools.ietf.org/html/rfc4648
|
||||
var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc='';
|
||||
|
||||
str = encodeUTF8(str); // encode multi-byte chars into UTF-8 for byte-array
|
||||
|
||||
do { // pack three octets into four hexets
|
||||
o1 = str.charCodeAt(i++);
|
||||
o2 = str.charCodeAt(i++);
|
||||
o3 = str.charCodeAt(i++);
|
||||
|
||||
bits = o1<<16 | o2<<8 | o3;
|
||||
|
||||
h1 = bits>>18 & 0x3f;
|
||||
h2 = bits>>12 & 0x3f;
|
||||
h3 = bits>>6 & 0x3f;
|
||||
h4 = bits & 0x3f;
|
||||
|
||||
// end of string? index to '=' in b64
|
||||
if (isNaN(o3)) h4 = 64;
|
||||
if (isNaN(o2)) h3 = 64;
|
||||
|
||||
// use hexets to index into b64, and append result to encoded string
|
||||
enc += b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
|
||||
} while (i < str.length);
|
||||
|
||||
return enc;
|
||||
}
|
||||
|
||||
function decodeBase64(str) {
|
||||
var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc='';
|
||||
|
||||
do { // unpack four hexets into three octets using index points in b64
|
||||
h1 = b64.indexOf(str.charAt(i++));
|
||||
h2 = b64.indexOf(str.charAt(i++));
|
||||
h3 = b64.indexOf(str.charAt(i++));
|
||||
h4 = b64.indexOf(str.charAt(i++));
|
||||
|
||||
bits = h1<<18 | h2<<12 | h3<<6 | h4;
|
||||
|
||||
o1 = bits>>16 & 0xff;
|
||||
o2 = bits>>8 & 0xff;
|
||||
o3 = bits & 0xff;
|
||||
|
||||
if (h3 == 64) enc += String.fromCharCode(o1);
|
||||
else if (h4 == 64) enc += String.fromCharCode(o1, o2);
|
||||
else enc += String.fromCharCode(o1, o2, o3);
|
||||
} while (i < str.length);
|
||||
|
||||
return decodeUTF8(enc); // decode UTF-8 byte-array back to Unicode
|
||||
}
|
||||
|
||||
function encodeUTF8(str) { // encode multi-byte string into utf-8 multiple single-byte characters
|
||||
str = str.replace(
|
||||
/[\u0080-\u07ff]/g, // U+0080 - U+07FF = 2-byte chars
|
||||
function(c) {
|
||||
var cc = c.charCodeAt(0);
|
||||
return String.fromCharCode(0xc0 | cc>>6, 0x80 | cc&0x3f); }
|
||||
);
|
||||
str = str.replace(
|
||||
/[\u0800-\uffff]/g, // U+0800 - U+FFFF = 3-byte chars
|
||||
function(c) {
|
||||
var cc = c.charCodeAt(0);
|
||||
return String.fromCharCode(0xe0 | cc>>12, 0x80 | cc>>6&0x3F, 0x80 | cc&0x3f); }
|
||||
);
|
||||
return str;
|
||||
}
|
||||
|
||||
function decodeUTF8(str) { // decode utf-8 encoded string back into multi-byte characters
|
||||
str = str.replace(
|
||||
/[\u00c0-\u00df][\u0080-\u00bf]/g, // 2-byte chars
|
||||
function(c) {
|
||||
var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f;
|
||||
return String.fromCharCode(cc); }
|
||||
);
|
||||
str = str.replace(
|
||||
/[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, // 3-byte chars
|
||||
function(c) {
|
||||
var cc = (c.charCodeAt(0)&0x0f)<<12 | (c.charCodeAt(1)&0x3f<<6) | c.charCodeAt(2)&0x3f;
|
||||
return String.fromCharCode(cc); }
|
||||
);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
function byteArrayToHexStr(b) { // convert byte array to hex string for displaying test vectors
|
||||
var s = '';
|
||||
for (var i=0; i<b.length; i++) s += b[i].toString(16) + ' ';
|
||||
return s;
|
||||
}
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
var plainText = "ROMEO: But, soft! what light through yonder window breaks?\n\
|
||||
It is the east, and Juliet is the sun.\n\
|
||||
Arise, fair sun, and kill the envious moon,\n\
|
||||
Who is already sick and pale with grief,\n\
|
||||
That thou her maid art far more fair than she:\n\
|
||||
Be not her maid, since she is envious;\n\
|
||||
Her vestal livery is but sick and green\n\
|
||||
And none but fools do wear it; cast it off.\n\
|
||||
It is my lady, O, it is my love!\n\
|
||||
O, that she knew she were!\n\
|
||||
She speaks yet she says nothing: what of that?\n\
|
||||
Her eye discourses; I will answer it.\n\
|
||||
I am too bold, 'tis not to me she speaks:\n\
|
||||
Two of the fairest stars in all the heaven,\n\
|
||||
Having some business, do entreat her eyes\n\
|
||||
To twinkle in their spheres till they return.\n\
|
||||
What if her eyes were there, they in her head?\n\
|
||||
The brightness of her cheek would shame those stars,\n\
|
||||
As daylight doth a lamp; her eyes in heaven\n\
|
||||
Would through the airy region stream so bright\n\
|
||||
That birds would sing and think it were not night.\n\
|
||||
See, how she leans her cheek upon her hand!\n\
|
||||
O, that I were a glove upon that hand,\n\
|
||||
That I might touch that cheek!\n\
|
||||
JULIET: Ay me!\n\
|
||||
ROMEO: She speaks:\n\
|
||||
O, speak again, bright angel! for thou art\n\
|
||||
As glorious to this night, being o'er my head\n\
|
||||
As is a winged messenger of heaven\n\
|
||||
Unto the white-upturned wondering eyes\n\
|
||||
Of mortals that fall back to gaze on him\n\
|
||||
When he bestrides the lazy-pacing clouds\n\
|
||||
And sails upon the bosom of the air.";
|
||||
|
||||
var password = "O Romeo, Romeo! wherefore art thou Romeo?";
|
||||
|
||||
var cipherText = AESEncryptCtr(plainText, password, 256);
|
||||
var decryptedText = AESDecryptCtr(cipherText, password, 256);
|
|
@ -1,286 +0,0 @@
|
|||
/*
|
||||
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
|
||||
* Digest Algorithm, as defined in RFC 1321.
|
||||
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
|
||||
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
||||
* Distributed under the BSD License
|
||||
* See http://pajhome.org.uk/crypt/md5 for more info.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Configurable variables. You may need to tweak these to be compatible with
|
||||
* the server-side, but the defaults work in most cases.
|
||||
*/
|
||||
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
|
||||
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
|
||||
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
|
||||
|
||||
/*
|
||||
* These are the functions you'll usually want to call
|
||||
* They take string arguments and return either hex or base-64 encoded strings
|
||||
*/
|
||||
function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
|
||||
function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
|
||||
function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
|
||||
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
|
||||
function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
|
||||
function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
|
||||
|
||||
/*
|
||||
* Perform a simple self-test to see if the VM is working
|
||||
*/
|
||||
function md5_vm_test()
|
||||
{
|
||||
return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the MD5 of an array of little-endian words, and a bit length
|
||||
*/
|
||||
function core_md5(x, len)
|
||||
{
|
||||
/* append padding */
|
||||
x[len >> 5] |= 0x80 << ((len) % 32);
|
||||
x[(((len + 64) >>> 9) << 4) + 14] = len;
|
||||
|
||||
var a = 1732584193;
|
||||
var b = -271733879;
|
||||
var c = -1732584194;
|
||||
var d = 271733878;
|
||||
|
||||
for(var i = 0; i < x.length; i += 16)
|
||||
{
|
||||
var olda = a;
|
||||
var oldb = b;
|
||||
var oldc = c;
|
||||
var oldd = d;
|
||||
|
||||
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
|
||||
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
|
||||
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
|
||||
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
|
||||
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
|
||||
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
|
||||
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
|
||||
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
|
||||
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
|
||||
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
|
||||
c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
|
||||
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
|
||||
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
|
||||
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
|
||||
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
|
||||
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
|
||||
|
||||
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
|
||||
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
|
||||
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
|
||||
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
|
||||
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
|
||||
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
|
||||
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
|
||||
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
|
||||
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
|
||||
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
|
||||
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
|
||||
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
|
||||
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
|
||||
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
|
||||
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
|
||||
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
|
||||
|
||||
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
|
||||
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
|
||||
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
|
||||
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
|
||||
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
|
||||
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
|
||||
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
|
||||
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
|
||||
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
|
||||
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
|
||||
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
|
||||
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
|
||||
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
|
||||
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
|
||||
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
|
||||
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
|
||||
|
||||
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
|
||||
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
|
||||
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
|
||||
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
|
||||
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
|
||||
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
|
||||
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
|
||||
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
|
||||
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
|
||||
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
|
||||
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
|
||||
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
|
||||
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
|
||||
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
|
||||
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
|
||||
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
|
||||
|
||||
a = safe_add(a, olda);
|
||||
b = safe_add(b, oldb);
|
||||
c = safe_add(c, oldc);
|
||||
d = safe_add(d, oldd);
|
||||
}
|
||||
return Array(a, b, c, d);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* These functions implement the four basic operations the algorithm uses.
|
||||
*/
|
||||
function md5_cmn(q, a, b, x, s, t)
|
||||
{
|
||||
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
|
||||
}
|
||||
function md5_ff(a, b, c, d, x, s, t)
|
||||
{
|
||||
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
|
||||
}
|
||||
function md5_gg(a, b, c, d, x, s, t)
|
||||
{
|
||||
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
|
||||
}
|
||||
function md5_hh(a, b, c, d, x, s, t)
|
||||
{
|
||||
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
|
||||
}
|
||||
function md5_ii(a, b, c, d, x, s, t)
|
||||
{
|
||||
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the HMAC-MD5, of a key and some data
|
||||
*/
|
||||
function core_hmac_md5(key, data)
|
||||
{
|
||||
var bkey = str2binl(key);
|
||||
if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
|
||||
|
||||
var ipad = Array(16), opad = Array(16);
|
||||
for(var i = 0; i < 16; i++)
|
||||
{
|
||||
ipad[i] = bkey[i] ^ 0x36363636;
|
||||
opad[i] = bkey[i] ^ 0x5C5C5C5C;
|
||||
}
|
||||
|
||||
var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
|
||||
return core_md5(opad.concat(hash), 512 + 128);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
|
||||
* to work around bugs in some JS interpreters.
|
||||
*/
|
||||
function safe_add(x, y)
|
||||
{
|
||||
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
|
||||
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
||||
return (msw << 16) | (lsw & 0xFFFF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bitwise rotate a 32-bit number to the left.
|
||||
*/
|
||||
function bit_rol(num, cnt)
|
||||
{
|
||||
return (num << cnt) | (num >>> (32 - cnt));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a string to an array of little-endian words
|
||||
* If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
|
||||
*/
|
||||
function str2binl(str)
|
||||
{
|
||||
var bin = Array();
|
||||
var mask = (1 << chrsz) - 1;
|
||||
for(var i = 0; i < str.length * chrsz; i += chrsz)
|
||||
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
|
||||
return bin;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of little-endian words to a string
|
||||
*/
|
||||
function binl2str(bin)
|
||||
{
|
||||
var str = "";
|
||||
var mask = (1 << chrsz) - 1;
|
||||
for(var i = 0; i < bin.length * 32; i += chrsz)
|
||||
str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of little-endian words to a hex string.
|
||||
*/
|
||||
function binl2hex(binarray)
|
||||
{
|
||||
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
|
||||
var str = "";
|
||||
for(var i = 0; i < binarray.length * 4; i++)
|
||||
{
|
||||
str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
|
||||
hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of little-endian words to a base-64 string
|
||||
*/
|
||||
function binl2b64(binarray)
|
||||
{
|
||||
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
var str = "";
|
||||
for(var i = 0; i < binarray.length * 4; i += 3)
|
||||
{
|
||||
var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
|
||||
| (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
|
||||
| ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
|
||||
for(var j = 0; j < 4; j++)
|
||||
{
|
||||
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
|
||||
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
var plainText = "Rebellious subjects, enemies to peace,\n\
|
||||
Profaners of this neighbour-stained steel,--\n\
|
||||
Will they not hear? What, ho! you men, you beasts,\n\
|
||||
That quench the fire of your pernicious rage\n\
|
||||
With purple fountains issuing from your veins,\n\
|
||||
On pain of torture, from those bloody hands\n\
|
||||
Throw your mistemper'd weapons to the ground,\n\
|
||||
And hear the sentence of your moved prince.\n\
|
||||
Three civil brawls, bred of an airy word,\n\
|
||||
By thee, old Capulet, and Montague,\n\
|
||||
Have thrice disturb'd the quiet of our streets,\n\
|
||||
And made Verona's ancient citizens\n\
|
||||
Cast by their grave beseeming ornaments,\n\
|
||||
To wield old partisans, in hands as old,\n\
|
||||
Canker'd with peace, to part your canker'd hate:\n\
|
||||
If ever you disturb our streets again,\n\
|
||||
Your lives shall pay the forfeit of the peace.\n\
|
||||
For this time, all the rest depart away:\n\
|
||||
You Capulet; shall go along with me:\n\
|
||||
And, Montague, come you this afternoon,\n\
|
||||
To know our further pleasure in this case,\n\
|
||||
To old Free-town, our common judgment-place.\n\
|
||||
Once more, on pain of death, all men depart."
|
||||
|
||||
for (var i = 0; i <4; i++) {
|
||||
plainText += plainText;
|
||||
}
|
||||
|
||||
var md5Output = hex_md5(plainText);
|
|
@ -1,224 +0,0 @@
|
|||
/*
|
||||
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
|
||||
* in FIPS PUB 180-1
|
||||
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
|
||||
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
||||
* Distributed under the BSD License
|
||||
* See http://pajhome.org.uk/crypt/md5 for details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Configurable variables. You may need to tweak these to be compatible with
|
||||
* the server-side, but the defaults work in most cases.
|
||||
*/
|
||||
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
|
||||
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
|
||||
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
|
||||
|
||||
/*
|
||||
* These are the functions you'll usually want to call
|
||||
* They take string arguments and return either hex or base-64 encoded strings
|
||||
*/
|
||||
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
|
||||
function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
|
||||
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
|
||||
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
|
||||
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
|
||||
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
|
||||
|
||||
/*
|
||||
* Perform a simple self-test to see if the VM is working
|
||||
*/
|
||||
function sha1_vm_test()
|
||||
{
|
||||
return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the SHA-1 of an array of big-endian words, and a bit length
|
||||
*/
|
||||
function core_sha1(x, len)
|
||||
{
|
||||
/* append padding */
|
||||
x[len >> 5] |= 0x80 << (24 - len % 32);
|
||||
x[((len + 64 >> 9) << 4) + 15] = len;
|
||||
|
||||
var w = Array(80);
|
||||
var a = 1732584193;
|
||||
var b = -271733879;
|
||||
var c = -1732584194;
|
||||
var d = 271733878;
|
||||
var e = -1009589776;
|
||||
|
||||
for(var i = 0; i < x.length; i += 16)
|
||||
{
|
||||
var olda = a;
|
||||
var oldb = b;
|
||||
var oldc = c;
|
||||
var oldd = d;
|
||||
var olde = e;
|
||||
|
||||
for(var j = 0; j < 80; j++)
|
||||
{
|
||||
if(j < 16) w[j] = x[i + j];
|
||||
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
|
||||
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
|
||||
safe_add(safe_add(e, w[j]), sha1_kt(j)));
|
||||
e = d;
|
||||
d = c;
|
||||
c = rol(b, 30);
|
||||
b = a;
|
||||
a = t;
|
||||
}
|
||||
|
||||
a = safe_add(a, olda);
|
||||
b = safe_add(b, oldb);
|
||||
c = safe_add(c, oldc);
|
||||
d = safe_add(d, oldd);
|
||||
e = safe_add(e, olde);
|
||||
}
|
||||
return Array(a, b, c, d, e);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the appropriate triplet combination function for the current
|
||||
* iteration
|
||||
*/
|
||||
function sha1_ft(t, b, c, d)
|
||||
{
|
||||
if(t < 20) return (b & c) | ((~b) & d);
|
||||
if(t < 40) return b ^ c ^ d;
|
||||
if(t < 60) return (b & c) | (b & d) | (c & d);
|
||||
return b ^ c ^ d;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the appropriate additive constant for the current iteration
|
||||
*/
|
||||
function sha1_kt(t)
|
||||
{
|
||||
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
|
||||
(t < 60) ? -1894007588 : -899497514;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the HMAC-SHA1 of a key and some data
|
||||
*/
|
||||
function core_hmac_sha1(key, data)
|
||||
{
|
||||
var bkey = str2binb(key);
|
||||
if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
|
||||
|
||||
var ipad = Array(16), opad = Array(16);
|
||||
for(var i = 0; i < 16; i++)
|
||||
{
|
||||
ipad[i] = bkey[i] ^ 0x36363636;
|
||||
opad[i] = bkey[i] ^ 0x5C5C5C5C;
|
||||
}
|
||||
|
||||
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
|
||||
return core_sha1(opad.concat(hash), 512 + 160);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
|
||||
* to work around bugs in some JS interpreters.
|
||||
*/
|
||||
function safe_add(x, y)
|
||||
{
|
||||
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
|
||||
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
||||
return (msw << 16) | (lsw & 0xFFFF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bitwise rotate a 32-bit number to the left.
|
||||
*/
|
||||
function rol(num, cnt)
|
||||
{
|
||||
return (num << cnt) | (num >>> (32 - cnt));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an 8-bit or 16-bit string to an array of big-endian words
|
||||
* In 8-bit function, characters >255 have their hi-byte silently ignored.
|
||||
*/
|
||||
function str2binb(str)
|
||||
{
|
||||
var bin = Array();
|
||||
var mask = (1 << chrsz) - 1;
|
||||
for(var i = 0; i < str.length * chrsz; i += chrsz)
|
||||
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
|
||||
return bin;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of big-endian words to a string
|
||||
*/
|
||||
function binb2str(bin)
|
||||
{
|
||||
var str = "";
|
||||
var mask = (1 << chrsz) - 1;
|
||||
for(var i = 0; i < bin.length * 32; i += chrsz)
|
||||
str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of big-endian words to a hex string.
|
||||
*/
|
||||
function binb2hex(binarray)
|
||||
{
|
||||
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
|
||||
var str = "";
|
||||
for(var i = 0; i < binarray.length * 4; i++)
|
||||
{
|
||||
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
|
||||
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of big-endian words to a base-64 string
|
||||
*/
|
||||
function binb2b64(binarray)
|
||||
{
|
||||
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
var str = "";
|
||||
for(var i = 0; i < binarray.length * 4; i += 3)
|
||||
{
|
||||
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
|
||||
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
|
||||
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
|
||||
for(var j = 0; j < 4; j++)
|
||||
{
|
||||
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
|
||||
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
var plainText = "Two households, both alike in dignity,\n\
|
||||
In fair Verona, where we lay our scene,\n\
|
||||
From ancient grudge break to new mutiny,\n\
|
||||
Where civil blood makes civil hands unclean.\n\
|
||||
From forth the fatal loins of these two foes\n\
|
||||
A pair of star-cross'd lovers take their life;\n\
|
||||
Whole misadventured piteous overthrows\n\
|
||||
Do with their death bury their parents' strife.\n\
|
||||
The fearful passage of their death-mark'd love,\n\
|
||||
And the continuance of their parents' rage,\n\
|
||||
Which, but their children's end, nought could remove,\n\
|
||||
Is now the two hours' traffic of our stage;\n\
|
||||
The which if you with patient ears attend,\n\
|
||||
What here shall miss, our toil shall strive to mend.";
|
||||
|
||||
for (var i = 0; i <4; i++) {
|
||||
plainText += plainText;
|
||||
}
|
||||
|
||||
var sha1Output = hex_sha1(plainText);
|
|
@ -1,299 +0,0 @@
|
|||
function arrayExists(array, x) {
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
if (array[i] == x) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Date.prototype.formatDate = function (input,time) {
|
||||
// formatDate :
|
||||
// a PHP date like function, for formatting date strings
|
||||
// See: http://www.php.net/date
|
||||
//
|
||||
// input : format string
|
||||
// time : epoch time (seconds, and optional)
|
||||
//
|
||||
// if time is not passed, formatting is based on
|
||||
// the current "this" date object's set time.
|
||||
//
|
||||
// supported:
|
||||
// a, A, B, d, D, F, g, G, h, H, i, j, l (lowercase L), L,
|
||||
// m, M, n, O, r, s, S, t, U, w, W, y, Y, z
|
||||
//
|
||||
// unsupported:
|
||||
// I (capital i), T, Z
|
||||
|
||||
var switches = ["a", "A", "B", "d", "D", "F", "g", "G", "h", "H",
|
||||
"i", "j", "l", "L", "m", "M", "n", "O", "r", "s",
|
||||
"S", "t", "U", "w", "W", "y", "Y", "z"];
|
||||
var daysLong = ["Sunday", "Monday", "Tuesday", "Wednesday",
|
||||
"Thursday", "Friday", "Saturday"];
|
||||
var daysShort = ["Sun", "Mon", "Tue", "Wed",
|
||||
"Thu", "Fri", "Sat"];
|
||||
var monthsShort = ["Jan", "Feb", "Mar", "Apr",
|
||||
"May", "Jun", "Jul", "Aug", "Sep",
|
||||
"Oct", "Nov", "Dec"];
|
||||
var monthsLong = ["January", "February", "March", "April",
|
||||
"May", "June", "July", "August", "September",
|
||||
"October", "November", "December"];
|
||||
var daysSuffix = ["st", "nd", "rd", "th", "th", "th", "th", // 1st - 7th
|
||||
"th", "th", "th", "th", "th", "th", "th", // 8th - 14th
|
||||
"th", "th", "th", "th", "th", "th", "st", // 15th - 21st
|
||||
"nd", "rd", "th", "th", "th", "th", "th", // 22nd - 28th
|
||||
"th", "th", "st"]; // 29th - 31st
|
||||
|
||||
function a() {
|
||||
// Lowercase Ante meridiem and Post meridiem
|
||||
return self.getHours() > 11? "pm" : "am";
|
||||
}
|
||||
function A() {
|
||||
// Uppercase Ante meridiem and Post meridiem
|
||||
return self.getHours() > 11? "PM" : "AM";
|
||||
}
|
||||
|
||||
function B(){
|
||||
// Swatch internet time. code simply grabbed from ppk,
|
||||
// since I was feeling lazy:
|
||||
// http://www.xs4all.nl/~ppk/js/beat.html
|
||||
var off = (self.getTimezoneOffset() + 60)*60;
|
||||
var theSeconds = (self.getHours() * 3600) +
|
||||
(self.getMinutes() * 60) +
|
||||
self.getSeconds() + off;
|
||||
var beat = Math.floor(theSeconds/86.4);
|
||||
if (beat > 1000) beat -= 1000;
|
||||
if (beat < 0) beat += 1000;
|
||||
if ((""+beat).length == 1) beat = "00"+beat;
|
||||
if ((""+beat).length == 2) beat = "0"+beat;
|
||||
return beat;
|
||||
}
|
||||
|
||||
function d() {
|
||||
// Day of the month, 2 digits with leading zeros
|
||||
return new String(self.getDate()).length == 1?
|
||||
"0"+self.getDate() : self.getDate();
|
||||
}
|
||||
function D() {
|
||||
// A textual representation of a day, three letters
|
||||
return daysShort[self.getDay()];
|
||||
}
|
||||
function F() {
|
||||
// A full textual representation of a month
|
||||
return monthsLong[self.getMonth()];
|
||||
}
|
||||
function g() {
|
||||
// 12-hour format of an hour without leading zeros
|
||||
return self.getHours() > 12? self.getHours()-12 : self.getHours();
|
||||
}
|
||||
function G() {
|
||||
// 24-hour format of an hour without leading zeros
|
||||
return self.getHours();
|
||||
}
|
||||
function h() {
|
||||
// 12-hour format of an hour with leading zeros
|
||||
if (self.getHours() > 12) {
|
||||
var s = new String(self.getHours()-12);
|
||||
return s.length == 1?
|
||||
"0"+ (self.getHours()-12) : self.getHours()-12;
|
||||
} else {
|
||||
var s = new String(self.getHours());
|
||||
return s.length == 1?
|
||||
"0"+self.getHours() : self.getHours();
|
||||
}
|
||||
}
|
||||
function H() {
|
||||
// 24-hour format of an hour with leading zeros
|
||||
return new String(self.getHours()).length == 1?
|
||||
"0"+self.getHours() : self.getHours();
|
||||
}
|
||||
function i() {
|
||||
// Minutes with leading zeros
|
||||
return new String(self.getMinutes()).length == 1?
|
||||
"0"+self.getMinutes() : self.getMinutes();
|
||||
}
|
||||
function j() {
|
||||
// Day of the month without leading zeros
|
||||
return self.getDate();
|
||||
}
|
||||
function l() {
|
||||
// A full textual representation of the day of the week
|
||||
return daysLong[self.getDay()];
|
||||
}
|
||||
function L() {
|
||||
// leap year or not. 1 if leap year, 0 if not.
|
||||
// the logic should match iso's 8601 standard.
|
||||
var y_ = Y();
|
||||
if (
|
||||
(y_ % 4 == 0 && y_ % 100 != 0) ||
|
||||
(y_ % 4 == 0 && y_ % 100 == 0 && y_ % 400 == 0)
|
||||
) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
function m() {
|
||||
// Numeric representation of a month, with leading zeros
|
||||
return self.getMonth() < 9?
|
||||
"0"+(self.getMonth()+1) :
|
||||
self.getMonth()+1;
|
||||
}
|
||||
function M() {
|
||||
// A short textual representation of a month, three letters
|
||||
return monthsShort[self.getMonth()];
|
||||
}
|
||||
function n() {
|
||||
// Numeric representation of a month, without leading zeros
|
||||
return self.getMonth()+1;
|
||||
}
|
||||
function O() {
|
||||
// Difference to Greenwich time (GMT) in hours
|
||||
var os = Math.abs(self.getTimezoneOffset());
|
||||
var h = ""+Math.floor(os/60);
|
||||
var m = ""+(os%60);
|
||||
h.length == 1? h = "0"+h:1;
|
||||
m.length == 1? m = "0"+m:1;
|
||||
return self.getTimezoneOffset() < 0 ? "+"+h+m : "-"+h+m;
|
||||
}
|
||||
function r() {
|
||||
// RFC 822 formatted date
|
||||
var r; // result
|
||||
// Thu , 21 Dec 2000
|
||||
r = D() + ", " + j() + " " + M() + " " + Y() +
|
||||
// 16 : 01 : 07 +0200
|
||||
" " + H() + ":" + i() + ":" + s() + " " + O();
|
||||
return r;
|
||||
}
|
||||
function S() {
|
||||
// English ordinal suffix for the day of the month, 2 characters
|
||||
return daysSuffix[self.getDate()-1];
|
||||
}
|
||||
function s() {
|
||||
// Seconds, with leading zeros
|
||||
return new String(self.getSeconds()).length == 1?
|
||||
"0"+self.getSeconds() : self.getSeconds();
|
||||
}
|
||||
function t() {
|
||||
|
||||
// thanks to Matt Bannon for some much needed code-fixes here!
|
||||
var daysinmonths = [null,31,28,31,30,31,30,31,31,30,31,30,31];
|
||||
if (L()==1 && n()==2) return 29; // leap day
|
||||
return daysinmonths[n()];
|
||||
}
|
||||
function U() {
|
||||
// Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
|
||||
return Math.round(self.getTime()/1000);
|
||||
}
|
||||
function W() {
|
||||
// Weeknumber, as per ISO specification:
|
||||
// http://www.cl.cam.ac.uk/~mgk25/iso-time.html
|
||||
|
||||
// if the day is three days before newyears eve,
|
||||
// there's a chance it's "week 1" of next year.
|
||||
// here we check for that.
|
||||
var beforeNY = 364+L() - z();
|
||||
var afterNY = z();
|
||||
var weekday = w()!=0?w()-1:6; // makes sunday (0), into 6.
|
||||
if (beforeNY <= 2 && weekday <= 2-beforeNY) {
|
||||
return 1;
|
||||
}
|
||||
// similarly, if the day is within threedays of newyears
|
||||
// there's a chance it belongs in the old year.
|
||||
var ny = new Date("January 1 " + Y() + " 00:00:00");
|
||||
var nyDay = ny.getDay()!=0?ny.getDay()-1:6;
|
||||
if (
|
||||
(afterNY <= 2) &&
|
||||
(nyDay >=4) &&
|
||||
(afterNY >= (6-nyDay))
|
||||
) {
|
||||
// Since I'm not sure we can just always return 53,
|
||||
// i call the function here again, using the last day
|
||||
// of the previous year, as the date, and then just
|
||||
// return that week.
|
||||
var prevNY = new Date("December 31 " + (Y()-1) + " 00:00:00");
|
||||
return prevNY.formatDate("W");
|
||||
}
|
||||
|
||||
// week 1, is the week that has the first thursday in it.
|
||||
// note that this value is not zero index.
|
||||
if (nyDay <= 3) {
|
||||
// first day of the year fell on a thursday, or earlier.
|
||||
return 1 + Math.floor( ( z() + nyDay ) / 7 );
|
||||
} else {
|
||||
// first day of the year fell on a friday, or later.
|
||||
return 1 + Math.floor( ( z() - ( 7 - nyDay ) ) / 7 );
|
||||
}
|
||||
}
|
||||
function w() {
|
||||
// Numeric representation of the day of the week
|
||||
return self.getDay();
|
||||
}
|
||||
|
||||
function Y() {
|
||||
// A full numeric representation of a year, 4 digits
|
||||
|
||||
// we first check, if getFullYear is supported. if it
|
||||
// is, we just use that. ppks code is nice, but wont
|
||||
// work with dates outside 1900-2038, or something like that
|
||||
if (self.getFullYear) {
|
||||
var newDate = new Date("January 1 2001 00:00:00 +0000");
|
||||
var x = newDate .getFullYear();
|
||||
if (x == 2001) {
|
||||
// i trust the method now
|
||||
return self.getFullYear();
|
||||
}
|
||||
}
|
||||
// else, do this:
|
||||
// codes thanks to ppk:
|
||||
// http://www.xs4all.nl/~ppk/js/introdate.html
|
||||
var x = self.getYear();
|
||||
var y = x % 100;
|
||||
y += (y < 38) ? 2000 : 1900;
|
||||
return y;
|
||||
}
|
||||
function y() {
|
||||
// A two-digit representation of a year
|
||||
var y = Y()+"";
|
||||
return y.substring(y.length-2,y.length);
|
||||
}
|
||||
function z() {
|
||||
// The day of the year, zero indexed! 0 through 366
|
||||
var t = new Date("January 1 " + Y() + " 00:00:00");
|
||||
var diff = self.getTime() - t.getTime();
|
||||
return Math.floor(diff/1000/60/60/24);
|
||||
}
|
||||
|
||||
var self = this;
|
||||
if (time) {
|
||||
// save time
|
||||
var prevTime = self.getTime();
|
||||
self.setTime(time);
|
||||
}
|
||||
|
||||
var ia = input.split("");
|
||||
var ij = 0;
|
||||
while (ia[ij]) {
|
||||
if (ia[ij] == "\\") {
|
||||
// this is our way of allowing users to escape stuff
|
||||
ia.splice(ij,1);
|
||||
} else {
|
||||
if (arrayExists(switches,ia[ij])) {
|
||||
ia[ij] = eval(ia[ij] + "()");
|
||||
}
|
||||
}
|
||||
ij++;
|
||||
}
|
||||
// reset time, back to what it was
|
||||
if (prevTime) {
|
||||
self.setTime(prevTime);
|
||||
}
|
||||
return ia.join("");
|
||||
}
|
||||
|
||||
var date = new Date("1/1/2007 1:11:11");
|
||||
|
||||
for (i = 0; i < 500; ++i) {
|
||||
var shortFormat = date.formatDate("Y-m-d");
|
||||
var longFormat = date.formatDate("l, F d, Y g:i:s A");
|
||||
date.setTime(date.getTime() + 84266956);
|
||||
}
|
||||
|
|
@ -1,417 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2004 Baron Schwartz <baron at sequent dot org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, version 2.1.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
Date.parseFunctions = {count:0};
|
||||
Date.parseRegexes = [];
|
||||
Date.formatFunctions = {count:0};
|
||||
|
||||
Date.prototype.dateFormat = function(format) {
|
||||
if (Date.formatFunctions[format] == null) {
|
||||
Date.createNewFormat(format);
|
||||
}
|
||||
var func = Date.formatFunctions[format];
|
||||
return this[func]();
|
||||
}
|
||||
|
||||
Date.createNewFormat = function(format) {
|
||||
var funcName = "format" + Date.formatFunctions.count++;
|
||||
Date.formatFunctions[format] = funcName;
|
||||
var code = "Date.prototype." + funcName + " = function(){return ";
|
||||
var special = false;
|
||||
var ch = '';
|
||||
for (var i = 0; i < format.length; ++i) {
|
||||
ch = format.charAt(i);
|
||||
if (!special && ch == "\\") {
|
||||
special = true;
|
||||
}
|
||||
else if (special) {
|
||||
special = false;
|
||||
code += "'" + String.escape(ch) + "' + ";
|
||||
}
|
||||
else {
|
||||
code += Date.getFormatCode(ch);
|
||||
}
|
||||
}
|
||||
eval(code.substring(0, code.length - 3) + ";}");
|
||||
}
|
||||
|
||||
Date.getFormatCode = function(character) {
|
||||
switch (character) {
|
||||
case "d":
|
||||
return "String.leftPad(this.getDate(), 2, '0') + ";
|
||||
case "D":
|
||||
return "Date.dayNames[this.getDay()].substring(0, 3) + ";
|
||||
case "j":
|
||||
return "this.getDate() + ";
|
||||
case "l":
|
||||
return "Date.dayNames[this.getDay()] + ";
|
||||
case "S":
|
||||
return "this.getSuffix() + ";
|
||||
case "w":
|
||||
return "this.getDay() + ";
|
||||
case "z":
|
||||
return "this.getDayOfYear() + ";
|
||||
case "W":
|
||||
return "this.getWeekOfYear() + ";
|
||||
case "F":
|
||||
return "Date.monthNames[this.getMonth()] + ";
|
||||
case "m":
|
||||
return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
|
||||
case "M":
|
||||
return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
|
||||
case "n":
|
||||
return "(this.getMonth() + 1) + ";
|
||||
case "t":
|
||||
return "this.getDaysInMonth() + ";
|
||||
case "L":
|
||||
return "(this.isLeapYear() ? 1 : 0) + ";
|
||||
case "Y":
|
||||
return "this.getFullYear() + ";
|
||||
case "y":
|
||||
return "('' + this.getFullYear()).substring(2, 4) + ";
|
||||
case "a":
|
||||
return "(this.getHours() < 12 ? 'am' : 'pm') + ";
|
||||
case "A":
|
||||
return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
|
||||
case "g":
|
||||
return "((this.getHours() %12) ? this.getHours() % 12 : 12) + ";
|
||||
case "G":
|
||||
return "this.getHours() + ";
|
||||
case "h":
|
||||
return "String.leftPad((this.getHours() %12) ? this.getHours() % 12 : 12, 2, '0') + ";
|
||||
case "H":
|
||||
return "String.leftPad(this.getHours(), 2, '0') + ";
|
||||
case "i":
|
||||
return "String.leftPad(this.getMinutes(), 2, '0') + ";
|
||||
case "s":
|
||||
return "String.leftPad(this.getSeconds(), 2, '0') + ";
|
||||
case "O":
|
||||
return "this.getGMTOffset() + ";
|
||||
case "T":
|
||||
return "this.getTimezone() + ";
|
||||
case "Z":
|
||||
return "(this.getTimezoneOffset() * -60) + ";
|
||||
default:
|
||||
return "'" + String.escape(character) + "' + ";
|
||||
}
|
||||
}
|
||||
|
||||
Date.parseDate = function(input, format) {
|
||||
if (Date.parseFunctions[format] == null) {
|
||||
Date.createParser(format);
|
||||
}
|
||||
var func = Date.parseFunctions[format];
|
||||
return Date[func](input);
|
||||
}
|
||||
|
||||
Date.createParser = function(format) {
|
||||
var funcName = "parse" + Date.parseFunctions.count++;
|
||||
var regexNum = Date.parseRegexes.length;
|
||||
var currentGroup = 1;
|
||||
Date.parseFunctions[format] = funcName;
|
||||
|
||||
var code = "Date." + funcName + " = function(input){\n"
|
||||
+ "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1;\n"
|
||||
+ "var d = new Date();\n"
|
||||
+ "y = d.getFullYear();\n"
|
||||
+ "m = d.getMonth();\n"
|
||||
+ "d = d.getDate();\n"
|
||||
+ "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
|
||||
+ "if (results && results.length > 0) {"
|
||||
var regex = "";
|
||||
|
||||
var special = false;
|
||||
var ch = '';
|
||||
for (var i = 0; i < format.length; ++i) {
|
||||
ch = format.charAt(i);
|
||||
if (!special && ch == "\\") {
|
||||
special = true;
|
||||
}
|
||||
else if (special) {
|
||||
special = false;
|
||||
regex += String.escape(ch);
|
||||
}
|
||||
else {
|
||||
obj = Date.formatCodeToRegex(ch, currentGroup);
|
||||
currentGroup += obj.g;
|
||||
regex += obj.s;
|
||||
if (obj.g && obj.c) {
|
||||
code += obj.c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
code += "if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
|
||||
+ "{return new Date(y, m, d, h, i, s);}\n"
|
||||
+ "else if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
|
||||
+ "{return new Date(y, m, d, h, i);}\n"
|
||||
+ "else if (y > 0 && m >= 0 && d > 0 && h >= 0)\n"
|
||||
+ "{return new Date(y, m, d, h);}\n"
|
||||
+ "else if (y > 0 && m >= 0 && d > 0)\n"
|
||||
+ "{return new Date(y, m, d);}\n"
|
||||
+ "else if (y > 0 && m >= 0)\n"
|
||||
+ "{return new Date(y, m);}\n"
|
||||
+ "else if (y > 0)\n"
|
||||
+ "{return new Date(y);}\n"
|
||||
+ "}return null;}";
|
||||
|
||||
Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
|
||||
eval(code);
|
||||
}
|
||||
|
||||
Date.formatCodeToRegex = function(character, currentGroup) {
|
||||
switch (character) {
|
||||
case "D":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
|
||||
case "j":
|
||||
case "d":
|
||||
return {g:1,
|
||||
c:"d = parseInt(results[" + currentGroup + "], 10);\n",
|
||||
s:"(\\d{1,2})"};
|
||||
case "l":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"(?:" + Date.dayNames.join("|") + ")"};
|
||||
case "S":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"(?:st|nd|rd|th)"};
|
||||
case "w":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"\\d"};
|
||||
case "z":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"(?:\\d{1,3})"};
|
||||
case "W":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"(?:\\d{2})"};
|
||||
case "F":
|
||||
return {g:1,
|
||||
c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
|
||||
s:"(" + Date.monthNames.join("|") + ")"};
|
||||
case "M":
|
||||
return {g:1,
|
||||
c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
|
||||
s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
|
||||
case "n":
|
||||
case "m":
|
||||
return {g:1,
|
||||
c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
|
||||
s:"(\\d{1,2})"};
|
||||
case "t":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"\\d{1,2}"};
|
||||
case "L":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"(?:1|0)"};
|
||||
case "Y":
|
||||
return {g:1,
|
||||
c:"y = parseInt(results[" + currentGroup + "], 10);\n",
|
||||
s:"(\\d{4})"};
|
||||
case "y":
|
||||
return {g:1,
|
||||
c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
|
||||
+ "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
|
||||
s:"(\\d{1,2})"};
|
||||
case "a":
|
||||
return {g:1,
|
||||
c:"if (results[" + currentGroup + "] == 'am') {\n"
|
||||
+ "if (h == 12) { h = 0; }\n"
|
||||
+ "} else { if (h < 12) { h += 12; }}",
|
||||
s:"(am|pm)"};
|
||||
case "A":
|
||||
return {g:1,
|
||||
c:"if (results[" + currentGroup + "] == 'AM') {\n"
|
||||
+ "if (h == 12) { h = 0; }\n"
|
||||
+ "} else { if (h < 12) { h += 12; }}",
|
||||
s:"(AM|PM)"};
|
||||
case "g":
|
||||
case "G":
|
||||
case "h":
|
||||
case "H":
|
||||
return {g:1,
|
||||
c:"h = parseInt(results[" + currentGroup + "], 10);\n",
|
||||
s:"(\\d{1,2})"};
|
||||
case "i":
|
||||
return {g:1,
|
||||
c:"i = parseInt(results[" + currentGroup + "], 10);\n",
|
||||
s:"(\\d{2})"};
|
||||
case "s":
|
||||
return {g:1,
|
||||
c:"s = parseInt(results[" + currentGroup + "], 10);\n",
|
||||
s:"(\\d{2})"};
|
||||
case "O":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"[+-]\\d{4}"};
|
||||
case "T":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"[A-Z]{3}"};
|
||||
case "Z":
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:"[+-]\\d{1,5}"};
|
||||
default:
|
||||
return {g:0,
|
||||
c:null,
|
||||
s:String.escape(character)};
|
||||
}
|
||||
}
|
||||
|
||||
Date.prototype.getTimezone = function() {
|
||||
return this.toString().replace(
|
||||
/^.*? ([A-Z]{3}) [0-9]{4}.*$/, "$1").replace(
|
||||
/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3");
|
||||
}
|
||||
|
||||
Date.prototype.getGMTOffset = function() {
|
||||
return (this.getTimezoneOffset() > 0 ? "-" : "+")
|
||||
+ String.leftPad(Math.floor(this.getTimezoneOffset() / 60), 2, "0")
|
||||
+ String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
|
||||
}
|
||||
|
||||
Date.prototype.getDayOfYear = function() {
|
||||
var num = 0;
|
||||
Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
|
||||
for (var i = 0; i < this.getMonth(); ++i) {
|
||||
num += Date.daysInMonth[i];
|
||||
}
|
||||
return num + this.getDate() - 1;
|
||||
}
|
||||
|
||||
Date.prototype.getWeekOfYear = function() {
|
||||
// Skip to Thursday of this week
|
||||
var now = this.getDayOfYear() + (4 - this.getDay());
|
||||
// Find the first Thursday of the year
|
||||
var jan1 = new Date(this.getFullYear(), 0, 1);
|
||||
var then = (7 - jan1.getDay() + 4);
|
||||
document.write(then);
|
||||
return String.leftPad(((now - then) / 7) + 1, 2, "0");
|
||||
}
|
||||
|
||||
Date.prototype.isLeapYear = function() {
|
||||
var year = this.getFullYear();
|
||||
return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
|
||||
}
|
||||
|
||||
Date.prototype.getFirstDayOfMonth = function() {
|
||||
var day = (this.getDay() - (this.getDate() - 1)) % 7;
|
||||
return (day < 0) ? (day + 7) : day;
|
||||
}
|
||||
|
||||
Date.prototype.getLastDayOfMonth = function() {
|
||||
var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
|
||||
return (day < 0) ? (day + 7) : day;
|
||||
}
|
||||
|
||||
Date.prototype.getDaysInMonth = function() {
|
||||
Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
|
||||
return Date.daysInMonth[this.getMonth()];
|
||||
}
|
||||
|
||||
Date.prototype.getSuffix = function() {
|
||||
switch (this.getDate()) {
|
||||
case 1:
|
||||
case 21:
|
||||
case 31:
|
||||
return "st";
|
||||
case 2:
|
||||
case 22:
|
||||
return "nd";
|
||||
case 3:
|
||||
case 23:
|
||||
return "rd";
|
||||
default:
|
||||
return "th";
|
||||
}
|
||||
}
|
||||
|
||||
String.escape = function(string) {
|
||||
return string.replace(/('|\\)/g, "\\$1");
|
||||
}
|
||||
|
||||
String.leftPad = function (val, size, ch) {
|
||||
var result = new String(val);
|
||||
if (ch == null) {
|
||||
ch = " ";
|
||||
}
|
||||
while (result.length < size) {
|
||||
result = ch + result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
|
||||
Date.monthNames =
|
||||
["January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July",
|
||||
"August",
|
||||
"September",
|
||||
"October",
|
||||
"November",
|
||||
"December"];
|
||||
Date.dayNames =
|
||||
["Sunday",
|
||||
"Monday",
|
||||
"Tuesday",
|
||||
"Wednesday",
|
||||
"Thursday",
|
||||
"Friday",
|
||||
"Saturday"];
|
||||
Date.y2kYear = 50;
|
||||
Date.monthNumbers = {
|
||||
Jan:0,
|
||||
Feb:1,
|
||||
Mar:2,
|
||||
Apr:3,
|
||||
May:4,
|
||||
Jun:5,
|
||||
Jul:6,
|
||||
Aug:7,
|
||||
Sep:8,
|
||||
Oct:9,
|
||||
Nov:10,
|
||||
Dec:11};
|
||||
Date.patterns = {
|
||||
ISO8601LongPattern:"Y-m-d H:i:s",
|
||||
ISO8601ShortPattern:"Y-m-d",
|
||||
ShortDatePattern: "n/j/Y",
|
||||
LongDatePattern: "l, F d, Y",
|
||||
FullDateTimePattern: "l, F d, Y g:i:s A",
|
||||
MonthDayPattern: "F d",
|
||||
ShortTimePattern: "g:i A",
|
||||
LongTimePattern: "g:i:s A",
|
||||
SortableDateTimePattern: "Y-m-d\\TH:i:s",
|
||||
UniversalSortableDateTimePattern: "Y-m-d H:i:sO",
|
||||
YearMonthPattern: "F, Y"};
|
||||
|
||||
var date = new Date("1/1/2007 1:11:11");
|
||||
|
||||
for (i = 0; i < 4000; ++i) {
|
||||
var shortFormat = date.dateFormat("Y-m-d");
|
||||
var longFormat = date.dateFormat("l, F d, Y g:i:s A");
|
||||
date.setTime(date.getTime() + 84266956);
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Rich Moore. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/////. Start CORDIC
|
||||
|
||||
var AG_CONST = 0.6072529350;
|
||||
|
||||
function FIXED(X)
|
||||
{
|
||||
return X * 65536.0;
|
||||
}
|
||||
|
||||
function FLOAT(X)
|
||||
{
|
||||
return X / 65536.0;
|
||||
}
|
||||
|
||||
function DEG2RAD(X)
|
||||
{
|
||||
return 0.017453 * (X);
|
||||
}
|
||||
|
||||
var Angles = [
|
||||
FIXED(45.0), FIXED(26.565), FIXED(14.0362), FIXED(7.12502),
|
||||
FIXED(3.57633), FIXED(1.78991), FIXED(0.895174), FIXED(0.447614),
|
||||
FIXED(0.223811), FIXED(0.111906), FIXED(0.055953),
|
||||
FIXED(0.027977)
|
||||
];
|
||||
|
||||
|
||||
function cordicsincos() {
|
||||
var X;
|
||||
var Y;
|
||||
var TargetAngle;
|
||||
var CurrAngle;
|
||||
var Step;
|
||||
|
||||
X = FIXED(AG_CONST); /* AG_CONST * cos(0) */
|
||||
Y = 0; /* AG_CONST * sin(0) */
|
||||
|
||||
TargetAngle = FIXED(28.027);
|
||||
CurrAngle = 0;
|
||||
for (Step = 0; Step < 12; Step++) {
|
||||
var NewX;
|
||||
if (TargetAngle > CurrAngle) {
|
||||
NewX = X - (Y >> Step);
|
||||
Y = (X >> Step) + Y;
|
||||
X = NewX;
|
||||
CurrAngle += Angles[Step];
|
||||
} else {
|
||||
NewX = X + (Y >> Step);
|
||||
Y = -(X >> Step) + Y;
|
||||
X = NewX;
|
||||
CurrAngle -= Angles[Step];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///// End CORDIC
|
||||
|
||||
function cordic( runs ) {
|
||||
var start = new Date();
|
||||
|
||||
for ( var i = 0 ; i < runs ; i++ ) {
|
||||
cordicsincos();
|
||||
}
|
||||
|
||||
var end = new Date();
|
||||
|
||||
return end.getTime() - start.getTime();
|
||||
}
|
||||
|
||||
cordic(25000);
|
|
@ -1,33 +0,0 @@
|
|||
// The Computer Language Shootout
|
||||
// http://shootout.alioth.debian.org/
|
||||
// contributed by Isaac Gouy
|
||||
|
||||
function partial(n){
|
||||
var a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 0.0;
|
||||
var twothirds = 2.0/3.0;
|
||||
var alt = -1.0;
|
||||
var k2 = k3 = sk = ck = 0.0;
|
||||
|
||||
for (var k = 1; k <= n; k++){
|
||||
k2 = k*k;
|
||||
k3 = k2*k;
|
||||
sk = Math.sin(k);
|
||||
ck = Math.cos(k);
|
||||
alt = -alt;
|
||||
|
||||
a1 += Math.pow(twothirds,k-1);
|
||||
a2 += Math.pow(k,-0.5);
|
||||
a3 += 1.0/(k*(k+1.0));
|
||||
a4 += 1.0/(k3 * sk*sk);
|
||||
a5 += 1.0/(k3 * ck*ck);
|
||||
a6 += 1.0/k;
|
||||
a7 += 1.0/k2;
|
||||
a8 += alt/k;
|
||||
a9 += alt/(2*k -1);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 1024; i <= 16384; i *= 2) {
|
||||
partial(i);
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
// The Great Computer Language Shootout
|
||||
// http://shootout.alioth.debian.org/
|
||||
//
|
||||
// contributed by Ian Osgood
|
||||
|
||||
function A(i,j) {
|
||||
return 1/((i+j)*(i+j+1)/2+i+1);
|
||||
}
|
||||
|
||||
function Au(u,v) {
|
||||
for (var i=0; i<u.length; ++i) {
|
||||
var t = 0;
|
||||
for (var j=0; j<u.length; ++j)
|
||||
t += A(i,j) * u[j];
|
||||
v[i] = t;
|
||||
}
|
||||
}
|
||||
|
||||
function Atu(u,v) {
|
||||
for (var i=0; i<u.length; ++i) {
|
||||
var t = 0;
|
||||
for (var j=0; j<u.length; ++j)
|
||||
t += A(j,i) * u[j];
|
||||
v[i] = t;
|
||||
}
|
||||
}
|
||||
|
||||
function AtAu(u,v,w) {
|
||||
Au(u,w);
|
||||
Atu(w,v);
|
||||
}
|
||||
|
||||
function spectralnorm(n) {
|
||||
var i, u=[], v=[], w=[], vv=0, vBv=0;
|
||||
for (i=0; i<n; ++i) {
|
||||
u[i] = 1; v[i] = w[i] = 0;
|
||||
}
|
||||
for (i=0; i<10; ++i) {
|
||||
AtAu(u,v,w);
|
||||
AtAu(v,u,w);
|
||||
}
|
||||
for (i=0; i<n; ++i) {
|
||||
vBv += u[i]*v[i];
|
||||
vv += v[i]*v[i];
|
||||
}
|
||||
return Math.sqrt(vBv/vv);
|
||||
}
|
||||
|
||||
for (var i = 6; i <= 48; i *= 2) {
|
||||
spectralnorm(i);
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,135 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla XML-RPC Client component.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Digital Creations 2, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Martijn Pieters <mj@digicool.com> (original author)
|
||||
* Samuel Sieb <samuel@sieb.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// From: http://lxr.mozilla.org/mozilla/source/extensions/xml-rpc/src/nsXmlRpcClient.js#956
|
||||
|
||||
/* Convert data (an array of integers) to a Base64 string. */
|
||||
var toBase64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||
var base64Pad = '=';
|
||||
|
||||
function toBase64(data) {
|
||||
var result = '';
|
||||
var length = data.length;
|
||||
var i;
|
||||
// Convert every three bytes to 4 ascii characters.
|
||||
for (i = 0; i < (length - 2); i += 3) {
|
||||
result += toBase64Table[data.charCodeAt(i) >> 2];
|
||||
result += toBase64Table[((data.charCodeAt(i) & 0x03) << 4) + (data.charCodeAt(i+1) >> 4)];
|
||||
result += toBase64Table[((data.charCodeAt(i+1) & 0x0f) << 2) + (data.charCodeAt(i+2) >> 6)];
|
||||
result += toBase64Table[data.charCodeAt(i+2) & 0x3f];
|
||||
}
|
||||
|
||||
// Convert the remaining 1 or 2 bytes, pad out to 4 characters.
|
||||
if (length%3) {
|
||||
i = length - (length%3);
|
||||
result += toBase64Table[data.charCodeAt(i) >> 2];
|
||||
if ((length%3) == 2) {
|
||||
result += toBase64Table[((data.charCodeAt(i) & 0x03) << 4) + (data.charCodeAt(i+1) >> 4)];
|
||||
result += toBase64Table[(data.charCodeAt(i+1) & 0x0f) << 2];
|
||||
result += base64Pad;
|
||||
} else {
|
||||
result += toBase64Table[(data.charCodeAt(i) & 0x03) << 4];
|
||||
result += base64Pad + base64Pad;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Convert Base64 data to a string */
|
||||
var toBinaryTable = [
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
|
||||
52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1,
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
|
||||
15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
|
||||
-1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
|
||||
41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
|
||||
];
|
||||
|
||||
function base64ToString(data) {
|
||||
var result = '';
|
||||
var leftbits = 0; // number of bits decoded, but yet to be appended
|
||||
var leftdata = 0; // bits decoded, but yet to be appended
|
||||
|
||||
// Convert one by one.
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var c = toBinaryTable[data.charCodeAt(i) & 0x7f];
|
||||
var padding = (data.charCodeAt(i) == base64Pad.charCodeAt(0));
|
||||
// Skip illegal characters and whitespace
|
||||
if (c == -1) continue;
|
||||
|
||||
// Collect data into leftdata, update bitcount
|
||||
leftdata = (leftdata << 6) | c;
|
||||
leftbits += 6;
|
||||
|
||||
// If we have 8 or more bits, append 8 bits to the result
|
||||
if (leftbits >= 8) {
|
||||
leftbits -= 8;
|
||||
// Append if not padding.
|
||||
if (!padding)
|
||||
result += String.fromCharCode((leftdata >> leftbits) & 0xff);
|
||||
leftdata &= (1 << leftbits) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are any bits left, the base64 string was corrupted
|
||||
if (leftbits)
|
||||
throw Components.Exception('Corrupted base64 string');
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var str = "";
|
||||
|
||||
for ( var i = 0; i < 8192; i++ )
|
||||
str += String.fromCharCode( (25 * Math.random()) + 97 );
|
||||
|
||||
for ( var i = 8192; i <= 16384; i *= 2 ) {
|
||||
|
||||
var base64;
|
||||
|
||||
base64 = toBase64(str);
|
||||
base64ToString(base64);
|
||||
|
||||
// Double the string
|
||||
str += str;
|
||||
}
|
||||
|
||||
toBinaryTable = null;
|
|
@ -1,85 +0,0 @@
|
|||
// The Great Computer Language Shootout
|
||||
// http://shootout.alioth.debian.org
|
||||
//
|
||||
// Contributed by Ian Osgood
|
||||
|
||||
var last = 42, A = 3877, C = 29573, M = 139968;
|
||||
|
||||
function rand(max) {
|
||||
last = (last * A + C) % M;
|
||||
return max * last / M;
|
||||
}
|
||||
|
||||
var ALU =
|
||||
"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
|
||||
"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
|
||||
"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
|
||||
"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
|
||||
"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
|
||||
"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
|
||||
"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
|
||||
|
||||
var IUB = {
|
||||
a:0.27, c:0.12, g:0.12, t:0.27,
|
||||
B:0.02, D:0.02, H:0.02, K:0.02,
|
||||
M:0.02, N:0.02, R:0.02, S:0.02,
|
||||
V:0.02, W:0.02, Y:0.02
|
||||
}
|
||||
|
||||
var HomoSap = {
|
||||
a: 0.3029549426680,
|
||||
c: 0.1979883004921,
|
||||
g: 0.1975473066391,
|
||||
t: 0.3015094502008
|
||||
}
|
||||
|
||||
function makeCumulative(table) {
|
||||
var last = null;
|
||||
for (var c in table) {
|
||||
if (last) table[c] += table[last];
|
||||
last = c;
|
||||
}
|
||||
}
|
||||
|
||||
function fastaRepeat(n, seq) {
|
||||
var seqi = 0, lenOut = 60;
|
||||
while (n>0) {
|
||||
if (n<lenOut) lenOut = n;
|
||||
if (seqi + lenOut < seq.length) {
|
||||
ret = seq.substring(seqi, seqi+lenOut);
|
||||
seqi += lenOut;
|
||||
} else {
|
||||
var s = seq.substring(seqi);
|
||||
seqi = lenOut - s.length;
|
||||
ret = s + seq.substring(0, seqi);
|
||||
}
|
||||
n -= lenOut;
|
||||
}
|
||||
}
|
||||
|
||||
function fastaRandom(n, table) {
|
||||
var line = new Array(60);
|
||||
makeCumulative(table);
|
||||
while (n>0) {
|
||||
if (n<line.length) line = new Array(n);
|
||||
for (var i=0; i<line.length; i++) {
|
||||
var r = rand(1);
|
||||
for (var c in table) {
|
||||
if (r < table[c]) {
|
||||
line[i] = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = line.join('');
|
||||
n -= line.length;
|
||||
}
|
||||
}
|
||||
|
||||
var ret;
|
||||
|
||||
var count = 7;
|
||||
ret = fastaRepeat(2*count*100000, ALU);
|
||||
ret = fastaRandom(3*count*1000, IUB);
|
||||
ret = fastaRandom(5*count*1000, HomoSap);
|
||||
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,89 +0,0 @@
|
|||
letters = new Array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z");
|
||||
numbers = new Array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26);
|
||||
colors = new Array("FF","CC","99","66","33","00");
|
||||
|
||||
var endResult;
|
||||
|
||||
function doTest()
|
||||
{
|
||||
endResult = "";
|
||||
|
||||
// make up email address
|
||||
for (var k=0;k<4000;k++)
|
||||
{
|
||||
name = makeName(6);
|
||||
(k%2)?email=name+"@mac.com":email=name+"(at)mac.com";
|
||||
|
||||
// validate the email address
|
||||
var pattern = /^[a-zA-Z0-9\-\._]+@[a-zA-Z0-9\-_]+(\.?[a-zA-Z0-9\-_]*)\.[a-zA-Z]{2,3}$/;
|
||||
|
||||
if(pattern.test(email))
|
||||
{
|
||||
var r = email + " appears to be a valid email address.";
|
||||
addResult(r);
|
||||
}
|
||||
else
|
||||
{
|
||||
r = email + " does NOT appear to be a valid email address.";
|
||||
addResult(r);
|
||||
}
|
||||
}
|
||||
|
||||
// make up ZIP codes
|
||||
for (var s=0;s<4000;s++)
|
||||
{
|
||||
var zipGood = true;
|
||||
var zip = makeNumber(4);
|
||||
(s%2)?zip=zip+"xyz":zip=zip.concat("7");
|
||||
|
||||
// validate the zip code
|
||||
for (var i = 0; i < zip.length; i++) {
|
||||
var ch = zip.charAt(i);
|
||||
if (ch < "0" || ch > "9") {
|
||||
zipGood = false;
|
||||
r = zip + " contains letters.";
|
||||
addResult(r);
|
||||
}
|
||||
}
|
||||
if (zipGood && zip.length>5)
|
||||
{
|
||||
zipGood = false;
|
||||
r = zip + " is longer than five characters.";
|
||||
addResult(r);
|
||||
}
|
||||
if (zipGood)
|
||||
{
|
||||
r = zip + " appears to be a valid ZIP code.";
|
||||
addResult(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeName(n)
|
||||
{
|
||||
var tmp = "";
|
||||
for (var i=0;i<n;i++)
|
||||
{
|
||||
var l = Math.floor(26*Math.random());
|
||||
tmp += letters[l];
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
function makeNumber(n)
|
||||
{
|
||||
var tmp = "";
|
||||
for (var i=0;i<n;i++)
|
||||
{
|
||||
var l = Math.floor(9*Math.random());
|
||||
tmp = tmp.concat(l);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
function addResult(r)
|
||||
{
|
||||
endResult += "\n" + r;
|
||||
}
|
||||
|
||||
doTest();
|
|
@ -1,7 +0,0 @@
|
|||
function f()
|
||||
{
|
||||
function g() { }
|
||||
}
|
||||
|
||||
for (var i = 0; i < 300000; ++i)
|
||||
f();
|
|
@ -1,6 +0,0 @@
|
|||
function f(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9)
|
||||
{
|
||||
}
|
||||
|
||||
for (var i = 0; i < 3000000; ++i)
|
||||
f(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
|
@ -1,6 +0,0 @@
|
|||
function f()
|
||||
{
|
||||
}
|
||||
|
||||
for (var i = 0; i < 4000000; ++i)
|
||||
f();
|
|
@ -1,6 +0,0 @@
|
|||
function f(x0, x1, x2, x3, x4)
|
||||
{
|
||||
}
|
||||
|
||||
for (var i = 0; i < 3000000; ++i)
|
||||
f(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
|
|
@ -1,6 +0,0 @@
|
|||
function f(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9)
|
||||
{
|
||||
}
|
||||
|
||||
for (var i = 0; i < 3000000; ++i)
|
||||
f();
|
|
@ -1,7 +0,0 @@
|
|||
function f(x, y, z)
|
||||
{
|
||||
return x + y + z;
|
||||
}
|
||||
|
||||
for (var i = 0; i < 2500000; ++i)
|
||||
f(1, 2, 3);
|
|
@ -1,2 +0,0 @@
|
|||
for (x = 0; x < 1200000; ++x)
|
||||
;
|
|
@ -1,2 +0,0 @@
|
|||
for (var i = 0; i < 10000000; ++i)
|
||||
;
|
|
@ -1,5 +0,0 @@
|
|||
var count = 6000000;
|
||||
var sum = 0;
|
||||
for (var i = 0; i < count; i++) {
|
||||
sum = i + count;
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,877 +0,0 @@
|
|||
// Copyright 2008 the V8 project authors. All rights reserved.
|
||||
// Copyright 1996 John Maloney and Mario Wolczko.
|
||||
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
// This implementation of the DeltaBlue benchmark is derived
|
||||
// from the Smalltalk implementation by John Maloney and Mario
|
||||
// Wolczko. Some parts have been translated directly, whereas
|
||||
// others have been modified more aggresively to make it feel
|
||||
// more like a JavaScript program.
|
||||
|
||||
/**
|
||||
* A JavaScript implementation of the DeltaBlue constrain-solving
|
||||
* algorithm, as described in:
|
||||
*
|
||||
* "The DeltaBlue Algorithm: An Incremental Constraint Hierarchy Solver"
|
||||
* Bjorn N. Freeman-Benson and John Maloney
|
||||
* January 1990 Communications of the ACM,
|
||||
* also available as University of Washington TR 89-08-06.
|
||||
*
|
||||
* Beware: this benchmark is written in a grotesque style where
|
||||
* the constraint model is built by side-effects from constructors.
|
||||
* I've kept it this way to avoid deviating too much from the original
|
||||
* implementation.
|
||||
*/
|
||||
|
||||
|
||||
/* --- O b j e c t M o d e l --- */
|
||||
|
||||
Object.prototype.inherits = function (shuper) {
|
||||
function Inheriter() { }
|
||||
Inheriter.prototype = shuper.prototype;
|
||||
this.prototype = new Inheriter();
|
||||
this.superConstructor = shuper;
|
||||
}
|
||||
|
||||
function OrderedCollection() {
|
||||
this.elms = new Array();
|
||||
}
|
||||
|
||||
OrderedCollection.prototype.add = function (elm) {
|
||||
this.elms.push(elm);
|
||||
}
|
||||
|
||||
OrderedCollection.prototype.at = function (index) {
|
||||
return this.elms[index];
|
||||
}
|
||||
|
||||
OrderedCollection.prototype.size = function () {
|
||||
return this.elms.length;
|
||||
}
|
||||
|
||||
OrderedCollection.prototype.removeFirst = function () {
|
||||
return this.elms.pop();
|
||||
}
|
||||
|
||||
OrderedCollection.prototype.remove = function (elm) {
|
||||
var index = 0, skipped = 0;
|
||||
for (var i = 0; i < this.elms.length; i++) {
|
||||
var value = this.elms[i];
|
||||
if (value != elm) {
|
||||
this.elms[index] = value;
|
||||
index++;
|
||||
} else {
|
||||
skipped++;
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < skipped; i++)
|
||||
this.elms.pop();
|
||||
}
|
||||
|
||||
/* --- *
|
||||
* S t r e n g t h
|
||||
* --- */
|
||||
|
||||
/**
|
||||
* Strengths are used to measure the relative importance of constraints.
|
||||
* New strengths may be inserted in the strength hierarchy without
|
||||
* disrupting current constraints. Strengths cannot be created outside
|
||||
* this class, so pointer comparison can be used for value comparison.
|
||||
*/
|
||||
function Strength(strengthValue, name) {
|
||||
this.strengthValue = strengthValue;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
Strength.stronger = function (s1, s2) {
|
||||
return s1.strengthValue < s2.strengthValue;
|
||||
}
|
||||
|
||||
Strength.weaker = function (s1, s2) {
|
||||
return s1.strengthValue > s2.strengthValue;
|
||||
}
|
||||
|
||||
Strength.weakestOf = function (s1, s2) {
|
||||
return this.weaker(s1, s2) ? s1 : s2;
|
||||
}
|
||||
|
||||
Strength.strongest = function (s1, s2) {
|
||||
return this.stronger(s1, s2) ? s1 : s2;
|
||||
}
|
||||
|
||||
Strength.prototype.nextWeaker = function () {
|
||||
switch (this.strengthValue) {
|
||||
case 0: return Strength.WEAKEST;
|
||||
case 1: return Strength.WEAK_DEFAULT;
|
||||
case 2: return Strength.NORMAL;
|
||||
case 3: return Strength.STRONG_DEFAULT;
|
||||
case 4: return Strength.PREFERRED;
|
||||
case 5: return Strength.REQUIRED;
|
||||
}
|
||||
}
|
||||
|
||||
// Strength constants.
|
||||
Strength.REQUIRED = new Strength(0, "required");
|
||||
Strength.STONG_PREFERRED = new Strength(1, "strongPreferred");
|
||||
Strength.PREFERRED = new Strength(2, "preferred");
|
||||
Strength.STRONG_DEFAULT = new Strength(3, "strongDefault");
|
||||
Strength.NORMAL = new Strength(4, "normal");
|
||||
Strength.WEAK_DEFAULT = new Strength(5, "weakDefault");
|
||||
Strength.WEAKEST = new Strength(6, "weakest");
|
||||
|
||||
/* --- *
|
||||
* C o n s t r a i n t
|
||||
* --- */
|
||||
|
||||
/**
|
||||
* An abstract class representing a system-maintainable relationship
|
||||
* (or "constraint") between a set of variables. A constraint supplies
|
||||
* a strength instance variable; concrete subclasses provide a means
|
||||
* of storing the constrained variables and other information required
|
||||
* to represent a constraint.
|
||||
*/
|
||||
function Constraint(strength) {
|
||||
this.strength = strength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate this constraint and attempt to satisfy it.
|
||||
*/
|
||||
Constraint.prototype.addConstraint = function () {
|
||||
this.addToGraph();
|
||||
planner.incrementalAdd(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to find a way to enforce this constraint. If successful,
|
||||
* record the solution, perhaps modifying the current dataflow
|
||||
* graph. Answer the constraint that this constraint overrides, if
|
||||
* there is one, or nil, if there isn't.
|
||||
* Assume: I am not already satisfied.
|
||||
*/
|
||||
Constraint.prototype.satisfy = function (mark) {
|
||||
this.chooseMethod(mark);
|
||||
if (!this.isSatisfied()) {
|
||||
if (this.strength == Strength.REQUIRED)
|
||||
alert("Could not satisfy a required constraint!");
|
||||
return null;
|
||||
}
|
||||
this.markInputs(mark);
|
||||
var out = this.output();
|
||||
var overridden = out.determinedBy;
|
||||
if (overridden != null) overridden.markUnsatisfied();
|
||||
out.determinedBy = this;
|
||||
if (!planner.addPropagate(this, mark))
|
||||
alert("Cycle encountered");
|
||||
out.mark = mark;
|
||||
return overridden;
|
||||
}
|
||||
|
||||
Constraint.prototype.destroyConstraint = function () {
|
||||
if (this.isSatisfied()) planner.incrementalRemove(this);
|
||||
else this.removeFromGraph();
|
||||
}
|
||||
|
||||
/**
|
||||
* Normal constraints are not input constraints. An input constraint
|
||||
* is one that depends on external state, such as the mouse, the
|
||||
* keybord, a clock, or some arbitraty piece of imperative code.
|
||||
*/
|
||||
Constraint.prototype.isInput = function () {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* --- *
|
||||
* U n a r y C o n s t r a i n t
|
||||
* --- */
|
||||
|
||||
/**
|
||||
* Abstract superclass for constraints having a single possible output
|
||||
* variable.
|
||||
*/
|
||||
function UnaryConstraint(v, strength) {
|
||||
UnaryConstraint.superConstructor.call(this, strength);
|
||||
this.myOutput = v;
|
||||
this.satisfied = false;
|
||||
this.addConstraint();
|
||||
}
|
||||
|
||||
UnaryConstraint.inherits(Constraint);
|
||||
|
||||
/**
|
||||
* Adds this constraint to the constraint graph
|
||||
*/
|
||||
UnaryConstraint.prototype.addToGraph = function () {
|
||||
this.myOutput.addConstraint(this);
|
||||
this.satisfied = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decides if this constraint can be satisfied and records that
|
||||
* decision.
|
||||
*/
|
||||
UnaryConstraint.prototype.chooseMethod = function (mark) {
|
||||
this.satisfied = (this.myOutput.mark != mark)
|
||||
&& Strength.stronger(this.strength, this.myOutput.walkStrength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this constraint is satisfied in the current solution.
|
||||
*/
|
||||
UnaryConstraint.prototype.isSatisfied = function () {
|
||||
return this.satisfied;
|
||||
}
|
||||
|
||||
UnaryConstraint.prototype.markInputs = function (mark) {
|
||||
// has no inputs
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current output variable.
|
||||
*/
|
||||
UnaryConstraint.prototype.output = function () {
|
||||
return this.myOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the walkabout strength, the stay flag, and, if it is
|
||||
* 'stay', the value for the current output of this constraint. Assume
|
||||
* this constraint is satisfied.
|
||||
*/
|
||||
UnaryConstraint.prototype.recalculate = function () {
|
||||
this.myOutput.walkStrength = this.strength;
|
||||
this.myOutput.stay = !this.isInput();
|
||||
if (this.myOutput.stay) this.execute(); // Stay optimization
|
||||
}
|
||||
|
||||
/**
|
||||
* Records that this constraint is unsatisfied
|
||||
*/
|
||||
UnaryConstraint.prototype.markUnsatisfied = function () {
|
||||
this.satisfied = false;
|
||||
}
|
||||
|
||||
UnaryConstraint.prototype.inputsKnown = function () {
|
||||
return true;
|
||||
}
|
||||
|
||||
UnaryConstraint.prototype.removeFromGraph = function () {
|
||||
if (this.myOutput != null) this.myOutput.removeConstraint(this);
|
||||
this.satisfied = false;
|
||||
}
|
||||
|
||||
/* --- *
|
||||
* S t a y C o n s t r a i n t
|
||||
* --- */
|
||||
|
||||
/**
|
||||
* Variables that should, with some level of preference, stay the same.
|
||||
* Planners may exploit the fact that instances, if satisfied, will not
|
||||
* change their output during plan execution. This is called "stay
|
||||
* optimization".
|
||||
*/
|
||||
function StayConstraint(v, str) {
|
||||
StayConstraint.superConstructor.call(this, v, str);
|
||||
}
|
||||
|
||||
StayConstraint.inherits(UnaryConstraint);
|
||||
|
||||
StayConstraint.prototype.execute = function () {
|
||||
// Stay constraints do nothing
|
||||
}
|
||||
|
||||
/* --- *
|
||||
* E d i t C o n s t r a i n t
|
||||
* --- */
|
||||
|
||||
/**
|
||||
* A unary input constraint used to mark a variable that the client
|
||||
* wishes to change.
|
||||
*/
|
||||
function EditConstraint(v, str) {
|
||||
EditConstraint.superConstructor.call(this, v, str);
|
||||
}
|
||||
|
||||
EditConstraint.inherits(UnaryConstraint);
|
||||
|
||||
/**
|
||||
* Edits indicate that a variable is to be changed by imperative code.
|
||||
*/
|
||||
EditConstraint.prototype.isInput = function () {
|
||||
return true;
|
||||
}
|
||||
|
||||
EditConstraint.prototype.execute = function () {
|
||||
// Edit constraints do nothing
|
||||
}
|
||||
|
||||
/* --- *
|
||||
* B i n a r y C o n s t r a i n t
|
||||
* --- */
|
||||
|
||||
var Direction = new Object();
|
||||
Direction.NONE = 0;
|
||||
Direction.FORWARD = 1;
|
||||
Direction.BACKWARD = -1;
|
||||
|
||||
/**
|
||||
* Abstract superclass for constraints having two possible output
|
||||
* variables.
|
||||
*/
|
||||
function BinaryConstraint(var1, var2, strength) {
|
||||
BinaryConstraint.superConstructor.call(this, strength);
|
||||
this.v1 = var1;
|
||||
this.v2 = var2;
|
||||
this.direction = Direction.NONE;
|
||||
this.addConstraint();
|
||||
}
|
||||
|
||||
BinaryConstraint.inherits(Constraint);
|
||||
|
||||
/**
|
||||
* Decides if this constratint can be satisfied and which way it
|
||||
* should flow based on the relative strength of the variables related,
|
||||
* and record that decision.
|
||||
*/
|
||||
BinaryConstraint.prototype.chooseMethod = function (mark) {
|
||||
if (this.v1.mark == mark) {
|
||||
this.direction = (this.v1.mark != mark && Strength.stronger(this.strength, this.v2.walkStrength))
|
||||
? Direction.FORWARD
|
||||
: Direction.NONE;
|
||||
}
|
||||
if (this.v2.mark == mark) {
|
||||
this.direction = (this.v1.mark != mark && Strength.stronger(this.strength, this.v1.walkStrength))
|
||||
? Direction.BACKWARD
|
||||
: Direction.NONE;
|
||||
}
|
||||
if (Strength.weaker(this.v1.walkStrength, this.v2.walkStrength)) {
|
||||
this.direction = Strength.stronger(this.strength, this.v1.walkStrength)
|
||||
? Direction.BACKWARD
|
||||
: Direction.NONE;
|
||||
} else {
|
||||
this.direction = Strength.stronger(this.strength, this.v2.walkStrength)
|
||||
? Direction.FORWARD
|
||||
: Direction.BACKWARD
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add this constraint to the constraint graph
|
||||
*/
|
||||
BinaryConstraint.prototype.addToGraph = function () {
|
||||
this.v1.addConstraint(this);
|
||||
this.v2.addConstraint(this);
|
||||
this.direction = Direction.NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Answer true if this constraint is satisfied in the current solution.
|
||||
*/
|
||||
BinaryConstraint.prototype.isSatisfied = function () {
|
||||
return this.direction != Direction.NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the input variable with the given mark.
|
||||
*/
|
||||
BinaryConstraint.prototype.markInputs = function (mark) {
|
||||
this.input().mark = mark;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current input variable
|
||||
*/
|
||||
BinaryConstraint.prototype.input = function () {
|
||||
return (this.direction == Direction.FORWARD) ? this.v1 : this.v2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current output variable
|
||||
*/
|
||||
BinaryConstraint.prototype.output = function () {
|
||||
return (this.direction == Direction.FORWARD) ? this.v2 : this.v1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the walkabout strength, the stay flag, and, if it is
|
||||
* 'stay', the value for the current output of this
|
||||
* constraint. Assume this constraint is satisfied.
|
||||
*/
|
||||
BinaryConstraint.prototype.recalculate = function () {
|
||||
var ihn = this.input(), out = this.output();
|
||||
out.walkStrength = Strength.weakestOf(this.strength, ihn.walkStrength);
|
||||
out.stay = ihn.stay;
|
||||
if (out.stay) this.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Record the fact that this constraint is unsatisfied.
|
||||
*/
|
||||
BinaryConstraint.prototype.markUnsatisfied = function () {
|
||||
this.direction = Direction.NONE;
|
||||
}
|
||||
|
||||
BinaryConstraint.prototype.inputsKnown = function (mark) {
|
||||
var i = this.input();
|
||||
return i.mark == mark || i.stay || i.determinedBy == null;
|
||||
}
|
||||
|
||||
BinaryConstraint.prototype.removeFromGraph = function () {
|
||||
if (this.v1 != null) this.v1.removeConstraint(this);
|
||||
if (this.v2 != null) this.v2.removeConstraint(this);
|
||||
this.direction = Direction.NONE;
|
||||
}
|
||||
|
||||
/* --- *
|
||||
* S c a l e C o n s t r a i n t
|
||||
* --- */
|
||||
|
||||
/**
|
||||
* Relates two variables by the linear scaling relationship: "v2 =
|
||||
* (v1 * scale) + offset". Either v1 or v2 may be changed to maintain
|
||||
* this relationship but the scale factor and offset are considered
|
||||
* read-only.
|
||||
*/
|
||||
function ScaleConstraint(src, scale, offset, dest, strength) {
|
||||
this.direction = Direction.NONE;
|
||||
this.scale = scale;
|
||||
this.offset = offset;
|
||||
ScaleConstraint.superConstructor.call(this, src, dest, strength);
|
||||
}
|
||||
|
||||
ScaleConstraint.inherits(BinaryConstraint);
|
||||
|
||||
/**
|
||||
* Adds this constraint to the constraint graph.
|
||||
*/
|
||||
ScaleConstraint.prototype.addToGraph = function () {
|
||||
ScaleConstraint.superConstructor.prototype.addToGraph.call(this);
|
||||
this.scale.addConstraint(this);
|
||||
this.offset.addConstraint(this);
|
||||
}
|
||||
|
||||
ScaleConstraint.prototype.removeFromGraph = function () {
|
||||
ScaleConstraint.superConstructor.prototype.removeFromGraph.call(this);
|
||||
if (this.scale != null) this.scale.removeConstraint(this);
|
||||
if (this.offset != null) this.offset.removeConstraint(this);
|
||||
}
|
||||
|
||||
ScaleConstraint.prototype.markInputs = function (mark) {
|
||||
ScaleConstraint.superConstructor.prototype.markInputs.call(this, mark);
|
||||
this.scale.mark = this.offset.mark = mark;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforce this constraint. Assume that it is satisfied.
|
||||
*/
|
||||
ScaleConstraint.prototype.execute = function () {
|
||||
if (this.direction == Direction.FORWARD) {
|
||||
this.v2.value = this.v1.value * this.scale.value + this.offset.value;
|
||||
} else {
|
||||
this.v1.value = (this.v2.value - this.offset.value) / this.scale.value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the walkabout strength, the stay flag, and, if it is
|
||||
* 'stay', the value for the current output of this constraint. Assume
|
||||
* this constraint is satisfied.
|
||||
*/
|
||||
ScaleConstraint.prototype.recalculate = function () {
|
||||
var ihn = this.input(), out = this.output();
|
||||
out.walkStrength = Strength.weakestOf(this.strength, ihn.walkStrength);
|
||||
out.stay = ihn.stay && this.scale.stay && this.offset.stay;
|
||||
if (out.stay) this.execute();
|
||||
}
|
||||
|
||||
/* --- *
|
||||
* E q u a l i t y C o n s t r a i n t
|
||||
* --- */
|
||||
|
||||
/**
|
||||
* Constrains two variables to have the same value.
|
||||
*/
|
||||
function EqualityConstraint(var1, var2, strength) {
|
||||
EqualityConstraint.superConstructor.call(this, var1, var2, strength);
|
||||
}
|
||||
|
||||
EqualityConstraint.inherits(BinaryConstraint);
|
||||
|
||||
/**
|
||||
* Enforce this constraint. Assume that it is satisfied.
|
||||
*/
|
||||
EqualityConstraint.prototype.execute = function () {
|
||||
this.output().value = this.input().value;
|
||||
}
|
||||
|
||||
/* --- *
|
||||
* V a r i a b l e
|
||||
* --- */
|
||||
|
||||
/**
|
||||
* A constrained variable. In addition to its value, it maintain the
|
||||
* structure of the constraint graph, the current dataflow graph, and
|
||||
* various parameters of interest to the DeltaBlue incremental
|
||||
* constraint solver.
|
||||
**/
|
||||
function Variable(name, initialValue) {
|
||||
this.value = initialValue || 0;
|
||||
this.constraints = new OrderedCollection();
|
||||
this.determinedBy = null;
|
||||
this.mark = 0;
|
||||
this.walkStrength = Strength.WEAKEST;
|
||||
this.stay = true;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given constraint to the set of all constraints that refer
|
||||
* this variable.
|
||||
*/
|
||||
Variable.prototype.addConstraint = function (c) {
|
||||
this.constraints.add(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all traces of c from this variable.
|
||||
*/
|
||||
Variable.prototype.removeConstraint = function (c) {
|
||||
this.constraints.remove(c);
|
||||
if (this.determinedBy == c) this.determinedBy = null;
|
||||
}
|
||||
|
||||
/* --- *
|
||||
* P l a n n e r
|
||||
* --- */
|
||||
|
||||
/**
|
||||
* The DeltaBlue planner
|
||||
*/
|
||||
function Planner() {
|
||||
this.currentMark = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to satisfy the given constraint and, if successful,
|
||||
* incrementally update the dataflow graph. Details: If satifying
|
||||
* the constraint is successful, it may override a weaker constraint
|
||||
* on its output. The algorithm attempts to resatisfy that
|
||||
* constraint using some other method. This process is repeated
|
||||
* until either a) it reaches a variable that was not previously
|
||||
* determined by any constraint or b) it reaches a constraint that
|
||||
* is too weak to be satisfied using any of its methods. The
|
||||
* variables of constraints that have been processed are marked with
|
||||
* a unique mark value so that we know where we've been. This allows
|
||||
* the algorithm to avoid getting into an infinite loop even if the
|
||||
* constraint graph has an inadvertent cycle.
|
||||
*/
|
||||
Planner.prototype.incrementalAdd = function (c) {
|
||||
var mark = this.newMark();
|
||||
var overridden = c.satisfy(mark);
|
||||
while (overridden != null)
|
||||
overridden = overridden.satisfy(mark);
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point for retracting a constraint. Remove the given
|
||||
* constraint and incrementally update the dataflow graph.
|
||||
* Details: Retracting the given constraint may allow some currently
|
||||
* unsatisfiable downstream constraint to be satisfied. We therefore collect
|
||||
* a list of unsatisfied downstream constraints and attempt to
|
||||
* satisfy each one in turn. This list is traversed by constraint
|
||||
* strength, strongest first, as a heuristic for avoiding
|
||||
* unnecessarily adding and then overriding weak constraints.
|
||||
* Assume: c is satisfied.
|
||||
*/
|
||||
Planner.prototype.incrementalRemove = function (c) {
|
||||
var out = c.output();
|
||||
c.markUnsatisfied();
|
||||
c.removeFromGraph();
|
||||
var unsatisfied = this.removePropagateFrom(out);
|
||||
var strength = Strength.REQUIRED;
|
||||
do {
|
||||
for (var i = 0; i < unsatisfied.size(); i++) {
|
||||
var u = unsatisfied.at(i);
|
||||
if (u.strength == strength)
|
||||
this.incrementalAdd(u);
|
||||
}
|
||||
strength = strength.nextWeaker();
|
||||
} while (strength != Strength.WEAKEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a previously unused mark value.
|
||||
*/
|
||||
Planner.prototype.newMark = function () {
|
||||
return ++this.currentMark;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a plan for resatisfaction starting from the given source
|
||||
* constraints, usually a set of input constraints. This method
|
||||
* assumes that stay optimization is desired; the plan will contain
|
||||
* only constraints whose output variables are not stay. Constraints
|
||||
* that do no computation, such as stay and edit constraints, are
|
||||
* not included in the plan.
|
||||
* Details: The outputs of a constraint are marked when it is added
|
||||
* to the plan under construction. A constraint may be appended to
|
||||
* the plan when all its input variables are known. A variable is
|
||||
* known if either a) the variable is marked (indicating that has
|
||||
* been computed by a constraint appearing earlier in the plan), b)
|
||||
* the variable is 'stay' (i.e. it is a constant at plan execution
|
||||
* time), or c) the variable is not determined by any
|
||||
* constraint. The last provision is for past states of history
|
||||
* variables, which are not stay but which are also not computed by
|
||||
* any constraint.
|
||||
* Assume: sources are all satisfied.
|
||||
*/
|
||||
Planner.prototype.makePlan = function (sources) {
|
||||
var mark = this.newMark();
|
||||
var plan = new Plan();
|
||||
var todo = sources;
|
||||
while (todo.size() > 0) {
|
||||
var c = todo.removeFirst();
|
||||
if (c.output().mark != mark && c.inputsKnown(mark)) {
|
||||
plan.addConstraint(c);
|
||||
c.output().mark = mark;
|
||||
this.addConstraintsConsumingTo(c.output(), todo);
|
||||
}
|
||||
}
|
||||
return plan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a plan for resatisfying starting from the output of the
|
||||
* given constraints, usually a set of input constraints.
|
||||
*/
|
||||
Planner.prototype.extractPlanFromConstraints = function (constraints) {
|
||||
var sources = new OrderedCollection();
|
||||
for (var i = 0; i < constraints.size(); i++) {
|
||||
var c = constraints.at(i);
|
||||
if (c.isInput() && c.isSatisfied())
|
||||
// not in plan already and eligible for inclusion
|
||||
sources.add(c);
|
||||
}
|
||||
return this.makePlan(sources);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recompute the walkabout strengths and stay flags of all variables
|
||||
* downstream of the given constraint and recompute the actual
|
||||
* values of all variables whose stay flag is true. If a cycle is
|
||||
* detected, remove the given constraint and answer
|
||||
* false. Otherwise, answer true.
|
||||
* Details: Cycles are detected when a marked variable is
|
||||
* encountered downstream of the given constraint. The sender is
|
||||
* assumed to have marked the inputs of the given constraint with
|
||||
* the given mark. Thus, encountering a marked node downstream of
|
||||
* the output constraint means that there is a path from the
|
||||
* constraint's output to one of its inputs.
|
||||
*/
|
||||
Planner.prototype.addPropagate = function (c, mark) {
|
||||
var todo = new OrderedCollection();
|
||||
todo.add(c);
|
||||
while (todo.size() > 0) {
|
||||
var d = todo.removeFirst();
|
||||
if (d.output().mark == mark) {
|
||||
this.incrementalRemove(c);
|
||||
return false;
|
||||
}
|
||||
d.recalculate();
|
||||
this.addConstraintsConsumingTo(d.output(), todo);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the walkabout strengths and stay flags of all variables
|
||||
* downstream of the given constraint. Answer a collection of
|
||||
* unsatisfied constraints sorted in order of decreasing strength.
|
||||
*/
|
||||
Planner.prototype.removePropagateFrom = function (out) {
|
||||
out.determinedBy = null;
|
||||
out.walkStrength = Strength.WEAKEST;
|
||||
out.stay = true;
|
||||
var unsatisfied = new OrderedCollection();
|
||||
var todo = new OrderedCollection();
|
||||
todo.add(out);
|
||||
while (todo.size() > 0) {
|
||||
var v = todo.removeFirst();
|
||||
for (var i = 0; i < v.constraints.size(); i++) {
|
||||
var c = v.constraints.at(i);
|
||||
if (!c.isSatisfied())
|
||||
unsatisfied.add(c);
|
||||
}
|
||||
var determining = v.determinedBy;
|
||||
for (var i = 0; i < v.constraints.size(); i++) {
|
||||
var next = v.constraints.at(i);
|
||||
if (next != determining && next.isSatisfied()) {
|
||||
next.recalculate();
|
||||
todo.add(next.output());
|
||||
}
|
||||
}
|
||||
}
|
||||
return unsatisfied;
|
||||
}
|
||||
|
||||
Planner.prototype.addConstraintsConsumingTo = function (v, coll) {
|
||||
var determining = v.determinedBy;
|
||||
var cc = v.constraints;
|
||||
for (var i = 0; i < cc.size(); i++) {
|
||||
var c = cc.at(i);
|
||||
if (c != determining && c.isSatisfied())
|
||||
coll.add(c);
|
||||
}
|
||||
}
|
||||
|
||||
/* --- *
|
||||
* P l a n
|
||||
* --- */
|
||||
|
||||
/**
|
||||
* A Plan is an ordered list of constraints to be executed in sequence
|
||||
* to resatisfy all currently satisfiable constraints in the face of
|
||||
* one or more changing inputs.
|
||||
*/
|
||||
function Plan() {
|
||||
this.v = new OrderedCollection();
|
||||
}
|
||||
|
||||
Plan.prototype.addConstraint = function (c) {
|
||||
this.v.add(c);
|
||||
}
|
||||
|
||||
Plan.prototype.size = function () {
|
||||
return this.v.size();
|
||||
}
|
||||
|
||||
Plan.prototype.constraintAt = function (index) {
|
||||
return this.v.at(index);
|
||||
}
|
||||
|
||||
Plan.prototype.execute = function () {
|
||||
for (var i = 0; i < this.size(); i++) {
|
||||
var c = this.constraintAt(i);
|
||||
c.execute();
|
||||
}
|
||||
}
|
||||
|
||||
/* --- *
|
||||
* M a i n
|
||||
* --- */
|
||||
|
||||
/**
|
||||
* This is the standard DeltaBlue benchmark. A long chain of equality
|
||||
* constraints is constructed with a stay constraint on one end. An
|
||||
* edit constraint is then added to the opposite end and the time is
|
||||
* measured for adding and removing this constraint, and extracting
|
||||
* and executing a constraint satisfaction plan. There are two cases.
|
||||
* In case 1, the added constraint is stronger than the stay
|
||||
* constraint and values must propagate down the entire length of the
|
||||
* chain. In case 2, the added constraint is weaker than the stay
|
||||
* constraint so it cannot be accomodated. The cost in this case is,
|
||||
* of course, very low. Typical situations lie somewhere between these
|
||||
* two extremes.
|
||||
*/
|
||||
function chainTest(n) {
|
||||
planner = new Planner();
|
||||
var prev = null, first = null, last = null;
|
||||
|
||||
// Build chain of n equality constraints
|
||||
for (var i = 0; i <= n; i++) {
|
||||
var name = "v" + i;
|
||||
var v = new Variable(name);
|
||||
if (prev != null)
|
||||
new EqualityConstraint(prev, v, Strength.REQUIRED);
|
||||
if (i == 0) first = v;
|
||||
if (i == n) last = v;
|
||||
prev = v;
|
||||
}
|
||||
|
||||
new StayConstraint(last, Strength.STRONG_DEFAULT);
|
||||
var edit = new EditConstraint(first, Strength.PREFERRED);
|
||||
var edits = new OrderedCollection();
|
||||
edits.add(edit);
|
||||
var plan = planner.extractPlanFromConstraints(edits);
|
||||
for (var i = 0; i < 100; i++) {
|
||||
first.value = i;
|
||||
plan.execute();
|
||||
if (last.value != i)
|
||||
alert("Chain test failed.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This test constructs a two sets of variables related to each
|
||||
* other by a simple linear transformation (scale and offset). The
|
||||
* time is measured to change a variable on either side of the
|
||||
* mapping and to change the scale and offset factors.
|
||||
*/
|
||||
function projectionTest(n) {
|
||||
planner = new Planner();
|
||||
var scale = new Variable("scale", 10);
|
||||
var offset = new Variable("offset", 1000);
|
||||
var src = null, dst = null;
|
||||
|
||||
var dests = new OrderedCollection();
|
||||
for (var i = 0; i < n; i++) {
|
||||
src = new Variable("src" + i, i);
|
||||
dst = new Variable("dst" + i, i);
|
||||
dests.add(dst);
|
||||
new StayConstraint(src, Strength.NORMAL);
|
||||
new ScaleConstraint(src, scale, offset, dst, Strength.REQUIRED);
|
||||
}
|
||||
|
||||
change(src, 17);
|
||||
if (dst.value != 1170) alert("Projection 1 failed");
|
||||
change(dst, 1050);
|
||||
if (src.value != 5) alert("Projection 2 failed");
|
||||
change(scale, 5);
|
||||
for (var i = 0; i < n - 1; i++) {
|
||||
if (dests.at(i).value != i * 5 + 1000)
|
||||
alert("Projection 3 failed");
|
||||
}
|
||||
change(offset, 2000);
|
||||
for (var i = 0; i < n - 1; i++) {
|
||||
if (dests.at(i).value != i * 5 + 2000)
|
||||
alert("Projection 4 failed");
|
||||
}
|
||||
}
|
||||
|
||||
function change(v, newValue) {
|
||||
var edit = new EditConstraint(v, Strength.PREFERRED);
|
||||
var edits = new OrderedCollection();
|
||||
edits.add(edit);
|
||||
var plan = planner.extractPlanFromConstraints(edits);
|
||||
for (var i = 0; i < 10; i++) {
|
||||
v.value = newValue;
|
||||
plan.execute();
|
||||
}
|
||||
edit.destroyConstraint();
|
||||
}
|
||||
|
||||
// Global variable holding the current planner.
|
||||
var planner = null;
|
||||
|
||||
function deltaBlue() {
|
||||
chainTest(100);
|
||||
projectionTest(100);
|
||||
}
|
||||
|
||||
for (var i = 0; i < 155; ++i)
|
||||
deltaBlue();
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,933 +0,0 @@
|
|||
// The ray tracer code in this file is written by Adam Burmister. It
|
||||
// is available in its original form from:
|
||||
//
|
||||
// http://labs.flog.nz.co/raytracer/
|
||||
//
|
||||
// It has been modified slightly by Google to work as a standalone
|
||||
// benchmark, but the all the computational code remains
|
||||
// untouched. This file also contains a copy of parts of the Prototype
|
||||
// JavaScript framework which is used by the ray tracer.
|
||||
|
||||
// Variable used to hold a number that can be used to verify that
|
||||
// the scene was ray traced correctly.
|
||||
var checkNumber;
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// The following is a copy of parts of the Prototype JavaScript library:
|
||||
|
||||
// Prototype JavaScript framework, version 1.5.0
|
||||
// (c) 2005-2007 Sam Stephenson
|
||||
//
|
||||
// Prototype is freely distributable under the terms of an MIT-style license.
|
||||
// For details, see the Prototype web site: http://prototype.conio.net/
|
||||
|
||||
|
||||
var Class = {
|
||||
create: function() {
|
||||
return function() {
|
||||
this.initialize.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Object.extend = function(destination, source) {
|
||||
for (var property in source) {
|
||||
destination[property] = source[property];
|
||||
}
|
||||
return destination;
|
||||
};
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// The rest of this file is the actual ray tracer written by Adam
|
||||
// Burmister. It's a concatenation of the following files:
|
||||
//
|
||||
// flog/color.js
|
||||
// flog/light.js
|
||||
// flog/vector.js
|
||||
// flog/ray.js
|
||||
// flog/scene.js
|
||||
// flog/material/basematerial.js
|
||||
// flog/material/solid.js
|
||||
// flog/material/chessboard.js
|
||||
// flog/shape/baseshape.js
|
||||
// flog/shape/sphere.js
|
||||
// flog/shape/plane.js
|
||||
// flog/intersectioninfo.js
|
||||
// flog/camera.js
|
||||
// flog/background.js
|
||||
// flog/engine.js
|
||||
|
||||
|
||||
/* Fake a Flog.* namespace */
|
||||
if(typeof(Flog) == 'undefined') var Flog = {};
|
||||
if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
|
||||
|
||||
Flog.RayTracer.Color = Class.create();
|
||||
|
||||
Flog.RayTracer.Color.prototype = {
|
||||
red : 0.0,
|
||||
green : 0.0,
|
||||
blue : 0.0,
|
||||
|
||||
initialize : function(r, g, b) {
|
||||
if(!r) r = 0.0;
|
||||
if(!g) g = 0.0;
|
||||
if(!b) b = 0.0;
|
||||
|
||||
this.red = r;
|
||||
this.green = g;
|
||||
this.blue = b;
|
||||
},
|
||||
|
||||
add : function(c1, c2){
|
||||
var result = new Flog.RayTracer.Color(0,0,0);
|
||||
|
||||
result.red = c1.red + c2.red;
|
||||
result.green = c1.green + c2.green;
|
||||
result.blue = c1.blue + c2.blue;
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
addScalar: function(c1, s){
|
||||
var result = new Flog.RayTracer.Color(0,0,0);
|
||||
|
||||
result.red = c1.red + s;
|
||||
result.green = c1.green + s;
|
||||
result.blue = c1.blue + s;
|
||||
|
||||
result.limit();
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
subtract: function(c1, c2){
|
||||
var result = new Flog.RayTracer.Color(0,0,0);
|
||||
|
||||
result.red = c1.red - c2.red;
|
||||
result.green = c1.green - c2.green;
|
||||
result.blue = c1.blue - c2.blue;
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
multiply : function(c1, c2) {
|
||||
var result = new Flog.RayTracer.Color(0,0,0);
|
||||
|
||||
result.red = c1.red * c2.red;
|
||||
result.green = c1.green * c2.green;
|
||||
result.blue = c1.blue * c2.blue;
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
multiplyScalar : function(c1, f) {
|
||||
var result = new Flog.RayTracer.Color(0,0,0);
|
||||
|
||||
result.red = c1.red * f;
|
||||
result.green = c1.green * f;
|
||||
result.blue = c1.blue * f;
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
divideFactor : function(c1, f) {
|
||||
var result = new Flog.RayTracer.Color(0,0,0);
|
||||
|
||||
result.red = c1.red / f;
|
||||
result.green = c1.green / f;
|
||||
result.blue = c1.blue / f;
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
limit: function(){
|
||||
this.red = (this.red > 0.0) ? ( (this.red > 1.0) ? 1.0 : this.red ) : 0.0;
|
||||
this.green = (this.green > 0.0) ? ( (this.green > 1.0) ? 1.0 : this.green ) : 0.0;
|
||||
this.blue = (this.blue > 0.0) ? ( (this.blue > 1.0) ? 1.0 : this.blue ) : 0.0;
|
||||
},
|
||||
|
||||
distance : function(color) {
|
||||
var d = Math.abs(this.red - color.red) + Math.abs(this.green - color.green) + Math.abs(this.blue - color.blue);
|
||||
return d;
|
||||
},
|
||||
|
||||
blend: function(c1, c2, w){
|
||||
var result = new Flog.RayTracer.Color(0,0,0);
|
||||
result = Flog.RayTracer.Color.prototype.add(
|
||||
Flog.RayTracer.Color.prototype.multiplyScalar(c1, 1 - w),
|
||||
Flog.RayTracer.Color.prototype.multiplyScalar(c2, w)
|
||||
);
|
||||
return result;
|
||||
},
|
||||
|
||||
brightness : function() {
|
||||
var r = Math.floor(this.red*255);
|
||||
var g = Math.floor(this.green*255);
|
||||
var b = Math.floor(this.blue*255);
|
||||
return (r * 77 + g * 150 + b * 29) >> 8;
|
||||
},
|
||||
|
||||
toString : function () {
|
||||
var r = Math.floor(this.red*255);
|
||||
var g = Math.floor(this.green*255);
|
||||
var b = Math.floor(this.blue*255);
|
||||
|
||||
return "rgb("+ r +","+ g +","+ b +")";
|
||||
}
|
||||
}
|
||||
/* Fake a Flog.* namespace */
|
||||
if(typeof(Flog) == 'undefined') var Flog = {};
|
||||
if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
|
||||
|
||||
Flog.RayTracer.Light = Class.create();
|
||||
|
||||
Flog.RayTracer.Light.prototype = {
|
||||
position: null,
|
||||
color: null,
|
||||
intensity: 10.0,
|
||||
|
||||
initialize : function(pos, color, intensity) {
|
||||
this.position = pos;
|
||||
this.color = color;
|
||||
this.intensity = (intensity ? intensity : 10.0);
|
||||
},
|
||||
|
||||
getIntensity: function(distance){
|
||||
if(distance >= intensity) return 0;
|
||||
|
||||
return Math.pow((intensity - distance) / strength, 0.2);
|
||||
},
|
||||
|
||||
toString : function () {
|
||||
return 'Light [' + this.position.x + ',' + this.position.y + ',' + this.position.z + ']';
|
||||
}
|
||||
}
|
||||
/* Fake a Flog.* namespace */
|
||||
if(typeof(Flog) == 'undefined') var Flog = {};
|
||||
if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
|
||||
|
||||
Flog.RayTracer.Vector = Class.create();
|
||||
|
||||
Flog.RayTracer.Vector.prototype = {
|
||||
x : 0.0,
|
||||
y : 0.0,
|
||||
z : 0.0,
|
||||
|
||||
initialize : function(x, y, z) {
|
||||
this.x = (x ? x : 0);
|
||||
this.y = (y ? y : 0);
|
||||
this.z = (z ? z : 0);
|
||||
},
|
||||
|
||||
copy: function(vector){
|
||||
this.x = vector.x;
|
||||
this.y = vector.y;
|
||||
this.z = vector.z;
|
||||
},
|
||||
|
||||
normalize : function() {
|
||||
var m = this.magnitude();
|
||||
return new Flog.RayTracer.Vector(this.x / m, this.y / m, this.z / m);
|
||||
},
|
||||
|
||||
magnitude : function() {
|
||||
return Math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z));
|
||||
},
|
||||
|
||||
cross : function(w) {
|
||||
return new Flog.RayTracer.Vector(
|
||||
-this.z * w.y + this.y * w.z,
|
||||
this.z * w.x - this.x * w.z,
|
||||
-this.y * w.x + this.x * w.y);
|
||||
},
|
||||
|
||||
dot : function(w) {
|
||||
return this.x * w.x + this.y * w.y + this.z * w.z;
|
||||
},
|
||||
|
||||
add : function(v, w) {
|
||||
return new Flog.RayTracer.Vector(w.x + v.x, w.y + v.y, w.z + v.z);
|
||||
},
|
||||
|
||||
subtract : function(v, w) {
|
||||
if(!w || !v) throw 'Vectors must be defined [' + v + ',' + w + ']';
|
||||
return new Flog.RayTracer.Vector(v.x - w.x, v.y - w.y, v.z - w.z);
|
||||
},
|
||||
|
||||
multiplyVector : function(v, w) {
|
||||
return new Flog.RayTracer.Vector(v.x * w.x, v.y * w.y, v.z * w.z);
|
||||
},
|
||||
|
||||
multiplyScalar : function(v, w) {
|
||||
return new Flog.RayTracer.Vector(v.x * w, v.y * w, v.z * w);
|
||||
},
|
||||
|
||||
toString : function () {
|
||||
return 'Vector [' + this.x + ',' + this.y + ',' + this.z + ']';
|
||||
}
|
||||
}
|
||||
/* Fake a Flog.* namespace */
|
||||
if(typeof(Flog) == 'undefined') var Flog = {};
|
||||
if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
|
||||
|
||||
Flog.RayTracer.Ray = Class.create();
|
||||
|
||||
Flog.RayTracer.Ray.prototype = {
|
||||
position : null,
|
||||
direction : null,
|
||||
initialize : function(pos, dir) {
|
||||
this.position = pos;
|
||||
this.direction = dir;
|
||||
},
|
||||
|
||||
toString : function () {
|
||||
return 'Ray [' + this.position + ',' + this.direction + ']';
|
||||
}
|
||||
}
|
||||
/* Fake a Flog.* namespace */
|
||||
if(typeof(Flog) == 'undefined') var Flog = {};
|
||||
if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
|
||||
|
||||
Flog.RayTracer.Scene = Class.create();
|
||||
|
||||
Flog.RayTracer.Scene.prototype = {
|
||||
camera : null,
|
||||
shapes : [],
|
||||
lights : [],
|
||||
background : null,
|
||||
|
||||
initialize : function() {
|
||||
this.camera = new Flog.RayTracer.Camera(
|
||||
new Flog.RayTracer.Vector(0,0,-5),
|
||||
new Flog.RayTracer.Vector(0,0,1),
|
||||
new Flog.RayTracer.Vector(0,1,0)
|
||||
);
|
||||
this.shapes = new Array();
|
||||
this.lights = new Array();
|
||||
this.background = new Flog.RayTracer.Background(new Flog.RayTracer.Color(0,0,0.5), 0.2);
|
||||
}
|
||||
}
|
||||
/* Fake a Flog.* namespace */
|
||||
if(typeof(Flog) == 'undefined') var Flog = {};
|
||||
if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
|
||||
if(typeof(Flog.RayTracer.Material) == 'undefined') Flog.RayTracer.Material = {};
|
||||
|
||||
Flog.RayTracer.Material.BaseMaterial = Class.create();
|
||||
|
||||
Flog.RayTracer.Material.BaseMaterial.prototype = {
|
||||
|
||||
gloss: 2.0, // [0...infinity] 0 = matt
|
||||
transparency: 0.0, // 0=opaque
|
||||
reflection: 0.0, // [0...infinity] 0 = no reflection
|
||||
refraction: 0.50,
|
||||
hasTexture: false,
|
||||
|
||||
initialize : function() {
|
||||
|
||||
},
|
||||
|
||||
getColor: function(u, v){
|
||||
|
||||
},
|
||||
|
||||
wrapUp: function(t){
|
||||
t = t % 2.0;
|
||||
if(t < -1) t += 2.0;
|
||||
if(t >= 1) t -= 2.0;
|
||||
return t;
|
||||
},
|
||||
|
||||
toString : function () {
|
||||
return 'Material [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
|
||||
}
|
||||
}
|
||||
/* Fake a Flog.* namespace */
|
||||
if(typeof(Flog) == 'undefined') var Flog = {};
|
||||
if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
|
||||
|
||||
Flog.RayTracer.Material.Solid = Class.create();
|
||||
|
||||
Flog.RayTracer.Material.Solid.prototype = Object.extend(
|
||||
new Flog.RayTracer.Material.BaseMaterial(), {
|
||||
initialize : function(color, reflection, refraction, transparency, gloss) {
|
||||
this.color = color;
|
||||
this.reflection = reflection;
|
||||
this.transparency = transparency;
|
||||
this.gloss = gloss;
|
||||
this.hasTexture = false;
|
||||
},
|
||||
|
||||
getColor: function(u, v){
|
||||
return this.color;
|
||||
},
|
||||
|
||||
toString : function () {
|
||||
return 'SolidMaterial [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
|
||||
}
|
||||
}
|
||||
);
|
||||
/* Fake a Flog.* namespace */
|
||||
if(typeof(Flog) == 'undefined') var Flog = {};
|
||||
if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
|
||||
|
||||
Flog.RayTracer.Material.Chessboard = Class.create();
|
||||
|
||||
Flog.RayTracer.Material.Chessboard.prototype = Object.extend(
|
||||
new Flog.RayTracer.Material.BaseMaterial(), {
|
||||
colorEven: null,
|
||||
colorOdd: null,
|
||||
density: 0.5,
|
||||
|
||||
initialize : function(colorEven, colorOdd, reflection, transparency, gloss, density) {
|
||||
this.colorEven = colorEven;
|
||||
this.colorOdd = colorOdd;
|
||||
this.reflection = reflection;
|
||||
this.transparency = transparency;
|
||||
this.gloss = gloss;
|
||||
this.density = density;
|
||||
this.hasTexture = true;
|
||||
},
|
||||
|
||||
getColor: function(u, v){
|
||||
var t = this.wrapUp(u * this.density) * this.wrapUp(v * this.density);
|
||||
|
||||
if(t < 0.0)
|
||||
return this.colorEven;
|
||||
else
|
||||
return this.colorOdd;
|
||||
},
|
||||
|
||||
toString : function () {
|
||||
return 'ChessMaterial [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
|
||||
}
|
||||
}
|
||||
);
|
||||
/* Fake a Flog.* namespace */
|
||||
if(typeof(Flog) == 'undefined') var Flog = {};
|
||||
if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
|
||||
if(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {};
|
||||
|
||||
Flog.RayTracer.Shape.BaseShape = Class.create();
|
||||
|
||||
Flog.RayTracer.Shape.BaseShape.prototype = {
|
||||
position: null,
|
||||
material: null,
|
||||
|
||||
initialize : function() {
|
||||
this.position = new Vector(0,0,0);
|
||||
this.material = new Flog.RayTracer.Material.SolidMaterial(
|
||||
new Flog.RayTracer.Color(1,0,1),
|
||||
0,
|
||||
0,
|
||||
0
|
||||
);
|
||||
},
|
||||
|
||||
toString : function () {
|
||||
return 'Material [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
|
||||
}
|
||||
}
|
||||
/* Fake a Flog.* namespace */
|
||||
if(typeof(Flog) == 'undefined') var Flog = {};
|
||||
if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
|
||||
if(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {};
|
||||
|
||||
Flog.RayTracer.Shape.Sphere = Class.create();
|
||||
|
||||
Flog.RayTracer.Shape.Sphere.prototype = {
|
||||
initialize : function(pos, radius, material) {
|
||||
this.radius = radius;
|
||||
this.position = pos;
|
||||
this.material = material;
|
||||
},
|
||||
|
||||
intersect: function(ray){
|
||||
var info = new Flog.RayTracer.IntersectionInfo();
|
||||
info.shape = this;
|
||||
|
||||
var dst = Flog.RayTracer.Vector.prototype.subtract(ray.position, this.position);
|
||||
|
||||
var B = dst.dot(ray.direction);
|
||||
var C = dst.dot(dst) - (this.radius * this.radius);
|
||||
var D = (B * B) - C;
|
||||
|
||||
if(D > 0){ // intersection!
|
||||
info.isHit = true;
|
||||
info.distance = (-B) - Math.sqrt(D);
|
||||
info.position = Flog.RayTracer.Vector.prototype.add(
|
||||
ray.position,
|
||||
Flog.RayTracer.Vector.prototype.multiplyScalar(
|
||||
ray.direction,
|
||||
info.distance
|
||||
)
|
||||
);
|
||||
info.normal = Flog.RayTracer.Vector.prototype.subtract(
|
||||
info.position,
|
||||
this.position
|
||||
).normalize();
|
||||
|
||||
info.color = this.material.getColor(0,0);
|
||||
} else {
|
||||
info.isHit = false;
|
||||
}
|
||||
return info;
|
||||
},
|
||||
|
||||
toString : function () {
|
||||
return 'Sphere [position=' + this.position + ', radius=' + this.radius + ']';
|
||||
}
|
||||
}
|
||||
/* Fake a Flog.* namespace */
|
||||
if(typeof(Flog) == 'undefined') var Flog = {};
|
||||
if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
|
||||
if(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {};
|
||||
|
||||
Flog.RayTracer.Shape.Plane = Class.create();
|
||||
|
||||
Flog.RayTracer.Shape.Plane.prototype = {
|
||||
d: 0.0,
|
||||
|
||||
initialize : function(pos, d, material) {
|
||||
this.position = pos;
|
||||
this.d = d;
|
||||
this.material = material;
|
||||
},
|
||||
|
||||
intersect: function(ray){
|
||||
var info = new Flog.RayTracer.IntersectionInfo();
|
||||
|
||||
var Vd = this.position.dot(ray.direction);
|
||||
if(Vd == 0) return info; // no intersection
|
||||
|
||||
var t = -(this.position.dot(ray.position) + this.d) / Vd;
|
||||
if(t <= 0) return info;
|
||||
|
||||
info.shape = this;
|
||||
info.isHit = true;
|
||||
info.position = Flog.RayTracer.Vector.prototype.add(
|
||||
ray.position,
|
||||
Flog.RayTracer.Vector.prototype.multiplyScalar(
|
||||
ray.direction,
|
||||
t
|
||||
)
|
||||
);
|
||||
info.normal = this.position;
|
||||
info.distance = t;
|
||||
|
||||
if(this.material.hasTexture){
|
||||
var vU = new Flog.RayTracer.Vector(this.position.y, this.position.z, -this.position.x);
|
||||
var vV = vU.cross(this.position);
|
||||
var u = info.position.dot(vU);
|
||||
var v = info.position.dot(vV);
|
||||
info.color = this.material.getColor(u,v);
|
||||
} else {
|
||||
info.color = this.material.getColor(0,0);
|
||||
}
|
||||
|
||||
return info;
|
||||
},
|
||||
|
||||
toString : function () {
|
||||
return 'Plane [' + this.position + ', d=' + this.d + ']';
|
||||
}
|
||||
}
|
||||
/* Fake a Flog.* namespace */
|
||||
if(typeof(Flog) == 'undefined') var Flog = {};
|
||||
if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
|
||||
|
||||
Flog.RayTracer.IntersectionInfo = Class.create();
|
||||
|
||||
Flog.RayTracer.IntersectionInfo.prototype = {
|
||||
isHit: false,
|
||||
hitCount: 0,
|
||||
shape: null,
|
||||
position: null,
|
||||
normal: null,
|
||||
color: null,
|
||||
distance: null,
|
||||
|
||||
initialize : function() {
|
||||
this.color = new Flog.RayTracer.Color(0,0,0);
|
||||
},
|
||||
|
||||
toString : function () {
|
||||
return 'Intersection [' + this.position + ']';
|
||||
}
|
||||
}
|
||||
/* Fake a Flog.* namespace */
|
||||
if(typeof(Flog) == 'undefined') var Flog = {};
|
||||
if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
|
||||
|
||||
Flog.RayTracer.Camera = Class.create();
|
||||
|
||||
Flog.RayTracer.Camera.prototype = {
|
||||
position: null,
|
||||
lookAt: null,
|
||||
equator: null,
|
||||
up: null,
|
||||
screen: null,
|
||||
|
||||
initialize : function(pos, lookAt, up) {
|
||||
this.position = pos;
|
||||
this.lookAt = lookAt;
|
||||
this.up = up;
|
||||
this.equator = lookAt.normalize().cross(this.up);
|
||||
this.screen = Flog.RayTracer.Vector.prototype.add(this.position, this.lookAt);
|
||||
},
|
||||
|
||||
getRay: function(vx, vy){
|
||||
var pos = Flog.RayTracer.Vector.prototype.subtract(
|
||||
this.screen,
|
||||
Flog.RayTracer.Vector.prototype.subtract(
|
||||
Flog.RayTracer.Vector.prototype.multiplyScalar(this.equator, vx),
|
||||
Flog.RayTracer.Vector.prototype.multiplyScalar(this.up, vy)
|
||||
)
|
||||
);
|
||||
pos.y = pos.y * -1;
|
||||
var dir = Flog.RayTracer.Vector.prototype.subtract(
|
||||
pos,
|
||||
this.position
|
||||
);
|
||||
|
||||
var ray = new Flog.RayTracer.Ray(pos, dir.normalize());
|
||||
|
||||
return ray;
|
||||
},
|
||||
|
||||
toString : function () {
|
||||
return 'Ray []';
|
||||
}
|
||||
}
|
||||
/* Fake a Flog.* namespace */
|
||||
if(typeof(Flog) == 'undefined') var Flog = {};
|
||||
if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
|
||||
|
||||
Flog.RayTracer.Background = Class.create();
|
||||
|
||||
Flog.RayTracer.Background.prototype = {
|
||||
color : null,
|
||||
ambience : 0.0,
|
||||
|
||||
initialize : function(color, ambience) {
|
||||
this.color = color;
|
||||
this.ambience = ambience;
|
||||
}
|
||||
}
|
||||
/* Fake a Flog.* namespace */
|
||||
if(typeof(Flog) == 'undefined') var Flog = {};
|
||||
if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
|
||||
|
||||
Flog.RayTracer.Engine = Class.create();
|
||||
|
||||
Flog.RayTracer.Engine.prototype = {
|
||||
canvas: null, /* 2d context we can render to */
|
||||
|
||||
initialize: function(options){
|
||||
this.options = Object.extend({
|
||||
canvasHeight: 100,
|
||||
canvasWidth: 100,
|
||||
pixelWidth: 2,
|
||||
pixelHeight: 2,
|
||||
renderDiffuse: false,
|
||||
renderShadows: false,
|
||||
renderHighlights: false,
|
||||
renderReflections: false,
|
||||
rayDepth: 2
|
||||
}, options || {});
|
||||
|
||||
this.options.canvasHeight /= this.options.pixelHeight;
|
||||
this.options.canvasWidth /= this.options.pixelWidth;
|
||||
|
||||
/* TODO: dynamically include other scripts */
|
||||
},
|
||||
|
||||
setPixel: function(x, y, color){
|
||||
var pxW, pxH;
|
||||
pxW = this.options.pixelWidth;
|
||||
pxH = this.options.pixelHeight;
|
||||
|
||||
if (this.canvas) {
|
||||
this.canvas.fillStyle = color.toString();
|
||||
this.canvas.fillRect (x * pxW, y * pxH, pxW, pxH);
|
||||
} else {
|
||||
if (x === y) {
|
||||
checkNumber += color.brightness();
|
||||
}
|
||||
// print(x * pxW, y * pxH, pxW, pxH);
|
||||
}
|
||||
},
|
||||
|
||||
renderScene: function(scene, canvas){
|
||||
checkNumber = 0;
|
||||
/* Get canvas */
|
||||
if (canvas) {
|
||||
this.canvas = canvas.getContext("2d");
|
||||
} else {
|
||||
this.canvas = null;
|
||||
}
|
||||
|
||||
var canvasHeight = this.options.canvasHeight;
|
||||
var canvasWidth = this.options.canvasWidth;
|
||||
|
||||
for(var y=0; y < canvasHeight; y++){
|
||||
for(var x=0; x < canvasWidth; x++){
|
||||
var yp = y * 1.0 / canvasHeight * 2 - 1;
|
||||
var xp = x * 1.0 / canvasWidth * 2 - 1;
|
||||
|
||||
var ray = scene.camera.getRay(xp, yp);
|
||||
|
||||
var color = this.getPixelColor(ray, scene);
|
||||
|
||||
this.setPixel(x, y, color);
|
||||
}
|
||||
}
|
||||
if (checkNumber !== 2321) {
|
||||
throw new Error("Scene rendered incorrectly");
|
||||
}
|
||||
},
|
||||
|
||||
getPixelColor: function(ray, scene){
|
||||
var info = this.testIntersection(ray, scene, null);
|
||||
if(info.isHit){
|
||||
var color = this.rayTrace(info, ray, scene, 0);
|
||||
return color;
|
||||
}
|
||||
return scene.background.color;
|
||||
},
|
||||
|
||||
testIntersection: function(ray, scene, exclude){
|
||||
var hits = 0;
|
||||
var best = new Flog.RayTracer.IntersectionInfo();
|
||||
best.distance = 2000;
|
||||
|
||||
for(var i=0; i<scene.shapes.length; i++){
|
||||
var shape = scene.shapes[i];
|
||||
|
||||
if(shape != exclude){
|
||||
var info = shape.intersect(ray);
|
||||
if(info.isHit && info.distance >= 0 && info.distance < best.distance){
|
||||
best = info;
|
||||
hits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
best.hitCount = hits;
|
||||
return best;
|
||||
},
|
||||
|
||||
getReflectionRay: function(P,N,V){
|
||||
var c1 = -N.dot(V);
|
||||
var R1 = Flog.RayTracer.Vector.prototype.add(
|
||||
Flog.RayTracer.Vector.prototype.multiplyScalar(N, 2*c1),
|
||||
V
|
||||
);
|
||||
return new Flog.RayTracer.Ray(P, R1);
|
||||
},
|
||||
|
||||
rayTrace: function(info, ray, scene, depth){
|
||||
// Calc ambient
|
||||
var color = Flog.RayTracer.Color.prototype.multiplyScalar(info.color, scene.background.ambience);
|
||||
var oldColor = color;
|
||||
var shininess = Math.pow(10, info.shape.material.gloss + 1);
|
||||
|
||||
for(var i=0; i<scene.lights.length; i++){
|
||||
var light = scene.lights[i];
|
||||
|
||||
// Calc diffuse lighting
|
||||
var v = Flog.RayTracer.Vector.prototype.subtract(
|
||||
light.position,
|
||||
info.position
|
||||
).normalize();
|
||||
|
||||
if(this.options.renderDiffuse){
|
||||
var L = v.dot(info.normal);
|
||||
if(L > 0.0){
|
||||
color = Flog.RayTracer.Color.prototype.add(
|
||||
color,
|
||||
Flog.RayTracer.Color.prototype.multiply(
|
||||
info.color,
|
||||
Flog.RayTracer.Color.prototype.multiplyScalar(
|
||||
light.color,
|
||||
L
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// The greater the depth the more accurate the colours, but
|
||||
// this is exponentially (!) expensive
|
||||
if(depth <= this.options.rayDepth){
|
||||
// calculate reflection ray
|
||||
if(this.options.renderReflections && info.shape.material.reflection > 0)
|
||||
{
|
||||
var reflectionRay = this.getReflectionRay(info.position, info.normal, ray.direction);
|
||||
var refl = this.testIntersection(reflectionRay, scene, info.shape);
|
||||
|
||||
if (refl.isHit && refl.distance > 0){
|
||||
refl.color = this.rayTrace(refl, reflectionRay, scene, depth + 1);
|
||||
} else {
|
||||
refl.color = scene.background.color;
|
||||
}
|
||||
|
||||
color = Flog.RayTracer.Color.prototype.blend(
|
||||
color,
|
||||
refl.color,
|
||||
info.shape.material.reflection
|
||||
);
|
||||
}
|
||||
|
||||
// Refraction
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
/* Render shadows and highlights */
|
||||
|
||||
var shadowInfo = new Flog.RayTracer.IntersectionInfo();
|
||||
|
||||
if(this.options.renderShadows){
|
||||
var shadowRay = new Flog.RayTracer.Ray(info.position, v);
|
||||
|
||||
shadowInfo = this.testIntersection(shadowRay, scene, info.shape);
|
||||
if(shadowInfo.isHit && shadowInfo.shape != info.shape /*&& shadowInfo.shape.type != 'PLANE'*/){
|
||||
var vA = Flog.RayTracer.Color.prototype.multiplyScalar(color, 0.5);
|
||||
var dB = (0.5 * Math.pow(shadowInfo.shape.material.transparency, 0.5));
|
||||
color = Flog.RayTracer.Color.prototype.addScalar(vA,dB);
|
||||
}
|
||||
}
|
||||
|
||||
// Phong specular highlights
|
||||
if(this.options.renderHighlights && !shadowInfo.isHit && info.shape.material.gloss > 0){
|
||||
var Lv = Flog.RayTracer.Vector.prototype.subtract(
|
||||
info.shape.position,
|
||||
light.position
|
||||
).normalize();
|
||||
|
||||
var E = Flog.RayTracer.Vector.prototype.subtract(
|
||||
scene.camera.position,
|
||||
info.shape.position
|
||||
).normalize();
|
||||
|
||||
var H = Flog.RayTracer.Vector.prototype.subtract(
|
||||
E,
|
||||
Lv
|
||||
).normalize();
|
||||
|
||||
var glossWeight = Math.pow(Math.max(info.normal.dot(H), 0), shininess);
|
||||
color = Flog.RayTracer.Color.prototype.add(
|
||||
Flog.RayTracer.Color.prototype.multiplyScalar(light.color, glossWeight),
|
||||
color
|
||||
);
|
||||
}
|
||||
}
|
||||
color.limit();
|
||||
return color;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function renderScene(){
|
||||
var scene = new Flog.RayTracer.Scene();
|
||||
|
||||
scene.camera = new Flog.RayTracer.Camera(
|
||||
new Flog.RayTracer.Vector(0, 0, -15),
|
||||
new Flog.RayTracer.Vector(-0.2, 0, 5),
|
||||
new Flog.RayTracer.Vector(0, 1, 0)
|
||||
);
|
||||
|
||||
scene.background = new Flog.RayTracer.Background(
|
||||
new Flog.RayTracer.Color(0.5, 0.5, 0.5),
|
||||
0.4
|
||||
);
|
||||
|
||||
var sphere = new Flog.RayTracer.Shape.Sphere(
|
||||
new Flog.RayTracer.Vector(-1.5, 1.5, 2),
|
||||
1.5,
|
||||
new Flog.RayTracer.Material.Solid(
|
||||
new Flog.RayTracer.Color(0,0.5,0.5),
|
||||
0.3,
|
||||
0.0,
|
||||
0.0,
|
||||
2.0
|
||||
)
|
||||
);
|
||||
|
||||
var sphere1 = new Flog.RayTracer.Shape.Sphere(
|
||||
new Flog.RayTracer.Vector(1, 0.25, 1),
|
||||
0.5,
|
||||
new Flog.RayTracer.Material.Solid(
|
||||
new Flog.RayTracer.Color(0.9,0.9,0.9),
|
||||
0.1,
|
||||
0.0,
|
||||
0.0,
|
||||
1.5
|
||||
)
|
||||
);
|
||||
|
||||
var plane = new Flog.RayTracer.Shape.Plane(
|
||||
new Flog.RayTracer.Vector(0.1, 0.9, -0.5).normalize(),
|
||||
1.2,
|
||||
new Flog.RayTracer.Material.Chessboard(
|
||||
new Flog.RayTracer.Color(1,1,1),
|
||||
new Flog.RayTracer.Color(0,0,0),
|
||||
0.2,
|
||||
0.0,
|
||||
1.0,
|
||||
0.7
|
||||
)
|
||||
);
|
||||
|
||||
scene.shapes.push(plane);
|
||||
scene.shapes.push(sphere);
|
||||
scene.shapes.push(sphere1);
|
||||
|
||||
var light = new Flog.RayTracer.Light(
|
||||
new Flog.RayTracer.Vector(5, 10, -1),
|
||||
new Flog.RayTracer.Color(0.8, 0.8, 0.8)
|
||||
);
|
||||
|
||||
var light1 = new Flog.RayTracer.Light(
|
||||
new Flog.RayTracer.Vector(-3, 5, -15),
|
||||
new Flog.RayTracer.Color(0.8, 0.8, 0.8),
|
||||
100
|
||||
);
|
||||
|
||||
scene.lights.push(light);
|
||||
scene.lights.push(light1);
|
||||
|
||||
var imageWidth = 100; // $F('imageWidth');
|
||||
var imageHeight = 100; // $F('imageHeight');
|
||||
var pixelSize = "5,5".split(','); // $F('pixelSize').split(',');
|
||||
var renderDiffuse = true; // $F('renderDiffuse');
|
||||
var renderShadows = true; // $F('renderShadows');
|
||||
var renderHighlights = true; // $F('renderHighlights');
|
||||
var renderReflections = true; // $F('renderReflections');
|
||||
var rayDepth = 2;//$F('rayDepth');
|
||||
|
||||
var raytracer = new Flog.RayTracer.Engine(
|
||||
{
|
||||
canvasWidth: imageWidth,
|
||||
canvasHeight: imageHeight,
|
||||
pixelWidth: pixelSize[0],
|
||||
pixelHeight: pixelSize[1],
|
||||
"renderDiffuse": renderDiffuse,
|
||||
"renderHighlights": renderHighlights,
|
||||
"renderShadows": renderShadows,
|
||||
"renderReflections": renderReflections,
|
||||
"rayDepth": rayDepth
|
||||
}
|
||||
);
|
||||
|
||||
raytracer.renderScene(scene, null, 0);
|
||||
}
|
||||
|
||||
for (var i = 0; i < 6; ++i)
|
||||
renderScene();
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,537 +0,0 @@
|
|||
// Copyright 2006-2008 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// This is a JavaScript implementation of the Richards
|
||||
// benchmark from:
|
||||
//
|
||||
// http://www.cl.cam.ac.uk/~mr10/Bench.html
|
||||
//
|
||||
// The benchmark was originally implemented in BCPL by
|
||||
// Martin Richards.
|
||||
|
||||
|
||||
/**
|
||||
* The Richards benchmark simulates the task dispatcher of an
|
||||
* operating system.
|
||||
**/
|
||||
function runRichards() {
|
||||
var scheduler = new Scheduler();
|
||||
scheduler.addIdleTask(ID_IDLE, 0, null, COUNT);
|
||||
|
||||
var queue = new Packet(null, ID_WORKER, KIND_WORK);
|
||||
queue = new Packet(queue, ID_WORKER, KIND_WORK);
|
||||
scheduler.addWorkerTask(ID_WORKER, 1000, queue);
|
||||
|
||||
queue = new Packet(null, ID_DEVICE_A, KIND_DEVICE);
|
||||
queue = new Packet(queue, ID_DEVICE_A, KIND_DEVICE);
|
||||
queue = new Packet(queue, ID_DEVICE_A, KIND_DEVICE);
|
||||
scheduler.addHandlerTask(ID_HANDLER_A, 2000, queue);
|
||||
|
||||
queue = new Packet(null, ID_DEVICE_B, KIND_DEVICE);
|
||||
queue = new Packet(queue, ID_DEVICE_B, KIND_DEVICE);
|
||||
queue = new Packet(queue, ID_DEVICE_B, KIND_DEVICE);
|
||||
scheduler.addHandlerTask(ID_HANDLER_B, 3000, queue);
|
||||
|
||||
scheduler.addDeviceTask(ID_DEVICE_A, 4000, null);
|
||||
|
||||
scheduler.addDeviceTask(ID_DEVICE_B, 5000, null);
|
||||
|
||||
scheduler.schedule();
|
||||
|
||||
if (scheduler.queueCount != EXPECTED_QUEUE_COUNT ||
|
||||
scheduler.holdCount != EXPECTED_HOLD_COUNT) {
|
||||
var msg =
|
||||
"Error during execution: queueCount = " + scheduler.queueCount +
|
||||
", holdCount = " + scheduler.holdCount + ".";
|
||||
throw new Error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
var COUNT = 1000;
|
||||
|
||||
/**
|
||||
* These two constants specify how many times a packet is queued and
|
||||
* how many times a task is put on hold in a correct run of richards.
|
||||
* They don't have any meaning a such but are characteristic of a
|
||||
* correct run so if the actual queue or hold count is different from
|
||||
* the expected there must be a bug in the implementation.
|
||||
**/
|
||||
var EXPECTED_QUEUE_COUNT = 2322;
|
||||
var EXPECTED_HOLD_COUNT = 928;
|
||||
|
||||
|
||||
/**
|
||||
* A scheduler can be used to schedule a set of tasks based on their relative
|
||||
* priorities. Scheduling is done by maintaining a list of task control blocks
|
||||
* which holds tasks and the data queue they are processing.
|
||||
* @constructor
|
||||
*/
|
||||
function Scheduler() {
|
||||
this.queueCount = 0;
|
||||
this.holdCount = 0;
|
||||
this.blocks = new Array(NUMBER_OF_IDS);
|
||||
this.list = null;
|
||||
this.currentTcb = null;
|
||||
this.currentId = null;
|
||||
}
|
||||
|
||||
var ID_IDLE = 0;
|
||||
var ID_WORKER = 1;
|
||||
var ID_HANDLER_A = 2;
|
||||
var ID_HANDLER_B = 3;
|
||||
var ID_DEVICE_A = 4;
|
||||
var ID_DEVICE_B = 5;
|
||||
var NUMBER_OF_IDS = 6;
|
||||
|
||||
var KIND_DEVICE = 0;
|
||||
var KIND_WORK = 1;
|
||||
|
||||
/**
|
||||
* Add an idle task to this scheduler.
|
||||
* @param {int} id the identity of the task
|
||||
* @param {int} priority the task's priority
|
||||
* @param {Packet} queue the queue of work to be processed by the task
|
||||
* @param {int} count the number of times to schedule the task
|
||||
*/
|
||||
Scheduler.prototype.addIdleTask = function (id, priority, queue, count) {
|
||||
this.addRunningTask(id, priority, queue, new IdleTask(this, 1, count));
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a work task to this scheduler.
|
||||
* @param {int} id the identity of the task
|
||||
* @param {int} priority the task's priority
|
||||
* @param {Packet} queue the queue of work to be processed by the task
|
||||
*/
|
||||
Scheduler.prototype.addWorkerTask = function (id, priority, queue) {
|
||||
this.addTask(id, priority, queue, new WorkerTask(this, ID_HANDLER_A, 0));
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a handler task to this scheduler.
|
||||
* @param {int} id the identity of the task
|
||||
* @param {int} priority the task's priority
|
||||
* @param {Packet} queue the queue of work to be processed by the task
|
||||
*/
|
||||
Scheduler.prototype.addHandlerTask = function (id, priority, queue) {
|
||||
this.addTask(id, priority, queue, new HandlerTask(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a handler task to this scheduler.
|
||||
* @param {int} id the identity of the task
|
||||
* @param {int} priority the task's priority
|
||||
* @param {Packet} queue the queue of work to be processed by the task
|
||||
*/
|
||||
Scheduler.prototype.addDeviceTask = function (id, priority, queue) {
|
||||
this.addTask(id, priority, queue, new DeviceTask(this))
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the specified task and mark it as running.
|
||||
* @param {int} id the identity of the task
|
||||
* @param {int} priority the task's priority
|
||||
* @param {Packet} queue the queue of work to be processed by the task
|
||||
* @param {Task} task the task to add
|
||||
*/
|
||||
Scheduler.prototype.addRunningTask = function (id, priority, queue, task) {
|
||||
this.addTask(id, priority, queue, task);
|
||||
this.currentTcb.setRunning();
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the specified task to this scheduler.
|
||||
* @param {int} id the identity of the task
|
||||
* @param {int} priority the task's priority
|
||||
* @param {Packet} queue the queue of work to be processed by the task
|
||||
* @param {Task} task the task to add
|
||||
*/
|
||||
Scheduler.prototype.addTask = function (id, priority, queue, task) {
|
||||
this.currentTcb = new TaskControlBlock(this.list, id, priority, queue, task);
|
||||
this.list = this.currentTcb;
|
||||
this.blocks[id] = this.currentTcb;
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute the tasks managed by this scheduler.
|
||||
*/
|
||||
Scheduler.prototype.schedule = function () {
|
||||
this.currentTcb = this.list;
|
||||
while (this.currentTcb != null) {
|
||||
if (this.currentTcb.isHeldOrSuspended()) {
|
||||
this.currentTcb = this.currentTcb.link;
|
||||
} else {
|
||||
this.currentId = this.currentTcb.id;
|
||||
this.currentTcb = this.currentTcb.run();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Release a task that is currently blocked and return the next block to run.
|
||||
* @param {int} id the id of the task to suspend
|
||||
*/
|
||||
Scheduler.prototype.release = function (id) {
|
||||
var tcb = this.blocks[id];
|
||||
if (tcb == null) return tcb;
|
||||
tcb.markAsNotHeld();
|
||||
if (tcb.priority > this.currentTcb.priority) {
|
||||
return tcb;
|
||||
} else {
|
||||
return this.currentTcb;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Block the currently executing task and return the next task control block
|
||||
* to run. The blocked task will not be made runnable until it is explicitly
|
||||
* released, even if new work is added to it.
|
||||
*/
|
||||
Scheduler.prototype.holdCurrent = function () {
|
||||
this.holdCount++;
|
||||
this.currentTcb.markAsHeld();
|
||||
return this.currentTcb.link;
|
||||
};
|
||||
|
||||
/**
|
||||
* Suspend the currently executing task and return the next task control block
|
||||
* to run. If new work is added to the suspended task it will be made runnable.
|
||||
*/
|
||||
Scheduler.prototype.suspendCurrent = function () {
|
||||
this.currentTcb.markAsSuspended();
|
||||
return this.currentTcb;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the specified packet to the end of the worklist used by the task
|
||||
* associated with the packet and make the task runnable if it is currently
|
||||
* suspended.
|
||||
* @param {Packet} packet the packet to add
|
||||
*/
|
||||
Scheduler.prototype.queue = function (packet) {
|
||||
var t = this.blocks[packet.id];
|
||||
if (t == null) return t;
|
||||
this.queueCount++;
|
||||
packet.link = null;
|
||||
packet.id = this.currentId;
|
||||
return t.checkPriorityAdd(this.currentTcb, packet);
|
||||
};
|
||||
|
||||
/**
|
||||
* A task control block manages a task and the queue of work packages associated
|
||||
* with it.
|
||||
* @param {TaskControlBlock} link the preceding block in the linked block list
|
||||
* @param {int} id the id of this block
|
||||
* @param {int} priority the priority of this block
|
||||
* @param {Packet} queue the queue of packages to be processed by the task
|
||||
* @param {Task} task the task
|
||||
* @constructor
|
||||
*/
|
||||
function TaskControlBlock(link, id, priority, queue, task) {
|
||||
this.link = link;
|
||||
this.id = id;
|
||||
this.priority = priority;
|
||||
this.queue = queue;
|
||||
this.task = task;
|
||||
if (queue == null) {
|
||||
this.state = STATE_SUSPENDED;
|
||||
} else {
|
||||
this.state = STATE_SUSPENDED_RUNNABLE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The task is running and is currently scheduled.
|
||||
*/
|
||||
var STATE_RUNNING = 0;
|
||||
|
||||
/**
|
||||
* The task has packets left to process.
|
||||
*/
|
||||
var STATE_RUNNABLE = 1;
|
||||
|
||||
/**
|
||||
* The task is not currently running. The task is not blocked as such and may
|
||||
* be started by the scheduler.
|
||||
*/
|
||||
var STATE_SUSPENDED = 2;
|
||||
|
||||
/**
|
||||
* The task is blocked and cannot be run until it is explicitly released.
|
||||
*/
|
||||
var STATE_HELD = 4;
|
||||
|
||||
var STATE_SUSPENDED_RUNNABLE = STATE_SUSPENDED | STATE_RUNNABLE;
|
||||
var STATE_NOT_HELD = ~STATE_HELD;
|
||||
|
||||
TaskControlBlock.prototype.setRunning = function () {
|
||||
this.state = STATE_RUNNING;
|
||||
};
|
||||
|
||||
TaskControlBlock.prototype.markAsNotHeld = function () {
|
||||
this.state = this.state & STATE_NOT_HELD;
|
||||
};
|
||||
|
||||
TaskControlBlock.prototype.markAsHeld = function () {
|
||||
this.state = this.state | STATE_HELD;
|
||||
};
|
||||
|
||||
TaskControlBlock.prototype.isHeldOrSuspended = function () {
|
||||
return (this.state & STATE_HELD) != 0 || (this.state == STATE_SUSPENDED);
|
||||
};
|
||||
|
||||
TaskControlBlock.prototype.markAsSuspended = function () {
|
||||
this.state = this.state | STATE_SUSPENDED;
|
||||
};
|
||||
|
||||
TaskControlBlock.prototype.markAsRunnable = function () {
|
||||
this.state = this.state | STATE_RUNNABLE;
|
||||
};
|
||||
|
||||
/**
|
||||
* Runs this task, if it is ready to be run, and returns the next task to run.
|
||||
*/
|
||||
TaskControlBlock.prototype.run = function () {
|
||||
var packet;
|
||||
if (this.state == STATE_SUSPENDED_RUNNABLE) {
|
||||
packet = this.queue;
|
||||
this.queue = packet.link;
|
||||
if (this.queue == null) {
|
||||
this.state = STATE_RUNNING;
|
||||
} else {
|
||||
this.state = STATE_RUNNABLE;
|
||||
}
|
||||
} else {
|
||||
packet = null;
|
||||
}
|
||||
return this.task.run(packet);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a packet to the worklist of this block's task, marks this as runnable if
|
||||
* necessary, and returns the next runnable object to run (the one
|
||||
* with the highest priority).
|
||||
*/
|
||||
TaskControlBlock.prototype.checkPriorityAdd = function (task, packet) {
|
||||
if (this.queue == null) {
|
||||
this.queue = packet;
|
||||
this.markAsRunnable();
|
||||
if (this.priority > task.priority) return this;
|
||||
} else {
|
||||
this.queue = packet.addTo(this.queue);
|
||||
}
|
||||
return task;
|
||||
};
|
||||
|
||||
TaskControlBlock.prototype.toString = function () {
|
||||
return "tcb { " + this.task + "@" + this.state + " }";
|
||||
};
|
||||
|
||||
/**
|
||||
* An idle task doesn't do any work itself but cycles control between the two
|
||||
* device tasks.
|
||||
* @param {Scheduler} scheduler the scheduler that manages this task
|
||||
* @param {int} v1 a seed value that controls how the device tasks are scheduled
|
||||
* @param {int} count the number of times this task should be scheduled
|
||||
* @constructor
|
||||
*/
|
||||
function IdleTask(scheduler, v1, count) {
|
||||
this.scheduler = scheduler;
|
||||
this.v1 = v1;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
IdleTask.prototype.run = function (packet) {
|
||||
this.count--;
|
||||
if (this.count == 0) return this.scheduler.holdCurrent();
|
||||
if ((this.v1 & 1) == 0) {
|
||||
this.v1 = this.v1 >> 1;
|
||||
return this.scheduler.release(ID_DEVICE_A);
|
||||
} else {
|
||||
this.v1 = (this.v1 >> 1) ^ 0xD008;
|
||||
return this.scheduler.release(ID_DEVICE_B);
|
||||
}
|
||||
};
|
||||
|
||||
IdleTask.prototype.toString = function () {
|
||||
return "IdleTask"
|
||||
};
|
||||
|
||||
/**
|
||||
* A task that suspends itself after each time it has been run to simulate
|
||||
* waiting for data from an external device.
|
||||
* @param {Scheduler} scheduler the scheduler that manages this task
|
||||
* @constructor
|
||||
*/
|
||||
function DeviceTask(scheduler) {
|
||||
this.scheduler = scheduler;
|
||||
this.v1 = null;
|
||||
}
|
||||
|
||||
DeviceTask.prototype.run = function (packet) {
|
||||
if (packet == null) {
|
||||
if (this.v1 == null) return this.scheduler.suspendCurrent();
|
||||
var v = this.v1;
|
||||
this.v1 = null;
|
||||
return this.scheduler.queue(v);
|
||||
} else {
|
||||
this.v1 = packet;
|
||||
return this.scheduler.holdCurrent();
|
||||
}
|
||||
};
|
||||
|
||||
DeviceTask.prototype.toString = function () {
|
||||
return "DeviceTask";
|
||||
};
|
||||
|
||||
/**
|
||||
* A task that manipulates work packets.
|
||||
* @param {Scheduler} scheduler the scheduler that manages this task
|
||||
* @param {int} v1 a seed used to specify how work packets are manipulated
|
||||
* @param {int} v2 another seed used to specify how work packets are manipulated
|
||||
* @constructor
|
||||
*/
|
||||
function WorkerTask(scheduler, v1, v2) {
|
||||
this.scheduler = scheduler;
|
||||
this.v1 = v1;
|
||||
this.v2 = v2;
|
||||
}
|
||||
|
||||
WorkerTask.prototype.run = function (packet) {
|
||||
if (packet == null) {
|
||||
return this.scheduler.suspendCurrent();
|
||||
} else {
|
||||
if (this.v1 == ID_HANDLER_A) {
|
||||
this.v1 = ID_HANDLER_B;
|
||||
} else {
|
||||
this.v1 = ID_HANDLER_A;
|
||||
}
|
||||
packet.id = this.v1;
|
||||
packet.a1 = 0;
|
||||
for (var i = 0; i < DATA_SIZE; i++) {
|
||||
this.v2++;
|
||||
if (this.v2 > 26) this.v2 = 1;
|
||||
packet.a2[i] = this.v2;
|
||||
}
|
||||
return this.scheduler.queue(packet);
|
||||
}
|
||||
};
|
||||
|
||||
WorkerTask.prototype.toString = function () {
|
||||
return "WorkerTask";
|
||||
};
|
||||
|
||||
/**
|
||||
* A task that manipulates work packets and then suspends itself.
|
||||
* @param {Scheduler} scheduler the scheduler that manages this task
|
||||
* @constructor
|
||||
*/
|
||||
function HandlerTask(scheduler) {
|
||||
this.scheduler = scheduler;
|
||||
this.v1 = null;
|
||||
this.v2 = null;
|
||||
}
|
||||
|
||||
HandlerTask.prototype.run = function (packet) {
|
||||
if (packet != null) {
|
||||
if (packet.kind == KIND_WORK) {
|
||||
this.v1 = packet.addTo(this.v1);
|
||||
} else {
|
||||
this.v2 = packet.addTo(this.v2);
|
||||
}
|
||||
}
|
||||
if (this.v1 != null) {
|
||||
var count = this.v1.a1;
|
||||
var v;
|
||||
if (count < DATA_SIZE) {
|
||||
if (this.v2 != null) {
|
||||
v = this.v2;
|
||||
this.v2 = this.v2.link;
|
||||
v.a1 = this.v1.a2[count];
|
||||
this.v1.a1 = count + 1;
|
||||
return this.scheduler.queue(v);
|
||||
}
|
||||
} else {
|
||||
v = this.v1;
|
||||
this.v1 = this.v1.link;
|
||||
return this.scheduler.queue(v);
|
||||
}
|
||||
}
|
||||
return this.scheduler.suspendCurrent();
|
||||
};
|
||||
|
||||
HandlerTask.prototype.toString = function () {
|
||||
return "HandlerTask";
|
||||
};
|
||||
|
||||
/* --- *
|
||||
* P a c k e t
|
||||
* --- */
|
||||
|
||||
var DATA_SIZE = 4;
|
||||
|
||||
/**
|
||||
* A simple package of data that is manipulated by the tasks. The exact layout
|
||||
* of the payload data carried by a packet is not importaint, and neither is the
|
||||
* nature of the work performed on packets by the tasks.
|
||||
*
|
||||
* Besides carrying data, packets form linked lists and are hence used both as
|
||||
* data and worklists.
|
||||
* @param {Packet} link the tail of the linked list of packets
|
||||
* @param {int} id an ID for this packet
|
||||
* @param {int} kind the type of this packet
|
||||
* @constructor
|
||||
*/
|
||||
function Packet(link, id, kind) {
|
||||
this.link = link;
|
||||
this.id = id;
|
||||
this.kind = kind;
|
||||
this.a1 = 0;
|
||||
this.a2 = new Array(DATA_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add this packet to the end of a worklist, and return the worklist.
|
||||
* @param {Packet} queue the worklist to add this packet to
|
||||
*/
|
||||
Packet.prototype.addTo = function (queue) {
|
||||
this.link = null;
|
||||
if (queue == null) return this;
|
||||
var peek, next = queue;
|
||||
while ((peek = next.link) != null)
|
||||
next = peek;
|
||||
next.link = this;
|
||||
return queue;
|
||||
};
|
||||
|
||||
Packet.prototype.toString = function () {
|
||||
return "Packet";
|
||||
};
|
||||
|
||||
for (var i = 0; i < 350; ++i)
|
||||
runRichards();
|
|
@ -1,377 +0,0 @@
|
|||
// Copyright 2009 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This benchmark is based on a JavaScript log processing module used
|
||||
// by the V8 profiler to generate execution time profiles for runs of
|
||||
// JavaScript applications, and it effectively measures how fast the
|
||||
// JavaScript engine is at allocating nodes and reclaiming the memory
|
||||
// used for old nodes. Because of the way splay trees work, the engine
|
||||
// also has to deal with a lot of changes to the large tree object
|
||||
// graph.
|
||||
|
||||
// Configuration.
|
||||
var kSplayTreeSize = 8000;
|
||||
var kSplayTreeModifications = 80;
|
||||
var kSplayTreePayloadDepth = 5;
|
||||
|
||||
var splayTree = null;
|
||||
|
||||
|
||||
function GeneratePayloadTree(depth, key) {
|
||||
if (depth == 0) {
|
||||
return {
|
||||
array : [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
|
||||
string : 'String for key ' + key + ' in leaf node'
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
left: GeneratePayloadTree(depth - 1, key),
|
||||
right: GeneratePayloadTree(depth - 1, key)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function GenerateKey() {
|
||||
// The benchmark framework guarantees that Math.random is
|
||||
// deterministic; see base.js.
|
||||
return Math.random();
|
||||
}
|
||||
|
||||
|
||||
function InsertNewNode() {
|
||||
// Insert new node with a unique key.
|
||||
var key;
|
||||
do {
|
||||
key = GenerateKey();
|
||||
} while (splayTree.find(key) != null);
|
||||
splayTree.insert(key, GeneratePayloadTree(kSplayTreePayloadDepth, key));
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function SplaySetup() {
|
||||
splayTree = new SplayTree();
|
||||
for (var i = 0; i < kSplayTreeSize; i++) InsertNewNode();
|
||||
}
|
||||
|
||||
|
||||
function SplayTearDown() {
|
||||
// Allow the garbage collector to reclaim the memory
|
||||
// used by the splay tree no matter how we exit the
|
||||
// tear down function.
|
||||
var keys = splayTree.exportKeys();
|
||||
splayTree = null;
|
||||
|
||||
// Verify that the splay tree has the right size.
|
||||
var length = keys.length;
|
||||
if (length != kSplayTreeSize) {
|
||||
throw new Error("Splay tree has wrong size");
|
||||
}
|
||||
|
||||
// Verify that the splay tree has sorted, unique keys.
|
||||
for (var i = 0; i < length - 1; i++) {
|
||||
if (keys[i] >= keys[i + 1]) {
|
||||
throw new Error("Splay tree not sorted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function SplayRun() {
|
||||
// Replace a few nodes in the splay tree.
|
||||
for (var i = 0; i < kSplayTreeModifications; i++) {
|
||||
var key = InsertNewNode();
|
||||
var greatest = splayTree.findGreatestLessThan(key);
|
||||
if (greatest == null) splayTree.remove(key);
|
||||
else splayTree.remove(greatest.key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a Splay tree. A splay tree is a self-balancing binary
|
||||
* search tree with the additional property that recently accessed
|
||||
* elements are quick to access again. It performs basic operations
|
||||
* such as insertion, look-up and removal in O(log(n)) amortized time.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function SplayTree() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Pointer to the root node of the tree.
|
||||
*
|
||||
* @type {SplayTree.Node}
|
||||
* @private
|
||||
*/
|
||||
SplayTree.prototype.root_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether the tree is empty.
|
||||
*/
|
||||
SplayTree.prototype.isEmpty = function() {
|
||||
return !this.root_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Inserts a node into the tree with the specified key and value if
|
||||
* the tree does not already contain a node with the specified key. If
|
||||
* the value is inserted, it becomes the root of the tree.
|
||||
*
|
||||
* @param {number} key Key to insert into the tree.
|
||||
* @param {*} value Value to insert into the tree.
|
||||
*/
|
||||
SplayTree.prototype.insert = function(key, value) {
|
||||
if (this.isEmpty()) {
|
||||
this.root_ = new SplayTree.Node(key, value);
|
||||
return;
|
||||
}
|
||||
// Splay on the key to move the last node on the search path for
|
||||
// the key to the root of the tree.
|
||||
this.splay_(key);
|
||||
if (this.root_.key == key) {
|
||||
return;
|
||||
}
|
||||
var node = new SplayTree.Node(key, value);
|
||||
if (key > this.root_.key) {
|
||||
node.left = this.root_;
|
||||
node.right = this.root_.right;
|
||||
this.root_.right = null;
|
||||
} else {
|
||||
node.right = this.root_;
|
||||
node.left = this.root_.left;
|
||||
this.root_.left = null;
|
||||
}
|
||||
this.root_ = node;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes a node with the specified key from the tree if the tree
|
||||
* contains a node with this key. The removed node is returned. If the
|
||||
* key is not found, an exception is thrown.
|
||||
*
|
||||
* @param {number} key Key to find and remove from the tree.
|
||||
* @return {SplayTree.Node} The removed node.
|
||||
*/
|
||||
SplayTree.prototype.remove = function(key) {
|
||||
if (this.isEmpty()) {
|
||||
throw Error('Key not found: ' + key);
|
||||
}
|
||||
this.splay_(key);
|
||||
if (this.root_.key != key) {
|
||||
throw Error('Key not found: ' + key);
|
||||
}
|
||||
var removed = this.root_;
|
||||
if (!this.root_.left) {
|
||||
this.root_ = this.root_.right;
|
||||
} else {
|
||||
var right = this.root_.right;
|
||||
this.root_ = this.root_.left;
|
||||
// Splay to make sure that the new root has an empty right child.
|
||||
this.splay_(key);
|
||||
// Insert the original right child as the right child of the new
|
||||
// root.
|
||||
this.root_.right = right;
|
||||
}
|
||||
return removed;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the node having the specified key or null if the tree doesn't contain
|
||||
* a node with the specified key.
|
||||
*
|
||||
* @param {number} key Key to find in the tree.
|
||||
* @return {SplayTree.Node} Node having the specified key.
|
||||
*/
|
||||
SplayTree.prototype.find = function(key) {
|
||||
if (this.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
this.splay_(key);
|
||||
return this.root_.key == key ? this.root_ : null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {SplayTree.Node} Node having the maximum key value that
|
||||
* is less or equal to the specified key value.
|
||||
*/
|
||||
SplayTree.prototype.findGreatestLessThan = function(key) {
|
||||
if (this.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
// Splay on the key to move the node with the given key or the last
|
||||
// node on the search path to the top of the tree.
|
||||
this.splay_(key);
|
||||
// Now the result is either the root node or the greatest node in
|
||||
// the left subtree.
|
||||
if (this.root_.key <= key) {
|
||||
return this.root_;
|
||||
} else if (this.root_.left) {
|
||||
return this.findMax(this.root_.left);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Array<*>} An array containing all the keys of tree's nodes.
|
||||
*/
|
||||
SplayTree.prototype.exportKeys = function() {
|
||||
var result = [];
|
||||
if (!this.isEmpty()) {
|
||||
this.root_.traverse_(function(node) { result.push(node.key); });
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Perform the splay operation for the given key. Moves the node with
|
||||
* the given key to the top of the tree. If no node has the given
|
||||
* key, the last node on the search path is moved to the top of the
|
||||
* tree. This is the simplified top-down splaying algorithm from:
|
||||
* "Self-adjusting Binary Search Trees" by Sleator and Tarjan
|
||||
*
|
||||
* @param {number} key Key to splay the tree on.
|
||||
* @private
|
||||
*/
|
||||
SplayTree.prototype.splay_ = function(key) {
|
||||
if (this.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// Create a dummy node. The use of the dummy node is a bit
|
||||
// counter-intuitive: The right child of the dummy node will hold
|
||||
// the L tree of the algorithm. The left child of the dummy node
|
||||
// will hold the R tree of the algorithm. Using a dummy node, left
|
||||
// and right will always be nodes and we avoid special cases.
|
||||
var dummy, left, right;
|
||||
dummy = left = right = new SplayTree.Node(null, null);
|
||||
var current = this.root_;
|
||||
while (true) {
|
||||
if (key < current.key) {
|
||||
if (!current.left) {
|
||||
break;
|
||||
}
|
||||
if (key < current.left.key) {
|
||||
// Rotate right.
|
||||
var tmp = current.left;
|
||||
current.left = tmp.right;
|
||||
tmp.right = current;
|
||||
current = tmp;
|
||||
if (!current.left) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Link right.
|
||||
right.left = current;
|
||||
right = current;
|
||||
current = current.left;
|
||||
} else if (key > current.key) {
|
||||
if (!current.right) {
|
||||
break;
|
||||
}
|
||||
if (key > current.right.key) {
|
||||
// Rotate left.
|
||||
var tmp = current.right;
|
||||
current.right = tmp.left;
|
||||
tmp.left = current;
|
||||
current = tmp;
|
||||
if (!current.right) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Link left.
|
||||
left.right = current;
|
||||
left = current;
|
||||
current = current.right;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Assemble.
|
||||
left.right = current.left;
|
||||
right.left = current.right;
|
||||
current.left = dummy.right;
|
||||
current.right = dummy.left;
|
||||
this.root_ = current;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a Splay tree node.
|
||||
*
|
||||
* @param {number} key Key.
|
||||
* @param {*} value Value.
|
||||
*/
|
||||
SplayTree.Node = function(key, value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @type {SplayTree.Node}
|
||||
*/
|
||||
SplayTree.Node.prototype.left = null;
|
||||
|
||||
|
||||
/**
|
||||
* @type {SplayTree.Node}
|
||||
*/
|
||||
SplayTree.Node.prototype.right = null;
|
||||
|
||||
|
||||
/**
|
||||
* Performs an ordered traversal of the subtree starting at
|
||||
* this SplayTree.Node.
|
||||
*
|
||||
* @param {function(SplayTree.Node)} f Visitor function.
|
||||
* @private
|
||||
*/
|
||||
SplayTree.Node.prototype.traverse_ = function(f) {
|
||||
var current = this;
|
||||
while (current) {
|
||||
var left = current.left;
|
||||
if (left) left.traverse_(f);
|
||||
f(current);
|
||||
current = current.right;
|
||||
}
|
||||
};
|
||||
|
||||
SplaySetup();
|
||||
SplayRun();
|
||||
SplayTearDown();
|
|
@ -1,44 +0,0 @@
|
|||
Microsoft Public License (Ms-PL)
|
||||
|
||||
This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept
|
||||
the license, do not use the software.
|
||||
|
||||
1. Definitions
|
||||
|
||||
The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law.
|
||||
|
||||
A "contribution" is the original software, or any additions or changes to the software.
|
||||
|
||||
A "contributor" is any person that distributes its contribution under this license.
|
||||
|
||||
"Licensed patents" are a contributor's patent claims that read directly on its contribution.
|
||||
|
||||
2. Grant of Rights
|
||||
|
||||
(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each
|
||||
contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare
|
||||
derivative works of its contribution, and distribute its contribution or any derivative works that you create.
|
||||
|
||||
(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each
|
||||
contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell,
|
||||
offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in
|
||||
the software.
|
||||
|
||||
3. Conditions and Limitations
|
||||
|
||||
(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
|
||||
|
||||
(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent
|
||||
license from such contributor to the software ends automatically.
|
||||
|
||||
(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that
|
||||
are present in the software.
|
||||
|
||||
(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete
|
||||
copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may
|
||||
only do so under a license that complies with this license.
|
||||
|
||||
(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or
|
||||
conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted
|
||||
under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and
|
||||
non-infringement.
|
Двоичные данные
Src/Dependencies/Microsoft.Dynamic.dll
Двоичные данные
Src/Dependencies/Microsoft.Dynamic.dll
Двоичный файл не отображается.
Двоичные данные
Src/Dependencies/Microsoft.Dynamic.pdb
Двоичные данные
Src/Dependencies/Microsoft.Dynamic.pdb
Двоичный файл не отображается.
Двоичные данные
Src/Dependencies/Microsoft.Scripting.dll
Двоичные данные
Src/Dependencies/Microsoft.Scripting.dll
Двоичный файл не отображается.
Двоичные данные
Src/Dependencies/Microsoft.Scripting.pdb
Двоичные данные
Src/Dependencies/Microsoft.Scripting.pdb
Двоичный файл не отображается.
|
@ -1,16 +0,0 @@
|
|||
let typ = Et.GetDelegateType([| typeof<int>.MakeByRefType(); typeof<int> |])
|
||||
let prm = Dlr.Expr.param "~in" (typeof<int>.MakeByRefType())
|
||||
let lmb = Et.Lambda(typ, Dlr.Expr.block [
|
||||
Dlr.Expr.assign prm (Dlr.Expr.constant 4)
|
||||
], [prm])
|
||||
|
||||
let i = Dlr.Expr.param "~i" (typeof<int>)
|
||||
let outer = Dlr.Expr.lambdaWithLocals [] [i] [
|
||||
Dlr.Expr.assign i (Dlr.Expr.constant 1)
|
||||
Et.Invoke(lmb, i)
|
||||
i
|
||||
]
|
||||
|
||||
let cmp = outer.Compile()
|
||||
|
||||
cmp.DynamicInvoke()
|
|
@ -0,0 +1,313 @@
|
|||
namespace IronJS.Compiler
|
||||
|
||||
open System
|
||||
open IronJS
|
||||
open IronJS.Aliases
|
||||
open IronJS.Utils
|
||||
open IronJS.Compiler
|
||||
|
||||
module Binary =
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let binaryTempBlock (ctx:Ctx) (l:Dlr.Expr) (r:Dlr.Expr) f =
|
||||
let vars, exprs, inits =
|
||||
if Dlr.Ext.isStatic l then [], l, []
|
||||
else
|
||||
let var = Dlr.param "~l" l.Type
|
||||
[var], var :> Dlr.Expr, [Dlr.assign var l]
|
||||
|
||||
let vars, exprs, inits =
|
||||
if Dlr.Ext.isStatic r then vars, (exprs, r), inits
|
||||
else
|
||||
let var = Dlr.param "~r" r.Type
|
||||
var :: vars, (exprs, var :> Dlr.Expr), inits @ [Dlr.assign var r]
|
||||
|
||||
Dlr.block vars (inits @ f exprs)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let binaryMathTempBlock (ctx:Ctx) (l:Dlr.Expr) (r:Dlr.Expr) f =
|
||||
if Dlr.Ext.isStatic l && Dlr.Ext.isStatic r then
|
||||
f(l, r)
|
||||
|
||||
else
|
||||
let _l = Dlr.paramRef "l" l.Type
|
||||
let _r = Dlr.paramRef "r" r.Type
|
||||
|
||||
(Dlr.invoke
|
||||
(Dlr.lambdaAuto [_l; _r] (f(_l, _r)))
|
||||
[l; r]
|
||||
)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let bitwise_Box_Box op fallback (ctx:Ctx) l r =
|
||||
binaryTempBlock ctx l r (fun (l, r) ->
|
||||
[
|
||||
(Dlr.ternary
|
||||
(Dlr.and'
|
||||
(Expr.containsNumber l)
|
||||
(Expr.containsNumber r)
|
||||
)
|
||||
(Expr.returnBoxedNumber
|
||||
(ctx)
|
||||
(Dlr.castT<Number>
|
||||
(op
|
||||
(Dlr.castT<int> (Expr.unboxNumber l))
|
||||
(Dlr.castT<int> (Expr.unboxNumber r))
|
||||
)
|
||||
)
|
||||
)
|
||||
(ctx.Env_Boxed_Zero)
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let bitwise_Box_Number op fallback (ctx:Ctx) b n =
|
||||
binaryTempBlock ctx b n (fun (b, n) ->
|
||||
[
|
||||
(Dlr.ternary
|
||||
(Expr.containsNumber b)
|
||||
(Expr.returnBoxedNumber
|
||||
(ctx)
|
||||
(Dlr.castT<Number>
|
||||
(op
|
||||
(Dlr.castT<int> (Expr.unboxNumber b))
|
||||
(Dlr.castT<int> n)
|
||||
)
|
||||
)
|
||||
)
|
||||
(ctx.Env_Boxed_Zero)
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let bitwise_Number_Number op (ctx:Ctx) l r =
|
||||
binaryTempBlock ctx l r (fun (l, r) ->
|
||||
[
|
||||
(Dlr.castT<Number>
|
||||
(op
|
||||
(Dlr.castT<int> l)
|
||||
(Dlr.castT<int> r)
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let logical_Box_Number op fallback (ctx:Ctx) b n =
|
||||
binaryTempBlock ctx b n (fun (b, n) ->
|
||||
[
|
||||
(Dlr.ternary
|
||||
(Expr.containsNumber b)
|
||||
(op (Expr.unboxNumber b) n)
|
||||
(fallback (seq[|b; n|]))
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let logical_Number_Box op fallback (ctx:Ctx) n b =
|
||||
binaryTempBlock ctx n b (fun (n, b) ->
|
||||
[
|
||||
(Dlr.ternary
|
||||
(Expr.containsNumber b)
|
||||
(op n (Expr.unboxNumber b))
|
||||
(Dlr.false')
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let logical_Number_Number op (ctx:Ctx) l r =
|
||||
binaryTempBlock ctx l r (fun (l, r) -> [op l r])
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let logical_Box_Box op fallback ctx l r =
|
||||
binaryTempBlock ctx l r (fun (l, r) ->
|
||||
[
|
||||
(Dlr.ternary
|
||||
(Dlr.and'
|
||||
(Expr.containsNumber l)
|
||||
(Expr.containsNumber r)
|
||||
)
|
||||
(op (Expr.unboxNumber l) (Expr.unboxNumber r))
|
||||
(Dlr.false')
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let math_Number_Number op (ctx:Ctx) l r =
|
||||
binaryTempBlock ctx l r (fun (l, r) -> [op l r])
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let math_Number_Box op fallback (ctx:Ctx) n b =
|
||||
binaryTempBlock ctx n b (fun (n, b) ->
|
||||
[
|
||||
(Dlr.ternary
|
||||
(Expr.containsNumber b)
|
||||
(Expr.returnBoxedNumber
|
||||
(ctx)
|
||||
(op n (Expr.unboxNumber b))
|
||||
)
|
||||
(ctx.Env_Boxed_Zero)
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let math_Box_Number op fallback ctx b n =
|
||||
binaryTempBlock ctx b n (fun (b, n) ->
|
||||
[
|
||||
(Dlr.ternary
|
||||
(Expr.containsNumber b)
|
||||
(Expr.returnBoxedNumber
|
||||
(ctx)
|
||||
(op (Expr.unboxNumber b) n)
|
||||
)
|
||||
(ctx.Env_Boxed_Zero)
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let math_Box_Box op fallback ctx l r =
|
||||
binaryTempBlock ctx l r (fun (l, r) ->
|
||||
[
|
||||
(Dlr.ternary
|
||||
(Dlr.and'
|
||||
(Expr.containsNumber l)
|
||||
(Expr.containsNumber r)
|
||||
)
|
||||
(Expr.returnBoxedNumber
|
||||
(ctx)
|
||||
(op (Expr.unboxNumber l) (Expr.unboxNumber r))
|
||||
)
|
||||
(ctx.Env_Boxed_Zero)
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let dummyFallback _ = Dlr.void'
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//<
|
||||
let lt_Number_Number = logical_Number_Number Dlr.lt
|
||||
let lt_Box_Number = logical_Box_Number Dlr.lt Operators.ltExpr
|
||||
|
||||
//<=
|
||||
let ltEq_Number_Number = logical_Number_Number Dlr.ltEq
|
||||
let ltEq_Box_Number = logical_Box_Number Dlr.ltEq Operators.ltEqExpr
|
||||
let ltEq_Number_Box = logical_Number_Box Dlr.ltEq Operators.ltEqExpr
|
||||
let ltEq_Box_Box = logical_Box_Box Dlr.ltEq Operators.ltEqExpr
|
||||
|
||||
//>=
|
||||
let gtEq_Box_Box = logical_Box_Box Dlr.gtEq Operators.gtEqExpr
|
||||
let gtEq_Number_Number = logical_Number_Number Dlr.gtEq
|
||||
|
||||
//==
|
||||
let eq_Box_Number = logical_Box_Number Dlr.eq Operators.eqExpr
|
||||
let eq_Number_Number = logical_Number_Number Dlr.eq
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//+
|
||||
let add_Number_Box = math_Number_Box Dlr.add dummyFallback
|
||||
let add_Number_Number = math_Number_Number Dlr.add
|
||||
let add_Box_Number = math_Box_Number Dlr.add dummyFallback
|
||||
let add_Box_Box = math_Box_Box Dlr.add dummyFallback
|
||||
|
||||
//-
|
||||
let sub_Box_Number = math_Box_Number Dlr.sub dummyFallback
|
||||
let sub_Number_Number = math_Number_Number Dlr.sub
|
||||
|
||||
//*
|
||||
let mul_Number_Box = math_Number_Box Dlr.mul dummyFallback
|
||||
let mul_Number_Number = math_Number_Number Dlr.mul
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//|
|
||||
let bitAnd_Box_Box = bitwise_Box_Box Dlr.bAnd' dummyFallback
|
||||
let bitAnd_Number_Number = bitwise_Number_Number Dlr.bAnd'
|
||||
|
||||
//<<
|
||||
let bitShiftLeft_Box_Number = bitwise_Box_Number Dlr.lhs dummyFallback
|
||||
let bitShiftLeft_Number_Number = bitwise_Number_Number Dlr.lhs
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let private compilerMap =
|
||||
Map.ofList<Ast.BinaryOp * TypeCode * TypeCode, Ctx -> Dlr.Expr -> Dlr.Expr -> Dlr.Expr> [
|
||||
((Ast.BinaryOp.Lt, TypeCodes.Box, TypeCodes.Number), lt_Box_Number)
|
||||
((Ast.BinaryOp.Lt, TypeCodes.Number, TypeCodes.Number), lt_Number_Number)
|
||||
|
||||
((Ast.BinaryOp.LtEq, TypeCodes.Box, TypeCodes.Number), ltEq_Box_Number)
|
||||
((Ast.BinaryOp.LtEq, TypeCodes.Number, TypeCodes.Box), ltEq_Number_Box)
|
||||
((Ast.BinaryOp.LtEq, TypeCodes.Number, TypeCodes.Number), ltEq_Number_Number)
|
||||
((Ast.BinaryOp.LtEq, TypeCodes.Box, TypeCodes.Box), ltEq_Box_Box)
|
||||
|
||||
((Ast.BinaryOp.GtEq, TypeCodes.Box, TypeCodes.Box), gtEq_Box_Box)
|
||||
((Ast.BinaryOp.GtEq, TypeCodes.Number, TypeCodes.Number), gtEq_Number_Number)
|
||||
|
||||
((Ast.BinaryOp.Eq, TypeCodes.Box, TypeCodes.Number), eq_Box_Number)
|
||||
((Ast.BinaryOp.Eq, TypeCodes.Number, TypeCodes.Number), eq_Number_Number)
|
||||
|
||||
((Ast.BinaryOp.Add, TypeCodes.Number, TypeCodes.Box), add_Number_Box)
|
||||
((Ast.BinaryOp.Add, TypeCodes.Box, TypeCodes.Box), add_Box_Box)
|
||||
((Ast.BinaryOp.Add, TypeCodes.Box, TypeCodes.Number), add_Box_Number)
|
||||
((Ast.BinaryOp.Add, TypeCodes.Number, TypeCodes.Number), add_Number_Number)
|
||||
|
||||
((Ast.BinaryOp.Sub, TypeCodes.Box, TypeCodes.Number), sub_Box_Number)
|
||||
((Ast.BinaryOp.Sub, TypeCodes.Number, TypeCodes.Number), sub_Number_Number)
|
||||
|
||||
((Ast.BinaryOp.Mul, TypeCodes.Number, TypeCodes.Box), mul_Number_Box)
|
||||
((Ast.BinaryOp.Mul, TypeCodes.Number, TypeCodes.Number), mul_Number_Number)
|
||||
|
||||
((Ast.BinaryOp.BitAnd, TypeCodes.Box, TypeCodes.Box), bitAnd_Box_Box)
|
||||
((Ast.BinaryOp.BitAnd, TypeCodes.Number, TypeCodes.Number), bitAnd_Number_Number)
|
||||
|
||||
((Ast.BinaryOp.BitShiftLeft, TypeCodes.Box, TypeCodes.Number), bitShiftLeft_Box_Number)
|
||||
((Ast.BinaryOp.BitShiftLeft, TypeCodes.Number, TypeCodes.Number), bitShiftLeft_Number_Number)
|
||||
]
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
let compile ctx op lexpr rexpr =
|
||||
let ltc = Utils.expr2tc lexpr
|
||||
let rtc = Utils.expr2tc rexpr
|
||||
match compilerMap.TryFind (op, ltc, rtc) with
|
||||
| Some f -> f ctx lexpr rexpr
|
||||
| None -> failwithf "Failed to compile %A %i %i" op ltc rtc
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
let binaryMathTempStorageBlock (ctx:Ctx) (l:Dlr.Expr) (r:Dlr.Expr) f (s:Dlr.Expr) =
|
||||
if Dlr.Ext.isStatic l && Dlr.Ext.isStatic r then
|
||||
f(l, r, s)
|
||||
|
||||
else
|
||||
let _l = Dlr.paramRef "l" l.Type
|
||||
let _r = Dlr.paramRef "r" r.Type
|
||||
let _s = Dlr.paramRef "s" s.Type
|
||||
|
||||
(Dlr.invoke
|
||||
(Dlr.lambdaAuto [_l; _r; _s] (f(_l, _r, _s)))
|
||||
[l; r; s]
|
||||
)
|
||||
|
||||
let math_Box_Box_Store op ctx l r =
|
||||
binaryMathTempStorageBlock ctx l r (fun (l, r, s) ->
|
||||
(Dlr.ifElse
|
||||
(Dlr.and'
|
||||
(Expr.containsNumber l)
|
||||
(Expr.containsNumber r)
|
||||
)
|
||||
(Expr.assignValue
|
||||
(s)
|
||||
(op (Expr.unboxNumber l) (Expr.unboxNumber r))
|
||||
)
|
||||
(Dlr.void')
|
||||
)
|
||||
)
|
||||
|
||||
let compileAssign ctx lexpr rexpr =
|
||||
math_Box_Box_Store Dlr.add ctx lexpr rexpr
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
namespace IronJS.Compiler
|
||||
|
||||
open System
|
||||
open IronJS
|
||||
open IronJS.Aliases
|
||||
open IronJS.Utils
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Record representing a compilation target
|
||||
//------------------------------------------------------------------------------
|
||||
type TargetMode
|
||||
= Eval
|
||||
| Global
|
||||
| Function
|
||||
|
||||
type Target = {
|
||||
Ast: Ast.Tree
|
||||
TargetMode: TargetMode
|
||||
Delegate: HostType option
|
||||
Environment: IjsEnv
|
||||
} with
|
||||
member x.ParamTypes =
|
||||
match x.Delegate with
|
||||
| None -> [||]
|
||||
| Some delegate' ->
|
||||
Dlr.ArrayUtils.RemoveFirst(
|
||||
Dlr.ArrayUtils.RemoveFirst(
|
||||
Reflection.getDelegateArgTypes delegate'
|
||||
)
|
||||
)
|
||||
|
||||
member x.ParamType i = x.ParamTypes.[i]
|
||||
member x.ParamCount = x.ParamTypes.Length
|
||||
member x.IsFunction = x.TargetMode = TargetMode.Function
|
||||
member x.IsEval = x.TargetMode = TargetMode.Eval
|
||||
member x.IsGlobal = x.TargetMode = TargetMode.Global
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Class representing an eval operation
|
||||
//------------------------------------------------------------------------------
|
||||
type [<AllowNullLiteral>] EvalTarget() =
|
||||
[<DefaultValue>] val mutable Target : IjsBox
|
||||
[<DefaultValue>] val mutable GlobalLevel : int
|
||||
[<DefaultValue>] val mutable ClosureLevel : int
|
||||
[<DefaultValue>] val mutable LocalLevel: int
|
||||
[<DefaultValue>] val mutable Closures : Ast.Closure Set
|
||||
[<DefaultValue>] val mutable Function : IjsFunc
|
||||
[<DefaultValue>] val mutable This : IjsObj
|
||||
[<DefaultValue>] val mutable Local : Scope
|
||||
[<DefaultValue>] val mutable EvalScope : IjsObj
|
||||
[<DefaultValue>] val mutable ScopeChain : Scope
|
||||
[<DefaultValue>] val mutable DynamicChain : DynamicChain
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Record representing a compilation context
|
||||
//------------------------------------------------------------------------------
|
||||
type Context = {
|
||||
Target: Target
|
||||
ScopeChain: Ast.Scope list
|
||||
ReturnLabel: Dlr.Label
|
||||
InsideWith: bool
|
||||
|
||||
This: Dlr.Expr
|
||||
Function: Dlr.Expr
|
||||
LocalExpr: Dlr.Expr
|
||||
ChainExpr: Dlr.Expr
|
||||
DynamicExpr: Dlr.Expr
|
||||
|
||||
Break: Dlr.Label option
|
||||
Continue: Dlr.Label option
|
||||
BreakLabels: Map<string, Dlr.Label>
|
||||
ContinueLabels: Map<string, Dlr.Label>
|
||||
|
||||
ParameterExprs: Dlr.ExprParam array
|
||||
} with
|
||||
|
||||
member x.Env = Dlr.field x.Function "Env"
|
||||
member x.Env_Return = Dlr.field x.Env "Return"
|
||||
member x.Env_Object_prototype = Dlr.field x.Env "Object_prototype"
|
||||
member x.Env_Array_prototype = Dlr.field x.Env "Array_prototype"
|
||||
|
||||
member x.Env_Base_Class = Dlr.field x.Env "Base_Class"
|
||||
member x.Env_Function_Class = Dlr.field x.Env "Function_Class"
|
||||
member x.Env_Array_Class = Dlr.field x.Env "Array_Class"
|
||||
member x.Env_Prototype_Class = Dlr.field x.Env "Prototype_Class"
|
||||
|
||||
member x.Env_Boxed_Temp = Dlr.field x.Env "Boxed_Temp"
|
||||
member x.Env_Boxed_NegOne = Dlr.field x.Env "Boxed_NegOne"
|
||||
member x.Env_Boxed_Zero = Dlr.field x.Env "Boxed_Zero"
|
||||
member x.Env_Boxed_One = Dlr.field x.Env "Boxed_One"
|
||||
member x.Env_Boxed_Undefined = Dlr.field x.Env "Boxed_Undefined"
|
||||
member x.Env_Boxed_EmptyString = Dlr.field x.Env "Boxed_EmptyString"
|
||||
member x.Env_Boxed_False = Dlr.field x.Env "Boxed_False"
|
||||
member x.Env_Boxed_True = Dlr.field x.Env "Boxed_True"
|
||||
member x.Env_Boxed_Null = Dlr.field x.Env "Boxed_Null"
|
||||
|
||||
member x.Env_Temp_Bool = Dlr.field x.Env "Temp_Bool"
|
||||
member x.Env_Temp_Number = Dlr.field x.Env "Temp_Number"
|
||||
member x.Env_Temp_Clr = Dlr.field x.Env "Temp_Clr"
|
||||
member x.Env_Temp_String = Dlr.field x.Env "Temp_String"
|
||||
member x.Env_Temp_Object = Dlr.field x.Env "Temp_Object"
|
||||
member x.Env_Temp_Function = Dlr.field x.Env "Temp_Function"
|
||||
|
||||
member x.Fun_DynamicChain = Dlr.field x.Function "DynamicChain"
|
||||
member x.Fun_Chain = Dlr.field x.Function "ScopeChain"
|
||||
|
||||
member x.Globals = Dlr.Ext.static' (Dlr.field x.Env "Globals")
|
||||
member x.Scope = match x.ScopeChain with s::_ -> s | [] -> failwith "Que?"
|
||||
member x.WithScope s = {x with ScopeChain = s :: x.ScopeChain}
|
||||
member x.DynamicLookup = x.Scope.DynamicLookup || x.InsideWith
|
||||
member x.TopScope = x.ScopeChain.[x.ScopeChain.Length - 1]
|
||||
|
||||
member x.AddLoopLabels label break' continue' =
|
||||
let y = {x with Break=Some break'; Continue=Some continue'}
|
||||
match label with
|
||||
| None -> y
|
||||
| Some label ->
|
||||
{y with
|
||||
BreakLabels = y.BreakLabels.Add(label, break')
|
||||
ContinueLabels = y.ContinueLabels.Add(label, continue')
|
||||
}
|
||||
|
||||
member x.AddLabel label break' =
|
||||
{x with BreakLabels = x.BreakLabels.Add(label, break')}
|
||||
|
||||
type Ctx = Context
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
type IdentifierType
|
||||
= Global
|
||||
| Variable of Ast.Scope * Ast.Variable
|
||||
| Closure of Ast.Closure
|
|
@ -0,0 +1,37 @@
|
|||
namespace IronJS.Compiler
|
||||
|
||||
open IronJS
|
||||
open IronJS.Compiler
|
||||
|
||||
module ControlFlow =
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let loopLabels () =
|
||||
Dlr.labelBreak(), Dlr.labelContinue()
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let break' (ctx:Ctx) (label:string option) =
|
||||
match label with
|
||||
| None ->
|
||||
match ctx.Break with
|
||||
| None -> Errors.compiler "No unlabeled break target available"
|
||||
| Some label -> Dlr.break' label
|
||||
|
||||
| Some label ->
|
||||
match ctx.BreakLabels.TryFind label with
|
||||
| None -> Errors.compiler (sprintf "Missing label %s" label)
|
||||
| Some label -> Dlr.continue' label
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let continue' (ctx:Ctx) (label:string option) =
|
||||
match label with
|
||||
| None ->
|
||||
match ctx.Continue with
|
||||
| None -> Errors.compiler "No unlabeled continue target available"
|
||||
| Some label -> Dlr.continue' label
|
||||
|
||||
| Some label ->
|
||||
match ctx.ContinueLabels.TryFind label with
|
||||
| None -> Errors.compiler (sprintf "Missing label %s" label)
|
||||
| Some label -> Dlr.continue' label
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
namespace IronJS.Compiler
|
||||
|
||||
open System
|
||||
open IronJS
|
||||
open IronJS.Aliases
|
||||
open IronJS.Utils
|
||||
open IronJS.Compiler
|
||||
|
||||
module Convert =
|
||||
|
||||
let toBool (expr:Dlr.Expr) =
|
||||
match Utils.expr2tc expr with
|
||||
| TypeCodes.Bool -> expr
|
||||
| TypeCodes.Undefined -> Dlr.false'
|
||||
| TypeCodes.Object -> Dlr.true'
|
||||
| TypeCodes.Function -> Dlr.true'
|
||||
| TypeCodes.Clr -> Dlr.notEq expr (Dlr.null')
|
||||
| TypeCodes.String -> Dlr.gt (Dlr.property expr "Length") Dlr.int0
|
||||
| TypeCodes.Number ->
|
||||
Expr.blockTmpT<Number> expr (fun tmp ->
|
||||
[
|
||||
(Dlr.or'
|
||||
(Dlr.lt tmp Dlr.dbl0)
|
||||
(Dlr.gt tmp Dlr.dbl0)
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
| TypeCodes.Box ->
|
||||
let value = Dlr.paramRefT<Box> "ref"
|
||||
|
||||
(Dlr.invoke
|
||||
(Dlr.lambdaAuto
|
||||
[value]
|
||||
(Dlr.ternary
|
||||
(Expr.containsNumber value)
|
||||
(Dlr.or'
|
||||
(Dlr.lt
|
||||
(Expr.unboxNumber value)
|
||||
(Dlr.dbl0)
|
||||
)
|
||||
(Dlr.gt
|
||||
(Expr.unboxNumber value)
|
||||
(Dlr.dbl0)
|
||||
)
|
||||
)
|
||||
(Dlr.callStaticT<TypeConverter> "toBoolean" [value])
|
||||
)
|
||||
)
|
||||
[expr]
|
||||
)
|
||||
|
||||
| _ -> Errors.compiler "Invalid type"
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,559 @@
|
|||
namespace IronJS.Compiler
|
||||
|
||||
open System
|
||||
open IronJS
|
||||
open IronJS.Aliases
|
||||
open IronJS.Utils
|
||||
open IronJS.Compiler
|
||||
|
||||
type Compiler = Ctx -> Ast.Tree -> Dlr.Expr
|
||||
type OptionCompiler = Ctx -> Ast.Tree option -> Dlr.Expr option
|
||||
|
||||
module Core =
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Compiler functions
|
||||
let rec private compileAst (ctx:Context) tree =
|
||||
match tree with
|
||||
//Constants
|
||||
| Ast.Pass -> Dlr.void'
|
||||
| Ast.This -> ctx.This
|
||||
| Ast.Undefined -> Dlr.constant Expr.undefinedBoxed
|
||||
| Ast.String s -> Dlr.constant s
|
||||
| Ast.Number n -> Dlr.constant n
|
||||
| Ast.Boolean b -> Dlr.constant b
|
||||
|
||||
//Others
|
||||
| Ast.Identifier name -> Identifier.getValue ctx name
|
||||
| Ast.Block trees -> Dlr.blockSimple [for t in trees -> compileAst ctx t]
|
||||
| Ast.Assign(ltree, rtree) -> _compileAssign ctx ltree rtree
|
||||
| Ast.Eval tree -> _compileEval ctx tree
|
||||
| Ast.Unary(op, tree) -> _compileUnary ctx op tree
|
||||
| Ast.Binary(op, left, right) ->
|
||||
let lexpr = compileAst ctx left
|
||||
let rexpr = compileAst ctx right
|
||||
Binary.compile ctx op lexpr rexpr
|
||||
|
||||
//Scopes
|
||||
| Ast.LocalScope(scope, tree) -> compileLocalScope ctx scope tree
|
||||
| Ast.With(init, tree) -> _compileWith ctx init tree
|
||||
|
||||
//Objects
|
||||
| Ast.Object properties -> _compileObject ctx properties
|
||||
| Ast.Array indexes -> _compileArray ctx indexes
|
||||
| Ast.Index(tree, index) -> _compileIndexAccess ctx tree index
|
||||
| Ast.Property(tree, name) -> _compilePropertyAccess ctx tree name
|
||||
|
||||
//Functions
|
||||
| Ast.Invoke(func, args) -> _compileInvoke ctx func args
|
||||
| Ast.New(func, args) -> _compileNew ctx func args
|
||||
| Ast.Function(id, body) -> Function.create ctx compile id body
|
||||
| Ast.Return tree -> _compileReturn ctx tree
|
||||
|
||||
//Control Flow
|
||||
| Ast.If(test, ifTrue, ifFalse) -> _compileIf ctx test ifTrue ifFalse
|
||||
| Ast.While(label, test, body) -> _compileWhile ctx label test body
|
||||
| Ast.For(label, i, t, incr, b) -> _compileFor ctx label i t incr b
|
||||
| Ast.Break label -> ControlFlow.break' ctx label
|
||||
| Ast.Continue label -> ControlFlow.continue' ctx label
|
||||
| Ast.Label(label, tree) -> _compileLabel ctx label tree
|
||||
|
||||
//Exceptions
|
||||
| Ast.Try(body, catch, finally') -> _compileTry ctx body catch finally'
|
||||
| Ast.Throw tree -> Exception.throw (compileAst ctx tree)
|
||||
| Ast.Finally body -> Exception.finally' (compileAst ctx body)
|
||||
|
||||
| _ -> failwithf "Failed to compile %A" tree
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
and compileTreeOption ctx tree =
|
||||
match tree with
|
||||
| None -> None
|
||||
| Some t -> Some (compileAst ctx t)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
and compileTreeAsVoid ctx tree =
|
||||
Dlr.castVoid (compileAst ctx tree)
|
||||
|
||||
and _compileLabel (ctx:Ctx) label tree =
|
||||
let target = Dlr.labelVoid label
|
||||
let ctx = ctx.AddLabel label target
|
||||
Dlr.blockSimple [
|
||||
(compileAst ctx tree)
|
||||
(Dlr.labelExprVoid target)
|
||||
]
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
and _compileWhile ctx label test body =
|
||||
let break', continue' = ControlFlow.loopLabels()
|
||||
let test = Convert.toBool (compileAst ctx test)
|
||||
let body = compileAst (ctx.AddLoopLabels label break' continue') body
|
||||
Dlr.whileL test body break' continue'
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
and _compileFor ctx label init test incr body =
|
||||
let break', continue' = ControlFlow.loopLabels()
|
||||
let init = compileAst ctx init
|
||||
let test = compileAst ctx test
|
||||
let incr = compileAst ctx incr
|
||||
let body = compileAst (ctx.AddLoopLabels label break' continue') body
|
||||
Dlr.forL init test incr body break' continue'
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
and _compileIf ctx test ifTrue ifFalse =
|
||||
let test = Convert.toBool (compileAst ctx test)
|
||||
let ifTrue = Dlr.castVoid (compileAst ctx ifTrue)
|
||||
match compileTreeOption ctx ifFalse with
|
||||
| None -> Dlr.if' test ifTrue
|
||||
| Some ifFalse -> Dlr.ifElse test ifTrue ifFalse
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
and _compilePostInc ctx tree =
|
||||
match tree with
|
||||
| Ast.Identifier name ->
|
||||
Increment.postIncrementIdentifier ctx name
|
||||
|
||||
| Ast.Property(tree, name) ->
|
||||
let expr = compileAst ctx tree
|
||||
Increment.postIncrementProperty ctx expr name
|
||||
|
||||
| _ -> failwithf "Failed to compile PostInc for %A" tree
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
and _compileUnary ctx op tree =
|
||||
match op with
|
||||
| Ast.UnaryOp.Delete -> _compileDelete ctx tree
|
||||
| Ast.UnaryOp.TypeOf -> Unary.typeOf (compileAst ctx tree)
|
||||
| Ast.UnaryOp.Void ->
|
||||
|
||||
Dlr.blockSimple [
|
||||
(compileAst ctx tree)
|
||||
(Expr.undefined)
|
||||
]
|
||||
|
||||
| Ast.UnaryOp.PostInc -> _compilePostInc ctx tree
|
||||
| _ -> failwithf "Failed to compile %A" op
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
and _compileDelete ctx tree =
|
||||
match tree with
|
||||
| Ast.Identifier name ->
|
||||
Unary.deleteIdentifier ctx name
|
||||
|
||||
| Ast.Index(object', index) ->
|
||||
let index = _compileIndex ctx index
|
||||
let object' = compileAst ctx object'
|
||||
Unary.deleteIndex object' index
|
||||
|
||||
| Ast.Property(object', name) ->
|
||||
let object' = compileAst ctx object'
|
||||
Unary.deleteProperty object' name
|
||||
|
||||
| _ -> failwith "Que?"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
and _compileIndex ctx index =
|
||||
match index with
|
||||
| Ast.Number n ->
|
||||
if double (uint32 n) = n
|
||||
then Dlr.const' (uint32 n)
|
||||
else compileAst ctx index
|
||||
|
||||
| Ast.String s ->
|
||||
let mutable ui = 0u
|
||||
if Utils.isStringIndex(s, &ui)
|
||||
then Dlr.const' ui
|
||||
else compileAst ctx index
|
||||
|
||||
| _ -> compileAst ctx index
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
and _compileIndexAccess ctx tree index =
|
||||
let index = _compileIndex ctx index
|
||||
(Expr.testIsObject
|
||||
(compileAst ctx tree)
|
||||
(fun x -> Api.Expr.jsObjectGetIndex x index)
|
||||
(fun x -> Expr.undefinedBoxed)
|
||||
)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
and private _compileCatch ctx catch =
|
||||
match catch with
|
||||
| Ast.Catch(Ast.LocalScope(s, tree)) ->
|
||||
Exception.catch ctx s (compileAst (ctx.WithScope s) tree)
|
||||
|
||||
| Ast.Catch(tree) ->
|
||||
Exception.catchSimple (compileAst ctx tree)
|
||||
|
||||
| _ -> failwith "Que?"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
and private _compileTry ctx body catches finally' =
|
||||
(Exception.try'
|
||||
(compileTreeAsVoid ctx body)
|
||||
(seq{for x in catches -> _compileCatch ctx x})
|
||||
(compileTreeOption ctx finally')
|
||||
)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
and private _compileWith ctx init tree =
|
||||
let object' = Expr.unboxT<IjsObj> (compileAst ctx init)
|
||||
let tree = compileAst ({ctx with InsideWith=true}) tree
|
||||
Scope.initWith ctx object' tree
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
and private compileLocalScope ctx (s:Ast.Scope) tree =
|
||||
match s.ScopeType with
|
||||
| Ast.GlobalScope ->
|
||||
Scope.initGlobal ctx (compileAst (ctx.WithScope s) tree)
|
||||
|
||||
| Ast.FunctionScope ->
|
||||
let scopeInit = Scope.Function.initLocalScope ctx s.LocalCount
|
||||
let scopeChainInit = Scope.Function.initScopeChain ctx s.ClosedOverCount
|
||||
let dynamicChainInit = Scope.Function.initDynamicChain ctx s
|
||||
|
||||
let variables =
|
||||
(Scope.Function.demoteMissingParams
|
||||
(s.Variables)
|
||||
(s.ParamCount)
|
||||
(ctx.Target.ParamCount)
|
||||
) |> Scope.Function.resolveVariableTypes ctx
|
||||
|
||||
let initParams, initNonParams =
|
||||
Scope.Function.initVariables ctx variables
|
||||
|
||||
Seq.concat [
|
||||
[scopeInit; scopeChainInit; dynamicChainInit]
|
||||
(initParams |> List.ofSeq)
|
||||
(initNonParams |> List.ofSeq)
|
||||
[compileAst (ctx.WithScope {s with Variables=variables}) tree]
|
||||
] |> Dlr.blockSimple
|
||||
|
||||
| Ast.CatchScope ->
|
||||
Errors.compiler "Catch scopes should never reach this point"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Compiles a return statement, e.g: return 1;
|
||||
and private _compileReturn ctx tree =
|
||||
Dlr.blockSimple [
|
||||
(Expr.assignValue ctx.Env_Return (compileAst ctx tree))
|
||||
(Dlr.returnVoid ctx.ReturnLabel)
|
||||
]
|
||||
|
||||
and private _compileArray ctx indexes =
|
||||
let length = indexes.Length
|
||||
let args = [
|
||||
ctx.Env_Array_Class
|
||||
ctx.Env_Array_prototype
|
||||
Dlr.const' Classes.Array
|
||||
Dlr.const' (uint32 length)
|
||||
]
|
||||
|
||||
Dlr.blockTmpT<IjsObj> (fun tmp ->
|
||||
[
|
||||
(Dlr.assign tmp (Dlr.newArgsT<IjsObj> args))
|
||||
(List.mapi (fun i t ->
|
||||
(Expr.assignValue
|
||||
(Dlr.indexInt (Dlr.field tmp "IndexValues") i)
|
||||
(compileAst ctx t)
|
||||
)
|
||||
) indexes) |> Dlr.blockSimple
|
||||
(Expr.assignValue
|
||||
(Expr.propertyValue tmp Dlr.int0)
|
||||
(Dlr.const' (double length))
|
||||
)
|
||||
(tmp :> Dlr.Expr)
|
||||
] |> Seq.ofList
|
||||
)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// {foo: 12}
|
||||
and private _compileObject ctx properties =
|
||||
//Compute property class
|
||||
let pc =
|
||||
Seq.fold (fun s init ->
|
||||
match init with
|
||||
| Ast.Assign(Ast.String name, _) ->
|
||||
Api.PropertyClass.subClass(s, name)
|
||||
|
||||
| _ -> Errors.compiler "_compileNew:0"
|
||||
|
||||
) ctx.Target.Environment.Base_Class properties
|
||||
|
||||
//New object
|
||||
let newArgs = [
|
||||
Dlr.const' pc;
|
||||
ctx.Env_Object_prototype;
|
||||
Dlr.const' Classes.Object;
|
||||
Dlr.const' 0u
|
||||
]
|
||||
|
||||
let newExpr = Dlr.newArgsT<IjsObj> newArgs
|
||||
|
||||
//Set properties
|
||||
Dlr.blockTmpT<IjsObj> (fun tmp ->
|
||||
let initExprs =
|
||||
List.fold (fun s init ->
|
||||
match init with
|
||||
| Ast.Assign(Ast.String name, expr) ->
|
||||
(Expr.assignValue
|
||||
(Expr.propertyValue
|
||||
(tmp)
|
||||
(Dlr.const' (Api.PropertyClass.getIndex(pc, name)))
|
||||
)
|
||||
(compileAst ctx expr)
|
||||
) :: s
|
||||
|
||||
| _ -> failwith "Que?"
|
||||
|
||||
) [tmp] properties
|
||||
|
||||
(Dlr.assign tmp newExpr :: initExprs) |> Seq.ofList
|
||||
)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// foo.bar;
|
||||
and private _compilePropertyAccess ctx tree name =
|
||||
(Expr.testIsObject
|
||||
(compileAst ctx tree)
|
||||
(fun x -> Api.Expr.jsObjectGetProperty x name)
|
||||
(fun x -> Expr.undefinedBoxed)
|
||||
)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//var foo = new Foo(arg1, arg2, [arg3, ...]);
|
||||
and private _compileNew ctx func args =
|
||||
let args = [for a in args -> compileAst ctx a]
|
||||
let func = compileAst ctx func
|
||||
|
||||
(Expr.testIsFunction
|
||||
(func)
|
||||
(fun f ->
|
||||
(Dlr.ternary
|
||||
(Expr.isConstructor f)
|
||||
(Dlr.blockTmpT<IjsObj> (fun obj ->
|
||||
[
|
||||
(Dlr.assign obj (_compileObject ctx []))
|
||||
(Dlr.assign
|
||||
(Expr.constructorMode f)
|
||||
(Dlr.const' ConstructorModes.CalledAsConstructor)
|
||||
)
|
||||
(Api.Expr.jsFunctionInvoke f obj args)
|
||||
(Dlr.assign
|
||||
(Expr.constructorMode f)
|
||||
(Dlr.const' ConstructorModes.Constructor)
|
||||
)
|
||||
(Dlr.assign
|
||||
(Expr.prototype obj)
|
||||
(Dlr.ternary
|
||||
(Expr.testBoxType
|
||||
(Expr.propertyValue f Dlr.int1)
|
||||
(TypeCodes.Object)
|
||||
)
|
||||
(Expr.unboxObject (Expr.propertyValue f Dlr.int1))
|
||||
(ctx.Env_Object_prototype)
|
||||
)
|
||||
)
|
||||
(obj :> Dlr.Expr)
|
||||
] |> Seq.ofList
|
||||
))
|
||||
(Dlr.defaultT<IjsObj>)
|
||||
)
|
||||
)
|
||||
(fun _ -> Dlr.defaultT<IjsObj>)
|
||||
)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// foo(arg1, arg2, [arg3, ...]);
|
||||
and private _compileInvoke ctx tree argTrees =
|
||||
let args = [for tree in argTrees -> compileAst ctx tree]
|
||||
let temps, args, assigns = Function.createTempVars args
|
||||
|
||||
let invokeExpr =
|
||||
//foo(arg1, arg2, [arg3, ...])
|
||||
match tree with
|
||||
| Ast.Identifier(name) ->
|
||||
Function.invokeIdentifier ctx name args
|
||||
|
||||
//bar.foo(arg1, arg2, [arg3, ...])
|
||||
| Ast.Property(tree, name) ->
|
||||
let object' = compileAst ctx tree
|
||||
Function.invokeProperty ctx object' name args
|
||||
|
||||
//bar["foo"](arg1, arg2, [arg3, ...])
|
||||
| Ast.Index(tree, index) ->
|
||||
let object' = compileAst ctx tree
|
||||
let index = compileAst ctx index
|
||||
Function.invokeIndex ctx object' index args
|
||||
|
||||
| _ -> failwith "Que?"
|
||||
|
||||
Dlr.block temps (assigns @ [invokeExpr])
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Compiles an assignment operation, e.g: foo = 1; or foo.bar = 1;
|
||||
and private _compileAssign (ctx:Context) ltree rtree =
|
||||
let value = compileAst ctx rtree
|
||||
match ltree with
|
||||
| Ast.Identifier(name) -> //Variable assignment: foo = 1;
|
||||
Identifier.setValue ctx name value
|
||||
|
||||
| Ast.Property(tree, name) -> //Property assignment: foo.bar = 1;
|
||||
Expr.blockTmp value (fun value ->
|
||||
[
|
||||
(Expr.testIsObject
|
||||
(compileAst ctx tree)
|
||||
(fun x -> Api.Expr.jsObjectPutProperty x name value)
|
||||
(fun x -> value)
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
| Ast.Index(tree, index) -> //Index assignemnt: foo[0] = "bar";
|
||||
let index = _compileIndex ctx index
|
||||
Expr.blockTmp value (fun value ->
|
||||
[
|
||||
(Expr.testIsObject
|
||||
(compileAst ctx tree)
|
||||
(fun x -> Api.Expr.jsObjectPutIndex x index value)
|
||||
(fun x -> value)
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
| _ -> failwithf "Failed to compile assign for: %A" ltree
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Compiles a call to eval, e.g: eval('foo = 1');
|
||||
and private _compileEval (ctx:Context) evalTree =
|
||||
|
||||
let eval = Dlr.paramT<IjsBox> "eval"
|
||||
let target = Dlr.paramT<EvalTarget> "target"
|
||||
|
||||
Dlr.block [eval; target] [
|
||||
(Dlr.assign eval (Api.Expr.jsObjectGetProperty ctx.Globals "eval"))
|
||||
(Dlr.assign target Dlr.newT<EvalTarget>)
|
||||
|
||||
(Expr.assignValue (Dlr.field target "Target") (compileAst ctx evalTree))
|
||||
(Expr.assignValue
|
||||
(Dlr.field target "GlobalLevel") (Dlr.const' ctx.Scope.GlobalLevel)
|
||||
)
|
||||
(Expr.assignValue
|
||||
(Dlr.field target "ClosureLevel") (Dlr.const' ctx.Scope.ClosureLevel)
|
||||
)
|
||||
(Expr.assignValue
|
||||
(Dlr.field target "LocalLevel") (Dlr.const' ctx.Scope.LocalLevel)
|
||||
)
|
||||
(Expr.assignValue
|
||||
(Dlr.field target "Closures") (Dlr.const' ctx.Scope.Closures)
|
||||
)
|
||||
|
||||
(Expr.assignValue (Dlr.field target "Function") ctx.Function)
|
||||
(Expr.assignValue (Dlr.field target "This") ctx.This)
|
||||
(Expr.assignValue (Dlr.field target "Local") ctx.LocalExpr)
|
||||
(Expr.assignValue (Dlr.field target "ScopeChain") ctx.ChainExpr)
|
||||
(Expr.assignValue (Dlr.field target "DynamicChain") ctx.DynamicExpr)
|
||||
|
||||
(Expr.testIsFunction
|
||||
(eval)
|
||||
(fun x -> Api.Expr.jsFunctionInvoke x ctx.This [target])
|
||||
(fun x -> ctx.Env_Boxed_Undefined)
|
||||
)
|
||||
]
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Main compiler function that setups compilation and invokes compileAst
|
||||
and compile (target:Target) =
|
||||
|
||||
//Parameter variables
|
||||
let parameterExprs =
|
||||
target.ParamTypes
|
||||
|> Seq.mapi (fun i type' -> Dlr.param (sprintf "param%i" i) type')
|
||||
|> Seq.toArray
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Main Context
|
||||
let ctx = {
|
||||
Target = target
|
||||
InsideWith = false
|
||||
ScopeChain = List.empty
|
||||
ReturnLabel = Dlr.labelVoid "~return"
|
||||
|
||||
Break = None
|
||||
Continue = None
|
||||
BreakLabels = Map.empty
|
||||
ContinueLabels = Map.empty
|
||||
|
||||
Function = Dlr.paramT<IjsFunc> "~function"
|
||||
This = Dlr.paramT<IjsObj> "~this"
|
||||
LocalExpr = Dlr.paramT<Scope> "~locals"
|
||||
ChainExpr = Dlr.paramT<Scope> "~chain"
|
||||
DynamicExpr = Dlr.paramT<DynamicChain> "~dynamic"
|
||||
ParameterExprs = parameterExprs
|
||||
}
|
||||
|
||||
let finalizers =
|
||||
Dlr.blockSimple [
|
||||
#if REUSABLE_STACK
|
||||
(Dlr.if'
|
||||
(Dlr.isNull ctx.Fun_LocalStack)
|
||||
(Dlr.assign ctx.Fun_LocalStack ctx.LocalExpr)
|
||||
)
|
||||
#endif
|
||||
]
|
||||
|
||||
let returnExpr = [
|
||||
(Dlr.labelExprVoid ctx.ReturnLabel)
|
||||
(finalizers)
|
||||
(ctx.Env_Return)
|
||||
]
|
||||
|
||||
let locals =
|
||||
if ctx.Target.IsEval then [] |> Seq.ofList
|
||||
else
|
||||
[ ctx.LocalExpr; ctx.ChainExpr; ctx.DynamicExpr;
|
||||
] |> Seq.cast<Dlr.ExprParam>
|
||||
|
||||
//Main function body
|
||||
let functionBody =
|
||||
(if ctx.Target.IsFunction then returnExpr else [])
|
||||
|> Seq.append [compileAst ctx target.Ast]
|
||||
|> Dlr.block locals
|
||||
|
||||
let allParameters =
|
||||
(
|
||||
if ctx.Target.IsEval then
|
||||
[ ctx.Function; ctx.This; ctx.LocalExpr;
|
||||
ctx.ChainExpr; ctx.DynamicExpr
|
||||
] |> Seq.cast<Dlr.ExprParam>
|
||||
else
|
||||
ctx.ParameterExprs
|
||||
|> Seq.cast<Dlr.ExprParam>
|
||||
|> Seq.append (Seq.cast<Dlr.ExprParam> [ctx.Function; ctx.This])
|
||||
|
||||
) |> Array.ofSeq
|
||||
|
||||
|
||||
let lambda =
|
||||
match target.Delegate with
|
||||
| Some d -> Dlr.lambda d allParameters functionBody
|
||||
| _ -> Dlr.lambdaAuto allParameters functionBody
|
||||
|
||||
#if INTERACTIVE
|
||||
Dlr.Utils.printDebugView lambda
|
||||
#else
|
||||
#if DEBUG
|
||||
Dlr.Utils.printDebugView lambda
|
||||
#endif
|
||||
#endif
|
||||
|
||||
lambda.Compile()
|
||||
|
||||
let compileAsGlobal env tree =
|
||||
compile {
|
||||
TargetMode = TargetMode.Global
|
||||
Ast = tree
|
||||
Delegate = None
|
||||
Environment = env
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
namespace IronJS.Compiler
|
||||
|
||||
open IronJS
|
||||
open IronJS.Compiler
|
||||
|
||||
module Exception =
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let throw expr =
|
||||
Dlr.throwT<UserError> [Expr.boxValue expr]
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let finally' expr =
|
||||
Dlr.castVoid expr
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let try' body catches finally' =
|
||||
match finally' with
|
||||
| None -> Dlr.tryCatch body catches
|
||||
| Some finally' -> Dlr.tryCatchFinally body catches finally'
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let catchSimple bodyExpr =
|
||||
Dlr.catchT<UserError> (Dlr.castVoid bodyExpr)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let private _pushClosedOverCatch ctx tmp =
|
||||
Dlr.blockSimple [
|
||||
(Dlr.assign
|
||||
(Dlr.field (Dlr.index0 tmp) "Scope")
|
||||
(ctx.ChainExpr)
|
||||
)
|
||||
(Dlr.assign ctx.ChainExpr tmp)
|
||||
]
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let private _pushLocalCatch ctx tmp =
|
||||
Dlr.blockSimple [
|
||||
(Dlr.assign
|
||||
(Dlr.field (Dlr.index0 tmp) "Scope")
|
||||
(ctx.LocalExpr)
|
||||
)
|
||||
(Dlr.assign ctx.LocalExpr tmp)
|
||||
]
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let private _popClosedOverCatch ctx =
|
||||
(Dlr.assign
|
||||
(ctx.ChainExpr)
|
||||
(Dlr.field (Dlr.index0 ctx.ChainExpr) "Scope")
|
||||
)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let private _popLocalCatch ctx =
|
||||
(Dlr.assign
|
||||
(ctx.LocalExpr)
|
||||
(Dlr.field (Dlr.index0 ctx.LocalExpr) "Scope")
|
||||
)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let catch ctx (scope:Ast.Scope) bodyExpr =
|
||||
let var = Utils.Seq.first scope.Variables
|
||||
let tmp = Dlr.paramT<Scope> "~newScope"
|
||||
let param = Dlr.paramT<UserError> "~ex"
|
||||
|
||||
let pushScope =
|
||||
Dlr.blockTmpT<Scope> (fun tmp ->
|
||||
[
|
||||
(Dlr.assign tmp (Dlr.newArrayBoundsT<Box> Dlr.int2))
|
||||
(Dlr.assign (Dlr.index1 tmp) (Expr.errorValue param))
|
||||
(if var.IsClosedOver
|
||||
then _pushClosedOverCatch ctx tmp
|
||||
else _pushLocalCatch ctx tmp
|
||||
)
|
||||
] |> Seq.ofList
|
||||
)
|
||||
|
||||
let popScope =
|
||||
if var.IsClosedOver
|
||||
then _popClosedOverCatch ctx
|
||||
else _popLocalCatch ctx
|
||||
|
||||
Dlr.catchVar param (
|
||||
Dlr.blockSimple [
|
||||
(pushScope)
|
||||
(bodyExpr)
|
||||
(popScope)
|
||||
(Dlr.void')
|
||||
]
|
||||
)
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
namespace IronJS.Compiler
|
||||
|
||||
open System
|
||||
open IronJS
|
||||
open IronJS.Aliases
|
||||
open IronJS.Utils
|
||||
open IronJS.Compiler
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Utility functions for compiling IronJS ast trees
|
||||
module Expr =
|
||||
|
||||
let returnBoxedBool (ctx:Ctx) boolExpr =
|
||||
Dlr.blockSimple [
|
||||
(Dlr.assign (Expr.unboxBool ctx.Env_Temp_Bool) boolExpr)
|
||||
(ctx.Env_Temp_Bool)
|
||||
]
|
||||
|
||||
let returnBoxedNumber (ctx:Ctx) number =
|
||||
Dlr.blockTmpT<Box> (fun tmp ->
|
||||
[
|
||||
(Expr.setBoxType tmp TypeCodes.Number)
|
||||
(Expr.setBoxValue tmp number)
|
||||
(tmp :> Dlr.Expr)
|
||||
] |> Seq.ofList
|
||||
)
|
||||
(*
|
||||
Dlr.blockSimple [
|
||||
(Dlr.assign (Expr.unboxNumber ctx.Env_Temp_Number) number)
|
||||
(ctx.Env_Temp_Number)
|
||||
]
|
||||
*)
|
||||
|
||||
let returnBoxedClr (ctx:Ctx) clr =
|
||||
Dlr.blockSimple [
|
||||
(Dlr.assign (Expr.unboxClr ctx.Env_Temp_Clr) clr)
|
||||
(ctx.Env_Temp_Clr)
|
||||
]
|
||||
|
||||
let returnBoxedString (ctx:Ctx) str =
|
||||
Dlr.blockSimple [
|
||||
(Dlr.assign (Expr.unboxString ctx.Env_Temp_String) str)
|
||||
(ctx.Env_Temp_String)
|
||||
]
|
||||
|
||||
let returnBoxedObject (ctx:Ctx) object' =
|
||||
Dlr.blockSimple [
|
||||
(Dlr.assign (Expr.unboxObject ctx.Env_Temp_Object) object')
|
||||
(ctx.Env_Temp_Object)
|
||||
]
|
||||
|
||||
let returnBoxedFunction (ctx:Ctx) function' =
|
||||
Dlr.blockSimple [
|
||||
(Dlr.assign (Expr.unboxObject ctx.Env_Temp_Function) function')
|
||||
(ctx.Env_Temp_Function)
|
||||
]
|
|
@ -0,0 +1,133 @@
|
|||
namespace IronJS.Compiler
|
||||
|
||||
open System
|
||||
open IronJS
|
||||
open IronJS.Compiler
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
module Function =
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let applyCompiler (compiler:Target -> Delegate) target (_:IjsFunc) delegateType =
|
||||
compiler {target with Delegate = Some delegateType}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let makeCompiler ctx compiler tree =
|
||||
let target = {
|
||||
Ast = tree
|
||||
TargetMode = TargetMode.Function
|
||||
Delegate = None
|
||||
Environment = ctx.Target.Environment
|
||||
}
|
||||
|
||||
applyCompiler compiler target
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let scopeLocalSize tree =
|
||||
match tree with
|
||||
| Ast.LocalScope(scope, _) -> scope.LocalCount
|
||||
| _ -> failwith "Que?"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let scopeParamCount tree =
|
||||
match tree with
|
||||
| Ast.LocalScope(scope, _) -> scope.ParamCount
|
||||
| _ -> failwith "Que?"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let create ctx compiler id tree =
|
||||
//Make sure a compiler exists for this function
|
||||
if not (Api.Environment.hasCompiler (ctx.Target.Environment, id)) then
|
||||
Api.Environment.addCompiler(
|
||||
ctx.Target.Environment, id, makeCompiler ctx compiler tree
|
||||
)
|
||||
|
||||
let argCount =
|
||||
Dlr.const' (double (scopeParamCount tree))
|
||||
|
||||
let funcArgs = [
|
||||
(ctx.Env)
|
||||
(Dlr.const' id)
|
||||
(ctx.ChainExpr)
|
||||
(ctx.DynamicExpr)
|
||||
]
|
||||
|
||||
let prototypeArgs = [
|
||||
ctx.Env_Prototype_Class;
|
||||
ctx.Env_Object_prototype;
|
||||
Dlr.const' Classes.Object;
|
||||
Dlr.const' 0u
|
||||
]
|
||||
|
||||
let func = Dlr.paramT<IjsFunc> "function"
|
||||
let prototype = Dlr.paramT<IjsObj> "prototype"
|
||||
|
||||
Dlr.block [func; prototype] [
|
||||
(Dlr.assign func (Dlr.newArgsT<IjsFunc> funcArgs))
|
||||
(Dlr.assign prototype (Dlr.newArgsT<IjsObj> prototypeArgs))
|
||||
(Expr.assignValue (Expr.propertyValue prototype Dlr.int0) func)
|
||||
(Expr.assignValue (Expr.propertyValue func Dlr.int0) argCount)
|
||||
(Expr.assignValue (Expr.propertyValue func Dlr.int1) prototype)
|
||||
(func)
|
||||
]
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let invokeIdentifierDynamic (ctx:Ctx) name args =
|
||||
let argsArray = Dlr.newArrayItemsT<obj> [for a in args -> Dlr.castT<obj> a]
|
||||
let typeArgs = Utils.addInternalArgs [for a in args -> a.Type]
|
||||
let delegateType = Utils.createDelegate typeArgs
|
||||
let dynamicArgs = Identifier.getDynamicArgs ctx name
|
||||
let defaultArgs = [Dlr.const' name; argsArray; ctx.DynamicExpr]
|
||||
(Dlr.callStaticGenericT<Helpers.ScopeHelpers>
|
||||
"DynamicCall" [delegateType] (defaultArgs @ dynamicArgs)
|
||||
)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let invokeIdentifier (ctx:Ctx) name args =
|
||||
if ctx.DynamicLookup then invokeIdentifierDynamic ctx name args
|
||||
else
|
||||
(Expr.testIsFunction
|
||||
(Identifier.getValue ctx name)
|
||||
(fun x -> Api.Expr.jsFunctionInvoke x ctx.Globals args)
|
||||
(fun x -> Expr.undefinedBoxed)
|
||||
)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let invokeProperty (ctx:Ctx) object' name args =
|
||||
(Expr.testIsObject
|
||||
(object')
|
||||
(fun x ->
|
||||
(Api.Expr.jsMethodInvoke
|
||||
(x)
|
||||
(fun x -> Api.Expr.jsObjectGetProperty x name)
|
||||
(args)
|
||||
)
|
||||
)
|
||||
(fun x -> Expr.undefinedBoxed)
|
||||
)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let invokeIndex (ctx:Ctx) object' index args =
|
||||
(Expr.testIsObject
|
||||
(object')
|
||||
(fun x ->
|
||||
(Api.Expr.jsMethodInvoke
|
||||
(x)
|
||||
(fun x -> Api.Expr.jsObjectGetIndex x index)
|
||||
(args)
|
||||
)
|
||||
)
|
||||
(fun x -> Expr.undefinedBoxed)
|
||||
)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let createTempVars args =
|
||||
List.foldBack (fun a (temps, args:Dlr.Expr list, ass) ->
|
||||
|
||||
if Dlr.Ext.isStatic a then (temps, a :: args, ass)
|
||||
else
|
||||
let tmp = Dlr.param (Dlr.tmpName()) a.Type
|
||||
let assign = Dlr.assign tmp a
|
||||
(tmp :: temps, tmp :> Dlr.Expr :: args, assign :: ass)
|
||||
|
||||
) args ([], [], [])
|
|
@ -0,0 +1,120 @@
|
|||
namespace IronJS.Compiler
|
||||
|
||||
open IronJS
|
||||
open IronJS.Compiler
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
module Identifier =
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let private walkScopeChain expr target current =
|
||||
let rec walk expr times =
|
||||
if times = 0
|
||||
then expr
|
||||
else walk (Dlr.field (Dlr.index0 expr) "Scope") (times-1)
|
||||
|
||||
walk expr (current - target)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let getData (ctx:Ctx) name =
|
||||
match Seq.tryFind (Ast.hasVar name) ctx.ScopeChain with
|
||||
| Some scope -> Variable(scope, Ast.getVar name scope)
|
||||
| None ->
|
||||
match Seq.tryFind (Ast.hasCls name) ctx.ScopeChain with
|
||||
| None -> Global
|
||||
| Some scope -> Closure(Ast.getCls name scope)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let clsExprAndIndex ctx (cls:Ast.Closure) =
|
||||
let expr =
|
||||
(walkScopeChain
|
||||
(ctx.ChainExpr)
|
||||
(cls.ClosureLevel)
|
||||
(ctx.Scope.ClosureLevel)
|
||||
)
|
||||
|
||||
Some(expr, cls.Index, cls.GlobalLevel, None)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let varExprAndIndex ctx (scope:Ast.Scope) (var:Ast.Variable) =
|
||||
let expr =
|
||||
if var.IsClosedOver then
|
||||
(walkScopeChain
|
||||
(ctx.ChainExpr)
|
||||
(scope.ClosureLevel)
|
||||
(ctx.Scope.ClosureLevel)
|
||||
)
|
||||
else
|
||||
(walkScopeChain
|
||||
(ctx.LocalExpr)
|
||||
(scope.LocalLevel)
|
||||
(ctx.Scope.LocalLevel)
|
||||
)
|
||||
|
||||
Some(expr, var.Index, scope.GlobalLevel, var.Type)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let isGlobal ctx name =
|
||||
getData ctx name = Global
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let getExprIndexLevelType ctx name =
|
||||
match getData ctx name with
|
||||
| Global -> None
|
||||
| Variable(scope, var) -> varExprAndIndex ctx scope var
|
||||
| Closure cls -> clsExprAndIndex ctx cls
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let dynamicGetGlobalArgs (ctx:Ctx) name =
|
||||
[Dlr.neg1; ctx.Globals; Dlr.defaultT<Scope>; Dlr.neg1]
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let dynamicGetVariableArgs (ctx:Ctx) expr (name:string) (i:int) (l:int) =
|
||||
[Dlr.const' l; ctx.Globals; expr; Dlr.const' i]
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let getDynamicArgs (ctx:Ctx) name =
|
||||
match getExprIndexLevelType ctx name with
|
||||
| None -> dynamicGetGlobalArgs ctx name
|
||||
| Some(expr, i, l, _) -> dynamicGetVariableArgs ctx expr name i l
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let getValueDynamic (ctx:Ctx) name =
|
||||
let defaultArgs = [Dlr.const' name; ctx.DynamicExpr]
|
||||
let dynamicArgs = getDynamicArgs ctx name
|
||||
let args = defaultArgs @ dynamicArgs
|
||||
Dlr.callStaticT<Helpers.ScopeHelpers> "DynamicGet" (args)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let setValueDynamic (ctx:Ctx) name value =
|
||||
let defaultArgs = [Dlr.const' name; Expr.boxValue value; ctx.DynamicExpr]
|
||||
let dynamicArgs = getDynamicArgs ctx name
|
||||
let args = defaultArgs @ dynamicArgs
|
||||
Dlr.callStaticT<Helpers.ScopeHelpers> "DynamicSet" (args)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let getValue (ctx:Ctx) name =
|
||||
match ctx.DynamicLookup with
|
||||
| true -> getValueDynamic ctx name
|
||||
| _ ->
|
||||
match ctx.Scope.ScopeType with
|
||||
| Ast.GlobalScope -> Api.Expr.jsObjectGetProperty ctx.Globals name
|
||||
| _ ->
|
||||
match getExprIndexLevelType ctx name with
|
||||
| None -> Api.Expr.jsObjectGetProperty ctx.Globals name
|
||||
| Some(expr, i, _, tc) -> Dlr.Ext.static' (Expr.unboxIndex expr i tc)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let setValue (ctx:Ctx) name value =
|
||||
match ctx.DynamicLookup with
|
||||
| true -> setValueDynamic ctx name value
|
||||
| _ ->
|
||||
match getExprIndexLevelType ctx name with
|
||||
| None ->
|
||||
Expr.blockTmp value (fun value ->
|
||||
[Api.Expr.jsObjectPutProperty ctx.Globals name value]
|
||||
)
|
||||
|
||||
| Some(expr, i, _, tc) ->
|
||||
let varExpr = Expr.unboxIndex expr i tc
|
||||
Expr.assignValue (Dlr.Ext.static' varExpr) value
|
|
@ -0,0 +1,89 @@
|
|||
namespace IronJS.Compiler
|
||||
|
||||
open IronJS
|
||||
open IronJS.Compiler
|
||||
|
||||
module Increment =
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
type ChangeVariable =
|
||||
Ctx -> Dlr.Expr -> TypeCode option -> Dlr.Expr
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
type ChangeProperty =
|
||||
Ctx -> Dlr.Expr -> string -> Dlr.Expr
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let postChangeVariable op (ctx:Ctx) expr tc =
|
||||
match tc with
|
||||
| None ->
|
||||
Dlr.blockTmpT<IjsBox> (fun tmp ->
|
||||
[
|
||||
(Dlr.assign tmp expr)
|
||||
(Dlr.ternary
|
||||
(Expr.containsNumber expr)
|
||||
(Dlr.blockSimple [
|
||||
(Expr.updateBoxValue
|
||||
(expr)
|
||||
(op (Expr.unboxNumber expr) Dlr.dbl1)
|
||||
)
|
||||
(tmp :> Dlr.Expr)
|
||||
])
|
||||
(ctx.Env_Boxed_Zero) //TODO: Fallback for non-numbers
|
||||
)
|
||||
] |> Seq.ofList
|
||||
)
|
||||
|
||||
| Some tc ->
|
||||
match tc with
|
||||
| TypeCodes.Number ->
|
||||
Dlr.blockTmpT<IjsNum> (fun tmp ->
|
||||
[
|
||||
(Dlr.assign tmp expr)
|
||||
(Dlr.assign expr (op expr Dlr.dbl1))
|
||||
(tmp :> Dlr.Expr)
|
||||
] |> Seq.ofList
|
||||
)
|
||||
|
||||
| _ ->failwith "Que?"
|
||||
|
||||
//foo++, foo--
|
||||
let postIncrementVariable : ChangeVariable = postChangeVariable Dlr.add
|
||||
let postDecrementVariable : ChangeVariable = postChangeVariable Dlr.sub
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let postChangeProperty op (ctx:Ctx) expr name =
|
||||
Dlr.blockTmpT<IjsBox> (fun tmp ->
|
||||
[
|
||||
(Dlr.assign
|
||||
(tmp)
|
||||
(Api.Expr.jsObjectGetProperty expr name)
|
||||
)
|
||||
(Dlr.ternary
|
||||
(Expr.containsNumber tmp)
|
||||
(Dlr.blockSimple
|
||||
[
|
||||
(Api.Expr.jsObjectUpdateProperty
|
||||
(expr)
|
||||
(name)
|
||||
(op (Expr.unboxNumber tmp) Dlr.dbl1)
|
||||
)
|
||||
(tmp)
|
||||
]
|
||||
)
|
||||
(ctx.Env_Boxed_Undefined) //TODO: Fallback for non-numbers
|
||||
)
|
||||
] |> Seq.ofList
|
||||
)
|
||||
|
||||
//foo.bar++, foo.bar--
|
||||
let postIncrementProperty : ChangeProperty = postChangeProperty Dlr.add
|
||||
let postDecrementProperty : ChangeProperty = postChangeProperty Dlr.sub
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let postIncrementIdentifier ctx name =
|
||||
match Identifier.getExprIndexLevelType ctx name with
|
||||
| None -> postIncrementProperty ctx ctx.Globals name
|
||||
| Some(expr, i, _, tc) ->
|
||||
let var = Expr.unboxIndex expr i tc
|
||||
postIncrementVariable ctx var tc
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{81bfb688-1621-42d6-9062-093865a185d3}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>IronJS.Compiler</RootNamespace>
|
||||
<AssemblyName>IronJS.Compiler</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<Name>IronJS.Compiler</Name>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<Tailcalls>false</Tailcalls>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>bin\Debug\IronJS.Compiler.XML</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<Tailcalls>true</Tailcalls>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>bin\Release\IronJS.Compiler.XML</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<Tailcalls>false</Tailcalls>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>bin\Debug\IronJS.Compiler.XML</DocumentationFile>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<Tailcalls>true</Tailcalls>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>bin\Release\IronJS.Compiler.XML</DocumentationFile>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<Tailcalls>false</Tailcalls>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>bin\Debug\IronJS.Compiler.XML</DocumentationFile>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<Tailcalls>true</Tailcalls>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>bin\Release\IronJS.Compiler.XML</DocumentationFile>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Antlr3.Runtime">
|
||||
<HintPath>..\..\Lib\Antlr3.Runtime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Dynamic">
|
||||
<HintPath>..\..\Lib\Microsoft.Dynamic.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="FSharp.Core" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="Xebic.ES3">
|
||||
<HintPath>..\..\Lib\Xebic.ES3.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IronJS\IronJS.fsproj">
|
||||
<Name>IronJS</Name>
|
||||
<Project>{9e257324-94e7-49af-ae83-718288e925d8}</Project>
|
||||
<Private>True</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Parser.fs" />
|
||||
<Compile Include="Context.fs" />
|
||||
<Compile Include="Expr.fs" />
|
||||
<Compile Include="Scope.fs" />
|
||||
<Compile Include="Identifier.fs" />
|
||||
<Compile Include="Function.fs" />
|
||||
<Compile Include="Increment.fs" />
|
||||
<Compile Include="Exception.fs" />
|
||||
<Compile Include="Unary.fs" />
|
||||
<Compile Include="Binary.fs" />
|
||||
<Compile Include="Convert.fs" />
|
||||
<Compile Include="ControlFlow.fs" />
|
||||
<Compile Include="Core.fs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="!Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition=" Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,901 @@
|
|||
namespace IronJS
|
||||
|
||||
module Ast =
|
||||
|
||||
open IronJS
|
||||
open IronJS.Utils
|
||||
open IronJS.Aliases
|
||||
open IronJS.Ops
|
||||
|
||||
open System.Globalization
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
type BinaryOp
|
||||
= Add = 1
|
||||
| Sub = 2
|
||||
| Mul = 3
|
||||
| Div = 4
|
||||
| Eq = 100
|
||||
| NotEq = 101
|
||||
| Lt = 102
|
||||
| LtEq = 103
|
||||
| Gt = 104
|
||||
| GtEq = 105
|
||||
|
||||
| BitAnd = 50
|
||||
| BitOr = 51
|
||||
| BitShiftLeft = 52
|
||||
| BitShiftRight = 53
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
type UnaryOp
|
||||
= Inc
|
||||
| Dec
|
||||
| PostInc
|
||||
| PostDec
|
||||
| Void
|
||||
| Delete
|
||||
| TypeOf
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
type ScopeType
|
||||
= GlobalScope
|
||||
| FunctionScope
|
||||
| CatchScope
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
type EvalMode
|
||||
= Clean
|
||||
| Contains
|
||||
| Effected
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
and Tree
|
||||
//Constants
|
||||
= String of string
|
||||
| Number of double
|
||||
| Boolean of bool
|
||||
| This
|
||||
| Pass
|
||||
| Null
|
||||
| Undefined
|
||||
|
||||
//Ops
|
||||
| Unary of UnaryOp * Tree
|
||||
| Binary of BinaryOp * Tree * Tree
|
||||
|
||||
| Object of Tree list
|
||||
| Array of Tree list
|
||||
| New of Tree * Tree list
|
||||
|
||||
//
|
||||
| Eval of Tree
|
||||
| Var of Tree
|
||||
| Return of Tree
|
||||
| Identifier of string
|
||||
| Block of Tree list
|
||||
| Assign of Tree * Tree
|
||||
| With of Tree * Tree
|
||||
| Function of int64 * Tree
|
||||
| Property of Tree * string
|
||||
| Index of Tree * Tree
|
||||
| Invoke of Tree * Tree list
|
||||
| Typed of TypeCode * Tree
|
||||
| Try of Tree * Tree list * Tree option
|
||||
| Catch of Tree
|
||||
| Finally of Tree
|
||||
| Throw of Tree
|
||||
| If of Tree * Tree * Tree option
|
||||
|
||||
| For of string option * Tree * Tree * Tree * Tree
|
||||
| While of string option * Tree * Tree
|
||||
|
||||
| Break of string option
|
||||
| Continue of string option
|
||||
| Label of string * Tree
|
||||
|
||||
//
|
||||
| LocalScope of Scope * Tree
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
and [<CustomEquality>] [<CustomComparison>] Variable = {
|
||||
Name: string
|
||||
Type: TypeCode option
|
||||
Index: int
|
||||
ParamIndex: int option
|
||||
ForceDynamic: bool
|
||||
AssignedFrom: Tree Set
|
||||
IsClosedOver: bool
|
||||
InitToUndefined: bool
|
||||
} with
|
||||
|
||||
interface System.IComparable with
|
||||
member x.CompareTo y =
|
||||
match y with
|
||||
| :? Variable as y -> compare x.Name y.Name
|
||||
| _ -> invalidArg "y" "Can't compare objects of different type"
|
||||
|
||||
override x.GetHashCode () = x.Name.GetHashCode()
|
||||
override x.Equals (y:obj) =
|
||||
match y with
|
||||
| :? Variable as y -> x.Name = y.Name
|
||||
| _ -> invalidArg "y" "Can't compare objects of different type"
|
||||
|
||||
member x.IsParameter = x.ParamIndex <> None
|
||||
member x.HasStaticType = x.Type <> None
|
||||
member x.AddAssignedFrom tree =
|
||||
{x with AssignedFrom = x.AssignedFrom.Add tree}
|
||||
|
||||
static member NewParam n i = {Variable.New n i with ParamIndex=Some(i)}
|
||||
static member NewTyped n i type' =
|
||||
{Variable.New n i with Type = Some(type')}
|
||||
|
||||
static member New name index = {
|
||||
Name = name
|
||||
Type = None
|
||||
Index = index
|
||||
ParamIndex = None
|
||||
AssignedFrom = Set.empty
|
||||
ForceDynamic = false
|
||||
IsClosedOver = false
|
||||
InitToUndefined = false
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
and Closure = {
|
||||
Name: string
|
||||
Index: int
|
||||
Type: TypeCode option
|
||||
ClosureLevel: int
|
||||
GlobalLevel: int
|
||||
} with
|
||||
static member New n i cl gl = {
|
||||
Name = n
|
||||
Index = i
|
||||
Type = None
|
||||
ClosureLevel = cl
|
||||
GlobalLevel = gl
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
and Scope = {
|
||||
GlobalLevel: int
|
||||
ClosureLevel: int
|
||||
LocalLevel: int
|
||||
|
||||
EvalMode: EvalMode
|
||||
DynamicLookup: bool
|
||||
|
||||
ScopeType: ScopeType
|
||||
Variables: Variable Set
|
||||
Closures: Closure Set
|
||||
} with
|
||||
member x.VariableCount = x.Variables.Count
|
||||
|
||||
member x.AddVar n =
|
||||
let c = x.VariableCount
|
||||
{x with Variables = x.Variables.Add (Variable.New n c)}
|
||||
|
||||
member x.ReplaceVar old new' =
|
||||
{x with Variables = (x.Variables.Remove old).Add new'}
|
||||
|
||||
member x.AddCls cls =
|
||||
{x with Closures = x.Closures.Add cls}
|
||||
|
||||
member x.TryGetVar n = x.Variables |> Seq.tryFind (fun x -> x.Name = n)
|
||||
member x.TryGetCls n = x.Closures |> Seq.tryFind (fun x -> x.Name = n)
|
||||
|
||||
member x.ParamCount =
|
||||
x.Variables |> Set.filter (fun x -> x.IsParameter)
|
||||
|> Set.count
|
||||
|
||||
member x.ClosedOverCount =
|
||||
x.Variables |> Set.filter (fun x -> x.IsClosedOver)
|
||||
|> Set.count
|
||||
|
||||
member x.NonParamCount =
|
||||
x.Variables |> Set.filter (fun x -> not x.IsParameter)
|
||||
|> Set.count
|
||||
|
||||
member x.LocalCount =
|
||||
x.Variables |> Set.filter (fun x -> not x.IsClosedOver)
|
||||
|> Set.count
|
||||
|
||||
member x.ClosedOverSize = x.ClosedOverCount + 1
|
||||
|
||||
|
||||
member x.MakeVarClosedOver var =
|
||||
if var.IsClosedOver then
|
||||
failwith "Variable is already closed over"
|
||||
|
||||
//New, closed over version
|
||||
let var' =
|
||||
{var with
|
||||
Index = x.ClosedOverCount + 1
|
||||
IsClosedOver = true}
|
||||
|
||||
//New variable set
|
||||
let variables = (x.Variables.Remove var).Add var'
|
||||
|
||||
//Update indexes of non-closed over variable indexes in set
|
||||
let variables =
|
||||
variables |> Set.map (fun x ->
|
||||
if not x.IsClosedOver && x.Index > var.Index // (var.Index-1) ???
|
||||
then {x with Index = x.Index - 1}
|
||||
else x
|
||||
)
|
||||
|
||||
//Return new scope
|
||||
{x with Variables = variables}
|
||||
|
||||
|
||||
static member NewDynamic = {Scope.New with DynamicLookup = true}
|
||||
static member NewGlobal = {Scope.New with ScopeType = GlobalScope}
|
||||
static member New = {
|
||||
GlobalLevel = -1
|
||||
ClosureLevel = -1
|
||||
LocalLevel = -1
|
||||
|
||||
EvalMode = Clean
|
||||
DynamicLookup = false
|
||||
|
||||
ScopeType = FunctionScope
|
||||
Variables = Set.empty
|
||||
Closures = Set.empty
|
||||
}
|
||||
static member NewFunction parms = {
|
||||
Scope.New with
|
||||
ScopeType = FunctionScope
|
||||
Variables =
|
||||
parms
|
||||
|> List.mapi (fun i n -> Variable.NewParam n i)
|
||||
|> Set.ofList
|
||||
}
|
||||
static member NewCatch name = {
|
||||
Scope.New with
|
||||
ScopeType = CatchScope
|
||||
Variables = Set.ofList [Variable.New name 0]
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// ANALYZERS
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
let private _walk f tree =
|
||||
match tree with
|
||||
//Simple nodes
|
||||
| Identifier _
|
||||
| Boolean _
|
||||
| String _
|
||||
| Number _
|
||||
| Break _
|
||||
| Continue _
|
||||
| Typed (_, _)
|
||||
| Pass
|
||||
| Null
|
||||
| This
|
||||
| Undefined -> tree
|
||||
|
||||
| Binary(op, ltree, rtree) -> Binary(op, f ltree, f rtree)
|
||||
| Unary(op, tree) -> Unary(op, f tree)
|
||||
|
||||
| Array indexes -> Array [for t in indexes -> f t]
|
||||
| Object properties -> Object [for t in properties -> f t]
|
||||
| New(func, args) -> New(f func, [for a in args -> f a])
|
||||
| Invoke(func, args) -> Invoke(f func, [for a in args -> f a])
|
||||
|
||||
| Eval(tree) -> Eval (f tree)
|
||||
| Property(tree, name) -> Property(f tree, name)
|
||||
| Index(target, tree) -> Index(f target, f tree)
|
||||
| Assign(ltree, rtree) -> Assign(f ltree, f rtree)
|
||||
| Block(trees) -> Block([for t in trees -> f t])
|
||||
| Var(tree) -> Var(f tree)
|
||||
| Return(tree) -> Return(f tree)
|
||||
| With(target, tree) -> With(f target, f tree)
|
||||
| Function(id, tree) -> Function(id, f tree)
|
||||
| LocalScope(scope, tree) -> LocalScope(scope, f tree)
|
||||
|
||||
| Label(label, tree) -> Label(label, f tree)
|
||||
| If(test, ifTrue, ifFalse) -> If(f test, f ifTrue, (f >? ifFalse))
|
||||
| While(label, tree, body) -> While(label, f tree, f body)
|
||||
| For(label, init, test, incr, body) ->
|
||||
For(label, f init, f test, f incr, f body)
|
||||
|
||||
//Exception Stuff
|
||||
| Try(body, catch, finally') ->
|
||||
let finally' = match finally' with Some t -> Some (f t) |x->x
|
||||
Try(f body, [for x in catch -> f x], finally')
|
||||
|
||||
| Catch tree -> Catch (f tree)
|
||||
| Finally body -> Finally (f body)
|
||||
| Throw tree -> Throw (f tree)
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
let varByName n (v:Variable) = n = v.Name
|
||||
let clsByName n (v:Closure) = n = v.Name
|
||||
|
||||
let hasCls n s = s.Closures |> Set.exists (clsByName n)
|
||||
let hasVar n s = s.Variables |> Set.exists (varByName n)
|
||||
|
||||
let getCls n s = s.Closures |> Seq.find (clsByName n)
|
||||
let getVar n s = s.Variables |> Seq.find (varByName n)
|
||||
|
||||
let popScope sc =
|
||||
match !sc with
|
||||
| [] -> failwith "Que?"
|
||||
| s::sc' -> sc := sc'; s
|
||||
|
||||
let pushScopeAnd sc s f t =
|
||||
sc := s :: !sc
|
||||
let t' = f t
|
||||
popScope sc, t'
|
||||
|
||||
let replaceScope old new' sc =
|
||||
let replace x = if x = old then new' else x
|
||||
sc := sc %> List.map replace
|
||||
|
||||
let modifyScope f sc =
|
||||
match !sc with
|
||||
| [] -> ()
|
||||
| x::xs -> sc := f x :: xs
|
||||
|
||||
let bottomScope sc =
|
||||
match !sc with
|
||||
| [] -> failwith "Que?"
|
||||
| x::_ -> x
|
||||
|
||||
let isCatchScope s =
|
||||
s.ScopeType = CatchScope
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let stripVarStatements tree =
|
||||
let sc = ref List.empty<Scope>
|
||||
|
||||
let rec addVar name rtree =
|
||||
if (bottomScope sc).ScopeType <> GlobalScope then
|
||||
modifyScope (fun (s:Scope) -> s.AddVar name) sc
|
||||
|
||||
match rtree with
|
||||
| None -> Pass
|
||||
| Some rtree -> Assign(Identifier name, analyze rtree)
|
||||
|
||||
and analyze tree =
|
||||
match tree with
|
||||
| LocalScope(s, t) when s.ScopeType <> CatchScope ->
|
||||
LocalScope(pushScopeAnd sc s analyze t)
|
||||
|
||||
| Var(Identifier name) -> addVar name None
|
||||
| Var(Assign(Identifier name, rtree)) -> addVar name (Some rtree)
|
||||
|
||||
| _ -> _walk analyze tree
|
||||
|
||||
analyze tree
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let markClosedOverVars tree =
|
||||
let sc = ref List.empty
|
||||
|
||||
let rec mark tree =
|
||||
match tree with
|
||||
| LocalScope(s, t) ->
|
||||
LocalScope(pushScopeAnd sc s mark t)
|
||||
|
||||
| Invoke(Identifier "eval", source::[]) ->
|
||||
|
||||
//Close over all variables in scope
|
||||
sc := sc %> List.map (fun x ->
|
||||
Set.fold (fun (s:Scope) v ->
|
||||
if not v.IsClosedOver then s.MakeVarClosedOver v else s
|
||||
) x x.Variables
|
||||
)
|
||||
|
||||
modifyScope (fun s -> {s with EvalMode=EvalMode.Contains}) sc
|
||||
|
||||
Eval(source)
|
||||
|
||||
| Identifier name ->
|
||||
let refScope = sc %> List.head
|
||||
|
||||
if not (hasVar name refScope) then
|
||||
match sc %> List.tryFind (hasVar name) with
|
||||
| None -> () //Global
|
||||
| Some defScope ->
|
||||
//Make sure we don't close over variables
|
||||
//in the same function scope but in different
|
||||
//catch scopes
|
||||
let continue' =
|
||||
match defScope.ScopeType with
|
||||
| CatchScope ->
|
||||
sc %> Seq.takeWhile isCatchScope
|
||||
|> Seq.exists (fun x -> x = defScope)
|
||||
|> not
|
||||
|
||||
| _ -> true
|
||||
|
||||
//If we're ok to continue set the variable
|
||||
//as closed over in its defining scope
|
||||
if continue' then
|
||||
match defScope.TryGetVar name with
|
||||
| None -> failwith "Que?"
|
||||
| Some var ->
|
||||
if not var.IsClosedOver then
|
||||
let varScope' = defScope.MakeVarClosedOver var
|
||||
replaceScope defScope varScope' sc
|
||||
|
||||
//Return Tree
|
||||
tree
|
||||
|
||||
| _ -> _walk mark tree
|
||||
|
||||
mark tree
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let calculateScopeLevels levels tree =
|
||||
//wl = WithLevel
|
||||
//gl = GlobalLevel
|
||||
//cl = ClosureLevel
|
||||
//ll = LocalLevel
|
||||
//dl = DynamicLookup
|
||||
//em = EvalMode
|
||||
|
||||
let getLocalLevel ll s =
|
||||
match s.ScopeType with
|
||||
| FunctionScope -> 0
|
||||
| CatchScope when s.LocalCount > 0 -> ll+1
|
||||
| _ -> ll
|
||||
|
||||
let getGlobalLevel gl s = gl + 1
|
||||
let getClosureLevel cl (s:Scope) =
|
||||
if s.ClosedOverCount > 0 then cl+1 else cl
|
||||
|
||||
let getDynamicLookup wl s (sc:Scope list ref) =
|
||||
wl > 0
|
||||
|| s.DynamicLookup
|
||||
|| ((!sc).Length > 0 && (!sc).[0].DynamicLookup)
|
||||
|
||||
let getEvalMode (s:Scope) (sc:Scope list ref) =
|
||||
match s.EvalMode with
|
||||
| Clean ->
|
||||
if (!sc).Length > 0 && (!sc).[0].EvalMode <> EvalMode.Clean
|
||||
then EvalMode.Effected
|
||||
else EvalMode.Clean
|
||||
| mode -> mode
|
||||
|
||||
let sc = ref List.empty
|
||||
let rec calculate wl gl cl ll tree =
|
||||
match tree with
|
||||
| LocalScope(s, t) ->
|
||||
|
||||
let dl = getDynamicLookup wl s sc
|
||||
let em = getEvalMode s sc
|
||||
let gl, cl, ll =
|
||||
match !sc with
|
||||
| [] -> gl, cl, ll
|
||||
| _ ->
|
||||
getGlobalLevel gl s,
|
||||
getClosureLevel cl s,
|
||||
getLocalLevel ll s
|
||||
|
||||
let s =
|
||||
{s with
|
||||
GlobalLevel=gl
|
||||
ClosureLevel=cl
|
||||
LocalLevel=ll
|
||||
DynamicLookup=dl
|
||||
EvalMode=em
|
||||
}
|
||||
|
||||
let s =
|
||||
match s.ScopeType with
|
||||
| CatchScope when s.LocalCount > 0 ->
|
||||
let var = Seq.first s.Variables
|
||||
let var = {var with Index=1}
|
||||
{s with Variables=set[var]}
|
||||
| _ -> s
|
||||
|
||||
LocalScope(pushScopeAnd sc s (calculate wl gl cl ll) t)
|
||||
|
||||
| With(object', tree) ->
|
||||
let object' = calculate wl gl cl ll object'
|
||||
let tree = calculate (wl+1) gl cl ll tree
|
||||
modifyScope (fun s -> {s with DynamicLookup=true}) sc
|
||||
With(object', tree)
|
||||
|
||||
| _ -> _walk (calculate wl gl cl ll) tree
|
||||
|
||||
match levels with
|
||||
| Some(gl, cl, ll) -> calculate 0 gl cl ll tree
|
||||
| None -> calculate 0 0 -1 -1 tree
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let resolveClosures tree =
|
||||
let sc = ref List.empty<Scope>
|
||||
|
||||
let hasVariable name (s:Scope) =
|
||||
match s.TryGetVar name with
|
||||
| None -> s.TryGetCls name <> None
|
||||
| _ -> true
|
||||
|
||||
let rec analyze tree =
|
||||
match tree with
|
||||
| LocalScope(s, t) ->
|
||||
LocalScope(pushScopeAnd sc s analyze t)
|
||||
|
||||
| Eval _ ->
|
||||
|
||||
let closures =
|
||||
sc %> Seq.map (fun x ->
|
||||
x.Variables
|
||||
|> Seq.map (fun v ->
|
||||
v, x.GlobalLevel, x.ClosureLevel))
|
||||
|> Seq.concat
|
||||
|> Seq.groupBy (fun (v, _, _) -> v.Name)
|
||||
|> Seq.map (fun (_, s) -> Seq.maxBy(fun (_, _, cl) -> cl) s)
|
||||
|> Seq.map (fun (v, gl, cl) -> Closure.New v.Name v.Index cl gl)
|
||||
|> Set.ofSeq
|
||||
|
||||
modifyScope (fun s -> {s with Closures=closures}) sc
|
||||
|
||||
tree
|
||||
|
||||
| Identifier name ->
|
||||
let refScope = List.head !sc
|
||||
let hasVariable = hasVariable name
|
||||
|
||||
if not (hasVariable refScope) then
|
||||
|
||||
match sc %> List.tryFind (fun x -> hasVariable x) with
|
||||
| None -> () //Global
|
||||
| Some defScope ->
|
||||
|
||||
match defScope.TryGetVar name with
|
||||
| None ->
|
||||
|
||||
match defScope.TryGetCls name with
|
||||
| None -> failwith "Que?"
|
||||
| Some cls -> modifyScope (fun (s:Scope) -> s.AddCls cls) sc
|
||||
|
||||
| Some var ->
|
||||
if var.IsClosedOver then
|
||||
let cl = defScope.ClosureLevel
|
||||
let gl = defScope.GlobalLevel
|
||||
let cls = Closure.New name var.Index cl gl
|
||||
modifyScope (fun (s:Scope) -> s.AddCls cls) sc
|
||||
|
||||
tree
|
||||
|
||||
| _ -> _walk analyze tree
|
||||
|
||||
analyze tree
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let expressionType tree =
|
||||
match tree with
|
||||
| Tree.Number _ -> Some TypeCodes.Number
|
||||
| Tree.Function (_, _) -> Some TypeCodes.Function
|
||||
| Tree.Object _ -> Some TypeCodes.Object
|
||||
| Tree.Binary (op, l, r) ->
|
||||
match op with
|
||||
| BinaryOp.BitShiftLeft -> Some TypeCodes.Number
|
||||
| BinaryOp.BitAnd -> Some TypeCodes.Number
|
||||
| _ -> None
|
||||
| _ -> None
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let findAssignmentOperations tree =
|
||||
let sc = ref List.empty<Scope>
|
||||
|
||||
let rec find tree =
|
||||
match tree with
|
||||
| LocalScope(s, t) ->
|
||||
LocalScope(pushScopeAnd sc s find t)
|
||||
|
||||
| Assign(Identifier name, value) ->
|
||||
|
||||
let s = sc %> List.head
|
||||
|
||||
match s.TryGetVar name with
|
||||
| None -> ()
|
||||
| Some var ->
|
||||
let from =
|
||||
match expressionType value with
|
||||
| None -> value
|
||||
| Some tc -> Tree.Typed(tc, Pass)
|
||||
|
||||
let var' = var.AddAssignedFrom from
|
||||
modifyScope (fun (s:Scope) -> s.ReplaceVar var var') sc
|
||||
|
||||
Assign(Identifier name, find value)
|
||||
|
||||
| _ -> _walk find tree
|
||||
|
||||
find tree
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let transform tree =
|
||||
|
||||
let rec transform tree =
|
||||
tree
|
||||
|
||||
transform tree
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
let applyAnalyzers tree levels =
|
||||
let analyzers = [
|
||||
stripVarStatements
|
||||
markClosedOverVars
|
||||
calculateScopeLevels levels
|
||||
resolveClosures
|
||||
findAssignmentOperations
|
||||
transform
|
||||
]
|
||||
|
||||
List.fold (fun t f -> f t) tree analyzers
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// PARSERS
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
module Parsers =
|
||||
|
||||
module Ecma3 =
|
||||
|
||||
open IronJS
|
||||
open Xebic.ES3
|
||||
|
||||
type private AntlrToken = Antlr.Runtime.Tree.CommonTree
|
||||
|
||||
let private _funIdCounter = ref 0L
|
||||
let private _funId () =
|
||||
_funIdCounter := !_funIdCounter + 1L
|
||||
!_funIdCounter
|
||||
|
||||
let private children (tok:AntlrToken) =
|
||||
if tok.Children = null then []
|
||||
else
|
||||
tok.Children |> Seq.cast<AntlrToken>
|
||||
|> Seq.toList
|
||||
|
||||
let private cast (tok:obj) = tok :?> AntlrToken
|
||||
let private hasChild (tok:AntlrToken) index = tok.ChildCount > index
|
||||
|
||||
let private child (tok:AntlrToken) index =
|
||||
if hasChild tok index then cast tok.Children.[index] else null
|
||||
|
||||
let private text (tok:AntlrToken) = tok.Text
|
||||
let private jsString (tok:AntlrToken) =
|
||||
let str = text tok
|
||||
str.Substring(1, str.Length - 2)
|
||||
|
||||
let rec binary op tok =
|
||||
Binary(op, translate (child tok 0), translate (child tok 1))
|
||||
|
||||
and for' label tok =
|
||||
let type' = child tok 0
|
||||
match type'.Type with
|
||||
| ES3Parser.FORSTEP ->
|
||||
let init = translate (child type' 0)
|
||||
let test = translate (child type' 1)
|
||||
let incr = translate (child type' 2)
|
||||
For(label, init, test, incr, translate (child tok 1))
|
||||
|
||||
| _ -> failwith "Que?"
|
||||
|
||||
and while' label tok =
|
||||
While(label, translate (child tok 0), translate (child tok 1))
|
||||
|
||||
and binaryAsn op tok =
|
||||
Assign(
|
||||
translate (child tok 0),
|
||||
Binary(op, translate (child tok 0), translate (child tok 1))
|
||||
)
|
||||
|
||||
and unary op tok =
|
||||
Unary(op, translate (child tok 0))
|
||||
|
||||
and translate (tok:AntlrToken) =
|
||||
if tok = null then Pass else
|
||||
match tok.Type with
|
||||
// Nil
|
||||
| 0
|
||||
|
||||
// { }
|
||||
| ES3Parser.BLOCK -> Block [for x in children tok -> translate x]
|
||||
|
||||
// var foo
|
||||
| ES3Parser.VAR ->
|
||||
if tok.ChildCount > 1
|
||||
then Block [for x in children tok -> Var(translate x)]
|
||||
else Var(translate (child tok 0))
|
||||
|
||||
// foo = 1
|
||||
| ES3Parser.ASSIGN ->
|
||||
Assign(translate (child tok 0), translate (child tok 1))
|
||||
|
||||
// true
|
||||
| ES3Parser.TRUE -> Boolean true
|
||||
|
||||
// false
|
||||
| ES3Parser.FALSE -> Boolean false
|
||||
|
||||
// foo
|
||||
| ES3Parser.Identifier -> Identifier(text tok)
|
||||
|
||||
// "foo"
|
||||
| ES3Parser.StringLiteral -> String(jsString tok)
|
||||
|
||||
// 1
|
||||
| ES3Parser.DecimalLiteral -> Tree.Number(double (text tok))
|
||||
|
||||
// 0xFF
|
||||
| ES3Parser.HexIntegerLiteral ->
|
||||
let n = System.Convert.ToInt32(text tok, 16)
|
||||
Tree.Number(double n)
|
||||
|
||||
// foo(1, 2, 3)
|
||||
| ES3Parser.CALL ->
|
||||
let child0 = child tok 0
|
||||
let args = [for x in children (child tok 1) -> translate x]
|
||||
if child0.Type = ES3Parser.NEW
|
||||
then New(translate (child child0 0), args)
|
||||
else Invoke(translate child0, args)
|
||||
|
||||
// foo.bar
|
||||
| ES3Parser.BYFIELD ->
|
||||
Property (translate (child tok 0), text (child tok 1))
|
||||
|
||||
// return foo
|
||||
| ES3Parser.RETURN -> Return (translate (child tok 0))
|
||||
|
||||
// this
|
||||
| ES3Parser.THIS -> This
|
||||
|
||||
// {foo: 1}
|
||||
| ES3Parser.OBJECT ->
|
||||
Tree.Object [for x in children tok -> translate x]
|
||||
|
||||
// [1, 2, 3]
|
||||
| ES3Parser.ARRAY ->
|
||||
Tree.Array [for x in children tok -> translate (child x 0)]
|
||||
|
||||
// try { }
|
||||
| ES3Parser.TRY ->
|
||||
let finally' =
|
||||
if tok.ChildCount = 3
|
||||
then Some(translate (child tok 2))
|
||||
else None
|
||||
|
||||
Try(translate (child tok 0), [translate (child tok 1)], finally')
|
||||
|
||||
// throw
|
||||
| ES3Parser.THROW -> Throw(translate (child tok 0))
|
||||
|
||||
// finally { }
|
||||
| ES3Parser.FINALLY -> Finally(translate (child tok 0))
|
||||
|
||||
// foo[0]
|
||||
| ES3Parser.BYINDEX ->
|
||||
Index(translate (child tok 0), translate (child tok 1))
|
||||
|
||||
// delete foo.bar
|
||||
| ES3Parser.DELETE -> Unary(UnaryOp.Delete, translate (child tok 0))
|
||||
|
||||
// typeof foo
|
||||
| ES3Parser.TYPEOF -> Unary(UnaryOp.TypeOf, translate (child tok 0))
|
||||
|
||||
// {foo: 1}
|
||||
| ES3Parser.NAMEDVALUE ->
|
||||
Assign(String(text (child tok 0)), translate (child tok 1))
|
||||
|
||||
// if { }
|
||||
| ES3Parser.IF ->
|
||||
let test = translate (child tok 0)
|
||||
let ifTrue = translate (child tok 1)
|
||||
If(test, ifTrue, None)
|
||||
|
||||
// (foo)
|
||||
| ES3Parser.PAREXPR
|
||||
| ES3Parser.EXPR -> translate (child tok 0)
|
||||
|
||||
| ES3Parser.AND -> binary BinaryOp.BitAnd tok // foo | bar
|
||||
| ES3Parser.EQ -> binary BinaryOp.Eq tok // 1 = 1
|
||||
| ES3Parser.ADD -> binary BinaryOp.Add tok // 1 + 1
|
||||
| ES3Parser.SUB -> binary BinaryOp.Sub tok // 1 - 1
|
||||
| ES3Parser.LT -> binary BinaryOp.Lt tok // 1 < 1
|
||||
| ES3Parser.LTE -> binary BinaryOp.LtEq tok // 1 <= 1
|
||||
| ES3Parser.GT -> binary BinaryOp.Gt tok // 1 > 1
|
||||
| ES3Parser.GTE -> binary BinaryOp.GtEq tok // 1 >= 1
|
||||
| ES3Parser.MUL -> binary BinaryOp.Mul tok // 1 * 1
|
||||
| ES3Parser.SHL -> binary BinaryOp.BitShiftLeft tok // 1 << 1
|
||||
| ES3Parser.SHR -> binary BinaryOp.BitShiftRight tok // 1 >> 1
|
||||
| ES3Parser.ADDASS -> binaryAsn BinaryOp.Add tok // foo += 1
|
||||
| ES3Parser.PINC -> unary UnaryOp.PostInc tok // foo+
|
||||
|
||||
// for(;;)
|
||||
| ES3Parser.FOR -> for' None tok
|
||||
|
||||
// while() {}
|
||||
| ES3Parser.WHILE -> while' None tok
|
||||
|
||||
// catch() { }
|
||||
| ES3Parser.CATCH ->
|
||||
let varName = text (child tok 0)
|
||||
let body = translate (child tok 1)
|
||||
Catch(LocalScope(Scope.NewCatch varName, body))
|
||||
|
||||
// with() { }
|
||||
| ES3Parser.WITH -> With(translate (child tok 0), translate (child tok 1))
|
||||
|
||||
// break
|
||||
| ES3Parser.BREAK ->
|
||||
if tok.ChildCount = 1
|
||||
then Break (Some(text (child tok 0)))
|
||||
else Break None
|
||||
|
||||
// continue
|
||||
| ES3Parser.CONTINUE ->
|
||||
if tok.ChildCount = 1
|
||||
then Continue (Some(text (child tok 0)))
|
||||
else Continue None
|
||||
|
||||
| ES3Parser.LABELLED ->
|
||||
let child1 = child tok 1
|
||||
let label = text (child tok 0)
|
||||
match child1.Type with
|
||||
| ES3Parser.FOR -> for' (Some label) child1
|
||||
| ES3Parser.WHILE -> while' (Some label) child1
|
||||
| _ -> Label(label, translate child1)
|
||||
|
||||
// function() {}
|
||||
| ES3Parser.FUNCTION ->
|
||||
let pc, bc = if tok.ChildCount = 3 then (1, 2) else (0, 1)
|
||||
let id = _funId() + 1000000L
|
||||
let parms = [for x in children (child tok pc) -> text x]
|
||||
let scope = Scope.NewFunction parms
|
||||
let body = translate (child tok bc)
|
||||
let func = Tree.Function(id, LocalScope(scope, body))
|
||||
|
||||
if tok.ChildCount < 3 then func
|
||||
else
|
||||
let name = text (child tok 0)
|
||||
Var(Assign(Identifier name, func))
|
||||
|
||||
| _ -> failwithf "No parser for token %s (%i)" (ES3Parser.tokenNames.[tok.Type]) tok.Type
|
||||
|
||||
let parse source =
|
||||
let lexer = new Xebic.ES3.ES3Lexer(new Antlr.Runtime.ANTLRStringStream(source))
|
||||
let parser = new Xebic.ES3.ES3Parser(new Antlr.Runtime.CommonTokenStream(lexer))
|
||||
translate (parser.program().Tree :?> AntlrToken)
|
||||
|
||||
let parseFile path = parse (System.IO.File.ReadAllText(path))
|
||||
let parseGlobalFile path = LocalScope(Scope.NewGlobal, parseFile path)
|
||||
let parseGlobalSource source = LocalScope(Scope.NewGlobal, parse source)
|
||||
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
namespace IronJS.Compiler
|
||||
|
||||
open IronJS
|
||||
open IronJS.Compiler
|
||||
|
||||
module Scope =
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let initGlobal (ctx:Ctx) tree =
|
||||
Dlr.blockSimple [
|
||||
(Dlr.assign ctx.ChainExpr ctx.Fun_Chain)
|
||||
(Dlr.assign ctx.DynamicExpr ctx.Fun_DynamicChain)
|
||||
(tree)
|
||||
]
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let initWith (ctx:Ctx) object' tree =
|
||||
let pushArgs = [ctx.DynamicExpr; object'; Dlr.const' ctx.Scope.GlobalLevel]
|
||||
Dlr.blockSimple [
|
||||
(Dlr.callStaticT<Helpers.ScopeHelpers> "PushScope" pushArgs)
|
||||
(tree)
|
||||
(Dlr.callStaticT<Helpers.ScopeHelpers> "PopScope" [ctx.DynamicExpr])
|
||||
]
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
module Function =
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
let demoteParam maxIndex (v:Ast.Variable) =
|
||||
match v.ParamIndex with
|
||||
| None -> v
|
||||
| Some i -> if i < maxIndex then v else {v with ParamIndex=None}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
let demoteMissingParams vars count supplied =
|
||||
let diff = supplied - count
|
||||
if diff < 0
|
||||
then vars |> Set.map (demoteParam supplied)
|
||||
else vars
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
let resolveParamType ctx (var:Ast.Variable) =
|
||||
let i = Utils.Option.unwrap var.ParamIndex
|
||||
let tc = Utils.expr2tc ctx.ParameterExprs.[i]
|
||||
if tc > TypeCodes.Empty then {var with Type=Some tc} else var
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
let resolveNonParamType ctx (var:Ast.Variable) =
|
||||
let tree = Utils.Seq.first var.AssignedFrom
|
||||
let type' = match tree with
|
||||
| Ast.Typed(tc, Ast.Pass) -> Some tc
|
||||
| _ -> None
|
||||
|
||||
{var with Type=type'}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
let resolveVariableTypes ctx vars =
|
||||
vars |> Set.map (fun (var:Ast.Variable) -> var
|
||||
(*
|
||||
if var.IsParameter
|
||||
then resolveParamType ctx var
|
||||
elif var.AssignedFrom.Count = 1
|
||||
then resolveNonParamType ctx var
|
||||
else var
|
||||
*)
|
||||
)
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
let storageExpr ctx (var:Ast.Variable) =
|
||||
if var.IsClosedOver then ctx.ChainExpr else ctx.LocalExpr
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
let initParams ctx (params':Ast.Variable seq) =
|
||||
params' |> Seq.map (fun var ->
|
||||
let expr = storageExpr ctx var
|
||||
let variable = Dlr.indexInt expr var.Index
|
||||
let i = Utils.Option.unwrap var.ParamIndex
|
||||
Expr.assignBoxValue variable ctx.ParameterExprs.[i]
|
||||
)
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
let initNonParams ctx (nonParams:Ast.Variable seq) =
|
||||
nonParams |> Seq.map (fun var ->
|
||||
let expr = storageExpr ctx var
|
||||
let variable = Dlr.indexInt expr var.Index
|
||||
match var.Type with
|
||||
| None -> Expr.assignBoxValue variable Expr.undefined
|
||||
| Some tc -> Expr.setBoxType variable tc
|
||||
)
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
let initVariables ctx (vars:Ast.Variable Set) =
|
||||
let params', nonParams = vars |> Set.partition (fun var -> var.IsParameter)
|
||||
initParams ctx params', initNonParams ctx nonParams
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
let initLocalScope (ctx:Ctx) count =
|
||||
if ctx.Target.IsEval then Dlr.void'
|
||||
else
|
||||
match count with
|
||||
| 0 -> Dlr.void'
|
||||
| _ ->
|
||||
(Dlr.assign
|
||||
(ctx.LocalExpr)
|
||||
(Dlr.newArrayBoundsT<IronJS.Box> (Dlr.const' count))
|
||||
)
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
let initScopeChain (ctx:Ctx) count =
|
||||
if ctx.Target.IsEval then Dlr.void'
|
||||
else
|
||||
match count with
|
||||
| 0 -> Dlr.assign ctx.ChainExpr ctx.Fun_Chain
|
||||
| _ ->
|
||||
Dlr.blockSimple [
|
||||
(Dlr.assign
|
||||
(ctx.ChainExpr)
|
||||
(Dlr.newArrayBoundsT<IronJS.Box> (Dlr.const' (count+1)))
|
||||
)
|
||||
(Dlr.assign
|
||||
(Dlr.field (Dlr.index0 ctx.ChainExpr) "Scope")
|
||||
(ctx.Fun_Chain)
|
||||
)
|
||||
]
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
let initDynamicChain (ctx:Ctx) (s:Ast.Scope) =
|
||||
if ctx.Target.IsEval || not s.DynamicLookup
|
||||
then Dlr.void'
|
||||
else Dlr.assign ctx.DynamicExpr ctx.Fun_DynamicChain
|
|
@ -0,0 +1,37 @@
|
|||
namespace IronJS.Compiler
|
||||
|
||||
open IronJS
|
||||
open IronJS.Compiler
|
||||
|
||||
module Unary =
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let deleteIndex object' index =
|
||||
(Expr.testIsObject
|
||||
(object')
|
||||
(fun x -> Dlr.callStaticT<Api.Object> "deleteIndex" [x; index])
|
||||
(fun x -> Dlr.false')
|
||||
)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let deleteProperty object' name =
|
||||
let name = Dlr.const' name
|
||||
(Expr.testIsObject
|
||||
(object')
|
||||
(fun x -> Dlr.callStaticT<Api.Object> "deleteOwnProperty" [x; name])
|
||||
(fun x -> Dlr.false')
|
||||
)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
let deleteIdentifier (ctx:Ctx) name =
|
||||
if ctx.DynamicLookup then
|
||||
let args = [ctx.DynamicExpr; ctx.Globals; Dlr.const' name]
|
||||
Dlr.callStaticT<Helpers.ScopeHelpers> "DynamicDelete" args
|
||||
|
||||
else
|
||||
if Identifier.isGlobal ctx name
|
||||
then deleteProperty ctx.Globals name
|
||||
else Dlr.false'
|
||||
|
||||
let typeOf expr =
|
||||
Dlr.callStaticT<Operators> "typeOf" [expr]
|
|
@ -1,20 +0,0 @@
|
|||
open IronJS
|
||||
open IronJS.Fsi
|
||||
open IronJS.Aliases
|
||||
open IronJS.Runtime
|
||||
|
||||
open System
|
||||
|
||||
//IO.Directory.SetCurrentDirectory(@"C:\Users\fredrikhm.CPBEUROPE\Projects - Personal\IronJS\Src\IronJS.Console")
|
||||
IO.Directory.SetCurrentDirectory(@"C:\Users\Fredrik\Projects\IronJS\Src\IronJS.Console")
|
||||
|
||||
let env =
|
||||
(Environment.Create {
|
||||
File = Compiler.Core.compileFile
|
||||
Ast = Compiler.Core.compileAst2
|
||||
})
|
||||
|
||||
let compiled = env.CompileFile "Testing.js"
|
||||
|
||||
let timeCompile = Utils.time(compiled).TotalMilliseconds
|
||||
let time = Utils.time(compiled).TotalMilliseconds
|
|
@ -1,33 +0,0 @@
|
|||
#light
|
||||
#r @"FSharp.PowerPack"
|
||||
#r @"..\Dependencies\Antlr3.Runtime.dll"
|
||||
#r @"..\Dependencies\Microsoft.Dynamic.dll"
|
||||
#r @"..\IronJS.Parser\bin\Debug\IronJS.Parser.dll"
|
||||
#r @"..\IronJS\bin\Debug\IronJS.dll"
|
||||
|
||||
open IronJS
|
||||
open IronJS.Fsi
|
||||
open IronJS.Aliases
|
||||
open IronJS.Runtime
|
||||
|
||||
open System
|
||||
|
||||
fsi.AddPrinter(fun (x:Ast.Types.Variable) -> x.DebugView)
|
||||
fsi.AddPrinter(fun (x:Ast.Types.Closure) -> x.DebugView)
|
||||
fsi.AddPrinter(fun (x:EtParam) -> sprintf "EtParam:%A" x.Type)
|
||||
fsi.AddPrinter(fun (x:Et) -> sprintf "%A" (dbgViewProp.GetValue(x, null)))
|
||||
fsi.AddPrinter(fun (x:EtLambda) -> sprintf "%A" (dbgViewProp.GetValue(x, null)))
|
||||
|
||||
IO.Directory.SetCurrentDirectory(@"C:\Users\fredrikhm.CPBEUROPE\Projects - Personal\IronJS\Src\IronJS.Console")
|
||||
//IO.Directory.SetCurrentDirectory(@"C:\Users\Fredrik\Projects\IronJS\Src\IronJS.Console")
|
||||
|
||||
let env =
|
||||
(Environment.Create {
|
||||
File = Compiler.Core.compileFile
|
||||
Ast = Compiler.Core.compileAst2
|
||||
})
|
||||
|
||||
let compiled = env.CompileFile "Testing.js"
|
||||
|
||||
let timeCompile = Utils.time(compiled).TotalMilliseconds
|
||||
let time = Utils.time(compiled).TotalMilliseconds
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
var bench = function () {
|
||||
function f(x, y, z) {
|
||||
return x + y + z;
|
||||
}
|
||||
|
||||
var y = 2;
|
||||
|
||||
for (var i = 0; i < 2500000; ++i) {
|
||||
y = f(1, 2, 3);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
bench = function () {
|
||||
function f(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) {
|
||||
|
||||
}
|
||||
|
||||
for (var i = 0; i < 3000000; ++i)
|
||||
f();
|
||||
}
|
||||
|
||||
var bench = function () {
|
||||
var foo = function (a, b) {
|
||||
return function () {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
return foo()();
|
||||
}
|
||||
|
||||
bench();
|
||||
*/
|
||||
|
||||
/*
|
||||
foo = {};
|
||||
foo.a = {};
|
||||
foo.a.b = {};
|
||||
foo.a.b.c = {};
|
||||
foo.a.b.c.d = {};
|
||||
foo.a.b.c.d.e = {};
|
||||
*/
|
||||
|
||||
var foo = {};
|
||||
foo.bar = 1;
|
||||
bar = foo["bar"];
|
|
@ -5,14 +5,14 @@
|
|||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{7a13e1fa-9045-4e9e-866c-b649c0fc030c}</ProjectGuid>
|
||||
<ProjectGuid>{de1cd6ae-3829-4546-b46a-afd6dee78ee1}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>IronJS.Console</RootNamespace>
|
||||
<AssemblyName>IronJS.Console</AssemblyName>
|
||||
<RootNamespace>IronJS.Dev</RootNamespace>
|
||||
<AssemblyName>IronJS.Dev</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
<Name>IronJS.Console</Name>
|
||||
<Name>IronJS.Dev</Name>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -23,18 +23,18 @@
|
|||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DocumentationFile>bin\Debug\IronJS.Console.XML</DocumentationFile>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<Tailcalls>true</Tailcalls>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>
|
||||
</DefineConstants>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DocumentationFile>bin\Release\IronJS.Console.XML</DocumentationFile>
|
||||
<DocumentationFile>bin\Release\IronJS.Dev.XML</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -44,7 +44,7 @@
|
|||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>bin\Debug\IronJS.Console.XML</DocumentationFile>
|
||||
<DocumentationFile>bin\Debug\IronJS.Dev.XML</DocumentationFile>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
|
@ -52,19 +52,21 @@
|
|||
<Optimize>true</Optimize>
|
||||
<Tailcalls>true</Tailcalls>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>
|
||||
</DefineConstants>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<DocumentationFile>bin\Release\IronJS.Dev.XML</DocumentationFile>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="!Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition=" Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.fs" />
|
||||
<None Include="Testing.html" />
|
||||
<Content Include="Todo.txt" />
|
||||
<None Include="Script.fsx" />
|
||||
<Content Include="Testing.js" />
|
||||
<Content Include="Script.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib" />
|
||||
|
@ -72,14 +74,21 @@
|
|||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<ProjectReference Include="..\IronJS.Parser\IronJS.Parser.csproj">
|
||||
<Name>IronJS.Parser</Name>
|
||||
<Project>{fa54cac0-57bd-4ad0-b5fb-4e743bfd4d73}</Project>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IronJS.Compiler\IronJS.Compiler.fsproj">
|
||||
<Name>IronJS.Compiler</Name>
|
||||
<Project>{81bfb688-1621-42d6-9062-093865a185d3}</Project>
|
||||
<Private>True</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\IronJS.Runtime\IronJS.Runtime.fsproj">
|
||||
<Name>IronJS.Runtime</Name>
|
||||
<Project>{ba1d9fb7-b9eb-4f11-9148-1c0bfdf8c74e}</Project>
|
||||
<Private>True</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\IronJS\IronJS.fsproj">
|
||||
<Name>IronJS</Name>
|
||||
<Project>{fa738790-5b9b-4977-8c6b-ef487f24e435}</Project>
|
||||
<Project>{9e257324-94e7-49af-ae83-718288e925d8}</Project>
|
||||
<Private>True</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
|
@ -0,0 +1,20 @@
|
|||
namespace IronJS.Dev
|
||||
|
||||
module Main =
|
||||
|
||||
open System
|
||||
open IronJS
|
||||
open IronJS.Compiler
|
||||
open IronJS.Compiler.Core
|
||||
|
||||
let main () =
|
||||
|
||||
let ctx = IronJS.Hosting.Context.Create()
|
||||
|
||||
ctx.PutGlobal("print",
|
||||
ctx.CreateDelegateFunction(
|
||||
new Action<string>(Console.WriteLine)))
|
||||
|
||||
ctx.ExecuteFile @"Script.js"
|
||||
|
||||
main() |> ignore
|
|
@ -0,0 +1,24 @@
|
|||
#light
|
||||
#time
|
||||
#r @"FSharp.PowerPack"
|
||||
#r @"../../Lib/Antlr3.Runtime.dll"
|
||||
#r @"../../Lib/Xebic.ES3.dll"
|
||||
#r @"../../Lib/Microsoft.Dynamic.dll"
|
||||
#r @"../IronJS/bin/Debug/IronJS.dll"
|
||||
#r @"../IronJS.Compiler/bin/Debug/IronJS.Compiler.dll"
|
||||
#r @"../IronJS.Runtime/bin/Debug/IronJS.Runtime.dll"
|
||||
|
||||
open System
|
||||
open IronJS
|
||||
|
||||
IO.Directory.SetCurrentDirectory(
|
||||
@"C:\Users\fredrikhm\Personal\IronJS\Src\IronJS.REPL")
|
||||
|
||||
let ctx = IronJS.Hosting.Context.Create()
|
||||
|
||||
ctx.PutGlobal("print",
|
||||
ctx.CreateDelegateFunction(
|
||||
new Action<string>(Console.WriteLine)))
|
||||
|
||||
let cmp = ctx.CompileFile @"Script.js"
|
||||
let r = ctx.InvokeCompiled cmp
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,20 @@
|
|||
TODO:
|
||||
* eval
|
||||
* arguments object
|
||||
* static typing
|
||||
* objects
|
||||
* wrapping .net delegates in js objects
|
||||
|
||||
DONE:
|
||||
* delete
|
||||
* with
|
||||
* this
|
||||
* arrays
|
||||
* new operator
|
||||
* to many/to few args invocation
|
||||
* array .length property
|
||||
* passing Box byref
|
||||
* try/catch, exceptions
|
||||
* StaticExpr for Dlr.Expr
|
||||
* break/continue and labels
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
using Antlr.Runtime;
|
||||
|
||||
namespace IronJS.Parser
|
||||
{
|
||||
using IToken = Antlr.Runtime.IToken;
|
||||
|
||||
/// <summary>
|
||||
/// This partial class is complementary to the lexer generated with ANTLR from the JavaScript.g grammar.
|
||||
/// It implements the actions used in the lexer.
|
||||
/// </summary>
|
||||
public partial class ES3Lexer
|
||||
{
|
||||
/// <summary>
|
||||
/// Containts the last on channel token.
|
||||
/// </summary>
|
||||
protected IToken last;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether regular expression (yields true) or division expression recognition (false) in the lexer is enabled.
|
||||
/// These are mutual exclusive and the decision which is active in the lexer is based on the previous on channel token.
|
||||
/// When the previous token can be identified as a possible left operand for a division this results in false, otherwise true.
|
||||
/// </summary>
|
||||
private bool AreRegularExpressionsEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
if (last == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (last.Type)
|
||||
{
|
||||
// identifier
|
||||
case Identifier:
|
||||
// literals
|
||||
case NULL:
|
||||
case TRUE:
|
||||
case FALSE:
|
||||
case THIS:
|
||||
case OctalIntegerLiteral:
|
||||
case DecimalLiteral:
|
||||
case HexIntegerLiteral:
|
||||
case StringLiteral:
|
||||
// member access ending
|
||||
case RBRACK:
|
||||
// function call or nested expression ending
|
||||
case RPAREN:
|
||||
return false;
|
||||
|
||||
// otherwise OK
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Consumes an unicode identifier after validating that the first character can be the starting character.
|
||||
/// This method is called by the lexer logic as fallback alternative when a character can not be considered as start of an identifier in the ASCII range.
|
||||
/// See the Identfier lexer rule for more details.
|
||||
/// </summary>
|
||||
private void ConsumeIdentifierUnicodeStart()
|
||||
{
|
||||
int ch = (char)input.LA(1);
|
||||
if (IsIdentifierStartUnicode(ch))
|
||||
{
|
||||
MatchAny();
|
||||
do
|
||||
{
|
||||
ch = (char)input.LA(1);
|
||||
if (ch == '$' || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || ch == '\\' || ch == '_' || (ch >= 'a' && ch <= 'z') || IsIdentifierPartUnicode(ch))
|
||||
{
|
||||
mIdentifierPart();
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NoViableAltException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether a given character can be a part of an unicode identifier.
|
||||
/// This method doesn't consider ASCII characters that can be a part of an identifier, that is left to the mIdentifierPart method.
|
||||
/// The latter method will call this method to check other characters in the unicode range after evaluating those in the ASCII range.
|
||||
/// </summary>
|
||||
/// <param name="ch">The character to check.</param>
|
||||
/// <returns>True when the character matches, false otherwise.</returns>
|
||||
public static bool IsIdentifierPartUnicode(int ch)
|
||||
{
|
||||
switch (Char.GetUnicodeCategory((char)ch))
|
||||
{
|
||||
// UnicodeLetter
|
||||
case UnicodeCategory.UppercaseLetter: // Lu
|
||||
case UnicodeCategory.LowercaseLetter: // Ll
|
||||
case UnicodeCategory.TitlecaseLetter: // Lt
|
||||
case UnicodeCategory.ModifierLetter: // Lm
|
||||
case UnicodeCategory.OtherLetter: // Lo
|
||||
case UnicodeCategory.LetterNumber: // Nl
|
||||
// UnicodeCombiningMark
|
||||
case UnicodeCategory.NonSpacingMark: // Mn
|
||||
case UnicodeCategory.SpacingCombiningMark: // Mc
|
||||
// UnicodeDigit
|
||||
case UnicodeCategory.DecimalDigitNumber: // Nd
|
||||
// UnicodeConnectorPuntuation
|
||||
case UnicodeCategory.ConnectorPunctuation: // Pc
|
||||
return true;
|
||||
|
||||
// Not matching
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether a given character can be the first character of an unicode identifier.
|
||||
/// This method doesn't consider ASCII characters as it is used in a fallback scenario after the ASCII range is evaluated.
|
||||
/// </summary>
|
||||
/// <param name="ch">The character to check.</param>
|
||||
/// <returns>True when the character matches, false otherwise.</returns>
|
||||
public static bool IsIdentifierStartUnicode(int ch)
|
||||
{
|
||||
switch (Char.GetUnicodeCategory((char)ch))
|
||||
{
|
||||
// UnicodeLetter
|
||||
case UnicodeCategory.UppercaseLetter: // Lu
|
||||
case UnicodeCategory.LowercaseLetter: // Ll
|
||||
case UnicodeCategory.TitlecaseLetter: // Lt
|
||||
case UnicodeCategory.ModifierLetter: // Lm
|
||||
case UnicodeCategory.OtherLetter: // Lo
|
||||
case UnicodeCategory.LetterNumber: // Nl
|
||||
return true;
|
||||
|
||||
// Not matching
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override of base to track previous on channel token.
|
||||
/// This token is needed as input to decide whether regular expression or division expression recognition is enabled.
|
||||
/// </summary>
|
||||
public override IToken NextToken()
|
||||
{
|
||||
IToken result = base.NextToken();
|
||||
if (result.Channel == Token.DEFAULT_CHANNEL)
|
||||
{
|
||||
last = result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,174 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using Antlr.Runtime;
|
||||
using Antlr.Runtime.Tree;
|
||||
|
||||
namespace IronJS.Parser
|
||||
{
|
||||
using IToken = Antlr.Runtime.IToken;
|
||||
|
||||
/// <summary>
|
||||
/// This partial class is complementary to the parser generated with ANTLR from the JavaScript.g grammar.
|
||||
/// It implements the actions used in the parser.
|
||||
/// </summary>
|
||||
public partial class ES3Parser
|
||||
{
|
||||
/// <summary>
|
||||
/// Is a RuleReturnScope node candidate for the left-hand-side of an assignment expression?
|
||||
/// </summary>
|
||||
/// <param name="lhs">The RuleReturnScope node</param>
|
||||
/// <param name="cached">The cached result of a former call to this method</param>
|
||||
/// <returns>True if so, false otherwise</returns>
|
||||
public bool IsLeftHandSideAssign(RuleReturnScope lhs, ref bool? cached)
|
||||
{
|
||||
if (cached.HasValue)
|
||||
{
|
||||
return cached.Value;
|
||||
}
|
||||
|
||||
bool result;
|
||||
if (IsLeftHandSideExpression(lhs))
|
||||
{
|
||||
switch (input.LA(1))
|
||||
{
|
||||
case ASSIGN:
|
||||
case MULASS:
|
||||
case DIVASS:
|
||||
case MODASS:
|
||||
case ADDASS:
|
||||
case SUBASS:
|
||||
case SHLASS:
|
||||
case SHRASS:
|
||||
case SHUASS:
|
||||
case ANDASS:
|
||||
case XORASS:
|
||||
case ORASS:
|
||||
result = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
cached = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is a RuleReturnScope node candidate a left-hand-side expression?
|
||||
/// </summary>
|
||||
/// <param name="lhs">The RuleReturnScope node</param>
|
||||
/// <returns>True if so, false otherwise</returns>
|
||||
private bool IsLeftHandSideExpression(RuleReturnScope lhs)
|
||||
{
|
||||
if (lhs.Tree == null) // e.g. during backtracking
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (((ITree)lhs.Tree).Type)
|
||||
{
|
||||
// primaryExpression
|
||||
case THIS:
|
||||
case Identifier:
|
||||
case NULL:
|
||||
case TRUE:
|
||||
case FALSE:
|
||||
case DecimalLiteral:
|
||||
case OctalIntegerLiteral:
|
||||
case HexIntegerLiteral:
|
||||
case StringLiteral:
|
||||
case RegularExpressionLiteral:
|
||||
case ARRAY:
|
||||
case OBJECT:
|
||||
case PAREXPR:
|
||||
// functionExpression
|
||||
case FUNCTION:
|
||||
// newExpression
|
||||
case NEW:
|
||||
// leftHandSideExpression
|
||||
case CALL:
|
||||
case BYFIELD:
|
||||
case BYINDEX:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is a RuleReturnScope node candidate for the left-hand-side of an in expression?
|
||||
/// </summary>
|
||||
/// <param name="lhs">The RuleReturnScope node</param>
|
||||
/// <param name="cached">The cached result of a former call to this method</param>
|
||||
/// <returns>True if so, false otherwise</returns>
|
||||
public bool IsLeftHandSideIn(RuleReturnScope lhs, ref bool? cached)
|
||||
{
|
||||
if (cached.HasValue)
|
||||
{
|
||||
return cached.Value;
|
||||
}
|
||||
|
||||
bool result = IsLeftHandSideExpression(lhs) && (input.LA(1) == IN);
|
||||
|
||||
cached = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method handles promotion of an EOL token to on channel in situations where the ECMA 3 specification
|
||||
/// states there should be a semicolon inserted because of an EOL between the current (offending) token
|
||||
/// and the previous token.
|
||||
/// So an semicolon is not actually inserted but the EOL present is switched from off to on channel. In this
|
||||
/// way that EOL gets the notion of an "virtual" semicolon.
|
||||
/// As a side effect a given rule's return scope starting point is set to the found EOL and the input stream is repositioned on it.
|
||||
/// A multi line comment with an EOL is also promoted.
|
||||
/// </summary>
|
||||
/// <param name="rule">The invoking rule's return scope</param>
|
||||
public void PromoteEOL(ParserRuleReturnScope rule)
|
||||
{
|
||||
// Get current token and its type (the possibly offending token).
|
||||
IToken lt = input.LT(1);
|
||||
int la = lt.Type;
|
||||
|
||||
// We only need to promote an EOL when the current token is offending (not a SEMIC, EOF, RBRACE or EOL).
|
||||
// Promoting an EOL means switching it from off channel to on channel.
|
||||
if (!(la == SEMIC || la == EOF || la == RBRACE || la == EOL))
|
||||
{
|
||||
// Start on the possition before the current token and scan backwards off channel tokens until the previous on channel token.
|
||||
for (int ix = lt.TokenIndex - 1; ix > 0; ix--)
|
||||
{
|
||||
lt = input.Get(ix);
|
||||
if (lt.Channel == Token.DEFAULT_CHANNEL)
|
||||
{
|
||||
// On channel token found: stop scanning.
|
||||
break;
|
||||
}
|
||||
else if (lt.Type == EOL || (lt.Type == MultiLineComment && Regex.IsMatch(lt.Text, "/.*\r\n|\r|\n")))
|
||||
{
|
||||
// We found our EOL: promote it to on channel, position the input on it and reset the rule start.
|
||||
lt.Channel = Token.DEFAULT_CHANNEL;
|
||||
input.Seek(lt.TokenIndex);
|
||||
if (rule != null)
|
||||
{
|
||||
rule.Start = lt;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,65 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{FA54CAC0-57BD-4AD0-B5FB-4E743BFD4D73}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>IronJS.Parser</RootNamespace>
|
||||
<AssemblyName>IronJS.Parser</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>
|
||||
</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Antlr3.Runtime">
|
||||
<HintPath>..\Dependencies\Antlr3.Runtime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ES3Lexer.Action.cs" />
|
||||
<Compile Include="ES3Lexer.cs" />
|
||||
<Compile Include="ES3Parser.Action.cs" />
|
||||
<Compile Include="ES3Parser.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="LICENSE.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -1,36 +0,0 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("IronJS.Parser")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("IronJS.Parser")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("7be0c915-5293-4b45-bbaa-592b0bca97cf")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,122 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{0f78334f-ea74-4c5c-8232-b7d329be2226}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>IronJS.REPL</RootNamespace>
|
||||
<AssemblyName>IronJS.REPL</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
<Name>IronJS.REPL</Name>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<Tailcalls>false</Tailcalls>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DocumentationFile>bin\Debug\IronJS.REPL.XML</DocumentationFile>
|
||||
<EnableUnmanagedDebugging>true</EnableUnmanagedDebugging>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<Tailcalls>true</Tailcalls>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>
|
||||
</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DocumentationFile>bin\Release\IronJS.REPL.XML</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<Tailcalls>false</Tailcalls>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<Tailcalls>true</Tailcalls>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>
|
||||
</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<Tailcalls>false</Tailcalls>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile />
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<Tailcalls>true</Tailcalls>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>bin\Release\IronJS.REPL.XML</DocumentationFile>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="!Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition=" Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.fs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="FSharp.Core" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<ProjectReference Include="..\IronJS.Compiler\IronJS.Compiler.fsproj">
|
||||
<Name>IronJS.Compiler</Name>
|
||||
<Project>{81bfb688-1621-42d6-9062-093865a185d3}</Project>
|
||||
<Private>True</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\IronJS.Runtime\IronJS.Runtime.fsproj">
|
||||
<Name>IronJS.Runtime</Name>
|
||||
<Project>{ba1d9fb7-b9eb-4f11-9148-1c0bfdf8c74e}</Project>
|
||||
<Private>True</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\IronJS\IronJS.fsproj">
|
||||
<Name>IronJS</Name>
|
||||
<Project>{9e257324-94e7-49af-ae83-718288e925d8}</Project>
|
||||
<Private>True</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,29 @@
|
|||
namespace IronJS.REPL
|
||||
|
||||
module Main =
|
||||
|
||||
open System
|
||||
open IronJS
|
||||
open IronJS.Compiler
|
||||
open IronJS.Compiler.Core
|
||||
|
||||
let main () =
|
||||
|
||||
let console =
|
||||
Seq.initInfinite (fun _ -> printf ">>> "; Console.ReadLine())
|
||||
|
||||
let ctx =
|
||||
Hosting.Context.Create()
|
||||
|
||||
let toString : Box -> string = TypeConverter.toString
|
||||
|
||||
printfn "IronJS v%s" IronJS.Version.String
|
||||
printfn "Type #exit to quit"
|
||||
|
||||
console |> Seq.find (fun cmd ->
|
||||
match cmd with
|
||||
| "#exit" -> true
|
||||
| _ -> printfn "%s" (toString(Utils.box (ctx.Execute cmd))); false
|
||||
)
|
||||
|
||||
main() |> ignore
|
|
@ -0,0 +1,112 @@
|
|||
namespace IronJS.Native
|
||||
|
||||
open System
|
||||
open IronJS
|
||||
open IronJS.Compiler
|
||||
open IronJS.Aliases
|
||||
|
||||
module Global =
|
||||
|
||||
//15.1.2.1
|
||||
let eval (target:Compiler.EvalTarget) =
|
||||
match target.Target.Type with
|
||||
| TypeCodes.String ->
|
||||
let tree =
|
||||
Ast.LocalScope(
|
||||
{Ast.Scope.New with Closures=target.Closures},
|
||||
Ast.Parsers.Ecma3.parse target.Target.String
|
||||
)
|
||||
|
||||
let levels =
|
||||
Some(
|
||||
target.GlobalLevel,
|
||||
target.ClosureLevel,
|
||||
target.LocalLevel)
|
||||
|
||||
let compiled =
|
||||
Core.compile {
|
||||
Ast = Ast.applyAnalyzers tree levels
|
||||
TargetMode = TargetMode.Eval
|
||||
Delegate = None
|
||||
Environment = target.Function.Env
|
||||
}
|
||||
|
||||
Utils.box (
|
||||
compiled.DynamicInvoke(
|
||||
target.Function,
|
||||
target.This,
|
||||
target.Local,
|
||||
target.ScopeChain,
|
||||
target.DynamicChain))
|
||||
|
||||
| _ -> target.Target
|
||||
|
||||
//15.1.2.2
|
||||
let parseInt (str:IjsStr) =
|
||||
Utils.boxDouble (double (System.Int32.Parse(str)))
|
||||
|
||||
//15.1.2.3
|
||||
let parseFloat (str:IjsStr) =
|
||||
Utils.boxDouble (TypeConverter.toNumber str)
|
||||
|
||||
//15.1.2.4
|
||||
let isNaN (number:IjsNum) =
|
||||
Utils.boxBool (number = Double.NaN)
|
||||
|
||||
//15.1.2.5
|
||||
let isFinite (number:IjsNum) =
|
||||
Utils.boxBool (
|
||||
not(
|
||||
number = Double.NaN
|
||||
|| number = Double.PositiveInfinity
|
||||
|| number = Double.NegativeInfinity
|
||||
))
|
||||
|
||||
//15.1.1
|
||||
let create (env:IjsEnv) =
|
||||
//It's a g-thing.
|
||||
let g = IjsObj(env.Base_Class, env.Object_prototype, Classes.Object, 0u)
|
||||
|
||||
//15.1.1.1
|
||||
Api.Object.putProperty(g, "NaN",
|
||||
NaN, PropertyAttrs.DontDelete ||| PropertyAttrs.DontEnum)
|
||||
|
||||
//15.1.1.2
|
||||
Api.Object.putProperty(g, "Infinity",
|
||||
PosInf, PropertyAttrs.DontDelete ||| PropertyAttrs.DontEnum)
|
||||
|
||||
//15.1.1.3
|
||||
Api.Object.putProperty(g, "undefined",
|
||||
Undefined.Instance, PropertyAttrs.DontDelete ||| PropertyAttrs.DontEnum)
|
||||
|
||||
//15.1.2.1
|
||||
Api.Object.putProperty(
|
||||
g, "eval",
|
||||
Api.DelegateFunction<_>.create(
|
||||
env, new Func<Compiler.EvalTarget, IjsBox>(eval)), PropertyAttrs.All)
|
||||
|
||||
//15.1.2.3
|
||||
Api.Object.putProperty(
|
||||
g, "parseFloat",
|
||||
Api.DelegateFunction<_>.create(
|
||||
env, new Func<IjsStr, IjsBox>(parseFloat)), PropertyAttrs.All)
|
||||
|
||||
//15.1.2.3
|
||||
Api.Object.putProperty(
|
||||
g, "parseInt",
|
||||
Api.DelegateFunction<_>.create(
|
||||
env, new Func<IjsStr, IjsBox>(parseInt)), PropertyAttrs.All)
|
||||
|
||||
//15.1.2.4
|
||||
Api.Object.putProperty(
|
||||
g, "isNaN",
|
||||
Api.DelegateFunction<_>.create(
|
||||
env, new Func<IjsNum, IjsBox>(isNaN)), PropertyAttrs.All)
|
||||
|
||||
//15.1.2.5
|
||||
Api.Object.putProperty(
|
||||
g, "isFinite",
|
||||
Api.DelegateFunction<_>.create(
|
||||
env, new Func<IjsNum, IjsBox>(isFinite)), PropertyAttrs.All)
|
||||
|
||||
g
|
|
@ -0,0 +1,105 @@
|
|||
namespace IronJS
|
||||
|
||||
open System
|
||||
open IronJS
|
||||
|
||||
module Hosting =
|
||||
|
||||
let createEnvironment () =
|
||||
let x = IjsEnv()
|
||||
x.Base_Class <- PropertyClass(x)
|
||||
|
||||
//.prototype Property class
|
||||
x.Prototype_Class <-
|
||||
Api.PropertyClass.subClass(x.Base_Class, "constructor")
|
||||
|
||||
//Array property class
|
||||
x.Array_Class <-
|
||||
Api.PropertyClass.subClass(x.Base_Class, ["length"])
|
||||
|
||||
//Function property class
|
||||
x.Function_Class <-
|
||||
Api.PropertyClass.subClass(x.Base_Class, ["length"; "prototype"])
|
||||
|
||||
x.Object_prototype <- Native.Object.createObjectPrototype(x)
|
||||
x.Globals <- Native.Global.create x
|
||||
|
||||
//Boxed bools
|
||||
x.Boxed_False.Bool <- false
|
||||
x.Boxed_False.Type <- TypeCodes.Bool
|
||||
x.Boxed_True.Bool <- true
|
||||
x.Boxed_True.Type <- TypeCodes.Bool
|
||||
|
||||
//Boxed doubles
|
||||
x.Boxed_NegOne.Double <- -1.0
|
||||
x.Boxed_NegOne.Type <- TypeCodes.Number
|
||||
x.Boxed_Zero.Double <- 0.0
|
||||
x.Boxed_Zero.Type <- TypeCodes.Number
|
||||
x.Boxed_One.Double <- 1.0
|
||||
x.Boxed_One.Type <- TypeCodes.Number
|
||||
x.Boxed_NaN.Double <- System.Double.NaN
|
||||
x.Boxed_NaN.Type <- TypeCodes.Number
|
||||
|
||||
//Boxed null
|
||||
x.Boxed_Null.Clr <- null
|
||||
x.Boxed_Null.Type <- TypeCodes.Clr
|
||||
|
||||
//Boxed empty string
|
||||
x.Boxed_EmptyString.Clr <- ""
|
||||
x.Boxed_EmptyString.Type <- TypeCodes.String
|
||||
|
||||
//Boxed undefined
|
||||
x.Boxed_Undefined.Clr <- Undefined.Instance
|
||||
x.Boxed_Undefined.Type <- TypeCodes.Undefined
|
||||
|
||||
//Temp boxes
|
||||
x.Temp_Bool.Type <- TypeCodes.Bool
|
||||
x.Temp_Number.Type <- TypeCodes.Number
|
||||
x.Temp_Clr.Type <- TypeCodes.Clr
|
||||
x.Temp_String.Type <- TypeCodes.String
|
||||
x.Temp_Function.Type <- TypeCodes.Function
|
||||
x.Temp_Object.Type <- TypeCodes.Object
|
||||
|
||||
x
|
||||
|
||||
type Context(env:IjsEnv) =
|
||||
|
||||
let globalFunc = new IronJS.Function(env)
|
||||
|
||||
member x.Environment = env
|
||||
member x.GlobalFunc = globalFunc
|
||||
|
||||
member x.CompileFile fileName =
|
||||
let tree = Ast.Parsers.Ecma3.parseGlobalFile fileName
|
||||
let analyzed = Ast.applyAnalyzers tree None
|
||||
#if DEBUG
|
||||
printfn "%A" tree
|
||||
printfn "%A" analyzed
|
||||
#endif
|
||||
Compiler.Core.compileAsGlobal env analyzed
|
||||
|
||||
member x.CompileSource source =
|
||||
let tree = Ast.Parsers.Ecma3.parseGlobalSource source
|
||||
let analyzed = Ast.applyAnalyzers tree None
|
||||
Compiler.Core.compileAsGlobal env analyzed
|
||||
|
||||
member x.InvokeCompiled (compiled:Delegate) =
|
||||
compiled.DynamicInvoke(globalFunc, env.Globals)
|
||||
|
||||
member x.ExecuteFile fileName =
|
||||
x.InvokeCompiled (x.CompileFile fileName)
|
||||
|
||||
member x.Execute source =
|
||||
x.InvokeCompiled (x.CompileSource source)
|
||||
|
||||
member x.PutGlobal (name, value) =
|
||||
Api.Object.putProperty(env.Globals, name, value, PropertyAttrs.All)
|
||||
|
||||
member x.GetGlobal name =
|
||||
Api.Object.getProperty(env.Globals, name)
|
||||
|
||||
member x.CreateDelegateFunction delegate' =
|
||||
Api.DelegateFunction<'a>.create(env, delegate')
|
||||
|
||||
static member Create () =
|
||||
new Context(createEnvironment())
|
|
@ -0,0 +1,112 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{ba1d9fb7-b9eb-4f11-9148-1c0bfdf8c74e}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>IronJS.Runtime</RootNamespace>
|
||||
<AssemblyName>IronJS.Runtime</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<Name>IronJS.Runtime</Name>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<Tailcalls>false</Tailcalls>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>bin\Debug\IronJS.Runtime.XML</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<Tailcalls>true</Tailcalls>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>bin\Release\IronJS.Runtime.XML</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<Tailcalls>false</Tailcalls>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>bin\Debug\IronJS.Runtime.XML</DocumentationFile>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<Tailcalls>true</Tailcalls>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>bin\Release\IronJS.Runtime.XML</DocumentationFile>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<Tailcalls>false</Tailcalls>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<Tailcalls>true</Tailcalls>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>bin\Release\IronJS.Runtime.XML</DocumentationFile>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="FSharp.Core" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Numerics" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Utils.fs" />
|
||||
<Compile Include="Global.fs" />
|
||||
<Compile Include="Math.fs" />
|
||||
<Compile Include="Object.fs" />
|
||||
<Compile Include="Hosting.fs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IronJS.Compiler\IronJS.Compiler.fsproj">
|
||||
<Name>IronJS.Compiler</Name>
|
||||
<Project>{81bfb688-1621-42d6-9062-093865a185d3}</Project>
|
||||
<Private>True</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\IronJS\IronJS.fsproj">
|
||||
<Name>IronJS</Name>
|
||||
<Project>{9e257324-94e7-49af-ae83-718288e925d8}</Project>
|
||||
<Private>True</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="!Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition=" Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,47 @@
|
|||
namespace IronJS.Native
|
||||
|
||||
open System
|
||||
open IronJS
|
||||
|
||||
module Math =
|
||||
|
||||
let createMathObject prototype =
|
||||
|
||||
let math = new IjsObj()
|
||||
|
||||
math.Class <- Classes.Math
|
||||
math.Prototype <- prototype
|
||||
|
||||
//15.8.1.1 E
|
||||
Api.Object.putProperty(
|
||||
math, "E", Math.E, PropertyAttrs.All)
|
||||
|
||||
//15.8.1.2 LN10
|
||||
Api.Object.putProperty(
|
||||
math, "LN10", 2.302585092994046, PropertyAttrs.All)
|
||||
|
||||
//15.8.1.3 LN2
|
||||
Api.Object.putProperty(
|
||||
math, "LN2", 0.6931471805599453, PropertyAttrs.All)
|
||||
|
||||
//15.8.1.4 LOG2E
|
||||
Api.Object.putProperty(
|
||||
math, "LOG2E", 1.4426950408889634, PropertyAttrs.All)
|
||||
|
||||
//15.8.1.5 LOG10E
|
||||
Api.Object.putProperty(
|
||||
math, "LOG10E", 0.4342944819032518, PropertyAttrs.All)
|
||||
|
||||
//15.8.1.6 PI
|
||||
Api.Object.putProperty(
|
||||
math, "PI", Math.PI, PropertyAttrs.All)
|
||||
|
||||
//15.8.1.7 SQRT1_2
|
||||
Api.Object.putProperty(
|
||||
math, "SQRT1_2", 0.7071067811865476, PropertyAttrs.All)
|
||||
|
||||
//15.8.1.8 SQRT2
|
||||
Api.Object.putProperty(
|
||||
math, "SQRT2", 1.4142135623730951, PropertyAttrs.All)
|
||||
|
||||
math
|
|
@ -0,0 +1,81 @@
|
|||
namespace IronJS.Native
|
||||
|
||||
open System
|
||||
open IronJS
|
||||
|
||||
module Object =
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//15.2.4.2
|
||||
let toString (o:IjsObj) =
|
||||
sprintf "[object %s]" Classes.Names.[o.Class]
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//15.2.4.3
|
||||
let toLocaleString = toString
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//15.2.4.4
|
||||
let valueOf (o:IjsObj) = o
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//15.2.4.5
|
||||
let hasOwnProperty (o:IjsObj) (name:IjsStr) =
|
||||
let mutable i = 0
|
||||
if Api.Object.getOwnPropertyIndex(o, name, &i)
|
||||
then o.PropertyValues.[i].Type <> TypeCodes.Empty
|
||||
else
|
||||
if name.Length > 0 && (name.[0] < '0' || name.[0] > '9') then false
|
||||
else
|
||||
let mutable i = Index.Min
|
||||
if not (Utils.isStringIndex(name, &i)) then false
|
||||
elif Utils.isDense o
|
||||
then i < o.IndexLength && o.IndexValues.[int i].Type <> TypeCodes.Empty
|
||||
else o.IndexSparse.ContainsKey i
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//15.2.4.6
|
||||
let isPrototypeOf (o:IjsObj) (v:IjsObj) =
|
||||
v.Prototype = o
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//15.2.4
|
||||
let createObjectPrototype (env:IjsEnv) =
|
||||
|
||||
let o = IjsObj(env.Base_Class, null, Classes.Object, 0u)
|
||||
|
||||
//15.2.4.2
|
||||
Api.Object.putProperty(
|
||||
o, "toString",
|
||||
Api.DelegateFunction<_>.create(
|
||||
env, new Func<IjsObj, IjsStr>(toString)), PropertyAttrs.All)
|
||||
|
||||
//15.2.4.3
|
||||
Api.Object.putProperty(
|
||||
o, "toLocaleString",
|
||||
Api.DelegateFunction<_>.create(
|
||||
env, new Func<IjsObj, IjsStr>(toLocaleString)), PropertyAttrs.All)
|
||||
|
||||
//15.2.4.4
|
||||
Api.Object.putProperty(
|
||||
o, "valueOf",
|
||||
Api.DelegateFunction<_>.create(
|
||||
env, new Func<IjsObj, IjsObj>(valueOf)), PropertyAttrs.All)
|
||||
|
||||
//15.2.4.5
|
||||
Api.Object.putProperty(
|
||||
o, "hasOwnProperty",
|
||||
Api.DelegateFunction<_>.create(
|
||||
env, new Func<IjsObj, IjsStr, IjsBool>(hasOwnProperty)),
|
||||
PropertyAttrs.All)
|
||||
|
||||
//15.2.4.6
|
||||
Api.Object.putProperty(
|
||||
o, "isPrototypeOf",
|
||||
Api.DelegateFunction<_>.create(
|
||||
env, new Func<IjsObj, IjsObj, IjsBool>(isPrototypeOf)),
|
||||
PropertyAttrs.All)
|
||||
|
||||
o
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
namespace IronJS.Runtime
|
||||
|
||||
open IronJS
|
||||
|
||||
module Utils =
|
||||
|
||||
let createDeleateFunc env x =
|
||||
Api.DelegateFunction<_>.create(env, x)
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{f5b7a320-be95-4cef-9169-0a84b9f6c60b}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>IronJS.Tests</RootNamespace>
|
||||
<AssemblyName>IronJS.Tests</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
<Name>IronJS.Tests</Name>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<Tailcalls>false</Tailcalls>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DocumentationFile>bin\Debug\IronJS.Tests.XML</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<Tailcalls>true</Tailcalls>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DocumentationFile>bin\Release\IronJS.Tests.XML</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<Tailcalls>false</Tailcalls>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>bin\Debug\IronJS.Tests.XML</DocumentationFile>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<Tailcalls>true</Tailcalls>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>bin\Release\IronJS.Tests.XML</DocumentationFile>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<Tailcalls>false</Tailcalls>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<Tailcalls>true</Tailcalls>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>
|
||||
</DefineConstants>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="!Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition=" Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
|
||||
<ItemGroup>
|
||||
<Compile Include="Runner.fs" />
|
||||
<Compile Include="Program.fs" />
|
||||
<Content Include="function.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="with.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="eval.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="exception.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="break.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="FSharp.Core" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<ProjectReference Include="..\IronJS.Compiler\IronJS.Compiler.fsproj">
|
||||
<Name>IronJS.Compiler</Name>
|
||||
<Project>{81bfb688-1621-42d6-9062-093865a185d3}</Project>
|
||||
<Private>True</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\IronJS.Runtime\IronJS.Runtime.fsproj">
|
||||
<Name>IronJS.Runtime</Name>
|
||||
<Project>{ba1d9fb7-b9eb-4f11-9148-1c0bfdf8c74e}</Project>
|
||||
<Private>True</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\IronJS\IronJS.fsproj">
|
||||
<Name>IronJS</Name>
|
||||
<Project>{9e257324-94e7-49af-ae83-718288e925d8}</Project>
|
||||
<Private>True</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,10 @@
|
|||
//Unit Tests
|
||||
IronJS.Tests.Runner.run "function.js" true
|
||||
IronJS.Tests.Runner.run "with.js" true
|
||||
IronJS.Tests.Runner.run "exception.js" true
|
||||
IronJS.Tests.Runner.run "break.js" true
|
||||
IronJS.Tests.Runner.run "eval.js" true
|
||||
|
||||
//Wait
|
||||
System.Console.WriteLine("Press [Enter]");
|
||||
System.Console.ReadLine() |> ignore
|
|
@ -0,0 +1,71 @@
|
|||
namespace IronJS.Tests
|
||||
|
||||
open System
|
||||
open IronJS
|
||||
open IronJS.Compiler
|
||||
open IronJS.Compiler.Core
|
||||
open Microsoft.VisualStudio.TestTools.UnitTesting
|
||||
|
||||
module Runner =
|
||||
|
||||
let setupEnv () =
|
||||
let ctx = Hosting.Context.Create()
|
||||
let env = ctx.Environment
|
||||
|
||||
let assertSame (a:IronJS.Object) (b:IronJS.Object) (msg:string) = Assert.AreSame(a, b, msg)
|
||||
let assertNotSame (a:IronJS.Object) (b:IronJS.Object) (msg:string) = Assert.AreNotSame(a, b, msg)
|
||||
|
||||
let assertEqual (a:IronJS.Box) (b:IronJS.Box) (msg:string) =
|
||||
Assert.AreEqual(a, b, msg)
|
||||
|
||||
let assertNotEqual (a:IronJS.Box) (b:IronJS.Box) (msg:string) = Assert.AreNotEqual(a, b, msg)
|
||||
let assertTrue (a:bool) (msg:string) = Assert.IsTrue(a, msg)
|
||||
let assertFalse (a:bool) (msg:string) = Assert.IsFalse(a, msg)
|
||||
|
||||
Api.Object.putProperty(env.Globals, "assertEqual", Api.DelegateFunction.create(env, new Action<IronJS.Box, IronJS.Box, string>(assertEqual))) |> ignore
|
||||
Api.Object.putProperty(env.Globals, "assertNotEqual", Api.DelegateFunction.create(env, new Action<IronJS.Box, IronJS.Box, string>(assertNotEqual))) |> ignore
|
||||
Api.Object.putProperty(env.Globals, "assertSame", Api.DelegateFunction.create(env, new Action<IronJS.Object, IronJS.Object, string>(assertSame))) |> ignore
|
||||
Api.Object.putProperty(env.Globals, "assertNotSame", Api.DelegateFunction.create(env, new Action<IronJS.Object, IronJS.Object, string>(assertNotSame))) |> ignore
|
||||
Api.Object.putProperty(env.Globals, "assertTrue", Api.DelegateFunction.create(env, new Action<bool, string>(assertTrue))) |> ignore
|
||||
Api.Object.putProperty(env.Globals, "assertFalse", Api.DelegateFunction.create(env, new Action<bool, string>(assertFalse))) |> ignore
|
||||
Api.Object.putProperty(env.Globals, "globals", env.Globals) |> ignore
|
||||
|
||||
env
|
||||
|
||||
let compileAndLoadTests (env:Environment) file =
|
||||
Api.Object.deleteOwnProperty(env.Globals, "tests")
|
||||
|> ignore
|
||||
|
||||
let tree = Ast.Parsers.Ecma3.parseGlobalFile file
|
||||
let analyzed = Ast.applyAnalyzers tree None
|
||||
let compiled = Compiler.Core.compileAsGlobal env analyzed
|
||||
|
||||
compiled.DynamicInvoke(new IronJS.Function(env), env.Globals)
|
||||
|> ignore
|
||||
|
||||
Api.Object.getProperty(env.Globals, "tests").Object, Api.Object.getProperty(env.Globals, "name").String
|
||||
|
||||
let run file catch =
|
||||
let env = setupEnv()
|
||||
let tests, name = compileAndLoadTests env file
|
||||
let results = IronJS.Aliases.MutableDict<string, string>();
|
||||
|
||||
for x in Api.Object.getOwnPropertyNames tests do
|
||||
let test = Api.Object.getProperty(tests, x).Func
|
||||
let compiled = test.Compiler.compileAs<Func<IronJS.Function, IronJS.Object, IronJS.Box>> test
|
||||
try
|
||||
compiled.Invoke(test, env.Globals) |> ignore
|
||||
results.Add(x, "Passed")
|
||||
with
|
||||
| ex when catch ->
|
||||
let msg =
|
||||
if ex.InnerException <> null
|
||||
then ex.InnerException.Message
|
||||
else ex.Message
|
||||
|
||||
results.Add(x, "Failed: " + msg)
|
||||
|
||||
printfn "### %s " name
|
||||
for x in results do
|
||||
printfn "%s - %s" x.Key x.Value
|
||||
printfn ""
|
|
@ -0,0 +1,83 @@
|
|||
var name = "Break/Continue/Label Tests";
|
||||
|
||||
var tests = {
|
||||
simpleBreak: function () {
|
||||
var x = 1;
|
||||
while (true) {
|
||||
x = x + 1;
|
||||
break;
|
||||
}
|
||||
assertEqual(x, 2, "x should equal 2");
|
||||
},
|
||||
|
||||
simpleContinue: function () {
|
||||
var x = 1;
|
||||
while (true) {
|
||||
x = x + 1;
|
||||
if (x < 3) continue;
|
||||
break;
|
||||
}
|
||||
assertEqual(x, 3, "x should equal 2");
|
||||
},
|
||||
|
||||
nestedBreaks: function () {
|
||||
var x = 1;
|
||||
|
||||
while (true) {
|
||||
x = x + 1;
|
||||
|
||||
while (true) {
|
||||
x = x + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
assertEqual(x, 3, "x should equal 3");
|
||||
},
|
||||
|
||||
nestedLabeledBreaks: function () {
|
||||
var x = 1;
|
||||
|
||||
outer: while (true) {
|
||||
x = x + 1;
|
||||
|
||||
inner: while (true) {
|
||||
x = x + 1;
|
||||
break inner;
|
||||
}
|
||||
|
||||
break outer;
|
||||
}
|
||||
|
||||
assertEqual(x, 3, "x should equal 3");
|
||||
},
|
||||
|
||||
nestedLabeledBreaksBreakingAllFromInner: function () {
|
||||
var x = 1;
|
||||
|
||||
outer: while (true) {
|
||||
x = x + 1;
|
||||
|
||||
inner: while (true) {
|
||||
x = x + 1;
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
|
||||
assertEqual(x, 3, "x should equal 3");
|
||||
},
|
||||
|
||||
breakingNonLoops: function () {
|
||||
var x = 1;
|
||||
|
||||
foo: if (true) {
|
||||
x = 2;
|
||||
break foo;
|
||||
x = 3;
|
||||
}
|
||||
|
||||
assertEqual(x, 2, "x should equal 3");
|
||||
}
|
||||
};
|
|
@ -0,0 +1,43 @@
|
|||
var name = "Eval Tests";
|
||||
|
||||
var tests = {
|
||||
setVarValueInside: function () {
|
||||
var x = 1;
|
||||
eval("x = 2");
|
||||
assertEqual(x, 2, "x should equal 2");
|
||||
},
|
||||
|
||||
defineVarInside: function () {
|
||||
var inner = function () {
|
||||
var y = 2;
|
||||
eval("var x = 2");
|
||||
assertEqual(y, 2, "y should equal 2");
|
||||
assertEqual(x, 2, "x should equal 2");
|
||||
}
|
||||
|
||||
inner();
|
||||
|
||||
assertEqual(y, undefined, "y should equal undefined");
|
||||
assertEqual(x, undefined, "x should equal undefined");
|
||||
},
|
||||
|
||||
defineFunctionInside: function () {
|
||||
var x = 1;
|
||||
eval("var func = function() { return x; }");
|
||||
assertEqual(func(), 1, "func should return 1");
|
||||
},
|
||||
|
||||
shouldReturnLastValue: function () {
|
||||
var z = eval("var b = 1; b");
|
||||
assertEqual(z, 1, "z should equal 1");
|
||||
},
|
||||
|
||||
closureHasAccessToEvalDefinedVars: function () {
|
||||
eval("var y = 1");
|
||||
var closure = function () {
|
||||
return y;
|
||||
};
|
||||
|
||||
assertEqual(closure(), 1, "closure should return 1");
|
||||
}
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче