From 68f634db59f34f11830beeca3c0b3e249966c780 Mon Sep 17 00:00:00 2001
From: Tapeline
Date: Fri, 23 Feb 2024 01:11:38 +0500
Subject: [PATCH 01/10] Add lang/data library. Fix bool, number and string
behaviour in hashmaps. Fix String::chars Add #?see construction to
DocumentationGenerator
---
.../quailj/docgen/DocumentationGenerator.java | 30 +++
.../quailj/launcher/QuailLauncher.java | 2 +-
.../me/tapeline/quailj/parsing/Parser.java | 2 +
.../parsing/nodes/comments/DocSeeNode.java | 19 ++
.../me/tapeline/quailj/runtime/Runtime.java | 2 +
.../basic/classes/string/StringFuncChars.java | 2 +-
.../quailj/runtime/std/data/DataLibrary.java | 41 ++++
.../runtime/std/data/bytes/BytesAnd.java | 60 ++++++
.../runtime/std/data/bytes/BytesAsBase64.java | 40 ++++
.../runtime/std/data/bytes/BytesAsBits.java | 41 ++++
.../std/data/bytes/BytesAsSignedInt.java | 43 ++++
.../std/data/bytes/BytesAsUnsignedInt.java | 44 ++++
.../runtime/std/data/bytes/BytesBitAt.java | 55 +++++
.../std/data/bytes/BytesFromBase64.java | 41 ++++
.../runtime/std/data/bytes/BytesFromBits.java | 45 ++++
.../std/data/bytes/BytesFromSignedInt.java | 42 ++++
.../runtime/std/data/bytes/BytesImplies.java | 60 ++++++
.../runtime/std/data/bytes/BytesNand.java | 60 ++++++
.../runtime/std/data/bytes/BytesNor.java | 60 ++++++
.../runtime/std/data/bytes/BytesOr.java | 60 ++++++
.../runtime/std/data/bytes/BytesSetBitAt.java | 63 ++++++
.../runtime/std/data/bytes/BytesUtils.java | 24 +++
.../runtime/std/data/bytes/BytesXnor.java | 60 ++++++
.../runtime/std/data/bytes/BytesXor.java | 60 ++++++
.../runtime/std/data/bytes/DataLibBytes.java | 195 ++++++++++++++++++
.../runtime/std/data/deque/DataLibDeque.java | 122 +++++++++++
.../runtime/std/data/deque/DequeAddBack.java | 47 +++++
.../runtime/std/data/deque/DequeAddFront.java | 47 +++++
.../runtime/std/data/deque/DequeClear.java | 41 ++++
.../runtime/std/data/deque/DequePeekBack.java | 39 ++++
.../std/data/deque/DequePeekFront.java | 39 ++++
.../runtime/std/data/deque/DequePopBack.java | 40 ++++
.../runtime/std/data/deque/DequePopFront.java | 40 ++++
.../runtime/std/data/deque/DequeSize.java | 40 ++++
.../runtime/std/data/queue/DataLibQueue.java | 117 +++++++++++
.../runtime/std/data/queue/QueueAdd.java | 48 +++++
.../runtime/std/data/queue/QueueClear.java | 41 ++++
.../runtime/std/data/queue/QueuePeek.java | 39 ++++
.../runtime/std/data/queue/QueuePop.java | 40 ++++
.../runtime/std/data/queue/QueueSize.java | 40 ++++
.../runtime/std/data/set/DataLibSet.java | 141 +++++++++++++
.../quailj/runtime/std/data/set/SetAdd.java | 47 +++++
.../quailj/runtime/std/data/set/SetClear.java | 41 ++++
.../runtime/std/data/set/SetConstructor.java | 56 +++++
.../runtime/std/data/set/SetIntersection.java | 47 +++++
.../runtime/std/data/set/SetRemove.java | 47 +++++
.../quailj/runtime/std/data/set/SetSize.java | 40 ++++
.../quailj/runtime/std/data/set/SetUnion.java | 47 +++++
.../tapeline/quailj/typing/classes/QBool.java | 16 ++
.../quailj/typing/classes/QNumber.java | 17 +-
.../quailj/typing/classes/QString.java | 16 ++
docs-md/libs/data.q | 65 ++++++
docs-md/libs/ji.html | 10 +-
docs-md/libs/ji.q | 10 +
docs-md/spec/chapter13.md | 12 ++
program6.q | 10 +
56 files changed, 2545 insertions(+), 8 deletions(-)
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/parsing/nodes/comments/DocSeeNode.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/DataLibrary.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAnd.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAsBase64.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAsBits.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAsSignedInt.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAsUnsignedInt.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesBitAt.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesFromBase64.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesFromBits.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesFromSignedInt.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesImplies.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesNand.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesNor.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesOr.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesSetBitAt.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesUtils.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesXnor.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesXor.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/DataLibBytes.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DataLibDeque.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequeAddBack.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequeAddFront.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequeClear.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequePeekBack.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequePeekFront.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequePopBack.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequePopFront.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequeSize.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/DataLibQueue.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueueAdd.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueueClear.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueuePeek.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueuePop.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueueSize.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/DataLibSet.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetAdd.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetClear.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetConstructor.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetIntersection.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetRemove.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetSize.java
create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetUnion.java
create mode 100644 docs-md/libs/data.q
create mode 100644 program6.q
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/docgen/DocumentationGenerator.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/docgen/DocumentationGenerator.java
index 3a34532..9ed0869 100644
--- a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/docgen/DocumentationGenerator.java
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/docgen/DocumentationGenerator.java
@@ -17,6 +17,14 @@
public class DocumentationGenerator {
+ private HashMap flags = new HashMap<>();
+
+ public DocumentationGenerator() {}
+
+ public DocumentationGenerator(HashMap flags) {
+ this.flags = flags;
+ }
+
private static final HashMap colorAssociations = Dict.make(
new Pair<>("default", "primary"),
new Pair<>("red", "danger"),
@@ -117,10 +125,20 @@ private List convertToList(Node node) {
return Collections.singletonList(node);
}
+ private String convertSeeLink(String link) {
+ if (link.startsWith(">")) {
+ link = link.substring(link.indexOf('>') + 1).replaceAll("\\.q", "");
+ if (flags.containsKey("seeLinkPrefix"))
+ link = flags.get("seeLinkPrefix") + link;
+ }
+ return link;
+ }
+
public String compileAllDocNodes(List nodes) {
List docStrings = new ArrayList<>();
List docBadges = new ArrayList<>();
List authors = new ArrayList<>();
+ List seeLinks = new ArrayList<>();
String since = null;
for (Node node : nodes) {
if (node instanceof DocSinceNode)
@@ -133,6 +151,8 @@ else if (node instanceof DocBadgeNode)
docBadges.add(((DocBadgeNode) node));
else if (node instanceof DocTOCNode)
tocEntries.add(((DocTOCNode) node));
+ else if (node instanceof DocSeeNode)
+ seeLinks.add(((DocSeeNode) node).see);
}
StringBuilder sb = new StringBuilder();
if (!docBadges.isEmpty()) {
@@ -148,6 +168,16 @@ else if (node instanceof DocTOCNode)
sb.append(docString).append("
");
sb.append("
");
}
+ if (!seeLinks.isEmpty()) {
+ sb.append("See:
");
+ for (String see : seeLinks)
+ sb.append("")
+ .append(convertSeeLink(see))
+ .append("");
+ sb.append("
");
+ }
if (authors.size() == 1) {
sb.append("Author: ").append(authors.get(0)).append("
");
}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/launcher/QuailLauncher.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/launcher/QuailLauncher.java
index 46aee9e..768e98b 100644
--- a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/launcher/QuailLauncher.java
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/launcher/QuailLauncher.java
@@ -98,7 +98,7 @@ public QObject launch(String[] args) throws IOException, PreprocessorException,
if (mode.equalsIgnoreCase("gendoc")) {
if (launchCommandParser.getOutputFile() == null)
throw new LauncherException("Output file for documentation is not specified");
- DocumentationGenerator generator = new DocumentationGenerator();
+ DocumentationGenerator generator = new DocumentationGenerator(localFlags);
String name = new File(launchCommandParser.getTargetScript()).getName();
if (localFlags.containsKey("documentationHeadline"))
name = localFlags.get("documentationHeadline").toString();
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/parsing/Parser.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/parsing/Parser.java
index f0f9f56..2e88f05 100644
--- a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/parsing/Parser.java
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/parsing/Parser.java
@@ -730,6 +730,8 @@ private Node parseDocs() {
return new DocBadgeNode(docToken);
else if (docToken.getLexeme().startsWith("#?author"))
return new DocAuthorNode(docToken);
+ else if (docToken.getLexeme().startsWith("#?see"))
+ return new DocSeeNode(docToken);
else if (docToken.getLexeme().startsWith("#?since"))
return new DocSinceNode(docToken);
else if (docToken.getLexeme().startsWith("#?toc-entry"))
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/parsing/nodes/comments/DocSeeNode.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/parsing/nodes/comments/DocSeeNode.java
new file mode 100644
index 0000000..23d7997
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/parsing/nodes/comments/DocSeeNode.java
@@ -0,0 +1,19 @@
+package me.tapeline.quailj.parsing.nodes.comments;
+
+import me.tapeline.quailj.lexing.Token;
+
+public class DocSeeNode extends DocNode {
+
+ public final String see;
+
+ public DocSeeNode(Token token) {
+ super(token);
+ see = token.getLexeme().replaceFirst("#\\?see", "").trim();
+ }
+
+ @Override
+ public String stringRepr() {
+ return "See: " + see;
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/Runtime.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/Runtime.java
index 3272257..0d06ff6 100644
--- a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/Runtime.java
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/Runtime.java
@@ -27,6 +27,7 @@
import me.tapeline.quailj.runtime.std.basic.numbers.*;
import me.tapeline.quailj.runtime.std.basic.threading.QThread;
import me.tapeline.quailj.runtime.std.cli.CliLibrary;
+import me.tapeline.quailj.runtime.std.data.DataLibrary;
import me.tapeline.quailj.runtime.std.event.EventLibrary;
import me.tapeline.quailj.runtime.std.fs.FSLibrary;
import me.tapeline.quailj.runtime.std.ji.JILibrary;
@@ -268,6 +269,7 @@ private void registerDefaults() {
libraryLoader.addBuiltinLibrary(new MathLibrary());
libraryLoader.addBuiltinLibrary(new ReflectLibrary());
libraryLoader.addBuiltinLibrary(new CliLibrary());
+ libraryLoader.addBuiltinLibrary(new DataLibrary());
}
public void error(String message) throws RuntimeStriker {
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/basic/classes/string/StringFuncChars.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/basic/classes/string/StringFuncChars.java
index bd0ea09..822a381 100644
--- a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/basic/classes/string/StringFuncChars.java
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/basic/classes/string/StringFuncChars.java
@@ -36,7 +36,7 @@ public QObject action(Runtime runtime, HashMap args, List result = new ArrayList<>();
for (int i = 0; i < thisString.length(); i++)
- result.add(Val(thisString.charAt(i)));
+ result.add(Val(Character.toString(thisString.charAt(i))));
return Val(result);
}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/DataLibrary.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/DataLibrary.java
new file mode 100644
index 0000000..ce168e5
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/DataLibrary.java
@@ -0,0 +1,41 @@
+package me.tapeline.quailj.runtime.std.data;
+
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.runtime.librarymanagement.BuiltinLibrary;
+import me.tapeline.quailj.runtime.std.data.bytes.DataLibBytes;
+import me.tapeline.quailj.runtime.std.data.deque.DataLibDeque;
+import me.tapeline.quailj.runtime.std.data.queue.DataLibQueue;
+import me.tapeline.quailj.runtime.std.data.set.DataLibSet;
+import me.tapeline.quailj.runtime.std.math.MathFuncGcd;
+import me.tapeline.quailj.runtime.std.math.MathFuncLcm;
+import me.tapeline.quailj.runtime.std.math.MathFuncProduct;
+import me.tapeline.quailj.typing.classes.QObject;
+
+import java.util.HashMap;
+
+public class DataLibrary implements BuiltinLibrary {
+
+ @Override
+ public String id() {
+ return "lang/data";
+ }
+
+ @Override
+ public Runtime initializeRuntime() {
+ return new Runtime();
+ }
+
+ @Override
+ public QObject constructLibrary(Runtime runtime) {
+ HashMap contents = new HashMap<>();
+ contents.put("Bytes", DataLibBytes.prototype(runtime));
+ contents.put("Queue", DataLibQueue.prototype(runtime));
+ contents.put("Deque", DataLibDeque.prototype(runtime));
+ contents.put("Set", DataLibSet.prototype(runtime));
+
+ runtime.getMemory().table.putAll(contents);
+
+ return QObject.Val(contents);
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAnd.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAnd.java
new file mode 100644
index 0000000..445c902
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAnd.java
@@ -0,0 +1,60 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.classes.errors.QUnsuitableTypeException;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class BytesAnd extends QBuiltinFunc {
+
+ public BytesAnd(Runtime runtime) {
+ super(
+ "and",
+ Arrays.asList(
+ new FuncArgument(
+ "a",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "b",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ byte[] a = BytesUtils.getByteArray(runtime, args.get("a"));
+ byte[] b = BytesUtils.getByteArray(runtime, args.get("b"));
+ if (a == null) {
+ runtime.error(new QUnsuitableTypeException("Bytes | String", args.get("a")));
+ return Val();
+ }
+ if (b == null) {
+ runtime.error(new QUnsuitableTypeException("Bytes | String", args.get("b")));
+ return Val();
+ }
+ byte[] result = new byte[Math.min(a.length, b.length)];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = (byte) (a[i] & b[i]);
+ }
+ return new DataLibBytes(result);
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAsBase64.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAsBase64.java
new file mode 100644
index 0000000..ceffc59
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAsBase64.java
@@ -0,0 +1,40 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+
+public class BytesAsBase64 extends QBuiltinFunc {
+
+ public BytesAsBase64(Runtime runtime) {
+ super(
+ "asBase64",
+ Arrays.asList(
+ new FuncArgument(
+ "bytes",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ return Val(new String(Base64.getEncoder().encode(DataLibBytes.validate(runtime, args.get("bytes")).data)));
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAsBits.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAsBits.java
new file mode 100644
index 0000000..ec3ad53
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAsBits.java
@@ -0,0 +1,41 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import org.apache.commons.codec.binary.BinaryCodec;
+
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+
+public class BytesAsBits extends QBuiltinFunc {
+
+ public BytesAsBits(Runtime runtime) {
+ super(
+ "asBits",
+ Arrays.asList(
+ new FuncArgument(
+ "bytes",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ return Val(BinaryCodec.toAsciiString(DataLibBytes.validate(runtime, args.get("bytes")).data));
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAsSignedInt.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAsSignedInt.java
new file mode 100644
index 0000000..e9623d0
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAsSignedInt.java
@@ -0,0 +1,43 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class BytesAsSignedInt extends QBuiltinFunc {
+
+ public BytesAsSignedInt(Runtime runtime) {
+ super(
+ "asSignedInt",
+ Arrays.asList(
+ new FuncArgument(
+ "bytes",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ int value = 0;
+ for (byte b : DataLibBytes.validate(runtime, args.get("bytes")).data) {
+ value = (value << 8) + (b & 0xFF);
+ }
+ return Val(value);
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAsUnsignedInt.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAsUnsignedInt.java
new file mode 100644
index 0000000..b2da93b
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesAsUnsignedInt.java
@@ -0,0 +1,44 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class BytesAsUnsignedInt extends QBuiltinFunc {
+
+ public BytesAsUnsignedInt(Runtime runtime) {
+ super(
+ "asUnsignedInt",
+ Arrays.asList(
+ new FuncArgument(
+ "bytes",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ long value = 0;
+ byte[] data = DataLibBytes.validate(runtime, args.get("bytes")).data;
+ for (int i = 0; i < Math.min(data.length, 8); i++) {
+ value += (long) (Byte.toUnsignedInt(data[i]) * Math.pow(256, i));
+ }
+ return Val(value);
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesBitAt.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesBitAt.java
new file mode 100644
index 0000000..b9d941d
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesBitAt.java
@@ -0,0 +1,55 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.classes.errors.QIndexOutOfBoundsException;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class BytesBitAt extends QBuiltinFunc {
+
+ public BytesBitAt(Runtime runtime) {
+ super(
+ "bitAt",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[] {ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "pos",
+ QObject.Val(),
+ new int[] {ModifierConstants.NUM},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ byte[] data = DataLibBytes.validate(runtime, args.get("bytes")).data;
+ if (data.length <= args.get("pos").numValue()) {
+ runtime.error(new QIndexOutOfBoundsException(args.get("pos"), Val(data.length)));
+ return Val();
+ }
+ int pos = ((int) args.get("pos").numValue());
+ byte segment = data[pos / 8];
+ int posInSegment = pos % 8;
+ int mask = 1 << posInSegment;
+ return Val((segment & mask) > 0);
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesFromBase64.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesFromBase64.java
new file mode 100644
index 0000000..c53bb25
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesFromBase64.java
@@ -0,0 +1,41 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+
+public class BytesFromBase64 extends QBuiltinFunc {
+
+ public BytesFromBase64(Runtime runtime) {
+ super(
+ "fromBase64",
+ Arrays.asList(
+ new FuncArgument(
+ "b64",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ byte[] data = Base64.getDecoder().decode(args.get("b64").strValue());
+ return new DataLibBytes(data);
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesFromBits.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesFromBits.java
new file mode 100644
index 0000000..149a995
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesFromBits.java
@@ -0,0 +1,45 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import org.apache.commons.codec.binary.BinaryCodec;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+
+public class BytesFromBits extends QBuiltinFunc {
+
+ public BytesFromBits(Runtime runtime) {
+ super(
+ "fromBits",
+ Arrays.asList(
+ new FuncArgument(
+ "bits",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ String bits = args.get("bits").strValue();
+ bits = StringUtils.repeat('0', bits.length() % 8) + bits;
+ byte[] data = BinaryCodec.fromAscii(bits.toCharArray());
+ return new DataLibBytes(data);
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesFromSignedInt.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesFromSignedInt.java
new file mode 100644
index 0000000..ce0983d
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesFromSignedInt.java
@@ -0,0 +1,42 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class BytesFromSignedInt extends QBuiltinFunc {
+
+ public BytesFromSignedInt(Runtime runtime) {
+ super(
+ "fromSignedInt",
+ Arrays.asList(
+ new FuncArgument(
+ "int",
+ QObject.Val(),
+ new int[] {ModifierConstants.NUM},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
+ buffer.putLong(((long) args.get("int").numValue()));
+ return new DataLibBytes(buffer.array());
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesImplies.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesImplies.java
new file mode 100644
index 0000000..b011956
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesImplies.java
@@ -0,0 +1,60 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.classes.errors.QUnsuitableTypeException;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class BytesImplies extends QBuiltinFunc {
+
+ public BytesImplies(Runtime runtime) {
+ super(
+ "implies",
+ Arrays.asList(
+ new FuncArgument(
+ "a",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "b",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ byte[] a = BytesUtils.getByteArray(runtime, args.get("a"));
+ byte[] b = BytesUtils.getByteArray(runtime, args.get("b"));
+ if (a == null) {
+ runtime.error(new QUnsuitableTypeException("Bytes | String", args.get("a")));
+ return Val();
+ }
+ if (b == null) {
+ runtime.error(new QUnsuitableTypeException("Bytes | String", args.get("b")));
+ return Val();
+ }
+ byte[] result = new byte[Math.min(a.length, b.length)];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = (byte) (~a[i] & b[i]);
+ }
+ return new DataLibBytes(result);
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesNand.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesNand.java
new file mode 100644
index 0000000..8e4f7b0
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesNand.java
@@ -0,0 +1,60 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.classes.errors.QUnsuitableTypeException;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class BytesNand extends QBuiltinFunc {
+
+ public BytesNand(Runtime runtime) {
+ super(
+ "nand",
+ Arrays.asList(
+ new FuncArgument(
+ "a",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "b",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ byte[] a = BytesUtils.getByteArray(runtime, args.get("a"));
+ byte[] b = BytesUtils.getByteArray(runtime, args.get("b"));
+ if (a == null) {
+ runtime.error(new QUnsuitableTypeException("Bytes | String", args.get("a")));
+ return Val();
+ }
+ if (b == null) {
+ runtime.error(new QUnsuitableTypeException("Bytes | String", args.get("b")));
+ return Val();
+ }
+ byte[] result = new byte[Math.min(a.length, b.length)];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = (byte) ~(a[i] & b[i]);
+ }
+ return new DataLibBytes(result);
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesNor.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesNor.java
new file mode 100644
index 0000000..2b7b46b
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesNor.java
@@ -0,0 +1,60 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.classes.errors.QUnsuitableTypeException;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class BytesNor extends QBuiltinFunc {
+
+ public BytesNor(Runtime runtime) {
+ super(
+ "nor",
+ Arrays.asList(
+ new FuncArgument(
+ "a",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "b",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ byte[] a = BytesUtils.getByteArray(runtime, args.get("a"));
+ byte[] b = BytesUtils.getByteArray(runtime, args.get("b"));
+ if (a == null) {
+ runtime.error(new QUnsuitableTypeException("Bytes | String", args.get("a")));
+ return Val();
+ }
+ if (b == null) {
+ runtime.error(new QUnsuitableTypeException("Bytes | String", args.get("b")));
+ return Val();
+ }
+ byte[] result = new byte[Math.min(a.length, b.length)];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = (byte) ~(a[i] | b[i]);
+ }
+ return new DataLibBytes(result);
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesOr.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesOr.java
new file mode 100644
index 0000000..260320c
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesOr.java
@@ -0,0 +1,60 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.classes.errors.QUnsuitableTypeException;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class BytesOr extends QBuiltinFunc {
+
+ public BytesOr(Runtime runtime) {
+ super(
+ "or",
+ Arrays.asList(
+ new FuncArgument(
+ "a",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "b",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ byte[] a = BytesUtils.getByteArray(runtime, args.get("a"));
+ byte[] b = BytesUtils.getByteArray(runtime, args.get("b"));
+ if (a == null) {
+ runtime.error(new QUnsuitableTypeException("Bytes | String", args.get("a")));
+ return Val();
+ }
+ if (b == null) {
+ runtime.error(new QUnsuitableTypeException("Bytes | String", args.get("b")));
+ return Val();
+ }
+ byte[] result = new byte[Math.min(a.length, b.length)];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = (byte) (a[i] | b[i]);
+ }
+ return new DataLibBytes(result);
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesSetBitAt.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesSetBitAt.java
new file mode 100644
index 0000000..f02be51
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesSetBitAt.java
@@ -0,0 +1,63 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.classes.errors.QIndexOutOfBoundsException;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class BytesSetBitAt extends QBuiltinFunc {
+
+ public BytesSetBitAt(Runtime runtime) {
+ super(
+ "setBitAt",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[] {ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "pos",
+ QObject.Val(),
+ new int[] {ModifierConstants.NUM},
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "bit",
+ QObject.Val(),
+ new int[] {ModifierConstants.BOOL},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ byte[] data = DataLibBytes.validate(runtime, args.get("bytes")).data;
+ if (data.length <= args.get("pos").numValue()) {
+ runtime.error(new QIndexOutOfBoundsException(args.get("pos"), Val(data.length)));
+ return Val();
+ }
+ int pos = ((int) args.get("pos").numValue());
+ int posInSegment = pos % 8;
+ if (args.get("bit").boolValue())
+ data[pos / 8] |= (byte) (1 << posInSegment);
+ else
+ data[pos / 8] &= (byte) ~(1 << posInSegment);
+ return Val();
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesUtils.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesUtils.java
new file mode 100644
index 0000000..6c3d8e6
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesUtils.java
@@ -0,0 +1,24 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+import me.tapeline.quailj.typing.classes.QObject;
+import org.apache.commons.lang3.StringUtils;
+
+public class BytesUtils {
+
+ public static byte[] getByteArray(Runtime runtime, QObject object) throws RuntimeStriker {
+ if (object instanceof DataLibBytes) {
+ return DataLibBytes.validate(runtime, object).data;
+ } else if (object.isStr()) {
+ String s = object.strValue();
+ s = StringUtils.repeat('0', s.length() % 8) + s;
+ byte[] data = new byte[s.length() / 8];
+ for (int i = 0; i < s.length() / 8; i++) {
+ data[i] = Byte.parseByte(s.substring(i, (i + 1) * 8));
+ }
+ return data;
+ } else return null;
+ }
+
+}
\ No newline at end of file
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesXnor.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesXnor.java
new file mode 100644
index 0000000..f6bb70a
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesXnor.java
@@ -0,0 +1,60 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.classes.errors.QUnsuitableTypeException;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class BytesXnor extends QBuiltinFunc {
+
+ public BytesXnor(Runtime runtime) {
+ super(
+ "xnor",
+ Arrays.asList(
+ new FuncArgument(
+ "a",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "b",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ byte[] a = BytesUtils.getByteArray(runtime, args.get("a"));
+ byte[] b = BytesUtils.getByteArray(runtime, args.get("b"));
+ if (a == null) {
+ runtime.error(new QUnsuitableTypeException("Bytes | String", args.get("a")));
+ return Val();
+ }
+ if (b == null) {
+ runtime.error(new QUnsuitableTypeException("Bytes | String", args.get("b")));
+ return Val();
+ }
+ byte[] result = new byte[Math.min(a.length, b.length)];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = (byte) ~(a[i] ^ b[i]);
+ }
+ return new DataLibBytes(result);
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesXor.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesXor.java
new file mode 100644
index 0000000..627bd15
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/BytesXor.java
@@ -0,0 +1,60 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.classes.errors.QUnsuitableTypeException;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class BytesXor extends QBuiltinFunc {
+
+ public BytesXor(Runtime runtime) {
+ super(
+ "xor",
+ Arrays.asList(
+ new FuncArgument(
+ "a",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "b",
+ QObject.Val(),
+ new int[] {ModifierConstants.STR, ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ byte[] a = BytesUtils.getByteArray(runtime, args.get("a"));
+ byte[] b = BytesUtils.getByteArray(runtime, args.get("b"));
+ if (a == null) {
+ runtime.error(new QUnsuitableTypeException("Bytes | String", args.get("a")));
+ return Val();
+ }
+ if (b == null) {
+ runtime.error(new QUnsuitableTypeException("Bytes | String", args.get("b")));
+ return Val();
+ }
+ byte[] result = new byte[Math.min(a.length, b.length)];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = (byte) (a[i] ^ b[i]);
+ }
+ return new DataLibBytes(result);
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/DataLibBytes.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/DataLibBytes.java
new file mode 100644
index 0000000..4c01ec9
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/bytes/DataLibBytes.java
@@ -0,0 +1,195 @@
+package me.tapeline.quailj.runtime.std.data.bytes;
+
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+import me.tapeline.quailj.runtime.Table;
+import me.tapeline.quailj.runtime.std.basic.threading.QThread;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.classes.errors.*;
+import me.tapeline.quailj.typing.classes.utils.Initializable;
+import me.tapeline.quailj.utils.Dict;
+import me.tapeline.quailj.utils.Pair;
+import me.tapeline.quailj.runtime.std.data.bytes.BytesXnor;
+import me.tapeline.quailj.runtime.std.data.bytes.BytesOr;
+import me.tapeline.quailj.runtime.std.data.bytes.BytesAsSignedInt;
+import me.tapeline.quailj.runtime.std.data.bytes.BytesAsBase64;
+import me.tapeline.quailj.runtime.std.data.bytes.BytesFromBase64;
+import me.tapeline.quailj.runtime.std.data.bytes.BytesNor;
+import me.tapeline.quailj.runtime.std.data.bytes.BytesFromSignedInt;
+import me.tapeline.quailj.runtime.std.data.bytes.BytesAsUnsignedInt;
+import me.tapeline.quailj.runtime.std.data.bytes.BytesAnd;
+import me.tapeline.quailj.runtime.std.data.bytes.BytesBitAt;
+import me.tapeline.quailj.runtime.std.data.bytes.BytesXor;
+import me.tapeline.quailj.runtime.std.data.bytes.BytesNand;
+import me.tapeline.quailj.runtime.std.data.bytes.BytesImplies;
+import me.tapeline.quailj.runtime.std.data.bytes.BytesSetBitAt;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class DataLibBytes extends QObject implements Initializable {
+
+ public static DataLibBytes prototype = null;
+ public static DataLibBytes prototype(Runtime runtime) {
+ if (prototype == null)
+ prototype = new DataLibBytes(
+ new Table(Dict.make(
+ new Pair<>("xnor", new BytesXnor(runtime)),
+ new Pair<>("or", new BytesOr(runtime)),
+ new Pair<>("asSignedInt", new BytesAsSignedInt(runtime)),
+ new Pair<>("asBase64", new BytesAsBase64(runtime)),
+ new Pair<>("asBits", new BytesAsBits(runtime)),
+ new Pair<>("fromBase64", new BytesFromBase64(runtime)),
+ new Pair<>("fromBits", new BytesFromBits(runtime)),
+ new Pair<>("nor", new BytesNor(runtime)),
+ new Pair<>("fromSignedInt", new BytesFromSignedInt(runtime)),
+ new Pair<>("asUnsignedInt", new BytesAsUnsignedInt(runtime)),
+ new Pair<>("and", new BytesAnd(runtime)),
+ new Pair<>("bitAt", new BytesBitAt(runtime)),
+ new Pair<>("xor", new BytesXor(runtime)),
+ new Pair<>("nand", new BytesNand(runtime)),
+ new Pair<>("implies", new BytesImplies(runtime)),
+ new Pair<>("setBitAt", new BytesSetBitAt(runtime))
+ )),
+ "Bytes",
+ QObject.superObject,
+ true
+ );
+ return prototype;
+ }
+
+ protected byte[] data;
+ protected int iterator;
+
+ public DataLibBytes(Table table, String className, QObject parent, boolean isPrototype) {
+ super(table, className, parent, isPrototype);
+ }
+
+ public DataLibBytes(Table table, String className, QObject parent, boolean isPrototype, byte[] data) {
+ this(table, className, parent, isPrototype);
+ this.data = data;
+ }
+
+ public DataLibBytes(byte[] data) {
+ this(new Table(), prototype.className, prototype, false, data);
+ }
+
+ public static DataLibBytes validate(Runtime runtime, QObject object) throws RuntimeStriker {
+ if (!(object instanceof DataLibBytes))
+ runtime.error(new QUnsuitableTypeException(prototype.className, object));
+ DataLibBytes thisObject = (DataLibBytes) object;
+ if (!thisObject.isInitialized())
+ runtime.error(new QNotInitializedException("Bytes"));
+ return thisObject;
+ }
+
+ @Override
+ public QObject derive(Runtime runtime) throws RuntimeStriker {
+ if (!isPrototype)
+ runtime.error("Attempt to inherit from non-prototype value");
+ return new DataLibBytes(new Table(), className, this, false);
+ }
+
+ @Override
+ public QObject extendAs(Runtime runtime, String className) throws RuntimeStriker {
+ if (!isPrototype)
+ runtime.error("Attempt to inherit from non-prototype value");
+ return new DataLibBytes(new Table(), className, this, true);
+ }
+
+ @Override
+ public QObject copy() {
+ QObject copy = new DataLibBytes(table, className, parent, isPrototype);
+ copy.setInheritableFlag(isInheritable);
+ return copy;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return data != null;
+ }
+
+ @Override
+ public QObject defaultEqualsObject(Runtime runtime, QObject other) throws RuntimeStriker {
+ if (other instanceof DataLibBytes)
+ return Val(Arrays.equals(((DataLibBytes) other).data, data));
+ return super.defaultEqualsObject(runtime, other);
+ }
+
+ @Override
+ public QObject defaultNotEqualsObject(Runtime runtime, QObject other) throws RuntimeStriker {
+ if (other instanceof DataLibBytes)
+ return Val(!Arrays.equals(((DataLibBytes) other).data, data));
+ return super.defaultNotEqualsObject(runtime, other);
+ }
+
+ @Override
+ public QObject defaultIndex(Runtime runtime, QObject index) throws RuntimeStriker {
+ if (index.isNum()) {
+ if (index.numValue() >= data.length) {
+ runtime.error(new QIndexOutOfBoundsException(index, Val(data.length)));
+ return Val();
+ }
+ return new DataLibBytes(new byte[] {data[((int) index.numValue())]});
+ }
+ return super.defaultIndex(runtime, index);
+ }
+
+ @Override
+ public QObject defaultIndexSet(Runtime runtime, QObject index, QObject value) throws RuntimeStriker {
+ if (!(value instanceof DataLibBytes)) return super.defaultIndexSet(runtime, index, value);
+ byte[] valueData = ((DataLibBytes) value).data;
+ if (index.isNum()) {
+ if (index.numValue() >= data.length) {
+ runtime.error(new QIndexOutOfBoundsException(index, Val(data.length)));
+ return Val();
+ }
+ int caret = (int) index.numValue();
+ for (int i = 0; i < valueData.length; i++) {
+ if (i + caret >= data.length) break;
+ data[i + caret] = valueData[i];
+ }
+ return Val();
+ }
+ return super.defaultIndexSet(runtime, index, value);
+ }
+
+ @Override
+ public QObject defaultSubscriptStartEnd(Runtime runtime, QObject start, QObject end) throws RuntimeStriker {
+ if (start.isNum() && end.isNum()) {
+ int startIndex = ((int) start.numValue());
+ int endIndex = ((int) end.numValue());
+ if (startIndex >= endIndex) {
+ runtime.error(new QUnsuitableValueException("End should be bigger than start", end));
+ return Val();
+ }
+ if (startIndex >= data.length) {
+ runtime.error(new QIndexOutOfBoundsException(start, Val(data.length)));
+ return Val();
+ }
+ if (endIndex >= data.length) {
+ runtime.error(new QIndexOutOfBoundsException(end, Val(data.length)));
+ return Val();
+ }
+ byte[] newData = new byte[endIndex - startIndex];
+ System.arraycopy(data, startIndex, newData, 0, newData.length);
+ return new DataLibBytes(newData);
+ }
+ return super.defaultSubscriptStartEnd(runtime, start, end);
+ }
+
+ @Override
+ public QObject defaultIterateStart(Runtime runtime) throws RuntimeStriker {
+ iterator = 0;
+ return this;
+ }
+
+ @Override
+ public QObject defaultIterateNext(Runtime runtime) throws RuntimeStriker {
+ if (iterator >= data.length)
+ runtime.error(new QIterationStopException());
+ return new DataLibBytes(new byte[] {data[iterator++]});
+ }
+}
\ No newline at end of file
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DataLibDeque.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DataLibDeque.java
new file mode 100644
index 0000000..e17b473
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DataLibDeque.java
@@ -0,0 +1,122 @@
+package me.tapeline.quailj.runtime.std.data.deque;
+
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+import me.tapeline.quailj.runtime.Table;
+import me.tapeline.quailj.runtime.std.data.bytes.DataLibBytes;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.classes.errors.QIterationStopException;
+import me.tapeline.quailj.typing.classes.errors.QNotInitializedException;
+import me.tapeline.quailj.typing.classes.errors.QUnsuitableTypeException;
+import me.tapeline.quailj.typing.classes.utils.Initializable;
+import me.tapeline.quailj.utils.Dict;
+import me.tapeline.quailj.utils.Pair;
+import me.tapeline.quailj.runtime.std.data.deque.DequeSize;
+import me.tapeline.quailj.runtime.std.data.deque.DequePopBack;
+import me.tapeline.quailj.runtime.std.data.deque.DequeClear;
+import me.tapeline.quailj.runtime.std.data.deque.DequeAddBack;
+import me.tapeline.quailj.runtime.std.data.deque.DequeAddFront;
+import me.tapeline.quailj.runtime.std.data.deque.DequePopFront;
+
+import java.util.*;
+
+public class DataLibDeque extends QObject implements Initializable {
+
+ public static DataLibDeque prototype = null;
+ public static DataLibDeque prototype(Runtime runtime) {
+ if (prototype == null)
+ prototype = new DataLibDeque(
+ new Table(Dict.make(
+ new Pair<>("size", new DequeSize(runtime)),
+ new Pair<>("popBack", new DequePopBack(runtime)),
+ new Pair<>("clear", new DequeClear(runtime)),
+ new Pair<>("addBack", new DequeAddBack(runtime)),
+ new Pair<>("addFront", new DequeAddFront(runtime)),
+ new Pair<>("popFront", new DequePopFront(runtime))
+ )),
+ "Deque",
+ QObject.superObject,
+ true
+ );
+ return prototype;
+ }
+
+ protected Deque deque = new ArrayDeque<>();
+ protected Iterator iterator = null;
+
+ public Deque getDeque() {
+ return deque;
+ }
+
+ public static DataLibDeque validate(Runtime runtime, QObject object) throws RuntimeStriker {
+ if (!(object instanceof DataLibDeque))
+ runtime.error(new QUnsuitableTypeException(prototype.className, object));
+ DataLibDeque thisObject = (DataLibDeque) object;
+ if (!thisObject.isInitialized())
+ runtime.error(new QNotInitializedException("Deque"));
+ return thisObject;
+ }
+
+ public DataLibDeque(Table table, String className, QObject parent, boolean isPrototype) {
+ super(table, className, parent, isPrototype);
+ }
+
+ public DataLibDeque(Table table, String className, QObject parent, boolean isPrototype, Deque deque) {
+ this(table, className, parent, isPrototype);
+ this.deque = deque;
+ }
+
+ public DataLibDeque(Deque deque) {
+ this(new Table(), prototype.className, prototype, false);
+ this.deque = deque;
+ }
+
+ @Override
+ public QObject derive(Runtime runtime) throws RuntimeStriker {
+ if (!isPrototype)
+ runtime.error("Attempt to inherit from non-prototype value");
+ return new DataLibDeque(new Table(), className, this, false);
+ }
+
+ @Override
+ public QObject extendAs(Runtime runtime, String className) throws RuntimeStriker {
+ if (!isPrototype)
+ runtime.error("Attempt to inherit from non-prototype value");
+ return new DataLibDeque(new Table(), className, this, true);
+ }
+
+ @Override
+ public QObject copy() {
+ QObject copy = new DataLibDeque(table, className, parent, isPrototype);
+ copy.setInheritableFlag(isInheritable);
+ return copy;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return deque != null;
+ }
+
+ @Override
+ public QObject defaultContainsObject(Runtime runtime, QObject other) throws RuntimeStriker {
+ return Val(deque.contains(other));
+ }
+
+ @Override
+ public QObject defaultNotContainsObject(Runtime runtime, QObject other) throws RuntimeStriker {
+ return Val(!deque.contains(other));
+ }
+
+ @Override
+ public QObject defaultIterateStart(Runtime runtime) throws RuntimeStriker {
+ iterator = deque.iterator();
+ return this;
+ }
+
+ @Override
+ public QObject defaultIterateNext(Runtime runtime) throws RuntimeStriker {
+ if (!iterator.hasNext())
+ runtime.error(new QIterationStopException());
+ return iterator.next();
+ }
+}
\ No newline at end of file
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequeAddBack.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequeAddBack.java
new file mode 100644
index 0000000..9e4414e
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequeAddBack.java
@@ -0,0 +1,47 @@
+package me.tapeline.quailj.runtime.std.data.deque;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class DequeAddBack extends QBuiltinFunc {
+
+ public DequeAddBack(Runtime runtime) {
+ super(
+ "addBack",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "obj",
+ QObject.Val(),
+ new int[] {ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibDeque thisObject = DataLibDeque.validate(runtime, args.get("this"));
+ thisObject.getDeque().addLast(args.get("obj"));
+ return Val();
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequeAddFront.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequeAddFront.java
new file mode 100644
index 0000000..0ea8963
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequeAddFront.java
@@ -0,0 +1,47 @@
+package me.tapeline.quailj.runtime.std.data.deque;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class DequeAddFront extends QBuiltinFunc {
+
+ public DequeAddFront(Runtime runtime) {
+ super(
+ "addFront",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "obj",
+ QObject.Val(),
+ new int[] {ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibDeque thisObject = DataLibDeque.validate(runtime, args.get("this"));
+ thisObject.getDeque().addFirst(args.get("obj"));
+ return Val();
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequeClear.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequeClear.java
new file mode 100644
index 0000000..107bb05
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequeClear.java
@@ -0,0 +1,41 @@
+package me.tapeline.quailj.runtime.std.data.deque;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class DequeClear extends QBuiltinFunc {
+
+ public DequeClear(Runtime runtime) {
+ super(
+ "clear",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibDeque thisObject = DataLibDeque.validate(runtime, args.get("this"));
+ thisObject.getDeque().clear();
+ return Val();
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequePeekBack.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequePeekBack.java
new file mode 100644
index 0000000..febb71e
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequePeekBack.java
@@ -0,0 +1,39 @@
+package me.tapeline.quailj.runtime.std.data.deque;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class DequePeekBack extends QBuiltinFunc {
+
+ public DequePeekBack(Runtime runtime) {
+ super(
+ "peekBack",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibDeque thisObject = DataLibDeque.validate(runtime, args.get("this"));
+ return QObject.nullSafe(thisObject.getDeque().peekLast());
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequePeekFront.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequePeekFront.java
new file mode 100644
index 0000000..fe95ec8
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequePeekFront.java
@@ -0,0 +1,39 @@
+package me.tapeline.quailj.runtime.std.data.deque;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class DequePeekFront extends QBuiltinFunc {
+
+ public DequePeekFront(Runtime runtime) {
+ super(
+ "peekFront",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibDeque thisObject = DataLibDeque.validate(runtime, args.get("this"));
+ return QObject.nullSafe(thisObject.getDeque().peekFirst());
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequePopBack.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequePopBack.java
new file mode 100644
index 0000000..0950ff6
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequePopBack.java
@@ -0,0 +1,40 @@
+package me.tapeline.quailj.runtime.std.data.deque;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class DequePopBack extends QBuiltinFunc {
+
+ public DequePopBack(Runtime runtime) {
+ super(
+ "popBack",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibDeque thisObject = DataLibDeque.validate(runtime, args.get("this"));
+ return QObject.nullSafe(thisObject.getDeque().pollLast());
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequePopFront.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequePopFront.java
new file mode 100644
index 0000000..fcd2039
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequePopFront.java
@@ -0,0 +1,40 @@
+package me.tapeline.quailj.runtime.std.data.deque;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class DequePopFront extends QBuiltinFunc {
+
+ public DequePopFront(Runtime runtime) {
+ super(
+ "popFront",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibDeque thisObject = DataLibDeque.validate(runtime, args.get("this"));
+ return QObject.nullSafe(thisObject.getDeque().pollFirst());
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequeSize.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequeSize.java
new file mode 100644
index 0000000..137a0e8
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/deque/DequeSize.java
@@ -0,0 +1,40 @@
+package me.tapeline.quailj.runtime.std.data.deque;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class DequeSize extends QBuiltinFunc {
+
+ public DequeSize(Runtime runtime) {
+ super(
+ "size",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibDeque thisObject = DataLibDeque.validate(runtime, args.get("this"));
+ return Val(thisObject.getDeque().size());
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/DataLibQueue.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/DataLibQueue.java
new file mode 100644
index 0000000..beeb2ef
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/DataLibQueue.java
@@ -0,0 +1,117 @@
+package me.tapeline.quailj.runtime.std.data.queue;
+
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+import me.tapeline.quailj.runtime.Table;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.classes.errors.QIterationStopException;
+import me.tapeline.quailj.typing.classes.errors.QNotInitializedException;
+import me.tapeline.quailj.typing.classes.errors.QUnsuitableTypeException;
+import me.tapeline.quailj.typing.classes.utils.Initializable;
+import me.tapeline.quailj.utils.Dict;
+import me.tapeline.quailj.utils.Pair;
+
+import java.util.ArrayDeque;
+import java.util.Iterator;
+import java.util.Queue;
+
+public class DataLibQueue extends QObject implements Initializable {
+
+ public static DataLibQueue prototype = null;
+ public static DataLibQueue prototype(Runtime runtime) {
+ if (prototype == null)
+ prototype = new DataLibQueue(
+ new Table(Dict.make(
+ new Pair<>("add", new QueueAdd(runtime)),
+ new Pair<>("pop", new QueuePop(runtime)),
+ new Pair<>("size", new QueueSize(runtime)),
+ new Pair<>("clear", new QueueClear(runtime)),
+ new Pair<>("peek", new QueuePeek(runtime))
+ )),
+ "Queue",
+ QObject.superObject,
+ true
+ );
+ return prototype;
+ }
+
+ protected Queue queue = new ArrayDeque<>();
+ protected Iterator iterator = null;
+
+ public Queue getQueue() {
+ return queue;
+ }
+
+ public static DataLibQueue validate(Runtime runtime, QObject object) throws RuntimeStriker {
+ if (!(object instanceof DataLibQueue))
+ runtime.error(new QUnsuitableTypeException(prototype.className, object));
+ DataLibQueue thisObject = (DataLibQueue) object;
+ if (!thisObject.isInitialized())
+ runtime.error(new QNotInitializedException("Queue"));
+ return thisObject;
+ }
+
+ public DataLibQueue(Table table, String className, QObject parent, boolean isPrototype) {
+ super(table, className, parent, isPrototype);
+ }
+
+ public DataLibQueue(Table table, String className, QObject parent, boolean isPrototype, Queue queue) {
+ this(table, className, parent, isPrototype);
+ this.queue = queue;
+ }
+
+ public DataLibQueue(Queue queue) {
+ this(new Table(), prototype.className, prototype, false);
+ this.queue = queue;
+ }
+
+ @Override
+ public QObject derive(Runtime runtime) throws RuntimeStriker {
+ if (!isPrototype)
+ runtime.error("Attempt to inherit from non-prototype value");
+ return new DataLibQueue(new Table(), className, this, false);
+ }
+
+ @Override
+ public QObject extendAs(Runtime runtime, String className) throws RuntimeStriker {
+ if (!isPrototype)
+ runtime.error("Attempt to inherit from non-prototype value");
+ return new DataLibQueue(new Table(), className, this, true);
+ }
+
+ @Override
+ public QObject copy() {
+ QObject copy = new DataLibQueue(table, className, parent, isPrototype);
+ copy.setInheritableFlag(isInheritable);
+ return copy;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return queue != null;
+ }
+
+ @Override
+ public QObject defaultContainsObject(Runtime runtime, QObject other) throws RuntimeStriker {
+ return Val(queue.contains(other));
+ }
+
+ @Override
+ public QObject defaultNotContainsObject(Runtime runtime, QObject other) throws RuntimeStriker {
+ return Val(!queue.contains(other));
+ }
+
+ @Override
+ public QObject defaultIterateStart(Runtime runtime) throws RuntimeStriker {
+ iterator = queue.iterator();
+ return this;
+ }
+
+ @Override
+ public QObject defaultIterateNext(Runtime runtime) throws RuntimeStriker {
+ if (!iterator.hasNext())
+ runtime.error(new QIterationStopException());
+ return iterator.next();
+ }
+
+}
\ No newline at end of file
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueueAdd.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueueAdd.java
new file mode 100644
index 0000000..79db455
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueueAdd.java
@@ -0,0 +1,48 @@
+package me.tapeline.quailj.runtime.std.data.queue;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.runtime.std.data.deque.DataLibDeque;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class QueueAdd extends QBuiltinFunc {
+
+ public QueueAdd(Runtime runtime) {
+ super(
+ "add",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "obj",
+ QObject.Val(),
+ new int[] {ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibQueue thisObject = DataLibQueue.validate(runtime, args.get("this"));
+ thisObject.getQueue().add(args.get("obj"));
+ return Val();
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueueClear.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueueClear.java
new file mode 100644
index 0000000..7f869eb
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueueClear.java
@@ -0,0 +1,41 @@
+package me.tapeline.quailj.runtime.std.data.queue;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class QueueClear extends QBuiltinFunc {
+
+ public QueueClear(Runtime runtime) {
+ super(
+ "clear",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibQueue thisObject = DataLibQueue.validate(runtime, args.get("this"));
+ thisObject.getQueue().clear();
+ return Val();
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueuePeek.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueuePeek.java
new file mode 100644
index 0000000..c01e3d7
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueuePeek.java
@@ -0,0 +1,39 @@
+package me.tapeline.quailj.runtime.std.data.queue;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class QueuePeek extends QBuiltinFunc {
+
+ public QueuePeek(Runtime runtime) {
+ super(
+ "peek",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibQueue thisObject = DataLibQueue.validate(runtime, args.get("this"));
+ return thisObject.getQueue().peek();
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueuePop.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueuePop.java
new file mode 100644
index 0000000..cd6b8e5
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueuePop.java
@@ -0,0 +1,40 @@
+package me.tapeline.quailj.runtime.std.data.queue;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class QueuePop extends QBuiltinFunc {
+
+ public QueuePop(Runtime runtime) {
+ super(
+ "pop",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibQueue thisObject = DataLibQueue.validate(runtime, args.get("this"));
+ return thisObject.getQueue().poll();
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueueSize.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueueSize.java
new file mode 100644
index 0000000..94f773a
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/queue/QueueSize.java
@@ -0,0 +1,40 @@
+package me.tapeline.quailj.runtime.std.data.queue;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class QueueSize extends QBuiltinFunc {
+
+ public QueueSize(Runtime runtime) {
+ super(
+ "size",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibQueue thisObject = DataLibQueue.validate(runtime, args.get("this"));
+ return Val(thisObject.getQueue().size());
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/DataLibSet.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/DataLibSet.java
new file mode 100644
index 0000000..42dc0fa
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/DataLibSet.java
@@ -0,0 +1,141 @@
+package me.tapeline.quailj.runtime.std.data.set;
+
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+import me.tapeline.quailj.runtime.Table;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.classes.errors.QIterationStopException;
+import me.tapeline.quailj.typing.classes.errors.QNotInitializedException;
+import me.tapeline.quailj.typing.classes.errors.QUnsuitableTypeException;
+import me.tapeline.quailj.typing.classes.utils.Initializable;
+import me.tapeline.quailj.utils.Dict;
+import me.tapeline.quailj.utils.Pair;
+import me.tapeline.quailj.runtime.std.data.set.SetAdd;
+import me.tapeline.quailj.runtime.std.data.set.SetSize;
+import me.tapeline.quailj.runtime.std.data.set.SetIntersection;
+import me.tapeline.quailj.runtime.std.data.set.SetClear;
+import me.tapeline.quailj.runtime.std.data.set.SetUnion;
+import me.tapeline.quailj.runtime.std.data.set.SetRemove;
+
+import java.util.*;
+
+public class DataLibSet extends QObject implements Initializable {
+
+ public static DataLibSet prototype = null;
+ public static DataLibSet prototype(Runtime runtime) {
+ if (prototype == null)
+ prototype = new DataLibSet(
+ new Table(Dict.make(
+ new Pair<>("_constructor", new SetConstructor(runtime)),
+ new Pair<>("add", new SetAdd(runtime)),
+ new Pair<>("size", new SetSize(runtime)),
+ new Pair<>("intersection", new SetIntersection(runtime)),
+ new Pair<>("clear", new SetClear(runtime)),
+ new Pair<>("union", new SetUnion(runtime)),
+ new Pair<>("remove", new SetRemove(runtime))
+ )),
+ "Set",
+ QObject.superObject,
+ true
+ );
+ return prototype;
+ }
+
+ protected Set set = new HashSet<>();
+ protected Iterator iterator = null;
+
+ public Set getSet() {
+ return set;
+ }
+
+ public static DataLibSet validate(Runtime runtime, QObject object) throws RuntimeStriker {
+ if (!(object instanceof DataLibSet))
+ runtime.error(new QUnsuitableTypeException(prototype.className, object));
+ DataLibSet thisObject = (DataLibSet) object;
+ if (!thisObject.isInitialized())
+ runtime.error(new QNotInitializedException("Set"));
+ return thisObject;
+ }
+
+ public DataLibSet(Table table, String className, QObject parent, boolean isPrototype) {
+ super(table, className, parent, isPrototype);
+ }
+
+ public DataLibSet(Table table, String className, QObject parent, boolean isPrototype, Set set) {
+ this(table, className, parent, isPrototype);
+ this.set = set;
+ }
+
+ public DataLibSet(Set set) {
+ this(new Table(), prototype.className, prototype, false);
+ this.set = set;
+ }
+
+ @Override
+ public QObject derive(Runtime runtime) throws RuntimeStriker {
+ if (!isPrototype)
+ runtime.error("Attempt to inherit from non-prototype value");
+ return new DataLibSet(new Table(), className, this, false);
+ }
+
+ @Override
+ public QObject extendAs(Runtime runtime, String className) throws RuntimeStriker {
+ if (!isPrototype)
+ runtime.error("Attempt to inherit from non-prototype value");
+ return new DataLibSet(new Table(), className, this, true);
+ }
+
+ @Override
+ public QObject copy() {
+ QObject copy = new DataLibSet(table, className, parent, isPrototype);
+ copy.setInheritableFlag(isInheritable);
+ return copy;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return set != null;
+ }
+
+ @Override
+ public QObject defaultEqualsObject(Runtime runtime, QObject other) throws RuntimeStriker {
+ if (other instanceof DataLibSet)
+ return Val(((DataLibSet) other).set.equals(set));
+ return super.defaultEqualsObject(runtime, other);
+ }
+
+ @Override
+ public QObject defaultNotEqualsObject(Runtime runtime, QObject other) throws RuntimeStriker {
+ if (other instanceof DataLibSet)
+ return Val(!((DataLibSet) other).set.equals(set));
+ return super.defaultNotEqualsObject(runtime, other);
+ }
+
+ @Override
+ public QObject defaultContainsObject(Runtime runtime, QObject other) throws RuntimeStriker {
+ if (other.isNum() || other.isStr() || other.isBool())
+ return Val(set.contains(other));
+ return super.defaultContainsObject(runtime, other);
+ }
+
+ @Override
+ public QObject defaultNotContainsObject(Runtime runtime, QObject other) throws RuntimeStriker {
+ if (other.isNum() || other.isStr() || other.isBool())
+ return Val(!set.contains(other));
+ return super.defaultNotContainsObject(runtime, other);
+ }
+
+ @Override
+ public QObject defaultIterateStart(Runtime runtime) throws RuntimeStriker {
+ iterator = set.iterator();
+ return this;
+ }
+
+ @Override
+ public QObject defaultIterateNext(Runtime runtime) throws RuntimeStriker {
+ if (!iterator.hasNext())
+ runtime.error(new QIterationStopException());
+ return iterator.next();
+ }
+
+}
\ No newline at end of file
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetAdd.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetAdd.java
new file mode 100644
index 0000000..9dbaf3f
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetAdd.java
@@ -0,0 +1,47 @@
+package me.tapeline.quailj.runtime.std.data.set;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class SetAdd extends QBuiltinFunc {
+
+ public SetAdd(Runtime runtime) {
+ super(
+ "add",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "obj",
+ QObject.Val(),
+ new int[] {ModifierConstants.BOOL, ModifierConstants.STR, ModifierConstants.NUM},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibSet thisObject = DataLibSet.validate(runtime, args.get("this"));
+ thisObject.getSet().add(args.get("obj"));
+ return Val();
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetClear.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetClear.java
new file mode 100644
index 0000000..12dcb14
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetClear.java
@@ -0,0 +1,41 @@
+package me.tapeline.quailj.runtime.std.data.set;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class SetClear extends QBuiltinFunc {
+
+ public SetClear(Runtime runtime) {
+ super(
+ "clear",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibSet thisObject = DataLibSet.validate(runtime, args.get("this"));
+ thisObject.getSet().clear();
+ return Val();
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetConstructor.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetConstructor.java
new file mode 100644
index 0000000..fe3ba93
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetConstructor.java
@@ -0,0 +1,56 @@
+package me.tapeline.quailj.runtime.std.data.set;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+import me.tapeline.quailj.runtime.std.event.eventmanager.EventManager;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.classes.errors.QUnsuitableTypeException;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+public class SetConstructor extends QBuiltinFunc {
+
+ public SetConstructor(Runtime runtime) {
+ super(
+ "_constructor",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "values",
+ QObject.Val(),
+ new int[] {ModifierConstants.LIST, ModifierConstants.NULL},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ if (!(args.get("this") instanceof DataLibSet))
+ runtime.error(new QUnsuitableTypeException("Set", args.get("this")));
+ DataLibSet thisObject = ((DataLibSet) args.get("this"));
+
+ if (args.get("values").isList()) {
+ thisObject.getSet().addAll(args.get("values").listValue());
+ }
+
+ return thisObject;
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetIntersection.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetIntersection.java
new file mode 100644
index 0000000..3002536
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetIntersection.java
@@ -0,0 +1,47 @@
+package me.tapeline.quailj.runtime.std.data.set;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.*;
+
+public class SetIntersection extends QBuiltinFunc {
+
+ public SetIntersection(Runtime runtime) {
+ super(
+ "intersection",
+ Arrays.asList(
+ new FuncArgument(
+ "a",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "b",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibSet a = DataLibSet.validate(runtime, args.get("a"));
+ DataLibSet b = DataLibSet.validate(runtime, args.get("b"));
+ Set result = new HashSet<>(a.getSet());
+ result.retainAll(b.getSet());
+ return new DataLibSet(result);
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetRemove.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetRemove.java
new file mode 100644
index 0000000..32a67fa
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetRemove.java
@@ -0,0 +1,47 @@
+package me.tapeline.quailj.runtime.std.data.set;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class SetRemove extends QBuiltinFunc {
+
+ public SetRemove(Runtime runtime) {
+ super(
+ "remove",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "obj",
+ QObject.Val(),
+ new int[] {ModifierConstants.OBJ},
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibSet thisObject = DataLibSet.validate(runtime, args.get("this"));
+ thisObject.getSet().remove(args.get("obj"));
+ return Val();
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetSize.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetSize.java
new file mode 100644
index 0000000..03ceddc
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetSize.java
@@ -0,0 +1,40 @@
+package me.tapeline.quailj.runtime.std.data.set;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+public class SetSize extends QBuiltinFunc {
+
+ public SetSize(Runtime runtime) {
+ super(
+ "size",
+ Arrays.asList(
+ new FuncArgument(
+ "this",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibSet thisObject = DataLibSet.validate(runtime, args.get("this"));
+ return Val(thisObject.getSet().size());
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetUnion.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetUnion.java
new file mode 100644
index 0000000..4bf4493
--- /dev/null
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/std/data/set/SetUnion.java
@@ -0,0 +1,47 @@
+package me.tapeline.quailj.runtime.std.data.set;
+
+import me.tapeline.quailj.parsing.nodes.literals.LiteralFunction;
+import me.tapeline.quailj.runtime.Runtime;
+import me.tapeline.quailj.typing.modifiers.ModifierConstants;
+import me.tapeline.quailj.typing.classes.QObject;
+import me.tapeline.quailj.typing.utils.FuncArgument;
+import me.tapeline.quailj.typing.classes.utils.QBuiltinFunc;
+import me.tapeline.quailj.runtime.RuntimeStriker;
+
+import java.util.*;
+
+public class SetUnion extends QBuiltinFunc {
+
+ public SetUnion(Runtime runtime) {
+ super(
+ "union",
+ Arrays.asList(
+ new FuncArgument(
+ "a",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ ),
+ new FuncArgument(
+ "b",
+ QObject.Val(),
+ new int[0],
+ LiteralFunction.Argument.POSITIONAL
+ )
+ ),
+ runtime,
+ runtime.getMemory(),
+ false
+ );
+ }
+
+ @Override
+ public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker {
+ DataLibSet a = DataLibSet.validate(runtime, args.get("a"));
+ DataLibSet b = DataLibSet.validate(runtime, args.get("b"));
+ Set result = new HashSet<>(a.getSet());
+ result.addAll(b.getSet());
+ return new DataLibSet(result);
+ }
+
+}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/typing/classes/QBool.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/typing/classes/QBool.java
index 488b0e5..e552538 100644
--- a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/typing/classes/QBool.java
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/typing/classes/QBool.java
@@ -101,4 +101,20 @@ public QObject defaultOr(Runtime runtime, QObject other) throws RuntimeStriker {
return super.or(runtime, other);
}
+ /**
+ * Only for things like HashSets.
+ * This thing shouldn't be used for
+ * actual comparison of objects.
+ * Use {@link QObject#equalsObject} instead!
+ */
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof QBool && ((QBool) obj).value == value;
+ }
+
+ @Override
+ public int hashCode() {
+ return Boolean.hashCode(value);
+ }
+
}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/typing/classes/QNumber.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/typing/classes/QNumber.java
index 3c6eee7..29cf032 100644
--- a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/typing/classes/QNumber.java
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/typing/classes/QNumber.java
@@ -62,7 +62,7 @@ public void setValue(double value) {
@Override
public String toString() {
if ((value % 1) == 0)
- return Integer.toString((int) value);
+ return Long.toString((long) value);
return Double.toString(value);
}
@@ -191,5 +191,20 @@ public QObject defaultConvertToNumber(Runtime runtime) {
return this;
}
+ /**
+ * Only for things like HashSets.
+ * This thing shouldn't be used for
+ * actual comparison of objects.
+ * Use {@link QObject#equalsObject} instead!
+ */
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof QNumber && ((QNumber) obj).value == value;
+ }
+
+ @Override
+ public int hashCode() {
+ return Double.hashCode(value);
+ }
}
diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/typing/classes/QString.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/typing/classes/QString.java
index 46d8c1d..5087509 100644
--- a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/typing/classes/QString.java
+++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/typing/classes/QString.java
@@ -200,4 +200,20 @@ public String toString() {
return value;
}
+ /**
+ * Only for things like HashSets.
+ * This thing shouldn't be used for
+ * actual comparison of objects.
+ * Use {@link QObject#equalsObject} instead!
+ */
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof QString && ((QString) obj).value.equals(value);
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
}
diff --git a/docs-md/libs/data.q b/docs-md/libs/data.q
new file mode 100644
index 0000000..e7be884
--- /dev/null
+++ b/docs-md/libs/data.q
@@ -0,0 +1,65 @@
+class Queue {
+ #? Implementation of a single-ended queue.
+ #? Supports in
operator and iteration
+
+ num size(this) {}
+ void add(this, object obj) {}
+ object pop(this) {}
+ void clear(this) {}
+ object peek(this) {}
+}
+
+class Deque {
+ #? Implementation of a double-ended queue.
+ #? Supports in
operator and iteration
+
+ num size(this) {}
+ void addFront(this, object obj) {}
+ void addBack(this, object obj) {}
+ object popFront(this) {}
+ object popBack(this) {}
+ void clear(this) {}
+ object peekFront(this) {}
+ object peekBack(this) {}
+}
+
+class Set {
+ #? Implementation of a set.
+ #? Can contain only booleans, strings and numbers
+ #? Supports in
operator, equality check and iteration
+
+ constructor (this, list | void values=null) {}
+
+ num size(this) {}
+ void add(this, bool | string | num obj) {}
+ void remove(this, bool | string | num obj) {}
+ void clear(this) {}
+
+ static object union(a, b) {}
+ static object intersection(a, b) {}
+}
+
+class Bytes {
+ #? Implementation of a byte array.
+ #? Supports equality check, iteration, indexing and subscripts
+
+ static object fromBase64(string b64) {}
+ static object fromBits(string bits) {}
+ static object fromSignedInt(num uint) {}
+ static string asBase64(string|object bytes) {}
+ static num asUnsignedInt(string|object bytes) {}
+ static num asSignedInt(string|object bytes) {}
+ static num asBits(string|object bytes) {}
+
+ static object or(string|object a, string|object b) {}
+ static object and(string|object a, string|object b) {}
+ static object xor(string|object a, string|object b) {}
+ static object implies(string|object a, string|object b) {}
+ static object nor(string|object a, string|object b) {}
+ static object nand(string|object a, string|object b) {}
+ static object xnor(string|object a, string|object b) {}
+
+ bool bitAt(this, num pos) {}
+ void setBitAt(this, num pos, bool bit) {}
+}
+
diff --git a/docs-md/libs/ji.html b/docs-md/libs/ji.html
index 171a07f..4466aa1 100644
--- a/docs-md/libs/ji.html
+++ b/docs-md/libs/ji.html
@@ -82,13 +82,13 @@ ji.q
lang/ji
JavaClass
-
Proxy for Java classes
Fields
static CLASS
static ABSTRACT
static INTERFACE
Methods
_constructor(this, args...)
Instantiate JavaObject of that class
JavaMethod
+
Proxy for Java classes
Fields
static CLASS
static ABSTRACT
static INTERFACE
Methods
_constructor(this, args...)
JavaMethod
Proxy for Java methods
Fields
Methods
JavaObject
-
Proxy for Java objects
Fields
Methods
object getClass(this)
Get class (instance of JavaClass)
object static pack(object obj)
StaticWraps Quail native value as a JavaObject
SketchedJavaClass
-
Used for runtime creation of Java classes
Fields
Methods
_constructor(this, string signature, contents...)
Prepares a Java class.
Signature is a sequence of Java keyword modifiers and name of the class:
E.g. public final ClassName
Contents is a sequence of SketchedJavaConstructors, SketchedJavaFields,
SketchedJavaInheritances and SketchedJavaMethods
SketchedJavaConstructor
+
Proxy for Java objects
Fields
Methods
object getClass(this)
object static pack(object obj)
StaticWraps Quail native value as a JavaObject
SketchedJavaClass
+
Used for runtime creation of Java classes
Fields
Methods
_constructor(this, string signature, contents...)
SketchedJavaConstructor
Used for runtime creation of Java class constructors
Fields
Methods
_constructor(this, string signature, list args, func body)
Prepares a Java class constructor.
Signature is a sequence of Java keyword modifiers: public, private, protected, static, final
E.g. public
Args is a list of strings that contain argument signatures.
E.g. ["double a", "String b"]
Body is the Quail function that will be executed when this constructor is invoked
SketchedJavaField
Used for runtime creation of Java class fields
Fields
Methods
_constructor(this, string signature, object default)
Prepares a Java class sequence.
Signature is a sequence of Java keyword modifiers (public, private, protected, static, final),
a type (double, String, boolean...) and a name. E.g. public double a
Default is an instance of JavaObject. Resembles the default value of this field
SketchedJavaInheritance
-
Used for inheritance of runtime created Java classes
Fields
Methods
_constructor(this, object extends)
Receives a JavaClass instance of extension or implementation
SketchedJavaMethod
+
Used for inheritance of runtime created Java classes
Fields
Methods
_constructor(this, object extends)
Receives a JavaClass instance of extension or implementation
See:
#JavaClass
SketchedJavaMethod
Used for runtime creation of Java class methods
Fields
Methods
_constructor(this, string signature, list args, func body)
Prepares a Java class constructor.
Signature is a sequence of Java keyword modifiers (public, private, protected, static, final),
a type (double, String, boolean...) and a name. E.g. public double a
Args is a list of strings that contain argument signatures.
E.g. ["double a", "String b"]
Body is the Quail function that will be executed when this method is invoked
SketchedJavaPackage
-
Used for runtime creation of Java packages
Fields
Methods
_constructor(this, string name, classes...)
Classes is a sequence of SketchedJavaClasses
getClass(string className)
Get defined Java class by qualified ID
deployPackage(object package)
Creates all Java classes specified in passed SketchedJavaPackage