diff options
| Commit | 0b2444013dfb6bfb0c033b5b827610f6df49ede5 (patch) | |
|---|---|---|
| Author | 2018-11-25 09:08:47 +0200 | |
| Committer | 2018-11-25 09:08:47 +0200 | |
| Files | e6206cd3329067cd48dd0ccf90262f6eaa6cdbbb | |
| IPL-0b2444013dfb6bfb0c033b5b827610f6df49ede5.tar IPL-0b2444013dfb6bfb0c033b5b827610f6df49ede5.tar.gz IPL-0b2444013dfb6bfb0c033b5b827610f6df49ede5.zip | ||
| Parent | 156d0957c1b36bba2685fef548a8573e9337309a (diff) | |
| Parent | 4fca8e8e6c1056aed11437c87e9175232b48c8f4 (diff) | |
Merge branch 'master' into json-to-ast
35 files changed, 1840 insertions, 616 deletions
diff --git a/JSImpl/test/empty.cpp b/JSImpl/test/empty.cpp index 2787b00..2725467 100644 --- a/JSImpl/test/empty.cpp +++ b/JSImpl/test/empty.cpp @@ -1,4 +1,6 @@ #include <gtest/gtest.h> +#include <memory> +#include <cmath> TEST(Empty, Empty) { @@ -58,5 +60,119 @@ TEST(Pointer, int64) ASSERT_EQ(data + 9, PC); } +/* + * Value will be either a double, undefined, null, string, array, object, + * function, boolean. + * + * Pointer values (like string, array, object, function) can be shared pointers + * via intrusive pointer implementation. This way we can get a reference + * counting garbage collection. + * + */ +struct Value +{ + Value(double v) + { + m_value.as_double = v; + } + + Value(int tag, void* pointer) + { + assert(tag && "Zero tag is plain double"); + assert(!((size_t)pointer >> 48) && "Use only pointers to the heap."); + m_value.as_pointer.pointer = (size_t)pointer; + m_value.as_pointer.tag = tag; + m_value.as_pointer.nan = 0x1fff; + } + struct NanPointer + { + size_t pointer:48; + size_t tag:3; + size_t nan:13; + }; + + struct CheckType + { + size_t payload: 48; + size_t check:16; + }; + union { + double as_double; + NanPointer as_pointer; + CheckType to_check; + + } m_value; + + static_assert(sizeof(size_t) == 8, "unsupported arch"); + static_assert(sizeof(double) == 8, "unsupported arch"); + + bool is_double() const + { + return m_value.to_check.check <= 0xFFF8; + } + + double get_double() const + { + assert(is_double()); + return m_value.as_double; + } + + int get_tag() { + assert(!is_double()); + return m_value.as_pointer.tag; + } + + void* get_pointer() const { + return (void*)(size_t) m_value.as_pointer.pointer; + } +}; + + +TEST(NaNBox, PlainDoubles) +{ + double a = floor(rand() / RAND_MAX); + double values[] = { + 0.0, 2.89, 3.14, 0.0 / 1.0, 1.0 / a + }; + for (auto value: values) + { + Value box(value); + ASSERT_TRUE(box.is_double()); + ASSERT_EQ(value, box.get_double()); + + Value box2(-value); + ASSERT_TRUE(box2.is_double()); + ASSERT_EQ(-value, box2.get_double()); + } +} +TEST(NaNBox, Border) +{ + Value v(2, nullptr); + ASSERT_TRUE(std::isnan(v.m_value.as_double)); + ASSERT_FALSE(std::isinf(v.m_value.as_double)); +} +TEST(NaNBox, IsNaN) +{ + Value v2(std::sqrt(-1.0)); + ASSERT_TRUE(v2.is_double()); +} + +TEST(NaNBox, Pointers) +{ + std::vector<std::unique_ptr<int>> pointers; + int n = 1024; + pointers.reserve(n); + for (int i = 0; i < n; ++i) + { + pointers.emplace_back(std::make_unique<int>(i)); + } + + for (auto& value: pointers) + { + Value box(1, value.get()); + ASSERT_FALSE(box.is_double()); + ASSERT_EQ(value.get(), box.get_pointer()); + } +} diff --git a/JSImpl/test/sprtTests.cpp b/JSImpl/test/sprtTests.cpp index eef7147..8480554 100644 --- a/JSImpl/test/sprtTests.cpp +++ b/JSImpl/test/sprtTests.cpp @@ -81,7 +81,7 @@ TEST_F(SPRTTest, Div) }; Run(bytecode, sizeof(bytecode)); - ASSERT_EQ(Output.str(), "0"); + ASSERT_EQ(Output.str(), "0.857143"); } TEST_F(SPRTTest, Mod) @@ -235,24 +235,24 @@ TEST_F(SPRTTest, Read) TEST_F(SPASMTest, RSyntax) { const char* program = - "push 5" "\n" - "const r1 0" "\n" - "const r2 6" "\n" - "const r3 7" "\n" - "const r4 2" "\n" - "pushr r3" "\n" - "pushr r2" "\n" - "pushr r4" "\n" - "call mult" "\n" - "popr r1" "\n" - "print r1" "\n" - "halt" "\n" - "label mult" "\n" - "print a0" "\n" - "print a1" "\n" - "print a2" "\n" - "mul r1 a2 a1" "\n" - "ret r1" "\n" + "00: push 5" "\n" + "01: const r1 0" "\n" + "02: const r2 6" "\n" + "03: const r3 7" "\n" + "04: const r4 2" "\n" + "05: pushr r3" "\n" + "06: pushr r2" "\n" + "07: pushr r4" "\n" + "08: call mult # *" "\n" + "09: popr r1" "\n" + "10: print r1" "\n" + "11: halt" "\n" + "12: label mult" "\n" + "13: print a0" "\n" + "14: print a1" "\n" + "15: print a2" "\n" + "16: mul r1 a2 a1" "\n" + "17: ret r1" "\n" "" ; CompileAndRun(program); @@ -5,3 +5,8 @@ Implementation of Programming Languages course [](https://ci.appveyor.com/project/dtrendafilov/ipl) +## How to contribute + +Checkout the [Virtual Machine](https://github.com/SofiaCPP/IPL/projects/1) and +[JavaScript Implementation](https://github.com/SofiaCPP/IPL/projects/2) projects +for a list of issues that need fixed or implemented and their statuses. diff --git a/homework/81333/brainfsck/.gitignore b/homework/81333/brainfsck/.gitignore new file mode 100644 index 0000000..c8db66d --- /dev/null +++ b/homework/81333/brainfsck/.gitignore @@ -0,0 +1,3 @@ +.stack-work/ +brainfsck.cabal +*~
\ No newline at end of file diff --git a/homework/81333/brainfsck/ChangeLog.md b/homework/81333/brainfsck/ChangeLog.md new file mode 100644 index 0000000..76c7fe5 --- /dev/null +++ b/homework/81333/brainfsck/ChangeLog.md @@ -0,0 +1,3 @@ +# Changelog for brainfsck + +## Unreleased changes diff --git a/homework/81333/brainfsck/LICENSE b/homework/81333/brainfsck/LICENSE new file mode 100644 index 0000000..c29d4ee --- /dev/null +++ b/homework/81333/brainfsck/LICENSE @@ -0,0 +1,232 @@ +Copyright Author name here (c) 2018 + +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 Author name here nor the names of other + 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. +======= + 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: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) 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 + + (d) 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. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/homework/81333/brainfsck/README.md b/homework/81333/brainfsck/README.md new file mode 100644 index 0000000..f9ef70c --- /dev/null +++ b/homework/81333/brainfsck/README.md @@ -0,0 +1,28 @@ +# Brainfsck interpreter + +# How to build + +Install [stack](https://docs.haskellstack.org/en/stable/README/) build tool + +Run following commands from root of project: + +Building: + +``` +stack build +``` + +Executing: + +``` +stack exec brainfsck <file_with_code> +``` + +# Examples + +Examples are in `examples/` folder. + +Best ones are: + +* `stack exec brainfsck examples/sierpinski.bf` - outputs sierpinski triangle +* `echo 0123456789 | stack exec brainfsck examples/pretty.bf` - pretty prints numbers diff --git a/homework/81333/brainfsck/Setup.hs b/homework/81333/brainfsck/Setup.hs new file mode 100644 index 0000000..9a994af --- /dev/null +++ b/homework/81333/brainfsck/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/homework/81333/brainfsck/app/Main.hs b/homework/81333/brainfsck/app/Main.hs new file mode 100644 index 0000000..a45882e --- /dev/null +++ b/homework/81333/brainfsck/app/Main.hs @@ -0,0 +1,22 @@ +{-# LANGUAGE OverloadedStrings #-} + +module Main where + +import System.Environment (getArgs) + +import qualified Data.ByteString.Char8 as B + +import Lib (blocks) + +import Text.Brainfsck.Parser (parseText) +import Text.Brainfsck.Types + +main :: IO () +main = do + args <- getArgs + case args of + [] -> putStrLn "Usage: stack exec brainfsck-exe <file_with_code>" + _ -> do + code <- B.readFile $ args !! 0 + result <- blocks newBlocks $ parseText code + B.putStrLn $ r result diff --git a/homework/81333/brainfsck/brainfsck.cabal b/homework/81333/brainfsck/brainfsck.cabal new file mode 100644 index 0000000..45f2ba4 --- /dev/null +++ b/homework/81333/brainfsck/brainfsck.cabal @@ -0,0 +1,74 @@ +cabal-version: 1.12 + +-- This file has been generated from package.yaml by hpack version 0.31.1. +-- +-- see: https://github.com/sol/hpack +-- +-- hash: 6e461fb9377fd9d13efd7b8e322e93ae789d4e0f77c88584498db65aa15f75ea + +name: brainfsck +version: 0.1.0.0 +description: Please see the README on GitHub at <https://github.com/githubuser/brainfsck#readme> +homepage: https://github.com/githubuser/brainfsck#readme +bug-reports: https://github.com/githubuser/brainfsck/issues +author: Author name here +maintainer: example@example.com +copyright: 2018 Author name here +license: BSD3 +license-file: LICENSE +build-type: Simple +extra-source-files: + README.md + ChangeLog.md + +source-repository head + type: git + location: https://github.com/githubuser/brainfsck + +library + exposed-modules: + Lib + Text.Brainfsck.Parser + Text.Brainfsck.Types + Text.Brainfsck.Util + other-modules: + Paths_brainfsck + hs-source-dirs: + src + build-depends: + attoparsec + , base >=4.7 && <5 + , bytestring + , haskeline + default-language: Haskell2010 + +executable brainfsck + main-is: Main.hs + other-modules: + Paths_brainfsck + hs-source-dirs: + app + ghc-options: -threaded -rtsopts -with-rtsopts=-N + build-depends: + attoparsec + , base >=4.7 && <5 + , brainfsck + , bytestring + , haskeline + default-language: Haskell2010 + +test-suite brainfsck-test + type: exitcode-stdio-1.0 + main-is: Spec.hs + other-modules: + Paths_brainfsck + hs-source-dirs: + test + ghc-options: -threaded -rtsopts -with-rtsopts=-N + build-depends: + attoparsec + , base >=4.7 && <5 + , brainfsck + , bytestring + , haskeline + default-language: Haskell2010 diff --git a/homework/81333/brainfsck/examples/fact.bf b/homework/81333/brainfsck/examples/fact.bf new file mode 100644 index 0000000..197f331 --- /dev/null +++ b/homework/81333/brainfsck/examples/fact.bf @@ -0,0 +1,42 @@ ++++++++++++++++++++++++++++++++++ c1v33 : ASCII code of ! +>++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++ c2v61 : ASCII code of = +>++++++++++ c3v10 : ASCII code of EOL +>+++++++ c4v7 : quantity of numbers to be calculated +> c5v0 : current number (one digit) +>+ c6v1 : current value of factorial (up to three digits) +<< c4 : loop counter +[ block : loop to print one line and calculate next +>++++++++++++++++++++++++++++++++++++++++++++++++. c5 : print current number +------------------------------------------------ c5 : back from ASCII to number +<<<<.-.>.<.+ c1 : print !_=_ + +>>>>> block : print c6 (preserve it) +> c7v0 : service zero +>++++++++++ c8v10 : divizor +<< c6 : back to dividend +[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<] c6v0 : divmod algo borrowed from esolangs; results in 0 n d_n%d n%d n/d +>[<+>-] c6 : move dividend back to c6 and clear c7 +>[-] c8v0 : clear c8 + +>> block : c10 can have two digits; divide it by ten again +>++++++++++ c11v10: divizor +< c10 : back to dividend +[->-[>+>>]>[+[-<+>]>+>>]<<<<<] c10v0 : another divmod algo borrowed from esolangs; results in 0 d_n%d n%d n/d +>[-] c11v0 : clear c11 +>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]c13v0 : print nonzero n/d (first digit) and clear c13 +<[++++++++++++++++++++++++++++++++++++++++++++++++.[-]] c12v0 : print nonzero n%d (second digit) and clear c12 +<<<++++++++++++++++++++++++++++++++++++++++++++++++.[-] c9v0 : print any n%d (last digit) and clear c9 + +<<<<<<. c3 : EOL +>>+ c5 : increment current number + block : multiply c6 by c5 (don't preserve c6) +>[>>+<<-] c6v0 : move c6 to c8 +>> c8v0 : repeat c8 times +[ +<<<[>+>+<<-] c5v0 : move c5 to c6 and c7 +>>[<<+>>-] c7v0 : move c7 back to c5 +>- +] +<<<<- c4 : decrement loop counter +] diff --git a/homework/81333/brainfsck/examples/hello.bf b/homework/81333/brainfsck/examples/hello.bf new file mode 100644 index 0000000..273b209 --- /dev/null +++ b/homework/81333/brainfsck/examples/hello.bf @@ -0,0 +1,3 @@ +>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-] +>++++++++[<++++>-] <.>+++++++++++[<++++++++>-]<-.--------.+++ +.------.--------.[-]>++++++++[<++++>- ]<+.[-]++++++++++. diff --git a/homework/81333/brainfsck/examples/input.bf b/homework/81333/brainfsck/examples/input.bf new file mode 100644 index 0000000..12597fc --- /dev/null +++ b/homework/81333/brainfsck/examples/input.bf @@ -0,0 +1,13 @@ +> + +[ - >,>+< + ----- ----- ; minus 10 + [ ; if enters means it is not a \n + +++++ +++++ ; restore prev value + < + ] >> ; moving forward +] + ; numbers are 0 0 49 0 50 0 51 + ; for input 123 +<<<<[<<] ; moving to the beginning +>> ; reaching first char +[.>>] ; just printing till end diff --git a/homework/81333/brainfsck/examples/pretty.bf b/homework/81333/brainfsck/examples/pretty.bf new file mode 100644 index 0000000..069aa4d --- /dev/null +++ b/homework/81333/brainfsck/examples/pretty.bf @@ -0,0 +1,31 @@ +>>>>+>+++>+++>>>>>+++[ + >,+>++++[>++++<-]>[<<[-[->]]>[<]>-]<<[ + >+>+>>+>+[<<<<]<+>>[+<]<[>]>+[[>>>]>>+[<<<<]>-]+<+>>>-[ + <<+[>]>>+<<<+<+<--------[ + <<-<<+[>]>+<<-<<-[ + <<<+<-[>>]<-<-<<<-<----[ + <<<->>>>+<-[ + <<<+[>]>+<<+<-<-[ + <<+<-<+[>>]<+<<<<+<-[ + <<-[>]>>-<<<-<-<-[ + <<<+<-[>>]<+<<<+<+<-[ + <<<<+[>]<-<<-[ + <<+[>]>>-<<<<-<-[ + >>>>>+<-<<<+<-[ + >>+<<-[ + <<-<-[>]>+<<-<-<-[ + <<+<+[>]<+<+<-[ + >>-<-<-[ + <<-[>]<+<++++[<-------->-]++<[ + <<+[>]>>-<-<<<<-[ + <<-<<->>>>-[ + <<<<+[>]>+<<<<-[ + <<+<<-[>>]<+<<<<<-[ + >>>>-<<<-<- + ]]]]]]]]]]]]]]]]]]]]]]>[>[[[<<<<]>+>>[>>>>>]<-]<]>>>+>>>>>>>+>]< +]<[-]<<<<<<<++<+++<+++[ + [>]>>>>>>++++++++[<<++++>++++++>-]<-<<[-[<+>>.<-]]<<<<[ + -[-[>+<-]>]>>>>>[.[>]]<<[<+>-]>>>[<<++[<+>--]>>-] + <<[->+<[<++>-]]<<<[<+>-]<<<< + ]>>+>>>--[<+>---]<.>>[[-]<<]< +] diff --git a/homework/81333/brainfsck/examples/sierpinski.bf b/homework/81333/brainfsck/examples/sierpinski.bf new file mode 100644 index 0000000..4c66685 --- /dev/null +++ b/homework/81333/brainfsck/examples/sierpinski.bf @@ -0,0 +1,5 @@ +++++++++[>+>++++<<-]>++>>+<[-[>>+<<-]+>>]>+[ + -<<<[ + ->[+[-]+>++>>>-<<]<[<]>>++++++[<<+++++>>-]+<<++.[-]<< + ]>.>+[>>]>+ +] diff --git a/homework/81333/brainfsck/examples/squares.bf b/homework/81333/brainfsck/examples/squares.bf new file mode 100644 index 0000000..fa0a6f8 --- /dev/null +++ b/homework/81333/brainfsck/examples/squares.bf @@ -0,0 +1,5 @@ +++++[>+++++<-]>[<+++++>-]+<+[ + >[>+>+<<-]++>>[<<+>>-]>>>[-]++>[-]+ + >>>+[[-]++++++>>>]<<<[[<++++++++<++>>-]+<.<[>----<-]<] + <<[>>>>>[>>>[-]+++++++++<[>-<-]+++++++++>[-[<->-]+[<<<]]<[>+<-]>]<<-]<<- +] diff --git a/homework/81333/brainfsck/examples/sum.bf b/homework/81333/brainfsck/examples/sum.bf new file mode 100644 index 0000000..df694ec --- /dev/null +++ b/homework/81333/brainfsck/examples/sum.bf @@ -0,0 +1,100 @@ +[ + A brainfuck program for doing a single digit addition. + + Ex. input: '13' -> output: '4' + input: '99' -> output: '18' + + Author: Florian Baierl +] + +initialize #0 with 48 (ASCII char for '0') +>++++ ++++ +[ +<++++ ++ +>- +] + +save input to #1 and #2 +,>, + +substract value from #0 from #1 and #2 +<< +[ +>- +>- +<<- +] + +move to #1 +> + +substract from #1 and add to #2; now the answer is in #2 +[ + ->+< +] + +since we need to modify the answer afterwards write it to #3 and #6 +as well +> +[>+>>>+<<<<-] + + +Is the answer bigger than 9? +to continue the memory tape should look like this: +0 1 0 (a) b 0 +with the pointer pointing to a + +<+ +>>>+++++ +++++ b is 10 +< point to a + ++>+< necessary in case a and b are zero + +loop to determine whether a or b reach 0 first +[->-[>]<<] + +<[- + a was bigger or equals b + the answer is still stored in #6 + + subtract 10 from #6 (the answer) + >>>>> ----- ----- + + write 48 to #4 + <++++ ++++ + [ + <++++ ++ + >- + ] + add 48 to #5 and #6 + < + [->+>+<<] + + print out the results + >+.>. + + leave loop (back to #2) + <<<< + ] + <[- + a was samller so we can simply print the answer out after adding 48 to it + the answer is still stored in #6 + + >> + ++++ ++++ + [ + <++++ ++ + >- + ] + + < + [ + ->>>>+<<<< + ] + + print #2 + >>>>. + + we want to leave the loop so go somewhere with the value '0' + > +] diff --git a/homework/81333/brainfsck/package.yaml b/homework/81333/brainfsck/package.yaml new file mode 100644 index 0000000..44043aa --- /dev/null +++ b/homework/81333/brainfsck/package.yaml @@ -0,0 +1,51 @@ +name: brainfsck +version: 0.1.0.0 +github: "githubuser/brainfsck" +license: BSD3 +author: "Author name here" +maintainer: "example@example.com" +copyright: "2018 Author name here" + +extra-source-files: +- README.md +- ChangeLog.md + +# Metadata used when publishing your package +# synopsis: Short description of your package +# category: Web + +# To avoid duplicated efforts in documentation and dealing with the +# complications of embedding Haddock markup inside cabal files, it is +# common to point users to the README.md file. +description: Please see the README on GitHub at <https://github.com/githubuser/brainfsck#readme> + +dependencies: +- base >= 4.7 && < 5 +- attoparsec +- bytestring +- haskeline + +library: + source-dirs: src + +executables: + brainfsck: + main: Main.hs + source-dirs: app + ghc-options: + - -threaded + - -rtsopts + - -with-rtsopts=-N + dependencies: + - brainfsck + +tests: + brainfsck-test: + main: Spec.hs + source-dirs: test + ghc-options: + - -threaded + - -rtsopts + - -with-rtsopts=-N + dependencies: + - brainfsck diff --git a/homework/81333/brainfsck/src/Lib.hs b/homework/81333/brainfsck/src/Lib.hs new file mode 100644 index 0000000..e4cc95c --- /dev/null +++ b/homework/81333/brainfsck/src/Lib.hs @@ -0,0 +1,30 @@ +{-# LANGUAGE OverloadedStrings #-} + +module Lib + ( blocks + ) where + +import Data.Attoparsec.ByteString.Char8 +import qualified Data.ByteString.Char8 as B + +import Data.Char +import Text.Brainfsck.Types +import Text.Brainfsck.Util + +blocks :: Blocks -> [BFExpr] -> IO Blocks +blocks b [] = pure b +blocks (Blocks h b r) (BFRight:es) = blocks (Blocks (h + 1) b r) es +blocks (Blocks h b r) (BFLeft:es) = blocks (Blocks (max (h - 1) 0) b r) es +blocks (Blocks h b r) (BFPlus:es) = blocks (Blocks h (inc b h) r) es +blocks (Blocks h b r) (BFMinus:es) = blocks (Blocks h (dec b h) r) es +blocks (Blocks h b r) (BFPut:es) = + blocks (Blocks h b (r <> B.singleton (chr $ b !! h))) es +blocks (Blocks h b r) (BFGet:es) = do + v <- getChar + blocks (Blocks h (load b h $ ord v) r) es +blocks current@(Blocks h b r) (BFLoop expr:es) = do + if b !! h == 0 + then blocks current es + else do + newBlocks <- blocks current expr + blocks newBlocks ((BFLoop expr) : es) diff --git a/homework/81333/brainfsck/src/Text/Brainfsck/Parser.hs b/homework/81333/brainfsck/src/Text/Brainfsck/Parser.hs new file mode 100644 index 0000000..28c019a --- /dev/null +++ b/homework/81333/brainfsck/src/Text/Brainfsck/Parser.hs @@ -0,0 +1,56 @@ +module Text.Brainfsck.Parser + ( parseText + ) where + +import Control.Applicative + +import Data.Attoparsec.ByteString.Char8 +import qualified Data.ByteString.Char8 as B +import Data.Either (fromRight) + +import Text.Brainfsck.Types + +goRight :: Parser BFExpr +goRight = do + char '>' + pure BFRight + +goLeft :: Parser BFExpr +goLeft = do + char '<' + pure BFLeft + +plus :: Parser BFExpr +plus = do + char '+' + pure BFPlus + +minus :: Parser BFExpr +minus = do + char '-' + pure BFMinus + +get :: Parser BFExpr +get = do + char ',' + pure BFGet + +put :: Parser BFExpr +put = do + char '.' + pure BFPut + +bfsymbol :: Parser BFExpr +bfsymbol = goRight <|> goLeft <|> plus <|> minus <|> get <|> put <|> loop + +loop :: Parser BFExpr +loop = do + char '[' + m <- many' bfsymbol + char ']' + pure $ BFLoop m + +parseText :: B.ByteString -> [BFExpr] +parseText s = + fromRight [] $ + parseOnly (many' bfsymbol) $ B.filter ((flip elem) "+-,.<>[]") s diff --git a/homework/81333/brainfsck/src/Text/Brainfsck/Types.hs b/homework/81333/brainfsck/src/Text/Brainfsck/Types.hs new file mode 100644 index 0000000..5dd26f6 --- /dev/null +++ b/homework/81333/brainfsck/src/Text/Brainfsck/Types.hs @@ -0,0 +1,24 @@ +{-# LANGUAGE OverloadedStrings #-} + +module Text.Brainfsck.Types where + +import qualified Data.ByteString.Char8 as B + +data BFExpr + = BFRight + | BFLeft + | BFPlus + | BFMinus + | BFGet + | BFPut + | BFLoop [BFExpr] + deriving (Show) + +data Blocks = Blocks + { h :: Int + , b :: [Int] + , r :: B.ByteString + } deriving (Show) + +newBlocks :: Blocks +newBlocks = Blocks {h = 0, b = [0,0 ..], r = ""} diff --git a/homework/81333/brainfsck/src/Text/Brainfsck/Util.hs b/homework/81333/brainfsck/src/Text/Brainfsck/Util.hs new file mode 100644 index 0000000..fb2d5ad --- /dev/null +++ b/homework/81333/brainfsck/src/Text/Brainfsck/Util.hs @@ -0,0 +1,10 @@ +module Text.Brainfsck.Util where + +inc :: [Int] -> Int -> [Int] +inc b h = take h b <> [b !! h + 1] <> drop (h + 1) b + +dec :: [Int] -> Int -> [Int] +dec b h = take h b <> [b !! h - 1] <> drop (h + 1) b + +load :: [Int] -> Int -> Int -> [Int] +load b h v = take h b <> [v] <> drop (h + 1) b diff --git a/homework/81333/brainfsck/stack.yaml b/homework/81333/brainfsck/stack.yaml new file mode 100644 index 0000000..6ad76a0 --- /dev/null +++ b/homework/81333/brainfsck/stack.yaml @@ -0,0 +1,64 @@ +# This file was automatically generated by 'stack init' +# +# Some commonly used options have been documented as comments in this file. +# For advanced use and comprehensive documentation of the format, please see: +# https://docs.haskellstack.org/en/stable/yaml_configuration/ + +# Resolver to choose a 'specific' stackage snapshot or a compiler version. +# A snapshot resolver dictates the compiler version and the set of packages +# to be used for project dependencies. For example: +# +# resolver: lts-3.5 +# resolver: nightly-2015-09-21 +# resolver: ghc-7.10.2 +# +# The location of a snapshot can be provided as a file or url. Stack assumes +# a snapshot provided as a file might change, whereas a url resource does not. +# +# resolver: ./custom-snapshot.yaml +# resolver: https://example.com/snapshots/2018-01-01.yaml +resolver: lts-12.18 + +# User packages to be built. +# Various formats can be used as shown in the example below. +# +# packages: +# - some-directory +# - https://example.com/foo/bar/baz-0.0.2.tar.gz +# - location: +# git: https://github.com/commercialhaskell/stack.git +# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a +# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a +# subdirs: +# - auto-update +# - wai +packages: +- . +# Dependency packages to be pulled from upstream that are not in the resolver +# using the same syntax as the packages field. +# (e.g., acme-missiles-0.3) +# extra-deps: [] + +# Override default flag values for local packages and extra-deps +# flags: {} + +# Extra package databases containing global packages +# extra-package-dbs: [] + +# Control whether we use the GHC we find on the path +# system-ghc: true +# +# Require a specific version of stack, using version ranges +# require-stack-version: -any # Default +# require-stack-version: ">=1.9" +# +# Override the architecture used by stack, especially useful on Windows +# arch: i386 +# arch: x86_64 +# +# Extra directories used by stack for building +# extra-include-dirs: [/path/to/dir] +# extra-lib-dirs: [/path/to/dir] +# +# Allow a newer minor version of GHC than the snapshot specifies +# compiler-check: newer-minor diff --git a/homework/81333/brainfsck/test/Spec.hs b/homework/81333/brainfsck/test/Spec.hs new file mode 100644 index 0000000..cd4753f --- /dev/null +++ b/homework/81333/brainfsck/test/Spec.hs @@ -0,0 +1,2 @@ +main :: IO () +main = putStrLn "Test suite not yet implemented" diff --git a/spasm/src/asm/assembler.cpp b/spasm/src/asm/assembler.cpp index fbe6675..fadd747 100644 --- a/spasm/src/asm/assembler.cpp +++ b/spasm/src/asm/assembler.cpp @@ -14,6 +14,54 @@ Assembler::Assembler(Lexer::Tokenizer& tokenizer, Bytecode_Stream& bytecode) { } +int get_arg_size(const Lexer::Token args[]) +{ + int size = 0; + for (int i = 0; i < 3; ++i) + { + switch (args[i].type()) + { + case Lexer::Token::Integer: + case Lexer::Token::XInteger: + { + if (args[i].value_int() > 0xffffffff) + { + size = std::max(size, 3); + } + else if (args[i].value_int() > 0xffff) + { + size = std::max(size, 2); + } + else if (args[i].value_int() > 0xff) + { + size = std::max(size, 1); + } + else if (args[i].value_int() < -0xffffffffLL) + { + size = std::max(size, 3); + } + else if (args[i].value_int() < -0xffff) + { + size = std::max(size, 2); + } + else if (args[i].value_int() < -0xff) + { + size = std::max(size, 1); + } + break; + } + case Lexer::Token::FloatingPoint: + { + size = std::max(size, 3); + break; + } + default: + break; + } + } + return size; +} + void Assembler::assemble() { Lexer::Token token = _tokenizer->next_token(); @@ -39,42 +87,64 @@ void Assembler::assemble() } else { - _bytecode->push_opcode((Bytecode_Stream::Opcode_t)token.type()); + Lexer::Token args[3]; if (type >= Lexer::Token::_OneArgBegin) { + args[0] = _tokenizer->next_token(); + } + if (type >= Lexer::Token::_TwoArgBegin) + { + args[1] = _tokenizer->next_token(); + } + if (type >= Lexer::Token::_ThreeArgBegin) + { + args[2] = _tokenizer->next_token(); + } + const auto size = get_arg_size(args); + _bytecode->push_opcode( + (Bytecode_Stream::Opcode_t)((size << 6) | token.type())); + const auto arg_size = 1 << size; + + if (args[0].type() != Lexer::Token::NotUsed) + { if (type == Lexer::Token::Call || type == Lexer::Token::Jump) { - token = _tokenizer->next_token(); - assert(token.type() == Lexer::Token::Ident); - assemble_identifier(token); + assert(args[0].type() == Lexer::Token::Ident); + assemble_identifier(args[0]); } else { - token = _tokenizer->next_token(); - assert(token.type() == Lexer::Token::Integer); - _bytecode->push_integer(token.value_int()); + assert(args[0].type() == Lexer::Token::Integer); + _bytecode->push_integer(args[0].value_int(), arg_size); } } - if (type >= Lexer::Token::_TwoArgBegin) + if (args[1].type() != Lexer::Token::NotUsed) { if (type == Lexer::Token::JumpF || type == Lexer::Token::JumpT) { - token = _tokenizer->next_token(); - assert(token.type() == Lexer::Token::Ident); - assemble_identifier(token); + assert(args[1].type() == Lexer::Token::Ident); + assemble_identifier(args[1]); } else { - token = _tokenizer->next_token(); - assert(token.type() == Lexer::Token::Integer); - _bytecode->push_integer(token.value_int()); + if (args[1].type() == Lexer::Token::Integer) + { + _bytecode->push_integer(args[1].value_int(), arg_size); + } + else if (args[1].type() == Lexer::Token::FloatingPoint) + { + _bytecode->push_double(args[1].value_double()); + } + else + { + assert(false && "expected a number type"); + } } } - if (type >= Lexer::Token::_ThreeArgBegin) + if (args[2].type() != Lexer::Token::NotUsed) { - token = _tokenizer->next_token(); - assert(token.type() == Lexer::Token::Integer); - _bytecode->push_integer(token.value_int()); + assert(args[2].type() == Lexer::Token::Integer); + _bytecode->push_integer(args[2].value_int(), arg_size); } } @@ -105,7 +175,7 @@ void Assembler::assemble_identifier(const Lexer::Token& token) _bytecode->push_location(symbol->definition()); } -bool compile(std::istream& istr, Bytecode_Memory& bytecode) +bool compile(std::istream& istr, Bytecode_Stream& bytecode) { Lexer::Tokenizer tokenizer(istr); Assembler assembler(tokenizer, bytecode); diff --git a/spasm/src/asm/assembler.hpp b/spasm/src/asm/assembler.hpp index d29139b..90e8815 100644 --- a/spasm/src/asm/assembler.hpp +++ b/spasm/src/asm/assembler.hpp @@ -29,7 +29,7 @@ class Assembler }; // class Assembler -bool compile(std::istream&, Bytecode_Memory& bytecode); +bool compile(std::istream&, Bytecode_Stream& bytecode); } // namespace ASM } // namespace SpasmImpl diff --git a/spasm/src/asm/bytecode.cpp b/spasm/src/asm/bytecode.cpp index 39f1de6..cc250ba 100644 --- a/spasm/src/asm/bytecode.cpp +++ b/spasm/src/asm/bytecode.cpp @@ -26,17 +26,29 @@ void Bytecode_File::push_opcode(Bytecode_Stream::Opcode_t opcode) push_byte(opcode); } -void Bytecode_File::push_integer(int number) +union DoubleToBits { + double as_double; + int64_t as_bits; +}; + +int64_t to_bits(double d) { - if (number <= 0xff) - { - push_byte((byte)number); - } - else - { - for (size_t i = 0; i < sizeof(int); ++i) - push_byte((number >> (i << 3)) & 0xff); - } + DoubleToBits v; + v.as_double = d; + return v.as_bits; +}; + +void Bytecode_File::push_integer(int64_t number, int size) +{ + for (int i = 0; i < size; ++i) + push_byte((number >> (i << 3)) & 0xff); +} + +void Bytecode_File::push_double(double number) +{ + auto bits = to_bits(number); + for (size_t i = 0; i < sizeof(size_t); ++i) + push_byte((bits >> (i << 3)) & 0xff); } void Bytecode_Memory::push_byte(Bytecode_Stream::byte byte) @@ -49,17 +61,17 @@ void Bytecode_Memory::push_opcode(Bytecode_Stream::Opcode_t opcode) push_byte(opcode); } -void Bytecode_Memory::push_integer(int number) +void Bytecode_Memory::push_integer(int64_t number, int size) { - if (number <= 0xff) - { - push_byte((byte)number); - } - else - { - for (size_t i = 0; i < sizeof(int); ++i) - push_byte((number >> (i << 3)) & 0xff); - } + for (int i = 0; i < size; ++i) + push_byte((number >> (i << 3)) & 0xff); +} + +void Bytecode_Memory::push_double(double number) +{ + auto bits = to_bits(number); + for (size_t i = 0; i < sizeof(size_t); ++i) + push_byte((bits >> (i << 3)) & 0xff); } void Bytecode_Memory::set_location(size_t index, size_t location) diff --git a/spasm/src/asm/bytecode.hpp b/spasm/src/asm/bytecode.hpp index 374ccef..fb80122 100644 --- a/spasm/src/asm/bytecode.hpp +++ b/spasm/src/asm/bytecode.hpp @@ -18,7 +18,8 @@ class Bytecode_Stream virtual ~Bytecode_Stream(); virtual void push_opcode(Opcode_t) = 0; - virtual void push_integer(int) = 0; + virtual void push_integer(int64_t, int size) = 0; + virtual void push_double(double) = 0; virtual void push_location(size_t) = 0; virtual void set_location(size_t, size_t) = 0; virtual size_t size() const = 0; @@ -30,7 +31,8 @@ class Bytecode_File : public Bytecode_Stream Bytecode_File(const std::string&); virtual void push_opcode(Opcode_t); - virtual void push_integer(int); + virtual void push_integer(int64_t, int size) override; + virtual void push_double(double) override; private: Bytecode_File(const Bytecode_File&); @@ -45,7 +47,8 @@ class Bytecode_Memory : public Bytecode_Stream { public: virtual void push_opcode(Opcode_t); - virtual void push_integer(int); + virtual void push_integer(int64_t, int) override; + virtual void push_double(double) override; virtual void push_location(size_t); virtual void set_location(size_t, size_t); virtual size_t size() const; diff --git a/spasm/src/asm/lexer.cpp b/spasm/src/asm/lexer.cpp index 3af83c7..5be7836 100644 --- a/spasm/src/asm/lexer.cpp +++ b/spasm/src/asm/lexer.cpp @@ -1,4 +1,4 @@ -/* Generated by re2c 1.1.1 on Thu Nov 15 10:01:26 2018 */ +/* Generated by re2c 1.1.1 on Thu Nov 22 14:23:32 2018 */ #line 1 "lexer.re" #include <iostream> @@ -41,15 +41,16 @@ bool Lexer::tokenize(TokenStream& ts) { case 0x00: goto yy2; - case '\t': - case ' ': - goto yy6; case '\n': - goto yy9; - case '-': + goto yy6; + case ' ': + goto yy8; + case '#': goto yy11; + case '-': + goto yy13; case '0': - goto yy12; + goto yy14; case '1': case '2': case '3': @@ -59,7 +60,9 @@ bool Lexer::tokenize(TokenStream& ts) case '7': case '8': case '9': - goto yy14; + goto yy16; + case ':': + goto yy18; case 'A': case 'B': case 'C': @@ -104,111 +107,136 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; case 'a': - goto yy19; + goto yy23; case 'c': - goto yy20; + goto yy24; case 'd': - goto yy21; + goto yy25; case 'j': - goto yy22; + goto yy26; case 'l': - goto yy23; + goto yy27; case 'm': - goto yy24; + goto yy28; case 'p': - goto yy25; + goto yy29; case 'r': - goto yy26; + goto yy30; case 's': - goto yy27; + goto yy31; default: goto yy4; } yy2: ++cursor; -#line 254 "lexer.re" +#line 274 "lexer.re" { ts.push_token(Token(Token::EndInput, lineno)); break; } -#line 125 "lexer.cpp" +#line 126 "lexer.cpp" yy4: ++cursor; yy5: -#line 260 "lexer.re" +#line 280 "lexer.re" { return false; } -#line 133 "lexer.cpp" +#line 134 "lexer.cpp" yy6: ++cursor; +#line 267 "lexer.re" + { + ++lineno; + token_start = cursor; + + continue; + } +#line 144 "lexer.cpp" + yy8: + ++cursor; if (limit <= cursor) return true; yych = *cursor; switch (yych) { - case '\t': case ' ': - goto yy6; - default: goto yy8; + default: + goto yy10; } - yy8: -#line 241 "lexer.re" + yy10: +#line 251 "lexer.re" { token_start = cursor; continue; } -#line 150 "lexer.cpp" - yy9: +#line 160 "lexer.cpp" + yy11: ++cursor; -#line 247 "lexer.re" + if (limit <= cursor) + return true; + yych = *cursor; + switch (yych) { - ++lineno; - token_start = cursor; - - continue; + case '\n': + goto yy32; + default: + goto yy11; } -#line 160 "lexer.cpp" - yy11: + yy13: yych = *++cursor; switch (yych) { case '0': - goto yy28; + goto yy34; default: goto yy5; } - yy12: + yy14: yych = *(marker = ++cursor); switch (yych) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case ':': + goto yy36; case 'X': case 'x': - goto yy29; + goto yy38; default: - goto yy13; + goto yy15; } - yy13: -#line 59 "lexer.re" + yy15: +#line 60 "lexer.re" { ts.push_token(Token(Token::Integer, lineno, token_start, cursor)); token_start = cursor; continue; } -#line 183 "lexer.cpp" - yy14: - ++cursor; - if (limit <= cursor) +#line 202 "lexer.cpp" + yy16: + marker = ++cursor; + if ((limit - cursor) < 2) return true; yych = *cursor; switch (yych) { + case '.': + goto yy39; case '0': case '1': case '2': @@ -219,16 +247,27 @@ bool Lexer::tokenize(TokenStream& ts) case '7': case '8': case '9': - goto yy14; + goto yy16; + case ':': + goto yy18; default: - goto yy13; + goto yy15; } - yy16: + yy18: + ++cursor; +#line 256 "lexer.re" + { + token_start = cursor; + + continue; + } +#line 230 "lexer.cpp" + yy20: ++cursor; if (limit <= cursor) return true; yych = *cursor; - yy17: + yy21: switch (yych) { case '0': @@ -294,25 +333,25 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy18; + goto yy22; } - yy18: -#line 233 "lexer.re" + yy22: +#line 243 "lexer.re" { ts.push_token(Token(Token::Ident, lineno, token_start, cursor)); token_start = cursor; continue; } -#line 281 "lexer.cpp" - yy19: +#line 311 "lexer.cpp" + yy23: yych = *++cursor; switch (yych) { case '0': - goto yy31; + goto yy40; case '1': case '2': case '3': @@ -322,84 +361,84 @@ bool Lexer::tokenize(TokenStream& ts) case '7': case '8': case '9': - goto yy33; + goto yy42; case 'd': - goto yy35; + goto yy44; default: - goto yy17; + goto yy21; } - yy20: + yy24: yych = *++cursor; switch (yych) { case 'a': - goto yy36; + goto yy45; case 'o': - goto yy37; + goto yy46; default: - goto yy17; + goto yy21; } - yy21: + yy25: yych = *++cursor; switch (yych) { case 'i': - goto yy38; + goto yy47; case 'u': - goto yy39; + goto yy48; default: - goto yy17; + goto yy21; } - yy22: + yy26: yych = *++cursor; switch (yych) { case 'm': - goto yy40; + goto yy49; default: - goto yy17; + goto yy21; } - yy23: + yy27: yych = *++cursor; switch (yych) { case 'a': - goto yy41; + goto yy50; case 'e': - goto yy42; + goto yy51; default: - goto yy17; + goto yy21; } - yy24: + yy28: yych = *++cursor; switch (yych) { case 'o': - goto yy43; + goto yy52; case 'u': - goto yy44; + goto yy53; default: - goto yy17; + goto yy21; } - yy25: + yy29: yych = *++cursor; switch (yych) { case 'o': - goto yy45; + goto yy54; case 'r': - goto yy46; + goto yy55; case 'u': - goto yy47; + goto yy56; default: - goto yy17; + goto yy21; } - yy26: + yy30: yych = *++cursor; switch (yych) { case '0': - goto yy48; + goto yy57; case '1': case '2': case '3': @@ -409,25 +448,62 @@ bool Lexer::tokenize(TokenStream& ts) case '7': case '8': case '9': - goto yy50; + goto yy59; case 'e': - goto yy52; + goto yy61; default: - goto yy17; + goto yy21; } - yy27: + yy31: yych = *++cursor; switch (yych) { case 'u': - goto yy53; + goto yy62; default: - goto yy17; + goto yy21; } - yy28: + yy32: ++cursor; - goto yy13; - yy29: +#line 261 "lexer.re" + { + ++lineno; + token_start = cursor; + + continue; + } +#line 401 "lexer.cpp" + yy34: + ++cursor; + goto yy15; + yy35: + ++cursor; + if (limit <= cursor) + return true; + yych = *cursor; + yy36: + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + goto yy35; + case ':': + goto yy18; + default: + goto yy37; + } + yy37: + cursor = marker; + goto yy15; + yy38: yych = *++cursor; switch (yych) { @@ -453,14 +529,30 @@ bool Lexer::tokenize(TokenStream& ts) case 'd': case 'e': case 'f': - goto yy54; + goto yy63; default: - goto yy30; + goto yy37; } - yy30: - cursor = marker; - goto yy13; - yy31: + yy39: + yych = *++cursor; + switch (yych) + { + case '0': + goto yy66; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + goto yy68; + default: + goto yy37; + } + yy40: yych = *++cursor; switch (yych) { @@ -527,12 +619,12 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy32; + goto yy41; } - yy32: -#line 74 "lexer.re" + yy41: +#line 84 "lexer.re" { Token t(Token::Integer, lineno, token_start + 1, cursor); t.set_int(-t.value_int()); @@ -540,8 +632,8 @@ bool Lexer::tokenize(TokenStream& ts) token_start = cursor; continue; } -#line 473 "lexer.cpp" - yy33: +#line 547 "lexer.cpp" + yy42: ++cursor; if (limit <= cursor) return true; @@ -558,7 +650,7 @@ bool Lexer::tokenize(TokenStream& ts) case '7': case '8': case '9': - goto yy33; + goto yy42; case 'A': case 'B': case 'C': @@ -612,130 +704,130 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy32; + goto yy41; } - yy35: + yy44: yych = *++cursor; switch (yych) { case 'd': - goto yy57; + goto yy70; default: - goto yy17; + goto yy21; } - yy36: + yy45: yych = *++cursor; switch (yych) { case 'l': - goto yy59; + goto yy72; default: - goto yy17; + goto yy21; } - yy37: + yy46: yych = *++cursor; switch (yych) { case 'n': - goto yy60; + goto yy73; default: - goto yy17; + goto yy21; } - yy38: + yy47: yych = *++cursor; switch (yych) { case 'v': - goto yy61; + goto yy74; default: - goto yy17; + goto yy21; } - yy39: + yy48: yych = *++cursor; switch (yych) { case 'p': - goto yy63; + goto yy76; default: - goto yy17; + goto yy21; } - yy40: + yy49: yych = *++cursor; switch (yych) { case 'p': - goto yy65; + goto yy78; default: - goto yy17; + goto yy21; } - yy41: + yy50: yych = *++cursor; switch (yych) { case 'b': - goto yy67; + goto yy80; default: - goto yy17; + goto yy21; } - yy42: + yy51: yych = *++cursor; switch (yych) { case 'q': - goto yy68; + goto yy81; case 's': - goto yy70; + goto yy83; default: - goto yy17; + goto yy21; } - yy43: + yy52: yych = *++cursor; switch (yych) { case 'd': - goto yy71; + goto yy84; default: - goto yy17; + goto yy21; } - yy44: + yy53: yych = *++cursor; switch (yych) { case 'l': - goto yy73; + goto yy86; default: - goto yy17; + goto yy21; } - yy45: + yy54: yych = *++cursor; switch (yych) { case 'p': - goto yy75; + goto yy88; default: - goto yy17; + goto yy21; } - yy46: + yy55: yych = *++cursor; switch (yych) { case 'i': - goto yy77; + goto yy90; default: - goto yy17; + goto yy21; } - yy47: + yy56: yych = *++cursor; switch (yych) { case 's': - goto yy78; + goto yy91; default: - goto yy17; + goto yy21; } - yy48: + yy57: yych = *++cursor; switch (yych) { @@ -802,12 +894,12 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy49; + goto yy58; } - yy49: -#line 67 "lexer.re" + yy58: +#line 77 "lexer.re" { ts.push_token( Token(Token::Integer, lineno, token_start + 1, cursor)); @@ -815,8 +907,8 @@ bool Lexer::tokenize(TokenStream& ts) continue; } -#line 700 "lexer.cpp" - yy50: +#line 774 "lexer.cpp" + yy59: ++cursor; if (limit <= cursor) return true; @@ -833,7 +925,7 @@ bool Lexer::tokenize(TokenStream& ts) case '7': case '8': case '9': - goto yy50; + goto yy59; case 'A': case 'B': case 'C': @@ -887,31 +979,31 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy49; + goto yy58; } - yy52: + yy61: yych = *++cursor; switch (yych) { case 'a': - goto yy79; + goto yy92; case 't': - goto yy80; + goto yy93; default: - goto yy17; + goto yy21; } - yy53: + yy62: yych = *++cursor; switch (yych) { case 'b': - goto yy82; + goto yy95; default: - goto yy17; + goto yy21; } - yy54: + yy63: ++cursor; if (limit <= cursor) return true; @@ -940,20 +1032,53 @@ bool Lexer::tokenize(TokenStream& ts) case 'd': case 'e': case 'f': - goto yy54; + goto yy63; default: - goto yy56; + goto yy65; } - yy56: -#line 83 "lexer.re" + yy65: +#line 93 "lexer.re" { ts.push_token(Token(Token::XInteger, lineno, token_start, cursor)); token_start = cursor; continue; } -#line 822 "lexer.cpp" - yy57: +#line 896 "lexer.cpp" + yy66: + ++cursor; + yy67: +#line 68 "lexer.re" + { + ts.push_token( + Token(Token::FloatingPoint, lineno, token_start, cursor)); + token_start = cursor; + + continue; + } +#line 909 "lexer.cpp" + yy68: + ++cursor; + if (limit <= cursor) + return true; + yych = *cursor; + switch (yych) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + goto yy68; + default: + goto yy67; + } + yy70: yych = *++cursor; switch (yych) { @@ -1020,38 +1145,38 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy58; + goto yy71; } - yy58: -#line 137 "lexer.re" + yy71: +#line 147 "lexer.re" { ts.push_token(Token(Token::Add, lineno)); token_start = cursor; continue; } -#line 899 "lexer.cpp" - yy59: +#line 1003 "lexer.cpp" + yy72: yych = *++cursor; switch (yych) { case 'l': - goto yy84; + goto yy97; default: - goto yy17; + goto yy21; } - yy60: + yy73: yych = *++cursor; switch (yych) { case 's': - goto yy86; + goto yy99; default: - goto yy17; + goto yy21; } - yy61: + yy74: yych = *++cursor; switch (yych) { @@ -1118,20 +1243,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy62; + goto yy75; } - yy62: -#line 158 "lexer.re" + yy75: +#line 168 "lexer.re" { ts.push_token(Token(Token::Div, lineno)); token_start = cursor; continue; } -#line 988 "lexer.cpp" - yy63: +#line 1092 "lexer.cpp" + yy76: yych = *++cursor; switch (yych) { @@ -1198,20 +1323,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy64; + goto yy77; } - yy64: -#line 116 "lexer.re" + yy77: +#line 126 "lexer.re" { ts.push_token(Token(Token::Dup, lineno)); token_start = cursor; continue; } -#line 1065 "lexer.cpp" - yy65: +#line 1169 "lexer.cpp" + yy78: yych = *++cursor; switch (yych) { @@ -1276,33 +1401,33 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; case 'f': - goto yy87; + goto yy100; case 't': - goto yy89; + goto yy102; default: - goto yy66; + goto yy79; } - yy66: -#line 186 "lexer.re" + yy79: +#line 196 "lexer.re" { ts.push_token(Token(Token::Jump, lineno)); token_start = cursor; continue; } -#line 1142 "lexer.cpp" - yy67: +#line 1246 "lexer.cpp" + yy80: yych = *++cursor; switch (yych) { case 'e': - goto yy91; + goto yy104; default: - goto yy17; + goto yy21; } - yy68: + yy81: yych = *++cursor; switch (yych) { @@ -1369,29 +1494,29 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy69; + goto yy82; } - yy69: -#line 213 "lexer.re" + yy82: +#line 223 "lexer.re" { ts.push_token(Token(Token::LessEq, lineno)); token_start = cursor; continue; } -#line 1225 "lexer.cpp" - yy70: +#line 1329 "lexer.cpp" + yy83: yych = *++cursor; switch (yych) { case 's': - goto yy92; + goto yy105; default: - goto yy17; + goto yy21; } - yy71: + yy84: yych = *++cursor; switch (yych) { @@ -1458,20 +1583,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy72; + goto yy85; } - yy72: -#line 165 "lexer.re" + yy85: +#line 175 "lexer.re" { ts.push_token(Token(Token::Mod, lineno)); token_start = cursor; continue; } -#line 1308 "lexer.cpp" - yy73: +#line 1412 "lexer.cpp" + yy86: yych = *++cursor; switch (yych) { @@ -1538,20 +1663,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy74; + goto yy87; } - yy74: -#line 151 "lexer.re" + yy87: +#line 161 "lexer.re" { ts.push_token(Token(Token::Mul, lineno)); token_start = cursor; continue; } -#line 1385 "lexer.cpp" - yy75: +#line 1489 "lexer.cpp" + yy88: yych = *++cursor; switch (yych) { @@ -1617,49 +1742,49 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; case 'r': - goto yy94; + goto yy107; default: - goto yy76; + goto yy89; } - yy76: -#line 103 "lexer.re" + yy89: +#line 113 "lexer.re" { ts.push_token(Token(Token::Pop, lineno)); token_start = cursor; continue; } -#line 1462 "lexer.cpp" - yy77: +#line 1566 "lexer.cpp" + yy90: yych = *++cursor; switch (yych) { case 'n': - goto yy96; + goto yy109; default: - goto yy17; + goto yy21; } - yy78: + yy91: yych = *++cursor; switch (yych) { case 'h': - goto yy97; + goto yy110; default: - goto yy17; + goto yy21; } - yy79: + yy92: yych = *++cursor; switch (yych) { case 'd': - goto yy99; + goto yy112; default: - goto yy17; + goto yy21; } - yy80: + yy93: yych = *++cursor; switch (yych) { @@ -1726,20 +1851,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy81; + goto yy94; } - yy81: -#line 206 "lexer.re" + yy94: +#line 216 "lexer.re" { ts.push_token(Token(Token::Ret, lineno)); token_start = cursor; continue; } -#line 1557 "lexer.cpp" - yy82: +#line 1661 "lexer.cpp" + yy95: yych = *++cursor; switch (yych) { @@ -1806,20 +1931,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy83; + goto yy96; } - yy83: -#line 144 "lexer.re" + yy96: +#line 154 "lexer.re" { ts.push_token(Token(Token::Sub, lineno)); token_start = cursor; continue; } -#line 1634 "lexer.cpp" - yy84: +#line 1738 "lexer.cpp" + yy97: yych = *++cursor; switch (yych) { @@ -1886,29 +2011,29 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy85; + goto yy98; } - yy85: -#line 199 "lexer.re" + yy98: +#line 209 "lexer.re" { ts.push_token(Token(Token::Call, lineno)); token_start = cursor; continue; } -#line 1711 "lexer.cpp" - yy86: +#line 1815 "lexer.cpp" + yy99: yych = *++cursor; switch (yych) { case 't': - goto yy101; + goto yy114; default: - goto yy17; + goto yy21; } - yy87: + yy100: yych = *++cursor; switch (yych) { @@ -1975,20 +2100,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy88; + goto yy101; } - yy88: -#line 179 "lexer.re" + yy101: +#line 189 "lexer.re" { ts.push_token(Token(Token::JumpF, lineno)); token_start = cursor; continue; } -#line 1794 "lexer.cpp" - yy89: +#line 1898 "lexer.cpp" + yy102: yych = *++cursor; switch (yych) { @@ -2055,29 +2180,29 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy90; + goto yy103; } - yy90: -#line 172 "lexer.re" + yy103: +#line 182 "lexer.re" { ts.push_token(Token(Token::JumpT, lineno)); token_start = cursor; continue; } -#line 1871 "lexer.cpp" - yy91: +#line 1975 "lexer.cpp" + yy104: yych = *++cursor; switch (yych) { case 'l': - goto yy103; + goto yy116; default: - goto yy17; + goto yy21; } - yy92: + yy105: yych = *++cursor; switch (yych) { @@ -2144,20 +2269,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy93; + goto yy106; } - yy93: -#line 219 "lexer.re" + yy106: +#line 229 "lexer.re" { ts.push_token(Token(Token::Less, lineno)); token_start = cursor; continue; } -#line 1954 "lexer.cpp" - yy94: +#line 2058 "lexer.cpp" + yy107: yych = *++cursor; switch (yych) { @@ -2224,29 +2349,29 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy95; + goto yy108; } - yy95: -#line 109 "lexer.re" + yy108: +#line 119 "lexer.re" { ts.push_token(Token(Token::PopTo, lineno)); token_start = cursor; continue; } -#line 2031 "lexer.cpp" - yy96: +#line 2135 "lexer.cpp" + yy109: yych = *++cursor; switch (yych) { case 't': - goto yy105; + goto yy118; default: - goto yy17; + goto yy21; } - yy97: + yy110: yych = *++cursor; switch (yych) { @@ -2312,22 +2437,22 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; case 'r': - goto yy107; + goto yy120; default: - goto yy98; + goto yy111; } - yy98: -#line 97 "lexer.re" + yy111: +#line 107 "lexer.re" { ts.push_token(Token(Token::Push, lineno)); token_start = cursor; continue; } -#line 2114 "lexer.cpp" - yy99: +#line 2218 "lexer.cpp" + yy112: yych = *++cursor; switch (yych) { @@ -2394,20 +2519,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy100; + goto yy113; } - yy100: -#line 123 "lexer.re" + yy113: +#line 133 "lexer.re" { ts.push_token(Token(Token::Read, lineno)); token_start = cursor; continue; } -#line 2191 "lexer.cpp" - yy101: +#line 2295 "lexer.cpp" + yy114: yych = *++cursor; switch (yych) { @@ -2474,20 +2599,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy102; + goto yy115; } - yy102: -#line 192 "lexer.re" + yy115: +#line 202 "lexer.re" { ts.push_token(Token(Token::Const, lineno)); token_start = cursor; continue; } -#line 2268 "lexer.cpp" - yy103: +#line 2372 "lexer.cpp" + yy116: yych = *++cursor; switch (yych) { @@ -2554,20 +2679,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy104; + goto yy117; } - yy104: -#line 226 "lexer.re" + yy117: +#line 236 "lexer.re" { ts.push_token(Token(Token::Label, lineno)); token_start = cursor; continue; } -#line 2345 "lexer.cpp" - yy105: +#line 2449 "lexer.cpp" + yy118: yych = *++cursor; switch (yych) { @@ -2634,20 +2759,20 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy106; + goto yy119; } - yy106: -#line 130 "lexer.re" + yy119: +#line 140 "lexer.re" { ts.push_token(Token(Token::Print, lineno)); token_start = cursor; continue; } -#line 2422 "lexer.cpp" - yy107: +#line 2526 "lexer.cpp" + yy120: yych = *++cursor; switch (yych) { @@ -2714,21 +2839,21 @@ bool Lexer::tokenize(TokenStream& ts) case 'x': case 'y': case 'z': - goto yy16; + goto yy20; default: - goto yy108; + goto yy121; } - yy108: -#line 91 "lexer.re" + yy121: +#line 101 "lexer.re" { ts.push_token(Token(Token::PushFrom, lineno)); token_start = cursor; continue; } -#line 2499 "lexer.cpp" +#line 2603 "lexer.cpp" } -#line 264 "lexer.re" +#line 284 "lexer.re" } return true; } @@ -2738,7 +2863,7 @@ bool Lexer::tokenize(TokenStream& ts) ** Note the buffer is always filled to the maximum, not just the ** number of bytes neccessary for the lexer to continue. ** -** \param nbytes - the number of bytes +** \param nbytes - the number of bytes */ void Lexer::buffer_grow(size_t new_size) diff --git a/spasm/src/asm/lexer.re b/spasm/src/asm/lexer.re index c182653..fabeaf7 100644 --- a/spasm/src/asm/lexer.re +++ b/spasm/src/asm/lexer.re @@ -13,16 +13,16 @@ namespace Lexer { Lexer::Lexer (std::istream & _file, size_t _buffer_size) - : file (&_file), buffer_size (_buffer_size), state (unsigned(-1)), - lineno (0) + : file (&_file), buffer_size (_buffer_size), state (unsigned(-1)), + lineno (0) { - buffer = new char[buffer_size]; - cursor = limit = marker = token_start = NULL; + buffer = new char[buffer_size]; + cursor = limit = marker = token_start = NULL; } Lexer::~Lexer () { - delete [] buffer; + delete [] buffer; } bool Lexer::tokenize (TokenStream &ts) @@ -44,285 +44,305 @@ re2c:define:YYSETSTATE:naked=1; /*!getstate:re2c */ - while (1) { + while (1) { /*!re2c -DIGIT = [0-9] ; -XDIGIT = [0-9a-fA-F] ; +DIGIT = [0-9] ; +XDIGIT = [0-9a-fA-F] ; -INTEGER = "-"? "0" | ([1-9] DIGIT*) ; -NONNEGATIVE = "0" | ([1-9] DIGIT*) ; -XINTEGER = "0" [xX] XDIGIT+ ; -IDENTIFIER = [a-zA-Z_] [0-9a-zA-Z_]* ; +INTEGER = "-"? "0" | ([1-9] DIGIT*) ; +NONNEGATIVE = "0" | ([1-9] DIGIT*) ; +XINTEGER = "0" [xX] XDIGIT+ ; +FLOATING = "-"? "0" | ([1-9] DIGIT*) "." NONNEGATIVE ; +IDENTIFIER = [a-zA-Z_] [0-9a-zA-Z_]* ; -INTEGER { - ts.push_token (Token (Token::Integer, lineno, - token_start, cursor)); - token_start = cursor; +INTEGER { + ts.push_token (Token (Token::Integer, lineno, + token_start, cursor)); + token_start = cursor; - continue; - } + continue; + } -"r" NONNEGATIVE { - ts.push_token (Token (Token::Integer, lineno, - token_start + 1, cursor)); - token_start = cursor; +FLOATING { + ts.push_token (Token (Token::FloatingPoint, + lineno, token_start, + cursor)); + token_start = cursor; - continue; - } -"a" NONNEGATIVE { - Token t(Token::Integer, lineno, - token_start + 1, cursor); - t.set_int(-t.value_int()); - ts.push_token(t); - token_start = cursor; - continue; - } + continue; + } -XINTEGER { - ts.push_token (Token (Token::XInteger, lineno, - token_start, cursor)); - token_start = cursor; +"r" NONNEGATIVE { + ts.push_token (Token (Token::Integer, lineno, + token_start + 1, cursor)); + token_start = cursor; - continue; - } + continue; + } +"a" NONNEGATIVE { + Token t(Token::Integer, lineno, + token_start + 1, cursor); + t.set_int(-t.value_int()); + ts.push_token(t); + token_start = cursor; + continue; + } -"pushr" { - ts.push_token (Token (Token::PushFrom, lineno)); - token_start = cursor; +XINTEGER { + ts.push_token (Token (Token::XInteger, lineno, + token_start, cursor)); + token_start = cursor; - continue; - } -"push" { - ts.push_token (Token (Token::Push, lineno)); - token_start = cursor; + continue; + } - continue; - } -"pop" { - ts.push_token (Token (Token::Pop, lineno)); - token_start = cursor; +"pushr" { + ts.push_token (Token (Token::PushFrom, lineno)); + token_start = cursor; - continue; - } -"popr" { - ts.push_token (Token (Token::PopTo, lineno)); - token_start = cursor; + continue; + } +"push" { + ts.push_token (Token (Token::Push, lineno)); + token_start = cursor; - continue; - } + continue; + } +"pop" { + ts.push_token (Token (Token::Pop, lineno)); + token_start = cursor; -"dup" { - ts.push_token (Token (Token::Dup, lineno)); - token_start = cursor; + continue; + } +"popr" { + ts.push_token (Token (Token::PopTo, lineno)); + token_start = cursor; - continue; - } + continue; + } -"read" { - ts.push_token (Token (Token::Read, lineno)); - token_start = cursor; +"dup" { + ts.push_token (Token (Token::Dup, lineno)); + token_start = cursor; - continue; - } + continue; + } -"print" { - ts.push_token (Token (Token::Print, lineno)); - token_start = cursor; +"read" { + ts.push_token (Token (Token::Read, lineno)); + token_start = cursor; - continue; - } + continue; + } -"add" { - ts.push_token (Token (Token::Add, lineno)); - token_start = cursor; +"print" { + ts.push_token (Token (Token::Print, lineno)); + token_start = cursor; - continue; - } + continue; + } -"sub" { - ts.push_token (Token (Token::Sub, lineno)); - token_start = cursor; +"add" { + ts.push_token (Token (Token::Add, lineno)); + token_start = cursor; - continue; - } + continue; + } -"mul" { - ts.push_token (Token (Token::Mul, lineno)); - token_start = cursor; +"sub" { + ts.push_token (Token (Token::Sub, lineno)); + token_start = cursor; - continue; - } + continue; + } -"div" { - ts.push_token (Token (Token::Div, lineno)); - token_start = cursor; +"mul" { + ts.push_token (Token (Token::Mul, lineno)); + token_start = cursor; - continue; - } + continue; + } -"mod" { - ts.push_token (Token (Token::Mod, lineno)); - token_start = cursor; +"div" { + ts.push_token (Token (Token::Div, lineno)); + token_start = cursor; - continue; - } + continue; + } -"jmpt" { - ts.push_token (Token (Token::JumpT, lineno)); - token_start = cursor; +"mod" { + ts.push_token (Token (Token::Mod, lineno)); + token_start = cursor; - continue; - } + continue; + } -"jmpf" { - ts.push_token (Token (Token::JumpF, lineno)); - token_start = cursor; +"jmpt" { + ts.push_token (Token (Token::JumpT, lineno)); + token_start = cursor; - continue; - } + continue; + } -"jmp" { - ts.push_token (Token (Token::Jump, lineno)); - token_start = cursor; +"jmpf" { + ts.push_token (Token (Token::JumpF, lineno)); + token_start = cursor; - continue; - } -"const" { - ts.push_token (Token (Token::Const, lineno)); - token_start = cursor; + continue; + } - continue; - } +"jmp" { + ts.push_token (Token (Token::Jump, lineno)); + token_start = cursor; -"call" { - ts.push_token (Token (Token::Call, lineno)); - token_start = cursor; + continue; + } +"const" { + ts.push_token (Token (Token::Const, lineno)); + token_start = cursor; - continue; - } + continue; + } -"ret" { - ts.push_token (Token (Token::Ret, lineno)); - token_start = cursor; +"call" { + ts.push_token (Token (Token::Call, lineno)); + token_start = cursor; - continue; - } + continue; + } -"leq" { - ts.push_token (Token (Token::LessEq, lineno)); - token_start = cursor; +"ret" { + ts.push_token (Token (Token::Ret, lineno)); + token_start = cursor; - continue; - } -"less" { - ts.push_token (Token (Token::Less, lineno)); - token_start = cursor; + continue; + } - continue; - } +"leq" { + ts.push_token (Token (Token::LessEq, lineno)); + token_start = cursor; -"label" { - ts.push_token (Token (Token::Label, lineno)); - token_start = cursor; + continue; + } +"less" { + ts.push_token (Token (Token::Less, lineno)); + token_start = cursor; - continue; - } + continue; + } -IDENTIFIER { - ts.push_token (Token (Token::Ident, lineno, token_start, - cursor)); - token_start = cursor; +"label" { + ts.push_token (Token (Token::Label, lineno)); + token_start = cursor; - continue; - } + continue; + } -[ ]+ { - token_start = cursor; +IDENTIFIER { + ts.push_token (Token (Token::Ident, lineno, token_start, + cursor)); + token_start = cursor; - continue; - } + continue; + } -"\n" { - ++lineno; - token_start = cursor; +[ ]+ { + token_start = cursor; - continue; - } + continue; + } +DIGIT* ":" { + token_start = cursor; -"\000" { - ts.push_token (Token (Token::EndInput, lineno)); + continue; + } +"#" .* "\n" { + ++lineno; + token_start = cursor; - break; - } + continue; + } +"\n" { + ++lineno; + token_start = cursor; -[^] { - return false; - } + continue; + } + +"\000" { + ts.push_token (Token (Token::EndInput, lineno)); + + break; + } + +[^] { + return false; + } */ - } - return true; - } + } + return true; + } /*! ** Fills up the buffer when neccessary. ** Note the buffer is always filled to the maximum, not just the ** number of bytes neccessary for the lexer to continue. ** -** \param nbytes - the number of bytes +** \param nbytes - the number of bytes */ void Lexer::buffer_grow (size_t new_size) { - char *new_buffer = new char[new_size]; + char *new_buffer = new char[new_size]; - std::copy (buffer, limit, new_buffer); + std::copy (buffer, limit, new_buffer); - token_start = new_buffer + (token_start - buffer); - cursor = new_buffer + (cursor - buffer); - limit = new_buffer + new_size; + token_start = new_buffer + (token_start - buffer); + cursor = new_buffer + (cursor - buffer); + limit = new_buffer + new_size; - buffer_size = new_size; + buffer_size = new_size; - delete [] buffer; - buffer = new_buffer; + delete [] buffer; + buffer = new_buffer; } void Lexer::read (size_t nbytes) { - if (token_start + nbytes > limit) { // we need larger buffer - buffer_grow (token_start - buffer + nbytes); - } + if (token_start + nbytes > limit) { // we need larger buffer + buffer_grow (token_start - buffer + nbytes); + } - std::copy (token_start, limit, buffer); - cursor -= token_start - buffer; - char *old_limit = limit - (token_start - buffer); - token_start = buffer; + std::copy (token_start, limit, buffer); + cursor -= token_start - buffer; + char *old_limit = limit - (token_start - buffer); + token_start = buffer; - file->read (old_limit, limit - old_limit); - if (file->eof ()) { - size_t bytes = file->gcount (); - std::fill (old_limit + bytes, limit, '\0'); - } + file->read (old_limit, limit - old_limit); + if (file->eof ()) { + size_t bytes = file->gcount (); + std::fill (old_limit + bytes, limit, '\0'); + } } void Lexer::buffer_init () { - file->read (buffer, buffer_size); - if (file->eof ()) { - size_t bytes = file->gcount (); - std::fill (buffer + bytes, buffer + buffer_size, '\0'); - } + file->read (buffer, buffer_size); + if (file->eof ()) { + size_t bytes = file->gcount (); + std::fill (buffer + bytes, buffer + buffer_size, '\0'); + } - cursor = marker = token_start = buffer; - limit = buffer + buffer_size; + cursor = marker = token_start = buffer; + limit = buffer + buffer_size; } -} // namespace Lexer +} // namespace Lexer -} // namespace ASM -} // namespace SpasmImpl +} // namespace ASM +} // namespace SpasmImpl diff --git a/spasm/src/asm/token.cpp b/spasm/src/asm/token.cpp index 4f298cf..fa612e3 100644 --- a/spasm/src/asm/token.cpp +++ b/spasm/src/asm/token.cpp @@ -22,20 +22,33 @@ Token::Token(Token::Token_type type, const char* end) : _type(type), _lineno(lineno) { - if (_type == Integer || _type == XInteger) + switch (_type) { - _value_int = strtol(start, NULL, 0); - } - else if (_type == Ident) - { - if (end) + case Integer: + case XInteger: + { + _value_int = strtol(start, NULL, 0); + break; + } + case FloatingPoint: { - _value_str = std::string(start, end); + _value_double = strtod(start, NULL); + break; } - else + case Ident: { - _value_str = std::string(start); + if (end) + { + _value_str = std::string(start, end); + } + else + { + _value_str = std::string(start); + } + break; } + default: + break; } } @@ -44,7 +57,7 @@ Token::Token_type Token::type() const return _type; } -int Token::value_int() const +int64_t Token::value_int() const { return _value_int; } diff --git a/spasm/src/asm/token.hpp b/spasm/src/asm/token.hpp index 364b315..8f18768 100644 --- a/spasm/src/asm/token.hpp +++ b/spasm/src/asm/token.hpp @@ -45,6 +45,7 @@ class Token // Register, Integer, XInteger, + FloatingPoint, EndInput, NotUsed }; @@ -57,8 +58,10 @@ class Token size_t lineno() const; - int value_int() const; - void set_int(int v) { _value_int = v; } + int64_t value_int() const; + void set_int(int64_t v) { _value_int = v; } + + double value_double() const { return _value_double; } const std::string& value_str() const; @@ -67,7 +70,8 @@ class Token size_t _lineno; - int _value_int; + int64_t _value_int; + double _value_double; std::string _value_str; }; diff --git a/spasm/src/spasm.cpp b/spasm/src/spasm.cpp index 8e5e36d..58fb6d4 100644 --- a/spasm/src/spasm.cpp +++ b/spasm/src/spasm.cpp @@ -46,7 +46,6 @@ Spasm::RunResult Spasm::run() const auto instruction = m_ByteCode[m_PC++]; const auto opcode = OpCodes(instruction & 0x3f); const auto size = instruction >> 6; - assert(size == 0 && "no long args yet"); switch (opcode) { case OpCodes::Halt: @@ -281,7 +280,7 @@ void Spasm::divide(reg_t a0, reg_t a1, reg_t a2) */ void Spasm::modulus(reg_t a0, reg_t a1, reg_t a2) { - set_local(a0, get_local(a1) % get_local(a2)); + set_local(a0, data_t(int64_t(get_local(a1)) % int64_t(get_local(a2)))); } /*! @@ -410,14 +409,60 @@ void Spasm::push_data(data_t data) reg_t Spasm::read_reg(size_t size) { - assert(size == 0); - return m_ByteCode[m_PC++]; + switch (size) + { + case 0: + return m_ByteCode[m_PC++]; + case 1: + { + auto result = *reinterpret_cast<int16_t*>(&m_ByteCode[0] + m_PC); + m_PC += 2; + return result; + } + case 2: + { + auto result = *reinterpret_cast<int32_t*>(&m_ByteCode[0] + m_PC); + m_PC += 4; + return result; + } + case 3: + { + auto result = *reinterpret_cast<int64_t*>(&m_ByteCode[0] + m_PC); + m_PC += 8; + return result; + } + } + assert(false && "not reached"); + return 0; } data_t Spasm::read_number(size_t size) { - assert(size == 0); - return m_ByteCode[m_PC++]; + switch (size) + { + case 0: + return m_ByteCode[m_PC++]; + case 1: + { + auto result = *reinterpret_cast<int16_t*>(&m_ByteCode[0] + m_PC); + m_PC += 2; + return result; + } + case 2: + { + auto result = *reinterpret_cast<int32_t*>(&m_ByteCode[0] + m_PC); + m_PC += 4; + return result; + } + case 3: + { + auto result = *reinterpret_cast<double*>(&m_ByteCode[0] + m_PC); + m_PC += 8; + return result; + } + } + assert(false && "not reached"); + return 0; } } // namespace SpasmImpl diff --git a/spasm/src/types.hpp b/spasm/src/types.hpp index 26450db..59562e1 100644 --- a/spasm/src/types.hpp +++ b/spasm/src/types.hpp @@ -9,7 +9,7 @@ namespace SpasmImpl { typedef int8_t byte; typedef size_t PC_t; -typedef int data_t; +typedef double data_t; class Spasm; typedef void (Spasm::*Operation)(); diff --git a/website/content/post/homeworks.md b/website/content/post/homeworks.md new file mode 100644 index 0000000..7a4e0c5 --- /dev/null +++ b/website/content/post/homeworks.md @@ -0,0 +1,11 @@ +--- +title: "Homeworks" +date: 2018-11-17T19:01:49+02:00 +draft: false +--- +# Virtual Machine related homeworks + +The tasks that can be used as homeworks are added as +[issues](https://github.com/SofiaCPP/IPL/issues). Their status can be monitored +on the [projects page](https://github.com/SofiaCPP/IPL/projects) as well. + |
