Website Summary Files Commits Branches @commit @diff @stats
diff options
context:
space:
mode:
Commit0b2444013dfb6bfb0c033b5b827610f6df49ede5 (patch)
Author
 dtrendafilov <trendafilov.dn@gmail.com>
2018-11-25 09:08:47 +0200
Committer
 GitHub <noreply@github.com>
2018-11-25 09:08:47 +0200
Filese6206cd3329067cd48dd0ccf90262f6eaa6cdbbb
IPL-0b2444013dfb6bfb0c033b5b827610f6df49ede5.tar
IPL-0b2444013dfb6bfb0c033b5b827610f6df49ede5.tar.gz
IPL-0b2444013dfb6bfb0c033b5b827610f6df49ede5.zip
Parent156d0957c1b36bba2685fef548a8573e9337309a (diff)
Parent4fca8e8e6c1056aed11437c87e9175232b48c8f4 (diff)
Merge branch 'master' into json-to-ast
35 files changed, 1840 insertions, 616 deletions
-rw-r--r--JSImpl/test/empty.cpp116
-rw-r--r--JSImpl/test/sprtTests.cpp38
-rw-r--r--README.md5
-rw-r--r--homework/81333/brainfsck/.gitignore3
-rw-r--r--homework/81333/brainfsck/ChangeLog.md3
-rw-r--r--homework/81333/brainfsck/LICENSE232
-rw-r--r--homework/81333/brainfsck/README.md28
-rw-r--r--homework/81333/brainfsck/Setup.hs2
-rw-r--r--homework/81333/brainfsck/app/Main.hs22
-rw-r--r--homework/81333/brainfsck/brainfsck.cabal74
-rw-r--r--homework/81333/brainfsck/examples/fact.bf42
-rw-r--r--homework/81333/brainfsck/examples/hello.bf3
-rw-r--r--homework/81333/brainfsck/examples/input.bf13
-rw-r--r--homework/81333/brainfsck/examples/pretty.bf31
-rw-r--r--homework/81333/brainfsck/examples/sierpinski.bf5
-rw-r--r--homework/81333/brainfsck/examples/squares.bf5
-rw-r--r--homework/81333/brainfsck/examples/sum.bf100
-rw-r--r--homework/81333/brainfsck/package.yaml51
-rw-r--r--homework/81333/brainfsck/src/Lib.hs30
-rw-r--r--homework/81333/brainfsck/src/Text/Brainfsck/Parser.hs56
-rw-r--r--homework/81333/brainfsck/src/Text/Brainfsck/Types.hs24
-rw-r--r--homework/81333/brainfsck/src/Text/Brainfsck/Util.hs10
-rw-r--r--homework/81333/brainfsck/stack.yaml64
-rw-r--r--homework/81333/brainfsck/test/Spec.hs2
-rw-r--r--spasm/src/asm/assembler.cpp108
-rw-r--r--spasm/src/asm/assembler.hpp2
-rw-r--r--spasm/src/asm/bytecode.cpp52
-rw-r--r--spasm/src/asm/bytecode.hpp9
-rw-r--r--spasm/src/asm/lexer.cpp795
-rw-r--r--spasm/src/asm/lexer.re418
-rw-r--r--spasm/src/asm/token.cpp33
-rw-r--r--spasm/src/asm/token.hpp10
-rw-r--r--spasm/src/spasm.cpp57
-rw-r--r--spasm/src/types.hpp2
-rw-r--r--website/content/post/homeworks.md11
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);
diff --git a/README.md b/README.md
index d0fd7ee..cbf90e2 100644
--- a/README.md
+++ b/README.md
@@ -5,3 +5,8 @@ Implementation of Programming Languages course
[![Build status](https://ci.appveyor.com/api/projects/status/1h7vih4i36jl6xs6?svg=true)](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.
+