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...)

Instantiate JavaObject of that class

See:
#JavaObject

JavaMethod

Proxy for Java methods

Fields

None

Methods

None

JavaObject

-

Proxy for Java objects

Fields

None

Methods
object getClass(this)

Get class (instance of JavaClass)

object static pack(object obj)
Static

Wraps Quail native value as a JavaObject

SketchedJavaClass

-

Used for runtime creation of Java classes

Fields

None

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

None

Methods
object getClass(this)

Get class (instance of JavaClass)

See:
#JavaClass

object static pack(object obj)
Static

Wraps Quail native value as a JavaObject

SketchedJavaClass

+

Used for runtime creation of Java classes

Fields

None

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

See:
#SketchedJavaField#SketchedJavaInheritance#SketchedJavaMethod#SketchedJavaConstructor

SketchedJavaConstructor

Used for runtime creation of Java class constructors

Fields

None

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

None

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

None

Methods
_constructor(this, object extends)

Receives a JavaClass instance of extension or implementation

SketchedJavaMethod

+

Used for inheritance of runtime created Java classes

Fields

None

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

None

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

None

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

+

Used for runtime creation of Java packages

Fields

None

Methods
_constructor(this, string name, classes...)

Classes is a sequence of SketchedJavaClasses

See:
#SketchedJavaClass

getClass(string className)

Get defined Java class by qualified ID

See:
#JavaClass

deployPackage(object package)

Creates all Java classes specified in passed SketchedJavaPackage

See:
#SketchedJavaPackage

