├── .vscode └── settings.json ├── .gitignore ├── src ├── test │ ├── resources │ │ └── io │ │ │ └── reference-serialized-binary-values.zip │ └── java │ │ └── io │ │ └── usethesource │ │ └── vallang │ │ ├── specification │ │ ├── package-info.java │ │ ├── ListTests.java │ │ ├── SetTests.java │ │ └── IMapTests.java │ │ ├── ArgumentsSeed.java │ │ ├── GivenValue.java │ │ ├── ArgumentsMaxDepth.java │ │ ├── ArgumentsMaxWidth.java │ │ ├── ExpectedType.java │ │ ├── io │ │ ├── OpenAddressingLastWrittenReferenceTest.java │ │ ├── OpenAddressingLastWrittenBrokenHashTest.java │ │ ├── LinearCircularLookupWindowTest.java │ │ ├── TrackReadsTestBase.java │ │ ├── TrackWritesTestBase.java │ │ └── FileChannelOutputStreamTest.java │ │ ├── TypeConfig.java │ │ ├── basic │ │ ├── StreamCollectorTest.java │ │ ├── BooleanStoreProvider.java │ │ ├── RegressionTest.java │ │ ├── XMLSmokeTest.java │ │ ├── StreamTest.java │ │ └── ConcurrentTests.java │ │ └── issues │ │ └── RegressionTests.java ├── main │ └── java │ │ └── io │ │ └── usethesource │ │ └── vallang │ │ ├── impl │ │ ├── fields │ │ │ └── package-info.java │ │ ├── persistent │ │ │ ├── package-info.java │ │ │ ├── PersistentSetRelation.java │ │ │ ├── ListRelation.java │ │ │ ├── ValueCollectors.java │ │ │ └── PersistentSetFactory.java │ │ ├── reference │ │ │ ├── package-info.java │ │ │ ├── List.java │ │ │ ├── Set.java │ │ │ └── SetWriter.java │ │ ├── primitive │ │ │ ├── package-info.java │ │ │ ├── ICanBecomeABigInteger.java │ │ │ └── BoolValue.java │ │ └── util │ │ │ └── collections │ │ │ └── ShareableValuesList.java │ │ ├── exceptions │ │ ├── NullTypeException.java │ │ ├── TypeReificationException.java │ │ ├── EmptyIdentifierException.java │ │ ├── UnexpectedChildTypeException.java │ │ ├── UnexpectedAnnotationTypeException.java │ │ ├── UnexpectedConstructorTypeException.java │ │ ├── UndeclaredAbstractDataTypeException.java │ │ ├── InvalidDateTimeException.java │ │ ├── IllegalKeywordParameterDeclarationException.java │ │ ├── IllegalIdentifierException.java │ │ ├── IllegalConstructorApplicationException.java │ │ ├── UnsupportedTypeException.java │ │ ├── IllegalInstantiatedAbstractDataTypeException.java │ │ ├── IllegalOperationException.java │ │ ├── OverloadingNotSupportedException.java │ │ ├── FieldLabelMismatchException.java │ │ ├── UndeclaredFieldException.java │ │ ├── FactTypeRedeclaredException.java │ │ ├── RedeclaredKeywordParameterException.java │ │ ├── UnexpectedTypeException.java │ │ ├── IllegalFieldTypeException.java │ │ ├── IllegalFieldNameException.java │ │ ├── FactParseError.java │ │ ├── TypeParseError.java │ │ ├── RedeclaredConstructorException.java │ │ ├── FactTypeUseException.java │ │ ├── FactTypeDeclarationException.java │ │ └── RedeclaredFieldNameException.java │ │ ├── ISetWriter.java │ │ ├── io │ │ ├── AbstractTextReader.java │ │ ├── AbstractBinaryReader.java │ │ ├── binary │ │ │ ├── util │ │ │ │ ├── DirectByteBufferCache.java │ │ │ │ ├── ClearableWindow.java │ │ │ │ ├── ByteBufferInputStream.java │ │ │ │ ├── DirectZstdInputStream.java │ │ │ │ ├── TrackLastRead.java │ │ │ │ ├── TaggedInt.java │ │ │ │ ├── TrackLastWritten.java │ │ │ │ ├── ArrayUtil.java │ │ │ │ ├── FileChannelDirectOutputStream.java │ │ │ │ ├── LinearCircularLookupWindow.java │ │ │ │ ├── MapLastWritten.java │ │ │ │ ├── StructuredIValueVisitor.java │ │ │ │ ├── WindowSizes.java │ │ │ │ ├── DelayedCompressionOutputStream.java │ │ │ │ └── ByteBufferOutputStream.java │ │ │ ├── stream │ │ │ │ └── Header.java │ │ │ └── wire │ │ │ │ ├── FieldKind.java │ │ │ │ └── IWireOutputStream.java │ │ ├── IValueBinaryWriter.java │ │ ├── IValueTextWriter.java │ │ ├── IValueTextReader.java │ │ └── IValueBinaryReader.java │ │ ├── type │ │ ├── types.config │ │ ├── ITypeVisitor.java │ │ ├── DefaultTypeVisitor.java │ │ └── ExternalType.java │ │ ├── IBool.java │ │ ├── util │ │ ├── HashConsingMap.java │ │ ├── SecondsTicker.java │ │ └── RotatingQueue.java │ │ ├── visitors │ │ ├── IValueVisitor.java │ │ ├── IdentityVisitor.java │ │ ├── NullVisitor.java │ │ ├── BottomUpVisitor.java │ │ ├── VisitorAdapter.java │ │ └── BottomUpTransformer.java │ │ ├── IMapWriter.java │ │ ├── IWriter.java │ │ ├── ICollection.java │ │ ├── IListWriter.java │ │ └── IWithKeywordParameters.java └── CFErrors.rsc ├── .editorconfig ├── .git-blame-ignore-revs ├── .github ├── dependabot.yml └── workflows │ ├── publish-test-results.yaml │ └── codeql.yml ├── LICENSE ├── checkstyle.xml └── CODE_OF_CONDUCT.md /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "java.configuration.updateBuildConfiguration": "automatic", 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/bin/ 2 | **/target/ 3 | **/.project 4 | **/.classpath 5 | **/.settings 6 | 7 | .idea/ 8 | eclipse-java-google-style.xml 9 | -------------------------------------------------------------------------------- /src/test/resources/io/reference-serialized-binary-values.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usethesource/vallang/HEAD/src/test/resources/io/reference-serialized-binary-values.zip -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/impl/fields/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This contains generic wrapper classes to implement IAnnotable and IWithKeywordParameters for different 3 | * host values (INode and IConstructor). 4 | */ 5 | package io.usethesource.vallang.impl.fields; -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/impl/persistent/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This contains a full IValueFactory implementation which tries to be as efficient 3 | * as possible using persistent data-structures and specializations where possible. 4 | */ 5 | package io.usethesource.vallang.impl.persistent; -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/impl/reference/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This contains a full IValueFactory implementation which tries to be as simple 3 | * and direct as possible to implement the vallang specification. It is not efficient, 4 | * and only intended for design, documentation and testing purposes. 5 | */ 6 | package io.usethesource.vallang.impl.reference; -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/specification/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * work in progress: migrating random tests in Junit4 + homemade axiom based setup to this package 3 | * where we use JUnit 5 Parametrized tests instead. 4 | * 5 | * TODO: run tests for both implementations of IValueFactory somehow 6 | */ 7 | package io.usethesource.vallang.specification; 8 | 9 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/NullTypeException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | public class NullTypeException extends FactTypeUseException { 4 | private static final long serialVersionUID = -4201840676263159311L; 5 | 6 | public NullTypeException() { 7 | super("A null reference as a type"); 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/TypeReificationException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | public class TypeReificationException extends FactTypeUseException { 4 | private static final long serialVersionUID = -1606508959996710935L; 5 | 6 | public TypeReificationException(String reason, Throwable cause) { 7 | super(reason, cause); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/EmptyIdentifierException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | public class EmptyIdentifierException extends FactTypeDeclarationException { 4 | private static final long serialVersionUID = -7032740671919237233L; 5 | 6 | public EmptyIdentifierException() { 7 | super("An identifier can not be empty or null"); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/ArgumentsSeed.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.METHOD) 10 | public @interface ArgumentsSeed { 11 | long value(); 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/GivenValue.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.PARAMETER) 10 | public @interface GivenValue { 11 | String value(); 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/ArgumentsMaxDepth.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.METHOD) 10 | public @interface ArgumentsMaxDepth { 11 | int value(); 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/ArgumentsMaxWidth.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.METHOD) 10 | public @interface ArgumentsMaxWidth { 11 | int value(); 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/ExpectedType.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.PARAMETER) 10 | public @interface ExpectedType { 11 | String value(); 12 | } 13 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 4 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | max_line_length = 80 11 | 12 | [*.sh] 13 | end_of_line = lf 14 | 15 | [*.java] 16 | indent_size = 4 17 | max_line_length = 120 18 | 19 | 20 | [*.yaml] 21 | indent_size = 2 22 | 23 | [*.yml] 24 | indent_size = 2 25 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/UnexpectedChildTypeException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | import io.usethesource.vallang.type.Type; 4 | 5 | public class UnexpectedChildTypeException extends UnexpectedTypeException { 6 | private static final long serialVersionUID = -1848764011952028440L; 7 | 8 | public UnexpectedChildTypeException(Type expected, Type got) { 9 | super(expected, got); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/UnexpectedAnnotationTypeException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | import io.usethesource.vallang.type.Type; 4 | 5 | public class UnexpectedAnnotationTypeException extends UnexpectedTypeException { 6 | private static final long serialVersionUID = -4865168232421987847L; 7 | 8 | public UnexpectedAnnotationTypeException(Type expected, Type got) { 9 | super(expected, got); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/UnexpectedConstructorTypeException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | import io.usethesource.vallang.type.Type; 4 | 5 | public class UnexpectedConstructorTypeException extends UnexpectedTypeException { 6 | private static final long serialVersionUID = -6198133177142765746L; 7 | 8 | public UnexpectedConstructorTypeException(Type expected, Type got) { 9 | super(expected, got); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/UndeclaredAbstractDataTypeException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | import io.usethesource.vallang.type.Type; 4 | 5 | public class UndeclaredAbstractDataTypeException extends 6 | FactTypeDeclarationException { 7 | private static final long serialVersionUID = 2192451595458909479L; 8 | 9 | public UndeclaredAbstractDataTypeException(Type adt) { 10 | super(adt + " is not registered"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/InvalidDateTimeException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | public class InvalidDateTimeException extends FactTypeUseException { 4 | 5 | private static final long serialVersionUID = 5634976179346912971L; 6 | 7 | public InvalidDateTimeException(String message) { 8 | super(message); 9 | } 10 | 11 | public InvalidDateTimeException(String message, Throwable cause) { 12 | super(message, cause); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # Run this command to always ignore formatting commits in `git blame` 2 | # git config blame.ignoreRevsFile .git-blame-ignore-revs 3 | 4 | # replaced tabs with spaces 5 | 8efd5a7227658bbcc5b46ba647d15edf42dc0302 6 | 7 | # removed trailing whitespace 8 | 63917fec5f518cd66ebbf56903d5167ac1c815ab 9 | 10 | # normalize indentation 11 | 4ca06f1346d13d6e275d891de918cc6bae85c3d8 12 | f3301743a5e4ca39b415e4f1fa32c66a39ef37b5 13 | 14 | # normalize java style 15 | cd7470fee76f121adaca603b594228573be4d3d9 16 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/IllegalKeywordParameterDeclarationException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | import io.usethesource.vallang.type.Type; 4 | 5 | public class IllegalKeywordParameterDeclarationException extends FactTypeUseException { 6 | private static final long serialVersionUID = -1073149631907760703L; 7 | 8 | public IllegalKeywordParameterDeclarationException(Type type) { 9 | super("Keyword parameters can not be declared on " + type); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/io/OpenAddressingLastWrittenReferenceTest.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.io; 2 | 3 | import io.usethesource.vallang.io.binary.util.OpenAddressingLastWritten; 4 | import io.usethesource.vallang.io.binary.util.TrackLastWritten; 5 | 6 | public class OpenAddressingLastWrittenReferenceTest extends TrackWritesTestBase { 7 | @Override 8 | public TrackLastWritten getWritesWindow(int size) { 9 | return OpenAddressingLastWritten.referenceEquality(size); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/IllegalIdentifierException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | public class IllegalIdentifierException extends FactTypeDeclarationException { 4 | private static final long serialVersionUID = 7380196205269771711L; 5 | private String id; 6 | 7 | public IllegalIdentifierException(String id) { 8 | super(id + " is not a valid identifier"); 9 | this.id = id; 10 | } 11 | 12 | public String getIdentifier() { 13 | return id; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/IllegalConstructorApplicationException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | import io.usethesource.vallang.type.Type; 4 | 5 | public class IllegalConstructorApplicationException extends FactTypeUseException { 6 | private static final long serialVersionUID = -1412303012184333060L; 7 | 8 | public IllegalConstructorApplicationException(Type constructorType, Type arguments) { 9 | super("Constructor " + constructorType + " is not applicable to " + arguments); 10 | } 11 | 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/UnsupportedTypeException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | import io.usethesource.vallang.type.Type; 4 | 5 | public class UnsupportedTypeException extends FactTypeUseException { 6 | private static final long serialVersionUID = -8995093767494157052L; 7 | private Type type; 8 | public UnsupportedTypeException(String explanation, Type type) { 9 | super(explanation); 10 | this.type = type; 11 | } 12 | 13 | public Type getType() { 14 | return type; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/IllegalInstantiatedAbstractDataTypeException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | import io.usethesource.vallang.type.Type; 4 | 5 | public class IllegalInstantiatedAbstractDataTypeException extends 6 | FactTypeDeclarationException { 7 | private static final long serialVersionUID = -7171289358305194254L; 8 | 9 | public IllegalInstantiatedAbstractDataTypeException(Type adt) { 10 | super("should not declare instances of type-parametrized abstract data-types (" + adt + ")"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/TypeConfig.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ElementType.PARAMETER, ElementType.METHOD}) 10 | public @interface TypeConfig { 11 | public enum Option { 12 | TYPE_PARAMETERS, 13 | ALIASES, 14 | TUPLE_FIELDNAMES, 15 | MAP_FIELDNAMES, 16 | ALL 17 | } 18 | 19 | Option[] value(); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/IllegalOperationException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | import io.usethesource.vallang.type.Type; 4 | 5 | public class IllegalOperationException extends FactTypeUseException { 6 | private static final long serialVersionUID = 546504861606007094L; 7 | 8 | public IllegalOperationException(String op, Type lhs) { 9 | super("Operation " + op + " not allowed on " + lhs); 10 | } 11 | 12 | public IllegalOperationException(String op, Type lhs, Type rhs) { 13 | super("Operation " +op + " not allowed on " + lhs + " and " + rhs); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/OverloadingNotSupportedException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | import io.usethesource.vallang.type.Type; 4 | 5 | public class OverloadingNotSupportedException extends FactTypeUseException { 6 | private static final long serialVersionUID = 5645367130014687132L; 7 | 8 | public OverloadingNotSupportedException(String constructorId) { 9 | super("Overloading is not supported (" + constructorId + ")"); 10 | } 11 | 12 | public OverloadingNotSupportedException(Type adt, String constructorId) { 13 | super("Overloading is not supported (" + adt + "." + constructorId + ")"); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/FieldLabelMismatchException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | public class FieldLabelMismatchException extends FactTypeDeclarationException { 4 | private static final long serialVersionUID = 3510697170437859049L; 5 | private int fields; 6 | private int labels; 7 | 8 | public FieldLabelMismatchException(int fields, int labels) { 9 | super("Expected " + fields + " field labels, but got " + labels); 10 | this.fields = fields; 11 | this.labels = labels; 12 | } 13 | 14 | public int getFields() { 15 | return fields; 16 | } 17 | 18 | public int getLabels() { 19 | return labels; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/ISetWriter.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2007 IBM Corporation. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation 10 | 11 | *******************************************************************************/ 12 | 13 | package io.usethesource.vallang; 14 | 15 | public interface ISetWriter extends IWriter { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "maven" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | open-pull-requests-limit: 10 8 | groups: 9 | upstream-libs: 10 | patterns: 11 | - "*" 12 | exclude-patterns: 13 | - "*capsule*" 14 | - "*checkerframework*" 15 | - "*maven.plugins*" 16 | checker-framework: 17 | patterns: 18 | - "*checkerframework*" 19 | maven-plugins: 20 | patterns: 21 | - "*maven.plugins*" 22 | 23 | - package-ecosystem: "github-actions" 24 | directory: "/" 25 | schedule: 26 | interval: "monthly" 27 | groups: 28 | gh-actions: 29 | patterns: 30 | - "*" # group all GH action upgrades in a single PR 31 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/UndeclaredFieldException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | import io.usethesource.vallang.type.Type; 4 | 5 | public class UndeclaredFieldException extends FactTypeUseException { 6 | private static final long serialVersionUID = 8997399464492627705L; 7 | private Type type; 8 | private String label; 9 | 10 | public UndeclaredFieldException(Type type, String label) { 11 | super(type + " does not have a field with label " + label + " declared for it"); 12 | this.type = type; 13 | this.label = label; 14 | } 15 | 16 | public Type getType() { 17 | return type; 18 | } 19 | 20 | public String getLabel() { 21 | return label; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/FactTypeRedeclaredException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | import io.usethesource.vallang.type.Type; 4 | 5 | public class FactTypeRedeclaredException extends FactTypeDeclarationException { 6 | private static final long serialVersionUID = 9191150588452685289L; 7 | private String name; 8 | private Type earlier; 9 | 10 | public FactTypeRedeclaredException(String name, Type earlier) { 11 | super(name + " was declared earlier as " + earlier); 12 | this.name = name; 13 | this.earlier = earlier; 14 | } 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | public Type declaredEarlier() { 21 | return earlier; 22 | } 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/CFErrors.rsc: -------------------------------------------------------------------------------- 1 | module CFErrors 2 | 3 | import util::ResourceMarkers; 4 | import Message; 5 | import IO; 6 | import String; 7 | 8 | public loc LOG = |home:///git/vallang/LOG11|; 9 | 10 | int offset(loc file, int l) 11 | = ( 0 | it + size(line) | line <- readFileLines(file)[..l-1]); 12 | 13 | loc path(str path, str l, str c) { 14 | p = |project://vallang| + path; 15 | return p(offset(p, toInt(l)) + toInt(c), 1); 16 | } 17 | 18 | set[Message] messages(loc log) 19 | = { warning(m + "@, ", path(p, l, c)) 20 | | /\[ERROR\] .*\/git\/vallang\/:\[,\] $/ <- readFileLines(log) 21 | }; 22 | 23 | void setCFerrors() { 24 | addMessageMarkers(messages(LOG)); 25 | } 26 | 27 | void clearCFerrors() { 28 | removeMessageMarkers(|project://vallang/src|); 29 | } -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/RedeclaredKeywordParameterException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | import io.usethesource.vallang.type.Type; 4 | 5 | public class RedeclaredKeywordParameterException extends FactTypeDeclarationException { 6 | private static final long serialVersionUID = -2118606173620347920L; 7 | private String label; 8 | private Type earlier; 9 | 10 | public RedeclaredKeywordParameterException(String label, Type earlier) { 11 | super("Keyword parameter " + label + " was declared earlier as " + earlier); 12 | this.label = label; 13 | this.earlier = earlier; 14 | } 15 | 16 | public String getLabel() { 17 | return label; 18 | } 19 | 20 | public Type getEarlierType() { 21 | return earlier; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/UnexpectedTypeException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | import io.usethesource.vallang.type.Type; 4 | 5 | public class UnexpectedTypeException extends FactTypeUseException { 6 | private static final long serialVersionUID = -5107803679675463540L; 7 | private Type expected; 8 | private Type got; 9 | 10 | public UnexpectedTypeException(Type expected, Type got) { 11 | super("Expected " + expected + ", but got " + got); 12 | this.expected = expected; 13 | this.got = got; 14 | } 15 | 16 | public boolean hasExpected() { 17 | return expected != null; 18 | } 19 | 20 | public Type getExpected() { 21 | return expected; 22 | } 23 | 24 | public Type getGiven() { 25 | return got; 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/impl/persistent/PersistentSetRelation.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.impl.persistent; 2 | 3 | import io.usethesource.vallang.IRelation; 4 | import io.usethesource.vallang.ISet; 5 | 6 | /** 7 | * The current implementation of relations for persistent sets is mostly 8 | * done by {@link PersistentHashIndexedBinaryRelation} for binary reflexive 9 | * relations. The other relations are covered by the default impementations 10 | * of {@link IRelation}. There is room for improvement there in the performance 11 | * department. 12 | */ 13 | public class PersistentSetRelation implements IRelation { 14 | private final ISet set; 15 | 16 | public PersistentSetRelation(ISet set) { 17 | this.set = set; 18 | } 19 | 20 | @Override 21 | public ISet asContainer() { 22 | return set; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/impl/primitive/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This contains an abstract IValueFactory implementation, AbstractPrimitiveValueFactory, which offers the 3 | * implementation for the atomic data-types of Vallang, to be re-used by factories 4 | * which specialize on the implementation of the container types. 5 | * 6 | *
    7 | *
  • IBool: see BoolValue
  • 8 | *
  • IInteger: see AbstractNumberValue, BigIntegerValue and IntegerValue, ICanBecomeABigInteger
  • 9 | *
  • IReal: see AbstractNumberValue, BigDecimalValue
  • 10 | *
  • IRational: see AbstractNumberValue, RationalValue
  • 11 | *
  • ISourceLocation: see SourceLocationURIValues and SourceLocationValues
  • 12 | *
  • IString: see StringValue
  • 13 | *
  • IDateTime: see DateTimeValues
  • 14 | * 15 | *
16 | */ 17 | package io.usethesource.vallang.impl.primitive; -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/IllegalFieldTypeException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | public class IllegalFieldTypeException extends FactTypeDeclarationException { 4 | private static final long serialVersionUID = -8845629423612702596L; 5 | private int pos; 6 | private Object elem; 7 | 8 | public IllegalFieldTypeException(int pos, Object elem, ClassCastException cause) { 9 | super("Expected a field type at position " + pos + ", but got something different", cause); 10 | this.pos = pos; 11 | this.elem = elem; 12 | } 13 | 14 | public Object getElement() { 15 | return elem; 16 | } 17 | 18 | public int getPos() { 19 | return pos; 20 | } 21 | 22 | public synchronized Throwable getCause() { 23 | Throwable cause = super.getCause(); 24 | return cause == null ? this : cause; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/io/OpenAddressingLastWrittenBrokenHashTest.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.io; 2 | 3 | import org.checkerframework.checker.nullness.qual.NonNull; 4 | 5 | import io.usethesource.vallang.io.binary.util.OpenAddressingLastWritten; 6 | import io.usethesource.vallang.io.binary.util.TrackLastWritten; 7 | 8 | public class OpenAddressingLastWrittenBrokenHashTest extends TrackWritesTestBase { 9 | @Override 10 | public TrackLastWritten getWritesWindow(int size) { 11 | return new OpenAddressingLastWritten<@NonNull Object>(size) { 12 | @Override 13 | protected boolean equals(@NonNull Object a, @NonNull Object b) { 14 | return a == b; 15 | } 16 | 17 | @Override 18 | protected int hash(@NonNull Object obj) { 19 | return System.identityHashCode(obj) % Math.max(2, size / 2); 20 | } 21 | }; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/IllegalFieldNameException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | import org.checkerframework.checker.nullness.qual.Nullable; 4 | 5 | public class IllegalFieldNameException extends FactTypeDeclarationException { 6 | private static final long serialVersionUID = -2480224409679761754L; 7 | private int pos; 8 | private Object elem; 9 | 10 | public IllegalFieldNameException(int pos, Object elem, ClassCastException cause) { 11 | super("Expected a field name at position " + pos + ", but got something different", cause); 12 | this.pos = pos; 13 | this.elem = elem; 14 | } 15 | 16 | public Object getElement() { 17 | return elem; 18 | } 19 | 20 | public int getPos() { 21 | return pos; 22 | } 23 | 24 | public synchronized @Nullable ClassCastException getCause() { 25 | return (ClassCastException) super.getCause(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/FactParseError.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | public class FactParseError extends RuntimeException { 4 | private static final long serialVersionUID = 8208492896666238438L; 5 | private int offset = -1; 6 | 7 | public FactParseError(String message, Throwable cause) { 8 | super(message, cause); 9 | } 10 | 11 | public FactParseError(String message, int offset) { 12 | super(message); 13 | this.offset = offset; 14 | } 15 | 16 | public FactParseError(String message, int offset, Throwable cause) { 17 | super(message + " at offset " + offset, cause); 18 | this.offset = offset; 19 | } 20 | 21 | public boolean hasCause() { 22 | return getCause() != null; 23 | } 24 | 25 | 26 | public boolean hasOffset() { 27 | return offset != -1; 28 | } 29 | public int getOffset() { 30 | return offset; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/TypeParseError.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | public class TypeParseError extends RuntimeException { 4 | private static final long serialVersionUID = 7054359699049181437L; 5 | private int offset = -1; 6 | 7 | public TypeParseError(String message, Throwable cause) { 8 | super(message, cause); 9 | } 10 | 11 | public TypeParseError(String message, int offset) { 12 | super(message); 13 | this.offset = offset; 14 | } 15 | 16 | public TypeParseError(String message, int offset, Throwable cause) { 17 | super(message + " at offset " + offset, cause); 18 | this.offset = offset; 19 | } 20 | 21 | public boolean hasCause() { 22 | return getCause() != null; 23 | } 24 | 25 | 26 | public boolean hasOffset() { 27 | return offset != -1; 28 | } 29 | public int getOffset() { 30 | return offset; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/AbstractTextReader.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.io; 2 | 3 | import java.io.IOException; 4 | import java.io.Reader; 5 | 6 | import io.usethesource.vallang.IValue; 7 | import io.usethesource.vallang.IValueFactory; 8 | import io.usethesource.vallang.exceptions.FactTypeUseException; 9 | import io.usethesource.vallang.type.Type; 10 | import io.usethesource.vallang.type.TypeFactory; 11 | import io.usethesource.vallang.type.TypeStore; 12 | 13 | public abstract class AbstractTextReader implements IValueTextReader { 14 | public IValue read(IValueFactory factory, Type type, Reader reader) 15 | throws FactTypeUseException, IOException { 16 | return read(factory, new TypeStore(), type, reader); 17 | } 18 | 19 | public IValue read(IValueFactory factory, Reader reader) 20 | throws FactTypeUseException, IOException { 21 | return read(factory, new TypeStore(), TypeFactory.getInstance().valueType(), reader); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/AbstractBinaryReader.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.io; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | 6 | import io.usethesource.vallang.IValue; 7 | import io.usethesource.vallang.IValueFactory; 8 | import io.usethesource.vallang.exceptions.FactTypeUseException; 9 | import io.usethesource.vallang.type.Type; 10 | import io.usethesource.vallang.type.TypeFactory; 11 | import io.usethesource.vallang.type.TypeStore; 12 | 13 | public abstract class AbstractBinaryReader implements IValueBinaryReader { 14 | public IValue read(IValueFactory factory, Type type, InputStream stream) 15 | throws FactTypeUseException, IOException { 16 | return read(factory, new TypeStore(), type, stream); 17 | } 18 | 19 | public IValue read(IValueFactory factory, InputStream stream) 20 | throws FactTypeUseException, IOException { 21 | return read(factory, new TypeStore(), TypeFactory.getInstance().valueType(), stream); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/type/types.config: -------------------------------------------------------------------------------- 1 | io.usethesource.vallang.type.ValueType$Info 2 | io.usethesource.vallang.type.AbstractDataType$Info 3 | io.usethesource.vallang.type.AliasType$Info 4 | io.usethesource.vallang.type.BoolType$Info 5 | io.usethesource.vallang.type.ConstructorType$Info 6 | io.usethesource.vallang.type.DateTimeType$Info 7 | io.usethesource.vallang.type.IntegerType$Info 8 | io.usethesource.vallang.type.ListType$Info 9 | io.usethesource.vallang.type.MapType$Info 10 | io.usethesource.vallang.type.NodeType$Info 11 | io.usethesource.vallang.type.NumberType$Info 12 | io.usethesource.vallang.type.ParameterType$Info 13 | io.usethesource.vallang.type.RationalType$Info 14 | io.usethesource.vallang.type.RealType$Info 15 | io.usethesource.vallang.type.SetType$Info 16 | io.usethesource.vallang.type.SourceLocationType$Info 17 | io.usethesource.vallang.type.StringType$Info 18 | io.usethesource.vallang.type.TupleType$Info 19 | io.usethesource.vallang.type.FunctionType$Reifier 20 | io.usethesource.vallang.type.VoidType$Info 21 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/RedeclaredConstructorException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | import io.usethesource.vallang.type.Type; 4 | 5 | public class RedeclaredConstructorException extends 6 | FactTypeDeclarationException { 7 | private static final long serialVersionUID = 8330548728032865311L; 8 | private String name; 9 | private Type firstArgs; 10 | private Type secondArgs; 11 | 12 | public RedeclaredConstructorException(String name, Type firstArgs, Type secondArgs) { 13 | super("Constructor " + name + " overloaded with comparable argument types: " + firstArgs + " and " + secondArgs); 14 | this.name = name; 15 | this.firstArgs = firstArgs; 16 | this.secondArgs = secondArgs; 17 | } 18 | 19 | public String getName() { 20 | return name; 21 | } 22 | 23 | public Type getFirstArgs() { 24 | return firstArgs; 25 | } 26 | 27 | public Type getSecondArgs() { 28 | return secondArgs; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/FactTypeUseException.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2007 IBM Corporation. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation 10 | 11 | *******************************************************************************/ 12 | 13 | package io.usethesource.vallang.exceptions; 14 | 15 | public abstract class FactTypeUseException extends RuntimeException { 16 | private static final long serialVersionUID= 2135696551442574010L; 17 | 18 | public FactTypeUseException(String message) { 19 | super(message); 20 | } 21 | 22 | public FactTypeUseException(String reason, Throwable cause) { 23 | super(reason, cause); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/impl/primitive/ICanBecomeABigInteger.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2009-2013 CWI 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * 10 | * * Arnold Lankamp - interfaces and implementation 11 | *******************************************************************************/ 12 | package io.usethesource.vallang.impl.primitive; 13 | 14 | import java.math.BigInteger; 15 | 16 | /** 17 | * Strangely named class, which defines that the implementor can convert something to a big integer. 18 | * 19 | * @author Arnold Lankamp 20 | */ 21 | public interface ICanBecomeABigInteger{ 22 | 23 | /** 24 | * Returns the big integer. 25 | * 26 | * @return The big integer. 27 | */ 28 | BigInteger toBigInteger(); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/FactTypeDeclarationException.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2007 IBM Corporation. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation 10 | 11 | *******************************************************************************/ 12 | 13 | package io.usethesource.vallang.exceptions; 14 | 15 | public abstract class FactTypeDeclarationException extends RuntimeException { 16 | private static final long serialVersionUID = -2991169068626385361L; 17 | 18 | public FactTypeDeclarationException(String message) { 19 | super(message); 20 | } 21 | 22 | public FactTypeDeclarationException(String message, Throwable cause) { 23 | super(message, cause); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/exceptions/RedeclaredFieldNameException.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.exceptions; 2 | 3 | import io.usethesource.vallang.type.Type; 4 | 5 | public class RedeclaredFieldNameException extends 6 | FactTypeDeclarationException { 7 | private static final long serialVersionUID = -4401062690006714904L; 8 | private String label; 9 | private Type one; 10 | private Type two; 11 | private Type tupleType; 12 | 13 | public RedeclaredFieldNameException(String label, Type one, Type two, Type tupleType) { 14 | super("The field name " + label + " is illegally used for both " + one + " and " + two + " in type " + tupleType); 15 | this.label = label; 16 | this.one = one; 17 | this.two = two; 18 | this.tupleType = tupleType; 19 | } 20 | 21 | public String getFieldName() { 22 | return label; 23 | } 24 | 25 | public Type getFirstType() { 26 | return one; 27 | } 28 | 29 | public Type getSecondType() { 30 | return two; 31 | } 32 | 33 | public Type getTupleType() { 34 | return tupleType; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /.github/workflows/publish-test-results.yaml: -------------------------------------------------------------------------------- 1 | name: Publish Test Results 2 | # this separate workflow makes sure we can report test results, even for external PRs 3 | 4 | on: 5 | workflow_run: 6 | workflows: ["Build and Deploy"] 7 | types: 8 | - completed 9 | permissions: {} 10 | 11 | jobs: 12 | test-results: 13 | name: Test Results 14 | runs-on: ubuntu-latest 15 | if: github.event.workflow_run.conclusion != 'skipped' 16 | 17 | permissions: 18 | checks: write 19 | pull-requests: write 20 | actions: read 21 | 22 | steps: 23 | - name: Download and Extract Artifacts 24 | uses: dawidd6/action-download-artifact@v11 25 | with: 26 | run_id: ${{ github.event.workflow_run.id }} 27 | path: artifacts 28 | 29 | - name: Publish Test Results 30 | uses: EnricoMi/publish-unit-test-result-action@v2 31 | with: 32 | commit: ${{ github.event.workflow_run.head_sha }} 33 | event_file: artifacts/Event File/event.json 34 | event_name: ${{ github.event.workflow_run.event }} 35 | files: "artifacts/**/TEST*.xml" -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/util/DirectByteBufferCache.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.io.binary.util; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.util.concurrent.TimeUnit; 5 | 6 | public class DirectByteBufferCache { 7 | 8 | private static class InstanceHolder { 9 | static final DirectByteBufferCache sInstance = new DirectByteBufferCache(); 10 | } 11 | 12 | public static DirectByteBufferCache getInstance() { 13 | return InstanceHolder.sInstance; 14 | } 15 | 16 | private DirectByteBufferCache() { } 17 | 18 | 19 | private final CacheFactory buffers = new CacheFactory<>(3, TimeUnit.SECONDS, DirectByteBufferCache::clear); 20 | 21 | 22 | private static ByteBuffer clear(ByteBuffer b) { 23 | b.clear(); 24 | return b; 25 | } 26 | 27 | private static int roundSize(int size) { 28 | return (int)(Math.ceil(size / (8*1024.0)) * (8*1024)); 29 | } 30 | 31 | public ByteBuffer get(int size) { 32 | return getExact(roundSize(size)); 33 | } 34 | 35 | public void put(ByteBuffer returned) { 36 | if (returned.capacity() > (8*1024)) { 37 | buffers.put(returned.capacity(), returned); 38 | } 39 | } 40 | 41 | public ByteBuffer getExact(int size) { 42 | return buffers.get(size, ByteBuffer::allocateDirect); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/basic/StreamCollectorTest.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.basic; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.junit.jupiter.params.ParameterizedTest; 6 | import org.junit.jupiter.params.provider.ArgumentsSource; 7 | 8 | import io.usethesource.vallang.ExpectedType; 9 | import io.usethesource.vallang.IList; 10 | import io.usethesource.vallang.IMap; 11 | import io.usethesource.vallang.ISet; 12 | import io.usethesource.vallang.IValueFactory; 13 | import io.usethesource.vallang.ValueProvider; 14 | 15 | public class StreamCollectorTest { 16 | 17 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 18 | public void listCollector(IValueFactory vf, @ExpectedType("list[int]") IList elems) { 19 | IList l = elems.stream().collect(vf.listWriter()); 20 | assertEquals(l, elems); 21 | } 22 | 23 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 24 | public void setCollector(IValueFactory vf, @ExpectedType("set[int]") ISet elems) { 25 | ISet l = elems.stream().collect(vf.setWriter()); 26 | assertEquals(l, elems); 27 | } 28 | 29 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 30 | public void mapCollector(IValueFactory vf, @ExpectedType("map[int,int]") IMap elems) { 31 | IMap l = elems.stream().collect(vf.mapWriter()); 32 | assertEquals(l, elems); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/IBool.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2009 CWI 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * Jurgen Vinju (jurgen@vinju.org) - initial API and implementation 10 | *******************************************************************************/ 11 | package io.usethesource.vallang; 12 | 13 | import io.usethesource.vallang.visitors.IValueVisitor; 14 | 15 | public interface IBool extends IValue { 16 | @Override 17 | default int getMatchFingerprint() { 18 | if (getValue()) { 19 | return 3569038; /* "true".hashCode() */ 20 | } 21 | else { 22 | return 97196323; /* "false".hashCode() */ 23 | } 24 | } 25 | 26 | boolean getValue(); 27 | String getStringRepresentation(); 28 | IBool and(IBool other); 29 | IBool or(IBool other); 30 | IBool xor(IBool other); 31 | IBool not(); 32 | IBool implies(IBool other); 33 | IBool equivalent(IBool other); 34 | 35 | @Override 36 | default T accept(IValueVisitor v) throws E { 37 | return v.visitBoolean(this); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/specification/ListTests.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.specification; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.junit.jupiter.params.ParameterizedTest; 6 | import org.junit.jupiter.params.provider.ArgumentsSource; 7 | 8 | import io.usethesource.vallang.ExpectedType; 9 | import io.usethesource.vallang.GivenValue; 10 | import io.usethesource.vallang.IList; 11 | import io.usethesource.vallang.IValue; 12 | import io.usethesource.vallang.ValueProvider; 13 | 14 | public class ListTests { 15 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 16 | public void intersectionOrder( 17 | @GivenValue("[1,2,3,4,5]") IList l1, 18 | @GivenValue("[5,3,1]") IList l2, 19 | @GivenValue("[1,3,5]") IList result 20 | ) { 21 | assertEquals(l1.intersect(l2), result); 22 | } 23 | 24 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 25 | public void concatLength(@ExpectedType("list[num]") IList l1, @ExpectedType("list[num]") IList l2) { 26 | assertEquals(l1.concat(l2).length(), l1.length() + l2.length()); 27 | } 28 | 29 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 30 | public void iterationOrder(@ExpectedType("list[num]") IList l1) { 31 | int i = 0; 32 | for (IValue elem : l1) { 33 | assertEquals(elem, l1.get(i++)); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/IValueBinaryWriter.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) CWI 2008 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * Jurgen Vinju (jurgenv@cwi.nl) - initial API and implementation 10 | 11 | *******************************************************************************/ 12 | 13 | package io.usethesource.vallang.io; 14 | 15 | import java.io.IOException; 16 | import java.io.OutputStream; 17 | 18 | import io.usethesource.vallang.IValue; 19 | import io.usethesource.vallang.type.TypeStore; 20 | 21 | /** 22 | * An instance of IValueWriter can serialize all types of IValues. 23 | * There should be a corresponding IValueReader to de-serialize them 24 | * back to IValues. 25 | * 26 | * @author jurgenv 27 | * 28 | */ 29 | public interface IValueBinaryWriter { 30 | void write(IValue value, OutputStream stream) throws IOException; 31 | void write(IValue value, OutputStream stream, boolean compression) throws IOException; 32 | void write(IValue value, OutputStream stream, TypeStore typeStore) throws IOException; 33 | void write(IValue value, OutputStream stream, boolean compression, TypeStore typeStore) throws IOException; 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/basic/BooleanStoreProvider.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.basic; 2 | 3 | import io.usethesource.vallang.type.Type; 4 | import io.usethesource.vallang.type.TypeFactory; 5 | import io.usethesource.vallang.type.TypeStore; 6 | 7 | public class BooleanStoreProvider { 8 | 9 | public static TypeStore store = new TypeStore(); 10 | private static TypeFactory tf = TypeFactory.getInstance(); 11 | protected static Type Boolean = tf.abstractDataType(store, "Boolean"); 12 | 13 | protected static Type Name = tf.abstractDataType(store, "Name"); 14 | protected static Type True = tf.constructor(store, Boolean, "true"); 15 | 16 | protected static Type False = tf.constructor(store, Boolean, "false"); 17 | protected static Type And = tf.constructor(store, Boolean, "and", Boolean, Boolean); 18 | protected static Type Or = tf.constructor(store, Boolean, "or", tf.listType(Boolean)); 19 | protected static Type Not = tf.constructor(store, Boolean, "not", Boolean); 20 | protected static Type TwoTups = tf.constructor(store, Boolean, "twotups", 21 | tf.tupleType(Boolean, Boolean), tf.tupleType(Boolean, Boolean)); 22 | protected static Type NameNode = tf.constructor(store, Name, "name", tf.stringType()); 23 | protected static Type Friends = tf.constructor(store, Boolean, "friends", tf.listType(Name)); 24 | protected static Type Couples = tf.constructor(store, Boolean, "couples", tf.lrelType(Name, Name)); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/util/ClearableWindow.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, Davy Landman, Centrum Wiskunde & Informatica (CWI) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | * 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | */ 13 | package io.usethesource.vallang.io.binary.util; 14 | 15 | public interface ClearableWindow { 16 | int size(); 17 | void clear(); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/type/ITypeVisitor.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2008 CWI. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * jurgen@vinju.org 10 | 11 | *******************************************************************************/ 12 | package io.usethesource.vallang.type; 13 | 14 | /** 15 | * Visitor interface for all kinds of Types 16 | * 17 | * @param the result type of the visit methods 18 | */ 19 | public interface ITypeVisitor { 20 | T visitReal(Type type) throws E; 21 | T visitInteger(Type type) throws E; 22 | T visitRational(Type type) throws E; 23 | T visitList(Type type) throws E; 24 | T visitMap(Type type) throws E; 25 | T visitNumber(Type type) throws E; 26 | T visitAlias(Type type) throws E; 27 | T visitSet(Type type) throws E; 28 | T visitSourceLocation(Type type) throws E; 29 | T visitString(Type type) throws E; 30 | T visitNode(Type type) throws E; 31 | T visitConstructor(Type type) throws E; 32 | T visitAbstractData(Type type) throws E; 33 | T visitTuple(Type type) throws E; 34 | T visitValue(Type type) throws E; 35 | T visitVoid(Type type) throws E; 36 | T visitBool(Type type) throws E; 37 | T visitParameter(Type type) throws E; 38 | T visitExternal(Type type) throws E; 39 | T visitDateTime(Type type) throws E; 40 | T visitFunction(Type type) throws E; 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/IValueTextWriter.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) CWI 2008 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * Jurgen Vinju (jurgenv@cwi.nl) - initial API and implementation 10 | 11 | *******************************************************************************/ 12 | 13 | package io.usethesource.vallang.io; 14 | 15 | import java.io.IOException; 16 | import java.io.Writer; 17 | 18 | import io.usethesource.vallang.IValue; 19 | import io.usethesource.vallang.type.TypeStore; 20 | 21 | /** 22 | * An instance of IValueTextWriter can serialize all types of IValues as characters 23 | * There should be a corresponding IValueReader to de-serialize them again 24 | * back to IValues. 25 | */ 26 | public interface IValueTextWriter { 27 | /** 28 | * Serialize a value using the given writer 29 | * @param value the value to serialize 30 | * @param writer the writer to output character to 31 | * @throws IOException in case the writer does 32 | */ 33 | void write(IValue value, Writer writer) throws IOException; 34 | 35 | /** 36 | * Serialize a value using the given writer 37 | * @param value the value to serialize 38 | * @param writer the writer to output character to 39 | * @throws IOException in case the writer does 40 | */ 41 | void write(IValue value, Writer writer, TypeStore typeStore) throws IOException; 42 | } 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This whole project is released under the BSD-2 simplified clause, with the noted exception that a number of older files still have an Eclipse license. 2 | 3 | ----BSD license---- 4 | Copyright (c) 2018, Jurgen J. Vinju, Centrum Wiskunde & Informatica (CWI) 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | 15 | ----Eclipse v1 license---- 16 | 17 | Copyright (c) 2012-2013 CWI 18 | All rights reserved. This program and the accompanying materials 19 | are made available under the terms of the Eclipse Public License v1.0 20 | which accompanies this distribution, and is available at 21 | http://www.eclipse.org/legal/epl-v10.html 22 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/io/LinearCircularLookupWindowTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, Davy Landman, Centrum Wiskunde & Informatica (CWI) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | * 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | */ 13 | package io.usethesource.vallang.io; 14 | 15 | import io.usethesource.vallang.io.binary.util.LinearCircularLookupWindow; 16 | import io.usethesource.vallang.io.binary.util.TrackLastRead; 17 | 18 | public class LinearCircularLookupWindowTest extends TrackReadsTestBase { 19 | 20 | @Override 21 | public TrackLastRead getLastReadWindow(int size) { 22 | return new LinearCircularLookupWindow<>(size); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/stream/Header.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, Davy Landman, Centrum Wiskunde & Informatica (CWI) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | * 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | */ 13 | package io.usethesource.vallang.io.binary.stream; 14 | 15 | /*package*/ final class Header { 16 | public static final byte[] MAIN = { 'R', 'V', 1,0,0 }; 17 | public static final class Compression { 18 | public static final byte NONE = 0; 19 | public static final byte GZIP = 1; 20 | /** Never officially available, but still reserved */ 21 | public static final byte UNSUPPORTED_XZ = 2; 22 | public static final byte ZSTD = 3; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/util/ByteBufferInputStream.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.io.binary.util; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.nio.ByteBuffer; 6 | 7 | public class ByteBufferInputStream extends InputStream { 8 | 9 | protected ByteBuffer source; 10 | 11 | public ByteBuffer getByteBuffer() { 12 | return source; 13 | } 14 | 15 | public ByteBufferInputStream(ByteBuffer source) { 16 | this.source = source; 17 | } 18 | 19 | protected ByteBuffer refill(ByteBuffer torefill) throws IOException { 20 | return torefill; 21 | } 22 | 23 | @Override 24 | public int read(byte[] b, int off, int len) throws IOException { 25 | if (len <= source.remaining()) { 26 | source.get(b, off, len); 27 | return len; 28 | } 29 | // else first get what is left 30 | int read = 0; 31 | while (read < len) { 32 | int chunk = Math.min(source.remaining(), len - read); 33 | source.get(b, off + read, chunk); 34 | read += chunk; 35 | if (read < len && !source.hasRemaining()) { 36 | source = refill(source); 37 | if (!source.hasRemaining()) { 38 | if (read == 0) { 39 | return -1; 40 | } 41 | return read; 42 | } 43 | } 44 | } 45 | return len; 46 | } 47 | @Override 48 | public int read(byte[] b) throws IOException { 49 | return read(b, 0, b.length); 50 | } 51 | 52 | @Override 53 | public int read() throws IOException { 54 | if (!source.hasRemaining()) { 55 | source = refill(source); 56 | if (!source.hasRemaining()) { 57 | return -1; 58 | } 59 | } 60 | return Byte.toUnsignedInt(source.get()); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "main" ] 17 | pull_request: 18 | branches: [ "main" ] 19 | schedule: 20 | - cron: '28 10 * * 4' 21 | 22 | jobs: 23 | analyze: 24 | name: Analyze 25 | if: ${{ !(github.ref == 'refs/heads/main' && contains(github.event.head_commit.message, '[maven-release-plugin]')) }} 26 | 27 | runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} 28 | timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} 29 | permissions: 30 | actions: read 31 | contents: read 32 | security-events: write 33 | 34 | strategy: 35 | fail-fast: false 36 | matrix: 37 | language: [ 'java-kotlin' ] 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v5 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v4 46 | with: 47 | languages: ${{ matrix.language }} 48 | 49 | - name: Set up JDK 50 | uses: actions/setup-java@v5 51 | with: 52 | java-version: 17 53 | distribution: 'temurin' 54 | cache: 'maven' 55 | 56 | - name: Build 57 | run: mvn -B clean package -DskipTests 58 | 59 | - name: Perform CodeQL Analysis 60 | uses: github/codeql-action/analyze@v4 61 | with: 62 | category: "/language:${{matrix.language}}" 63 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/io/TrackReadsTestBase.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.io; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertSame; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | import io.usethesource.vallang.io.binary.util.TrackLastRead; 8 | 9 | 10 | public abstract class TrackReadsTestBase { 11 | public abstract TrackLastRead getLastReadWindow(int size); 12 | 13 | @Test 14 | public void getMostRecent() { 15 | Object a = new Object(); 16 | TrackLastRead w = getLastReadWindow(5); 17 | w.read(a); 18 | assertSame(a, w.lookBack(0)); 19 | } 20 | 21 | @Test 22 | public void getPrevious() { 23 | Object a = new Object(); 24 | Object b = new Object(); 25 | TrackLastRead w = getLastReadWindow(5); 26 | w.read(a); 27 | w.read(b); 28 | assertSame(a, w.lookBack(1)); 29 | } 30 | @Test 31 | public void getPreviousAfterCircleing() { 32 | Object a = new Object(); 33 | Object b = new Object(); 34 | Object c = new Object(); 35 | Object d = new Object(); 36 | TrackLastRead w = getLastReadWindow(5); 37 | w.read(a); 38 | w.read(b); 39 | w.read(c); 40 | w.read(d); 41 | assertSame(c, w.lookBack(1)); 42 | } 43 | 44 | @Test 45 | public void testLargeReads() { 46 | Object[] elements = new Object[10000];; 47 | for (int i = 0; i < elements.length; i++) { 48 | elements[i] = new Object(); 49 | } 50 | final int windowSize = elements.length / 2; 51 | TrackLastRead r = getLastReadWindow(windowSize); 52 | for (int i = 0; i < elements.length; i++) { 53 | r.read(elements[i]); 54 | for (int j = 0 ; j <= Math.min(i, windowSize); j++) { 55 | assertSame(r.lookBack(j), elements[i - j], "For " + j + "back after " + i + "reads"); 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/impl/persistent/ListRelation.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.impl.persistent; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | import io.usethesource.vallang.IList; 7 | import io.usethesource.vallang.IRelation; 8 | import io.usethesource.vallang.IValue; 9 | import io.usethesource.vallang.IWriter; 10 | 11 | public class ListRelation implements IRelation { 12 | private final IList list; 13 | 14 | public ListRelation(IList list) { 15 | this.list = list; 16 | } 17 | 18 | @Override 19 | public IList asContainer() { 20 | return list; 21 | } 22 | 23 | @Override 24 | public IList closure() { 25 | // will throw exception if not binary and reflexive 26 | list.getType().closure(); 27 | 28 | IRelation tmp = this; 29 | 30 | int prevCount = 0; 31 | 32 | Set addedTuples = new HashSet<>(); 33 | while (prevCount != tmp.asContainer().length()) { 34 | prevCount = tmp.asContainer().length(); 35 | IList tcomp = tmp.compose(tmp); 36 | IWriter w = writer(); 37 | for (IValue t1 : tcomp) { 38 | IValue w1 = t1; 39 | if (!tmp.asContainer().contains(t1) && !addedTuples.contains(w1)) { 40 | addedTuples.add(w1); 41 | w.append(t1); 42 | } 43 | } 44 | 45 | tmp = tmp.asContainer().concat(w.done()).asRelation(); 46 | addedTuples.clear(); 47 | } 48 | 49 | return tmp.asContainer(); 50 | } 51 | 52 | @Override 53 | public IList closureStar() { 54 | list.getType().closure(); 55 | // an exception will have been thrown if the type is not acceptable 56 | 57 | IWriter reflex = writer(); 58 | 59 | for (IValue e : carrier()) { 60 | reflex.insertTuple(e, e); 61 | } 62 | 63 | return closure().concat(reflex.done()); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/util/DirectZstdInputStream.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.io.binary.util; 2 | 3 | import java.io.Closeable; 4 | import java.io.IOException; 5 | import java.nio.ByteBuffer; 6 | 7 | import com.github.luben.zstd.ZstdDirectBufferDecompressingStream; 8 | 9 | public class DirectZstdInputStream extends ByteBufferInputStream { 10 | 11 | private final ByteBufferInputStream orginalStream; 12 | private ZstdDirectBufferDecompressingStream decompressor; 13 | private boolean closed = false; 14 | 15 | public DirectZstdInputStream(ByteBufferInputStream originalStream) { 16 | super(constructDecompressedBuffer(originalStream)); 17 | this.orginalStream = originalStream; 18 | decompressor = new ZstdDirectBufferDecompressingStream(originalStream.getByteBuffer()); 19 | } 20 | 21 | @Override 22 | protected ByteBuffer refill(ByteBuffer torefill) throws IOException { 23 | torefill.clear(); 24 | decompressor.read(torefill); 25 | torefill.flip(); 26 | return torefill; 27 | } 28 | 29 | private static ByteBuffer constructDecompressedBuffer(ByteBufferInputStream oriStream) { 30 | int compressedSize = oriStream.getByteBuffer().remaining(); 31 | int bufferSize = ZstdDirectBufferDecompressingStream.recommendedTargetBufferSize(); 32 | if (bufferSize > compressedSize) { 33 | bufferSize = Math.min(compressedSize * 2, bufferSize); 34 | } 35 | ByteBuffer result = DirectByteBufferCache.getInstance().get(bufferSize); 36 | result.limit(0); // delay compression for first read 37 | return result; 38 | } 39 | 40 | @Override 41 | public void close() throws IOException { 42 | if (!closed ) { 43 | closed = true; 44 | try (Closeable old = orginalStream) { 45 | super.close(); 46 | decompressor.close(); 47 | } 48 | finally { 49 | DirectByteBufferCache.getInstance().put(super.source); 50 | } 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/util/HashConsingMap.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Davy Landman, SWAT.engineering 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | * 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | */ 13 | package io.usethesource.vallang.util; 14 | 15 | /** 16 | * Basic interface to Hash-consing implementations. Hash-consing makes sure there is maximal sharing for every value that is equal. 17 | * @author Davy Landman 18 | */ 19 | public interface HashConsingMap { 20 | /** 21 | * Lookup the hash-consed value for this key (using the hash-code-equals contract for equality). 22 | * 23 | * The containers will take care of multi-threading concerns. 24 | * @param key key to lookup, will either be inserted and returned, or an older reference that is {@link #equals()} to this instance. 25 | * @return a non-null reference to something that is equal to key 26 | */ 27 | T get(T key); 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/visitors/IValueVisitor.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2008 CWI. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * jurgen@vinju.org 10 | *******************************************************************************/ 11 | 12 | package io.usethesource.vallang.visitors; 13 | 14 | import org.checkerframework.checker.nullness.qual.Nullable; 15 | 16 | import io.usethesource.vallang.IBool; 17 | import io.usethesource.vallang.IConstructor; 18 | import io.usethesource.vallang.IDateTime; 19 | import io.usethesource.vallang.IExternalValue; 20 | import io.usethesource.vallang.IInteger; 21 | import io.usethesource.vallang.IList; 22 | import io.usethesource.vallang.IMap; 23 | import io.usethesource.vallang.INode; 24 | import io.usethesource.vallang.IRational; 25 | import io.usethesource.vallang.IReal; 26 | import io.usethesource.vallang.ISet; 27 | import io.usethesource.vallang.ISourceLocation; 28 | import io.usethesource.vallang.IString; 29 | import io.usethesource.vallang.ITuple; 30 | 31 | public interface IValueVisitor { 32 | public R visitString(IString o) throws E; 33 | public R visitReal(IReal o) throws E; 34 | public R visitRational(IRational o) throws E; 35 | public R visitList(IList o) throws E; 36 | public R visitSet(ISet o) throws E; 37 | public R visitSourceLocation(ISourceLocation o) throws E; 38 | public R visitTuple(ITuple o) throws E; 39 | public R visitNode(INode o) throws E; 40 | public R visitConstructor(IConstructor o) throws E; 41 | public R visitInteger(IInteger o) throws E; 42 | public R visitMap(IMap o) throws E; 43 | public R visitBoolean(IBool boolValue) throws E; 44 | public R visitExternal(IExternalValue externalValue) throws E; 45 | public R visitDateTime(IDateTime o) throws E; 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/IMapWriter.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2008 CWI. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation 10 | 11 | *******************************************************************************/ 12 | 13 | package io.usethesource.vallang; 14 | 15 | import java.util.Map; 16 | import java.util.function.BiConsumer; 17 | 18 | import org.checkerframework.checker.nullness.qual.Nullable; 19 | 20 | import io.usethesource.vallang.exceptions.FactTypeUseException; 21 | 22 | 23 | public interface IMapWriter extends IWriter { 24 | /** 25 | * Put a value with a certain key into the map 26 | * @param key 27 | * @param value 28 | * @throws FactTypeUseException 29 | */ 30 | void put(IValue key, IValue value); 31 | 32 | /** 33 | * Merge an entire map into the writer. Existing keys 34 | * will be overwritten by the new map 35 | * @param map 36 | * @throws FactTypeUseException 37 | */ 38 | void putAll(IMap map); 39 | 40 | /** 41 | * Merge an entire java.util.Map into the writer. Existing 42 | * keys will be overwritten by the new map. 43 | * @param map 44 | * @throws FactTypeUseException 45 | */ 46 | void putAll(Map map); 47 | 48 | /** 49 | * Lookup a given key into the state of the current map-to-be 50 | * @param key 51 | * @return null if no value exists with this key, otherwise the respective value. 52 | */ 53 | @Nullable IValue get(IValue key); 54 | 55 | /** 56 | * The map writer collects key/value tuples 57 | */ 58 | @Override 59 | default BiConsumer, IValue> accumulator() { 60 | return (writer, elem) -> ((IMapWriter) writer).put(((ITuple) elem).get(0), ((ITuple) elem).get(1)); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/basic/RegressionTest.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.basic; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertTrue; 4 | 5 | import java.io.IOException; 6 | import java.util.Collections; 7 | 8 | import org.junit.jupiter.params.ParameterizedTest; 9 | import org.junit.jupiter.params.provider.ArgumentsSource; 10 | 11 | import io.usethesource.vallang.GivenValue; 12 | import io.usethesource.vallang.IConstructor; 13 | import io.usethesource.vallang.IValue; 14 | import io.usethesource.vallang.IValueFactory; 15 | import io.usethesource.vallang.ValueProvider; 16 | import io.usethesource.vallang.type.Type; 17 | import io.usethesource.vallang.type.TypeFactory; 18 | import io.usethesource.vallang.type.TypeStore; 19 | 20 | public class RegressionTest { 21 | 22 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 23 | public void testConstructorEquality(IValueFactory vf, TypeFactory tf) throws Exception { 24 | final TypeStore ts = new TypeStore(); 25 | final Type adtType = tf.abstractDataType(ts, "n"); 26 | final Type c0Type = tf.constructor (ts, adtType, "c"); 27 | final Type c1Type = tf.constructor (ts, adtType, "c1", tf.integerType()); 28 | 29 | final IConstructor c0Normal = vf.constructor(c0Type); final IConstructor c0WithKWParams = vf.constructor(c0Type).asWithKeywordParameters().setParameters(Collections.emptyMap()); 30 | 31 | final IConstructor c1Normal = vf.constructor(c1Type, vf.integer(1)); 32 | final IConstructor c1WithKWParams = vf.constructor(c1Type, vf.integer(1)).asWithKeywordParameters().setParameters(Collections.emptyMap()); 33 | 34 | assertTrue(c0WithKWParams.equals(c0Normal)); 35 | assertTrue(c0Normal.equals(c0WithKWParams)); 36 | assertTrue(c1WithKWParams.equals(c1Normal)); 37 | assertTrue(c1Normal.equals(c1WithKWParams)); 38 | } 39 | 40 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 41 | public void testRegression42_cause(IValueFactory vf, TypeStore store, @GivenValue("(\"\"():4,\"\"():3)") IValue v, @GivenValue("(\"\"():4,\"\"():3)") IValue u) throws IOException { 42 | assertTrue(v.equals(u)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/util/TrackLastRead.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, Davy Landman, Centrum Wiskunde & Informatica (CWI) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | * 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | */ 13 | package io.usethesource.vallang.io.binary.util; 14 | 15 | import org.checkerframework.checker.nullness.qual.NonNull; 16 | 17 | /** 18 | * 19 | * The inverse of the {@link TrackLastWritten}, keeping track of when an object was read. 20 | * Most commonly with a window size (that should be at least as large as during writing). 21 | * @author Davy Landman 22 | * @param 23 | */ 24 | public interface TrackLastRead { 25 | /** 26 | * Register a new object that was read. 27 | */ 28 | void read(T obj); 29 | /** 30 | * Get an object that was previously read 31 | * @param howLongBack how many objects back, 0 means the most recently read. larger than window size causes exceptions 32 | */ 33 | T lookBack(int howLongBack); 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/basic/XMLSmokeTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2007 IBM Corporation. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * Jurgen Vinju 10 | 11 | *******************************************************************************/ 12 | 13 | package io.usethesource.vallang.basic; 14 | 15 | import static org.junit.jupiter.api.Assertions.assertEquals; 16 | 17 | import java.io.IOException; 18 | import java.io.StringReader; 19 | import java.io.StringWriter; 20 | 21 | import org.junit.jupiter.api.Disabled; 22 | import org.junit.jupiter.params.ParameterizedTest; 23 | import org.junit.jupiter.params.provider.ArgumentsSource; 24 | 25 | import io.usethesource.vallang.ExpectedType; 26 | import io.usethesource.vallang.IConstructor; 27 | import io.usethesource.vallang.IValue; 28 | import io.usethesource.vallang.IValueFactory; 29 | import io.usethesource.vallang.ValueProvider; 30 | import io.usethesource.vallang.exceptions.UnsupportedTypeException; 31 | import io.usethesource.vallang.io.XMLReader; 32 | import io.usethesource.vallang.io.XMLWriter; 33 | import io.usethesource.vallang.type.TypeStore; 34 | 35 | public class XMLSmokeTest extends BooleanStoreProvider { 36 | 37 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 38 | @Disabled("XML writer fails on empty strings and empty lists") 39 | public void testXMLWriter(IValueFactory vf, TypeStore ts, @ExpectedType("Boolean") IConstructor val) throws IOException { 40 | StringWriter buffer = new StringWriter(); 41 | XMLWriter testWriter = new XMLWriter(); 42 | XMLReader testReader = new XMLReader(); 43 | 44 | try { 45 | testWriter.write(val, buffer); 46 | IValue result = testReader.read(vf, ts, val.getType(), new StringReader(buffer.toString())); 47 | assertEquals(val, result); 48 | } 49 | catch (UnsupportedTypeException e) { 50 | // this happens because the XML support does not offer serialization of all types 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/util/SecondsTicker.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2020, Davy Landman, swat.engineering 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | * 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | */ 13 | package io.usethesource.vallang.util; 14 | 15 | import java.util.concurrent.CompletableFuture; 16 | import java.util.concurrent.TimeUnit; 17 | 18 | /** 19 | * A monotonic ticker that fast to frequently access and is updated roughly once every second
20 | *
21 | * For more reasons why we want a fast time field, see this discussion. 22 | */ 23 | public class SecondsTicker { 24 | 25 | private static volatile int tick = 0; 26 | 27 | private static void doTick() { 28 | CompletableFuture 29 | .delayedExecutor(1, TimeUnit.SECONDS) 30 | .execute(SecondsTicker::doTick); 31 | tick++; 32 | } 33 | 34 | static { 35 | // start the ticker 36 | doTick(); 37 | } 38 | 39 | /** 40 | * Get a monotonic increasing integer that increments roughly every second 41 | */ 42 | public static int current() { 43 | return tick; 44 | } 45 | 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/util/TaggedInt.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, Davy Landman, Centrum Wiskunde & Informatica (CWI) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | * 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | */ 13 | package io.usethesource.vallang.io.binary.util; 14 | 15 | /** 16 | * Use the 3 lowest bits of an integer to store a tag. 17 | * @author Davy Landman 18 | */ 19 | public class TaggedInt { 20 | private TaggedInt() {} 21 | 22 | private static final int TAG_BITS = 3; 23 | private static final int TAG_MASK = 0b111; 24 | public static final int MAX_ORIGINAL_VALUE = 0xFFFFFFFF >>> TAG_BITS; 25 | static { 26 | assert (1 << (TAG_BITS - 1)) == Integer.highestOneBit(TAG_MASK); 27 | assert getOriginal(make(MAX_ORIGINAL_VALUE, 3)) == MAX_ORIGINAL_VALUE; 28 | } 29 | 30 | public static int make(final int original, final int tag) { 31 | assert (tag & TAG_MASK) == tag && original <= MAX_ORIGINAL_VALUE; 32 | return (original << TAG_BITS) | tag; 33 | } 34 | 35 | public static int getOriginal(final int i) { 36 | return i >>> TAG_BITS; 37 | } 38 | 39 | public static int getTag(final int i) { 40 | return i & TAG_MASK; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/impl/reference/List.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2013 CWI 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * 10 | * * Michael Steindorfer - Michael.Steindorfer@cwi.nl - CWI 11 | *******************************************************************************/ 12 | package io.usethesource.vallang.impl.reference; 13 | 14 | import java.util.Iterator; 15 | 16 | import org.checkerframework.checker.nullness.qual.Nullable; 17 | 18 | import io.usethesource.vallang.IList; 19 | import io.usethesource.vallang.IListWriter; 20 | import io.usethesource.vallang.IValue; 21 | import io.usethesource.vallang.type.Type; 22 | 23 | /*package*/ class List implements IList { 24 | private final Type type; 25 | private final java.util.List content; 26 | 27 | /*package*/ List(Type elementType, java.util.List content) { 28 | super(); 29 | this.type = TF.listType(elementType); 30 | this.content = content; 31 | } 32 | 33 | @Override 34 | public Type getType() { 35 | return type; 36 | } 37 | 38 | @Override 39 | public Iterator iterator() { 40 | return content.iterator(); 41 | } 42 | 43 | @Override 44 | public int length() { 45 | return content.size(); 46 | } 47 | 48 | @Override 49 | public IValue get(int i) { 50 | return content.get(i); 51 | } 52 | 53 | @Override 54 | public boolean isEmpty() { 55 | return content.isEmpty(); 56 | } 57 | 58 | @Override 59 | public int hashCode() { 60 | return content.hashCode(); 61 | } 62 | 63 | @Override 64 | public boolean equals(@Nullable Object that) { 65 | if (that == null) { 66 | return false; 67 | } 68 | 69 | return defaultEquals(that); 70 | } 71 | 72 | @Override 73 | public String toString() { 74 | return defaultToString(); 75 | } 76 | 77 | @Override 78 | public IListWriter writer() { 79 | return new ListWriter(); 80 | } 81 | 82 | @Override 83 | public int size() { 84 | return content.size(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/util/TrackLastWritten.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, Davy Landman, Centrum Wiskunde & Informatica (CWI) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | * 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | */ 13 | package io.usethesource.vallang.io.binary.util; 14 | 15 | import org.checkerframework.checker.nullness.qual.NonNull; 16 | 17 | /** 18 | * A lookback window in how long ago a certain object was written. 19 | * Commonly there is a window size, so only the last X are tracked. 20 | * @author Davy Landman 21 | * 22 | * @param 23 | */ 24 | public interface TrackLastWritten { 25 | /** 26 | * Register that an object has just been written. 27 | * It is very important that this object is not in the window anymore (eg howLongAgo(obj) == -1) 28 | * @param obj the new object to track. 29 | */ 30 | void write(T obj); 31 | 32 | /** 33 | * How long ago an object was written. 34 | * @param obj which object 35 | * @return how many objects ago it was written. 0 means is was the last, 1 means it was the second to last. -1 means that it isn't written yet, or longer than the windows size ago. 36 | */ 37 | int howLongAgo(T obj); 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/specification/SetTests.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.specification; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import java.util.Random; 7 | import org.junit.jupiter.params.ParameterizedTest; 8 | import org.junit.jupiter.params.provider.ArgumentsSource; 9 | 10 | import io.usethesource.vallang.ExpectedType; 11 | import io.usethesource.vallang.IInteger; 12 | import io.usethesource.vallang.ISet; 13 | import io.usethesource.vallang.ISourceLocation; 14 | import io.usethesource.vallang.IValue; 15 | import io.usethesource.vallang.IValueFactory; 16 | import io.usethesource.vallang.ValueProvider; 17 | 18 | public class SetTests { 19 | 20 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 21 | public void idempotence( @ExpectedType("set[int]") ISet set, IInteger i) { 22 | assertEquals(set.insert(i), set.insert(i).insert(i)); 23 | } 24 | 25 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 26 | public void idempotenceWithLoc( @ExpectedType("set[loc]") ISet set, ISourceLocation i) { 27 | assertEquals(set.insert(i), set.insert(i).insert(i)); 28 | } 29 | 30 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 31 | public void insertion( @ExpectedType("set[real]") ISet set, IInteger i) { 32 | assertEquals(set.insert(i).size(), set.size() + 1); 33 | } 34 | 35 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 36 | public void removal(Random rnd, IValueFactory vf, @ExpectedType("set[int]") ISet set) { 37 | if (set.isEmpty()) { 38 | return; 39 | } 40 | int index = rnd.nextInt(set.size()); 41 | IValue elem = set.stream().skip(index).findFirst().get(); 42 | ISet smaller = set.delete(elem); 43 | assertEquals(smaller.size() + 1, set.size()); 44 | assertTrue(!smaller.contains(elem)); 45 | } 46 | 47 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 48 | public void removalLocations(Random rnd, @ExpectedType("set[loc]") ISet set, ISourceLocation i) { 49 | if (set.isEmpty()) { 50 | return; 51 | } 52 | 53 | int index = rnd.nextInt(set.size()); 54 | IValue elem = set.stream().skip(index).findFirst().get(); 55 | ISet smaller = set.delete(elem); 56 | assertEquals(smaller.size() + 1, set.size()); 57 | assertTrue(!smaller.contains(elem)); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/impl/reference/Set.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2013 CWI 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * 10 | * * Michael Steindorfer - Michael.Steindorfer@cwi.nl - CWI 11 | * * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI 12 | * * Paul Klint - Paul.Klint@cwi.nl - CWI 13 | * 14 | * Based on code by: 15 | * 16 | * * Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation 17 | *******************************************************************************/ 18 | package io.usethesource.vallang.impl.reference; 19 | 20 | import java.util.Iterator; 21 | 22 | import org.checkerframework.checker.nullness.qual.Nullable; 23 | 24 | import io.usethesource.vallang.ISet; 25 | import io.usethesource.vallang.ISetWriter; 26 | import io.usethesource.vallang.IValue; 27 | import io.usethesource.vallang.type.Type; 28 | 29 | /*package*/ class Set implements ISet { 30 | final Type type; 31 | final java.util.Set content; 32 | 33 | /*package*/ Set(Type elementType, java.util.Set content) { 34 | super(); 35 | this.type = TF.setType(elementType); 36 | this.content = content; 37 | } 38 | 39 | @Override 40 | public Type getType() { 41 | return type; 42 | } 43 | 44 | @Override 45 | public boolean contains(IValue e) { 46 | return content.contains(e); 47 | } 48 | 49 | @Override 50 | public ISetWriter writer() { 51 | return ValueFactory.getInstance().setWriter(); 52 | } 53 | 54 | @Override 55 | public boolean isEmpty() { 56 | return content.isEmpty(); 57 | } 58 | 59 | @Override 60 | public int size() { 61 | return content.size(); 62 | } 63 | 64 | @Override 65 | public int hashCode() { 66 | return content.hashCode(); 67 | } 68 | 69 | @Override 70 | public boolean equals(@Nullable Object other) { 71 | if (other == null) { 72 | return false; 73 | } 74 | return defaultEquals(other); 75 | } 76 | 77 | @Override 78 | public String toString() { 79 | return defaultToString(); 80 | } 81 | 82 | @Override 83 | public Iterator iterator() { 84 | return content.iterator(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/basic/StreamTest.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.basic; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.junit.jupiter.params.ParameterizedTest; 6 | import org.junit.jupiter.params.provider.ArgumentsSource; 7 | 8 | import io.usethesource.vallang.GivenValue; 9 | import io.usethesource.vallang.IList; 10 | import io.usethesource.vallang.INode; 11 | import io.usethesource.vallang.IValue; 12 | import io.usethesource.vallang.IValueFactory; 13 | import io.usethesource.vallang.ValueProvider; 14 | import io.usethesource.vallang.visitors.ValueStreams; 15 | 16 | public class StreamTest { 17 | private static final String TREE = "\"1\"(\"2\"(\"4\"(),\"5\"()), \"3\"(\"6\"(),\"7\"()))"; 18 | private static final String BOTTOMUP = "[\"4\",\"5\",\"2\",\"6\",\"7\",\"3\",\"1\"]"; 19 | private static final String TOPDOWN = "[\"1\",\"2\",\"4\",\"5\",\"3\",\"6\",\"7\"]"; 20 | private static final String TOPDOWNBREADTHFIRST = "[\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\"]"; 21 | private static final String BOTTOMUPBREADTHFIRST = "[\"7\",\"6\",\"5\",\"4\",\"3\",\"2\",\"1\"]"; 22 | 23 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 24 | public void bottomup(IValueFactory vf, @GivenValue(TREE) IValue v, @GivenValue(BOTTOMUP) IValue answer) { 25 | IList numbers = ValueStreams.bottomup(v).map((n) -> vf.string(((INode) n).getName())).collect(vf.listWriter()); 26 | 27 | assertEquals(answer, numbers); 28 | } 29 | 30 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 31 | public void topdown(IValueFactory vf, @GivenValue(TREE) IValue v, @GivenValue(TOPDOWN) IValue answer) { 32 | IList numbers = ValueStreams.topdown(v).map((n) -> vf.string(((INode) n).getName())).collect(vf.listWriter()); 33 | 34 | assertEquals(answer, numbers); 35 | } 36 | 37 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 38 | public void topdownBreadthFirst(IValueFactory vf, @GivenValue(TREE) IValue v, @GivenValue(TOPDOWNBREADTHFIRST) IValue answer) { 39 | IList numbers = ValueStreams.topdownbf(v).map((n) -> vf.string(((INode) n).getName())).collect(vf.listWriter()); 40 | 41 | assertEquals(answer, numbers); 42 | } 43 | 44 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 45 | public void bottomupBreadthFirst(IValueFactory vf, @GivenValue(TREE) IValue v, @GivenValue(BOTTOMUPBREADTHFIRST) IValue answer) { 46 | IList numbers = ValueStreams.bottomupbf(v).map((n) -> vf.string(((INode) n).getName())).collect(vf.listWriter()); 47 | 48 | assertEquals(answer, numbers); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/IValueTextReader.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) CWI 2008 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * Jurgen Vinju (jurgenv@cwi.nl) - initial API and implementation 10 | 11 | *******************************************************************************/ 12 | 13 | package io.usethesource.vallang.io; 14 | 15 | import java.io.IOException; 16 | import java.io.Reader; 17 | 18 | import io.usethesource.vallang.IValue; 19 | import io.usethesource.vallang.IValueFactory; 20 | import io.usethesource.vallang.exceptions.FactTypeUseException; 21 | import io.usethesource.vallang.type.Type; 22 | import io.usethesource.vallang.type.TypeStore; 23 | 24 | /** 25 | * An instance of IValueTextReader can parse a serialized character-based representation of IValues. 26 | * There should be a corresponding IValueTextWriter to serialize them again. Note 27 | * that IValueTextReaders should also validate the serialized input against a {@link Type}. 28 | */ 29 | 30 | public interface IValueTextReader { 31 | /** 32 | * Parse an IValue, validate it and build it if it can be validated. 33 | * 34 | * @param factory used when building the value 35 | * @param store declarations of types to use 36 | * @param type used to validate the value 37 | * @param stream source of bytes to parse 38 | * @return an IValue that represents the string input 39 | */ 40 | IValue read(IValueFactory factory, TypeStore store, Type type, Reader reader) throws FactTypeUseException, IOException; 41 | 42 | /** 43 | * Parse an IValue, validate it and build it if it can be validated. 44 | * 45 | * @param factory used when building the value 46 | * @param type used to validate the value 47 | * @param reader source of character to parse 48 | * @return an IValue that represents the string input 49 | */ 50 | IValue read(IValueFactory factory, Type type, Reader reader) throws FactTypeUseException, IOException; 51 | 52 | /** 53 | * Parse an IValue without validation. 54 | * 55 | * @param factory used when building the value 56 | * @param reader source of characters to parse 57 | * @return an IValue that represents the string input 58 | */ 59 | IValue read(IValueFactory factory, Reader reader) throws FactTypeUseException, IOException; 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/util/ArrayUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, Davy Landman, Centrum Wiskunde & Informatica (CWI) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | * 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | */ 13 | package io.usethesource.vallang.io.binary.util; 14 | 15 | public class ArrayUtil { 16 | 17 | // source: http://stackoverflow.com/a/25508988/11098 18 | // based on: "Java server performance: A case study of building efficient, scalable Jvms" by R. Dimpsey, R. Arora, K. Kuiper. 19 | // in general, starts at the beginnning and then grows exponentially in the System.arrayCopy size chunks. 20 | // it is faster due to the memcopy that will be used underneath. 21 | // it taks log2(data.length) calls to arrayCopy instead of a data.length loop in java 22 | public static void fill(T[] array, T value) { 23 | int len = array.length; 24 | 25 | if (len > 0) { 26 | array[0] = value; 27 | } 28 | 29 | for (int i = 1; i < len; i += i) { 30 | System.arraycopy(array, 0, array, i, ((len - i) < i) ? (len - i) : i); 31 | } 32 | } 33 | 34 | public static void fill(int[] array, int value) { 35 | int len = array.length; 36 | 37 | if (len > 0) { 38 | array[0] = value; 39 | } 40 | 41 | for (int i = 1; i < len; i += i) { 42 | System.arraycopy(array, 0, array, i, ((len - i) < i) ? (len - i) : i); 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/util/FileChannelDirectOutputStream.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.io.binary.util; 2 | 3 | import java.io.IOException; 4 | import java.nio.ByteBuffer; 5 | import java.nio.channels.FileChannel; 6 | 7 | public class FileChannelDirectOutputStream extends ByteBufferOutputStream { 8 | private boolean closing = false; 9 | private int flushes = 0; 10 | private final FileChannel channel; 11 | private final int growEvery; 12 | 13 | public FileChannelDirectOutputStream(FileChannel channel, int growEvery) { 14 | super(DirectByteBufferCache.getInstance().get(8*1024)); 15 | this.channel = channel; 16 | this.growEvery = growEvery; 17 | } 18 | 19 | @Override 20 | protected ByteBuffer flush(ByteBuffer toflush) throws IOException { 21 | channel.write(toflush); 22 | toflush.clear(); 23 | flushes++; 24 | if (flushes == growEvery && !closing) { 25 | flushes = 0; 26 | return grow(toflush); 27 | } 28 | return toflush; 29 | } 30 | 31 | protected ByteBuffer grow(ByteBuffer current) { 32 | int currentCapacity = current.capacity(); 33 | if (currentCapacity < (1024*1024)) { 34 | DirectByteBufferCache.getInstance().put(current); 35 | return DirectByteBufferCache.getInstance().get(currentCapacity * 2); 36 | } 37 | return current; 38 | } 39 | 40 | @Override 41 | public void write(ByteBuffer buf) throws IOException { 42 | if (target.remaining() >= buf.remaining()) { 43 | target.put(buf); 44 | } 45 | else { 46 | int oldLimit = buf.limit(); 47 | buf.limit(buf.position() + target.remaining()); 48 | target.put(buf); 49 | buf.limit(oldLimit); 50 | 51 | flush(); 52 | if (target.remaining() >= buf.remaining()) { 53 | // now it does fit, no problem 54 | target.put(buf); 55 | } 56 | else { 57 | // directly write the remaining buffer to the channel 58 | // skipping our internal buffer 59 | assert target.position() == 0; 60 | channel.write(buf); 61 | } 62 | } 63 | } 64 | 65 | @Override 66 | public void close() throws IOException { 67 | if (!closed) { 68 | try (FileChannel chan = channel) { 69 | closing = true; 70 | flush(); 71 | super.close(); 72 | } 73 | finally { 74 | DirectByteBufferCache.getInstance().put(target); 75 | } 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/wire/FieldKind.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, Davy Landman, Centrum Wiskunde & Informatica (CWI) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | * 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | */ 13 | package io.usethesource.vallang.io.binary.wire; 14 | 15 | public class FieldKind { 16 | /* only values from 1-7 are valid (3 bits, 0 is taken by message flag) */ 17 | public static final int PREVIOUS_STR = 1; 18 | public static final int INT = 2; 19 | public static final int STRING = 3; 20 | public static final int NESTED = 4; 21 | public static final int REPEATED = 5; 22 | 23 | @SuppressWarnings("unused") 24 | private static final int UNUSED1 = 6; 25 | @SuppressWarnings("unused") 26 | private static final int UNUSED2 = 7; 27 | 28 | public static class Repeated { 29 | /* values from 0-7 are valid */ 30 | public static final int BYTES = 0; 31 | @SuppressWarnings("unused") 32 | private static final int UNUSED0 = 1; 33 | public static final int INTS = FieldKind.INT; // 2 34 | public static final int STRINGS = FieldKind.STRING; // 3 35 | public static final int NESTEDS = FieldKind.NESTED; // 4 36 | 37 | @SuppressWarnings("unused") 38 | private static final int UNUSED1 = 5; 39 | @SuppressWarnings("unused") 40 | private static final int UNUSED2 = 6; 41 | @SuppressWarnings("unused") 42 | private static final int UNUSED3 = 7; 43 | } 44 | private FieldKind() {} 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/type/DefaultTypeVisitor.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.type; 2 | 3 | public abstract class DefaultTypeVisitor implements ITypeVisitor { 4 | protected final T def; 5 | 6 | public DefaultTypeVisitor(T def) { 7 | this.def = def; 8 | } 9 | 10 | @Override 11 | public T visitReal(Type type) throws E { 12 | return def; 13 | } 14 | 15 | @Override 16 | public T visitInteger(Type type) throws E { 17 | return def; 18 | } 19 | 20 | @Override 21 | public T visitRational(Type type) throws E { 22 | return def; 23 | } 24 | 25 | @Override 26 | public T visitList(Type type) throws E { 27 | return def; 28 | } 29 | 30 | @Override 31 | public T visitMap(Type type) throws E { 32 | return def; 33 | } 34 | 35 | @Override 36 | public T visitNumber(Type type) throws E { 37 | return def; 38 | } 39 | 40 | @Override 41 | public T visitAlias(Type type) throws E { 42 | return def; 43 | } 44 | 45 | @Override 46 | public T visitSet(Type type) throws E { 47 | return def; 48 | } 49 | 50 | @Override 51 | public T visitSourceLocation(Type type) throws E { 52 | return def; 53 | } 54 | 55 | @Override 56 | public T visitString(Type type) throws E { 57 | return def; 58 | } 59 | 60 | @Override 61 | public T visitNode(Type type) throws E { 62 | return def; 63 | } 64 | 65 | @Override 66 | public T visitConstructor(Type type) throws E { 67 | return def; 68 | } 69 | 70 | @Override 71 | public T visitAbstractData(Type type) throws E { 72 | return def; 73 | } 74 | 75 | @Override 76 | public T visitTuple(Type type) throws E { 77 | return def; 78 | } 79 | 80 | @Override 81 | public T visitValue(Type type) throws E { 82 | return def; 83 | } 84 | 85 | @Override 86 | public T visitVoid(Type type) throws E { 87 | return def; 88 | } 89 | 90 | @Override 91 | public T visitBool(Type type) throws E { 92 | return def; 93 | } 94 | 95 | @Override 96 | public T visitParameter(Type type) throws E { 97 | return def; 98 | } 99 | 100 | @Override 101 | public T visitExternal(Type type) throws E { 102 | return def; 103 | } 104 | 105 | @Override 106 | public T visitDateTime(Type type) throws E { 107 | return def; 108 | } 109 | 110 | @Override 111 | public T visitFunction(Type type) throws E { 112 | return def; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesList.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2009 Centrum Wiskunde en Informatica (CWI) 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * Arnold Lankamp - interfaces and implementation 10 | *******************************************************************************/ 11 | package io.usethesource.vallang.impl.util.collections; 12 | 13 | import java.util.Iterator; 14 | 15 | import io.usethesource.vallang.IValue; 16 | import io.usethesource.vallang.util.ShareableList; 17 | 18 | /** 19 | * A specialized version of the ShareableList, specifically meant for storing values. 20 | * 21 | * @author Arnold Lankamp 22 | */ 23 | public class ShareableValuesList extends ShareableList { 24 | 25 | public ShareableValuesList(){ 26 | super(); 27 | } 28 | 29 | public ShareableValuesList(ShareableValuesList shareableValuesList){ 30 | super(shareableValuesList); 31 | } 32 | 33 | public ShareableValuesList(ShareableValuesList shareableValuesList, int offset, int length){ 34 | super(shareableValuesList, offset, length); 35 | } 36 | 37 | public boolean contains(IValue value){ 38 | Iterator valuesIterator = iterator(); 39 | while(valuesIterator.hasNext()){ 40 | IValue next = valuesIterator.next(); 41 | if(next.equals(value)) { 42 | return true; 43 | } 44 | } 45 | 46 | return false; 47 | } 48 | 49 | public boolean remove(IValue value){ 50 | int index = 0; 51 | Iterator valuesIterator = iterator(); 52 | while (valuesIterator.hasNext()){ 53 | IValue next = valuesIterator.next(); 54 | if (next.equals(value)) { 55 | break; 56 | } 57 | 58 | index++; 59 | } 60 | 61 | if(index < size()){ 62 | remove(index); 63 | return true; 64 | } 65 | 66 | return false; 67 | } 68 | 69 | public ShareableValuesList subList(int offset, int length){ 70 | if(offset < 0) { throw new IndexOutOfBoundsException("Offset may not be smaller than 0."); } 71 | if(length < 0) { throw new IndexOutOfBoundsException("Length may not be smaller than 0."); } 72 | if((offset + length) > size()) { throw new IndexOutOfBoundsException("'offset + length' may not be larger than 'list.size()'"); } 73 | 74 | return new ShareableValuesList(this, offset, length); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /checkstyle.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | 2 | Please refer to http://usethesource.io/about/values.html for the origin of this text. This text 3 | includes our Code of Conduct, which offers our basic social values, but first it lists a number of community values specific to meta programming and open-source software development. 4 | 5 | ## Main Principles 6 | 7 | These are principles that we strive to uphold in the UseTheSource community. 8 | 9 | * Metaprogramming, software language engineering and generic programming are cool 10 | * "real world" application (not just toy languages and toy examples) 11 | * Striving for good design 12 | * design code for readability: clear and simple code 13 | * design for all programmers/users: clear and simple languages, API and UX 14 | * avoid over-design, gold-plating and premature optimization 15 | * Proper attribution 16 | * open copyright licenses 17 | * clear authorship/ownership trace 18 | * clear funding/sponsorship trace 19 | * due diligence with reuse of open-source 20 | * Excellence 21 | * generic & simple 22 | * efficient & scalable 23 | * accurate & correct 24 | * continuously tested & delivered 25 | * Social 26 | * patience with both users and contributors 27 | * open to feedback 28 | * responsive 29 | * visibly active 30 | 31 | ## Contributor Code of Conduct 32 | 33 | As Contributors of the UseTheSource community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. 34 | 35 | We are committed to making participation in this community a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 36 | 37 | Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. 38 | 39 | [Project Owners](/about/processes.html) have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Contributors who do not follow the Code of Conduct may be removed from the project team. 40 | 41 | This code of conduct applies both within project spaces and in public spaces when an individual is representing the UseTheSource community or one of its projects. 42 | 43 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by [opening an issue](https://github.com/usethesource/usethesource.github.io/issues) or contacting one or more of the [Project Owners](/projects/). 44 | 45 | This Code of Conduct is adapted from the Contributor Covenant, version 1.1.0, available from 46 | 47 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/IValueBinaryReader.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) CWI 2008 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * Jurgen Vinju (jurgenv@cwi.nl) - initial API and implementation 10 | 11 | *******************************************************************************/ 12 | 13 | package io.usethesource.vallang.io; 14 | 15 | import java.io.IOException; 16 | import java.io.InputStream; 17 | 18 | import io.usethesource.vallang.IValue; 19 | import io.usethesource.vallang.IValueFactory; 20 | import io.usethesource.vallang.exceptions.FactTypeUseException; 21 | import io.usethesource.vallang.type.Type; 22 | import io.usethesource.vallang.type.TypeStore; 23 | 24 | /** 25 | * An instance of IValueReader can parse a serialized representation of IValues. 26 | * There should be a corresponding IValueWriter to serialize them again. Note 27 | * that IValueReaders should also validate the serialized input 28 | * against a {@link Type}. 29 | * 30 | * @author jurgenv 31 | * 32 | */ 33 | 34 | public interface IValueBinaryReader { 35 | /** 36 | * Parse an IValue, validate it and build it if it can be validated. 37 | * 38 | * @param factory 39 | * used when building the value 40 | * @param store 41 | * declarations of types to use 42 | * @param type 43 | * used to validate the value 44 | * @param stream 45 | * source of bytes to parse 46 | * @return an IValue that represents the string input 47 | */ 48 | IValue read(IValueFactory factory, TypeStore store, Type type, 49 | InputStream stream) throws FactTypeUseException, IOException; 50 | 51 | /** 52 | * Parse an IValue, validate it and build it if it can be validated. 53 | * 54 | * @param factory 55 | * used when building the value 56 | * @param type 57 | * used to validate the value 58 | * @param stream 59 | * source of bytes to parse 60 | * @return an IValue that represents the string input 61 | */ 62 | IValue read(IValueFactory factory, Type type, InputStream stream) 63 | throws FactTypeUseException, IOException; 64 | 65 | /** 66 | * Parse an IValue without validation. 67 | * 68 | * @param factory 69 | * used when building the value 70 | * @param stream 71 | * source of bytes to parse 72 | * @return an IValue that represents the string input 73 | */ 74 | IValue read(IValueFactory factory, InputStream stream) 75 | throws FactTypeUseException, IOException; 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/IWriter.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang; 2 | 3 | import java.util.Collections; 4 | import java.util.Set; 5 | import java.util.function.BiConsumer; 6 | import java.util.function.BinaryOperator; 7 | import java.util.function.Function; 8 | import java.util.function.Supplier; 9 | import java.util.stream.Collector; 10 | 11 | import io.usethesource.vallang.exceptions.FactTypeUseException; 12 | 13 | public interface IWriter> extends Iterable, Collector, T> { 14 | /** 15 | * Modify this writer to insert only unique instances into the collection 16 | * @return 17 | */ 18 | public default IWriter unique() { 19 | return this; 20 | } 21 | 22 | /** 23 | * Insert several elements 24 | * @param value array of elements to insert 25 | */ 26 | public void insert(IValue... value); 27 | 28 | /** 29 | * Append several elements 30 | * @param value array of elements to append 31 | */ 32 | public default void append(IValue... value) { 33 | insert(value); 34 | } 35 | 36 | /** 37 | * Append elements at the end. 38 | * 39 | * @param value array of elements to append 40 | * @throws FactTypeUseException when done() was called before 41 | */ 42 | public default void appendAll(Iterable collection) { 43 | for (IValue v : collection) { 44 | append(v); 45 | } 46 | } 47 | 48 | /** 49 | * Insert a tuple made of the given fields 50 | * @param fields 51 | */ 52 | public void insertTuple(IValue... fields); 53 | 54 | /** 55 | * Append a tuple made of the given fields 56 | * @param fields 57 | */ 58 | public default void appendTuple(IValue... fields) { 59 | insertTuple(fields); 60 | } 61 | 62 | /** 63 | * Inserts all elements of an iterable 64 | * @param collection 65 | */ 66 | default void insertAll(Iterable collection) { 67 | for (IValue v : collection) { 68 | insert(v); 69 | } 70 | } 71 | 72 | public T done(); 73 | 74 | 75 | @Override 76 | default BiConsumer, IValue> accumulator() { 77 | return (writer, elem) -> writer.append(elem); 78 | } 79 | 80 | @Override 81 | abstract Supplier> supplier(); 82 | 83 | @Override 84 | default Function, T> finisher() { 85 | return w -> w.done(); 86 | } 87 | 88 | @Override 89 | default BinaryOperator> combiner() { 90 | return (w1, w2) -> { 91 | w2.forEach(e -> w1.append(e)); 92 | return w1; 93 | }; 94 | } 95 | 96 | @Override 97 | default Set characteristics() { 98 | return Collections.emptySet(); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/wire/IWireOutputStream.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, Davy Landman, Centrum Wiskunde & Informatica (CWI) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | * 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | */ 13 | package io.usethesource.vallang.io.binary.wire; 14 | 15 | import java.io.Closeable; 16 | import java.io.Flushable; 17 | import java.io.IOException; 18 | 19 | 20 | /** 21 | * a basic message writer for the IValue wire format 22 | */ 23 | public interface IWireOutputStream extends Closeable, Flushable { 24 | /** 25 | * start a message, always end with a {@linkplain #endMessage()}. 26 | */ 27 | void startMessage(int messageId) throws IOException; 28 | 29 | void writeField(int fieldId, int value) throws IOException; 30 | void writeField(int fieldId, byte[] value) throws IOException; 31 | void writeField(int fieldId, String value) throws IOException; 32 | 33 | void writeField(int fieldId, int[] values) throws IOException; 34 | void writeField(int fieldId, String[] values) throws IOException; 35 | 36 | /** 37 | * A nested field signals that next up in the stream, we get a nested message. it has no value of itself. 38 | */ 39 | void writeNestedField(int fieldId) throws IOException; 40 | /** 41 | * Similar to {@linkplain #writeNestedField(int)} , we signal a nested field that repeats fieldId times. Again, the user has to take care of actually writing this many nested messages. 42 | */ 43 | void writeRepeatedNestedField(int fieldId, int numberOfNestedElements) throws IOException; 44 | 45 | void endMessage() throws IOException; 46 | 47 | default void writeEmptyMessage(int messageId) throws IOException { 48 | startMessage(messageId); 49 | endMessage(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/ICollection.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang; 2 | 3 | import java.util.stream.Stream; 4 | import java.util.stream.StreamSupport; 5 | 6 | import org.checkerframework.checker.nullness.qual.NonNull; 7 | 8 | import io.usethesource.vallang.exceptions.IllegalOperationException; 9 | import io.usethesource.vallang.type.Type; 10 | 11 | public interface ICollection> extends IValue, Iterable<@NonNull IValue> { 12 | /** 13 | * @return the most concrete type (least upper bound) of the elements' types 14 | */ 15 | public default Type getElementType() { 16 | return getType().getElementType(); 17 | } 18 | 19 | /** 20 | * @return true iff this container has no elements 21 | */ 22 | public boolean isEmpty(); 23 | 24 | /** 25 | * @return an empty collection 26 | */ 27 | public default T empty() { 28 | return writer().done(); 29 | } 30 | 31 | /** 32 | * @return an empty writer for this collection kind 33 | */ 34 | public IWriter writer(); 35 | 36 | /** 37 | * @return the arity of the collection (the number of elements in it) 38 | */ 39 | public int size(); 40 | 41 | /** 42 | * @return this collection with an IRelation interface 43 | * @throws IllegalOperationException when the container does not contain all tuples of the same arity 44 | */ 45 | public IRelation asRelation(); 46 | 47 | /** 48 | * @return true iff the collection contains only tuples of a fixed width, if any. 49 | */ 50 | public default boolean isRelation() { 51 | return getElementType().isFixedWidth(); 52 | } 53 | 54 | /** 55 | * Computes the Cartesian product of two collections 56 | * @param that is another collection 57 | * @return a collection representing the Cartesian product of the receiver and the given collection 58 | */ 59 | public default T product(T that) { 60 | IWriter w = writer(); 61 | 62 | if (that.isEmpty()) { 63 | return that; 64 | } 65 | 66 | for (IValue t1 : this) { 67 | for (IValue t2 : that) { 68 | w.appendTuple(t1, t2); 69 | } 70 | } 71 | 72 | return w.done(); 73 | } 74 | 75 | /** 76 | * Computes the union of two collections, ignoring duplicates. The original duplicates in the receiver and the given container will dissappear as well. 77 | * 78 | * @param that is the other collection 79 | * @return a collection containing both the elements of the receiver and those of the given container, without introducing duplicates. 80 | */ 81 | public default T union(T that) { 82 | IWriter w = writer().unique(); 83 | w.appendAll(this); 84 | w.appendAll(that); 85 | return w.done(); 86 | } 87 | 88 | /** 89 | * @return a stream of IValues from the current collection 90 | */ 91 | public default Stream stream() { 92 | return StreamSupport.stream(spliterator(), false); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/type/ExternalType.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2007 IBM Corporation, 2009-2015 CWI 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * Jurgen Vinju (jurgen@vinju.org) - initial API and implementation 10 | 11 | *******************************************************************************/ 12 | package io.usethesource.vallang.type; 13 | 14 | import java.util.Map; 15 | import java.util.Random; 16 | 17 | import io.usethesource.vallang.IExternalValue; 18 | import io.usethesource.vallang.IValue; 19 | import io.usethesource.vallang.IValueFactory; 20 | import io.usethesource.vallang.type.TypeFactory.RandomTypesConfig; 21 | 22 | /** 23 | * ExternalType facilitates a limited form of extensibility to the PDB's type system. 24 | * It can be used for example to add 'function types' to the PDB. Any such extension 25 | * to PDB must be a subclass of ExternalType and override isSubTypeOf() and lub(). 26 | *
27 | * Note that NORMAL USE OF THE VALUES LIBRARY DOES NOT REQUIRE EXTENDING THIS CLASS 28 | */ 29 | public abstract class ExternalType extends DefaultSubtypeOfValue { 30 | 31 | /** 32 | * Provide the type of the values produced by {@link IExternalValue}.encodeAsConstructor() 33 | */ 34 | public abstract Type asAbstractDataType(); 35 | 36 | @Override 37 | public Type getTypeParameters() { 38 | return TypeFactory.getInstance().voidType(); 39 | } 40 | 41 | @Override 42 | public boolean isExternalType() { 43 | return true; 44 | } 45 | 46 | @Override 47 | public final T accept(ITypeVisitor visitor) throws E { 48 | return visitor.visitExternal(this); 49 | } 50 | 51 | @Override 52 | public final Type lub(Type other) { 53 | return other.lubWithExternal(this); 54 | } 55 | 56 | @Override 57 | public final Type glb(Type type) { 58 | return type.glbWithExternal(this); 59 | } 60 | 61 | @Override 62 | public boolean intersects(Type other) { 63 | return other.intersectsWithExternal(this); 64 | } 65 | 66 | @Override 67 | protected /*final*/ boolean isSupertypeOf(Type type) { 68 | return type.isSubtypeOfExternal(this); 69 | } 70 | 71 | @Override 72 | protected abstract Type lubWithExternal(Type type); 73 | 74 | @Override 75 | protected abstract boolean intersectsWithExternal(Type type); 76 | 77 | @Override 78 | protected abstract Type glbWithExternal(Type type); 79 | 80 | 81 | @Override 82 | protected abstract boolean isSubtypeOfExternal(Type type); 83 | 84 | @Override 85 | public abstract IValue randomValue(Random random, RandomTypesConfig typesConfig, IValueFactory vf, TypeStore store, Map typeParameters, int maxDepth, int maxBreadth); 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/util/LinearCircularLookupWindow.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, Davy Landman, Centrum Wiskunde & Informatica (CWI) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | * 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | */ 13 | package io.usethesource.vallang.io.binary.util; 14 | 15 | import java.util.Arrays; 16 | 17 | import org.checkerframework.checker.nullness.qual.NonNull; 18 | import org.checkerframework.checker.nullness.qual.Nullable; 19 | 20 | public class LinearCircularLookupWindow implements TrackLastRead, ClearableWindow { 21 | private @Nullable T[] data; 22 | private long written; 23 | private final int maxSize; 24 | 25 | @SuppressWarnings("unchecked") 26 | public LinearCircularLookupWindow(int size) { 27 | data = (T[]) new Object[Math.min(512, size)]; 28 | written = 0; 29 | maxSize = size + 1; 30 | } 31 | 32 | private int translate(long index) { 33 | return (int) (index % data.length); 34 | } 35 | 36 | 37 | @Override 38 | public T lookBack(int offset) { 39 | assert offset + 1 <= written && offset < maxSize; 40 | @Nullable T result = data[translate(written - (offset + 1))]; 41 | if (result == null) { 42 | throw new RuntimeException("Lookback of " + offset + "was invalid"); 43 | } 44 | return result; 45 | } 46 | 47 | @Override 48 | public void read(T obj) { 49 | growIfNeeded(); 50 | data[translate(written++)] = obj; 51 | } 52 | 53 | private void growIfNeeded() { 54 | if (written <= maxSize && written == data.length && data.length != maxSize) { 55 | data = Arrays.copyOf(data, Math.min(data.length * 2, maxSize)); 56 | } 57 | } 58 | 59 | @Override 60 | public int size() { 61 | return maxSize; 62 | } 63 | 64 | @Override 65 | public void clear() { 66 | ArrayUtil.fill(data, null); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/io/TrackWritesTestBase.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.io; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | import io.usethesource.vallang.io.binary.util.TrackLastWritten; 8 | 9 | public abstract class TrackWritesTestBase { 10 | 11 | public abstract TrackLastWritten getWritesWindow(int size); 12 | 13 | @Test 14 | public void canFindFirstObject() { 15 | Object a = new Object(); 16 | TrackLastWritten w = getWritesWindow(5); 17 | w.write(a); 18 | assertEquals(0, w.howLongAgo(a)); 19 | } 20 | 21 | @Test 22 | public void canFindOldObject() { 23 | Object a = new Object(); 24 | Object b = new Object(); 25 | TrackLastWritten w = getWritesWindow(5); 26 | w.write(a); 27 | w.write(b); 28 | assertEquals(1, w.howLongAgo(a)); 29 | } 30 | 31 | @Test 32 | public void canFindObjectAtEdge() { 33 | Object a = new Object(); 34 | Object b = new Object(); 35 | Object c = new Object(); 36 | TrackLastWritten w = getWritesWindow(5); 37 | w.write(a); 38 | w.write(b); 39 | w.write(c); 40 | assertEquals(2, w.howLongAgo(a)); 41 | } 42 | 43 | @Test 44 | public void dropsObject() { 45 | Object a = new Object(); 46 | Object b = new Object(); 47 | Object c = new Object(); 48 | Object d = new Object(); 49 | TrackLastWritten w = getWritesWindow(3); 50 | w.write(a); 51 | w.write(b); 52 | w.write(c); 53 | w.write(d); 54 | assertEquals(-1, w.howLongAgo(a)); 55 | assertEquals(2, w.howLongAgo(b)); 56 | assertEquals(1, w.howLongAgo(c)); 57 | assertEquals(0, w.howLongAgo(d)); 58 | } 59 | 60 | @Test 61 | public void dropsMany() { 62 | Object a = new Object(); 63 | Object b = new Object(); 64 | Object c = new Object(); 65 | Object d = new Object(); 66 | TrackLastWritten w = getWritesWindow(3); 67 | for (int i =0; i < 10000; i++) { 68 | w.write(new Object()); 69 | } 70 | w.write(a); 71 | w.write(b); 72 | w.write(c); 73 | w.write(d); 74 | assertEquals(-1, w.howLongAgo(a)); 75 | assertEquals(2, w.howLongAgo(b)); 76 | assertEquals(1, w.howLongAgo(c)); 77 | assertEquals(0, w.howLongAgo(d)); 78 | } 79 | 80 | @Test 81 | public void randomTest() { 82 | Object[] elements = new Object[1000];; 83 | for (int i = 0; i < elements.length; i++) { 84 | elements[i] = new Object(); 85 | } 86 | final int windowSize = elements.length / 2; 87 | TrackLastWritten w = getWritesWindow(windowSize); 88 | for (int i = 0; i < elements.length; i++) { 89 | w.write(elements[i]); 90 | for (int j = 0; j < Math.min(windowSize, i); j++) { 91 | assertEquals(j, w.howLongAgo(elements[i - j]), "Looking back: "+ j + " after " + i + "written"); 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/visitors/IdentityVisitor.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2008 CWI. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * jurgen@vinju.org 10 | *******************************************************************************/ 11 | package io.usethesource.vallang.visitors; 12 | 13 | import io.usethesource.vallang.IBool; 14 | import io.usethesource.vallang.IConstructor; 15 | import io.usethesource.vallang.IDateTime; 16 | import io.usethesource.vallang.IExternalValue; 17 | import io.usethesource.vallang.IInteger; 18 | import io.usethesource.vallang.IList; 19 | import io.usethesource.vallang.IMap; 20 | import io.usethesource.vallang.INode; 21 | import io.usethesource.vallang.IRational; 22 | import io.usethesource.vallang.IReal; 23 | import io.usethesource.vallang.ISet; 24 | import io.usethesource.vallang.ISourceLocation; 25 | import io.usethesource.vallang.IString; 26 | import io.usethesource.vallang.ITuple; 27 | import io.usethesource.vallang.IValue; 28 | 29 | /** 30 | * This abstract class does nothing except implementing identity. Extend it 31 | * to easily implement a visitor that visits selected types of IValues. 32 | * 33 | */ 34 | public abstract class IdentityVisitor implements IValueVisitor { 35 | @Override 36 | public IValue visitReal(IReal o) throws E{ 37 | return o; 38 | } 39 | 40 | @Override 41 | public IValue visitInteger(IInteger o) throws E{ 42 | return o; 43 | } 44 | 45 | @Override 46 | public IValue visitRational(IRational o) throws E{ 47 | return o; 48 | } 49 | 50 | @Override 51 | public IValue visitList(IList o) throws E{ 52 | return o; 53 | } 54 | 55 | @Override 56 | public IValue visitMap(IMap o) throws E{ 57 | return o; 58 | } 59 | 60 | @Override 61 | public IValue visitSet(ISet o) throws E{ 62 | return o; 63 | } 64 | 65 | @Override 66 | public IValue visitSourceLocation(ISourceLocation o) throws E{ 67 | return o; 68 | } 69 | 70 | @Override 71 | public IValue visitString(IString o) throws E{ 72 | return o; 73 | } 74 | 75 | @Override 76 | public IValue visitNode(INode o) throws E{ 77 | return o; 78 | } 79 | 80 | @Override 81 | public IValue visitConstructor(IConstructor o) throws E { 82 | return o; 83 | } 84 | 85 | @Override 86 | public IValue visitTuple(ITuple o) throws E{ 87 | return o; 88 | } 89 | 90 | @Override 91 | public IValue visitBoolean(IBool o) throws E { 92 | return o; 93 | } 94 | 95 | @Override 96 | public IValue visitExternal(IExternalValue o) throws E { 97 | return o; 98 | } 99 | 100 | @Override 101 | public IValue visitDateTime(IDateTime o) throws E { 102 | return o; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/visitors/NullVisitor.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2008 CWI. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * jurgen@vinju.org 10 | *******************************************************************************/ 11 | package io.usethesource.vallang.visitors; 12 | 13 | import org.checkerframework.checker.nullness.qual.Nullable; 14 | 15 | import io.usethesource.vallang.IBool; 16 | import io.usethesource.vallang.IConstructor; 17 | import io.usethesource.vallang.IDateTime; 18 | import io.usethesource.vallang.IExternalValue; 19 | import io.usethesource.vallang.IInteger; 20 | import io.usethesource.vallang.IList; 21 | import io.usethesource.vallang.IMap; 22 | import io.usethesource.vallang.INode; 23 | import io.usethesource.vallang.IRational; 24 | import io.usethesource.vallang.IReal; 25 | import io.usethesource.vallang.ISet; 26 | import io.usethesource.vallang.ISourceLocation; 27 | import io.usethesource.vallang.IString; 28 | import io.usethesource.vallang.ITuple; 29 | 30 | /** 31 | * This abstract class does nothing except returning null. Extend it 32 | * to easily implement a visitor that visits selected types of IValues. 33 | * 34 | */ 35 | public abstract class NullVisitor<@Nullable T, E extends Throwable> implements IValueVisitor { 36 | @Override 37 | public T visitReal(IReal o) throws E { 38 | return null; 39 | } 40 | 41 | @Override 42 | public T visitInteger(IInteger o) throws E { 43 | return null; 44 | } 45 | 46 | @Override 47 | public T visitRational(IRational o) throws E { 48 | return null; 49 | } 50 | 51 | @Override 52 | public T visitList(IList o) throws E { 53 | return null; 54 | } 55 | 56 | @Override 57 | public T visitMap(IMap o) throws E { 58 | return null; 59 | } 60 | 61 | @Override 62 | public T visitSet(ISet o) throws E { 63 | return null; 64 | } 65 | 66 | @Override 67 | public T visitSourceLocation(ISourceLocation o) throws E { 68 | return null; 69 | } 70 | 71 | @Override 72 | public T visitString(IString o) throws E { 73 | return null; 74 | } 75 | 76 | @Override 77 | public T visitNode(INode o) throws E { 78 | return null; 79 | } 80 | 81 | @Override 82 | public T visitConstructor(IConstructor o) throws E { 83 | return null; 84 | } 85 | 86 | @Override 87 | public T visitTuple(ITuple o) throws E { 88 | return null; 89 | } 90 | 91 | @Override 92 | public T visitBoolean(IBool boolValue) throws E { 93 | return null; 94 | } 95 | 96 | @Override 97 | public T visitExternal(IExternalValue externalValue) throws E { 98 | return null; 99 | } 100 | 101 | @Override 102 | public T visitDateTime(IDateTime o) throws E { 103 | return null; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/util/MapLastWritten.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, Davy Landman, Centrum Wiskunde & Informatica (CWI) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | * 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | */ 13 | package io.usethesource.vallang.io.binary.util; 14 | 15 | import java.util.LinkedHashMap; 16 | import java.util.Map; 17 | 18 | import org.checkerframework.checker.nullness.qual.NonNull; 19 | import org.checkerframework.checker.nullness.qual.Nullable; 20 | 21 | public class MapLastWritten implements TrackLastWritten { 22 | public static class IdentityWrapper { 23 | private final T wrapped; 24 | private final int hashCode; 25 | public IdentityWrapper(T wrapped) { 26 | this.wrapped = wrapped; 27 | this.hashCode = System.identityHashCode(wrapped); 28 | } 29 | 30 | @Override 31 | public int hashCode() { 32 | return hashCode; 33 | } 34 | 35 | @Override 36 | @SuppressWarnings("unchecked") 37 | public boolean equals(@Nullable Object obj) { 38 | return obj != null && getClass().equals(obj.getClass()) && ((IdentityWrapper)obj).wrapped == wrapped; 39 | } 40 | } 41 | private final Map, Long> lookupData; 42 | private long written; 43 | 44 | @SuppressWarnings("serial") 45 | public MapLastWritten(final int size) { 46 | lookupData = new LinkedHashMap, Long>(size + 1, 1.0f, false) { 47 | @Override 48 | protected boolean removeEldestEntry(java.util.Map.Entry, Long> eldest) { 49 | return super.size() > size; 50 | } 51 | }; 52 | written = 0; 53 | } 54 | 55 | @Override 56 | public int howLongAgo(T obj) { 57 | Long writtenAt = lookupData.get(new IdentityWrapper<>(obj)); 58 | if (writtenAt != null) { 59 | return (int) ((written - writtenAt) - 1); 60 | } 61 | return -1; 62 | } 63 | 64 | @Override 65 | public void write(T obj) { 66 | lookupData.put(new IdentityWrapper<>(obj), written++); 67 | } 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/impl/reference/SetWriter.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2013 CWI 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * 10 | * * Michael Steindorfer - Michael.Steindorfer@cwi.nl - CWI 11 | * * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI 12 | * * Paul Klint - Paul.Klint@cwi.nl - CWI 13 | * 14 | * Based on code by: 15 | * 16 | * * Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation 17 | *******************************************************************************/ 18 | package io.usethesource.vallang.impl.reference; 19 | 20 | import java.util.HashSet; 21 | import java.util.Iterator; 22 | import java.util.function.Supplier; 23 | 24 | import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 25 | 26 | import io.usethesource.vallang.ISet; 27 | import io.usethesource.vallang.ISetWriter; 28 | import io.usethesource.vallang.IValue; 29 | import io.usethesource.vallang.IWriter; 30 | import io.usethesource.vallang.exceptions.FactTypeUseException; 31 | import io.usethesource.vallang.type.Type; 32 | import io.usethesource.vallang.type.TypeFactory; 33 | 34 | /*package*/ class SetWriter implements ISetWriter { 35 | protected final HashSet setContent; 36 | protected Type eltType; 37 | protected @MonotonicNonNull Set constructedSet = null; 38 | 39 | /*package*/ SetWriter() { 40 | super(); 41 | this.eltType = TypeFactory.getInstance().voidType(); 42 | setContent = new HashSet<>(); 43 | } 44 | 45 | @Override 46 | public Iterator iterator() { 47 | return setContent.iterator(); 48 | } 49 | 50 | private void put(IValue elem) { 51 | updateType(elem); 52 | setContent.add(elem); 53 | } 54 | 55 | private void updateType(IValue elem) { 56 | eltType = eltType.lub(elem.getType()); 57 | } 58 | 59 | @Override 60 | public void insertTuple(IValue... fields) { 61 | insert(ValueFactory.getInstance().tuple(fields)); 62 | } 63 | 64 | @Override 65 | public void insert(IValue... elems) throws FactTypeUseException { 66 | checkMutation(); 67 | 68 | for (IValue elem : elems) { 69 | put(elem); 70 | } 71 | } 72 | 73 | @Override 74 | public void insertAll(Iterable collection) throws FactTypeUseException { 75 | checkMutation(); 76 | 77 | for (IValue v : collection) { 78 | put(v); 79 | } 80 | } 81 | 82 | @Override 83 | public ISet done() { 84 | if (constructedSet == null) { 85 | constructedSet = new Set(eltType, setContent); 86 | } 87 | 88 | return constructedSet; 89 | } 90 | 91 | private void checkMutation() { 92 | if (constructedSet != null) { 93 | throw new UnsupportedOperationException("Mutation of a finalized set is not supported."); 94 | } 95 | } 96 | 97 | @Override 98 | public Supplier> supplier() { 99 | return () -> ValueFactory.getInstance().setWriter(); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/util/StructuredIValueVisitor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, Davy Landman, Centrum Wiskunde & Informatica (CWI) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | * 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | */ 13 | package io.usethesource.vallang.io.binary.util; 14 | 15 | import io.usethesource.vallang.IBool; 16 | import io.usethesource.vallang.IConstructor; 17 | import io.usethesource.vallang.IDateTime; 18 | import io.usethesource.vallang.IInteger; 19 | import io.usethesource.vallang.IList; 20 | import io.usethesource.vallang.IMap; 21 | import io.usethesource.vallang.INode; 22 | import io.usethesource.vallang.IRational; 23 | import io.usethesource.vallang.IReal; 24 | import io.usethesource.vallang.ISet; 25 | import io.usethesource.vallang.ISourceLocation; 26 | import io.usethesource.vallang.IString; 27 | import io.usethesource.vallang.ITuple; 28 | import io.usethesource.vallang.IValue; 29 | 30 | public interface StructuredIValueVisitor { 31 | 32 | void enterNamedValues(String[] names, int numberOfNestedValues) throws E; 33 | void leaveNamedValue() throws E; 34 | 35 | boolean enterConstructor(IConstructor cons, int children) throws E; 36 | void enterConstructorKeywordParameters() throws E; 37 | void leaveConstructor(IValue cons) throws E; 38 | 39 | boolean enterNode(INode node, int children) throws E; 40 | void enterNodeKeywordParameters() throws E; 41 | void leaveNode(IValue node) throws E; 42 | 43 | boolean enterList(IList lst, int children) throws E; 44 | void leaveList(IValue lst) throws E; 45 | 46 | boolean enterSet(ISet set, int elements) throws E; 47 | void leaveSet(IValue set) throws E; 48 | 49 | boolean enterMap(IMap map, int elements) throws E; 50 | void leaveMap(IValue map) throws E; 51 | 52 | boolean enterTuple(ITuple tuple, int arity) throws E; 53 | void leaveTuple(IValue tuple) throws E; 54 | 55 | void visitString(IString val) throws E; 56 | void visitInteger(IInteger val) throws E; 57 | void visitReal(IReal val) throws E; 58 | void visitRational(IRational val) throws E; 59 | void visitSourceLocation(ISourceLocation val) throws E; 60 | void visitBoolean(IBool val) throws E; 61 | void visitDateTime(IDateTime val) throws E; 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/visitors/BottomUpVisitor.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2008 CWI. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * jurgen@vinju.org 10 | 11 | *******************************************************************************/ 12 | package io.usethesource.vallang.visitors; 13 | 14 | import java.util.Map.Entry; 15 | 16 | import io.usethesource.vallang.IConstructor; 17 | import io.usethesource.vallang.IExternalValue; 18 | import io.usethesource.vallang.IList; 19 | import io.usethesource.vallang.IListWriter; 20 | import io.usethesource.vallang.IMap; 21 | import io.usethesource.vallang.IMapWriter; 22 | import io.usethesource.vallang.INode; 23 | import io.usethesource.vallang.ISet; 24 | import io.usethesource.vallang.ISetWriter; 25 | import io.usethesource.vallang.ITuple; 26 | import io.usethesource.vallang.IValue; 27 | import io.usethesource.vallang.IValueFactory; 28 | 29 | /** 30 | * This visitor will apply another visitor in a bottom-up fashion to an IValue 31 | * 32 | */ 33 | public class BottomUpVisitor extends VisitorAdapter { 34 | protected IValueFactory fFactory; 35 | 36 | public BottomUpVisitor(IValueVisitor visitor, IValueFactory factory) { 37 | super(visitor); 38 | this.fFactory = factory; 39 | } 40 | 41 | @Override 42 | public T visitNode(INode o) throws E { 43 | for (int i = 0; i < o.arity(); i++) { 44 | o.get(i).accept(this); 45 | } 46 | 47 | return fVisitor.visitNode(o); 48 | } 49 | 50 | public T visitConstructor(IConstructor o) throws E { 51 | for (int i = 0; i < o.arity(); i++) { 52 | o.get(i).accept(this); 53 | } 54 | 55 | return fVisitor.visitConstructor(o); 56 | } 57 | 58 | @Override 59 | public T visitList(IList o) throws E { 60 | IListWriter w = fFactory.listWriter(); 61 | for (IValue elem : o) { 62 | elem.accept(this); 63 | } 64 | 65 | return fVisitor.visitList(w.done()); 66 | } 67 | 68 | @Override 69 | public T visitSet(ISet o) throws E { 70 | ISetWriter w = fFactory.setWriter(); 71 | for (IValue elem : o) { 72 | elem.accept(this); 73 | } 74 | 75 | return fVisitor.visitSet(w.done()); 76 | } 77 | 78 | @Override 79 | public T visitMap(IMap o) throws E { 80 | IMapWriter w = fFactory.mapWriter(); 81 | 82 | for (Entry entry : (Iterable>) () -> o.entryIterator()) { 83 | entry.getKey().accept(this); 84 | entry.getValue().accept(this); 85 | } 86 | 87 | return fVisitor.visitMap(w.done()); 88 | } 89 | 90 | @Override 91 | public T visitTuple(ITuple o) throws E { 92 | for (int i = 0; i < o.arity(); i++) { 93 | o.get(i).accept(this); 94 | } 95 | 96 | return fVisitor.visitTuple(o); 97 | } 98 | 99 | public T visitExternal(IExternalValue externalValue) throws E { 100 | return fVisitor.visitExternal(externalValue); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/visitors/VisitorAdapter.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2008 CWI. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * jurgen@vinju.org 10 | *******************************************************************************/ 11 | package io.usethesource.vallang.visitors; 12 | 13 | import io.usethesource.vallang.IBool; 14 | import io.usethesource.vallang.IConstructor; 15 | import io.usethesource.vallang.IDateTime; 16 | import io.usethesource.vallang.IExternalValue; 17 | import io.usethesource.vallang.IInteger; 18 | import io.usethesource.vallang.IList; 19 | import io.usethesource.vallang.IMap; 20 | import io.usethesource.vallang.INode; 21 | import io.usethesource.vallang.IRational; 22 | import io.usethesource.vallang.IReal; 23 | import io.usethesource.vallang.ISet; 24 | import io.usethesource.vallang.ISourceLocation; 25 | import io.usethesource.vallang.IString; 26 | import io.usethesource.vallang.ITuple; 27 | 28 | /** 29 | * Extend this class to easily create a reusable generic visitor implementation. 30 | * 31 | */ 32 | public abstract class VisitorAdapter implements IValueVisitor { 33 | protected IValueVisitor fVisitor; 34 | 35 | public VisitorAdapter(IValueVisitor visitor) { 36 | this.fVisitor = visitor; 37 | } 38 | 39 | @Override 40 | public T visitReal(IReal o) throws E { 41 | return fVisitor.visitReal(o); 42 | } 43 | 44 | @Override 45 | public T visitInteger(IInteger o) throws E { 46 | return fVisitor.visitInteger(o); 47 | } 48 | 49 | @Override 50 | public T visitRational(IRational o) throws E { 51 | return fVisitor.visitRational(o); 52 | } 53 | 54 | @Override 55 | public T visitList(IList o) throws E { 56 | return fVisitor.visitList(o); 57 | } 58 | 59 | @Override 60 | public T visitMap(IMap o) throws E { 61 | return fVisitor.visitMap(o); 62 | } 63 | 64 | @Override 65 | public T visitSet(ISet o) throws E { 66 | return fVisitor.visitSet(o); 67 | } 68 | 69 | @Override 70 | public T visitSourceLocation(ISourceLocation o) throws E { 71 | return fVisitor.visitSourceLocation(o); 72 | } 73 | 74 | @Override 75 | public T visitString(IString o) throws E { 76 | return fVisitor.visitString(o); 77 | } 78 | 79 | @Override 80 | public T visitNode(INode o) throws E { 81 | return fVisitor.visitNode(o); 82 | } 83 | 84 | @Override 85 | public T visitConstructor(IConstructor o) throws E { 86 | return fVisitor.visitConstructor(o); 87 | } 88 | 89 | @Override 90 | public T visitTuple(ITuple o) throws E { 91 | return fVisitor.visitTuple(o); 92 | } 93 | 94 | @Override 95 | public T visitBoolean(IBool o) throws E { 96 | return fVisitor.visitBoolean(o); 97 | } 98 | 99 | @Override 100 | public T visitDateTime(IDateTime o) throws E { 101 | return fVisitor.visitDateTime(o); 102 | } 103 | 104 | @Override 105 | public T visitExternal(IExternalValue externalValue) throws E { 106 | return fVisitor.visitExternal(externalValue); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/IListWriter.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2007 IBM Corporation. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation 10 | 11 | *******************************************************************************/ 12 | 13 | package io.usethesource.vallang; 14 | 15 | import io.usethesource.vallang.exceptions.FactTypeUseException; 16 | 17 | /** 18 | * This interface allows to gather the elements of a list efficiently and in a specific order. 19 | * When all elements have been gathered the done() method can be used to obtain an immutable IList 20 | * with the gathered elements in the specified order. 21 | * 22 | * Note: implementations are not required to guarantee thread-safe access to the writer object. 23 | */ 24 | public interface IListWriter extends IWriter { 25 | 26 | /** 27 | * Inserts elements at a specific position, keeping the argument in order of appearance. 28 | * 29 | * @param index 30 | * @param value an array of elements to insert . 31 | * @throws FactTypeUseException when done() was called before or when the elements have an incompatible type. 32 | * @throws IndexOutOfBoundsException 33 | */ 34 | public void insertAt(int index, IValue... value); 35 | 36 | /** 37 | * Inserts elements in front, keeping the argument in order of appearance. 38 | * 39 | * @param elems an array of elements to insert 40 | * @param start index to start copying elements from 41 | * @param length amount of elements to copy from the array 42 | * 43 | * @throws FactTypeUseException when done() was called before or when the elements have an incompatible type. 44 | * @throws IndexOutOfBoundsException 45 | */ 46 | public void insert(IValue[] elems, int start, int length); 47 | 48 | /** 49 | * Inserts elements at a specific position, keeping the argument in order of appearance. 50 | * 51 | * @param index place to insert elements at 52 | * @param elems an array of elements to insert 53 | * @param start index to start copying elements from 54 | * @param length amount of elements to copy from the array 55 | * 56 | * @throws FactTypeUseException when done() was called before or when the elements have an incompatible type. 57 | * @throws IndexOutOfBoundsException 58 | */ 59 | public void insertAt(int index, IValue[] elems, int start, int length); 60 | 61 | /** 62 | * Replaces an existing element at index in the list. 63 | * @param index the location where to replace the element 64 | * @param elem the new element 65 | * @throws FactTypeUseException when the type of the new element is not a subtype of the element type 66 | * @throws IndexOutOfBoundsException 67 | * @returns the replaced element 68 | */ 69 | public IValue replaceAt(int index, IValue elem); 70 | 71 | /** 72 | * Return the ith element of the list. 73 | * 74 | * @param i 75 | * @return the ith element of the list 76 | * @throws IndexOutOfBoundsException when i < 0 or i >= IList.length 77 | */ 78 | public IValue get(int i); 79 | 80 | /** 81 | * @return the number of elements in the list 82 | */ 83 | public int length(); 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/visitors/BottomUpTransformer.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2008 CWI. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * jurgen@vinju.org 10 | 11 | *******************************************************************************/ 12 | package io.usethesource.vallang.visitors; 13 | 14 | import java.util.Map.Entry; 15 | import io.usethesource.vallang.IConstructor; 16 | import io.usethesource.vallang.IExternalValue; 17 | import io.usethesource.vallang.IList; 18 | import io.usethesource.vallang.IListWriter; 19 | import io.usethesource.vallang.IMap; 20 | import io.usethesource.vallang.IMapWriter; 21 | import io.usethesource.vallang.INode; 22 | import io.usethesource.vallang.ISet; 23 | import io.usethesource.vallang.ISetWriter; 24 | import io.usethesource.vallang.ITuple; 25 | import io.usethesource.vallang.IValue; 26 | import io.usethesource.vallang.IValueFactory; 27 | 28 | /** 29 | * This visitor will apply another visitor in a bottom-up fashion to an IValue 30 | * 31 | */ 32 | public class BottomUpTransformer extends VisitorAdapter { 33 | protected IValueFactory fFactory; 34 | 35 | public BottomUpTransformer(IValueVisitor visitor, IValueFactory factory) { 36 | super(visitor); 37 | this.fFactory = factory; 38 | } 39 | 40 | @Override 41 | public IValue visitNode(INode o) throws E { 42 | for (int i = 0; i < o.arity(); i++) { 43 | o = o.set(i, o.get(i).accept(this)); 44 | } 45 | return fVisitor.visitNode(o); 46 | } 47 | 48 | @Override 49 | public IValue visitConstructor(IConstructor o) throws E { 50 | for (int i = 0; i < o.arity(); i++) { 51 | o = o.set(i, o.get(i).accept(this)); 52 | } 53 | 54 | return fVisitor.visitConstructor(o); 55 | } 56 | 57 | @Override 58 | public IValue visitList(IList o) throws E { 59 | IListWriter w = fFactory.listWriter(); 60 | for (IValue elem : o) { 61 | w.append(elem.accept(this)); 62 | } 63 | 64 | return fVisitor.visitList(w.done()); 65 | } 66 | 67 | @Override 68 | public IValue visitSet(ISet o) throws E { 69 | ISetWriter w = fFactory.setWriter(); 70 | for (IValue elem : o) { 71 | w.insert(elem.accept(this)); 72 | } 73 | 74 | return fVisitor.visitSet(w.done()); 75 | } 76 | 77 | @Override 78 | public IValue visitMap(IMap o) throws E { 79 | IMapWriter w = fFactory.mapWriter(); 80 | for (Entry entry : (Iterable>) () -> o.entryIterator()) { 81 | w.put(entry.getKey().accept(this), entry.getValue().accept(this)); 82 | } 83 | 84 | return fVisitor.visitMap(w.done()); 85 | } 86 | 87 | @Override 88 | public IValue visitTuple(ITuple o) throws E { 89 | for (int i = 0; i < o.arity(); i++) { 90 | o = o.set(i, o.get(i).accept(this)); 91 | } 92 | 93 | return fVisitor.visitTuple(o); 94 | } 95 | 96 | @Override 97 | public IValue visitExternal(IExternalValue externalValue) throws E { 98 | return fVisitor.visitExternal(externalValue); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/IWithKeywordParameters.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2008-2013 CWI 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * 10 | * * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI 11 | * * Michael Steindorfer - Michael.Steindorfer@cwi.nl - CWI 12 | *******************************************************************************/ 13 | package io.usethesource.vallang; 14 | 15 | import java.util.Map; 16 | import java.util.Set; 17 | import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; 18 | import org.checkerframework.checker.nullness.qual.Nullable; 19 | import io.usethesource.vallang.exceptions.FactTypeUseException; 20 | 21 | public interface IWithKeywordParameters { 22 | 23 | /** 24 | * Get the value of a parmeter 25 | * 26 | * @param label identifies the parameter 27 | * @return a value if the parameter has a value on this node or null otherwise 28 | */ 29 | public X getParameter(String label); 30 | 31 | /** 32 | * Set the value of an parameter 33 | * 34 | * @param label identifies the parameter 35 | * @param newValue the new value for the parameter 36 | * @return a new node where the value of the parameter is replaced (if previously present) or newly added 37 | * @throws FactTypeUseException when the type of the new value is not comparable to the old parameter value 38 | */ 39 | public T setParameter(String label, IValue newValue); 40 | 41 | /** 42 | * Unset the value of an parameter 43 | * 44 | * @param label identifies the parameter 45 | * @return a new node where the value of the parameter is not present anymore 46 | */ 47 | public T unsetParameter(String label); 48 | 49 | /** 50 | * Unset the values of all parameters 51 | * 52 | * @param label identifies the parameter 53 | * @return a new node where the value of all keyword parameters are unset 54 | */ 55 | public T unsetAll(); 56 | 57 | /** 58 | * Check whether a certain parameter is set. 59 | * 60 | * @param label identifies the parameter 61 | * @return true iff the parameter has a value on this node 62 | * @throws FactTypeUseException when no parameter with this label is defined for this type of node. 63 | */ 64 | @EnsuresNonNullIf(expression="getParameter(#1)", result=true) 65 | public boolean hasParameter(String label); 66 | 67 | /** 68 | * Check whether any parameters are present. 69 | */ 70 | public boolean hasParameters(); 71 | 72 | /** 73 | * @return a set of parameter names 74 | */ 75 | public Set getParameterNames(); 76 | 77 | /** 78 | * @return an unmodifiable map for the keyword parameters 79 | */ 80 | Map getParameters(); 81 | 82 | /** 83 | * 84 | * @param params 85 | * @return 86 | */ 87 | T setParameters(Map params); 88 | 89 | /** 90 | * Given an arbitrary other IWithKeywordParameters, compare the values of the 91 | * parameters. 92 | * @param other 93 | * @return true iff the parameters are the same (same labels, same values) 94 | */ 95 | > boolean equalParameters(U other); 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/util/WindowSizes.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, Davy Landman, Centrum Wiskunde & Informatica (CWI) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | * 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | */ 13 | package io.usethesource.vallang.io.binary.util; 14 | 15 | public class WindowSizes { 16 | public final int uriWindow; 17 | public final int typeWindow; 18 | public final int valueWindow; 19 | public final int stringsWindow; 20 | 21 | 22 | /** 23 | * @param typeWindow the size of the window for type-reuse. normally 1024 should be enough, when storing parse trees, use a larger number (10_000 for example) 24 | * @param valueWindow the size of the window for value-reuse. normally 100_000 should be enough, when expecting large values, you can use a larger number 25 | * @param uriWindow the size of the window for source location reuse. normally 50_000 should be more than enough, when you expect a lot of source locations, increase this number 26 | */ 27 | public WindowSizes(int valueWindow, int uriWindow, int typeWindow) { 28 | this(valueWindow, uriWindow, typeWindow, 1_000); 29 | } 30 | /** 31 | * @param typeWindow the size of the window for type-reuse. normally 1024 should be enough, when storing parse trees, use a larger number (10_000 for example) 32 | * @param valueWindow the size of the window for value-reuse. normally 100_000 should be enough, when expecting large values, you can use a larger number 33 | * @param uriWindow the size of the window for source location reuse. normally 50_000 should be more than enough, when you expect a lot of source locations, increase this number 34 | * @param stringsWindow the size of the window for the wire strings, normally not more than a 1_000 35 | */ 36 | public WindowSizes(int valueWindow, int uriWindow, int typeWindow, int stringsWindow) { 37 | this.stringsWindow = stringsWindow; 38 | this.typeWindow = typeWindow; 39 | this.uriWindow = uriWindow; 40 | this.valueWindow = valueWindow; 41 | } 42 | public static final WindowSizes NO_WINDOW = new WindowSizes(0, 0, 0, 0); 43 | public static final WindowSizes TINY_WINDOW = new WindowSizes(500, 200, 100, 500); 44 | public static final WindowSizes SMALL_WINDOW = new WindowSizes(10_000, 1_000, 800, 5_000); 45 | public static final WindowSizes NORMAL_WINDOW = new WindowSizes(200_000, 40_000, 5_000, 40_000); 46 | } -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/util/RotatingQueue.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2009 Centrum Wiskunde en Informatica (CWI) 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * Arnold Lankamp - interfaces and implementation 10 | *******************************************************************************/ 11 | package io.usethesource.vallang.util; 12 | 13 | import org.checkerframework.checker.nullness.qual.Nullable; 14 | 15 | /** 16 | * A simple (fast) queue. 17 | * 18 | * @author Arnold Lankamp 19 | * 20 | * @param The value type. 21 | */ 22 | public final class RotatingQueue{ 23 | private static final int DEFAULT_CAPACITY = 16; 24 | private static final int DEFAULT_CAPACITY_MASK = DEFAULT_CAPACITY - 1; 25 | 26 | private @Nullable T[] queue; 27 | private int capacity; 28 | private int capacityMask; 29 | private int nextPutIndex; 30 | private int getIndex; 31 | 32 | /** 33 | * Constructor. 34 | */ 35 | @SuppressWarnings("unchecked") 36 | public RotatingQueue(){ 37 | super(); 38 | 39 | capacity = DEFAULT_CAPACITY; 40 | capacityMask = DEFAULT_CAPACITY_MASK; 41 | 42 | queue = (T[]) new Object[capacity]; 43 | 44 | nextPutIndex = 1; 45 | getIndex = 0; 46 | } 47 | 48 | private void ensureCapacity(){ 49 | if(nextPutIndex == getIndex){ 50 | int size = capacity; 51 | capacity <<= 1; 52 | capacityMask = capacity - 1; 53 | @SuppressWarnings("unchecked") 54 | T[] newQueue = (T[]) new Object[capacity]; 55 | if(getIndex == 0){ 56 | System.arraycopy(queue, 0, newQueue, 0, queue.length); 57 | 58 | nextPutIndex = size; 59 | }else{ 60 | int numElemsTillEnd = size - getIndex; 61 | System.arraycopy(queue, getIndex, newQueue, 0, numElemsTillEnd); 62 | System.arraycopy(queue, 0, newQueue, numElemsTillEnd, getIndex); 63 | 64 | getIndex = 0; 65 | nextPutIndex = size; 66 | } 67 | 68 | queue = newQueue; 69 | } 70 | } 71 | 72 | /** 73 | * Enqueues the given element. 74 | * 75 | * @param element 76 | * The element to enqueue. 77 | */ 78 | public void put(T element){ 79 | ensureCapacity(); 80 | 81 | queue[nextPutIndex] = element; 82 | 83 | nextPutIndex = (nextPutIndex + 1) & capacityMask; 84 | } 85 | 86 | /** 87 | * Check if the queue contains any elements. 88 | * 89 | * @return True if the queue contains any elements; false otherwise. 90 | */ 91 | public boolean isEmpty(){ 92 | return (nextPutIndex == ((getIndex + 1) & capacityMask)); 93 | } 94 | 95 | /** 96 | * Returns and removes the next element from the queue. 97 | * 98 | * @return The next element from the queue; null if the queue was empty. 99 | */ 100 | public @Nullable T get(){ 101 | if(isEmpty()) { 102 | return null; 103 | } 104 | 105 | getIndex = (getIndex + 1) & capacityMask; 106 | T element = queue[getIndex]; 107 | queue[getIndex] = null; 108 | 109 | return element; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/issues/RegressionTests.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.issues; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertFalse; 5 | import static org.junit.jupiter.api.Assertions.assertTrue; 6 | 7 | import java.io.IOException; 8 | import java.io.Reader; 9 | import java.io.StringReader; 10 | import java.io.StringWriter; 11 | 12 | import org.junit.jupiter.params.ParameterizedTest; 13 | import org.junit.jupiter.params.provider.ArgumentsSource; 14 | 15 | import io.usethesource.vallang.GivenValue; 16 | import io.usethesource.vallang.IConstructor; 17 | import io.usethesource.vallang.ISet; 18 | import io.usethesource.vallang.ISourceLocation; 19 | import io.usethesource.vallang.IString; 20 | import io.usethesource.vallang.IValueFactory; 21 | import io.usethesource.vallang.ValueProvider; 22 | import io.usethesource.vallang.io.StandardTextReader; 23 | import io.usethesource.vallang.io.StandardTextWriter; 24 | import io.usethesource.vallang.type.Type; 25 | import io.usethesource.vallang.type.TypeFactory; 26 | import io.usethesource.vallang.type.TypeStore; 27 | 28 | public class RegressionTests { 29 | 30 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 31 | public void iTupleCastExceptionsInEquals(IValueFactory vf, 32 | @GivenValue("{<5,0>,<1330107671,7>,<0,0>}") ISet rel, 33 | @GivenValue("{6,-1426731573,0}") ISet set) { 34 | // these calls would throw ClassCastExceptions because the 35 | // receiver or the argument was specialized as a binary relation 36 | // and contained tuples, while the other was not. Still a cast to 37 | // ITuple was performed. 38 | 39 | // To trigger the bug both sets had to be of equal arity, 40 | // to avoid short-circuiting the equality check on that. 41 | 42 | if (!rel.isEmpty() && !set.isEmpty()) { 43 | assertTrue(!rel.equals(set)); 44 | assertTrue(!set.equals(rel)); 45 | } 46 | } 47 | 48 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 49 | void toStringSourceLocationEqualsTextWriter(IValueFactory vf, ISourceLocation loc) throws IOException { 50 | StandardTextWriter writer = new StandardTextWriter(false); 51 | StringWriter target = new StringWriter(); 52 | writer.write(loc, target); 53 | assertEquals(target.toString(), loc.toString()); 54 | } 55 | 56 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 57 | void keywordFieldsMakeConstructorsDifferent(IValueFactory vf, TypeFactory tf, TypeStore store) { 58 | Type X = tf.abstractDataType(store, "X"); 59 | Type cons = tf.constructor(store, X, "x"); 60 | store.declareKeywordParameter(X, "name", tf.stringType()); 61 | 62 | IConstructor cons1 = vf.constructor(cons).asWithKeywordParameters().setParameter("name", vf.string("paul")); 63 | IConstructor cons2 = vf.constructor(cons).asWithKeywordParameters().setParameter("name", vf.string("jurgen")); 64 | 65 | assertFalse(cons1.equals(cons2)); 66 | } 67 | 68 | private IString readString(IValueFactory valueFactory, TypeStore typeStore, String s) throws IOException { 69 | Reader reader = new StringReader(s); 70 | StandardTextReader textReader = new StandardTextReader(); 71 | return (IString) textReader.read(valueFactory, typeStore, TypeFactory.getInstance().stringType(), reader); 72 | 73 | } 74 | 75 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 76 | void escapeNormalCharacters(IValueFactory valueFactory, TypeStore typeStore) throws IOException { 77 | IString s = readString(valueFactory, typeStore, "\"\\$\""); 78 | assertEquals("$", s.getValue()); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/impl/primitive/BoolValue.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2012-2013 Centrum Wiskunde en Informatica (CWI) 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * * Arnold Lankamp - interfaces and implementation 10 | * * Jurgen Vinju 11 | * * Michael Steindorfer - Michael.Steindorfer@cwi.nl - CWI 12 | *******************************************************************************/ 13 | package io.usethesource.vallang.impl.primitive; 14 | 15 | import org.checkerframework.checker.nullness.qual.Nullable; 16 | 17 | import io.usethesource.vallang.IBool; 18 | import io.usethesource.vallang.type.Type; 19 | import io.usethesource.vallang.type.TypeFactory; 20 | 21 | /*package*/ abstract class BoolValue implements IBool { 22 | /*package*/ static final BoolValue TRUE = new BoolValue() { 23 | @Override 24 | public boolean getValue() { 25 | return true; 26 | } 27 | 28 | public int hashCode() { 29 | return 1; 30 | } 31 | 32 | @Override 33 | public IBool not() { 34 | return FALSE; 35 | } 36 | 37 | @Override 38 | public IBool and(IBool other) { 39 | return other; 40 | } 41 | 42 | @Override 43 | public IBool or(IBool other) { 44 | return this; 45 | } 46 | 47 | @Override 48 | public IBool xor(IBool other) { 49 | return other == this ? FALSE : TRUE; 50 | } 51 | 52 | @Override 53 | public IBool implies(IBool other) { 54 | return other; 55 | } 56 | 57 | }; 58 | 59 | /*package*/ static final BoolValue FALSE = new BoolValue() { 60 | @Override 61 | public boolean getValue() { 62 | return false; 63 | } 64 | 65 | @Override 66 | public IBool not() { 67 | return TRUE; 68 | } 69 | 70 | @Override 71 | public IBool and(IBool other) { 72 | return this; 73 | } 74 | 75 | @Override 76 | public IBool or(IBool other) { 77 | return other; 78 | } 79 | 80 | @Override 81 | public IBool xor(IBool other) { 82 | return other; 83 | } 84 | 85 | @Override 86 | public IBool implies(IBool other) { 87 | return TRUE; 88 | } 89 | 90 | public int hashCode() { 91 | return 2; 92 | } 93 | }; 94 | private static final Type BOOL_TYPE = TypeFactory.getInstance().boolType(); 95 | 96 | private BoolValue() { 97 | super(); 98 | } 99 | 100 | /*package*/ static BoolValue getBoolValue(boolean bool) { 101 | return bool ? TRUE : FALSE; 102 | } 103 | 104 | public abstract int hashCode(); 105 | 106 | @Override 107 | public String toString() { 108 | return defaultToString(); 109 | } 110 | 111 | public boolean equals(@Nullable Object o) { 112 | return this == o; 113 | } 114 | 115 | @Override 116 | public Type getType() { 117 | return BOOL_TYPE; 118 | } 119 | 120 | @Override 121 | public IBool equivalent(IBool other) { 122 | return other == this ? TRUE : this; 123 | } 124 | 125 | @Override 126 | public String getStringRepresentation() { 127 | return toString(); 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/util/DelayedCompressionOutputStream.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016, Davy Landman, Centrum Wiskunde & Informatica (CWI) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | * 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | */ 13 | package io.usethesource.vallang.io.binary.util; 14 | 15 | import java.io.IOException; 16 | import java.io.OutputStream; 17 | 18 | public class DelayedCompressionOutputStream extends OutputStream { 19 | 20 | private static final int COMPRESS_AFTER = 4*1024; 21 | private byte[] buffer; 22 | private int written; 23 | private OutputStream out; 24 | private WrappingCompressorFunction compress; 25 | private int compressHeader; 26 | 27 | @FunctionalInterface 28 | public interface WrappingCompressorFunction { 29 | OutputStream wrap(OutputStream toWrap) throws IOException; 30 | } 31 | 32 | public DelayedCompressionOutputStream(OutputStream out, int compressHeader, WrappingCompressorFunction compress) throws IOException { 33 | this.out = out; 34 | this.compressHeader = compressHeader; 35 | this.compress = compress; 36 | buffer = new byte[COMPRESS_AFTER]; 37 | written = 0; 38 | } 39 | 40 | @Override 41 | public void flush() throws IOException { 42 | if (written != -1) { 43 | out.write(0); // no compression 44 | out.write(buffer, 0, written); 45 | written = -1; 46 | } 47 | out.flush(); 48 | } 49 | 50 | @Override 51 | public void close() throws IOException { 52 | try (OutputStream out2 = out) { 53 | flush(); 54 | } 55 | } 56 | 57 | @Override 58 | public void write(int b) throws IOException { 59 | write(new byte[] { (byte)b }, 0, 1); // normally shouldn't occur, so take slow path 60 | } 61 | @Override 62 | public void write(byte[] b) throws IOException { 63 | write(b, 0, b.length); 64 | } 65 | 66 | @Override 67 | public void write(byte[] b, int off, int len) throws IOException { 68 | if (written != -1) { 69 | if (written + len < COMPRESS_AFTER) { 70 | // append buffer 71 | System.arraycopy(b, off, buffer, written, len); 72 | written += len; 73 | return; 74 | } 75 | else { 76 | // buffer overflowed, enough data for compression overhead 77 | out.write(compressHeader); 78 | out = compress.wrap(out); 79 | out.write(buffer, 0, written); 80 | written = -1; 81 | } 82 | } 83 | out.write(b, off, len); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/impl/persistent/ValueCollectors.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.impl.persistent; 2 | 3 | import static io.usethesource.capsule.util.stream.CapsuleCollectors.UNORDERED; 4 | 5 | import java.util.Collections; 6 | import java.util.function.BiConsumer; 7 | import java.util.function.BinaryOperator; 8 | import java.util.function.Function; 9 | import java.util.stream.Collector; 10 | 11 | import io.usethesource.capsule.Set; 12 | import io.usethesource.capsule.SetMultimap; 13 | import io.usethesource.capsule.util.stream.DefaultCollector; 14 | import io.usethesource.vallang.IList; 15 | import io.usethesource.vallang.ISet; 16 | import io.usethesource.vallang.ITuple; 17 | import io.usethesource.vallang.IValue; 18 | import io.usethesource.vallang.util.AbstractTypeBag; 19 | 20 | /*package*/ class ValueCollectors { 21 | 22 | @SuppressWarnings("unchecked") 23 | public static Collector toSet() { 24 | 25 | class SetStruct { 26 | AbstractTypeBag elementTypeBag = AbstractTypeBag.of(); 27 | Set.Transient set = Set.Transient.of(); 28 | } 29 | 30 | /** extract key/value from type {@code T} and insert into multimap */ 31 | final BiConsumer accumulator = (struct, element) -> { 32 | if (struct.set.__insert(element)) { 33 | struct.elementTypeBag = struct.elementTypeBag.increase(element.getType()); 34 | } 35 | }; 36 | 37 | return new DefaultCollector<>(SetStruct::new, accumulator, unsupportedCombiner(), 38 | struct -> PersistentSetFactory.from(struct.elementTypeBag, 39 | (Set.Immutable) struct.set.freeze()), 40 | UNORDERED); 41 | } 42 | 43 | public static Collector toList() { 44 | return new DefaultCollector<>( 45 | ValueFactory.getInstance()::listWriter, 46 | (w,e) -> w.append(e), 47 | unsupportedCombiner(), 48 | w -> w.done(), 49 | Collections.emptySet() 50 | ); 51 | } 52 | 53 | 54 | /** 55 | * @param keyLabel optional label of first column 56 | * @param valueLabel optional label of second column 57 | */ 58 | @SuppressWarnings("unchecked") 59 | public static Collector toSetMultimap( 60 | Function keyMapper, 61 | Function valueMapper) { 62 | 63 | class SetMultimapStruct { 64 | AbstractTypeBag keyTypeBag = AbstractTypeBag.of(); 65 | AbstractTypeBag valTypeBag = AbstractTypeBag.of(); 66 | SetMultimap.Transient map = SetMultimap.Transient.of(); 67 | } 68 | 69 | /** extract key/value from type {@code T} and insert into multimap */ 70 | final BiConsumer accumulator = (struct, element) -> { 71 | final K key = keyMapper.apply(element); 72 | final V val = valueMapper.apply(element); 73 | 74 | if (struct.map.__insert(key, val)) { 75 | struct.keyTypeBag = struct.keyTypeBag.increase(key.getType()); 76 | struct.valTypeBag = struct.valTypeBag.increase(val.getType()); 77 | } 78 | }; 79 | 80 | return new DefaultCollector<>(SetMultimapStruct::new, accumulator, 81 | unsupportedCombiner(), struct -> PersistentSetFactory.from(struct.keyTypeBag, 82 | struct.valTypeBag, (SetMultimap.Immutable) struct.map.freeze()), 83 | UNORDERED); 84 | } 85 | 86 | private static BinaryOperator unsupportedCombiner() { 87 | return (u, v) -> { 88 | throw new UnsupportedOperationException("Merging is not yet supported."); 89 | }; 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/io/binary/util/ByteBufferOutputStream.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.io.binary.util; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | import java.nio.ByteBuffer; 6 | 7 | public abstract class ByteBufferOutputStream extends OutputStream { 8 | 9 | protected ByteBuffer target; 10 | protected boolean closed = false; 11 | public ByteBufferOutputStream(ByteBuffer target) { 12 | this.target = target; 13 | } 14 | 15 | 16 | 17 | public ByteBuffer getBuffer() { 18 | return target; 19 | } 20 | 21 | /*** 22 | * Flush the buffer (that has been flipped already) and return the same buffer (but cleared) or a new buffer for the next round. 23 | * @param toflush the flipped buffer to flush 24 | * @return a new or the same buffer that has room available for writing. 25 | * @throws IOException 26 | */ 27 | protected abstract ByteBuffer flush(ByteBuffer toflush) throws IOException; 28 | 29 | @Override 30 | public void flush() throws IOException { 31 | if (closed) { 32 | throw new IOException("Stream closed"); 33 | } 34 | 35 | target.flip(); 36 | if (target.hasRemaining()) { 37 | target = flush(target); 38 | if (!target.hasRemaining()) { 39 | throw new IOException("flush implementation didn't correctly provide a new buffer to write to: " + target); 40 | } 41 | } 42 | else { 43 | // the buffer was empty, so flush was called on an already flushed stream 44 | // so we'll reset the buffer to make sure we don't continue with empty buffer 45 | target.clear(); 46 | } 47 | assert target.hasRemaining(): "after a flush, we should have a buffer with some room. (it was: " + target + ")"; 48 | } 49 | 50 | @Override 51 | public void close() throws IOException { 52 | if (!closed ) { 53 | try { 54 | flush(); 55 | } 56 | finally { 57 | closed = true; 58 | } 59 | } 60 | } 61 | 62 | 63 | @Override 64 | public void write(int b) throws IOException { 65 | if (closed) { 66 | throw new IOException("Stream closed"); 67 | } 68 | if (!target.hasRemaining()) { 69 | flush(); 70 | } 71 | target.put((byte)(b & 0xFF)); 72 | } 73 | @Override 74 | public void write(byte[] b, int off, int len) throws IOException { 75 | if (closed) { 76 | throw new IOException("Stream closed"); 77 | } 78 | 79 | int written = 0; 80 | while (written < len) { 81 | if (!target.hasRemaining()) { 82 | flush(); 83 | } 84 | int chunk = Math.min(target.remaining(), len - written); 85 | target.put(b, off + written, chunk); 86 | written += chunk; 87 | } 88 | } 89 | @Override 90 | public void write(byte[] b) throws IOException { 91 | write(b, 0, b.length); 92 | } 93 | 94 | public void write(ByteBuffer buf) throws IOException { 95 | if (closed) { 96 | throw new IOException("Stream closed"); 97 | } 98 | int originalLimit = buf.limit(); 99 | while (buf.hasRemaining()) { 100 | if (!target.hasRemaining()) { 101 | flush(); 102 | } 103 | int chunk = Math.min(target.remaining(), buf.remaining()); 104 | buf.limit(buf.position() + chunk); // we have to move the limit around to fit the size of the target 105 | target.put(buf); // this api is limited so that it will always consume the full buffer, so thats why we move around the limit 106 | buf.limit(originalLimit); 107 | } 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/io/FileChannelOutputStreamTest.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.io; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertArrayEquals; 4 | import static org.junit.jupiter.api.Assertions.assertEquals; 5 | import java.io.IOException; 6 | import java.nio.channels.FileChannel; 7 | import java.nio.file.Files; 8 | import java.nio.file.Path; 9 | import java.nio.file.StandardOpenOption; 10 | import java.util.Random; 11 | import org.junit.jupiter.api.Test; 12 | import io.usethesource.vallang.io.binary.util.FileChannelDirectInputStream; 13 | import io.usethesource.vallang.io.binary.util.FileChannelDirectOutputStream; 14 | 15 | class FileChannelOutputStreamTest { 16 | private static final Path targetFile; 17 | static { 18 | Path file = null; 19 | try { 20 | file = Files.createTempFile("file-channel-test", "bin"); 21 | } catch (IOException e) { 22 | System.err.println(e); 23 | } 24 | targetFile = file; 25 | } 26 | 27 | private FileChannel openWriteChannel() throws IOException { 28 | return FileChannel.open(targetFile, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING); 29 | } 30 | 31 | private FileChannel openReadChannel() throws IOException { 32 | return FileChannel.open(targetFile, StandardOpenOption.READ); 33 | } 34 | 35 | @Test 36 | void testSimpleWrite() throws IOException { 37 | roundTripChannel(new byte[][]{{42}}); 38 | } 39 | 40 | @Test 41 | void testBigWrite() throws IOException { 42 | byte[] buffer = new byte[1024*1024]; 43 | new Random().nextBytes(buffer); 44 | roundTripChannel(new byte[][]{buffer}); 45 | } 46 | 47 | @Test 48 | void testChunkedBigWrite() throws IOException { 49 | byte[][] buffers = new byte[1024][]; 50 | var r = new Random(); 51 | for (int i = 0; i < buffers.length; i++) { 52 | buffers[i] = new byte[i * 128]; 53 | r.nextBytes(buffers[i]); 54 | } 55 | roundTripChannel(buffers); 56 | } 57 | 58 | 59 | private void roundTripChannel(byte[][] buffers) throws IOException { 60 | writeChannelInBulk(buffers); 61 | verifyChannelInBulk(buffers); 62 | writeChannelBytePerByte(buffers); 63 | verifyChannelBytePerByte(buffers); 64 | } 65 | 66 | private void verifyChannelBytePerByte(byte[][] buffers) throws IOException { 67 | try (var reader = new FileChannelDirectInputStream(openReadChannel())) { 68 | for (byte[] expected: buffers) { 69 | for (byte expect: expected) { 70 | assertEquals(expect & 0xFF, reader.read()); 71 | } 72 | } 73 | } 74 | } 75 | 76 | 77 | private void verifyChannelInBulk(byte[][] buffers) throws IOException { 78 | try (var reader = new FileChannelDirectInputStream(openReadChannel())) { 79 | for (byte[] expected: buffers) { 80 | byte[] actual = new byte[expected.length]; 81 | reader.read(actual); 82 | assertArrayEquals(expected, actual); 83 | } 84 | } 85 | } 86 | 87 | private void writeChannelBytePerByte(byte[][] buffers) throws IOException { 88 | try (var writer = new FileChannelDirectOutputStream(openWriteChannel(), 1)) { 89 | for (byte[] buf: buffers) { 90 | for (byte b: buf) { 91 | writer.write(b); 92 | } 93 | } 94 | } 95 | } 96 | 97 | private void writeChannelInBulk(byte[][] buffers) throws IOException { 98 | try (var writer = new FileChannelDirectOutputStream(openWriteChannel(), 1)) { 99 | for (byte[] buf: buffers) { 100 | writer.write(buf); 101 | } 102 | } 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/io/usethesource/vallang/impl/persistent/PersistentSetFactory.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2013-2014 CWI 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * 10 | * * Michael Steindorfer - Michael.Steindorfer@cwi.nl - CWI 11 | *******************************************************************************/ 12 | package io.usethesource.vallang.impl.persistent; 13 | 14 | import static io.usethesource.vallang.impl.persistent.SetWriter.asInstanceOf; 15 | import static io.usethesource.vallang.impl.persistent.SetWriter.isTupleOfArityTwo; 16 | 17 | import io.usethesource.capsule.Set; 18 | import io.usethesource.capsule.SetMultimap; 19 | import io.usethesource.vallang.ISet; 20 | import io.usethesource.vallang.ITuple; 21 | import io.usethesource.vallang.IValue; 22 | import io.usethesource.vallang.type.Type; 23 | import io.usethesource.vallang.util.AbstractTypeBag; 24 | 25 | /** 26 | * Smart constructors for choosing (or converting to) the most appropriate representations based on 27 | * dynamic types and data. 28 | */ 29 | /*package*/ class PersistentSetFactory { 30 | 31 | /** 32 | * Creating an {@link ISet} instance from a {@link SetMultimap.Immutable} representation 33 | * by recovering the precise dynamic type. 34 | * 35 | * @param content internal set representation of an {@link ISet} 36 | * @return appropriate {@link ISet} based on data and type 37 | */ 38 | static final ISet from(final Set.Immutable content) { 39 | 40 | if (content.isEmpty()) { 41 | return EmptySet.EMPTY_SET; 42 | } 43 | 44 | // recover precise dynamic type 45 | final AbstractTypeBag elementTypeBag = 46 | content.stream().map(IValue::getType).collect(AbstractTypeBag.toTypeBag()); 47 | 48 | return from(elementTypeBag, content); 49 | } 50 | 51 | /** 52 | * Creating an {@link ISet} instance from a {@link SetMultimap.Immutable} representation. 53 | * 54 | * @param keyTypeBag precise dynamic type of first data column 55 | * @param valTypeBag precise dynamic type of second data column 56 | * @param content internal multi-map representation of an {@link ISet} 57 | * @return appropriate {@link ISet} based on data and type 58 | */ 59 | static final ISet from(final AbstractTypeBag keyTypeBag, final AbstractTypeBag valTypeBag, 60 | final SetMultimap.Immutable content) { 61 | 62 | if (content.isEmpty()) { 63 | return EmptySet.EMPTY_SET; 64 | } 65 | 66 | // keep current representation 67 | return new PersistentHashIndexedBinaryRelation(keyTypeBag, valTypeBag, content); 68 | } 69 | 70 | /** 71 | * Creating an {@link ISet} instance from a {@link SetMultimap.Immutable} representation. 72 | * 73 | * @param elementTypeBag precise dynamic type of elements of a collection 74 | * @param content internal set representation of an {@link ISet} 75 | * @return appropriate {@link ISet} based on data and type 76 | */ 77 | static final ISet from(final AbstractTypeBag elementTypeBag, 78 | final Set.Immutable content) { 79 | 80 | final Type elementType = elementTypeBag.lub(); 81 | 82 | if (elementType.isBottom()) { 83 | return EmptySet.EMPTY_SET; 84 | } 85 | 86 | if (isTupleOfArityTwo.test(elementType)) { 87 | // convert to binary relation 88 | return content.stream().map(asInstanceOf(ITuple.class)) 89 | .collect(ValueCollectors.toSetMultimap(tuple -> tuple.get(0), tuple -> tuple.get(1))); 90 | } 91 | 92 | // keep current representation 93 | return new PersistentHashSet(elementTypeBag, content); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/basic/ConcurrentTests.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.basic; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertNull; 4 | 5 | import java.util.HashMap; 6 | import java.util.Random; 7 | import java.util.concurrent.BrokenBarrierException; 8 | import java.util.concurrent.CyclicBarrier; 9 | import java.util.concurrent.TimeUnit; 10 | import java.util.concurrent.TimeoutException; 11 | import java.util.concurrent.atomic.AtomicReference; 12 | import org.junit.jupiter.params.ParameterizedTest; 13 | import org.junit.jupiter.params.provider.ArgumentsSource; 14 | import io.usethesource.vallang.IValueFactory; 15 | import io.usethesource.vallang.ValueProvider; 16 | import io.usethesource.vallang.type.Type; 17 | import io.usethesource.vallang.type.TypeFactory; 18 | import io.usethesource.vallang.type.TypeFactory.RandomTypesConfig; 19 | import io.usethesource.vallang.type.TypeStore; 20 | 21 | public class ConcurrentTests { 22 | 23 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 24 | public void parallelRandomGenerators(IValueFactory vf) throws InterruptedException, BrokenBarrierException, TimeoutException { 25 | int cores = Math.max(2, Runtime.getRuntime().availableProcessors()); 26 | var allStarted = new CyclicBarrier(cores + 1); 27 | var allDone = new CyclicBarrier(cores + 1); 28 | var error = new AtomicReference(null); 29 | for (int i = 0; i < cores; i++) { 30 | var runner = new Thread(() -> { 31 | try { 32 | Random r = new Random(); 33 | r.setSeed(Thread.currentThread().getId()); 34 | TypeStore ts = new TypeStore(); 35 | 36 | allStarted.await(); 37 | // now we run this init sequence at the same time, hoping to crash something 38 | TypeFactory tf = TypeFactory.getInstance(); 39 | Type Boolean = tf.abstractDataType(ts, "Boolean"); 40 | 41 | Type Name = tf.abstractDataType(ts, "Name"); 42 | tf.constructor(ts, Boolean, "true"); 43 | tf.constructor(ts, Boolean, "false"); 44 | tf.constructor(ts, Boolean, "and", Boolean, Boolean); 45 | tf.constructor(ts, Boolean, "or", tf.listType(Boolean)); 46 | tf.constructor(ts, Boolean, "not", Boolean); 47 | tf.constructor(ts, Boolean, "twotups", tf.tupleType(Boolean, Boolean), 48 | tf.tupleType(Boolean, Boolean)); 49 | tf.constructor(ts, Name, "name", tf.stringType()); 50 | tf.constructor(ts, Boolean, "friends", tf.listType(Name)); 51 | tf.constructor(ts, Boolean, "couples", tf.listType(tf.tupleType(Name, Name))); 52 | ts.declareKeywordParameter(Name, "moreName", Name); 53 | ts.declareKeywordParameter(Name, "listName", tf.listType(Name)); 54 | ts.declareKeywordParameter(Name, "anyValue", tf.valueType()); 55 | for (int j = 0; j < 1000; j++) { 56 | tf.valueType().randomValue(r, RandomTypesConfig.defaultConfig(r), vf, ts, new HashMap<>(), 5, 5); 57 | } 58 | allDone.await(); 59 | } 60 | catch (Exception failure) { 61 | failure.printStackTrace(); 62 | error.set(failure); 63 | } 64 | finally { 65 | try { 66 | allDone.await(1, TimeUnit.SECONDS); // just to be sure, if nobody is waiting, we just stop. 67 | } catch (InterruptedException | BrokenBarrierException | TimeoutException e) { 68 | //ignore ; 69 | } 70 | } 71 | 72 | }); 73 | runner.setDaemon(true); 74 | runner.start(); 75 | } 76 | 77 | allStarted.await(); 78 | allDone.await(10, TimeUnit.MINUTES); 79 | assertNull(error.get(), "Should be no exception when running init"); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/test/java/io/usethesource/vallang/specification/IMapTests.java: -------------------------------------------------------------------------------- 1 | package io.usethesource.vallang.specification; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import java.util.Map.Entry; 7 | 8 | import org.junit.jupiter.params.ParameterizedTest; 9 | import org.junit.jupiter.params.provider.ArgumentsSource; 10 | 11 | import io.usethesource.vallang.ExpectedType; 12 | import io.usethesource.vallang.IMap; 13 | import io.usethesource.vallang.ISourceLocation; 14 | import io.usethesource.vallang.IValue; 15 | import io.usethesource.vallang.IValueFactory; 16 | import io.usethesource.vallang.ValueProvider; 17 | import io.usethesource.vallang.type.Type; 18 | import io.usethesource.vallang.type.TypeFactory; 19 | 20 | public class IMapTests { 21 | 22 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 23 | public void canonicalEmptyMap(IValueFactory vf, @ExpectedType("map[value,value]") IMap m) { 24 | for (IValue key : m) { 25 | m = m.removeKey(key); 26 | } 27 | 28 | assertTrue(m.isEmpty()); 29 | assertTrue(m.equals(vf.map())); 30 | } 31 | 32 | 33 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 34 | public void lubInvariant(TypeFactory tf, @ExpectedType("map[value,value]") IMap m) { 35 | Type keyLub = tf.voidType(); 36 | Type valueLub = tf.voidType(); 37 | 38 | for (Entry entry : (Iterable>) () -> m.entryIterator()) { 39 | keyLub = keyLub.lub(entry.getKey().getType()); 40 | valueLub = valueLub.lub(entry.getValue().getType()); 41 | } 42 | 43 | assertEquals(tf.mapType(keyLub, valueLub), m.getType()); 44 | } 45 | 46 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 47 | public void lubInvariantAfterRemoveKey(TypeFactory tf, @ExpectedType("map[int,int]") IMap m) { 48 | for (IValue key : m) { 49 | m = m.removeKey(key); 50 | lubInvariant(tf, m); 51 | } 52 | } 53 | 54 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 55 | public void equalsIsKey(@ExpectedType("map[value,value]") IMap m, IValue key1, IValue key2) { 56 | IValue value = key1; 57 | IMap m2 = m.put(key1, value); 58 | 59 | if (key1.equals(key2)) { 60 | assertEquals(m2.get(key2), value); 61 | } 62 | else if (!m.containsKey(key2)) { 63 | assertEquals(m2.size() + 1, m2.put(key2, value).size()); 64 | } 65 | else { 66 | assertEquals(m2.size(), m2.put(key2, value).size()); 67 | } 68 | } 69 | 70 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 71 | public void equalsIsKeyLocs(@ExpectedType("map[loc,loc]") IMap m, ISourceLocation key1, ISourceLocation key2) { 72 | IValue value = key1; 73 | IMap m2 = m.put(key1, value); 74 | 75 | if (key1.equals(key2)) { 76 | assertEquals(m2.get(key2), value); 77 | } 78 | else if (!m.containsKey(key2)) { 79 | assertEquals(m2.size() + 1, m2.put(key2, value).size()); 80 | } 81 | else { 82 | assertEquals(m2.size(), m2.put(key2, value).size()); 83 | } 84 | } 85 | 86 | 87 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 88 | public void lubInvariantAfterRemoveKeyLoc(TypeFactory tf, @ExpectedType("map[loc,loc]") IMap m) { 89 | for (IValue key : m) { 90 | m = m.removeKey(key); 91 | lubInvariant(tf, m); 92 | } 93 | } 94 | 95 | @ParameterizedTest @ArgumentsSource(ValueProvider.class) 96 | public void mapIsVoidAfterAllRemoved(TypeFactory tf, IMap m) { 97 | IMap copy = m; 98 | for (IValue key : m) { 99 | copy = copy.removeKey(key); 100 | } 101 | 102 | // this failed due to issue #55 but only if the random generator 103 | // accidentally adds two of the same key/value pairs to the map 104 | assertTrue(copy.getKeyType() == tf.voidType()); 105 | assertTrue(copy.getValueType() == tf.voidType()); 106 | } 107 | } 108 | --------------------------------------------------------------------------------