\ No newline at end of file diff --git a/docs-md/libs/ji.q b/docs-md/libs/ji.q index be39386..320300a 100644 --- a/docs-md/libs/ji.q +++ b/docs-md/libs/ji.q @@ -21,6 +21,7 @@ class JavaClass { constructor (this, args...) { #? Instantiate JavaObject of that class + #?see #JavaObject } } @@ -37,6 +38,7 @@ class JavaObject { object getClass(this) { #? Get class (instance of JavaClass) + #?see #JavaClass } } @@ -48,6 +50,10 @@ class SketchedJavaClass { #? E.g. public final ClassName #? Contents is a sequence of SketchedJavaConstructors, SketchedJavaFields, #? SketchedJavaInheritances and SketchedJavaMethods + #?see #SketchedJavaField + #?see #SketchedJavaInheritance + #?see #SketchedJavaMethod + #?see #SketchedJavaConstructor } } @@ -77,6 +83,7 @@ class SketchedJavaInheritance { #? Used for inheritance of runtime created Java classes constructor (this, object extends) { #? Receives a JavaClass instance of extension or implementation + #?see #JavaClass } } @@ -96,13 +103,16 @@ class SketchedJavaPackage { #? Used for runtime creation of Java packages constructor (this, string name, classes...) { #? Classes is a sequence of SketchedJavaClasses + #?see #SketchedJavaClass } } function getClass(string className) { #? Get defined Java class by qualified ID + #?see #JavaClass } function deployPackage(object package) { #? Creates all Java classes specified in passed SketchedJavaPackage + #?see #SketchedJavaPackage } \ No newline at end of file diff --git a/docs-md/spec/chapter13.md b/docs-md/spec/chapter13.md index a46fa91..55107b6 100644 --- a/docs-md/spec/chapter13.md +++ b/docs-md/spec/chapter13.md @@ -84,6 +84,18 @@ Adds a textual description Example: `#? Checks if given key is present` +#### 13.2.7 See + +Syntax: `#?see ` + +Add a link. If link starts with `>` and special flag `-sF.seeLinkPrefix` is set, it will be prepended. + +Also, if link starts with `>`, `.q` sequences will be dropped. + +Examples: +- `#?see https://google.com` +- `#?see >event.q#EventManager::addHandler` + ### 13.3 Classes and functions representation Classes and functions are automatically documented. diff --git a/program6.q b/program6.q new file mode 100644 index 0000000..78d271b --- /dev/null +++ b/program6.q @@ -0,0 +1,10 @@ +use "lang/data" = data; Bytes = data.Bytes; Set = data.Set; Queue = data.Queue; Deque = data.Deque; + +q = Deque() +q.addBack("a") +q.addBack("b") +q.addFront("d") + +for e in q: + print(e) + From 3f71cbf423432701584df92bf3c828ec31a37815 Mon Sep 17 00:00:00 2001 From: Tapeline Date: Sat, 24 Feb 2024 23:08:32 +0500 Subject: [PATCH 02/10] Snapshot --- docs-md/dev-tutorials/index.md | 3 +++ docs-md/index.md | 11 +++++++++++ 2 files changed, 14 insertions(+) create mode 100644 docs-md/dev-tutorials/index.md create mode 100644 docs-md/index.md diff --git a/docs-md/dev-tutorials/index.md b/docs-md/dev-tutorials/index.md new file mode 100644 index 0000000..cc8644d --- /dev/null +++ b/docs-md/dev-tutorials/index.md @@ -0,0 +1,3 @@ +# Quail Developer Tutorials + +This section contains tutorials \ No newline at end of file diff --git a/docs-md/index.md b/docs-md/index.md new file mode 100644 index 0000000..347d945 --- /dev/null +++ b/docs-md/index.md @@ -0,0 +1,11 @@ +## Quail Documentation Home + +[Back to home](/) + +[Quail Specification](spec/) + +[Quail Core Docs](core/) + +[Quail Library Docs](libs/) + +[Quail Developer Tutorials](dev-tutorials/) From 12ca35b998f5363ee7e9c6a3ffab2c282ea024d1 Mon Sep 17 00:00:00 2001 From: Tapeline Date: Sun, 25 Feb 2024 00:12:24 +0500 Subject: [PATCH 03/10] Add support for addons. Fix global flags --- .idea/artifacts/quailTestAddon.xml | 8 ++ .idea/compiler.xml | 1 + .idea/encodings.xml | 2 + .../java/me/tapeline/quailj/GlobalFlags.java | 5 ++ .../main/java/me/tapeline/quailj/Main.java | 2 + .../AddonAlreadyRegisteredException.java | 16 ++++ .../quailj/addons/AddonLoadException.java | 23 ++++++ .../addons/AddonNotRegisteredException.java | 16 ++++ .../me/tapeline/quailj/addons/QuailAddon.java | 18 ++++ .../quailj/addons/QuailAddonLoader.java | 82 +++++++++++++++++++ .../quailj/addons/QuailAddonRegistry.java | 35 ++++++++ .../UnresolvedAddonMainClassException.java | 18 ++++ .../quailj/launcher/LaunchCommandParser.java | 10 ++- .../quailj/launcher/QuailLauncher.java | 18 +++- .../me/tapeline/quailj/parsing/Parser.java | 5 ++ .../quailj/preprocessing/Preprocessor.java | 4 + .../me/tapeline/quailj/runtime/Runtime.java | 10 +++ pom.xml | 1 + program6.q | 12 ++- quailAddons/QuailTestAddon/pom.xml | 30 +++++++ .../quail/addons/MyTestAnnotation.java | 20 +++++ .../quail/addons/MyTestDirective.java | 29 +++++++ .../tapeline/quail/addons/MyTestFuncTest.java | 33 ++++++++ .../tapeline/quail/addons/MyTestLibrary.java | 31 +++++++ .../tapeline/quail/addons/QuailTestAddon.java | 39 +++++++++ .../src/main/resources/addonMainClass | 1 + 26 files changed, 459 insertions(+), 10 deletions(-) create mode 100644 .idea/artifacts/quailTestAddon.xml create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/AddonAlreadyRegisteredException.java create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/AddonLoadException.java create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/AddonNotRegisteredException.java create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/QuailAddon.java create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/QuailAddonLoader.java create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/QuailAddonRegistry.java create mode 100644 QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/UnresolvedAddonMainClassException.java create mode 100644 quailAddons/QuailTestAddon/pom.xml create mode 100644 quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/MyTestAnnotation.java create mode 100644 quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/MyTestDirective.java create mode 100644 quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/MyTestFuncTest.java create mode 100644 quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/MyTestLibrary.java create mode 100644 quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/QuailTestAddon.java create mode 100644 quailAddons/QuailTestAddon/src/main/resources/addonMainClass diff --git a/.idea/artifacts/quailTestAddon.xml b/.idea/artifacts/quailTestAddon.xml new file mode 100644 index 0000000..3d36db4 --- /dev/null +++ b/.idea/artifacts/quailTestAddon.xml @@ -0,0 +1,8 @@ + + + $PROJECT_DIR$/out/artifacts/quailTestAddon + + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 2c878f0..8b33e95 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -8,6 +8,7 @@ + diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 9b1b835..a7358d0 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -7,5 +7,7 @@ + + \ No newline at end of file diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/GlobalFlags.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/GlobalFlags.java index fc45694..d8ca6f4 100644 --- a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/GlobalFlags.java +++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/GlobalFlags.java @@ -25,4 +25,9 @@ public class GlobalFlags { public static short debugPort = 4004; + /** + * Specifies list of addons that should be loaded + */ + public static String addons = ""; + } diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/Main.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/Main.java index f4e1b2a..8693277 100644 --- a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/Main.java +++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/Main.java @@ -5,6 +5,8 @@ // TODO fix error display // TODO fix in operator and add contains method to list +// TODO revise flag documentation + public class Main { public static void main(String[] args) { diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/AddonAlreadyRegisteredException.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/AddonAlreadyRegisteredException.java new file mode 100644 index 0000000..2465073 --- /dev/null +++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/AddonAlreadyRegisteredException.java @@ -0,0 +1,16 @@ +package me.tapeline.quailj.addons; + +public class AddonAlreadyRegisteredException extends Exception { + + protected QuailAddon addon; + + public AddonAlreadyRegisteredException(QuailAddon addon) { + super("Addon " + addon + " already registered"); + this.addon = addon; + } + + public QuailAddon getAddon() { + return addon; + } + +} diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/AddonLoadException.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/AddonLoadException.java new file mode 100644 index 0000000..7abf6d0 --- /dev/null +++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/AddonLoadException.java @@ -0,0 +1,23 @@ +package me.tapeline.quailj.addons; + +import java.io.File; + +public class AddonLoadException extends Exception { + + protected File file; + + public AddonLoadException(String message, File file) { + super(message + "\nFile: " + file); + this.file = file; + } + + public AddonLoadException(Throwable cause, File file) { + super("Cannot load addon " + file + " due to " + cause, cause); + this.file = file; + } + + public File getFile() { + return file; + } + +} diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/AddonNotRegisteredException.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/AddonNotRegisteredException.java new file mode 100644 index 0000000..da30ef8 --- /dev/null +++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/AddonNotRegisteredException.java @@ -0,0 +1,16 @@ +package me.tapeline.quailj.addons; + +public class AddonNotRegisteredException extends Exception { + + protected String addon; + + public AddonNotRegisteredException(String addon) { + super("Addon " + addon + " is not registered"); + this.addon = addon; + } + + public String getAddon() { + return addon; + } + +} diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/QuailAddon.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/QuailAddon.java new file mode 100644 index 0000000..a44de3d --- /dev/null +++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/QuailAddon.java @@ -0,0 +1,18 @@ +package me.tapeline.quailj.addons; + +import me.tapeline.quailj.parsing.annotation.Annotation; +import me.tapeline.quailj.preprocessing.directives.AbstractDirective; +import me.tapeline.quailj.runtime.Runtime; +import me.tapeline.quailj.runtime.librarymanagement.BuiltinLibrary; + +import java.util.List; + +public abstract class QuailAddon { + + public abstract String getName(); + public abstract List providedDirectives(); + public abstract List providedAnnotations(); + public abstract List providedLibraries(); + public void customizeRuntime(Runtime runtime) {} + +} diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/QuailAddonLoader.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/QuailAddonLoader.java new file mode 100644 index 0000000..ee754a9 --- /dev/null +++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/QuailAddonLoader.java @@ -0,0 +1,82 @@ +package me.tapeline.quailj.addons; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +public class QuailAddonLoader { + + public static QuailAddon loadAddonFromJar(File file) throws + UnresolvedAddonMainClassException, AddonLoadException { + JarFile jarFile; + try { + jarFile = new JarFile(file); + } catch (IOException e) { + throw new AddonLoadException(e, file); + } + Enumeration e = jarFile.entries(); + String mainClass = null; + while (e.hasMoreElements()) { + JarEntry entry = e.nextElement(); + if (entry.getName().equals("addonMainClass")) { + BufferedReader reader; + try { + reader = new BufferedReader(new InputStreamReader(jarFile.getInputStream(entry))); + } catch (IOException ex) { + throw new AddonLoadException(ex, file); + } + try { + String line = reader.readLine(); + if (line == null) throw new UnresolvedAddonMainClassException(file); + mainClass = line.trim(); + break; + } catch (IOException exception) { + throw new UnresolvedAddonMainClassException(file); + } + } + } + + URL[] urls; + try { + urls = new URL[]{ new URL("jar:file:" + file + "!/") }; + } catch (MalformedURLException ex) { + throw new AddonLoadException(ex, file); + } + URLClassLoader cl = URLClassLoader.newInstance(urls); + + while (e.hasMoreElements()) { + JarEntry je = e.nextElement(); + if(je.isDirectory() || !je.getName().endsWith(".class")) { + continue; + } + // -6 because of .class + String className = je.getName().substring(0, je.getName().length() - 6); + className = className.replace('/', '.'); + try { + Class c = cl.loadClass(className); + if (className.equals(mainClass)) { + return (QuailAddon) c.newInstance(); + } + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException exception) { + throw new AddonLoadException(exception, file); + } + } + + throw new UnresolvedAddonMainClassException(file); + } + + public static QuailAddon loadAndRegisterFromJar(File file) throws UnresolvedAddonMainClassException, + AddonLoadException, AddonAlreadyRegisteredException { + QuailAddon addon = loadAddonFromJar(file); + QuailAddonRegistry.registerAddon(addon); + return addon; + } + +} diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/QuailAddonRegistry.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/QuailAddonRegistry.java new file mode 100644 index 0000000..1a98b19 --- /dev/null +++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/QuailAddonRegistry.java @@ -0,0 +1,35 @@ +package me.tapeline.quailj.addons; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class QuailAddonRegistry { + + protected static HashMap registeredAddons = new HashMap<>(); + + public static void registerAddon(QuailAddon addon) throws AddonAlreadyRegisteredException { + if (registeredAddons.containsKey(addon.getName())) + throw new AddonAlreadyRegisteredException(addon); + registeredAddons.put(addon.getName(), addon); + } + + public static QuailAddon getAddonByName(String name) { + return registeredAddons.get(name); + } + + public static List getAddons() { + return new ArrayList<>(registeredAddons.values()); + } + + public static void unregisterAddon(String name) throws AddonNotRegisteredException { + if (!registeredAddons.containsKey(name)) + throw new AddonNotRegisteredException(name); + registeredAddons.remove(name); + } + + public static boolean addonRegistered(String name) { + return registeredAddons.containsKey(name); + } + +} diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/UnresolvedAddonMainClassException.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/UnresolvedAddonMainClassException.java new file mode 100644 index 0000000..45538a3 --- /dev/null +++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/addons/UnresolvedAddonMainClassException.java @@ -0,0 +1,18 @@ +package me.tapeline.quailj.addons; + +import java.io.File; + +public class UnresolvedAddonMainClassException extends Exception { + + protected File file; + + public UnresolvedAddonMainClassException(File file) { + super("Cannot resolve main class in addon " + file); + this.file = file; + } + + public File getFile() { + return file; + } + +} diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/launcher/LaunchCommandParser.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/launcher/LaunchCommandParser.java index 1c0f64d..366e580 100644 --- a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/launcher/LaunchCommandParser.java +++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/launcher/LaunchCommandParser.java @@ -70,9 +70,15 @@ private void parseFlag(String flag) { else { String flagName = flag.substring(3, flag.indexOf('=')); if (flagName.equals("encoding")) - globalFlags.put("encoding", flag.substring(flag.indexOf('=' + 1))); + globalFlags.put("encoding", flag.substring(flag.indexOf('=') + 1)); if (flagName.equals("ignoreDocs")) - globalFlags.put("ignoreDocs", toBoolean(flag.substring(flag.indexOf('=' + 1)))); + globalFlags.put("ignoreDocs", toBoolean(flag.substring(flag.indexOf('=') + 1))); + if (flagName.equals("debugPort")) + globalFlags.put("debugPort", Short.parseShort(flag.substring(flag.indexOf('=') + 1))); + if (flagName.equals("displayReturnValue")) + globalFlags.put("displayReturnValue", toBoolean(flag.substring(flag.indexOf('=') + 1))); + if (flagName.equals("addons")) + globalFlags.put("addons", flag.substring(flag.indexOf('=') + 1)); } } else { int assignPosition = 0; 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 768e98b..2973714 100644 --- a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/launcher/QuailLauncher.java +++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/launcher/QuailLauncher.java @@ -1,6 +1,7 @@ package me.tapeline.quailj.launcher; import me.tapeline.quailj.GlobalFlags; +import me.tapeline.quailj.addons.*; import me.tapeline.quailj.debugging.DebugServer; import me.tapeline.quailj.docgen.DocumentationGenerator; import me.tapeline.quailj.io.DefaultIO; @@ -20,8 +21,11 @@ import java.io.File; import java.io.IOException; +import java.util.Arrays; import java.util.HashMap; import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; public class QuailLauncher { // TODO: refactor @@ -49,6 +53,8 @@ private void setupGlobalFlags(HashMap flags) { GlobalFlags.displayReturnValue = parseBoolFlag(flags.get("displayReturnValue").toString()); if (flags.containsKey("debugPort")) GlobalFlags.debugPort = (short) flags.get("debugPort"); + if (flags.containsKey("addons")) + GlobalFlags.addons = ((String) flags.get("addons")); } private void setupDebugger() throws IOException { @@ -59,7 +65,8 @@ private void setupDebugger() throws IOException { } public QObject launch(String[] args) throws IOException, PreprocessorException, - LexerException, ParserException, LauncherException { + LexerException, ParserException, LauncherException, AddonAlreadyRegisteredException, + UnresolvedAddonMainClassException, AddonLoadException { LaunchCommandParser launchCommandParser = new LaunchCommandParser(args); launchCommandParser.parseReceivedArgs(); localFlags = launchCommandParser.getUserFlags(); @@ -85,6 +92,11 @@ public QObject launch(String[] args) throws IOException, PreprocessorException, GlobalFlags.encoding); File scriptHome = new File(launchCommandParser.getTargetScript()).getAbsoluteFile().getParentFile(); + List addonsToLoad = Arrays.stream(GlobalFlags.addons.split(";")). + filter(s -> !s.isEmpty()) + .map(File::new).collect(Collectors.toList()); + for (File file : addonsToLoad) QuailAddonLoader.loadAndRegisterFromJar(file); + Preprocessor.resetDirectives(); Preprocessor preprocessor = new Preprocessor(code, scriptHome); String preprocessedCode = preprocessor.preprocess(); @@ -209,6 +221,10 @@ public QObject launchAndHandleErrors(String[] args) { } catch (LexerException e) { System.err.println("Lexer error:"); System.err.println(e.formatError()); + } catch (AddonAlreadyRegisteredException | UnresolvedAddonMainClassException | AddonLoadException e) { + System.err.println("Addon exception: "); + System.err.println(e.getMessage()); + e.printStackTrace(System.err); } return null; } 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 2e88f05..3e40d14 100644 --- a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/parsing/Parser.java +++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/parsing/Parser.java @@ -1,5 +1,7 @@ package me.tapeline.quailj.parsing; +import me.tapeline.quailj.addons.QuailAddon; +import me.tapeline.quailj.addons.QuailAddonRegistry; import me.tapeline.quailj.lexing.Token; import me.tapeline.quailj.lexing.TokenType; import me.tapeline.quailj.parsing.annotation.Annotation; @@ -64,6 +66,9 @@ public Parser(String code, List tokens) { public static void registerDefaultAnnotations() { registerAnnotation(new DeprecatedAnnotation()); registerAnnotation(new DecoratorAnnotation()); + for (QuailAddon addon : QuailAddonRegistry.getAddons()) + for (Annotation annotation : addon.providedAnnotations()) + registerAnnotation(annotation); } public static void registerAnnotation(Annotation annotation) { diff --git a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/preprocessing/Preprocessor.java b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/preprocessing/Preprocessor.java index f2dd5fe..15c0221 100644 --- a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/preprocessing/Preprocessor.java +++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/preprocessing/Preprocessor.java @@ -1,5 +1,7 @@ package me.tapeline.quailj.preprocessing; +import me.tapeline.quailj.addons.QuailAddon; +import me.tapeline.quailj.addons.QuailAddonRegistry; import me.tapeline.quailj.preprocessing.directives.*; import java.io.File; @@ -13,6 +15,8 @@ public static void resetDirectives() { registeredDirectives.clear(); registeredDirectives.add(new IncludeDirective()); registeredDirectives.add(new AliasDirective()); + for (QuailAddon addon : QuailAddonRegistry.getAddons()) + registeredDirectives.addAll(addon.providedDirectives()); } private int pos; 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 0d06ff6..e187884 100644 --- a/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/Runtime.java +++ b/QuailRuntimeEnvironment/src/main/java/me/tapeline/quailj/runtime/Runtime.java @@ -1,5 +1,7 @@ package me.tapeline.quailj.runtime; +import me.tapeline.quailj.addons.QuailAddon; +import me.tapeline.quailj.addons.QuailAddonRegistry; import me.tapeline.quailj.debugging.DebugServer; import me.tapeline.quailj.io.DefaultIO; import me.tapeline.quailj.io.IO; @@ -15,6 +17,7 @@ import me.tapeline.quailj.parsing.nodes.variable.VariableNode; import me.tapeline.quailj.preprocessing.Preprocessor; import me.tapeline.quailj.preprocessing.PreprocessorException; +import me.tapeline.quailj.runtime.librarymanagement.BuiltinLibrary; import me.tapeline.quailj.runtime.librarymanagement.LibraryCache; import me.tapeline.quailj.runtime.librarymanagement.LibraryLoader; import me.tapeline.quailj.runtime.std.basic.classes.dict.*; @@ -270,6 +273,13 @@ private void registerDefaults() { libraryLoader.addBuiltinLibrary(new ReflectLibrary()); libraryLoader.addBuiltinLibrary(new CliLibrary()); libraryLoader.addBuiltinLibrary(new DataLibrary()); + + for (QuailAddon addon : QuailAddonRegistry.getAddons()) + for (BuiltinLibrary library : addon.providedLibraries()) + libraryLoader.addBuiltinLibrary(library); + + for (QuailAddon addon : QuailAddonRegistry.getAddons()) + addon.customizeRuntime(this); } public void error(String message) throws RuntimeStriker { diff --git a/pom.xml b/pom.xml index 41cdf81..6178c70 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,7 @@ QuailRuntimeEnvironment QuailDevelopmentKit + quailAddons/QuailTestAddon diff --git a/program6.q b/program6.q index 78d271b..ba643ae 100644 --- a/program6.q +++ b/program6.q @@ -1,10 +1,8 @@ -use "lang/data" = data; Bytes = data.Bytes; Set = data.Set; Queue = data.Queue; Deque = data.Deque; +#:testdirective -q = Deque() -q.addBack("a") -q.addBack("b") -q.addFront("d") +@MyTestAnnotation +function f() {} -for e in q: - print(e) +use "qta/mytestlib" = mytestlib +print(mytestlib.test()) diff --git a/quailAddons/QuailTestAddon/pom.xml b/quailAddons/QuailTestAddon/pom.xml new file mode 100644 index 0000000..9cf49be --- /dev/null +++ b/quailAddons/QuailTestAddon/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + + me.tapeline + quail + 2.0-alpha + ../../pom.xml + + + me.tapeline.quail.addons + QuailTestAddon + + + 8 + 8 + UTF-8 + + + + me.tapeline.quail + qre + 2.0-alpha + compile + + + + \ No newline at end of file diff --git a/quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/MyTestAnnotation.java b/quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/MyTestAnnotation.java new file mode 100644 index 0000000..76f44f6 --- /dev/null +++ b/quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/MyTestAnnotation.java @@ -0,0 +1,20 @@ +package me.tapeline.quail.addons; + +import me.tapeline.quailj.parsing.annotation.Annotation; +import me.tapeline.quailj.parsing.nodes.Node; + +import java.util.Arrays; + +public class MyTestAnnotation implements Annotation { + @Override + public String name() { + return "MyTestAnnotation"; + } + + @Override + public Node apply(Node target, Object... args) { + System.out.println("MyTestAnnotation called with args:"); + System.out.println(Arrays.toString(args)); + return target; + } +} diff --git a/quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/MyTestDirective.java b/quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/MyTestDirective.java new file mode 100644 index 0000000..c4b229f --- /dev/null +++ b/quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/MyTestDirective.java @@ -0,0 +1,29 @@ +package me.tapeline.quail.addons; + +import me.tapeline.quailj.preprocessing.StringBoundariesMap; +import me.tapeline.quailj.preprocessing.directives.AbstractDirective; +import me.tapeline.quailj.preprocessing.directives.DirectiveArgument; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +public class MyTestDirective extends AbstractDirective { + + @Override + public String prefix() { + return "testdirective"; + } + + @Override + public List arguments() { + return new ArrayList<>(); + } + + @Override + public String applyDirective(String code, File scriptHome, StringBoundariesMap boundaries, Object... arguments) { + System.out.println("Test directive applied"); + return code; + } + +} diff --git a/quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/MyTestFuncTest.java b/quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/MyTestFuncTest.java new file mode 100644 index 0000000..36faa6e --- /dev/null +++ b/quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/MyTestFuncTest.java @@ -0,0 +1,33 @@ +package me.tapeline.quail.addons; + +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.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.List; + +public class MyTestFuncTest extends QBuiltinFunc { + + public MyTestFuncTest(Runtime runtime) { + super( + "test", + Arrays.asList(), + runtime, + runtime.getMemory(), + false + ); + } + + @Override + public QObject action(Runtime runtime, HashMap args, List argList) throws RuntimeStriker { + return Val("Test library works!"); + } + +} diff --git a/quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/MyTestLibrary.java b/quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/MyTestLibrary.java new file mode 100644 index 0000000..630c9f7 --- /dev/null +++ b/quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/MyTestLibrary.java @@ -0,0 +1,31 @@ +package me.tapeline.quail.addons; + +import me.tapeline.quailj.runtime.Runtime; +import me.tapeline.quailj.runtime.librarymanagement.BuiltinLibrary; +import me.tapeline.quailj.typing.classes.QObject; + +import java.util.HashMap; + +public class MyTestLibrary implements BuiltinLibrary { + + @Override + public String id() { + return "qta/mytestlib"; + } + + @Override + public Runtime initializeRuntime() { + return new Runtime(); + } + + @Override + public QObject constructLibrary(Runtime runtime) { + HashMap contents = new HashMap<>(); + contents.put("test", new MyTestFuncTest(runtime)); + + runtime.getMemory().table.putAll(contents); + + return QObject.Val(contents); + } + +} diff --git a/quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/QuailTestAddon.java b/quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/QuailTestAddon.java new file mode 100644 index 0000000..60d2522 --- /dev/null +++ b/quailAddons/QuailTestAddon/src/main/java/me/tapeline/quail/addons/QuailTestAddon.java @@ -0,0 +1,39 @@ +package me.tapeline.quail.addons; + +import me.tapeline.quailj.addons.QuailAddon; +import me.tapeline.quailj.parsing.annotation.Annotation; +import me.tapeline.quailj.preprocessing.directives.AbstractDirective; +import me.tapeline.quailj.runtime.librarymanagement.BuiltinLibrary; + +import java.util.Arrays; +import java.util.List; + +public class QuailTestAddon extends QuailAddon { + + @Override + public String getName() { + return "QuailTestAddon"; + } + + @Override + public List providedDirectives() { + return Arrays.asList( + new MyTestDirective() + ); + } + + @Override + public List providedAnnotations() { + return Arrays.asList( + new MyTestAnnotation() + ); + } + + @Override + public List providedLibraries() { + return Arrays.asList( + new MyTestLibrary() + ); + } + +} diff --git a/quailAddons/QuailTestAddon/src/main/resources/addonMainClass b/quailAddons/QuailTestAddon/src/main/resources/addonMainClass new file mode 100644 index 0000000..7fbe14f --- /dev/null +++ b/quailAddons/QuailTestAddon/src/main/resources/addonMainClass @@ -0,0 +1 @@ +me.tapeline.quail.addons.QuailTestAddon From 6d44256fcddddc95b63e4267f9be4393af55f844 Mon Sep 17 00:00:00 2001 From: Tapeline Date: Sun, 25 Feb 2024 21:30:54 +0500 Subject: [PATCH 04/10] Add comprehensive docs on syntax. Begin work on dev tutorials --- .idea/misc.xml | 2 + .../main/java/me/tapeline/quailj/Main.java | 2 + .../dev-tutorials/1-how-to-create-addon.md | 101 ++ .../2-how-to-create-directives.md | 37 + .../3-how-to-create-annotations.md | 28 + docs-md/dev-tutorials/index.md | 8 +- docs-md/spec/chapter1.md | 8 + docs-md/spec/chapter16.md | 31 + docs-md/spec/chapter2.md | 1031 ++++++++++++++++- docs-md/spec/chapter8.md | 2 + docs-md/spec/index.md | 4 +- program6.q | 14 +- 12 files changed, 1252 insertions(+), 16 deletions(-) create mode 100644 docs-md/dev-tutorials/1-how-to-create-addon.md create mode 100644 docs-md/dev-tutorials/2-how-to-create-directives.md create mode 100644 docs-md/dev-tutorials/3-how-to-create-annotations.md create mode 100644 docs-md/spec/chapter16.md diff --git a/.idea/misc.xml b/.idea/misc.xml index afad88e..0158d06 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,3 +1,4 @@ + @@ -5,6 +6,7 @@