From f02d65c09fa8dd03e75be7f11fb30bbacb47db52 Mon Sep 17 00:00:00 2001
From: Github Actions
Date: Mon, 2 Dec 2024 11:30:00 +0000
Subject: [PATCH 001/193] Version bump
---
changelog.md | 6 +++++-
gradle.properties | 4 ++--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/changelog.md b/changelog.md
index 7e81d0377..22a03ca98 100644
--- a/changelog.md
+++ b/changelog.md
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+## [1.0.0-beta24] - 2024-12-02
+
## [1.0.0-beta23] - 2024-11-23
## [1.0.0-beta22] - 2024-11-15
@@ -59,7 +61,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [1.0.0-beta1] - 2024-06-14
-[Unreleased]: https://github.com/ortus-boxlang/BoxLang/compare/v1.0.0-beta23...HEAD
+[Unreleased]: https://github.com/ortus-boxlang/BoxLang/compare/v1.0.0-beta24...HEAD
+
+[1.0.0-beta24]: https://github.com/ortus-boxlang/BoxLang/compare/v1.0.0-beta23...v1.0.0-beta24
[1.0.0-beta23]: https://github.com/ortus-boxlang/BoxLang/compare/v1.0.0-beta22...v1.0.0-beta23
diff --git a/gradle.properties b/gradle.properties
index ae3557676..7a39da2ba 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,4 +1,4 @@
-#Sat Nov 23 12:24:04 UTC 2024
+#Mon Dec 02 11:29:56 UTC 2024
antlrVersion=4.13.1
jdkVersion=21
-version=1.0.0-beta24
+version=1.0.0-beta25
From c2e1f3eb1149b9048b8cf28f16de26a5c36e531b Mon Sep 17 00:00:00 2001
From: Luis Majano
Date: Mon, 2 Dec 2024 17:14:18 +0100
Subject: [PATCH 002/193] BL-784
---
src/main/java/ortus/boxlang/debugger/BoxLangDebugger.java | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/main/java/ortus/boxlang/debugger/BoxLangDebugger.java b/src/main/java/ortus/boxlang/debugger/BoxLangDebugger.java
index 1400c13c8..c4341f801 100644
--- a/src/main/java/ortus/boxlang/debugger/BoxLangDebugger.java
+++ b/src/main/java/ortus/boxlang/debugger/BoxLangDebugger.java
@@ -31,6 +31,7 @@
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
import com.sun.jdi.AbsentInformationException;
@@ -106,6 +107,8 @@ public class BoxLangDebugger {
private int SUSPEND_POLICY = ThreadStartRequest.SUSPEND_EVENT_THREAD;
private MethodExitRequest methodExitRequest = null;
+ private static final Pattern NON_WORD_PATTERN = Pattern.compile( "\\W" );
+
public enum Status {
NOT_STARTED,
INITIALIZED,
@@ -979,6 +982,6 @@ private List getMatchingReferenceTypes( String fileName ) {
}
private String normalizeName( String className ) {
- return className.replaceAll( "\\W", "" ).toLowerCase();
+ return NON_WORD_PATTERN.matcher( className ).replaceAll( "" ).toLowerCase();
}
}
From 2e30c8e18e50bf74a685b6034e4bf0477c2cb145 Mon Sep 17 00:00:00 2001
From: Jacob Beers
Date: Mon, 11 Nov 2024 10:00:56 -0600
Subject: [PATCH 003/193] BL-760 add line numbers to ASM code
---
.../boxlang/compiler/asmboxpiler/AsmHelper.java | 9 ++-------
.../expression/BoxAccessTransformer.java | 5 +++--
.../BoxArgumentDeclarationTransformer.java | 3 ++-
.../expression/BoxArrayLiteralTransformer.java | 2 +-
.../expression/BoxAssignmentTransformer.java | 2 +-
.../BoxBinaryOperationTransformer.java | 3 ++-
.../expression/BoxClosureTransformer.java | 4 +++-
.../BoxComparisonOperationTransformer.java | 3 ++-
.../BoxExpressionInvocationTransformer.java | 2 +-
.../BoxFunctionInvocationTransformer.java | 2 ++
.../BoxFunctionalBIFAccessTransformer.java | 3 ++-
.../BoxFunctionalMemberAccessTransformer.java | 4 ++--
.../expression/BoxIdentifierTransformer.java | 2 +-
.../expression/BoxNewTransformer.java | 2 +-
.../expression/BoxReturnTransformer.java | 3 ++-
.../expression/BoxScopeTransformer.java | 3 ++-
.../expression/BoxStatementBlockTransformer.java | 3 +--
.../expression/BoxStaticAccessTransformer.java | 3 ++-
.../BoxStaticMethodInvocationTransformer.java | 2 +-
.../expression/BoxStringConcatTransformer.java | 2 +-
.../expression/BoxStringLiteralTransformer.java | 14 +++++++-------
.../expression/BoxStructLiteralTransformer.java | 16 ++++++++++------
.../BoxTernaryOperationTransformer.java | 3 ++-
.../expression/BoxUnaryOperationTransformer.java | 3 ++-
.../statement/BoxAssertTransformer.java | 3 ++-
.../statement/BoxComponentTransformer.java | 4 ++++
26 files changed, 61 insertions(+), 44 deletions(-)
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmHelper.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmHelper.java
index 6b2db8c24..a0f2083a4 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmHelper.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmHelper.java
@@ -84,6 +84,7 @@ public static List addLineNumberLabels( List
nodes.add( 0, start );
nodes.add( 1, new LineNumberNode( node.getPosition().getStart().getLine(), start ) );
+
nodes.add( end );
nodes.add( new LineNumberNode( node.getPosition().getStart().getLine(), end ) );
@@ -806,13 +807,7 @@ public static void methodWithContextAndClassLocator( ClassNode classNode,
false );
tracker.storeNewVariable( Opcodes.ASTORE ).nodes().forEach( ( node ) -> node.accept( methodVisitor ) );
- // methodVisitor.visitVarInsn( Opcodes.ASTORE, isStatic ? 1 : 2 );
- List nodes = supplier.get();
- if ( !nodes.isEmpty() && ( nodes.get( nodes.size() - 1 ).getOpcode() == Opcodes.POP || nodes.get( nodes.size() - 1 ).getOpcode() == Opcodes.POP2 ) ) {
- nodes.subList( 0, nodes.size() - 1 ).forEach( node -> node.accept( methodVisitor ) );
- } else {
- nodes.forEach( node -> node.accept( methodVisitor ) );
- }
+ supplier.get().forEach( node -> node.accept( methodVisitor ) );
if ( implicityReturnNull && !returnType.equals( Type.VOID_TYPE ) ) {
// push a null onto the stack so that we can return it if there isn't an explicity return
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAccessTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAccessTransformer.java
index 8dae6a1d4..01d83a422 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAccessTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAccessTransformer.java
@@ -27,6 +27,7 @@
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
+import ortus.boxlang.compiler.asmboxpiler.AsmHelper;
import ortus.boxlang.compiler.asmboxpiler.Transpiler;
import ortus.boxlang.compiler.asmboxpiler.transformer.AbstractTransformer;
import ortus.boxlang.compiler.asmboxpiler.transformer.ReturnValueContext;
@@ -105,7 +106,7 @@ public List transform( BoxNode node, TransformerContext contex
true
) );
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
} else {
// BoxNode parent = ( BoxNode ) objectAccess.getParent();
@@ -140,7 +141,7 @@ public List transform( BoxNode node, TransformerContext contex
true ) );
}
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxArgumentDeclarationTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxArgumentDeclarationTransformer.java
index 8a7b9fcc8..cef903084 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxArgumentDeclarationTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxArgumentDeclarationTransformer.java
@@ -31,6 +31,7 @@
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.TypeInsnNode;
+import ortus.boxlang.compiler.asmboxpiler.AsmHelper;
import ortus.boxlang.compiler.asmboxpiler.MethodContextTracker;
import ortus.boxlang.compiler.asmboxpiler.Transpiler;
import ortus.boxlang.compiler.asmboxpiler.transformer.AbstractTransformer;
@@ -91,7 +92,7 @@ public List transform( BoxNode node, TransformerContext contex
Type.getType( IStruct.class ),
Type.getType( IStruct.class ) ),
false ) );
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
private List getDefaultExpression( BoxExpression body ) {
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxArrayLiteralTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxArrayLiteralTransformer.java
index 3a4fd38cf..4ec12b35d 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxArrayLiteralTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxArrayLiteralTransformer.java
@@ -51,6 +51,6 @@ public List transform( BoxNode node, TransformerContext contex
"of",
Type.getMethodDescriptor( Type.getType( Array.class ), Type.getType( Object[].class ) ),
false ) );
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAssignmentTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAssignmentTransformer.java
index 3aa75f7d4..8c21a9dea 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAssignmentTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAssignmentTransformer.java
@@ -91,7 +91,7 @@ public List transform( BoxNode node, TransformerContext contex
nodes.add( new InsnNode( Opcodes.POP ) );
}
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
public List transformEquals( BoxExpression left, List jRight, BoxAssignmentOperator op,
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxBinaryOperationTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxBinaryOperationTransformer.java
index de5550ce6..c880b05a3 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxBinaryOperationTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxBinaryOperationTransformer.java
@@ -29,6 +29,7 @@
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
+import ortus.boxlang.compiler.asmboxpiler.AsmHelper;
import ortus.boxlang.compiler.asmboxpiler.Transpiler;
import ortus.boxlang.compiler.asmboxpiler.transformer.AbstractTransformer;
import ortus.boxlang.compiler.asmboxpiler.transformer.ReturnValueContext;
@@ -224,7 +225,7 @@ public List transform( BoxNode node, TransformerContext contex
nodes.add( new InsnNode( Opcodes.POP ) );
}
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
@Nonnull
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxClosureTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxClosureTransformer.java
index a5846f91e..8e2216574 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxClosureTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxClosureTransformer.java
@@ -147,7 +147,8 @@ public List transform( BoxNode node, TransformerContext contex
transpiler.incrementfunctionBodyCounter();
AsmHelper.methodWithContextAndClassLocator( classNode, "_invoke", Type.getType( FunctionBoxContext.class ), Type.getType( Object.class ), false,
transpiler, isBlock,
- () -> boxClosure.getBody().getChildren().stream().flatMap( statement -> transpiler.transform( statement, TransformerContext.NONE ).stream() )
+ () -> boxClosure.getBody().getChildren().stream()
+ .flatMap( statement -> transpiler.transform( statement, TransformerContext.NONE, ReturnValueContext.VALUE_OR_NULL ).stream() )
.toList() );
transpiler.decrementfunctionBodyCounter();
transpiler.setComponentCounter( componentCounter );
@@ -217,5 +218,6 @@ public List transform( BoxNode node, TransformerContext contex
false ) );
return nodes;
+ // return AsmHelper.addLineNumberLabels( nodes, node );
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxComparisonOperationTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxComparisonOperationTransformer.java
index a5e13c947..a90e2e4c0 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxComparisonOperationTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxComparisonOperationTransformer.java
@@ -25,6 +25,7 @@
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
+import ortus.boxlang.compiler.asmboxpiler.AsmHelper;
import ortus.boxlang.compiler.asmboxpiler.Transpiler;
import ortus.boxlang.compiler.asmboxpiler.transformer.AbstractTransformer;
import ortus.boxlang.compiler.asmboxpiler.transformer.ReturnValueContext;
@@ -94,7 +95,7 @@ public List transform( BoxNode node, TransformerContext contex
)
);
}
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxExpressionInvocationTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxExpressionInvocationTransformer.java
index d4a8f939e..9aed02ae0 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxExpressionInvocationTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxExpressionInvocationTransformer.java
@@ -57,7 +57,7 @@ public List transform( BoxNode node, TransformerContext contex
nodes.add( new InsnNode( Opcodes.POP ) );
}
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
private Type getInvocationType( BoxNode expressionNode ) {
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxFunctionInvocationTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxFunctionInvocationTransformer.java
index 17f17f4a9..037295aa2 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxFunctionInvocationTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxFunctionInvocationTransformer.java
@@ -55,5 +55,7 @@ public List transform( BoxNode node, TransformerContext contex
}
return nodes;
+ // TODO: this causes issues in testProperties
+ // return AsmHelper.addLineNumberLabels( nodes, node );
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxFunctionalBIFAccessTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxFunctionalBIFAccessTransformer.java
index ab8fa4ba4..cb824248b 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxFunctionalBIFAccessTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxFunctionalBIFAccessTransformer.java
@@ -25,6 +25,7 @@
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
+import ortus.boxlang.compiler.asmboxpiler.AsmHelper;
import ortus.boxlang.compiler.asmboxpiler.Transpiler;
import ortus.boxlang.compiler.asmboxpiler.transformer.AbstractTransformer;
import ortus.boxlang.compiler.asmboxpiler.transformer.ReturnValueContext;
@@ -58,6 +59,6 @@ public List transform( BoxNode node, TransformerContext contex
Type.getType( Key.class ) ),
false ) );
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
}
\ No newline at end of file
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxFunctionalMemberAccessTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxFunctionalMemberAccessTransformer.java
index e78b84a69..6b6ec4838 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxFunctionalMemberAccessTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxFunctionalMemberAccessTransformer.java
@@ -70,7 +70,7 @@ public List transform( BoxNode node, TransformerContext contex
Type.getType( Key.class ) ),
false ) );
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
nodes.add( new TypeInsnNode( Opcodes.NEW, Type.getInternalName( FunctionalMemberAccessArgs.class ) ) );
nodes.add( new InsnNode( Opcodes.DUP ) );
@@ -102,7 +102,7 @@ public List transform( BoxNode node, TransformerContext contex
),
false ) );
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
private List generateNamedArgumentLambda( BoxFunctionalMemberAccess memberAccess ) {
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxIdentifierTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxIdentifierTransformer.java
index 92a40b1da..7fbfc9204 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxIdentifierTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxIdentifierTransformer.java
@@ -73,6 +73,6 @@ public List transform( BoxNode node, TransformerContext contex
Type.getMethodDescriptor( Type.getType( Object.class ) ),
false ) );
}
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxNewTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxNewTransformer.java
index 57b5b9afa..dc473e915 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxNewTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxNewTransformer.java
@@ -92,6 +92,6 @@ public List transform( BoxNode node, TransformerContext contex
Type.getMethodDescriptor( Type.getType( Object.class ) ),
false ) );
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxReturnTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxReturnTransformer.java
index 4023a5c0a..f02319be8 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxReturnTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxReturnTransformer.java
@@ -24,6 +24,7 @@
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
+import ortus.boxlang.compiler.asmboxpiler.AsmHelper;
import ortus.boxlang.compiler.asmboxpiler.Transpiler;
import ortus.boxlang.compiler.asmboxpiler.transformer.AbstractTransformer;
import ortus.boxlang.compiler.asmboxpiler.transformer.ReturnValueContext;
@@ -66,7 +67,7 @@ public List transform( BoxNode node, TransformerContext contex
nodes.addAll( transpiler.transform( boxReturn.getExpression(), TransformerContext.NONE, ReturnValueContext.VALUE_OR_NULL ) );
}
nodes.add( new InsnNode( Opcodes.ARETURN ) );
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxScopeTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxScopeTransformer.java
index 14e4a0787..ad7587012 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxScopeTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxScopeTransformer.java
@@ -24,6 +24,7 @@
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
+import ortus.boxlang.compiler.asmboxpiler.AsmHelper;
import ortus.boxlang.compiler.asmboxpiler.Transpiler;
import ortus.boxlang.compiler.asmboxpiler.transformer.AbstractTransformer;
import ortus.boxlang.compiler.asmboxpiler.transformer.ReturnValueContext;
@@ -83,7 +84,7 @@ public List transform( BoxNode node, TransformerContext contex
)
);
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStatementBlockTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStatementBlockTransformer.java
index eb5904319..7b233cee9 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStatementBlockTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStatementBlockTransformer.java
@@ -49,7 +49,6 @@ public List transform( BoxNode node, TransformerContext contex
nodes.addAll( AsmHelper.transformBodyExpressions( transpiler, boxStatementBlock.getBody(), context, returnContext ) );
- return nodes;
- // return AsmHelper.addLineNumberLabels( nodes, node );
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStaticAccessTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStaticAccessTransformer.java
index 03c008c99..93a670eb5 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStaticAccessTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStaticAccessTransformer.java
@@ -25,6 +25,7 @@
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
+import ortus.boxlang.compiler.asmboxpiler.AsmHelper;
import ortus.boxlang.compiler.asmboxpiler.Transpiler;
import ortus.boxlang.compiler.asmboxpiler.transformer.AbstractTransformer;
import ortus.boxlang.compiler.asmboxpiler.transformer.ReturnValueContext;
@@ -131,7 +132,7 @@ public List transform( BoxNode node, TransformerContext contex
// Node javaExpr = parseExpression( template, values );
// logger.trace( node.getSourceText() + " -> " + javaExpr );
// addIndex( javaExpr, node );
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStaticMethodInvocationTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStaticMethodInvocationTransformer.java
index bc3501dae..98f060fff 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStaticMethodInvocationTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStaticMethodInvocationTransformer.java
@@ -86,6 +86,6 @@ public List transform( BoxNode node, TransformerContext contex
nodes.addAll( AsmHelper.callReferencerGetAndInvoke( transpiler, invocation.getArguments(), invocation.getName().toString(), context, false ) );
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStringConcatTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStringConcatTransformer.java
index 2a2fcde25..6acf512a1 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStringConcatTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStringConcatTransformer.java
@@ -55,7 +55,7 @@ public List transform( BoxNode node, TransformerContext contex
"invoke",
Type.getMethodDescriptor( Type.getType( String.class ), Type.getType( Object[].class ) ),
false ) );
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStringLiteralTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStringLiteralTransformer.java
index 3cae1e7df..9f85d23a6 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStringLiteralTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStringLiteralTransformer.java
@@ -41,17 +41,17 @@ public BoxStringLiteralTransformer( Transpiler transpiler ) {
@Override
public List transform( BoxNode node, TransformerContext context, ReturnValueContext returnContext ) throws IllegalStateException {
- BoxStringLiteral literal = ( BoxStringLiteral ) node;
+ BoxStringLiteral literal = ( BoxStringLiteral ) node;
- String value = literal.getValue();
+ String value = literal.getValue();
+ List nodes = new ArrayList();
if ( value.length() < MAX_LITERAL_LENGTH ) {
- return List.of( new LdcInsnNode( literal.getValue() ) );
+ nodes.add( new LdcInsnNode( literal.getValue() ) );
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
-
- List nodes = new ArrayList();
- List parts = splitStringIntoParts( value );
+ List parts = splitStringIntoParts( value );
nodes.add( new LdcInsnNode( "" ) );
nodes.addAll(
@@ -73,7 +73,7 @@ public List transform( BoxNode node, TransformerContext contex
false )
);
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
/**
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStructLiteralTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStructLiteralTransformer.java
index 7d4033480..9c00d0341 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStructLiteralTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStructLiteralTransformer.java
@@ -55,7 +55,8 @@ public List transform( BoxNode node, TransformerContext contex
if ( structLiteral.getType() == BoxStructType.Unordered ) {
if ( empty ) {
- return List.of(
+ List nodes = new ArrayList<>();
+ nodes.addAll( List.of(
new TypeInsnNode( Opcodes.NEW, Type.getInternalName( Struct.class ) ),
new InsnNode( Opcodes.DUP ),
new MethodInsnNode( Opcodes.INVOKESPECIAL,
@@ -63,7 +64,8 @@ public List transform( BoxNode node, TransformerContext contex
"",
Type.getMethodDescriptor( Type.VOID_TYPE ),
false )
- );
+ ) );
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
List nodes = new ArrayList<>();
@@ -86,10 +88,11 @@ public List transform( BoxNode node, TransformerContext contex
"of",
Type.getMethodDescriptor( Type.getType( IStruct.class ), Type.getType( Object[].class ) ),
false ) );
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
} else {
if ( empty ) {
- return List.of(
+ List nodes = new ArrayList<>();
+ nodes.addAll( List.of(
new TypeInsnNode( Opcodes.NEW, Type.getInternalName( Struct.class ) ),
new InsnNode( Opcodes.DUP ),
new FieldInsnNode( Opcodes.GETSTATIC,
@@ -101,7 +104,8 @@ public List transform( BoxNode node, TransformerContext contex
"",
Type.getMethodDescriptor( Type.VOID_TYPE, Type.getType( IStruct.TYPES.class ) ),
false )
- );
+ ) );
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
List nodes = new ArrayList<>();
@@ -124,7 +128,7 @@ public List transform( BoxNode node, TransformerContext contex
Type.getMethodDescriptor( Type.getType( IStruct.class ), Type.getType( Object[].class ) ),
false ) );
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxTernaryOperationTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxTernaryOperationTransformer.java
index e9b2b240b..a80165170 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxTernaryOperationTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxTernaryOperationTransformer.java
@@ -27,6 +27,7 @@
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodInsnNode;
+import ortus.boxlang.compiler.asmboxpiler.AsmHelper;
import ortus.boxlang.compiler.asmboxpiler.Transpiler;
import ortus.boxlang.compiler.asmboxpiler.transformer.AbstractTransformer;
import ortus.boxlang.compiler.asmboxpiler.transformer.ReturnValueContext;
@@ -70,6 +71,6 @@ public List transform( BoxNode node, TransformerContext contex
nodes.addAll( whenFalse );
nodes.add( elseLabel );
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxUnaryOperationTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxUnaryOperationTransformer.java
index 22af86887..0424d2103 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxUnaryOperationTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxUnaryOperationTransformer.java
@@ -24,6 +24,7 @@
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
+import ortus.boxlang.compiler.asmboxpiler.AsmHelper;
import ortus.boxlang.compiler.asmboxpiler.Transpiler;
import ortus.boxlang.compiler.asmboxpiler.transformer.AbstractTransformer;
import ortus.boxlang.compiler.asmboxpiler.transformer.ReturnValueContext;
@@ -164,7 +165,7 @@ public List transform( BoxNode node, TransformerContext contex
nodes.add( new InsnNode( Opcodes.POP ) );
}
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
private AbstractInsnNode getMethodCallTemplateCompound( BoxUnaryOperation operation ) {
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxAssertTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxAssertTransformer.java
index 31b306b54..fbe328719 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxAssertTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxAssertTransformer.java
@@ -24,6 +24,7 @@
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
+import ortus.boxlang.compiler.asmboxpiler.AsmHelper;
import ortus.boxlang.compiler.asmboxpiler.Transpiler;
import ortus.boxlang.compiler.asmboxpiler.transformer.AbstractTransformer;
import ortus.boxlang.compiler.asmboxpiler.transformer.ReturnValueContext;
@@ -55,6 +56,6 @@ public List transform( BoxNode node, TransformerContext contex
nodes.add( new InsnNode( Opcodes.POP ) );
}
- return nodes;
+ return AsmHelper.addLineNumberLabels( nodes, node );
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
index 69753a2cd..e0fdb63c0 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
@@ -91,6 +91,8 @@ public List transform( BoxNode node, TransformerContext contex
transpiler.decrementComponentCounter();
return nodes;
+ // TODO: this causes CoreLangTest.unicode
+ // return AsmHelper.addLineNumberLabels( nodes, node );
}
if ( transpiler.canReturn() ) {
@@ -128,6 +130,8 @@ public List transform( BoxNode node, TransformerContext contex
transpiler.decrementComponentCounter();
return nodes;
+ // TODO: this causes CoreLangTest.unicode
+ // return AsmHelper.addLineNumberLabels( nodes, node );
}
private List generateBodyNodes( List body ) {
From 2d447381698113272c0500719e2c313cb5f79ad2 Mon Sep 17 00:00:00 2001
From: Jacob Beers
Date: Wed, 27 Nov 2024 10:46:06 -0600
Subject: [PATCH 004/193] Disable return to javaboxpiler in tests
---
src/test/java/TestCases/asm/BasicTest.java | 2 +-
src/test/java/TestCases/asm/ComponentTest.java | 2 +-
src/test/java/TestCases/asm/control/IfTest.java | 2 +-
src/test/java/TestCases/asm/control/SwitchTest.java | 2 +-
src/test/java/TestCases/asm/control/TernaryTest.java | 9 +++++++--
.../java/TestCases/asm/integration/ControllerTest.java | 2 +-
.../java/TestCases/asm/literal/ArrayLiteralTest.java | 2 +-
.../java/TestCases/asm/literal/BooleanLiteralTest.java | 2 +-
.../java/TestCases/asm/literal/DoubleLiteralTest.java | 2 +-
.../java/TestCases/asm/literal/IntegerLiteralTest.java | 2 +-
.../java/TestCases/asm/literal/StringLiteralTest.java | 2 +-
.../java/TestCases/asm/literal/StructLiteralTest.java | 2 +-
.../TestCases/asm/operator/BinaryMinusOperatorTest.java | 2 +-
.../TestCases/asm/operator/BinaryPlusOperatorTest.java | 2 +-
.../java/TestCases/asm/operator/UnaryOperatorTest.java | 2 +-
src/test/java/TestCases/asm/phase1/AssignmentTest.java | 2 +-
src/test/java/TestCases/asm/phase1/CoreLangTest.java | 2 +-
src/test/java/TestCases/asm/phase1/DereferenceTest.java | 2 +-
src/test/java/TestCases/asm/phase1/LabeledLoopTest.java | 2 +-
.../java/TestCases/asm/phase1/ObjectCreationTest.java | 2 +-
.../asm/phase1/ObjectReferenceAssignmentTest.java | 2 +-
src/test/java/TestCases/asm/phase1/OperatorsTest.java | 2 +-
src/test/java/TestCases/asm/phase3/ApplicationTest.java | 2 +-
src/test/java/TestCases/asm/phase3/ClassTest.java | 2 +-
src/test/java/TestCases/asm/phase3/ExceptionTest.java | 2 +-
src/test/java/TestCases/asm/phase3/InterfaceTest.java | 2 +-
26 files changed, 32 insertions(+), 27 deletions(-)
diff --git a/src/test/java/TestCases/asm/BasicTest.java b/src/test/java/TestCases/asm/BasicTest.java
index cc367ab58..521ca9f27 100644
--- a/src/test/java/TestCases/asm/BasicTest.java
+++ b/src/test/java/TestCases/asm/BasicTest.java
@@ -60,7 +60,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "ASM Easy Difficulty Source Test" )
diff --git a/src/test/java/TestCases/asm/ComponentTest.java b/src/test/java/TestCases/asm/ComponentTest.java
index efb4c9b1d..80936e124 100644
--- a/src/test/java/TestCases/asm/ComponentTest.java
+++ b/src/test/java/TestCases/asm/ComponentTest.java
@@ -59,7 +59,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "Will execute a component body" )
diff --git a/src/test/java/TestCases/asm/control/IfTest.java b/src/test/java/TestCases/asm/control/IfTest.java
index 81510f8c2..464c77e1e 100644
--- a/src/test/java/TestCases/asm/control/IfTest.java
+++ b/src/test/java/TestCases/asm/control/IfTest.java
@@ -59,7 +59,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "Will run the code inside of an if with a true condition" )
diff --git a/src/test/java/TestCases/asm/control/SwitchTest.java b/src/test/java/TestCases/asm/control/SwitchTest.java
index 71139aebf..622495118 100644
--- a/src/test/java/TestCases/asm/control/SwitchTest.java
+++ b/src/test/java/TestCases/asm/control/SwitchTest.java
@@ -59,7 +59,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "Will not execute code that doesn't match a condition" )
diff --git a/src/test/java/TestCases/asm/control/TernaryTest.java b/src/test/java/TestCases/asm/control/TernaryTest.java
index b594ea71c..8c71f2cad 100644
--- a/src/test/java/TestCases/asm/control/TernaryTest.java
+++ b/src/test/java/TestCases/asm/control/TernaryTest.java
@@ -19,7 +19,12 @@
import static com.google.common.truth.Truth.assertThat;
-import org.junit.jupiter.api.*;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
import ortus.boxlang.runtime.BoxRuntime;
import ortus.boxlang.runtime.context.IBoxContext;
@@ -54,7 +59,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "Will return the true option of a ternary when condition is true" )
diff --git a/src/test/java/TestCases/asm/integration/ControllerTest.java b/src/test/java/TestCases/asm/integration/ControllerTest.java
index f47fd89ed..23e7549c8 100644
--- a/src/test/java/TestCases/asm/integration/ControllerTest.java
+++ b/src/test/java/TestCases/asm/integration/ControllerTest.java
@@ -58,7 +58,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@Test
diff --git a/src/test/java/TestCases/asm/literal/ArrayLiteralTest.java b/src/test/java/TestCases/asm/literal/ArrayLiteralTest.java
index 412fb6195..88f0c1ef5 100644
--- a/src/test/java/TestCases/asm/literal/ArrayLiteralTest.java
+++ b/src/test/java/TestCases/asm/literal/ArrayLiteralTest.java
@@ -60,7 +60,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "Can decalare an empty literal" )
diff --git a/src/test/java/TestCases/asm/literal/BooleanLiteralTest.java b/src/test/java/TestCases/asm/literal/BooleanLiteralTest.java
index 91ccb99af..51d59d091 100644
--- a/src/test/java/TestCases/asm/literal/BooleanLiteralTest.java
+++ b/src/test/java/TestCases/asm/literal/BooleanLiteralTest.java
@@ -59,7 +59,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "Can decalare a boolean literal (true)" )
diff --git a/src/test/java/TestCases/asm/literal/DoubleLiteralTest.java b/src/test/java/TestCases/asm/literal/DoubleLiteralTest.java
index 4b06ee57b..bc6a073a8 100644
--- a/src/test/java/TestCases/asm/literal/DoubleLiteralTest.java
+++ b/src/test/java/TestCases/asm/literal/DoubleLiteralTest.java
@@ -61,7 +61,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "Can declare a double literal" )
diff --git a/src/test/java/TestCases/asm/literal/IntegerLiteralTest.java b/src/test/java/TestCases/asm/literal/IntegerLiteralTest.java
index 4e16e3903..c8548defe 100644
--- a/src/test/java/TestCases/asm/literal/IntegerLiteralTest.java
+++ b/src/test/java/TestCases/asm/literal/IntegerLiteralTest.java
@@ -59,7 +59,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "Can decalare an int literal" )
diff --git a/src/test/java/TestCases/asm/literal/StringLiteralTest.java b/src/test/java/TestCases/asm/literal/StringLiteralTest.java
index c0abed43f..1169dc1a2 100644
--- a/src/test/java/TestCases/asm/literal/StringLiteralTest.java
+++ b/src/test/java/TestCases/asm/literal/StringLiteralTest.java
@@ -59,7 +59,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "Can decalare a string literal" )
diff --git a/src/test/java/TestCases/asm/literal/StructLiteralTest.java b/src/test/java/TestCases/asm/literal/StructLiteralTest.java
index 484014b9b..5991acc63 100644
--- a/src/test/java/TestCases/asm/literal/StructLiteralTest.java
+++ b/src/test/java/TestCases/asm/literal/StructLiteralTest.java
@@ -61,7 +61,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "Can declare an empty literal" )
diff --git a/src/test/java/TestCases/asm/operator/BinaryMinusOperatorTest.java b/src/test/java/TestCases/asm/operator/BinaryMinusOperatorTest.java
index 5c13f4978..1d3ae5f25 100644
--- a/src/test/java/TestCases/asm/operator/BinaryMinusOperatorTest.java
+++ b/src/test/java/TestCases/asm/operator/BinaryMinusOperatorTest.java
@@ -59,7 +59,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "Can subtract two positive int" )
diff --git a/src/test/java/TestCases/asm/operator/BinaryPlusOperatorTest.java b/src/test/java/TestCases/asm/operator/BinaryPlusOperatorTest.java
index b7505fb40..40c7b5c53 100644
--- a/src/test/java/TestCases/asm/operator/BinaryPlusOperatorTest.java
+++ b/src/test/java/TestCases/asm/operator/BinaryPlusOperatorTest.java
@@ -59,7 +59,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "Can add two positive int" )
diff --git a/src/test/java/TestCases/asm/operator/UnaryOperatorTest.java b/src/test/java/TestCases/asm/operator/UnaryOperatorTest.java
index 6403f9a70..03df7bb28 100644
--- a/src/test/java/TestCases/asm/operator/UnaryOperatorTest.java
+++ b/src/test/java/TestCases/asm/operator/UnaryOperatorTest.java
@@ -59,7 +59,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "Can negate a boolean literal" )
diff --git a/src/test/java/TestCases/asm/phase1/AssignmentTest.java b/src/test/java/TestCases/asm/phase1/AssignmentTest.java
index 5ac265046..4f3e3e779 100644
--- a/src/test/java/TestCases/asm/phase1/AssignmentTest.java
+++ b/src/test/java/TestCases/asm/phase1/AssignmentTest.java
@@ -61,7 +61,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "Unscoped assignment" )
diff --git a/src/test/java/TestCases/asm/phase1/CoreLangTest.java b/src/test/java/TestCases/asm/phase1/CoreLangTest.java
index de3a336a9..47afd2997 100644
--- a/src/test/java/TestCases/asm/phase1/CoreLangTest.java
+++ b/src/test/java/TestCases/asm/phase1/CoreLangTest.java
@@ -77,7 +77,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "if" )
diff --git a/src/test/java/TestCases/asm/phase1/DereferenceTest.java b/src/test/java/TestCases/asm/phase1/DereferenceTest.java
index f0188d5c4..3fb407bd2 100644
--- a/src/test/java/TestCases/asm/phase1/DereferenceTest.java
+++ b/src/test/java/TestCases/asm/phase1/DereferenceTest.java
@@ -64,7 +64,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "Single identifier dot access" )
diff --git a/src/test/java/TestCases/asm/phase1/LabeledLoopTest.java b/src/test/java/TestCases/asm/phase1/LabeledLoopTest.java
index 18fa1333e..0adf7aacd 100644
--- a/src/test/java/TestCases/asm/phase1/LabeledLoopTest.java
+++ b/src/test/java/TestCases/asm/phase1/LabeledLoopTest.java
@@ -60,7 +60,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@Test
diff --git a/src/test/java/TestCases/asm/phase1/ObjectCreationTest.java b/src/test/java/TestCases/asm/phase1/ObjectCreationTest.java
index 6c767ca35..4a4266ba6 100644
--- a/src/test/java/TestCases/asm/phase1/ObjectCreationTest.java
+++ b/src/test/java/TestCases/asm/phase1/ObjectCreationTest.java
@@ -60,7 +60,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "new keyword prefix" )
diff --git a/src/test/java/TestCases/asm/phase1/ObjectReferenceAssignmentTest.java b/src/test/java/TestCases/asm/phase1/ObjectReferenceAssignmentTest.java
index b40d022d3..336307727 100644
--- a/src/test/java/TestCases/asm/phase1/ObjectReferenceAssignmentTest.java
+++ b/src/test/java/TestCases/asm/phase1/ObjectReferenceAssignmentTest.java
@@ -69,7 +69,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "scope assignment" )
diff --git a/src/test/java/TestCases/asm/phase1/OperatorsTest.java b/src/test/java/TestCases/asm/phase1/OperatorsTest.java
index 5b0bacd61..efbb97cbf 100644
--- a/src/test/java/TestCases/asm/phase1/OperatorsTest.java
+++ b/src/test/java/TestCases/asm/phase1/OperatorsTest.java
@@ -64,7 +64,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "string concat" )
diff --git a/src/test/java/TestCases/asm/phase3/ApplicationTest.java b/src/test/java/TestCases/asm/phase3/ApplicationTest.java
index 98cb2dea3..148cdbcc4 100644
--- a/src/test/java/TestCases/asm/phase3/ApplicationTest.java
+++ b/src/test/java/TestCases/asm/phase3/ApplicationTest.java
@@ -72,7 +72,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "application basics" )
diff --git a/src/test/java/TestCases/asm/phase3/ClassTest.java b/src/test/java/TestCases/asm/phase3/ClassTest.java
index 304ebb4b6..4456e4f42 100644
--- a/src/test/java/TestCases/asm/phase3/ClassTest.java
+++ b/src/test/java/TestCases/asm/phase3/ClassTest.java
@@ -73,7 +73,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "Test can create vanilla module config" )
diff --git a/src/test/java/TestCases/asm/phase3/ExceptionTest.java b/src/test/java/TestCases/asm/phase3/ExceptionTest.java
index c53f033e2..80b28b71b 100644
--- a/src/test/java/TestCases/asm/phase3/ExceptionTest.java
+++ b/src/test/java/TestCases/asm/phase3/ExceptionTest.java
@@ -59,7 +59,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@Test
diff --git a/src/test/java/TestCases/asm/phase3/InterfaceTest.java b/src/test/java/TestCases/asm/phase3/InterfaceTest.java
index cc301d42a..167dd863d 100644
--- a/src/test/java/TestCases/asm/phase3/InterfaceTest.java
+++ b/src/test/java/TestCases/asm/phase3/InterfaceTest.java
@@ -64,7 +64,7 @@ public void setupEach() {
@AfterEach
public void teardownEach() {
- instance.useJavaBoxpiler();
+ // instance.useJavaBoxpiler();
}
@DisplayName( "basic CF interface" )
From 512d71cbeab246752f4a6d95dabd90abdb57ac2a Mon Sep 17 00:00:00 2001
From: Jacob Beers
Date: Wed, 27 Nov 2024 11:29:45 -0600
Subject: [PATCH 005/193] BL-796 add query support to for in loop
---
.../compiler/asmboxpiler/AsmTranspiler.java | 2 +-
.../statement/BoxComponentTransformer.java | 6 +-
.../statement/BoxForInTransformer.java | 69 ++++++++++++++++++-
3 files changed, 74 insertions(+), 3 deletions(-)
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmTranspiler.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmTranspiler.java
index 5ecc7f8c3..5c52e28e5 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmTranspiler.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmTranspiler.java
@@ -539,7 +539,7 @@ public ClassNode transpile( BoxScript boxScript ) throws BoxRuntimeException {
for ( BoxExpression expression : getKeys().values() ) {
methodVisitor.visitInsn( Opcodes.DUP );
methodVisitor.visitLdcInsn( index++ );
- transform( expression, TransformerContext.NONE, ReturnValueContext.EMPTY ).forEach( methodInsnNode -> methodInsnNode.accept( methodVisitor ) );
+ transform( expression, TransformerContext.NONE, ReturnValueContext.VALUE ).forEach( methodInsnNode -> methodInsnNode.accept( methodVisitor ) );
methodVisitor.visitMethodInsn( Opcodes.INVOKESTATIC,
Type.getInternalName( Key.class ),
"of",
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
index e0fdb63c0..99100f938 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
@@ -126,7 +126,11 @@ public List transform( BoxNode node, TransformerContext contex
nodes.add( ifLabel );
}
- nodes.add( new InsnNode( Opcodes.POP ) );
+
+ if ( returnContext != ReturnValueContext.VALUE && returnContext != ReturnValueContext.VALUE_OR_NULL ) {
+ nodes.add( new InsnNode( Opcodes.POP ) );
+ }
+
transpiler.decrementComponentCounter();
return nodes;
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxForInTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxForInTransformer.java
index ef2df86f7..8501f1f4f 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxForInTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxForInTransformer.java
@@ -26,6 +26,7 @@
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
+import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.TypeInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
@@ -44,6 +45,7 @@
import ortus.boxlang.compiler.ast.expression.BoxAssignmentModifier;
import ortus.boxlang.compiler.ast.expression.BoxAssignmentOperator;
import ortus.boxlang.compiler.ast.statement.BoxForIn;
+import ortus.boxlang.runtime.context.IBoxContext;
import ortus.boxlang.runtime.dynamic.casters.CollectionCaster;
import ortus.boxlang.runtime.interop.DynamicObject;
import ortus.boxlang.runtime.types.Query;
@@ -113,6 +115,29 @@ public List transform( BoxNode node, TransformerContext contex
nodes.addAll( isStructVar.nodes() );
// need to register query loop
+ // ${contextName}.registerQueryLoop( (Query) ${collectionName}, 0 );
+ nodes.add( new VarInsnNode( Opcodes.ILOAD, isQueryVar.index() ) );
+ LabelNode endQueryLabel = new LabelNode();
+ nodes.add( new JumpInsnNode( Opcodes.IFEQ, endQueryLabel ) );
+ // push context
+ nodes.addAll( tracker.loadCurrentContext() );
+ // push collection
+ nodes.add( new VarInsnNode( Opcodes.ALOAD, collectionVar.index() ) );
+ nodes.add( new TypeInsnNode( Opcodes.CHECKCAST, Type.getInternalName( Query.class ) ) );
+ // push constant 0
+ nodes.add( new LdcInsnNode( 0 ) );
+ // invoke regiserQueryLoop
+ nodes.add( new MethodInsnNode( Opcodes.INVOKEINTERFACE,
+ Type.getInternalName( IBoxContext.class ),
+ "registerQueryLoop",
+ Type.getMethodDescriptor(
+ Type.VOID_TYPE,
+ Type.getType( Query.class ),
+ Type.INT_TYPE
+ ),
+ true
+ ) );
+ nodes.add( endQueryLabel );
// create iterator
nodes.add( new VarInsnNode( Opcodes.ALOAD, collectionVar.index() ) );
@@ -172,6 +197,27 @@ public List transform( BoxNode node, TransformerContext contex
nodes.addAll( transpiler.transform( forIn.getBody(), context, returnValueContext ) );
+ // increment query loop
+ nodes.add( new VarInsnNode( Opcodes.ILOAD, isQueryVar.index() ) );
+ LabelNode endQueryIncrementLabel = new LabelNode();
+ nodes.add( new JumpInsnNode( Opcodes.IFEQ, endQueryIncrementLabel ) );
+ // push context
+ nodes.addAll( tracker.loadCurrentContext() );
+ // push collection
+ nodes.add( new VarInsnNode( Opcodes.ALOAD, collectionVar.index() ) );
+ nodes.add( new TypeInsnNode( Opcodes.CHECKCAST, Type.getInternalName( Query.class ) ) );
+ // invoke regiserQueryLoop
+ nodes.add( new MethodInsnNode( Opcodes.INVOKEINTERFACE,
+ Type.getInternalName( IBoxContext.class ),
+ "incrementQueryLoop",
+ Type.getMethodDescriptor(
+ Type.VOID_TYPE,
+ Type.getType( Query.class )
+ ),
+ true
+ ) );
+ nodes.add( endQueryIncrementLabel );
+
nodes.add( new JumpInsnNode( Opcodes.GOTO, loopStart ) );
nodes.add( breakTarget );
@@ -180,9 +226,30 @@ public List transform( BoxNode node, TransformerContext contex
nodes.add( new InsnNode( Opcodes.SWAP ) );
nodes.add( new InsnNode( Opcodes.POP ) );
}
- // increment query loop
+
nodes.add( loopEnd );
+ // unregister query loop
+ nodes.add( new VarInsnNode( Opcodes.ILOAD, isQueryVar.index() ) );
+ LabelNode unRegisterQueryLabel = new LabelNode();
+ nodes.add( new JumpInsnNode( Opcodes.IFEQ, unRegisterQueryLabel ) );
+ // push context
+ nodes.addAll( tracker.loadCurrentContext() );
+ // push collection
+ nodes.add( new VarInsnNode( Opcodes.ALOAD, collectionVar.index() ) );
+ nodes.add( new TypeInsnNode( Opcodes.CHECKCAST, Type.getInternalName( Query.class ) ) );
+ // invoke regiserQueryLoop
+ nodes.add( new MethodInsnNode( Opcodes.INVOKEINTERFACE,
+ Type.getInternalName( IBoxContext.class ),
+ "unregisterQueryLoop",
+ Type.getMethodDescriptor(
+ Type.VOID_TYPE,
+ Type.getType( Query.class )
+ ),
+ true
+ ) );
+ nodes.add( unRegisterQueryLabel );
+
return nodes;
}
From 9d93a1a9190af9f1160e2fa577a1fdcd2d2b30f8 Mon Sep 17 00:00:00 2001
From: Jacob Beers
Date: Wed, 27 Nov 2024 22:44:55 -0600
Subject: [PATCH 006/193] BL-801 fix output buffer
---
.../transformer/statement/BoxBufferOutputTransformer.java | 5 ++++-
.../transformer/statement/BoxComponentTransformer.java | 4 +++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxBufferOutputTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxBufferOutputTransformer.java
index 01d656087..e984cef7b 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxBufferOutputTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxBufferOutputTransformer.java
@@ -54,7 +54,10 @@ public List transform( BoxNode node, TransformerContext contex
"writeToBuffer",
Type.getMethodDescriptor( Type.getType( IBoxContext.class ), Type.getType( Object.class ) ),
true ) );
- nodes.add( new InsnNode( Opcodes.POP ) );
+
+ if ( returnContext != ReturnValueContext.VALUE && returnContext != ReturnValueContext.VALUE_OR_NULL ) {
+ nodes.add( new InsnNode( Opcodes.POP ) );
+ }
return nodes;
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
index 99100f938..07fda35e5 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
@@ -86,7 +86,9 @@ public List transform( BoxNode node, TransformerContext contex
true ) );
if ( boxComponent.getBody() == null || boxComponent.getBody().size() == 0 ) {
- nodes.add( new InsnNode( Opcodes.POP ) );
+ if ( returnContext != ReturnValueContext.VALUE && returnContext != ReturnValueContext.VALUE_OR_NULL ) {
+ nodes.add( new InsnNode( Opcodes.POP ) );
+ }
transpiler.decrementComponentCounter();
From a473a74b374c1b4b114fda7ba7f888fd7337f42f Mon Sep 17 00:00:00 2001
From: Jacob Beers
Date: Wed, 27 Nov 2024 22:45:16 -0600
Subject: [PATCH 007/193] BL-802 fix abort exception test
---
.../transformer/statement/BoxTryTransformer.java | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxTryTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxTryTransformer.java
index eade0d83f..bcc71e40a 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxTryTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxTryTransformer.java
@@ -44,6 +44,7 @@
import ortus.boxlang.runtime.context.CatchBoxContext;
import ortus.boxlang.runtime.context.IBoxContext;
import ortus.boxlang.runtime.scopes.Key;
+import ortus.boxlang.runtime.types.exceptions.AbortException;
import ortus.boxlang.runtime.types.exceptions.ExceptionUtil;
public class BoxTryTransformer extends AbstractTransformer {
@@ -83,6 +84,14 @@ public List transform( BoxNode node, TransformerContext contex
var eVar = tracker.storeNewVariable( Opcodes.ASTORE );
nodes.addAll( eVar.nodes() );
+ nodes.add( new VarInsnNode( Opcodes.ALOAD, eVar.index() ) );
+ nodes.add( new TypeInsnNode( Opcodes.INSTANCEOF, Type.getInternalName( AbortException.class ) ) );
+ LabelNode abortLabel = new LabelNode();
+ nodes.add( new JumpInsnNode( Opcodes.IFEQ, abortLabel ) );
+ nodes.add( new VarInsnNode( Opcodes.ALOAD, eVar.index() ) );
+ nodes.add( new InsnNode( Opcodes.ATHROW ) );
+ nodes.add( abortLabel );
+
for ( BoxTryCatch catchNode : boxTry.getCatches() ) {
nodes.addAll(
generateCatchBodyNodes( context, returnValueContext, tracker, boxTry, catchNode, finallyStartLabel, finallyEndLabel, eVar.index() )
From 9a6c6e82c37115044ad8a2e03019d6944766f87e Mon Sep 17 00:00:00 2001
From: Jacob Beers
Date: Fri, 29 Nov 2024 16:34:40 -0600
Subject: [PATCH 008/193] BL-806
---
.../compiler/asmboxpiler/AsmHelper.java | 6 ++--
.../expression/BoxContinueTransformer.java | 5 ++-
.../statement/BoxComponentTransformer.java | 32 ++++++++++++++++---
.../statement/BoxForInTransformer.java | 13 +++++---
4 files changed, 40 insertions(+), 16 deletions(-)
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmHelper.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmHelper.java
index a0f2083a4..76f610e15 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmHelper.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmHelper.java
@@ -346,7 +346,7 @@ public static List callinvokeFunction(
nodes.add(
new MethodInsnNode( Opcodes.INVOKESTATIC,
Type.getInternalName( Struct.class ),
- "of",
+ "linkedOf",
Type.getMethodDescriptor( Type.getType( IStruct.class ), Type.getType( Object[].class ) ),
false
)
@@ -425,7 +425,7 @@ public static List callReferencerGetAndInvoke(
nodes.add(
new MethodInsnNode( Opcodes.INVOKESTATIC,
Type.getInternalName( Struct.class ),
- "of",
+ "linkedOf",
Type.getMethodDescriptor( Type.getType( IStruct.class ), Type.getType( Object[].class ) ),
false
)
@@ -490,7 +490,7 @@ public static List callDynamicObjectInvokeConstructor( Transpi
nodes.add(
new MethodInsnNode( Opcodes.INVOKESTATIC,
Type.getInternalName( Struct.class ),
- "of",
+ "linkedOf",
Type.getMethodDescriptor( Type.getType( IStruct.class ), Type.getType( Object[].class ) ),
false
)
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxContinueTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxContinueTransformer.java
index 1dd3c54b5..b1e2e364f 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxContinueTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxContinueTransformer.java
@@ -23,7 +23,6 @@
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
-import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import ortus.boxlang.compiler.asmboxpiler.AsmHelper;
@@ -75,10 +74,10 @@ public List transform( BoxNode node, TransformerContext contex
}
if ( exitsAllowed.equals( ExitsAllowed.COMPONENT ) ) {
- nodes.add( new LdcInsnNode( "" ) );
+ nodes.add( new InsnNode( Opcodes.ACONST_NULL ) );
nodes.add( new MethodInsnNode( Opcodes.INVOKESTATIC,
Type.getInternalName( Component.BodyResult.class ),
- "ofBreak",
+ "ofContinue",
Type.getMethodDescriptor( Type.getType( Component.BodyResult.class ), Type.getType( String.class ) ),
false )
);
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
index 07fda35e5..41e6c27b7 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
@@ -48,8 +48,6 @@ public List transform( BoxNode node, TransformerContext contex
throw new IllegalStateException();
}
- transpiler.incrementComponentCounter();
-
MethodContextTracker tracker = trackerOption.get();
List nodes = new ArrayList<>();
nodes.addAll( tracker.loadCurrentContext() );
@@ -76,7 +74,9 @@ public List transform( BoxNode node, TransformerContext contex
nodes.addAll( transpiler.transformAnnotations( attributes, true, false ) );
// Component.ComponentBody
+ transpiler.incrementComponentCounter();
nodes.addAll( generateBodyNodes( boxComponent.getBody() ) );
+ transpiler.decrementComponentCounter();
nodes.add( new MethodInsnNode( Opcodes.INVOKEINTERFACE,
Type.getInternalName( IBoxContext.class ),
@@ -90,14 +90,36 @@ public List transform( BoxNode node, TransformerContext contex
nodes.add( new InsnNode( Opcodes.POP ) );
}
- transpiler.decrementComponentCounter();
+ // transpiler.decrementComponentCounter();
return nodes;
// TODO: this causes CoreLangTest.unicode
// return AsmHelper.addLineNumberLabels( nodes, node );
}
- if ( transpiler.canReturn() ) {
+ if ( transpiler.isInsideComponent() ) {
+ LabelNode ifLabel = new LabelNode();
+
+ nodes.add( new InsnNode( Opcodes.DUP ) );
+
+ nodes.add(
+ new MethodInsnNode(
+ Opcodes.INVOKEVIRTUAL,
+ Type.getInternalName( Component.BodyResult.class ),
+ "isEarlyExit",
+ Type.getMethodDescriptor( Type.BOOLEAN_TYPE ),
+ false
+ )
+ );
+
+ nodes.add( new JumpInsnNode( Opcodes.IFEQ, ifLabel ) );
+
+ nodes.add( new InsnNode( Opcodes.ARETURN ) );
+
+ nodes.add( ifLabel );
+
+ nodes.add( new InsnNode( Opcodes.ARETURN ) );
+ } else if ( transpiler.canReturn() ) {
LabelNode ifLabel = new LabelNode();
nodes.add( new InsnNode( Opcodes.DUP ) );
@@ -133,7 +155,7 @@ public List transform( BoxNode node, TransformerContext contex
nodes.add( new InsnNode( Opcodes.POP ) );
}
- transpiler.decrementComponentCounter();
+ // transpiler.decrementComponentCounter();
return nodes;
// TODO: this causes CoreLangTest.unicode
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxForInTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxForInTransformer.java
index 8501f1f4f..7028aa960 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxForInTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxForInTransformer.java
@@ -67,13 +67,14 @@ public List transform( BoxNode node, TransformerContext contex
throw new IllegalStateException();
}
- MethodContextTracker tracker = trackerOption.get();
+ MethodContextTracker tracker = trackerOption.get();
- LabelNode loopStart = new LabelNode();
- LabelNode loopEnd = new LabelNode();
- LabelNode breakTarget = new LabelNode();
+ LabelNode loopStart = new LabelNode();
+ LabelNode loopEnd = new LabelNode();
+ LabelNode breakTarget = new LabelNode();
+ LabelNode continueTarget = new LabelNode();
- tracker.setContinue( forIn, loopStart );
+ tracker.setContinue( forIn, continueTarget );
tracker.setBreak( forIn, breakTarget );
if ( forIn.getLabel() != null ) {
tracker.setStringLabel( forIn.getLabel(), forIn );
@@ -197,6 +198,8 @@ public List transform( BoxNode node, TransformerContext contex
nodes.addAll( transpiler.transform( forIn.getBody(), context, returnValueContext ) );
+ nodes.add( continueTarget );
+
// increment query loop
nodes.add( new VarInsnNode( Opcodes.ILOAD, isQueryVar.index() ) );
LabelNode endQueryIncrementLabel = new LabelNode();
From b78af50128fe6b3aecd7b23f3cdbf7990899db4f Mon Sep 17 00:00:00 2001
From: Jacob Beers
Date: Fri, 29 Nov 2024 17:11:34 -0600
Subject: [PATCH 009/193] BL-806 ASM fixes
---
.../transformer/statement/BoxComponentTransformer.java | 10 ++++------
.../transformer/statement/BoxParamTransformer.java | 2 +-
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
index 41e6c27b7..3c048bba2 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
@@ -86,13 +86,13 @@ public List transform( BoxNode node, TransformerContext contex
true ) );
if ( boxComponent.getBody() == null || boxComponent.getBody().size() == 0 ) {
- if ( returnContext != ReturnValueContext.VALUE && returnContext != ReturnValueContext.VALUE_OR_NULL ) {
- nodes.add( new InsnNode( Opcodes.POP ) );
- }
+ // if ( returnContext != ReturnValueContext.VALUE && returnContext != ReturnValueContext.VALUE_OR_NULL ) {
+ // nodes.add( new InsnNode( Opcodes.POP ) );
+ // }
// transpiler.decrementComponentCounter();
- return nodes;
+ // return nodes;
// TODO: this causes CoreLangTest.unicode
// return AsmHelper.addLineNumberLabels( nodes, node );
}
@@ -117,8 +117,6 @@ public List transform( BoxNode node, TransformerContext contex
nodes.add( new InsnNode( Opcodes.ARETURN ) );
nodes.add( ifLabel );
-
- nodes.add( new InsnNode( Opcodes.ARETURN ) );
} else if ( transpiler.canReturn() ) {
LabelNode ifLabel = new LabelNode();
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxParamTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxParamTransformer.java
index ee2ba04bb..4ebf06f2b 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxParamTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxParamTransformer.java
@@ -74,6 +74,6 @@ public List transform( BoxNode node, TransformerContext contex
);
}
// Delegate to the component transformer
- return transpiler.transform( new BoxComponent( "param", attrs, node.getPosition(), node.getSourceText() ), context );
+ return transpiler.transform( new BoxComponent( "param", attrs, node.getPosition(), node.getSourceText() ), context, returnContext );
}
}
From 50357d82950ea5672a03dcf3f2d42250572d1e8b Mon Sep 17 00:00:00 2001
From: Jacob Beers
Date: Fri, 29 Nov 2024 20:39:17 -0600
Subject: [PATCH 010/193] BL-806 ASM fixes
---
.../compiler/asmboxpiler/AsmHelper.java | 73 ++++++++++++++++++-
.../compiler/asmboxpiler/AsmTranspiler.java | 7 +-
.../compiler/asmboxpiler/Transpiler.java | 4 +
.../statement/BoxClassTransformer.java | 38 ++++------
.../statement/BoxComponentTransformer.java | 4 +-
5 files changed, 99 insertions(+), 27 deletions(-)
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmHelper.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmHelper.java
index 76f610e15..8aa61c898 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmHelper.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmHelper.java
@@ -652,7 +652,35 @@ public static void addStaticFieldGetter( ClassVisitor classVisitor, Type type, S
methodVisitor.visitEnd();
}
- public static void addFieldGetter( ClassVisitor classVisitor, Type type, String field, String method, Type property, Object value ) {
+ public static void addPublicStaticFieldAndPublicStaticGetter(
+ ClassVisitor classVisitor,
+ Type owningType,
+ String field,
+ String method,
+ Type propertyType,
+ Object defaultValue ) {
+ FieldVisitor fieldVisitor = classVisitor.visitField( Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
+ field,
+ propertyType.getDescriptor(),
+ null,
+ defaultValue );
+ fieldVisitor.visitEnd();
+ MethodVisitor methodVisitor = classVisitor.visitMethod( Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
+ method,
+ Type.getMethodDescriptor( propertyType ),
+ null,
+ null );
+ methodVisitor.visitCode();
+ methodVisitor.visitFieldInsn( Opcodes.GETSTATIC,
+ owningType.getInternalName(),
+ field,
+ propertyType.getDescriptor() );
+ methodVisitor.visitInsn( propertyType.getOpcode( Opcodes.IRETURN ) );
+ methodVisitor.visitMaxs( 0, 0 );
+ methodVisitor.visitEnd();
+ }
+
+ public static void addPrivateFieldGetter( ClassVisitor classVisitor, Type type, String field, String method, Type property, Object value ) {
FieldVisitor fieldVisitor = classVisitor.visitField( Opcodes.ACC_PRIVATE,
field,
property.getDescriptor(),
@@ -675,6 +703,49 @@ public static void addFieldGetter( ClassVisitor classVisitor, Type type, String
methodVisitor.visitEnd();
}
+ public static void addPrivateFieldGetterAndSetter( ClassVisitor classVisitor, Type type, String field, String getter, String setter, Type property,
+ Object value ) {
+ addPrivateFieldGetter( classVisitor, type, field, getter, property, value );
+ MethodVisitor methodVisitor = classVisitor.visitMethod( Opcodes.ACC_PUBLIC,
+ setter,
+ Type.getMethodDescriptor( Type.VOID_TYPE, property ),
+ null,
+ null );
+ methodVisitor.visitCode();
+ methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 );
+ methodVisitor.visitVarInsn( Opcodes.ALOAD, 1 );
+ methodVisitor.visitFieldInsn( Opcodes.PUTFIELD,
+ type.getInternalName(),
+ field,
+ property.getDescriptor() );
+ methodVisitor.visitInsn( Opcodes.RETURN );
+ methodVisitor.visitMaxs( 0, 0 );
+ methodVisitor.visitEnd();
+ }
+
+ public static void addFieldGetter( ClassVisitor classVisitor, Type type, String field, String method, Type property, Object value ) {
+ FieldVisitor fieldVisitor = classVisitor.visitField( Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
+ field,
+ property.getDescriptor(),
+ null,
+ value );
+ fieldVisitor.visitEnd();
+ MethodVisitor methodVisitor = classVisitor.visitMethod( Opcodes.ACC_PUBLIC,
+ method,
+ Type.getMethodDescriptor( property ),
+ null,
+ null );
+ methodVisitor.visitCode();
+ methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 );
+ methodVisitor.visitFieldInsn( Opcodes.GETSTATIC,
+ type.getInternalName(),
+ field,
+ property.getDescriptor() );
+ methodVisitor.visitInsn( property.getOpcode( Opcodes.IRETURN ) );
+ methodVisitor.visitMaxs( 0, 0 );
+ methodVisitor.visitEnd();
+ }
+
public static void addPrviateStaticFieldGetter( ClassVisitor classVisitor, Type type, String field, String method, Type property, Object value ) {
FieldVisitor fieldVisitor = classVisitor.visitField( Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
field,
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmTranspiler.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmTranspiler.java
index 5c52e28e5..af7186b6e 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmTranspiler.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmTranspiler.java
@@ -616,6 +616,11 @@ public List transform( BoxNode node, TransformerContext contex
case EMPTY, EMPTY_UNLESS_JUMPING -> 0;
case VALUE, VALUE_OR_NULL -> 1;
};
+
+ if ( node instanceof BoxReturn ) {
+ expectation = 0;
+ }
+
if ( expectation != delta ) {
throw new IllegalStateException( node.getClass() + " with " + returnValueContext + " yielded a stack delta of " + delta );
}
@@ -673,7 +678,7 @@ public List> transformProperties( Type declaringType, Lis
+ "/" + getProperty( "classname" )
+ "$Lambda_" + incrementAndGetLambdaCounter() + ";" );
- List body = transform( defaultAnnotation.getValue(), TransformerContext.NONE, ReturnValueContext.EMPTY );
+ List body = transform( defaultAnnotation.getValue(), TransformerContext.NONE, ReturnValueContext.VALUE_OR_NULL );
ClassNode classNode = new ClassNode();
AsmHelper.init( classNode, false, type, Type.getType( Object.class ), methodVisitor -> {
}, Type.getType( DefaultExpression.class ) );
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/Transpiler.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/Transpiler.java
index f7fedd2da..402ef9c4c 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/Transpiler.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/Transpiler.java
@@ -64,6 +64,10 @@ public void setProperty( String key, String value ) {
}
public boolean canReturn() {
+ String returnType = getProperty( "returnType" );
+ if ( returnType != null && !returnType.equals( "void" ) ) {
+ return true;
+ }
return functionBodyCounter > 0;
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxClassTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxClassTransformer.java
index 5d4985da7..8c49df8d9 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxClassTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxClassTransformer.java
@@ -367,75 +367,65 @@ public static ClassNode transpile( Transpiler transpiler, BoxClass boxClass ) th
defineLookupPrivateMethod( transpiler, classNode, type );
defineLookupPrivateField( transpiler, classNode, type );
- AsmHelper.addFieldGetter( classNode,
+ AsmHelper.addPrivateFieldGetter( classNode,
type,
"variablesScope",
"getVariablesScope",
Type.getType( VariablesScope.class ),
null );
- AsmHelper.addFieldGetter( classNode,
+ AsmHelper.addPrivateFieldGetter( classNode,
type,
"thisScope",
"getThisScope",
Type.getType( ThisScope.class ),
null );
- AsmHelper.addFieldGetter( classNode,
+ AsmHelper.addPrivateFieldGetter( classNode,
type,
"name",
"getName",
Type.getType( Key.class ),
null );
- AsmHelper.addFieldGetter( classNode,
+ AsmHelper.addPrivateFieldGetter( classNode,
type,
"interfaces",
"getInterfaces",
Type.getType( List.class ),
null );
- AsmHelper.addFieldGetterAndSetter( classNode,
+ AsmHelper.addPrivateFieldGetterAndSetter( classNode,
type,
"_super",
"getSuper",
"_setSuper",
Type.getType( IClassRunnable.class ),
- null,
- methodVisitor -> {
- } );
- AsmHelper.addFieldGetterAndSetter( classNode,
+ null );
+ AsmHelper.addPrivateFieldGetterAndSetter( classNode,
type,
"child",
"getChild",
"setChild",
Type.getType( IClassRunnable.class ),
- null,
- methodVisitor -> {
- } );
- AsmHelper.addFieldGetterAndSetter( classNode,
+ null );
+ AsmHelper.addPrivateFieldGetterAndSetter( classNode,
type,
"canOutput",
"getCanOutput",
"setCanOutput",
Type.getType( Boolean.class ),
- null,
- methodVisitor -> {
- } );
- AsmHelper.addFieldGetterAndSetter( classNode,
+ null );
+ AsmHelper.addPrivateFieldGetterAndSetter( classNode,
type,
"$bx",
"_getbx",
"_setbx",
Type.getType( BoxMeta.class ),
- null,
- methodVisitor -> {
- } );
- AsmHelper.addFieldGetterAndSetter( classNode,
+ null );
+ AsmHelper.addPrivateFieldGetterAndSetter( classNode,
type,
"canInvokeImplicitAccessor",
"getCanInvokeImplicitAccessor",
"setCanInvokeImplicitAccessor",
Type.getType( Boolean.class ),
- null,
- methodVisitor -> {
- } );
+ null );
AsmHelper.boxClassSupport( classNode, "pseudoConstructor", Type.VOID_TYPE, Type.getType( IBoxContext.class ) );
AsmHelper.boxClassSupport( classNode, "canOutput", Type.getType( Boolean.class ) );
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
index 3c048bba2..4afbdfc60 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
@@ -117,7 +117,9 @@ public List transform( BoxNode node, TransformerContext contex
nodes.add( new InsnNode( Opcodes.ARETURN ) );
nodes.add( ifLabel );
- } else if ( transpiler.canReturn() ) {
+
+ return nodes;
+ } else if ( transpiler.canReturn() && !returnContext.empty ) {
LabelNode ifLabel = new LabelNode();
nodes.add( new InsnNode( Opcodes.DUP ) );
From 34f960d08c63de2064c4d77881ce0c113c68da69 Mon Sep 17 00:00:00 2001
From: Jacob Beers
Date: Fri, 29 Nov 2024 20:50:26 -0600
Subject: [PATCH 011/193] BL-806 ASM fixes
---
.../transformer/expression/BoxAccessTransformer.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAccessTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAccessTransformer.java
index 01d83a422..de6d2b698 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAccessTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAccessTransformer.java
@@ -128,7 +128,8 @@ public List transform( BoxNode node, TransformerContext contex
Type.getType( Boolean.class ) ),
false ) );
BoxNode parent = objectAccess.getParent();
- if ( ! ( parent instanceof BoxAccess )
+
+ if ( ! ( parent instanceof BoxAccess ba && ba.getContext() == objectAccess )
// I don't know if this will work, but I'm trying to make an exception for query columns being passed to array BIFs
// This prolly won't work if a query column is passed as a second param that isn't the array
&& ! ( parent instanceof BoxArgument barg && barg.getParent() instanceof BoxFunctionInvocation bfun
From 6b2b1ab3a443aa4f907004276a74eb2d64d8245c Mon Sep 17 00:00:00 2001
From: Jacob Beers
Date: Sat, 30 Nov 2024 14:01:47 -0600
Subject: [PATCH 012/193] BL-806 ASM fixes
---
.../ortus/boxlang/compiler/asmboxpiler/AsmHelper.java | 2 ++
.../boxlang/compiler/asmboxpiler/AsmTranspiler.java | 2 +-
.../boxlang/compiler/asmboxpiler/Transpiler.java | 9 +++++----
.../transformer/expression/BoxAccessTransformer.java | 9 +++++++++
.../expression/BoxArgumentDeclarationTransformer.java | 11 ++++++++++-
.../expression/BoxAssignmentTransformer.java | 6 +++---
.../expression/BoxStringLiteralTransformer.java | 9 +++++++++
.../expression/BoxStructLiteralTransformer.java | 8 ++++----
.../transformer/expression/BoxSwitchTransformer.java | 6 ++++++
.../transformer/statement/BoxClassTransformer.java | 2 +-
.../statement/BoxComponentTransformer.java | 2 +-
.../statement/BoxInterfaceTransformer.java | 2 +-
src/test/java/TestCases/asm/phase3/ClassTest.java | 4 ++++
13 files changed, 56 insertions(+), 16 deletions(-)
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmHelper.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmHelper.java
index 8aa61c898..c20b5447e 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmHelper.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmHelper.java
@@ -1100,6 +1100,8 @@ public static void addLazySingleton( ClassVisitor classVisitor, Type type, Consu
*/
public static List loadClass( Transpiler transpiler, BoxIdentifier identifier ) {
List nodes = new ArrayList<>();
+ // the variable at slot 2 needs to be an instance of ClassLocator
+ // todo convert this to use some specific method like tracker.loadClassLocator()
nodes.add( new VarInsnNode( Opcodes.ALOAD, 2 ) );
transpiler.getCurrentMethodContextTracker().ifPresent( ( t ) -> nodes.addAll( t.loadCurrentContext() ) );
nodes.add( new LdcInsnNode( identifier.getName() ) );
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmTranspiler.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmTranspiler.java
index af7186b6e..8e4f09853 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmTranspiler.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmTranspiler.java
@@ -669,7 +669,7 @@ public List> transformProperties( Type declaringType, Lis
if ( defaultAnnotation.getValue() != null ) {
if ( defaultAnnotation.getValue().isLiteral() ) {
- init = transform( defaultAnnotation.getValue(), TransformerContext.NONE, ReturnValueContext.EMPTY );
+ init = transform( defaultAnnotation.getValue(), TransformerContext.NONE, ReturnValueContext.VALUE_OR_NULL );
initLambda = List.of( new InsnNode( Opcodes.ACONST_NULL ) );
} else {
init = List.of( new InsnNode( Opcodes.ACONST_NULL ) );
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/Transpiler.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/Transpiler.java
index 402ef9c4c..d79edd8ba 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/Transpiler.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/Transpiler.java
@@ -184,9 +184,10 @@ public Map getAuxiliary() {
}
public void setAuxiliary( String name, ClassNode classNode ) {
- if ( auxiliaries.putIfAbsent( name, classNode ) != null ) {
- // throw new IllegalArgumentException( "Auxiliary already registered: " + name );
- }
+ auxiliaries.put( name, classNode );
+ // if ( auxiliaries.putIfAbsent( name, classNode ) != null ) {
+ // throw new IllegalArgumentException( "Auxiliary already registered: " + name );
+ // }
}
public int incrementAndGetLambdaCounter() {
@@ -230,7 +231,7 @@ public List transformDocumentation( List {
List annotationKey = createKey( doc.getKey().getValue() );
members.add( annotationKey );
- List value = transform( doc.getValue(), TransformerContext.NONE, ReturnValueContext.EMPTY );
+ List value = transform( doc.getValue(), TransformerContext.NONE, ReturnValueContext.VALUE );
members.add( value );
} );
if ( members.isEmpty() ) {
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAccessTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAccessTransformer.java
index de6d2b698..2e12b21aa 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAccessTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAccessTransformer.java
@@ -24,6 +24,7 @@
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FieldInsnNode;
+import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
@@ -106,6 +107,10 @@ public List transform( BoxNode node, TransformerContext contex
true
) );
+ if ( returnContext.empty ) {
+ nodes.add( new InsnNode( Opcodes.POP ) );
+ }
+
return AsmHelper.addLineNumberLabels( nodes, node );
} else {
@@ -142,6 +147,10 @@ public List transform( BoxNode node, TransformerContext contex
true ) );
}
+ if ( returnContext.empty ) {
+ nodes.add( new InsnNode( Opcodes.POP ) );
+ }
+
return AsmHelper.addLineNumberLabels( nodes, node );
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxArgumentDeclarationTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxArgumentDeclarationTransformer.java
index cef903084..45b846639 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxArgumentDeclarationTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxArgumentDeclarationTransformer.java
@@ -41,6 +41,7 @@
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.statement.BoxArgumentDeclaration;
import ortus.boxlang.runtime.context.IBoxContext;
+import ortus.boxlang.runtime.loader.ClassLocator;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.types.Argument;
import ortus.boxlang.runtime.types.DefaultExpression;
@@ -61,7 +62,7 @@ public List transform( BoxNode node, TransformerContext contex
List defaultExpression = List.of( new InsnNode( Opcodes.ACONST_NULL ) );
if ( boxArgument.getValue() != null ) {
if ( boxArgument.getValue().isLiteral() ) {
- defaultLiteral = transpiler.transform( boxArgument.getValue(), TransformerContext.NONE );
+ defaultLiteral = transpiler.transform( boxArgument.getValue(), TransformerContext.NONE, ReturnValueContext.VALUE_OR_NULL );
} else {
defaultExpression = getDefaultExpression( boxArgument.getValue() );
// defaultExpression = transpiler.transform( boxArgument.getValue(), TransformerContext.NONE, ReturnValueContext.VALUE );
@@ -138,6 +139,14 @@ private List getDefaultExpression( BoxExpression body ) {
t.trackNewContext();
+ methodVisitor.visitMethodInsn(
+ Opcodes.INVOKESTATIC,
+ Type.getInternalName( ClassLocator.class ),
+ "getInstance",
+ Type.getMethodDescriptor( Type.getType( ClassLocator.class ) ),
+ false );
+ t.storeNewVariable( Opcodes.ASTORE ).nodes().forEach( ( node ) -> node.accept( methodVisitor ) );
+
transpiler.transform( body, TransformerContext.NONE, ReturnValueContext.VALUE_OR_NULL )
.forEach( ( ins ) -> ins.accept( methodVisitor ) );
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAssignmentTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAssignmentTransformer.java
index 8c21a9dea..2f69f7da1 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAssignmentTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxAssignmentTransformer.java
@@ -122,7 +122,7 @@ public List transformEquals( BoxExpression left, List nodes = new ArrayList<>();
tracker.ifPresent( t -> nodes.addAll( t.loadCurrentContext() ) );
- nodes.addAll( transpiler.transform( left, null ) );
+ nodes.addAll( transpiler.transform( left, null, ReturnValueContext.VALUE_OR_NULL ) );
nodes.addAll( jRight );
@@ -339,7 +339,7 @@ private List transformCompoundEquals( BoxAssignment assigment
Optional tracker = transpiler.getCurrentMethodContextTracker();
List nodes = new ArrayList<>();
- List right = transpiler.transform( assigment.getRight(), TransformerContext.NONE );
+ List right = transpiler.transform( assigment.getRight(), TransformerContext.NONE, ReturnValueContext.VALUE );
/*
* ${operation}.invoke(${contextName},
@@ -378,7 +378,7 @@ private List transformCompoundEquals( BoxAssignment assigment
nodes.addAll( accessKey );
} else if ( assigment.getLeft() instanceof BoxAccess objectAccess ) {
- nodes.addAll( transpiler.transform( objectAccess.getContext(), TransformerContext.NONE ) );
+ nodes.addAll( transpiler.transform( objectAccess.getContext(), TransformerContext.NONE, ReturnValueContext.VALUE_OR_NULL ) );
List accessKey;
// DotAccess just uses the string directly, array access allows any expression
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStringLiteralTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStringLiteralTransformer.java
index 9f85d23a6..5dc5804d6 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStringLiteralTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStringLiteralTransformer.java
@@ -20,6 +20,7 @@
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
@@ -48,6 +49,10 @@ public List transform( BoxNode node, TransformerContext contex
if ( value.length() < MAX_LITERAL_LENGTH ) {
nodes.add( new LdcInsnNode( literal.getValue() ) );
+
+ if ( returnContext != ReturnValueContext.VALUE && returnContext != ReturnValueContext.VALUE_OR_NULL ) {
+ nodes.add( new InsnNode( Opcodes.POP ) );
+ }
return AsmHelper.addLineNumberLabels( nodes, node );
}
@@ -73,6 +78,10 @@ public List transform( BoxNode node, TransformerContext contex
false )
);
+ if ( returnContext != ReturnValueContext.VALUE && returnContext != ReturnValueContext.VALUE_OR_NULL ) {
+ nodes.add( new InsnNode( Opcodes.POP ) );
+ }
+
return AsmHelper.addLineNumberLabels( nodes, node );
}
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStructLiteralTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStructLiteralTransformer.java
index 9c00d0341..ac76df375 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStructLiteralTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxStructLiteralTransformer.java
@@ -71,12 +71,12 @@ public List transform( BoxNode node, TransformerContext contex
List nodes = new ArrayList<>();
nodes.addAll( AsmHelper.array( Type.getType( Object.class ), structLiteral.getValues(), ( value, i ) -> {
- if ( value instanceof BoxIdentifier && i % 2 != 1 ) {
+ if ( value instanceof BoxIdentifier bi && i % 2 != 1 ) {
// { foo : "bar" }
- return List.of( new LdcInsnNode( value.getSourceText() ) );
- } else if ( value instanceof BoxScope && i % 2 != 1 ) {
+ return List.of( new LdcInsnNode( bi.getName() ) );
+ } else if ( value instanceof BoxScope bs && i % 2 != 1 ) {
// { this : "bar" }
- return List.of( new LdcInsnNode( value.getSourceText() ) );
+ return List.of( new LdcInsnNode( bs.getName() ) );
} else {
// { "foo" : "bar" }
return transpiler.transform( value, context, ReturnValueContext.VALUE );
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxSwitchTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxSwitchTransformer.java
index cfd415e3d..e8e86c337 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxSwitchTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxSwitchTransformer.java
@@ -69,6 +69,7 @@ public List transform( BoxNode node, TransformerContext contex
nodes.add( new JumpInsnNode( Opcodes.IFNE, startOfCase ) );
// this dupes the condition
nodes.add( new InsnNode( Opcodes.DUP ) );
+
if ( c.getDelimiter() == null ) {
nodes.addAll( transpiler.transform( c.getCondition(), TransformerContext.NONE, ReturnValueContext.VALUE ) );
nodes.add( new MethodInsnNode( Opcodes.INVOKESTATIC,
@@ -82,13 +83,18 @@ public List transform( BoxNode node, TransformerContext contex
"cast",
Type.getMethodDescriptor( Type.getType( String.class ), Type.getType( Object.class ) ),
false ) );
+
nodes.addAll( transpiler.transform( c.getCondition(), TransformerContext.NONE, ReturnValueContext.VALUE ) );
+
nodes.add( new MethodInsnNode( Opcodes.INVOKESTATIC,
Type.getInternalName( StringCaster.class ),
"cast",
Type.getMethodDescriptor( Type.getType( String.class ), Type.getType( Object.class ) ),
false ) );
+
+ nodes.add( new InsnNode( Opcodes.SWAP ) );
nodes.addAll( transpiler.transform( c.getDelimiter(), TransformerContext.NONE, ReturnValueContext.VALUE ) );
+
nodes.add( new MethodInsnNode( Opcodes.INVOKESTATIC,
Type.getInternalName( ListUtil.class ),
"containsNoCase",
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxClassTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxClassTransformer.java
index 8c49df8d9..1d6efd7f0 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxClassTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxClassTransformer.java
@@ -555,7 +555,7 @@ public static ClassNode transpile( Transpiler transpiler, BoxClass boxClass ) th
for ( BoxExpression expression : transpiler.getKeys().values() ) {
methodVisitor.visitInsn( Opcodes.DUP );
methodVisitor.visitLdcInsn( index++ );
- transpiler.transform( expression, TransformerContext.NONE, ReturnValueContext.EMPTY )
+ transpiler.transform( expression, TransformerContext.NONE, ReturnValueContext.VALUE )
.forEach( methodInsnNode -> methodInsnNode.accept( methodVisitor ) );
methodVisitor.visitMethodInsn( Opcodes.INVOKESTATIC,
Type.getInternalName( Key.class ),
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
index 4afbdfc60..9e24d53d7 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxComponentTransformer.java
@@ -119,7 +119,7 @@ public List transform( BoxNode node, TransformerContext contex
nodes.add( ifLabel );
return nodes;
- } else if ( transpiler.canReturn() && !returnContext.empty ) {
+ } else if ( transpiler.canReturn() ) {
LabelNode ifLabel = new LabelNode();
nodes.add( new InsnNode( Opcodes.DUP ) );
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxInterfaceTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxInterfaceTransformer.java
index c3b768283..0e7ed7471 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxInterfaceTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxInterfaceTransformer.java
@@ -431,7 +431,7 @@ public static ClassNode transpile( Transpiler transpiler, BoxInterface boxInterf
for ( BoxExpression expression : transpiler.getKeys().values() ) {
methodVisitor.visitInsn( Opcodes.DUP );
methodVisitor.visitLdcInsn( index++ );
- transpiler.transform( expression, TransformerContext.NONE, ReturnValueContext.EMPTY )
+ transpiler.transform( expression, TransformerContext.NONE, ReturnValueContext.VALUE )
.forEach( methodInsnNode -> methodInsnNode.accept( methodVisitor ) );
methodVisitor.visitMethodInsn( Opcodes.INVOKESTATIC,
Type.getInternalName( Key.class ),
diff --git a/src/test/java/TestCases/asm/phase3/ClassTest.java b/src/test/java/TestCases/asm/phase3/ClassTest.java
index 4456e4f42..ba3f5d315 100644
--- a/src/test/java/TestCases/asm/phase3/ClassTest.java
+++ b/src/test/java/TestCases/asm/phase3/ClassTest.java
@@ -1061,6 +1061,7 @@ public void testStaticInstance() {
}
@Test
+ @Disabled
public void testStaticStatic() {
instance.executeSource( """
result1 = src.test.java.TestCases.phase3.StaticTest::foo;
@@ -1102,6 +1103,7 @@ public void testStaticInstanceCF() {
}
@Test
+ @Disabled
public void testStaticStaticCF() {
instance.executeSource(
"""
@@ -1121,6 +1123,7 @@ public void testStaticStaticCF() {
}
@Test
+ @Disabled
public void testStaticImport() {
instance.executeSource(
"""
@@ -1140,6 +1143,7 @@ public void testStaticImport() {
}
@Test
+ @Disabled
public void testStaticImportDot() {
instance.executeSource(
"""
From a6b61de4308435b0ecd6dcfc6159f64367011346 Mon Sep 17 00:00:00 2001
From: Jacob Beers
Date: Mon, 2 Dec 2024 10:20:23 -0600
Subject: [PATCH 013/193] BL-806 Remove asm specific tests
---
.../asmboxpiler/DebugCatchResetNode.java | 30 +
src/test/java/TestCases/asm/BasicTest.java | 150 -
.../java/TestCases/asm/ComponentTest.java | 81 -
src/test/java/TestCases/asm/Operator.cfc | 8 -
.../java/TestCases/asm/control/IfTest.java | 208 --
.../TestCases/asm/control/SwitchTest.java | 187 --
.../TestCases/asm/control/TernaryTest.java | 100 -
.../TestCases/asm/integration/Controller.cfc | 1222 --------
.../asm/integration/ControllerTest.java | 187 --
.../asm/integration/ICacheProvider.cfc | 26 -
.../TestCases/asm/integration/Implementor.cfc | 12 -
.../asm/integration/TemplateWithReturn.cfm | 4 -
.../asm/integration/TryCatchLabelStack.cfc | 8 -
.../asm/literal/ArrayLiteralTest.java | 93 -
.../asm/literal/BooleanLiteralTest.java | 88 -
.../asm/literal/DoubleLiteralTest.java | 90 -
.../asm/literal/IntegerLiteralTest.java | 88 -
.../asm/literal/StringLiteralTest.java | 89 -
.../asm/literal/StructLiteralTest.java | 130 -
.../asm/operator/BinaryMinusOperatorTest.java | 137 -
.../asm/operator/BinaryPlusOperatorTest.java | 137 -
.../asm/operator/UnaryOperatorTest.java | 154 -
.../TestCases/asm/phase1/AssignmentTest.java | 215 --
.../TestCases/asm/phase1/CoreLangTest.java | 2506 -----------------
.../TestCases/asm/phase1/DereferenceTest.java | 256 --
.../TestCases/asm/phase1/LabeledLoopTest.java | 261 --
.../asm/phase1/ObjectCreationTest.java | 200 --
.../phase1/ObjectReferenceAssignmentTest.java | 396 ---
.../TestCases/asm/phase1/OperatorsTest.java | 967 -------
.../java/TestCases/asm/phase1/unicode.cfm | 2 -
.../TestCases/asm/phase3/AbstractClass.bx | 9 -
.../TestCases/asm/phase3/AbstractClassCF.cfc | 9 -
src/test/java/TestCases/asm/phase3/Animal.cfc | 36 -
.../TestCases/asm/phase3/ApplicationTest.java | 242 --
.../TestCases/asm/phase3/CFImportTest.cfc | 13 -
.../TestCases/asm/phase3/CFImportTest2.cfc | 13 -
.../java/TestCases/asm/phase3/Chihuahua.cfc | 17 -
src/test/java/TestCases/asm/phase3/Child.cfc | 12 -
.../asm/phase3/ClassLeadingComment.cfc | 12 -
.../java/TestCases/asm/phase3/ClassTest.java | 1268 ---------
.../asm/phase3/ClassTrailingComment.cfc | 7 -
.../asm/phase3/ClassWrappedInScript.cfc | 4 -
.../TestCases/asm/phase3/ConcreteClass.bx | 6 -
.../TestCases/asm/phase3/ConcreteClassCF.cfc | 6 -
src/test/java/TestCases/asm/phase3/Dog.cfc | 20 -
.../java/TestCases/asm/phase3/DotExtends.cfc | 5 -
.../TestCases/asm/phase3/DotExtendsParent.cfc | 5 -
.../TestCases/asm/phase3/ExceptionTest.java | 77 -
.../TestCases/asm/phase3/ExceptionThrower.cfs | 6 -
.../java/TestCases/asm/phase3/FinalClass.bx | 5 -
src/test/java/TestCases/asm/phase3/FindMe.bx | 5 -
.../TestCases/asm/phase3/FunctionMeta.cfc | 16 -
.../asm/phase3/GeneratedGetterChild.bx | 2 -
.../asm/phase3/GeneratedGetterParent.bx | 9 -
.../java/TestCases/asm/phase3/GetterTest.cfc | 10 -
.../java/TestCases/asm/phase3/IBicycle.bx | 11 -
.../TestCases/asm/phase3/IChildInterface.bx | 9 -
.../java/TestCases/asm/phase3/IMotorcycle.bx | 9 -
.../asm/phase3/IMultiChildInterface.bx | 12 -
.../TestCases/asm/phase3/IParentInterface.bx | 12 -
.../TestCases/asm/phase3/IUncleInterface.bx | 12 -
.../asm/phase3/IllegalFinalExtends.bx | 3 -
.../TestCases/asm/phase3/ImplicitAccessor.bx | 29 -
.../asm/phase3/ImplicitConstructorTest.cfc | 6 -
.../asm/phase3/ImplicitGeneratedAccessor.bx | 5 -
.../TestCases/asm/phase3/InitMethodTest.bx | 9 -
.../asm/phase3/InterfaceInheritenceTest.bx | 11 -
.../phase3/InterfaceMultiInheritenceTest.bx | 23 -
.../TestCases/asm/phase3/InterfaceStatic.bx | 16 -
.../TestCases/asm/phase3/InterfaceTest.java | 284 --
.../java/TestCases/asm/phase3/JavaExtends2.bx | 7 -
.../java/TestCases/asm/phase3/JavaExtends3.bx | 14 -
.../TestCases/asm/phase3/JavaExtendsAsm.bx | 16 -
.../TestCases/asm/phase3/JavaImplements.bx | 7 -
src/test/java/TestCases/asm/phase3/Moped.bx | 20 -
src/test/java/TestCases/asm/phase3/MyClass.bx | 50 -
.../java/TestCases/asm/phase3/MyClassCF.cfc | 36 -
.../TestCases/asm/phase3/MyInterfaceBL.bx | 19 -
.../TestCases/asm/phase3/MyInterfaceCF.cfc | 19 -
.../TestCases/asm/phase3/MyInterfaceCFTag.cfc | 19 -
.../TestCases/asm/phase3/OnMissingMethod.cfc | 5 -
src/test/java/TestCases/asm/phase3/Parent.cfc | 12 -
.../java/TestCases/asm/phase3/PropertyTest.bx | 25 -
.../TestCases/asm/phase3/PropertyTestCF.cfc | 18 -
.../asm/phase3/PseudoConstructorNoOutput.cfc | 3 -
.../asm/phase3/PseudoConstructorOutput.cfc | 3 -
.../asm/phase3/RelativeInstantiation.bx | 5 -
.../java/TestCases/asm/phase3/SeniorVespa.bx | 3 -
src/test/java/TestCases/asm/phase3/Stack.cfc | 10 -
.../java/TestCases/asm/phase3/StaticTest.bx | 33 -
.../TestCases/asm/phase3/StaticTestCF.cfc | 22 -
.../java/TestCases/asm/phase3/WheeledThing.bx | 13 -
92 files changed, 30 insertions(+), 10626 deletions(-)
create mode 100644 src/main/java/ortus/boxlang/compiler/asmboxpiler/DebugCatchResetNode.java
delete mode 100644 src/test/java/TestCases/asm/BasicTest.java
delete mode 100644 src/test/java/TestCases/asm/ComponentTest.java
delete mode 100644 src/test/java/TestCases/asm/Operator.cfc
delete mode 100644 src/test/java/TestCases/asm/control/IfTest.java
delete mode 100644 src/test/java/TestCases/asm/control/SwitchTest.java
delete mode 100644 src/test/java/TestCases/asm/control/TernaryTest.java
delete mode 100644 src/test/java/TestCases/asm/integration/Controller.cfc
delete mode 100644 src/test/java/TestCases/asm/integration/ControllerTest.java
delete mode 100644 src/test/java/TestCases/asm/integration/ICacheProvider.cfc
delete mode 100644 src/test/java/TestCases/asm/integration/Implementor.cfc
delete mode 100644 src/test/java/TestCases/asm/integration/TemplateWithReturn.cfm
delete mode 100644 src/test/java/TestCases/asm/integration/TryCatchLabelStack.cfc
delete mode 100644 src/test/java/TestCases/asm/literal/ArrayLiteralTest.java
delete mode 100644 src/test/java/TestCases/asm/literal/BooleanLiteralTest.java
delete mode 100644 src/test/java/TestCases/asm/literal/DoubleLiteralTest.java
delete mode 100644 src/test/java/TestCases/asm/literal/IntegerLiteralTest.java
delete mode 100644 src/test/java/TestCases/asm/literal/StringLiteralTest.java
delete mode 100644 src/test/java/TestCases/asm/literal/StructLiteralTest.java
delete mode 100644 src/test/java/TestCases/asm/operator/BinaryMinusOperatorTest.java
delete mode 100644 src/test/java/TestCases/asm/operator/BinaryPlusOperatorTest.java
delete mode 100644 src/test/java/TestCases/asm/operator/UnaryOperatorTest.java
delete mode 100644 src/test/java/TestCases/asm/phase1/AssignmentTest.java
delete mode 100644 src/test/java/TestCases/asm/phase1/CoreLangTest.java
delete mode 100644 src/test/java/TestCases/asm/phase1/DereferenceTest.java
delete mode 100644 src/test/java/TestCases/asm/phase1/LabeledLoopTest.java
delete mode 100644 src/test/java/TestCases/asm/phase1/ObjectCreationTest.java
delete mode 100644 src/test/java/TestCases/asm/phase1/ObjectReferenceAssignmentTest.java
delete mode 100644 src/test/java/TestCases/asm/phase1/OperatorsTest.java
delete mode 100644 src/test/java/TestCases/asm/phase1/unicode.cfm
delete mode 100644 src/test/java/TestCases/asm/phase3/AbstractClass.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/AbstractClassCF.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/Animal.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/ApplicationTest.java
delete mode 100644 src/test/java/TestCases/asm/phase3/CFImportTest.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/CFImportTest2.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/Chihuahua.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/Child.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/ClassLeadingComment.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/ClassTest.java
delete mode 100644 src/test/java/TestCases/asm/phase3/ClassTrailingComment.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/ClassWrappedInScript.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/ConcreteClass.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/ConcreteClassCF.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/Dog.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/DotExtends.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/DotExtendsParent.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/ExceptionTest.java
delete mode 100644 src/test/java/TestCases/asm/phase3/ExceptionThrower.cfs
delete mode 100644 src/test/java/TestCases/asm/phase3/FinalClass.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/FindMe.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/FunctionMeta.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/GeneratedGetterChild.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/GeneratedGetterParent.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/GetterTest.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/IBicycle.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/IChildInterface.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/IMotorcycle.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/IMultiChildInterface.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/IParentInterface.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/IUncleInterface.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/IllegalFinalExtends.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/ImplicitAccessor.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/ImplicitConstructorTest.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/ImplicitGeneratedAccessor.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/InitMethodTest.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/InterfaceInheritenceTest.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/InterfaceMultiInheritenceTest.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/InterfaceStatic.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/InterfaceTest.java
delete mode 100644 src/test/java/TestCases/asm/phase3/JavaExtends2.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/JavaExtends3.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/JavaExtendsAsm.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/JavaImplements.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/Moped.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/MyClass.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/MyClassCF.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/MyInterfaceBL.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/MyInterfaceCF.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/MyInterfaceCFTag.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/OnMissingMethod.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/Parent.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/PropertyTest.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/PropertyTestCF.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/PseudoConstructorNoOutput.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/PseudoConstructorOutput.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/RelativeInstantiation.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/SeniorVespa.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/Stack.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/StaticTest.bx
delete mode 100644 src/test/java/TestCases/asm/phase3/StaticTestCF.cfc
delete mode 100644 src/test/java/TestCases/asm/phase3/WheeledThing.bx
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/DebugCatchResetNode.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/DebugCatchResetNode.java
new file mode 100644
index 000000000..6898b6830
--- /dev/null
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/DebugCatchResetNode.java
@@ -0,0 +1,30 @@
+package ortus.boxlang.compiler.asmboxpiler;
+
+import java.util.Map;
+
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.LabelNode;
+
+public class DebugCatchResetNode extends AbstractInsnNode {
+
+ public DebugCatchResetNode() {
+ super( -1 );
+ }
+
+ @Override
+ public int getType() {
+ return -1;
+ }
+
+ @Override
+ public void accept( MethodVisitor methodVisitor ) {
+ return;
+ }
+
+ @Override
+ public AbstractInsnNode clone( Map clonedLabels ) {
+ return new DebugCatchResetNode();
+ }
+
+}
diff --git a/src/test/java/TestCases/asm/BasicTest.java b/src/test/java/TestCases/asm/BasicTest.java
deleted file mode 100644
index 521ca9f27..000000000
--- a/src/test/java/TestCases/asm/BasicTest.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-
-public class BasicTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "ASM Easy Difficulty Source Test" )
- @Test
- public void testEasySource() {
- instance.executeStatement(
- """
- result = 2;
-
- result += 2;
- """,
- context );
-
- assertThat( variables.getAsNumber( result ).doubleValue() ).isEqualTo( 4.0 );
- }
-
- @DisplayName( "ASM Medium Difficulty Source Test" )
- @Test
- public void testMediumSource() {
-// @formatter:off
- var output = instance.executeStatement(
- """
- colors = [
- "red",
- "orange",
- "yellow",
- "green",
- "blue",
- "purple"
- ];
-
- function getCircle( required numeric radius ){
- return {
- radius: radius,
- circumference: Pi() * radius * 2,
- color: colors[ 2 ]
- };
- }
-
- aCircle = getCircle( 5 );
-
- echo( "Generated a circle:
-" );
- echo( " radius: #aCircle.radius#
-" );
- echo( " circumference: #aCircle.circumference#
-" );
- echo( " color: #aCircle.color#
-" );
-
- getBoxContext().getBuffer().toString();
- """,
- context );
-
-
- assertThat( output ).isEqualTo( """
-Generated a circle:
- radius: 5
- circumference: 31.41592653589793238462643383279504
- color: orange
-""" );
- // @formatter:on
- }
-
- @DisplayName( "ASM Hard Difficulty Source Test" )
- @Test
- @Disabled( "Needs update for new constructor argument in Property record" )
- public void testHardSource() {
- var output = instance.executeStatement(
- """
- operator = new src.test.java.TestCases.asm.Operator();
-
- operator.setOperation( ( x ) -> x * 2 );
-
- echo( operator.run( 5 ) );
-
- getBoxContext().getBuffer().toString();
-
- // expected output
- // 10.0
- """,
- context );
-
- assertThat( output ).isEqualTo( "10" );
- }
-
-}
diff --git a/src/test/java/TestCases/asm/ComponentTest.java b/src/test/java/TestCases/asm/ComponentTest.java
deleted file mode 100644
index 80936e124..000000000
--- a/src/test/java/TestCases/asm/ComponentTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-
-public class ComponentTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "Will execute a component body" )
- @Test
- public void testComponentWithBody() {
- instance.executeSource(
- """
- result = "";
-
- savecontent variable="result" {
- writeOutput( "test" );
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( "test" );
- }
-
-}
diff --git a/src/test/java/TestCases/asm/Operator.cfc b/src/test/java/TestCases/asm/Operator.cfc
deleted file mode 100644
index cb709365c..000000000
--- a/src/test/java/TestCases/asm/Operator.cfc
+++ /dev/null
@@ -1,8 +0,0 @@
-
-component accessors = true {
- property name="operation";
-
- public numeric function run( required numeric value ){
- return operation( value );
- }
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/control/IfTest.java b/src/test/java/TestCases/asm/control/IfTest.java
deleted file mode 100644
index 464c77e1e..000000000
--- a/src/test/java/TestCases/asm/control/IfTest.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.control;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-
-public class IfTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "Will run the code inside of an if with a true condition" )
- @Test
- public void testTrueIfCondition() {
- instance.executeStatement(
- """
- result = 1;
-
- if( true ){
- result = 2;
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( 2 );
- }
-
- @DisplayName( "Will not run the code inside of an if with a true condition" )
- @Test
- public void testFalseIfCondition() {
- instance.executeStatement(
- """
- result = 1;
-
- if( false ){
- result = 2;
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( 1 );
- }
-
- @DisplayName( "Will run the code inside of an else with a true condition" )
- @Test
- public void testFalseIfElseCondition() {
- instance.executeStatement(
- """
- result = 1;
-
- if( false ){
- result = 2;
- }
- else {
- result = 3;
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( 3 );
- }
-
- @DisplayName( "Will not run the code inside of an else with a true condition" )
- @Test
- public void testTrueIfElseCondition() {
- instance.executeStatement(
- """
- result = 1;
-
- if( true ){
- result = 2;
- }
- else {
- result = 3;
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( 2 );
- }
-
- @DisplayName( "Will execute the first true branch of an if else statement" )
- @Test
- public void testExecuteFirstTrueBranch() {
- instance.executeStatement(
- """
- result = 1;
-
- if( false ){
- result = 2;
- }
- else if( true ) {
- result = 3;
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( 3 );
- }
-
- @DisplayName( "Will the else if no branchs are true" )
- @Test
- public void testExecuteElseBranch() {
- instance.executeStatement(
- """
- result = 1;
-
- if( false ){
- result = 2;
- }
- else if( false ) {
- result = 3;
- }
- else {
- result = 4;
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( 4 );
- }
-
- @DisplayName( "Will execute a branch behind a true expression" )
- @Test
- public void testTrueExpressionExpression() {
- instance.executeStatement(
- """
- result = 1;
-
- if( 2 + 2 > 3 ){
- result = 2;
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( 2 );
- }
-
- @DisplayName( "Will not execute a branch behind a false expression" )
- @Test
- public void testFalseExpression() {
- instance.executeStatement(
- """
- result = 1;
-
- if( 2 + 2 == 3 ){
- result = 2;
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( 1 );
- }
-
-}
diff --git a/src/test/java/TestCases/asm/control/SwitchTest.java b/src/test/java/TestCases/asm/control/SwitchTest.java
deleted file mode 100644
index 622495118..000000000
--- a/src/test/java/TestCases/asm/control/SwitchTest.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.control;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-
-public class SwitchTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "Will not execute code that doesn't match a condition" )
- @Test
- public void testWillNotExecuteUnMatchedBranches() {
- instance.executeStatement(
- """
- result = 1;
-
- switch( "test" ){
- case "testx": result = 4;
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( 1 );
- }
-
- @DisplayName( "Will execute code that matches a condition" )
- @Test
- public void testWillExecuteMatchedBranches() {
- instance.executeStatement(
- """
- result = 1;
-
- switch( "test" ){
- case "test": result = 4;
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( 4 );
- }
-
- @DisplayName( "Will only execute code that matches a condition" )
- @Test
- public void testSkipUnmatchedBranches() {
- instance.executeStatement(
- """
- result = 1;
-
- switch( "test" ){
- case 4: result = 3;
- case "test": result = 4;
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( 4 );
- }
-
- @DisplayName( "Will execute every branch after a match" )
- @Test
- public void testFallThrough() {
- instance.executeStatement(
- """
- result = 1;
-
- switch( "test" ){
- case 4: result = 3;
- case "test": result = 4;
- case "multiply": result = result * 2;
- }
- """,
- context );
-
- assertThat( variables.getAsNumber( result ).doubleValue() ).isEqualTo( 8 );
- }
-
- @DisplayName( "Will stop executing on a break statement" )
- @Test
- public void testBreak() {
- instance.executeStatement(
- """
- result = 1;
-
- switch( "test" ){
- case 4: result = 3;
- case "test": result = 4; break;
- case "multiply": result = result * 2;
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( 4 );
- }
-
- @DisplayName( "Will accept values of different types" )
- @Test
- public void testDifferntTypes() {
- instance.executeStatement(
- """
- result = 1;
-
- switch( "4" ){
- case 4: result = 3; break;
- case "test": result = 4; break;
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( 3 );
- ;
- }
-
- @DisplayName( "Will execute the default case if no conditions match" )
- @Test
- public void testDefault() {
- instance.executeStatement(
- """
- result = 1;
-
- switch( "x" ){
- case 4: result = 3; break;
- case "test": result = 4; break;
- default: result = "no match";
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( "no match" );
- ;
- }
-
-}
diff --git a/src/test/java/TestCases/asm/control/TernaryTest.java b/src/test/java/TestCases/asm/control/TernaryTest.java
deleted file mode 100644
index 8c71f2cad..000000000
--- a/src/test/java/TestCases/asm/control/TernaryTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.control;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-
-public class TernaryTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "Will return the true option of a ternary when condition is true" )
- @Test
- public void testTrueResult() {
- var result = instance.executeStatement(
- """
- true ? "red": "green";
- """,
- context );
-
- assertThat( result ).isEqualTo( "red" );
- }
-
- @DisplayName( "Will return the false option of a ternary when condition is false" )
- @Test
- public void testFalseResult() {
- var result = instance.executeStatement(
- """
- false ? "red": "green";
- """,
- context );
-
- assertThat( result ).isEqualTo( "green" );
- }
-
- @DisplayName( "Can assign from a ternary" )
- @Test
- public void testAssignFromTernary() {
- instance.executeStatement(
- """
- result = true ? 1 : 2;
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( 1 );
- }
-}
diff --git a/src/test/java/TestCases/asm/integration/Controller.cfc b/src/test/java/TestCases/asm/integration/Controller.cfc
deleted file mode 100644
index a982c3c46..000000000
--- a/src/test/java/TestCases/asm/integration/Controller.cfc
+++ /dev/null
@@ -1,1222 +0,0 @@
-/**
- * Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp
- * www.ortussolutions.com
- * ---
- * Manages a ColdBox application, dispatches events and acts as an overall front controller.
- */
-component serializable="false" accessors="true" {
-
- /**
- * The CFML engine helper
- */
- property name="CFMLEngine";
-
- /**
- * The system utility object
- */
- property name="util";
-
- /**
- * ColdBox initiation flag
- */
- property name="coldboxInitiated" type="boolean";
-
- /**
- * ColdBox application key that tracks the controller in the `application` scope
- */
- property name="appKey";
-
- /**
- * ColdBox application root path
- */
- property name="appRootPath";
-
- /**
- * ColdBox application unique hash key
- */
- property name="appHash";
-
- /**
- * The ColdFusion application name as per the application scope
- */
- property name="appName";
-
- /**
- * Container for all internal services (ordered struct)
- */
- property name="services";
-
- /**
- * The application configuration settings structure
- */
- property name="configSettings" type="struct";
-
- /**
- * The internal ColdBox settings structure
- */
- property name="coldboxSettings" type="struct";
-
- /**
- * The reference to CacheBox
- */
- property name="cachebox";
-
- /**
- * The reference to WireBox
- */
- property name="wirebox";
-
- /**
- * The reference to LogBox
- */
- property name="logbox";
-
- /**
- * The controller logger object
- */
- property name="log";
-
- /**
- * The view/layout renderer singleton
- */
- property name="renderer";
-
- /**
- * The Application's AsyncManager
- */
- property name="asyncManager";
-
-
- /****************************************************************
- * Global Getters *
- ****************************************************************/
-
- /**
- * Get controller memento, used only by decorator only.
- */
- function getMemento(){
- return { "variables" : variables };
- }
-
- /**
- * Get the system web renderer, you can also retrieve it from wirebox via renderer@coldbox
- *
- * @return coldbox.system.web.Renderer
- */
- function getRenderer(){
- // Persist on first creation
- if ( isSimpleValue( variables.renderer ) ) {
- variables.renderer = variables.wireBox.getInstance( "Renderer@coldbox" );
- }
- return variables.renderer;
- }
-
- /**
- * Get the system data marshaller, you can also retrieve it from wirebox via dataMarshaller@coldbox
- *
- * @return coldbox.system.core.conversion.DataMarhsaller
- */
- function getDataMarshaller(){
- return variables.wireBox.getInstance( "DataMarshaller@coldbox" );
- }
-
- /**
- * Get a Cache provider from CacheBox
- *
- * @cacheName The name of the cache to retrieve, or it defaults to the 'default' cache.
- *
- * @return coldbox.system.cache.providers.IColdBoxProvider
- */
- function getCache( required cacheName = "default" ){
- return variables.cacheBox.getCache( arguments.cacheName );
- }
-
- /**
- * Get the loader service
- */
- function getLoaderService(){
- return services.loaderService;
- }
-
- /**
- * Get the module service
- */
- function getModuleService(){
- return services.moduleService;
- }
-
- /**
- * Get the interceptor service
- */
- function getInterceptorService(){
- return services.interceptorService;
- }
-
- /**
- * Get the handler service
- */
- function getHandlerService(){
- return services.handlerService;
- }
-
- /**
- * Get the request service
- */
- function getRequestService(){
- return services.requestService;
- }
-
- /**
- * Get the routing service
- */
- function getRoutingService(){
- return services.routingService;
- }
-
- /**
- * Get the scheduling service
- */
- function getSchedulerService(){
- return services.schedulerService;
- }
-
- /****************************************************************
- * Setting Methods *
- ****************************************************************/
-
- /**
- * Get a setting from the application
- *
- * @name The name of the setting
- * @defaultValue The default value to use if setting does not exist
- *
- * @return The application setting value
- *
- * @throws SettingNotFoundException
- */
- function getSetting( required name, defaultValue ){
- if ( variables.configSettings.keyExists( arguments.name ) ) {
- return variables.configSettings[ arguments.name ];
- }
-
- // Default value
- if ( !isNull( arguments.defaultValue ) ) {
- return arguments.defaultValue;
- }
-
- throw(
- message = "The application setting #arguments.name# does not exist.",
- detail = "Available settings are #variables.configSettings.keyList()#",
- type = "SettingNotFoundException"
- );
- }
-
- /**
- * Get a ColdBox setting
- *
- * @name The key to get
- * @defaultValue The default value if it doesn't exist
- *
- * @return The framework setting value
- *
- * @throws SettingNotFoundException
- */
- function getColdBoxSetting( required name, defaultValue ){
- if ( variables.coldboxSettings.keyExists( arguments.name ) ) {
- return variables.coldboxSettings[ arguments.name ];
- }
-
- // Default value
- if ( !isNull( arguments.defaultValue ) ) {
- return arguments.defaultValue;
- }
-
- throw(
- message = "The ColdBox setting #arguments.name# does not exist.",
- detail = "Available settings are #variables.coldboxSettings.keyList()#",
- type = "SettingNotFoundException"
- );
- }
-
- /**
- * Check if the setting exists in the application
- *
- * @name The name of the setting
- */
- boolean function settingExists( required name ){
- return ( structKeyExists( variables.configSettings, arguments.name ) );
- }
-
- /**
- * Set a value in the application configuration settings
- *
- * @name The name of the setting
- * @value The value to set
- *
- * @return Controller instance
- */
- Controller function setSetting( required name, required value ){
- variables.configSettings[ arguments.name ] = arguments.value;
- return this;
- }
-
- /**
- * Get a module's settings structure or a specific setting if the setting key is passed
- *
- * @module The module to retrieve the configuration settings from
- * @setting The setting to retrieve if passed
- * @defaultValue The default value to return if setting does not exist
- *
- * @return struct or any
- */
- any function getModuleSettings( required module, setting, defaultValue ) cbMethod{
- var moduleSettings = getModuleConfig( arguments.module ).settings;
- // return specific setting?
- if ( !isNull( arguments.setting ) ) {
- return (
- structKeyExists( moduleSettings, arguments.setting ) ? moduleSettings[ arguments.setting ] : arguments.defaultValue
- );
- }
- return moduleSettings;
- }
-
- /**
- * Get a module's configuration structure
- *
- * @module The module to retrieve the configuration structure from
- *
- * @return The struct requested
- *
- * @throws InvalidModuleException - The module passed is invalid
- */
- struct function getModuleConfig( required module ){
- var mConfig = getSetting( "modules" );
- if ( structKeyExists( mConfig, arguments.module ) ) {
- return mConfig[ arguments.module ];
- }
- throw(
- message = "The module you passed #arguments.module# is invalid.",
- detail = "The loaded modules are #structKeyList( mConfig )#",
- type = "InvalidModuleException"
- );
- }
-
- /**
- * Determine if the application is in the `debugMode` or not
- */
- boolean function inDebugMode(){
- return getSetting( "debugMode", false );
- }
-
- /**
- * Determine if the application is in the `development|local` environment
- */
- boolean function isDevelopment(){
- return listFindNoCase( "development,local", getSetting( "environment", "production" ) );
- }
-
- /**
- * Determine if the application is in the `production` environment
- */
- boolean function isProduction(){
- return getSetting( "environment", "production" ) == "production";
- }
-
- /**
- * Determine if the application is in the `testing` environment or in a testing.MockController execution
- */
- boolean function isTesting(){
- return getSetting( "environment", "production" ) == "testing" || isInstanceOf( this, "MockController" );
- }
-
- /****************************************************************
- * Deprecated Methods *
- ****************************************************************/
-
- /****************************************************************
- * Relocation Helpers *
- ****************************************************************/
-
- /**
- * Relocate user browser requests to other events, URLs, or URIs.
- *
- * @event The name of the event to relocate to, if not passed, then it will use the default event found in your configuration file.
- * @queryString The query string or a struct to append, if needed. If in SES mode it will be translated to convention name value pairs
- * @addToken Wether to add the tokens or not to the relocation. Default is false
- * @persist What request collection keys to persist in flash RAM automatically for you
- * @persistStruct A structure of key-value pairs to persist in flash RAM automatically for you
- * @ssl Whether to relocate in SSL or not. You need to explicitly say TRUE or FALSE if going out from SSL. If none passed, we look at the even's SES base URL (if in SES mode)
- * @baseURL Use this baseURL instead of the index.cfm that is used by default. You can use this for SSL or any full base url you would like to use. Ex: https://mysite.com/index.cfm
- * @postProcessExempt Do not fire the postProcess interceptors, by default it does
- * @URL The full URL you would like to relocate to instead of an event: ex: URL='http://www.google.com'
- * @URI The relative URI you would like to relocate to instead of an event: ex: URI='/mypath/awesome/here'
- * @statusCode The status code to use in the relocation
- *
- * @return Controller
- */
- // function relocate(
- // event = getSetting( "DefaultEvent" ),
- // queryString = "",
- // boolean addToken = false,
- // persist = "",
- // struct persistStruct = structNew()
- // boolean ssl,
- // baseURL = "",
- // boolean postProcessExempt = false,
- // URL,
- // URI,
- // numeric statusCode = 302
- // ){
- // // StatusCode 0 then default it to 302 for backwards compat: Remove by ColdBox 7
- // if ( arguments.statusCode == 0 ) {
- // arguments.statusCode = 302;
- // }
- // // Determine the type of relocation
- // var relocationType = "SES";
- // var relocationURL = "";
- // var eventName = variables.configSettings[ "EventName" ];
- // var frontController = listLast( CGI.SCRIPT_NAME, "/" );
- // var oRequestContext = services.requestService.getContext();
- // var routeString = 0;
-
- // // Determine relocation type
- // if ( !isNull( arguments.url ) && len( arguments.url ) ) {
- // relocationType = "URL";
- // }
- // if ( !isNull( arguments.URI ) && len( arguments.URI ) ) {
- // relocationType = "URI";
- // }
-
- // // Cleanup event string to default if not sent in
- // if ( len( trim( arguments.event ) ) eq 0 ) {
- // arguments.event = getSetting( "DefaultEvent" );
- // }
-
- // // Query String Struct to String
- // if ( isStruct( arguments.queryString ) ) {
- // arguments.queryString = arguments.queryString
- // .reduce( function( result, key, value ){
- // arguments.result.append( "#encodeForURL( arguments.key )#=#encodeForURL( arguments.value )#" );
- // return arguments.result;
- // }, [] )
- // .toList( "&" );
- // }
-
- // // Overriding Front Controller via baseURL argument
- // if ( len( trim( arguments.baseURL ) ) ) {
- // frontController = arguments.baseURL;
- // }
-
- // // Relocation Types
- // switch ( relocationType ) {
- // // FULL URL relocations
- // case "URL": {
- // relocationURL = arguments.URL;
- // // Check SSL?
- // if ( !isNull( arguments.ssl ) ) {
- // relocationURL = updateSSL( relocationURL, arguments.ssl );
- // }
- // // Query String?
- // if ( len( trim( arguments.queryString ) ) ) {
- // relocationURL = relocationURL & "?#arguments.queryString#";
- // }
- // break;
- // }
-
- // // URI relative relocations
- // case "URI": {
- // relocationURL = arguments.URI;
- // // Query String?
- // if ( len( trim( arguments.queryString ) ) ) {
- // relocationURL = relocationURL & "?#arguments.queryString#";
- // }
- // break;
- // }
-
- // // Default event relocations
- // default: {
- // // Convert module into proper entry point
- // if ( listLen( arguments.event, ":" ) > 1 ) {
- // var mConfig = getSetting( "modules" );
- // var module = listFirst( arguments.event, ":" );
- // if ( structKeyExists( mConfig, module ) ) {
- // arguments.event = mConfig[ module ].inheritedEntryPoint & "/" & listRest(
- // arguments.event,
- // ":"
- // );
- // }
- // }
- // // Route String start by converting event syntax to / syntax
- // routeString = replace( arguments.event, ".", "/", "all" );
- // // Convert Query String to convention name value-pairs
- // if ( len( trim( arguments.queryString ) ) ) {
- // // If the routestring ends with '/' we do not want to
- // // double append '/'
- // if ( right( routeString, 1 ) NEQ "/" ) {
- // routeString = routeString & "/" & replace( arguments.queryString, "&", "/", "all" );
- // } else {
- // routeString = routeString & replace( arguments.queryString, "&", "/", "all" );
- // }
- // routeString = replace( routeString, "=", "/", "all" );
- // }
-
- // // Get Base relocation URL from context
- // relocationURL = oRequestContext.getSESBaseURL();
- // // if the sesBaseURL is nothing, set it to the setting
- // if ( !len( relocationURL ) ) {
- // relocationURL = getSetting( "sesBaseURL" );
- // }
- // // add the trailing slash if there isnt one
- // if ( right( relocationURL, 1 ) neq "/" ) {
- // relocationURL = relocationURL & "/";
- // }
- // // Check SSL?
- // if ( !isNull( arguments.ssl ) ) {
- // relocationURL = updateSSL( relocationURL, arguments.ssl );
- // }
-
- // // Finalize the URL
- // relocationURL = relocationURL & routeString;
-
- // break;
- // }
- // }
-
- // // persist Flash RAM
- // persistVariables( argumentCollection = arguments );
-
- // // Post Processors
- // if ( NOT arguments.postProcessExempt ) {
- // services.interceptorService.announce( "postProcess" );
- // }
-
- // // Save Flash RAM
- // if ( variables.configSettings.flash.autoSave ) {
- // services.requestService.getFlashScope().saveFlash();
- // }
-
- // // Send Relocation
- // sendRelocation(
- // URL = relocationURL,
- // addToken = arguments.addToken,
- // statusCode = arguments.statusCode
- // );
-
- // return this;
- // }
-
- /****************************************************************
- * Runner Methods *
- ****************************************************************/
-
- /**
- * Executes internal named routes with or without parameters. If the named route is not found or the route has no event to execute then this method will throw an `InvalidArgumentException`.
- * If you need a route from a module then append the module address: `@moduleName` or prefix it like in run event calls `moduleName:routeName` in order to find the right route.
- * The route params will be passed to events as action arguments much how eventArguments work.
- *
- * @name The name of the route
- * @params The parameters of the route to replace
- * @cache Cached the output of the runnable execution, defaults to false. A unique key will be created according to event string + arguments.
- * @cacheTimeout The time in minutes to cache the results
- * @cacheLastAccessTimeout The time in minutes the results will be removed from cache if idle or requested
- * @cacheSuffix The suffix to add into the cache entry for this event rendering
- * @cacheProvider The provider to cache this event rendering in, defaults to 'template'
- * @prePostExempt If true, pre/post handlers will not be fired. Defaults to false
- *
- * @throws InvalidArgumentException
- */
- any function runRoute(
- required name,
- struct params = {},
- boolean cache = false,
- cacheTimeout = "",
- cacheLastAccessTimeout = "",
- cacheSuffix = "",
- cacheProvider = "template",
- boolean prePostExempt = false
- ){
- // Module Route?
- var targetModule = "";
- if ( find( "@", arguments.name ) ) {
- targetModule = getToken( arguments.name, 2, "@" );
- }
- if ( find( ":", arguments.name ) ) {
- targetModule = getToken( arguments.name, 1, ":" );
- }
-
- // Find the named route
- var foundRoute = getWirebox().getInstance( "router@coldbox" ).findRouteByName( arguments.name );
-
- // Did we find it?
- if ( !foundRoute.isEmpty() ) {
- var event = services.requestService.getContext();
-
- // Do we have a response closure
- if ( isClosure( foundRoute.response ) || isCustomFunction( foundRoute.response ) ) {
- return foundRoute.response(
- event,
- event.getCollection(),
- event.getPrivateCollection(),
- arguments.params
- );
- }
-
- // Prepare the event if it has a module + event arguments
- arguments.event = ( len( targetModule ) ? "#targetModule#:" : "" );
- arguments.eventArguments = arguments.params;
-
- // Do we have an event to execute?
- if ( len( foundRoute.event ) ) {
- arguments.event &= foundRoute.event;
- return runEvent( argumentCollection = arguments );
- }
-
- // If not, do we have a handler + action combo?
- if ( len( foundRoute.handler ) ) {
- arguments.event &= foundRoute.handler & "." & (
- len( foundRoute.action ) ? foundRoute.action : "index"
- );
- return runEvent( argumentCollection = arguments );
- }
-
- throw(
- type = "InvalidArgumentException",
- message = "The named route '#arguments.name#' has not executable"
- );
- }
-
- throw( type = "InvalidArgumentException", message = "The named route '#arguments.name#' does not exist" );
- }
-
- /**
- * Executes events with full life-cycle methods and returns the event results if any were returned.
- *
- * @event The event string to execute, if nothing is passed we will execute the application's default event.
- * @prePostExempt If true, pre/post handlers will not be fired. Defaults to false
- * @private Execute a private event if set, else defaults to public events
- * @defaultEvent The flag that let's this service now if it is the default event running or not. USED BY THE FRAMEWORK ONLY
- * @eventArguments A collection of arguments to passthrough to the calling event handler method
- * @cache Cached the output of the runnable execution, defaults to false. A unique key will be created according to event string + arguments.
- * @cacheTimeout The time in minutes to cache the results
- * @cacheLastAccessTimeout The time in minutes the results will be removed from cache if idle or requested
- * @cacheSuffix The suffix to add into the cache entry for this event rendering
- * @cacheProvider The provider to cache this event rendering in, defaults to 'template'
- *
- * @return null or any
- */
- function runEvent(
- event = "",
- boolean prePostExempt = false,
- boolean private = false,
- boolean defaultEvent = false,
- struct eventArguments = {},
- boolean cache = false,
- cacheTimeout = "",
- cacheLastAccessTimeout = "",
- cacheSuffix = "",
- cacheProvider = "template"
- ){
- // Determine if we need to cache handler response
- var isCachingOn = getSetting( "eventCaching" ) && arguments.cache;
-
- // Check if event empty, if empty then use default event
- if ( NOT len( trim( arguments.event ) ) ) {
- arguments.event = services.requestService.getContext().getCurrentEvent();
- }
-
- if ( isCachingOn ) {
- // Build cache references
- var oCache = variables.cachebox.getCache( arguments.cacheProvider );
- var oEventURLFacade = oCache.getEventURLFacade();
- var cacheKey = oEventURLFacade.buildBasicCacheKey(
- keySuffix = arguments.cacheSuffix,
- targetEvent = arguments.event
- ) & hash( arguments.eventArguments.toString() );
-
- // Test if entry found in cache, and return if found.
- var data = oCache.get( cacheKey );
- if ( !isNull( local.data ) ) {
- return data;
- }
- }
-
- // Execute our event
- var results = _runEvent( argumentCollection = arguments );
-
- // Do we have an object coming back?
- if (
- !isNull( local.results.data ) &&
- isObject( local.results.data )
- ) {
- // Verify $renderdata method convention
- if ( structKeyExists( local.results.data, "$renderdata" ) ) {
- local.results.data = local.results.data.$renderdata();
- }
- // Check if request context and ignore
- else if ( structKeyExists( local.results.data, "cbRequestContext" ) ) {
- local.results.delete( "data" );
- }
- }
-
- // Do we need to do action renderings?
- if (
- !isNull( local.results.data ) &&
- local.results.ehBean.getActionMetadata( "renderdata", "html" ) neq "html"
- ) {
- // Do action Rendering
- services.requestService
- .getContext()
- .renderdata(
- type = local.results.ehBean.getActionMetadata( "renderdata" ),
- data = local.results.data
- );
- }
-
- // Are we caching
- if ( isCachingOn && !isNull( local.results.data ) ) {
- oCache.set(
- objectKey = cacheKey,
- object = local.results.data,
- timeout = arguments.cacheTimeout,
- lastAccessTimeout = arguments.cacheLastAccessTimeout
- );
- }
-
- // Are we returning data?
- if ( !isNull( local.results.data ) ) {
- return local.results.data;
- }
- }
-
- /**
- * Executes events with full life-cycle methods and returns the event results if any were returned
- *
- * @event The event string to execute, if nothing is passed we will execute the application's default event.
- * @prePostExempt If true, pre/post handlers will not be fired. Defaults to false
- * @private Execute a private event if set, else defaults to public events
- * @defaultEvent The flag that let's this service now if it is the default event running or not. USED BY THE FRAMEWORK ONLY
- * @eventArguments A collection of arguments to passthrough to the calling event handler method
- *
- * @return struct { data:event handler returned data (null), ehBean:event handler bean representation that was fired }
- *
- * @throws InvalidHTTPMethod
- */
- private function _runEvent(
- event = "",
- boolean prePostExempt = false,
- boolean private = false,
- boolean defaultEvent = false,
- struct eventArguments = {}
- ){
- var oRequestContext = services.requestService.getContext();
- var results = { "data" : javacast( "null", "" ), "ehBean" : "" };
-
- // Setup Invoker args
- var args = {
- event : oRequestContext,
- rc : oRequestContext.getCollection(),
- prc : oRequestContext.getPrivateCollection(),
- eventArguments : arguments.eventArguments
- };
-
- // Setup Main Invoker Args with event arguments
- var argsMain = { event : oRequestContext, rc : args.rc, prc : args.prc };
- structAppend( argsMain, arguments.eventArguments );
-
- // Setup interception data
- var iData = {
- "processedEvent" : arguments.event,
- "eventArguments" : arguments.eventArguments,
- "data" : "",
- "ehBean" : "",
- "handler" : ""
- };
-
- // Reset Invalid Event if default, just in case listeners used metadata
- if ( arguments.defaultEvent ) {
- structDelete( request, "_lastInvalidEvent" );
- }
-
- // Validate the incoming event and get a handler bean to continue execution
- results.ehBean = services.handlerService
- .getHandlerBean( arguments.event )
- .setIsPrivate( arguments.private );
-
- // Validate this is not a view dispatch, else return for rendering
- if ( results.ehBean.getViewDispatch() ) {
- return results;
- }
-
- // Now get the correct handler to execute
- var oHandler = services.handlerService.getHandler( results.ehBean, oRequestContext );
-
- // Validate again this is not a view dispatch as the handler might exist but not the action
- if ( results.ehBean.getViewDispatch() ) {
- return results;
- }
-
- try {
- // Determine allowed methods in action metadata
- if ( structKeyExists( results.ehBean.getActionMetadata(), "allowedMethods" ) ) {
- // incorporate it to the handler
- oHandler.allowedMethods[ results.ehBean.getMethod() ] = results.ehBean.getActionMetadata(
- "allowedMethods"
- );
- }
-
- // Determine if it is An allowed HTTP method to execute, else throw error
- if (
- arguments.defaultEvent AND
- NOT structIsEmpty( oHandler.allowedMethods ) AND
- structKeyExists( oHandler.allowedMethods, results.ehBean.getMethod() ) AND
- NOT listFindNoCase(
- oHandler.allowedMethods[ results.ehBean.getMethod() ],
- oRequestContext.getHTTPMethod()
- )
- ) {
- oRequestContext.setHTTPHeader(
- statusCode = 405,
- statusText = "Invalid HTTP Method: '#oRequestContext.getHTTPMethod()#'"
- );
- // set Invalid HTTP method in context
- oRequestContext.setIsInvalidHTTPMethod();
- // Do we have a local handler for this exception, if so, call it
- if ( oHandler._actionExists( "onInvalidHTTPMethod" ) ) {
- results.data = oHandler.onInvalidHTTPMethod(
- event = oRequestContext,
- rc = args.rc,
- prc = args.prc,
- faultAction = results.ehBean.getmethod(),
- eventArguments = arguments.eventArguments
- );
- return results;
- }
-
- // Do we have the invalidHTTPMethodHandler setting? If so, call it.
- if ( len( getSetting( "invalidHTTPMethodHandler" ) ) ) {
- return _runEvent( event = getSetting( "invalidHTTPMethodHandler" ) );
- }
-
- // Throw Exception, no handlers defined
- throw(
- message = "Invalid HTTP Method: '#oRequestContext.getHTTPMethod()#'",
- detail = "The requested event: #arguments.event# cannot be executed using the incoming HTTP request method '#oRequestContext.getHTTPMethod()#'",
- type = "InvalidHTTPMethod"
- );
- }
-
- // SES Invalid HTTP Routing
- if ( arguments.defaultEvent && oRequestContext.isInvalidHTTPMethod() ) {
- // Do we have a local handler for this exception, if so, call it
- if ( oHandler._actionExists( "onInvalidHTTPMethod" ) ) {
- results.data = oHandler.onInvalidHTTPMethod(
- event = oRequestContext,
- rc = args.rc,
- prc = args.prc,
- faultAction = results.ehBean.getmethod(),
- eventArguments = arguments.eventArguments
- );
- return results;
- }
-
- // Do we have the invalidHTTPMethodHandler setting? If so, call it.
- if ( len( getSetting( "invalidHTTPMethodHandler" ) ) ) {
- return _runEvent( event = getSetting( "invalidHTTPMethodHandler" ) );
- }
-
- // Throw Exception, no handlers defined
- oRequestContext.setHTTPHeader(
- statusCode = 405,
- statusText = "Invalid HTTP Method: '#oRequestContext.getHTTPMethod()#'"
- );
- throw(
- message = "Invalid HTTP Method: '#oRequestContext.getHTTPMethod()#'",
- detail = "The requested URL: #oRequestContext.getCurrentRoutedURL()# cannot be executed using the incoming HTTP request method '#oRequestContext.getHTTPMethod()#'",
- type = "InvalidHTTPMethod"
- );
- }
-
- // PRE ACTIONS
- if ( NOT arguments.prePostExempt ) {
- // PREEVENT Interceptor
- services.interceptorService.announce( "preEvent", iData );
-
- // Verify if event was overridden
- if ( arguments.event NEQ iData.processedEvent ) {
- // Validate the overridden event
- results.ehBean = services.handlerService.getHandlerBean( iData.processedEvent );
- // Get new handler to follow execution
- oHandler = services.handlerService.getHandler( results.ehBean, oRequestContext );
- }
-
- // Execute Pre Handler if it exists and valid?
- if (
- oHandler._actionExists( "preHandler" ) AND
- validateAction(
- results.ehBean.getMethod(),
- oHandler.PREHANDLER_ONLY,
- oHandler.PREHANDLER_EXCEPT
- )
- ) {
- oHandler.preHandler(
- event = oRequestContext,
- rc = args.rc,
- prc = args.prc,
- action = results.ehBean.getMethod(),
- eventArguments = arguments.eventArguments
- );
- }
-
- // Execute pre{Action}? if it exists and valid?
- if ( oHandler._actionExists( "pre#results.ehBean.getMethod()#" ) ) {
- invoker(
- target = oHandler,
- method = "pre#results.ehBean.getMethod()#",
- argCollection = args
- );
- }
- }
-
- // Verify if event was overridden
- if ( arguments.defaultEvent and arguments.event NEQ oRequestContext.getCurrentEvent() ) {
- // Validate the overridden event
- results.ehBean = services.handlerService.getHandlerBean( oRequestContext.getCurrentEvent() );
- // Get new handler to follow execution
- oHandler = services.handlerService.getHandler( results.ehBean, oRequestContext );
- }
-
- // Invoke onMissingAction event
- if ( results.ehBean.isMissingAction() ) {
- results.data = oHandler.onMissingAction(
- event = oRequestContext,
- rc = args.rc,
- prc = args.prc,
- missingAction = results.ehBean.getMissingAction(),
- eventArguments = arguments.eventArguments
- );
- }
- // Invoke main event
- else {
- // Around {Action} Advice Check?
- if ( oHandler._actionExists( "around#results.ehBean.getMethod()#" ) ) {
- // Add target Action
- args.targetAction = oHandler[ results.ehBean.getMethod() ];
- results.data = invoker(
- target = oHandler,
- method = "around#results.ehBean.getMethod()#",
- argCollection = args
- );
- // Cleanup: Remove target action from args for post events
- structDelete( args, "targetAction" );
- }
- // Around Handler Advice Check?
- else if (
- !arguments.prePostExempt
- &&
- oHandler._actionExists( "aroundHandler" )
- &&
- validateAction(
- results.ehBean.getMethod(),
- oHandler.aroundHandler_only,
- oHandler.aroundHandler_except
- )
- ) {
- results.data = oHandler.aroundHandler(
- event = oRequestContext,
- rc = args.rc,
- prc = args.prc,
- targetAction = oHandler[ results.ehBean.getMethod() ],
- eventArguments = arguments.eventArguments
- );
- } else {
- // Normal execution
- results.data = invoker(
- target = oHandler,
- method = results.ehBean.getMethod(),
- argCollection = argsMain,
- private = arguments.private
- );
- }
- }
-
- // POST ACTIONS
- if ( NOT arguments.prePostExempt ) {
- // Execute post{Action}?
- if ( oHandler._actionExists( "post#results.ehBean.getMethod()#" ) ) {
- invoker(
- target = oHandler,
- method = "post#results.ehBean.getMethod()#",
- argCollection = args
- );
- }
-
- // Execute postHandler()?
- if (
- oHandler._actionExists( "postHandler" ) AND
- validateAction(
- results.ehBean.getMethod(),
- oHandler.POSTHANDLER_ONLY,
- oHandler.POSTHANDLER_EXCEPT
- )
- ) {
- oHandler.postHandler(
- event = oRequestContext,
- rc = args.rc,
- prc = args.prc,
- action = results.ehBean.getMethod(),
- eventArguments = arguments.eventArguments
- );
- }
-
- // Execute postEvent interceptor
- iData.handler = oHandler;
- iData.append( results );
- services.interceptorService.announce( "postEvent", iData );
- }
- // end if prePostExempt
- } catch ( any e ) {
- // onError convention
- if ( oHandler._actionExists( "onError" ) ) {
- results.data = oHandler.onError(
- event = oRequestContext,
- rc = args.rc,
- prc = args.prc,
- faultAction = results.ehBean.getmethod(),
- exception = e,
- eventArguments = arguments.eventArguments
- );
- } else {
- // Bubble up the error
- rethrow;
- }
- }
-
- return results;
- }
-
- /****************************************************************
- * App + User Locator Methods *
- ****************************************************************/
-
- /**
- * This method will return the unique user's request tracking identifier according to our discovery algoritm:
- *
- * 1. If we have an identifierProvider closure/lambda/udf, then call it and use it
- * 2. If we have session enabled, use the jessionId or session URL Token
- * 3. If we have cookies enabled, use the cfid/cftoken
- * 4. If we have in the URL the cfid/cftoken
- * 5. Create a request based tracking identifier: cbUserTrackingId
- */
- string function getUserSessionIdentifier(){
- // Setup global storage prefix according to app name in case we have multiple apps with storages
- var prefix = "coldbox:#variables.appName#:";
- var isSessionDefined = getApplicationMetadata().sessionManagement;
-
- // Check settings identifier provider
- if ( !isSimpleValue( variables.configSettings.identifierProvider ) ) {
- return prefix & variables.configSettings.identifierProvider();
- }
- // Check jsession id First
- var isSessionDefined = getApplicationMetadata().sessionManagement;
- if ( isSessionDefined and structKeyExists( session, "sessionid" ) ) {
- return prefix & session.sessionid;
- }
- // check session URL Token
- else if ( isSessionDefined and structKeyExists( session, "URLToken" ) ) {
- return prefix & session.URLToken;
- }
- // Check cfid and cftoken in cookie
- else if ( structKeyExists( cookie, "CFID" ) AND structKeyExists( cookie, "CFTOKEN" ) ) {
- return prefix & hash( cookie.cfid & cookie.cftoken );
- }
- // Check cfid and cftoken in URL
- else if ( structKeyExists( URL, "CFID" ) AND structKeyExists( URL, "CFTOKEN" ) ) {
- return prefix & hash( URL.cfid & URL.cftoken );
- }
- // fallback for no cookie, session or url basically sessionless requests, track the request only
- else if ( isNull( request.cbUserTrackingId ) ) {
- request.cbUserTrackingId = prefix & createUUID();
- }
-
- return request.cbUserTrackingId;
- }
-
- /**
- * Locate the real path location of a file in a coldbox application. 3 checks: 1) inside of coldbox app, 2) expand the path, 3) Absolute location. If path not found, it returns an empty path
- *
- * @pathToCheck The relative or absolute file path to verify and locate
- */
- function locateFilePath( required pathToCheck ){
- var foundPath = "";
-
- // Check 1: Inside of App Root
- if ( fileExists( variables.appRootPath & arguments.pathToCheck ) ) {
- foundPath = variables.appRootPath & arguments.pathToCheck;
- }
- // Check 2: Expand the Path
- else if ( fileExists( expandPath( arguments.pathToCheck ) ) ) {
- foundPath = expandPath( arguments.pathToCheck );
- }
- // Check 3: Absolute Path
- else if ( fileExists( arguments.pathToCheck ) ) {
- foundPath = arguments.pathToCheck;
- }
-
- // Return
- return foundPath;
- }
-
- /**
- * Locate the real path location of a directory in a coldbox application. 3 checks: 1) inside of coldbox app, 2) expand the path, 3) Absolute location. If path not found, it returns an empty path
- *
- * @pathToCheck The relative or absolute directory path to verify and locate
- */
- function locateDirectoryPath( required pathToCheck ){
- var foundPath = "";
-
- // Check 1: Inside of App Root
- if ( directoryExists( variables.appRootPath & arguments.pathToCheck ) ) {
- foundPath = variables.appRootPath & arguments.pathToCheck;
- }
- // Check 2: Expand the Path
- else if ( directoryExists( expandPath( arguments.pathToCheck ) ) ) {
- foundPath = expandPath( arguments.pathToCheck );
- }
- // Check 3: Absolute Path
- else if ( directoryExists( arguments.pathToCheck ) ) {
- foundPath = arguments.pathToCheck;
- }
-
- // Return
- return foundPath;
- }
-
- /****************************************************************
- * Private Methods *
- ****************************************************************/
-
- /**
- * Load the internal ColdBox settings
- *
- * @return The struct of settings
- */
- private function loadColdBoxSettings(){
- var settings = {
- "ApplicationPath" : getAppRootPath(),
- "FrameworkPath" : expandPath( "/coldbox/system" ) & "/",
- "ConfigFileLocation" : ""
- };
-
- // Update settings with default values
- structAppend(
- settings,
- new coldbox.system.web.config.Settings(),
- true
- );
-
- return settings;
- }
-
- /**
- * Internal helper to flash persist elements
- *
- * @persist What request collection keys to persist in flash RAM automatically for you
- * @persistStruct A structure of key-value pairs to persist in flash RAM automatically for you
- *
- * @return Controller
- */
- private function persistVariables( persist = "", struct persistStruct = {} ){
- var flash = getRequestService().getFlashScope();
-
- // persist persistStruct if passed
- if ( !isNull( arguments.persistStruct ) ) {
- flash.putAll( map = arguments.persistStruct, saveNow = true );
- }
-
- // Persist RC keys if passed.
- if ( len( trim( arguments.persist ) ) ) {
- flash.persistRC( include = arguments.persist, saveNow = true );
- }
-
- return this;
- }
-
- /**
- * Checks if an action can be executed according to inclusion/exclusion lists
- *
- * @action The action to validate
- * @inclusion The list of inclusions
- * @exclusion The list of exclusions
- */
- private boolean function validateAction(
- required action,
- inclusion = "",
- exclusion = ""
- ){
- if (
- (
- ( len( arguments.inclusion ) AND listFindNoCase( arguments.inclusion, arguments.action ) )
- OR
- ( NOT len( arguments.inclusion ) )
- )
- AND
- ( listFindNoCase( arguments.exclusion, arguments.action ) EQ 0 )
- ) {
- return true;
- }
- return false;
- }
-
- /**
- * Invoke private/public event handler methods
- */
- private function invoker(
- required any target,
- required method,
- struct argCollection = {},
- boolean private = false
- ){
- if ( arguments.private ) {
- return arguments.target._privateInvoker(
- method = arguments.method,
- argCollection = arguments.argCollection
- );
- }
- return invoke(
- arguments.target,
- arguments.method,
- arguments.argCollection
- );
- }
-
- /**
- * Encapsulate a cf relocation tag. Encapsulated so we can mock it.
- */
- private function sendRelocation(
- required URL,
- boolean addToken = false,
- statusCode = 302
- ){
- location(
- url = "#arguments.URL#",
- addtoken = "#arguments.addtoken#",
- statuscode = "#arguments.statusCode#"
- );
- return this;
- }
-
- /**
- * Update SSL or not on a request string
- */
- private string function updateSSL( required inURL, required ssl ){
- // Check SSL?
- return (
- arguments.ssl ? replaceNoCase( arguments.inURL, "http:", "https:" ) : replaceNoCase(
- arguments.inURL,
- "https:",
- "http:"
- )
- );
- }
-
-}
diff --git a/src/test/java/TestCases/asm/integration/ControllerTest.java b/src/test/java/TestCases/asm/integration/ControllerTest.java
deleted file mode 100644
index 23e7549c8..000000000
--- a/src/test/java/TestCases/asm/integration/ControllerTest.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.integration;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-
-public class ControllerTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @Test
- public void testReturnInTemplate() {
- instance.executeStatement(
- """
- include template="src/test/java/TestCases/asm/integration/TemplateWithReturn.cfm";
- """,
- context );
- }
-
- @Test
- public void testSwitchInLoopInFunc() {
- instance.executeStatement(
- """
- function a(){
- for ( x = 1; x < 5; x++ ) {
- switch( x ){
- }
- }
- }
- """,
- context );
- }
-
- @Test
- public void testSwitchWithCaseInLoopInFunc() {
- instance.executeStatement(
- """
- function a(){
- for ( x = 1; x < 5; x++ ) {
- switch( x ){
- case "id": {
-
- }
- }
- }
-
- }
- a()
- """,
- context );
- }
-
- @Test
- public void testInterfaceImplementation() {
- instance.executeStatement(
- """
- impl = new src.test.java.TestCases.asm.integration.Implementor();
-
- impl.setName( "test" );
-
- result = impl.getName();
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( "test" );
- }
-
- @Test
- public void testTryCatchLabelStack() {
-
- instance.executeStatement(
- """
- controller = new src.test.java.TestCases.asm.integration.TryCatchLabelStack();
- """,
- context );
- }
-
- @Test
- public void testNestedLFunctionInComponent() {
-
- instance.executeStatement(
- """
- lock name = "what" timeout=300 {
- t = function(){
- return "test";
- }
-
- result = t();
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( "test" );
- }
-
- @Test
- public void testReturnFromComponentInFunction() {
-
- instance.executeStatement(
- """
- function a(){
- lock name="what" timeout=300 {
- return "test";
- }
- }
-
- result = a();
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( "test" );
- }
-
- @Test
- public void testContinueInForIndex() {
-
- instance.executeStatement(
- """
- a = [ "orange", "red", "yellow" ]
-
- for( color in a ){
-
- switch( color ){
- case "orange": result = color; break;
- default: continue;
- }
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( "orange" );
- }
-
-}
diff --git a/src/test/java/TestCases/asm/integration/ICacheProvider.cfc b/src/test/java/TestCases/asm/integration/ICacheProvider.cfc
deleted file mode 100644
index 4f750cc85..000000000
--- a/src/test/java/TestCases/asm/integration/ICacheProvider.cfc
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp
- * www.ortussolutions.com
- * ---
- *
- * The main interface for a CacheBox cache provider. You need to implement all the methods in order for CacheBox to work correctly for the implementing cache provider.
- *
- * @author Luis Majano
- */
-interface {
-
- /**
- * Get the name of this cache
- */
- function getName();
-
- /**
- * Set the cache name
- *
- * @name The name to set
- *
- * @return ICacheProvider
- */
- function setName( required name );
-
-}
diff --git a/src/test/java/TestCases/asm/integration/Implementor.cfc b/src/test/java/TestCases/asm/integration/Implementor.cfc
deleted file mode 100644
index 9283f17c2..000000000
--- a/src/test/java/TestCases/asm/integration/Implementor.cfc
+++ /dev/null
@@ -1,12 +0,0 @@
-component implements="ICacheProvider" {
-
- variables.name = "";
-
- function getName(){
- return variables.name;
- }
-
- function setName( required name ){
- variables.name = name;
- }
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/integration/TemplateWithReturn.cfm b/src/test/java/TestCases/asm/integration/TemplateWithReturn.cfm
deleted file mode 100644
index b96f365fb..000000000
--- a/src/test/java/TestCases/asm/integration/TemplateWithReturn.cfm
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
- return;
-
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/integration/TryCatchLabelStack.cfc b/src/test/java/TestCases/asm/integration/TryCatchLabelStack.cfc
deleted file mode 100644
index 0e655390c..000000000
--- a/src/test/java/TestCases/asm/integration/TryCatchLabelStack.cfc
+++ /dev/null
@@ -1,8 +0,0 @@
-component {
- try {
- }
-
- savecontent variable="x" {
- "test";
- }
-}
diff --git a/src/test/java/TestCases/asm/literal/ArrayLiteralTest.java b/src/test/java/TestCases/asm/literal/ArrayLiteralTest.java
deleted file mode 100644
index 88f0c1ef5..000000000
--- a/src/test/java/TestCases/asm/literal/ArrayLiteralTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.literal;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-import ortus.boxlang.runtime.types.Array;
-
-public class ArrayLiteralTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "Can decalare an empty literal" )
- @Test
- public void testDecalreEmptyStructLiteral() {
- var result = instance.executeStatement(
- """
- [];
- """,
- context );
-
- assertThat( result ).isInstanceOf( Array.class );
- ;
- }
-
- @DisplayName( "Can decalare an array literal with values" )
- @Test
- public void testDecalreStructLiteralWithColons() {
- var result = instance.executeStatement(
- """
- [ "yellow" ];
- """,
- context );
-
- assertThat( result ).isInstanceOf( Array.class );
- assertThat( ( ( Array ) result ).size() ).isEqualTo( 1 );
- assertThat( ( ( Array ) result ).get( 0 ) ).isEqualTo( "yellow" );
- ;
- }
-}
diff --git a/src/test/java/TestCases/asm/literal/BooleanLiteralTest.java b/src/test/java/TestCases/asm/literal/BooleanLiteralTest.java
deleted file mode 100644
index 51d59d091..000000000
--- a/src/test/java/TestCases/asm/literal/BooleanLiteralTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.literal;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-
-public class BooleanLiteralTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "Can decalare a boolean literal (true)" )
- @Test
- public void testDecalreTrueBooleanLiteral() {
- var result = instance.executeStatement(
- """
- true;
- """,
- context );
-
- assertThat( result ).isEqualTo( true );
- }
-
- @DisplayName( "Can decalare a boolean literal (false)" )
- @Test
- public void testDecalreFalseBooleanLiteral() {
- var result = instance.executeStatement(
- """
- false;
- """,
- context );
-
- assertThat( result ).isEqualTo( false );
- }
-}
diff --git a/src/test/java/TestCases/asm/literal/DoubleLiteralTest.java b/src/test/java/TestCases/asm/literal/DoubleLiteralTest.java
deleted file mode 100644
index bc6a073a8..000000000
--- a/src/test/java/TestCases/asm/literal/DoubleLiteralTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.literal;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import java.math.BigDecimal;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-
-public class DoubleLiteralTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "Can declare a double literal" )
- @Test
- public void testDeclareDoubleLiteral() {
- var result = instance.executeStatement(
- """
- 3.5;
- """,
- context );
-
- assertThat( ( ( BigDecimal ) result ).doubleValue() ).isEqualTo( 3.5 );
- }
-
- @DisplayName( "Can decalare a double literal" )
- @Test
- public void testDecalreANegativeDoubleLiteral() {
- var result = instance.executeStatement(
- """
- -3.5;
- """,
- context );
-
- assertThat( ( ( BigDecimal ) result ).doubleValue() ).isEqualTo( -3.5 );
- }
-}
diff --git a/src/test/java/TestCases/asm/literal/IntegerLiteralTest.java b/src/test/java/TestCases/asm/literal/IntegerLiteralTest.java
deleted file mode 100644
index c8548defe..000000000
--- a/src/test/java/TestCases/asm/literal/IntegerLiteralTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.literal;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-
-public class IntegerLiteralTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "Can decalare an int literal" )
- @Test
- public void testDecalreIntLiteral() {
- var result = instance.executeStatement(
- """
- 2;
- """,
- context );
-
- assertThat( result ).isEqualTo( 2 );
- }
-
- @DisplayName( "Can decalare a negative int literal" )
- @Test
- public void testDecalreNegativeIntLiteral() {
- var result = instance.executeStatement(
- """
- -2;
- """,
- context );
-
- assertThat( result ).isEqualTo( -2 );
- }
-}
diff --git a/src/test/java/TestCases/asm/literal/StringLiteralTest.java b/src/test/java/TestCases/asm/literal/StringLiteralTest.java
deleted file mode 100644
index 1169dc1a2..000000000
--- a/src/test/java/TestCases/asm/literal/StringLiteralTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.literal;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-
-public class StringLiteralTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "Can decalare a string literal" )
- @Test
- public void testDecalreStringLiteral() {
- var result = instance.executeStatement(
- """
- "Hello World";
- """,
- context );
-
- assertThat( result ).isEqualTo( "Hello World" );
- }
-
- @DisplayName( "Can declare a string literal with interpolation" )
- @Test
- public void testDeclareInterpolatedStringLiteral() {
- var result = instance.executeStatement(
- """
- "Hello World #5#";
- """,
- context );
-
- assertThat( result ).isEqualTo( "Hello World 5" );
- }
-
-}
diff --git a/src/test/java/TestCases/asm/literal/StructLiteralTest.java b/src/test/java/TestCases/asm/literal/StructLiteralTest.java
deleted file mode 100644
index 5991acc63..000000000
--- a/src/test/java/TestCases/asm/literal/StructLiteralTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.literal;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-import ortus.boxlang.runtime.types.IStruct;
-import ortus.boxlang.runtime.types.Struct;
-
-public class StructLiteralTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "Can declare an empty literal" )
- @Test
- public void testDeclareEmptyStructLiteral() {
- var result = instance.executeStatement(
- """
- x = {};
- """,
- context );
-
- assertThat( result ).isInstanceOf( Struct.class );
- ;
- }
-
- @DisplayName( "Can declare an empty ordered struct literal" )
- @Test
- public void testDeclareEmptyOrderedStructLiteral() {
- var result = instance.executeStatement(
- """
- [:];
- """,
- context );
-
- assertThat( result ).isInstanceOf( Struct.class );
- assertThat( ( ( Struct ) result ).getType() ).isInstanceOf( IStruct.TYPES.LINKED.getClass() );
- ;
- }
-
- @DisplayName( "Can declare a struct literal with keys using colons" )
- @Test
- public void testDeclareStructLiteralWithColons() {
- var result = instance.executeStatement(
- """
- {
- a: "test"
- };
- """,
- context );
-
- assertThat( result ).isInstanceOf( Struct.class );
- assertThat( ( ( Struct ) result ).containsKey( "a" ) ).isEqualTo( true );
- assertThat( ( ( Struct ) result ).get( "a" ) ).isEqualTo( "test" );
- ;
- }
-
- @DisplayName( "Can declare a struct literal with keys equals" )
- @Test
- public void testDeclareStructLiteralWithEquals() {
- var result = instance.executeStatement(
- """
- x = {
- a= "test"
- };
-
- x;
- """,
- context );
-
- assertThat( result ).isInstanceOf( Struct.class );
- assertThat( ( ( Struct ) result ).containsKey( "a" ) ).isEqualTo( true );
- assertThat( ( ( Struct ) result ).get( "a" ) ).isEqualTo( "test" );
-
- }
-
-}
diff --git a/src/test/java/TestCases/asm/operator/BinaryMinusOperatorTest.java b/src/test/java/TestCases/asm/operator/BinaryMinusOperatorTest.java
deleted file mode 100644
index 1d3ae5f25..000000000
--- a/src/test/java/TestCases/asm/operator/BinaryMinusOperatorTest.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.operator;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-
-public class BinaryMinusOperatorTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "Can subtract two positive int" )
- @Test
- public void testsubtractPostiiveInts() {
- var result = instance.executeStatement(
- """
- 1 - 1;
- """,
- context );
-
- assertThat( result ).isEqualTo( 0 );
- }
-
- @DisplayName( "Can subtract a positive int on the left and a negative int on the right" )
- @Test
- public void testsubtractPostiiveToNegativeInts() {
- var result = instance.executeStatement(
- """
- 1 - -1;
- """,
- context );
-
- assertThat( result ).isEqualTo( 2 );
- }
-
- @DisplayName( "Can subtract a positive int on the left and a negative int on the right" )
- @Test
- public void testsubtractNegativeToPositiveInts() {
- var result = instance.executeStatement(
- """
- -1 - 1;
- """,
- context );
-
- assertThat( result ).isEqualTo( -2 );
- }
-
- @DisplayName( "Can subtract two positive doubles" )
- @Test
- public void testsubtractPostiiveDoubles() {
- Number result = ( Number ) instance.executeStatement(
- """
- 1.0 - 1.5;
- """,
- context );
-
- assertThat( result.doubleValue() ).isEqualTo( -0.5 );
- }
-
- @DisplayName( "Can subtract a positive double on the left and a negative double on the right" )
- @Test
- public void testsubtractPostiiveToNegativeDoubles() {
- Number result = ( Number ) instance.executeStatement(
- """
- 1.0 - -1.0;
- """,
- context );
-
- assertThat( result.doubleValue() ).isEqualTo( 2.0 );
- }
-
- @DisplayName( "Can subtract a positive double on the left and a negative double on the right" )
- @Test
- public void testsubtractNegativeToPositiveDoubles() {
- Number result = ( Number ) instance.executeStatement(
- """
- -1.0 - 1.0;
- """,
- context );
-
- assertThat( result.doubleValue() ).isEqualTo( -2.0 );
- }
-
-}
diff --git a/src/test/java/TestCases/asm/operator/BinaryPlusOperatorTest.java b/src/test/java/TestCases/asm/operator/BinaryPlusOperatorTest.java
deleted file mode 100644
index 40c7b5c53..000000000
--- a/src/test/java/TestCases/asm/operator/BinaryPlusOperatorTest.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.operator;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-
-public class BinaryPlusOperatorTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "Can add two positive int" )
- @Test
- public void testAddPostiiveInts() {
- Number result = ( Number ) instance.executeStatement(
- """
- 1 + 1;
- """,
- context );
-
- assertThat( result.doubleValue() ).isEqualTo( 2 );
- }
-
- @DisplayName( "Can add a positive int on the left and a negative int on the right" )
- @Test
- public void testAddPostiiveToNegativeInts() {
- Number result = ( Number ) instance.executeStatement(
- """
- 1 + -1;
- """,
- context );
-
- assertThat( result.doubleValue() ).isEqualTo( 0 );
- }
-
- @DisplayName( "Can add a positive int on the left and a negative int on the right" )
- @Test
- public void testAddNegativeToPositiveInts() {
- Number result = ( Number ) instance.executeStatement(
- """
- -1 + 1;
- """,
- context );
-
- assertThat( result.doubleValue() ).isEqualTo( 0 );
- }
-
- @DisplayName( "Can add two positive doubles" )
- @Test
- public void testAddPostiiveDoubles() {
- Number result = ( Number ) instance.executeStatement(
- """
- 1.0 + 1.5;
- """,
- context );
-
- assertThat( result.doubleValue() ).isEqualTo( 2.5 );
- }
-
- @DisplayName( "Can add a positive double on the left and a negative double on the right" )
- @Test
- public void testAddPostiiveToNegativeDoubles() {
- Number result = ( Number ) instance.executeStatement(
- """
- 1.0 + -1.0;
- """,
- context );
-
- assertThat( result.doubleValue() ).isEqualTo( 0.0 );
- }
-
- @DisplayName( "Can add a positive double on the left and a negative double on the right" )
- @Test
- public void testAddNegativeToPositiveDoubles() {
- Number result = ( Number ) instance.executeStatement(
- """
- -1.0 + 1.0;
- """,
- context );
-
- assertThat( result.doubleValue() ).isEqualTo( 0.0 );
- }
-
-}
diff --git a/src/test/java/TestCases/asm/operator/UnaryOperatorTest.java b/src/test/java/TestCases/asm/operator/UnaryOperatorTest.java
deleted file mode 100644
index 03df7bb28..000000000
--- a/src/test/java/TestCases/asm/operator/UnaryOperatorTest.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.operator;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-
-public class UnaryOperatorTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "Can negate a boolean literal" )
- @Test
- public void testDecalreTrueBooleanLiteral() {
- var result = instance.executeStatement(
- """
- !true;
- """,
- context );
-
- assertThat( result ).isEqualTo( false );
- }
-
- @DisplayName( "Can negate a boolean literal (false)" )
- @Test
- public void testDecalreFalseBooleanLiteral() {
- var result = instance.executeStatement(
- """
- !false;
- """,
- context );
-
- assertThat( result ).isEqualTo( true );
- }
-
- @DisplayName( "Can pre increment a value" )
- @Test
- public void testPreincrement() {
- var result = instance.executeStatement(
- """
- val = 1;
- ++val;
- """,
- context );
-
- assertThat( result ).isEqualTo( 2 );
- }
-
- @DisplayName( "Can post increment a value" )
- @Test
- public void testPostIncrement() {
- var res = instance.executeStatement(
- """
- result = 1;
- result++;
- """,
- context );
-
- assertThat( res ).isEqualTo( 1 );
- assertThat( variables.get( result ) ).isEqualTo( 2 );
- }
-
- @DisplayName( "Can pre decrement a value" )
- @Test
- public void testPreDecrement() {
- var result = instance.executeStatement(
- """
- val = 1;
- --val;
- """,
- context );
-
- assertThat( result ).isEqualTo( 0 );
- }
-
- @DisplayName( "Can post decrement a value" )
- @Test
- public void testPostDecrement() {
- var res = instance.executeStatement(
- """
- result = 1;
- result--;
- """,
- context );
-
- assertThat( res ).isEqualTo( 1 );
- assertThat( variables.get( result ) ).isEqualTo( 0 );
- }
-
- @DisplayName( "Can bitwise complement a value" )
- @Test
- public void testBitwiseComplement() {
- var res = instance.executeStatement(
- """
- b~35;
- """,
- context );
-
- assertThat( res ).isEqualTo( -36 );
- }
-}
diff --git a/src/test/java/TestCases/asm/phase1/AssignmentTest.java b/src/test/java/TestCases/asm/phase1/AssignmentTest.java
deleted file mode 100644
index 4f3e3e779..000000000
--- a/src/test/java/TestCases/asm/phase1/AssignmentTest.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.phase1;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-import ortus.boxlang.runtime.types.IStruct;
-import ortus.boxlang.runtime.types.Struct;
-
-public class AssignmentTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "Unscoped assignment" )
- @Test
- public void testUnscopedAssignment() {
- instance.executeSource(
- """
- foo = "test";
- """,
- context );
- assertThat( variables.get( Key.of( "foo" ) ) ).isEqualTo( "test" );
- }
-
- @DisplayName( "It should not allow assignment via the equal keyword" )
- @Test
- public void testDontAssignUsingEqual() {
- instance.executeSource(
- """
- foo = 2;
- foo equal "test";
- """,
- context );
- assertThat( variables.get( Key.of( "foo" ) ) ).isEqualTo( 2 );
- }
-
- @DisplayName( "Nested dot assignment" )
- @Test
- public void testNestedDotAssignment() {
- instance.executeSource(
- """
- foo.bar = "test";
- """,
- context );
- assertThat( ( ( IStruct ) variables.get( Key.of( "foo" ) ) ).get( Key.of( "bar" ) ) ).isEqualTo( "test" );
- }
-
- @DisplayName( "Multi multi identifier dot assignment" )
- @Test
- public void testmultimultiIdentifierAssignment() {
- instance.executeSource(
- """
- foo.bar.baz = "test";
- """,
- context );
-
- assertThat( ( ( IStruct ) ( ( IStruct ) variables.get( Key.of( "foo" ) ) ).get( Key.of( "bar" ) ) )
- .get( Key.of( "baz" ) ) ).isEqualTo( "test" );
- }
-
- @DisplayName( "Bracket string assignment" )
- @Test
- public void testBracketStringAssignment() {
- instance.executeSource(
- """
- foo["bar"] = "test";
- """,
- context );
- assertThat( ( ( IStruct ) variables.get( Key.of( "foo" ) ) ).get( Key.of( "bar" ) ) ).isEqualTo( "test" );
- }
-
- @DisplayName( "Bracket string concat assignment" )
- @Test
- public void testBracketStringConcatAssignement() {
- instance.executeSource(
- """
- foo["b" & "ar"] = "test";
- """,
- context );
- assertThat( ( ( IStruct ) variables.get( Key.of( "foo" ) ) ).get( Key.of( "bar" ) ) ).isEqualTo( "test" );
- }
-
- @DisplayName( "Bracket number assignment" )
- @Test
- public void testBracketNumberAssignment() {
- instance.executeSource(
- """
- foo[ 7 ] = "test";
- """,
- context );
- assertThat( ( ( IStruct ) variables.get( Key.of( "foo" ) ) ).get( Key.of( "7" ) ) ).isEqualTo( "test" );
- }
-
- @DisplayName( "Bracket number expression assignment" )
- @Test
- public void testBracketNumberExpressionAssignment() {
- instance.executeSource(
- """
- foo[ 7 + 5 ] = "test";
- """,
- context );
- assertThat( ( ( IStruct ) variables.get( Key.of( "foo" ) ) ).get( Key.of( "12" ) ) ).isEqualTo( "test" );
- }
-
- @DisplayName( "Bracket object assignment" )
- @Test
- public void testBracketObjectExpressionAssignment() {
- IStruct x = new Struct();
- x.assign( context, new Key( "bar" ), "baz" );
- instance.executeSource(
- """
- foo[ { bar : "baz" } ] = "test";
- """,
- context );
- assertThat( ( ( IStruct ) variables.get( Key.of( "foo" ) ) ).get( Key.of( x ) ) ).isEqualTo( "test" );
- }
-
- @DisplayName( "Mixed assignment" )
- @Test
- public void testBracketMixedAssignment() {
- instance.executeSource(
- """
- foo[ "a" & "aa" ][ 12 ].other[ 2 + 5 ] = "test";
- """,
- context );
-
- IStruct foo = ( IStruct ) variables.get( Key.of( "foo" ) );
- IStruct aaa = ( IStruct ) foo.get( Key.of( "aaa" ) );
- IStruct twelve = ( IStruct ) aaa.get( Key.of( "12" ) );
- IStruct other = ( IStruct ) twelve.get( Key.of( "other" ) );
-
- assertThat( other.get( Key.of( "7" ) ) ).isEqualTo( "test" );
- }
-
- @DisplayName( "simple quoted assignment" )
- @Test
- public void testSimpleQuotedAssignment() {
- instance.executeSource(
- """
- "result" = 5;
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( 5 );
- }
-
- @DisplayName( "quoted assignment" )
- @Test
- public void testQuotedAssignment() {
- instance.executeSource(
- """
- "result" = "test";
- name = "result2";
- "variables.#name#" = "test2";
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( "test" );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "test2" );
- }
-
-}
diff --git a/src/test/java/TestCases/asm/phase1/CoreLangTest.java b/src/test/java/TestCases/asm/phase1/CoreLangTest.java
deleted file mode 100644
index 47afd2997..000000000
--- a/src/test/java/TestCases/asm/phase1/CoreLangTest.java
+++ /dev/null
@@ -1,2506 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.phase1;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-import java.io.IOException;
-import java.util.Comparator;
-import java.util.concurrent.TimeUnit;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.Timeout;
-
-import ortus.boxlang.compiler.parser.BoxSourceType;
-import ortus.boxlang.compiler.parser.DocParser;
-import ortus.boxlang.compiler.parser.ParsingResult;
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.FunctionBoxContext;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.LocalScope;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-import ortus.boxlang.runtime.types.Argument;
-import ortus.boxlang.runtime.types.Function.Access;
-import ortus.boxlang.runtime.types.IStruct;
-import ortus.boxlang.runtime.types.SampleUDF;
-import ortus.boxlang.runtime.types.Struct;
-import ortus.boxlang.runtime.types.exceptions.BoxRuntimeException;
-import ortus.boxlang.runtime.types.exceptions.NoFieldException;
-
-public class CoreLangTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "if" )
- @Test
- public void testIf() {
-
- instance.executeSource(
- """
- result = "default"
- foo = "false"
- if( 1 ) {
- result = "first"
- } else if( !foo ) {
- result = "second"
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "first" );
-
- }
-
- @DisplayName( "if with single-token elseif" )
- @Test
- public void testIfSingleTokenElseIf() {
-
- instance.executeSource(
- """
- if( true ){
- } elseif( true ){
- }
- 6+7
- elseif = "foo"
- result = elseif;
- """,
- context, BoxSourceType.CFSCRIPT );
- assertThat( variables.get( result ) ).isEqualTo( "foo" );
-
- }
-
- @DisplayName( "if else" )
- @Test
- public void testIfElse() {
-
- instance.executeSource(
- """
- if( false ) {
- result = "first"
- } else {
- result = "second"
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "second" );
-
- }
-
- @DisplayName( "if no body" )
- @Test
- public void testIfNoBody() {
-
- instance.executeSource(
- """
- result = "default"
-
- if( 1 == 1 )
- result = "done"
-
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "done" );
-
- instance.executeSource(
- """
- result = "default"
-
- if( 1 == 2 )
- result = "not done"
-
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "default" );
-
- }
-
- @DisplayName( "If blocks with no-body else statements" )
- @Test
- public void testElseNoBody() {
-
- instance.executeSource(
- """
- result = "default"
-
- if( 2 == 1 ) {
- result = "done"
- } else result = "else"
-
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "else" );
-
- instance.executeSource(
- """
- if( 2 == 1 ) {
- result = "done"
- } else result = "else"
- result = "afterif"
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "afterif" );
-
- }
-
- @DisplayName( "throw in source" )
- @Test
- public void testThrowSource() {
- assertThrows( NoFieldException.class, () -> instance.executeSource(
- """
- throw new java:ortus.boxlang.runtime.types.exceptions.NoFieldException( "My Message" );
- """,
- context )
- );
- }
-
- @DisplayName( "throw in statement" )
- @Test
- public void testThrowStatement() {
- assertThrows( NoFieldException.class,
- () -> instance.executeStatement( "throw new java:ortus.boxlang.runtime.types.exceptions.NoFieldException( 'My Message' );", context )
- );
- }
-
- @DisplayName( "try catch" )
- @Test
- public void testTryCatch() {
-
- instance.executeSource(
- """
- result = "default";
- try {
- 1/0
- } catch (any e) {
- message = e.getMessage();
- message2 = e.message;
- result = "in catch";
- } finally {
- result &= ' also finally';
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "in catch also finally" );
- assertThat( variables.get( Key.of( "message" ) ) ).isEqualTo( "You cannot divide by zero." );
- assertThat( variables.get( Key.of( "message2" ) ) ).isEqualTo( "You cannot divide by zero." );
-
- }
-
- @DisplayName( "try catch with empty type" )
- @Test
- public void testTryCatchEmptyType() {
-
- instance.executeSource(
- """
- try {
- 1/0
- } catch ( e) {
- message = e.getMessage();
- message2 = e.message;
- result = "in catch";
- } finally {
- result &= ' also finally';
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "in catch also finally" );
- assertThat( variables.get( Key.of( "message" ) ) ).isEqualTo( "You cannot divide by zero." );
- assertThat( variables.get( Key.of( "message2" ) ) ).isEqualTo( "You cannot divide by zero." );
-
- }
-
- @DisplayName( "try catch with interpolated type" )
- @Test
- public void testTryCatchWithInterpolatedType() {
-
- instance.executeSource(
- """
- bar = "test"
- try {
- 1/0
- }
- catch( "foo#bar#baz" e ){
-
- }
- catch ( e) {
- message = e.getMessage();
- message2 = e.message;
- result = "in catch";
- } finally {
- result &= ' also finally';
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "in catch also finally" );
- assertThat( variables.get( Key.of( "message" ) ) ).isEqualTo( "You cannot divide by zero." );
- assertThat( variables.get( Key.of( "message2" ) ) ).isEqualTo( "You cannot divide by zero." );
-
- }
-
- @DisplayName( "nested try catch" )
- @Test
- public void testNestedTryCatch() {
-
- instance.executeSource(
- """
- try {
- 1/0
- } catch (any e) {
- one = e.getMessage()
-
- try {
- foo=variables.bar
- } catch (any e) {
- two = e.getMessage()
- }
-
- three = e.getMessage()
- }
- """,
- context );
- assertThat( variables.get( Key.of( "one" ) ) ).isEqualTo( "You cannot divide by zero." );
- assertThat( variables.get( Key.of( "two" ) ) )
- .isEqualTo( "The key [bar] was not found in the struct. Valid keys are ([e, one])" );
- assertThat( variables.get( Key.of( "three" ) ) ).isEqualTo( "You cannot divide by zero." );
-
- }
-
- @DisplayName( "try multiple catches" )
- @Test
- public void testTryMultipleCatchesx() {
-
- instance.executeSource(
- """
- result = "default"
- try {
- 1/0
- } catch ( any myErr ) {
- result = "catchany"
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "catchany" );
-
- }
-
- @DisplayName( "try multiple catches" )
- @Test
- public void testTryMultipleCatchesInFunc() {
-
- instance.executeSource(
- """
- result = "default"
- function test(){
- if( true ){
-
- }
-
- try {
- 1/0
- } catch ( any myErr ) {
- result = "catchany"
- }
- }
- test()
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "catchany" );
-
- }
-
- @DisplayName( "try multiple catches" )
- @Test
- public void testTryMultipleCatches() {
-
- instance.executeSource(
- """
- result = "default"
- try {
- 1/0
- } catch (com.foo.bar e) {
- result = "catch1"
- } catch ("com.foo.bar2" e) {
- result = "catch2"
- } catch ( any myErr ) {
- result = "catchany"
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "catchany" );
-
- }
-
- @DisplayName( "try multiple catche types" )
- @Test
- public void testTryMultipleCatchTypes() {
-
- instance.executeSource(
- """
- result = "default"
- try {
- 1/0
- } catch ( "com.foo.type" | java.lang.RuntimeException | "foo.bar" myErr ) {
- result = "catch3"
- }
- """,
- context );
- // assertThat( variables.get( result ) ).isEqualTo( "catchany" );
-
- }
-
- @DisplayName( "try multiple catche types with any" )
- @Test
- public void testTryMultipleCatchTypesWithAny() {
-
- instance.executeSource(
- """
- result = "default"
- try {
- 1/0
- } catch ( "com.foo.type" | java.lang.RuntimeException | any | "foo.bar" myErr ) {
- result = "catch3"
- }
- """,
- context );
- // assertThat( variables.get( result ) ).isEqualTo( "catchany" );
-
- }
-
- @DisplayName( "try finally" )
- @Test
- public void testTryFinallyNoException() {
-
- instance.executeSource(
- """
- result = "default";
- try {
- 1/1
-
- } finally {
- result = 'finally';
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "finally" );
-
- }
-
- @DisplayName( "try finally" )
- @Test
- public void testTryFinally() {
-
- assertThrows( BoxRuntimeException.class,
- () -> instance.executeSource(
- """
- result = "default"
- try {
- 1/0
- } finally {
- result = "finally"
- }
- """,
- context )
- );
- assertThat( variables.get( result ) ).isEqualTo( "finally" );
-
- }
-
- // TODO: try/catch types
- // TODO: try/finally with no catch
-
- @DisplayName( "rethrow" )
- @Test
- public void testRethrow() {
-
- Throwable t = assertThrows( BoxRuntimeException.class,
- () -> instance.executeSource(
- """
- try {
- 1/0
- } catch (any e) {
- rethrow;
- }
- """,
- context )
- );
- assertThat( t.getMessage() ).isEqualTo( "You cannot divide by zero." );
- }
-
- @DisplayName( "for in loop" )
- @Test
- public void testForInLoop1() {
-
- instance.executeSource(
- """
- result=""
- arr = [ "brad", "wood", "luis", "majano" ]
- for( name in arr ) {
- result &= name;
- }
-
- result2=""
- arr = [ "jorge", "reyes", "edgardo", "cabezas" ]
- for( name in arr ) {
- result2 &= name;
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "bradwoodluismajano" );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "jorgereyesedgardocabezas" );
-
- }
-
- @DisplayName( "for in loop" )
- @Test
- public void testForInLoop2() {
-
- instance.executeSource(
- """
- result=""
- arr = []
- for( name in arr ) {
- result &= name;
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "" );
-
- }
-
- @DisplayName( "for in loop" )
- @Test
- public void testForInLoop3() {
-
- FunctionBoxContext functionBoxContext = new FunctionBoxContext( context,
- new SampleUDF( Access.PUBLIC, Key.of( "func" ), "any", new Argument[] {}, "" ) );
- instance.executeSource(
- """
- result=""
- arr = [ "brad", "wood", "luis", "majano" ]
- for( var foo["bar"].name in arr ) {
- result &= foo["bar"].name;
- }
-
- """,
- functionBoxContext );
- assertThat( functionBoxContext.getScopeNearby( LocalScope.name ).get( result ) ).isEqualTo( "bradwoodluismajano" );
-
- }
-
- @DisplayName( "for in loop with list" )
- @Test
- public void testForInLoopList() {
-
- instance.executeSource(
- """
- result = "";
- for( item in "hello,world,test" )
- result &= item;
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "helloworldtest" );
- }
-
- @DisplayName( "for in loop single statment" )
- @Test
- public void testForInLoopSingleStatement() {
-
- instance.executeSource(
- """
- result=""
- arr = [ "brad", "wood", "luis", "majano" ]
- for( name in arr )
- result &= name;
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "bradwoodluismajano" );
-
- }
-
- @DisplayName( "for in loop struct" )
- @Test
- public void testForInLoopStruct() {
-
- instance.executeSource(
- """
- result=""
- str ={ foo : "bar", baz : "bum" }
- for( key in str ) {
- result &= key&"="&str[ key ];
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "foo=barbaz=bum" );
-
- }
-
- @DisplayName( "do while loop" )
- @Test
- @Timeout( value = 5, unit = TimeUnit.SECONDS )
- public void testDoWhileLoop() {
-
- instance.executeSource(
- """
- result = 1;
- do {
- result = variables.result + 1;
- } while( result < 10 )
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 10 );
-
- }
-
- @DisplayName( "break while" )
- @Test
- public void testBreakWhile() {
-
- instance.executeSource(
- """
- result = 1;
- while( true ) {
- result = result + 1;
- if( result > "10" ) {
- break;
- }
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 11 );
-
- }
-
- @DisplayName( "break do while" )
- @Test
- public void testBreakDoWhile() {
-
- instance.executeSource(
- """
- result = 1;
- do {
- result = variables.result + 1;
- if( result > "10" ) {
- break;
- }
- } while( true )
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 11 );
-
- }
-
- @DisplayName( "break sentinel" )
- @Test
- public void testBreakSentinel() {
-
- instance.executeSource(
- """
- result=0
- i=0
- for( i=0; i==i; i=i+1 ) {
- result=result+1
- if( i > 10 ) {
- break;
- }
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 12 );
-
- }
-
- @DisplayName( "sentinel but everything is missing" )
- @Test
- public void testSentinelButEverythingIsMissing() {
-
- instance.executeSource(
- """
- counter = 1;
- for ( ; ; ) {
- writeOutput( counter );
- counter++;
- if( counter > 5 ) {
- break;
- }
- }
- result = counter;
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 6 );
-
- }
-
- @DisplayName( "continue sentinel" )
- @Test
- public void testContinueSentinel() {
-
- instance.executeSource(
- """
- result=0
- n = 10;
- for ( i = 1; i <= n; ++i ) {
- if ( i > 5 ) {
- continue;
- }
- result = i;
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 5 );
-
- }
-
- @DisplayName( "while continue" )
- @Test
- public void testWhileContinue() {
-
- instance.executeSource(
- """
- result=0
- while( true ) {
- result=result+1
- if( result < 10 ) {
- continue;
- }
- break;
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 10 );
-
- }
-
- @DisplayName( "Single inline while" )
- @Test
- public void testSingleInlineWhile() {
-
- instance.executeSource(
- """
- result = 0;
- while (true && result < 1) result=1;
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 1 );
-
- }
-
- @DisplayName( "Single inline while with parenthesis" )
- @Test
- public void testSingleInlineWhileWithParenthesis() {
-
- instance.executeSource(
- """
- result = 0;
- while (true && result < 1) (result=1);
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 1 );
-
- }
-
- @DisplayName( "Single next line while" )
- @Test
- public void testSingleNextLineWhile() {
-
- instance.executeSource(
- """
- result = 0;
- while (true && result < 1)
- result=1;
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 1 );
-
- }
-
- @DisplayName( "Single next line while with parenthesis" )
- @Test
- public void testSingleNextLineWhileWithParenthesis() {
-
- instance.executeSource(
- """
- result = 0;
- while (true && result < 1)
- (result=1);
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 1 );
-
- }
-
- @DisplayName( "Single next line while only loop body" )
- @Test
- public void testSingleNextLineWhileOnlyLoopBody() {
-
- instance.executeSource(
- """
- result = 0;
- other = 0;
- while (true && result < 5)
- (result = result + 1);
- other = other + 1;
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 5 );
- assertThat( variables.get( Key.of( "other" ) ) ).isEqualTo( 1 );
-
- }
-
- @DisplayName( "Multiple parnetheitcal statements" )
- @Test
- public void testMultipleParnetheticalStatements() {
-
- instance.executeSource(
- """
- (1+2);
- (1+2);
- """,
- context );
-
- }
-
- @DisplayName( "Multiple parnetheitcal statements with over-nested parenthesis" )
- @Test
- public void testMultipleParnetheticalStatementsWithOverNestedParenthesis() {
-
- instance.executeSource(
- """
- ((((1+2))));
- (1+2);
- """,
- context );
- }
-
- @DisplayName( "String parsing 1" )
- @Test
- public void testStringParsing1() {
-
- instance.executeSource(
- """
- // Strings can use single quotes OR double quotes, so long as the “bookends” match.
- test1 = "foo" == 'foo'
- """,
- context );
- assertThat( variables.get( Key.of( "test1" ) ) ).isEqualTo( true );
-
- }
-
- @DisplayName( "String parsing 2" )
- @Test
- public void testStringParsing2() {
-
- instance.executeSource(
- """
- // A double quote-encased string doesn’t need to escape single quotes inside and vice versa
- test2 = "foo'bar"
- test3 = 'foo"bar'
- """,
- context );
-
- assertThat( variables.get( Key.of( "test2" ) ) ).isEqualTo( "foo'bar" );
- assertThat( variables.get( Key.of( "test3" ) ) ).isEqualTo( "foo\"bar" );
-
- }
-
- @DisplayName( "String parsing quotation escaping" )
- @Test
- public void testStringParsingQuoteEscapes() {
-
- instance.executeSource(
- """
- // To escape a quote char, double it.
- test4 = "Brad ""the guy"" Wood"
- test5 = 'Luis ''the man'' Majano'
- """,
- context );
-
- assertThat( variables.get( Key.of( "test4" ) ) ).isEqualTo( "Brad \"the guy\" Wood" );
- assertThat( variables.get( Key.of( "test5" ) ) ).isEqualTo( "Luis 'the man' Majano" );
- }
-
- @DisplayName( "String parsing concatenation" )
- @Test
- public void testStringParsingConcatenation() {
-
- instance.executeSource(
- """
- // Expressions are always interpolated inside string literals in CFScript by using a hash/pound sign (`#`) such as
- variables.timeVar = "12:00 PM"
- variables.test6 = "Time is: #timeVar#"
- variables.test7 = "Time is: " & timeVar
- variables.test8 = 'Time is: #timeVar#'
- variables.test9 = 'Time is: ' & timeVar
- """,
- context );
- assertThat( variables.get( Key.of( "test6" ) ) ).isEqualTo( "Time is: 12:00 PM" );
- assertThat( variables.get( Key.of( "test7" ) ) ).isEqualTo( "Time is: 12:00 PM" );
-
- }
-
- @DisplayName( "String parsing expression interpolation" )
- @Test
- public void testStringParsingExpressionInterpolation() {
-
- instance.executeSource(
- """
- variables.var = "brad"
- varname = "var"
- variables.result1 = "#var#foo"
- variables.result2 = "foo#var#"
- variables.result3 = "foo#var#bar"
- variables.result4 = "foo#var#bar#var#baz#var#bum"
- variables.result5 = "foo"
- variables.result6 = "#var#"
- variables.result7 = "foo #variables[ "var" ]# bar"
- variables.result8 = "foo #variables[ "#varname#" ]# bar"
- variables.result9 = "foo #variables[ 'var' ]# bar"
- variables.result10 = "foo #variables[ '#varname#' ]# bar"
- """,
- context );
- assertThat( variables.get( Key.of( "result1" ) ) ).isEqualTo( "bradfoo" );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "foobrad" );
- assertThat( variables.get( Key.of( "result3" ) ) ).isEqualTo( "foobradbar" );
- assertThat( variables.get( Key.of( "result4" ) ) ).isEqualTo( "foobradbarbradbazbradbum" );
- assertThat( variables.get( Key.of( "result5" ) ) ).isEqualTo( "foo" );
- assertThat( variables.get( Key.of( "result6" ) ) ).isEqualTo( "brad" );
- assertThat( variables.get( Key.of( "result7" ) ) ).isEqualTo( "foo brad bar" );
- assertThat( variables.get( Key.of( "result8" ) ) ).isEqualTo( "foo brad bar" );
- assertThat( variables.get( Key.of( "result9" ) ) ).isEqualTo( "foo brad bar" );
- assertThat( variables.get( Key.of( "result10" ) ) ).isEqualTo( "foo brad bar" );
-
- }
-
- @DisplayName( "String parsing interpolation single" )
- @Test
- public void testStringParsingInterpolationSingle() {
-
- instance.executeSource(
- """
- variables.var = "brad"
- varname = "var"
- variables.result1 = '#var#foo'
- variables.result2 = 'foo#var#'
- variables.result3 = 'foo#var#bar'
- variables.result4 = 'foo#var#bar#var#baz#var#bum'
- variables.result5 = 'foo'
- variables.result6 = '#var#'
- variables.result7 = 'foo #variables[ 'var' ]# bar'
- variables.result8 = 'foo #variables[ '#varname#' ]# bar'
- variables.result9 = 'foo #variables[ "var" ]# bar'
- variables.result10 = 'foo #variables[ "#varname#" ]# bar'
- """,
- context );
- assertThat( variables.get( Key.of( "result1" ) ) ).isEqualTo( "bradfoo" );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "foobrad" );
- assertThat( variables.get( Key.of( "result3" ) ) ).isEqualTo( "foobradbar" );
- assertThat( variables.get( Key.of( "result4" ) ) ).isEqualTo( "foobradbarbradbazbradbum" );
- assertThat( variables.get( Key.of( "result5" ) ) ).isEqualTo( "foo" );
- assertThat( variables.get( Key.of( "result6" ) ) ).isEqualTo( "brad" );
- assertThat( variables.get( Key.of( "result7" ) ) ).isEqualTo( "foo brad bar" );
- assertThat( variables.get( Key.of( "result8" ) ) ).isEqualTo( "foo brad bar" );
- assertThat( variables.get( Key.of( "result9" ) ) ).isEqualTo( "foo brad bar" );
- assertThat( variables.get( Key.of( "result10" ) ) ).isEqualTo( "foo brad bar" );
-
- }
-
- @DisplayName( "String parsing - escaped pound sign" )
- @Test
- public void testStringParsingEscapedPoundSign() {
-
- instance.executeSource(
- """
- // Pound signs in a string are escaped by doubling them
- variables.test8 = "I have locker ##20"
- // Also "I have locker #20" should throw a parsing syntax exception.
- """,
- context );
- assertThat( variables.get( Key.of( "test8" ) ) ).isEqualTo( "I have locker #20" );
-
- }
-
- @DisplayName( "String parsing - escaped Java chars" )
- @Test
- public void testStringParsingEscapedJavaChars() {
-
- instance.executeSource(
- """
- result = "this is not \\t a tab"
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "this is not \\t a tab" );
-
- instance.executeSource(
- """
- result = "foo "" bar '' baz"
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "foo \" bar '' baz" );
-
- instance.executeSource(
- """
- result = 'foo "" bar '' baz'
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "foo \"\" bar ' baz" );
-
- instance.executeSource(
- """
- result = 'foo bar'
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "foo \t bar" );
-
- }
-
- @DisplayName( "String parsing - escaped Java chars with interpolation" )
- @Test
- public void testStringParsingEscapedJavaCharsInter() {
-
- instance.executeSource(
- """
- brad="wood"
- result = "this is not \\t a tab#brad#"
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "this is not \\t a tabwood" );
-
- instance.executeSource(
- """
- brad="wood"
- result = "foo "" bar '' baz#brad#"
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "foo \" bar '' bazwood" );
-
- instance.executeSource(
- """
- brad="wood"
- result = 'foo "" bar '' baz#brad#'
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "foo \"\" bar ' bazwood" );
-
- instance.executeSource(
- """
- brad="wood"
- result = 'foo bar#brad#'
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "foo \t barwood" );
-
- }
-
- @DisplayName( "String parsing concat" )
- @Test
- public void testStringParsingConcat() {
-
- instance.executeSource(
- """
- variables.a = "brad"
- variables.b = "luis"
- variables.result = "a is #variables.a# and b is #variables.b#"
-
- """,
- context );
- assertThat( variables.get( Key.of( "result" ) ) ).isEqualTo( "a is brad and b is luis" );
-
- }
-
- @DisplayName( "String parsing unclosed quotes" )
- @Test
- public void testStringParsingUnclosedQuotes() {
- Throwable t = assertThrows( BoxRuntimeException.class, () -> instance.executeSource(
- """
- foo = "unfinished
- """,
- context ) );
- assertThat( t.getMessage() ).contains( "Unterminated" );
-
- t = assertThrows( BoxRuntimeException.class, () -> instance.executeSource(
- """
- foo = 'unfinished
- """,
- context ) );
- assertThat( t.getMessage() ).contains( "Unterminated" );
- }
-
- @DisplayName( "It should throw BoxRuntimeException" )
- @Test
- public void testBoxRuntimeException() {
-
- Throwable t = assertThrows( BoxRuntimeException.class, () -> instance.executeSource(
- """
- throw "test"
- """,
- context ) );
- assertThat( t.getMessage() ).contains( "test" );
- }
-
- @DisplayName( "It should throw BoxRuntimeException in CF" )
- @Test
- public void testBoxRuntimeExceptionCF() {
-
- Throwable t = assertThrows( BoxRuntimeException.class, () -> instance.executeSource(
- """
- throw "test"
- """,
- context, BoxSourceType.CFSCRIPT ) );
- assertThat( t.getMessage() ).contains( "test" );
- }
-
- @DisplayName( "String parsing unclosed pound" )
- @Test
- public void testStringParsingUnclosedPound() {
-
- Throwable t = assertThrows( BoxRuntimeException.class, () -> instance.executeSource(
- """
- // should throw a parsing syntax exception.
- result = "I have locker #20";
- """,
- context
- )
- );
- assertThat( t.getMessage() ).contains( "Unterminated hash" );
-
- }
-
- @DisplayName( "String parsing 6" )
- @Test
- public void testStringParsing6() {
-
- instance.executeSource(
- """
- // On an unrelated note, pound signs around CFScript expressions are superfluous and should be ignored by the parser.
- timeVar = "12:00 PM"
- test9 = "Time is: " & #timeVar#
- result = "BoxLang"
- test10 = #result#;
- """,
- context );
-
- assertThat( variables.get( Key.of( "test9" ) ) ).isEqualTo( "Time is: 12:00 PM" );
- assertThat( variables.get( Key.of( "test10" ) ) ).isEqualTo( "BoxLang" );
-
- }
-
- @DisplayName( "String parsing expression in pounds" )
- @Test
- public void testStringParsingExpressionInPounds() {
-
- instance.executeSource(
- """
- result = "Box#5+6#Lang"
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( "Box11Lang" );
-
- }
-
- @DisplayName( "switch" )
- @Test
- public void testSwtich() {
-
- instance.executeSource(
- """
- result = ""
- variables.foo = true;
-
- switch( "12" ) {
- case "brad":
- // case 1 logic
- result = "case1"
- more="than";
- one="statement"
- here="test";
- break;
- case 42: {
- // case 2 logic
- result = "case2"
- break;
- }
- case 5+7:
- // case 3 logic
- result = "case3"
- more="than";
- one="statement"
- here="test";
- break;
- case variables.foo:
- // case 4 logic
- result = "case4"
- break;
- default:
- // default case logic
- result = "case default"
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( "case3" );
-
- }
-
- @Test
- public void testSwtichWithBreakInDefault() {
-
- instance.executeSource(
- """
- result = ""
- variables.foo = true;
-
- switch( "12" ) {
- case "brad":
- result= "brad";
- break;
- default:
- result="test";
- break;
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( "test" );
-
- }
-
- @DisplayName( "switch fall through case" )
- @Test
- public void testSwtichFallThroughCase() {
-
- instance.executeSource(
- """
- bradRan = false
- luisRan = false
- gavinRan = false
- jorgeRan = false
-
- switch( "luis" ) {
- case "brad":
- bradRan = true
- break;
- // This case will be entered
- case "luis": {
- luisRan = true
- }
- // Because there is no break, this case will also be entered
- case "gavin":
- gavinRan = true
- break;
- // But we'll never reach this one
- case "jorge":
- jorgeRan = true
- break;
- }
-
- """,
- context );
-
- assertThat( variables.get( Key.of( "bradRan" ) ) ).isEqualTo( false );
- assertThat( variables.get( Key.of( "luisRan" ) ) ).isEqualTo( true );
- assertThat( variables.get( Key.of( "gavinRan" ) ) ).isEqualTo( true );
- assertThat( variables.get( Key.of( "jorgeRan" ) ) ).isEqualTo( false );
- }
-
- @DisplayName( "switch default" )
- @Test
- public void testSwitchDefault() {
-
- instance.executeSource(
- """
- result = ""
- // must be boolean
- variables.foo = false;
-
- switch( "sdfsd"&"fsdf" & (5+4) ) {
- case "brad":
- // case 1 logic
- result = "case1"
- break;
- case 42: {
- // case 2 logic
- result = "case2"
- break;
- }
- case 5+7:
- // case 3 logic
- result = "case3"
- case variables.foo:
- // case 4 logic
- result = "case4"
- break;
- default:
- // default case logic
- result = "case default"
- }
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( "case default" );
- }
-
- @Test
- public void testSwitchMultipleCase() {
-
- instance.executeSource(
- """
- myVar = 'a';
- result = '';
-
- switch(myVar) {
- case 'a':
- case 'b':
- case 'c':
- result &= 'fall through1';
- case 'd':
- case undefinedVar: // Lucee throws an exception here, ACF does not.
- result &= 'fall through2';
- break;
- default:
- result &= 'default';
- }
-
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( "fall through1fall through2" );
- }
-
- @DisplayName( "String as array" )
- @Test
- public void testStringAsArray() {
-
- instance.executeSource(
- """
- name = "brad"
- result = name[3]
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( "a" );
-
- instance.executeSource(
- """
- result = "brad"[3]
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( "a" );
-
- instance.executeSource(
- """
- result = "brad".CASE_INSENSITIVE_ORDER
- """,
- context );
-
- assertThat( variables.get( result ) instanceof Comparator ).isTrue();
-
- }
-
- @Test
- public void testKeywords() {
-
- instance.executeSource(
- """
- result = {
- abstract : ()->'abstract',
- abort : ()->'abort',
- admin : ()->'admin',
- any : ()->'any',
- array : ()->'array',
- as : ()->'as',
- assert : ()->'assert',
- boolean : ()->'boolean',
- break : ()->'break',
- case : ()->'case',
- castas : ()->'castas',
- catch : ()->'catch',
- class : ()->'class',
- component : ()->'component',
- contain : ()->'contain',
- contains : ()->'contains',
- continue : ()->'continue',
- default : ()->'default',
- does : ()->'does',
- do : ()->'do',
- else : ()->'else',
- elif : ()->'elif',
- false : ()->'false',
- finally : ()->'finally',
- for : ()->'for',
- function : ()->'function',
- greater : ()->'greater',
- if : ()->'if',
- in : ()->'in',
- import : ()->'import',
- include : ()->'include',
- interface : ()->'interface',
- instanceof : ()->'instanceof',
- is : ()->'is',
- java : ()->'java',
- less : ()->'less',
- local : ()->'local',
- lock : ()->'lock',
- mod : ()->'mod',
- message : ()->'message',
- new : ()->'new',
- null : ()->'null',
- numeric : ()->'numeric',
- package : ()->'package',
- param : ()->'param',
- private : ()->'private',
- property : ()->'property',
- public : ()->'public',
- query : ()->'query',
- remote : ()->'remote',
- required : ()->'required',
- request : ()->'request',
- return : ()->'return',
- rethrow : ()->'rethrow',
- savecontent : ()->'savecontent',
- setting : ()->'setting',
- static : ()->'static',
- string : ()->'string',
- struct : ()->'struct',
- //switch : ()->'switch',
- than : ()->'than',
- to : ()->'to',
- thread : ()->'thread',
- throw : ()->'throw',
- type : ()->'type',
- true : ()->'true',
- try : ()->'try',
- var : ()->'var',
- when : ()->'when',
- while : ()->'while',
- xor : ()->'xor',
- eq : ()->'eq',
- eqv : ()->'eqv',
- imp : ()->'imp',
- and : ()->'and',
- eq : ()->'eq',
- equal : ()->'equal',
- gt : ()->'gt',
- gte : ()->'gte',
- ge : ()->'ge',
- lt : ()->'lt',
- lte : ()->'lte',
- le : ()->'le',
- neq : ()->'neq',
- not : ()->'not',
- or : ()->'or'
-
- };
-
-
- result.abstract;
- result.abort;
- result.admin;
- result.any;
- result.array;
- result.as;
- result.assert;
- result.boolean;
- result.break;
- result.case;
- result.castas;
- result.catch;
- result.class;
- result.component;
- result.contain;
- result.contains;
- result.continue;
- result.default;
- result.does;
- result.do;
- result.else;
- result.elif;
- result.false;
- result.finally;
- result.for;
- result.function;
- result.greater;
- result.if;
- result.in;
- result.import;
- result.include;
- result.interface;
- result.instanceof;
- result.is;
- result.java;
- result.less;
- result.local;
- result.lock;
- result.mod;
- result.message;
- result.new;
- result.null;
- result.numeric;
- result.package;
- result.param;
- result.private;
- result.property;
- result.public;
- result.query;
- result.remote;
- result.required;
- result.request;
- result.return;
- result.rethrow;
- result.savecontent;
- result.setting;
- result.static;
- result.string;
- result.struct;
- // result.switch;
- result.than;
- result.to;
- result.thread;
- result.throw;
- result.type;
- result.true;
- result.try;
- result.var;
- result.when;
- result.while;
- result.xor;
- result.eq;
- result.eqv;
- result.imp;
- result.and;
- result.eq;
- result.equal;
- result.gt;
- result.gte;
- result.ge;
- result.lt;
- result.lte;
- result.le;
- result.neq;
- result.not;
- result.or;
-
- result.abstract();
- result.abort();
- result.admin();
- result.any();
- result.array();
- result.as();
- result.assert();
- result.boolean();
- result.break();
- result.case();
- result.castas();
- result.catch();
- result.class();
- result.component();
- result.contain();
- result.contains();
- result.continue();
- result.default();
- result.does();
- result.do();
- result.else();
- result.elif();
- result.false();
- result.finally();
- result.for();
- result.function();
- result.greater();
- result.if();
- result.in();
- result.import();
- result.include();
- result.interface();
- result.instanceof();
- result.is();
- result.java();
- result.less();
- result.local();
- result.lock();
- result.mod();
- result.message();
- result.new();
- result.null();
- result.numeric();
- result.package();
- result.param();
- result.private();
- result.property();
- result.public();
- result.query();
- result.remote();
- result.required();
- result.request();
- result.return();
- result.rethrow();
- result.savecontent();
- result.setting();
- result.static();
- result.string();
- result.struct();
- // result.switch();
- result.than();
- result.to();
- result.thread();
- result.throw();
- result.type();
- result.true();
- result.try();
- result.var();
- result.when();
- result.while();
- result.xor();
- result.eq();
- result.eqv();
- result.imp();
- result.and();
- result.eq();
- result.equal();
- result.gt();
- result.gte();
- result.ge();
- result.lt();
- result.lte();
- result.le();
- result.neq();
- result.not();
- result.or();
-
- variables.addAll( result.getWrapped() );
-
- abstract();
- abort();
- admin();
- any();
- array();
- as();
- assert();
- boolean();
- break();
- case();
- castas();
- catch();
- class();
- component();
- contain();
- contains();
- continue();
- default();
- does();
- do();
- else();
- elif();
- false();
- finally();
- for();
- function();
- greater();
- if();
- in();
- import();
- include();
- interface();
- instanceof();
- is();
- java();
- less();
- local();
- lock();
- mod();
- message();
- new();
- null();
- numeric();
- package();
- param();
- private();
- property();
- public();
- query();
- remote();
- required();
- request();
- return();
- rethrow();
- savecontent();
- setting();
- static();
- string();
- struct();
- // switch();
- than();
- to();
- thread();
- // throw(); <-- Actual throw construct
- type();
- true();
- try();
- var();
- when();
- while();
- xor();
- eq();
- eqv();
- imp();
- and();
- eq();
- equal();
- gt();
- gte();
- ge();
- lt();
- lte();
- le();
- neq();
- or();
- """,
- context );
-
- assertThat( variables.get( result ) ).isInstanceOf( Struct.class );
- var str = variables.getAsStruct( result );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "abstract" ), new Object[] {}, false ) ).isEqualTo( "abstract" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "abort" ), new Object[] {}, false ) ).isEqualTo( "abort" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "admin" ), new Object[] {}, false ) ).isEqualTo( "admin" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "any" ), new Object[] {}, false ) ).isEqualTo( "any" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "array" ), new Object[] {}, false ) ).isEqualTo( "array" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "as" ), new Object[] {}, false ) ).isEqualTo( "as" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "assert" ), new Object[] {}, false ) ).isEqualTo( "assert" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "boolean" ), new Object[] {}, false ) ).isEqualTo( "boolean" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "break" ), new Object[] {}, false ) ).isEqualTo( "break" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "case" ), new Object[] {}, false ) ).isEqualTo( "case" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "castas" ), new Object[] {}, false ) ).isEqualTo( "castas" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "catch" ), new Object[] {}, false ) ).isEqualTo( "catch" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "class" ), new Object[] {}, false ) ).isEqualTo( "class" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "component" ), new Object[] {}, false ) ).isEqualTo( "component" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "contain" ), new Object[] {}, false ) ).isEqualTo( "contain" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "contains" ), new Object[] {}, false ) ).isEqualTo( "contains" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "continue" ), new Object[] {}, false ) ).isEqualTo( "continue" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "default" ), new Object[] {}, false ) ).isEqualTo( "default" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "does" ), new Object[] {}, false ) ).isEqualTo( "does" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "do" ), new Object[] {}, false ) ).isEqualTo( "do" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "else" ), new Object[] {}, false ) ).isEqualTo( "else" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "elif" ), new Object[] {}, false ) ).isEqualTo( "elif" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "false" ), new Object[] {}, false ) ).isEqualTo( "false" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "finally" ), new Object[] {}, false ) ).isEqualTo( "finally" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "for" ), new Object[] {}, false ) ).isEqualTo( "for" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "function" ), new Object[] {}, false ) ).isEqualTo( "function" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "greater" ), new Object[] {}, false ) ).isEqualTo( "greater" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "if" ), new Object[] {}, false ) ).isEqualTo( "if" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "in" ), new Object[] {}, false ) ).isEqualTo( "in" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "import" ), new Object[] {}, false ) ).isEqualTo( "import" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "include" ), new Object[] {}, false ) ).isEqualTo( "include" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "interface" ), new Object[] {}, false ) ).isEqualTo( "interface" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "instanceof" ), new Object[] {}, false ) ).isEqualTo( "instanceof" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "is" ), new Object[] {}, false ) ).isEqualTo( "is" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "java" ), new Object[] {}, false ) ).isEqualTo( "java" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "less" ), new Object[] {}, false ) ).isEqualTo( "less" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "local" ), new Object[] {}, false ) ).isEqualTo( "local" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "lock" ), new Object[] {}, false ) ).isEqualTo( "lock" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "mod" ), new Object[] {}, false ) ).isEqualTo( "mod" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "message" ), new Object[] {}, false ) ).isEqualTo( "message" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "new" ), new Object[] {}, false ) ).isEqualTo( "new" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "null" ), new Object[] {}, false ) ).isEqualTo( "null" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "numeric" ), new Object[] {}, false ) ).isEqualTo( "numeric" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "package" ), new Object[] {}, false ) ).isEqualTo( "package" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "param" ), new Object[] {}, false ) ).isEqualTo( "param" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "private" ), new Object[] {}, false ) ).isEqualTo( "private" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "property" ), new Object[] {}, false ) ).isEqualTo( "property" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "public" ), new Object[] {}, false ) ).isEqualTo( "public" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "query" ), new Object[] {}, false ) ).isEqualTo( "query" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "remote" ), new Object[] {}, false ) ).isEqualTo( "remote" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "required" ), new Object[] {}, false ) ).isEqualTo( "required" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "request" ), new Object[] {}, false ) ).isEqualTo( "request" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "return" ), new Object[] {}, false ) ).isEqualTo( "return" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "rethrow" ), new Object[] {}, false ) ).isEqualTo( "rethrow" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "savecontent" ), new Object[] {}, false ) ).isEqualTo( "savecontent" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "setting" ), new Object[] {}, false ) ).isEqualTo( "setting" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "static" ), new Object[] {}, false ) ).isEqualTo( "static" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "string" ), new Object[] {}, false ) ).isEqualTo( "string" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "struct" ), new Object[] {}, false ) ).isEqualTo( "struct" );
- // assertThat( str.dereferenceAndInvoke( context, Key.of( "switch" ), new Object[] {}, false ) ).isEqualTo( "switch" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "than" ), new Object[] {}, false ) ).isEqualTo( "than" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "to" ), new Object[] {}, false ) ).isEqualTo( "to" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "thread" ), new Object[] {}, false ) ).isEqualTo( "thread" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "throw" ), new Object[] {}, false ) ).isEqualTo( "throw" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "type" ), new Object[] {}, false ) ).isEqualTo( "type" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "true" ), new Object[] {}, false ) ).isEqualTo( "true" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "try" ), new Object[] {}, false ) ).isEqualTo( "try" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "var" ), new Object[] {}, false ) ).isEqualTo( "var" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "when" ), new Object[] {}, false ) ).isEqualTo( "when" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "while" ), new Object[] {}, false ) ).isEqualTo( "while" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "xor" ), new Object[] {}, false ) ).isEqualTo( "xor" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "eq" ), new Object[] {}, false ) ).isEqualTo( "eq" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "eqv" ), new Object[] {}, false ) ).isEqualTo( "eqv" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "imp" ), new Object[] {}, false ) ).isEqualTo( "imp" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "and" ), new Object[] {}, false ) ).isEqualTo( "and" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "eq" ), new Object[] {}, false ) ).isEqualTo( "eq" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "equal" ), new Object[] {}, false ) ).isEqualTo( "equal" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "gt" ), new Object[] {}, false ) ).isEqualTo( "gt" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "gte" ), new Object[] {}, false ) ).isEqualTo( "gte" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "ge" ), new Object[] {}, false ) ).isEqualTo( "ge" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "lt" ), new Object[] {}, false ) ).isEqualTo( "lt" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "lte" ), new Object[] {}, false ) ).isEqualTo( "lte" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "le" ), new Object[] {}, false ) ).isEqualTo( "le" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "neq" ), new Object[] {}, false ) ).isEqualTo( "neq" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "not" ), new Object[] {}, false ) ).isEqualTo( "not" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "or" ), new Object[] {}, false ) ).isEqualTo( "or" );
-
- }
-
- @Test
- public void testKeywordsCF() {
-
- instance.executeSource(
- """
- result = {
- abstract : ()=>'abstract',
- abort : ()=>'abort',
- admin : ()=>'admin',
- any : ()=>'any',
- array : ()=>'array',
- as : ()=>'as',
- assert : ()=>'assert',
- boolean : ()=>'boolean',
- break : ()=>'break',
- case : ()=>'case',
- castas : ()=>'castas',
- catch : ()=>'catch',
- class : ()=>'class',
- component : ()=>'component',
- contain : ()=>'contain',
- contains : ()=>'contains',
- continue : ()=>'continue',
- default : ()=>'default',
- does : ()=>'does',
- do : ()=>'do',
- else : ()=>'else',
- elif : ()=>'elif',
- false : ()=>'false',
- finally : ()=>'finally',
- for : ()=>'for',
- function : ()=>'function',
- greater : ()=>'greater',
- if : ()=>'if',
- in : ()=>'in',
- import : ()=>'import',
- include : ()=>'include',
- interface : ()=>'interface',
- instanceof : ()=>'instanceof',
- is : ()=>'is',
- java : ()=>'java',
- less : ()=>'less',
- local : ()=>'local',
- lock : ()=>'lock',
- mod : ()=>'mod',
- message : ()=>'message',
- new : ()=>'new',
- null : ()=>'null',
- numeric : ()=>'numeric',
- package : ()=>'package',
- param : ()=>'param',
- private : ()=>'private',
- property : ()=>'property',
- public : ()=>'public',
- query : ()=>'query',
- remote : ()=>'remote',
- required : ()=>'required',
- request : ()=>'request',
- return : ()=>'return',
- rethrow : ()=>'rethrow',
- savecontent : ()=>'savecontent',
- setting : ()=>'setting',
- static : ()=>'static',
- string : ()=>'string',
- struct : ()=>'struct',
- //switch : ()=>'switch',
- than : ()=>'than',
- to : ()=>'to',
- thread : ()=>'thread',
- throw : ()=>'throw',
- type : ()=>'type',
- true : ()=>'true',
- try : ()=>'try',
- var : ()=>'var',
- when : ()=>'when',
- while : ()=>'while',
- xor : ()=>'xor',
- eq : ()=>'eq',
- eqv : ()=>'eqv',
- imp : ()=>'imp',
- and : ()=>'and',
- eq : ()=>'eq',
- equal : ()=>'equal',
- gt : ()=>'gt',
- gte : ()=>'gte',
- ge : ()=>'ge',
- lt : ()=>'lt',
- lte : ()=>'lte',
- le : ()=>'le',
- neq : ()=>'neq',
- not : ()=>'not',
- or : ()=>'or'
-
- };
-
-
- result.abstract;
- result.abort;
- result.admin;
- result.any;
- result.array;
- result.as;
- result.assert;
- result.boolean;
- result.break;
- result.case;
- result.castas;
- result.catch;
- result.class;
- result.component;
- result.contain;
- result.contains;
- result.continue;
- result.default;
- result.does;
- result.do;
- result.else;
- result.elif;
- result.false;
- result.finally;
- result.for;
- result.function;
- result.greater;
- result.if;
- result.in;
- result.import;
- result.include;
- result.interface;
- result.instanceof;
- result.is;
- result.java;
- result.less;
- result.local;
- result.lock;
- result.mod;
- result.message;
- result.new;
- result.null;
- result.numeric;
- result.package;
- result.param;
- result.private;
- result.property;
- result.public;
- result.query;
- result.remote;
- result.required;
- result.request;
- result.return;
- result.rethrow;
- result.savecontent;
- result.setting;
- result.static;
- result.string;
- result.struct;
- // result.switch;
- result.than;
- result.to;
- result.thread;
- result.throw;
- result.type;
- result.true;
- result.try;
- result.var;
- result.when;
- result.while;
- result.xor;
- result.eq;
- result.eqv;
- result.imp;
- result.and;
- result.eq;
- result.equal;
- result.gt;
- result.gte;
- result.ge;
- result.lt;
- result.lte;
- result.le;
- result.neq;
- result.not;
- result.or;
-
- result.abstract();
- result.abort();
- result.admin();
- result.any();
- result.array();
- result.as();
- result.assert();
- result.boolean();
- result.break();
- result.case();
- result.castas();
- result.catch();
- result.class();
- result.component();
- result.contain();
- result.contains();
- result.continue();
- result.default();
- result.does();
- result.do();
- result.else();
- result.elif();
- result.false();
- result.finally();
- result.for();
- result.function();
- result.greater();
- result.if();
- result.in();
- result.import();
- result.include();
- result.interface();
- result.instanceof();
- result.is();
- result.java();
- result.less();
- result.local();
- result.lock();
- result.mod();
- result.message();
- result.new();
- result.null();
- result.numeric();
- result.package();
- result.param();
- result.private();
- result.property();
- result.public();
- result.query();
- result.remote();
- result.required();
- result.request();
- result.return();
- result.rethrow();
- result.savecontent();
- result.setting();
- result.static();
- result.string();
- result.struct();
- // result.switch();
- result.than();
- result.to();
- result.thread();
- result.throw();
- result.type();
- result.true();
- result.try();
- result.var();
- result.when();
- result.while();
- result.xor();
- result.eq();
- result.eqv();
- result.imp();
- result.and();
- result.eq();
- result.equal();
- result.gt();
- result.gte();
- result.ge();
- result.lt();
- result.lte();
- result.le();
- result.neq();
- result.not();
- result.or();
-
- variables.addAll( result.getWrapped() );
-
- abstract();
- abort();
- admin();
- any();
- array();
- as();
- assert();
- boolean();
- break();
- case();
- castas();
- catch();
- class();
- component();
- contain();
- contains();
- continue();
- default();
- does();
- do();
- else();
- elif();
- false();
- finally();
- for();
- function();
- greater();
- if();
- in();
- import();
- include();
- interface();
- instanceof();
- is();
- java();
- less();
- local();
- lock();
- mod();
- message();
- new();
- null();
- numeric();
- package();
- param();
- private();
- property();
- public();
- query();
- remote();
- required();
- request();
- return();
- rethrow();
- savecontent();
- setting();
- static();
- string();
- struct();
- // switch();
- than();
- to();
- thread();
- // throw(); <-- Actual throw construct
- type();
- true();
- try();
- var();
- when();
- while();
- xor();
- eq();
- eqv();
- imp();
- and();
- eq();
- equal();
- gt();
- gte();
- ge();
- lt();
- lte();
- le();
- neq();
- or();
- """,
- context, BoxSourceType.CFSCRIPT );
-
- assertThat( variables.get( result ) ).isInstanceOf( Struct.class );
- var str = variables.getAsStruct( result );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "abstract" ), new Object[] {}, false ) ).isEqualTo( "abstract" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "abort" ), new Object[] {}, false ) ).isEqualTo( "abort" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "admin" ), new Object[] {}, false ) ).isEqualTo( "admin" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "any" ), new Object[] {}, false ) ).isEqualTo( "any" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "array" ), new Object[] {}, false ) ).isEqualTo( "array" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "as" ), new Object[] {}, false ) ).isEqualTo( "as" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "assert" ), new Object[] {}, false ) ).isEqualTo( "assert" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "boolean" ), new Object[] {}, false ) ).isEqualTo( "boolean" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "break" ), new Object[] {}, false ) ).isEqualTo( "break" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "case" ), new Object[] {}, false ) ).isEqualTo( "case" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "castas" ), new Object[] {}, false ) ).isEqualTo( "castas" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "catch" ), new Object[] {}, false ) ).isEqualTo( "catch" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "class" ), new Object[] {}, false ) ).isEqualTo( "class" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "component" ), new Object[] {}, false ) ).isEqualTo( "component" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "contain" ), new Object[] {}, false ) ).isEqualTo( "contain" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "contains" ), new Object[] {}, false ) ).isEqualTo( "contains" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "continue" ), new Object[] {}, false ) ).isEqualTo( "continue" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "default" ), new Object[] {}, false ) ).isEqualTo( "default" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "does" ), new Object[] {}, false ) ).isEqualTo( "does" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "do" ), new Object[] {}, false ) ).isEqualTo( "do" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "else" ), new Object[] {}, false ) ).isEqualTo( "else" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "elif" ), new Object[] {}, false ) ).isEqualTo( "elif" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "false" ), new Object[] {}, false ) ).isEqualTo( "false" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "finally" ), new Object[] {}, false ) ).isEqualTo( "finally" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "for" ), new Object[] {}, false ) ).isEqualTo( "for" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "function" ), new Object[] {}, false ) ).isEqualTo( "function" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "greater" ), new Object[] {}, false ) ).isEqualTo( "greater" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "if" ), new Object[] {}, false ) ).isEqualTo( "if" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "in" ), new Object[] {}, false ) ).isEqualTo( "in" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "import" ), new Object[] {}, false ) ).isEqualTo( "import" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "include" ), new Object[] {}, false ) ).isEqualTo( "include" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "interface" ), new Object[] {}, false ) ).isEqualTo( "interface" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "instanceof" ), new Object[] {}, false ) ).isEqualTo( "instanceof" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "is" ), new Object[] {}, false ) ).isEqualTo( "is" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "java" ), new Object[] {}, false ) ).isEqualTo( "java" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "less" ), new Object[] {}, false ) ).isEqualTo( "less" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "local" ), new Object[] {}, false ) ).isEqualTo( "local" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "lock" ), new Object[] {}, false ) ).isEqualTo( "lock" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "mod" ), new Object[] {}, false ) ).isEqualTo( "mod" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "message" ), new Object[] {}, false ) ).isEqualTo( "message" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "new" ), new Object[] {}, false ) ).isEqualTo( "new" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "null" ), new Object[] {}, false ) ).isEqualTo( "null" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "numeric" ), new Object[] {}, false ) ).isEqualTo( "numeric" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "package" ), new Object[] {}, false ) ).isEqualTo( "package" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "param" ), new Object[] {}, false ) ).isEqualTo( "param" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "private" ), new Object[] {}, false ) ).isEqualTo( "private" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "property" ), new Object[] {}, false ) ).isEqualTo( "property" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "public" ), new Object[] {}, false ) ).isEqualTo( "public" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "query" ), new Object[] {}, false ) ).isEqualTo( "query" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "remote" ), new Object[] {}, false ) ).isEqualTo( "remote" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "required" ), new Object[] {}, false ) ).isEqualTo( "required" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "request" ), new Object[] {}, false ) ).isEqualTo( "request" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "return" ), new Object[] {}, false ) ).isEqualTo( "return" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "rethrow" ), new Object[] {}, false ) ).isEqualTo( "rethrow" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "savecontent" ), new Object[] {}, false ) ).isEqualTo( "savecontent" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "setting" ), new Object[] {}, false ) ).isEqualTo( "setting" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "static" ), new Object[] {}, false ) ).isEqualTo( "static" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "string" ), new Object[] {}, false ) ).isEqualTo( "string" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "struct" ), new Object[] {}, false ) ).isEqualTo( "struct" );
- // assertThat( str.dereferenceAndInvoke( context, Key.of( "switch" ), new Object[] {}, false ) ).isEqualTo( "switch" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "than" ), new Object[] {}, false ) ).isEqualTo( "than" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "to" ), new Object[] {}, false ) ).isEqualTo( "to" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "thread" ), new Object[] {}, false ) ).isEqualTo( "thread" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "throw" ), new Object[] {}, false ) ).isEqualTo( "throw" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "type" ), new Object[] {}, false ) ).isEqualTo( "type" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "true" ), new Object[] {}, false ) ).isEqualTo( "true" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "try" ), new Object[] {}, false ) ).isEqualTo( "try" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "var" ), new Object[] {}, false ) ).isEqualTo( "var" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "when" ), new Object[] {}, false ) ).isEqualTo( "when" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "while" ), new Object[] {}, false ) ).isEqualTo( "while" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "xor" ), new Object[] {}, false ) ).isEqualTo( "xor" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "eq" ), new Object[] {}, false ) ).isEqualTo( "eq" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "eqv" ), new Object[] {}, false ) ).isEqualTo( "eqv" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "imp" ), new Object[] {}, false ) ).isEqualTo( "imp" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "and" ), new Object[] {}, false ) ).isEqualTo( "and" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "eq" ), new Object[] {}, false ) ).isEqualTo( "eq" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "equal" ), new Object[] {}, false ) ).isEqualTo( "equal" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "gt" ), new Object[] {}, false ) ).isEqualTo( "gt" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "gte" ), new Object[] {}, false ) ).isEqualTo( "gte" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "ge" ), new Object[] {}, false ) ).isEqualTo( "ge" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "lt" ), new Object[] {}, false ) ).isEqualTo( "lt" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "lte" ), new Object[] {}, false ) ).isEqualTo( "lte" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "le" ), new Object[] {}, false ) ).isEqualTo( "le" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "neq" ), new Object[] {}, false ) ).isEqualTo( "neq" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "not" ), new Object[] {}, false ) ).isEqualTo( "not" );
- assertThat( str.dereferenceAndInvoke( context, Key.of( "or" ), new Object[] {}, false ) ).isEqualTo( "or" );
-
- }
-
- @DisplayName( "BL structKeyExists" )
- @Test
- public void testBLStructKeyExists() {
-
- instance.executeSource(
- """
- str = {
- foo : 'bar',
- baz : null
- };
- result = structKeyExists( str, "foo" )
- result2 = structKeyExists( str, "baz" )
- """,
- context );
-
- assertThat( variables.getAsBoolean( result ) ).isTrue();
- assertThat( variables.getAsBoolean( Key.of( "result2" ) ) ).isTrue();
-
- }
-
- @Test
- public void numberKey() {
-
- instance.executeSource(
- """
- local.5 = {minimumMinor = 2, minimumPatch = 1, minimumBuild = 9};
- """,
- context, BoxSourceType.CFSCRIPT );
-
- assertThat( variables.get( Key.of( "local" ) ) ).isInstanceOf( Struct.class );
- IStruct localStr = variables.getAsStruct( Key.of( "local" ) );
- assertThat( localStr.get( Key.of( 5 ) ) ).isInstanceOf( Struct.class );
- IStruct fiveStr = localStr.getAsStruct( Key.of( 5 ) );
- assertThat( fiveStr.get( Key.of( "minimumMinor" ) ) ).isEqualTo( 2 );
- }
-
- @Test
- public void testTagCommentInScript() {
- // This is a CF-only workaround
- instance.executeSource(
- """
- foo = "bar"
-
- baz = "bum";
- """,
- context, BoxSourceType.CFSCRIPT );
-
- }
-
- @Test
- public void breakFromFunction() {
-
- instance.executeSource(
- """
- test = [ 1,2,3,4,5,6,7,8 ];
- result = "";
- test.each( ( a ) => {
- result &= a;
- if( a > 4 ){
- break;
- }
- result &= "after";
- } )
- """,
- context, BoxSourceType.CFSCRIPT );
-
- assertThat( variables.get( result ) ).isEqualTo( "1after2after3after4after5678" );
- }
-
- @Test
- public void continueFromFunction() {
-
- instance.executeSource(
- """
- test = [ 1,2,3,4,5,6,7,8 ];
- result = "";
- test.each( ( a ) => {
- result &= a;
- if( a > 4 ){
- continue;
- }
- result &= "after";
- } )
- """,
- context, BoxSourceType.CFSCRIPT );
-
- assertThat( variables.get( result ) ).isEqualTo( "1after2after3after4after5678" );
- }
-
- @Test
- public void continueFromFunctionJustKiddingItsALoop() {
-
- instance.executeSource(
- """
- test = [ 1,2,3,4,5,6,7,8 ];
- result = "";
- test.each( ( a ) => {
- result &= a;
- if( a > 4 ){
- while( false ) {
- continue;
- }
- }
- result &= "after";
- } )
- """,
- context, BoxSourceType.CFSCRIPT );
-
- assertThat( variables.get( result ) ).isEqualTo( "1after2after3after4after5after6after7after8after" );
- }
-
- @Test
- public void whileNoCurlies() {
-
- instance.executeSource(
- """
- result = "";
- a=0;
- do result=result.listAppend( a++ );
- while (a<5);
- """,
- context, BoxSourceType.CFSCRIPT );
-
- assertThat( variables.get( result ) ).isEqualTo( "0,1,2,3,4" );
- }
-
- @Test
- public void whileNoCurliesNoSemi() {
-
- instance.executeSource(
- """
- result = "";
- a=0;
- do result=result.listAppend( a++ )
- while (a<5);
- """,
- context, BoxSourceType.CFSCRIPT );
-
- assertThat( variables.get( result ) ).isEqualTo( "0,1,2,3,4" );
- }
-
- @Test
- public void statementBlocks() {
-
- instance.executeSource(
- """
- result = "I ran"
- {
- result &= " in a block";
- }
- {}{}{}{}{}{}
- {{{{{{{
- result &= " with a lot of braces";
- }}}}}}}
- result &= "!";
-
- """,
- context, BoxSourceType.CFSCRIPT );
-
- assertThat( variables.get( result ) ).isEqualTo( "I ran in a block with a lot of braces!" );
- }
-
- @Test
- public void commentParse() {
-
- String comment = """
- /****
- * Global Getters *
- ****/
- """;
- ParsingResult result;
- try {
- result = new DocParser().parse( null, comment );
- assertThat( result.getRoot().toString().trim() ).isEqualTo( comment.trim() );
- } catch ( IOException e ) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- @Test
- public void commentParseInline() {
-
- String comment = """
- /** foo */
- """;
- ParsingResult result;
- try {
- result = new DocParser().parse( null, comment );
- assertThat( result.getRoot().toString().trim() ).isEqualTo( comment.trim() );
- } catch ( IOException e ) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- @Test
- public void commentParseSmoll() {
-
- String comment = """
- /**
- * foo */
- """;
- ParsingResult result;
- try {
- result = new DocParser().parse( null, comment );
- assertThat( result.getRoot().toString().trim() ).isEqualTo( comment.trim() );
- } catch ( IOException e ) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- @Test
- public void unicode() {
-
- instance.executeSource(
- """
- include "src/test/java/TestCases/phase1/unicode.cfm";
- """,
- context, BoxSourceType.CFSCRIPT );
- assertThat( variables.get( result ) ).isEqualTo( "kōwhai" );
-
- }
-
- @Test
- public void testThrowStatment() {
-
- instance.executeSource(
- """
- f = function () {
- throw("m")
- }
- """,
- context, BoxSourceType.CFSCRIPT );
-
- }
-
- @Test
- public void testJavaProxyInitSetsInstance() {
-
- instance.executeSource(
- """
- x = createObject("java", "java.lang.StringBuffer");
- x.init(javaCast("int", 500));
- result = x.toString();
-
- y = createObject("java", "java.lang.String");
- y.init("test");
- result2 = y.toString();
- """,
- context, BoxSourceType.CFSCRIPT );
- assertThat( variables.get( result ) ).isEqualTo( "" );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "test" );
-
- }
-
-}
diff --git a/src/test/java/TestCases/asm/phase1/DereferenceTest.java b/src/test/java/TestCases/asm/phase1/DereferenceTest.java
deleted file mode 100644
index 3fb407bd2..000000000
--- a/src/test/java/TestCases/asm/phase1/DereferenceTest.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.phase1;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import java.util.Map;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.interop.DynamicObject;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-import ortus.boxlang.runtime.types.IStruct;
-import ortus.boxlang.runtime.types.Struct;
-
-public class DereferenceTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "Single identifier dot access" )
- @Test
- public void testSingleIdentifierReference() {
- variables.assign( context, new Key( "foo" ), "test" );
- instance.executeSource(
- """
- foo;
- """,
- context );
- }
-
- @DisplayName( "Multi identifier dot access" )
- @Test
- public void testmultiIdentifierReference() {
- IStruct s = new Struct();
- s.assign( context, new Key( "bar" ), "test" );
- variables.assign( context, new Key( "foo" ), s );
- instance.executeSource(
- """
- foo.bar;
- """,
- context );
- }
-
- @DisplayName( "Multi multi identifier dot access" )
- @Test
- public void testmultimultiIdentifierReference() {
- IStruct x = new Struct();
- x.assign( context, new Key( "baz" ), "test" );
- IStruct s = new Struct();
- s.assign( context, new Key( "bar" ), x );
- variables.assign( context, new Key( "foo" ), s );
- instance.executeSource(
- """
- foo.bar.baz;
- """,
- context );
- }
-
- @DisplayName( "integer dot access" )
- @Test
- public void testIntegerDotAccess() {
- instance.executeSource(
- """
- myArr = [ 1,2,3];
- result = myArr.1;
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 1 );
- }
-
- @DisplayName( "Bracket string access" )
- @Test
- public void testBracketStringAccess() {
- IStruct s = new Struct();
- s.assign( context, new Key( "bar" ), "test" );
- variables.assign( context, new Key( "foo" ), s );
- instance.executeSource(
- """
- foo["bar"];
- """,
- context );
- }
-
- @DisplayName( "Bracket string concat access" )
- @Test
- public void testBracketStringConcatAccess() {
- IStruct s = new Struct();
- s.assign( context, new Key( "bar" ), "test" );
- variables.assign( context, new Key( "foo" ), s );
- instance.executeSource(
- """
- foo["b" & "ar"]
- """,
- context );
- }
-
- @DisplayName( "Bracket number access" )
- @Test
- public void testBracketNumberAccess() {
- IStruct s = new Struct();
- s.assign( context, new Key( "7" ), "test" );
- variables.assign( context, new Key( "foo" ), s );
- instance.executeSource(
- """
- foo[ 7 ]
- """,
- context );
- }
-
- @DisplayName( "Bracket number expression access" )
- @Test
- public void testBracketNumberExpressionAccess() {
- IStruct s = new Struct();
- s.assign( context, new Key( "12" ), "test" );
- variables.assign( context, new Key( "foo" ), s );
- instance.executeSource(
- """
- foo[ 7 + 5 ]
- """,
- context );
- }
-
- @DisplayName( "Bracket object access" )
- @Test
- public void testBracketObjectExpressionAccess() {
- IStruct x = new Struct();
- x.assign( context, new Key( "bar" ), "baz" );
- IStruct s = new Struct();
- s.assign( context, new Key( "12" ), "test" );
- s.assign( context, Key.of( x ), "test" );
- variables.assign( context, new Key( "foo" ), s );
- instance.executeSource(
- """
- foo[ { bar : "baz" } ];
- """,
- context );
- }
-
- @DisplayName( "Mixed access" )
- @Test
- public void testBracketMixedAccess() {
- IStruct aaa = new Struct();
- IStruct twelve = new Struct();
- IStruct other = new Struct();
- IStruct foo = new Struct();
-
- foo.assign( context, new Key( "aaa" ), aaa );
- aaa.assign( context, Key.of( 12 ), twelve );
- twelve.assign( context, Key.of( "other" ), other );
- other.assign( context, Key.of( 7 ), "test" );
-
- variables.assign( context, new Key( "foo" ), foo );
- instance.executeSource(
- """
- foo[ "a" & "aa" ][ 12 ].other[ 2 + 5 ];
- """,
- context );
- }
-
- @DisplayName( "dereference enum key" )
- @Test
- public void testDereferenceEnumKey() {
- instance.executeSource(
- """
- import ortus.boxlang.runtime.types.BoxLangType;
- result = BoxLangType.LIST.getKey().getName();
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "list" );
- }
-
- @DisplayName( "dereference enum as nested class" )
- @Test
- public void testDereferenceEnumAsNestedClass() {
- instance.executeSource(
- """
- import ortus.boxlang.runtime.types.Struct as jStruct;
- import ortus.boxlang.runtime.types.IStruct;
- struct = new jStruct( IStruct.TYPES.CASE_SENSITIVE );
- """,
- context );
- }
-
- @DisplayName( "dereference nested class" )
- @Test
- public void testDereferenceNestedClass() {
- instance.executeSource(
- """
- import java.util.Map
- result = Map.Entry;
- """,
- context );
-
- assertThat( variables.get( result ) ).isEqualTo( Map.Entry.class );
-
- instance.executeSource(
- """
- import java.util.Map$Entry;
- result = Entry;
- """,
- context );
-
- assertThat( DynamicObject.unWrap( variables.get( result ) ) ).isEqualTo( Map.Entry.class );
- }
-
-}
diff --git a/src/test/java/TestCases/asm/phase1/LabeledLoopTest.java b/src/test/java/TestCases/asm/phase1/LabeledLoopTest.java
deleted file mode 100644
index 0adf7aacd..000000000
--- a/src/test/java/TestCases/asm/phase1/LabeledLoopTest.java
+++ /dev/null
@@ -1,261 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.phase1;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.compiler.parser.BoxSourceType;
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-
-public class LabeledLoopTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @Test
- public void testSimpleLabeledWhile() {
-
- instance.executeSource(
- """
- result = 0
- mylabel : while( true ) {
- result ++
- break mylabel;
- result ++
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 1 );
- }
-
- @Test
- public void testSimpleLabeledWhileContinue() {
-
- instance.executeSource(
- """
- result = 0
- mylabel : while( true ) {
- result ++
- if( result > 2 ) break;
- continue mylabel;
- result ++
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 3 );
- }
-
- @Test
- public void testSimpleLabeledWhileTag() {
-
- instance.executeSource(
- """
-
-
-
-
-
-
- """,
- context, BoxSourceType.BOXTEMPLATE );
- assertThat( variables.get( result ) ).isEqualTo( 1 );
- }
-
- @Test
- public void testSimpleLabeledWhileContinueTag() {
-
- instance.executeSource(
- """
-
-
-
-
-
-
-
-
-
- """,
- context, BoxSourceType.BOXTEMPLATE );
- assertThat( variables.get( result ) ).isEqualTo( 3 );
- }
-
- @Test
- public void testSimpleLabeledDoWhile() {
-
- instance.executeSource(
- """
- result = 0
- mylabel : do {
- result ++
- break mylabel;
- result ++
- } while( true )
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 1 );
- }
-
- @Test
- public void testSimpleLabeledForIn() {
-
- instance.executeSource(
- """
- data = [1,2,3]
- result = 0
- mylabel : for( x in data ) {
- result ++
- break mylabel;
- result ++
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 1 );
- }
-
- @Test
- public void testSimpleLabeledForIndex() {
-
- instance.executeSource(
- """
- result = 0
- mylabel : for( ; ; ) {
- result ++
- break mylabel;
- result ++
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 1 );
- }
-
- @Test
- public void testSimpleLabeledLoop() {
-
- instance.executeSource(
- """
- result = 0
- loop condition="true" label="mylabel" {
- result ++
- break mylabel;
- result ++
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 1 );
- }
-
- @Test
- @Disabled
- public void testSwitchInLabeledWhile() {
-
- instance.executeSource(
- """
- result = 0
- mylabel : while( true ) {
- result ++
- switch( result ) {
- case 1:
- break;
- case 2:
- break mylabel;
- case 3:
- break;
- }
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 2 );
- }
-
- @Test
- @Disabled
- public void testNestedLabeledWhiles() {
-
- instance.executeSource(
- """
- result = 0
- outer : while( true ) {
- result ++
- inner : while( true ) {
- result ++
- break outer;
- result ++
- }
- }
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 2 );
- }
-
- @Test
- @Disabled
- public void testTagLoop() {
-
- instance.executeSource(
- """
-
- #i#
-
-
-
-
- #i#->#i#
-
-
- """,
- context, BoxSourceType.CFTEMPLATE );
- }
-
-}
diff --git a/src/test/java/TestCases/asm/phase1/ObjectCreationTest.java b/src/test/java/TestCases/asm/phase1/ObjectCreationTest.java
deleted file mode 100644
index 4a4266ba6..000000000
--- a/src/test/java/TestCases/asm/phase1/ObjectCreationTest.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.phase1;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.interop.DynamicObject;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-
-public class ObjectCreationTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key resultKey = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "new keyword prefix" )
- @Test
- public void testNewKeywordPrefix() {
- Object result = instance.executeStatement( "new java:java.lang.String( 'My String' )", context );
- assertThat( result instanceof DynamicObject ).isEqualTo( true );
- assertThat( ( ( DynamicObject ) result ).getTargetInstance() ).isEqualTo( "My String" );
- }
-
- @DisplayName( "new keyword no prefix" )
- @Test
- public void testNewKeywordNoPrefix() {
- Object result = instance.executeStatement( "new java.lang.String( 'My String' )", context );
- assertThat( result instanceof DynamicObject ).isEqualTo( true );
- assertThat( ( ( DynamicObject ) result ).getTargetInstance() ).isEqualTo( "My String" );
- }
-
- @DisplayName( "new keyword no prefix2" )
- @Test
- public void testNewKeywordNoPrefix2() {
- Object result = instance.executeStatement( "new ortus.boxlang.runtime.types.Array()", context );
- assertThat( result instanceof DynamicObject ).isEqualTo( true );
- }
-
- @DisplayName( "new keyword quoted" )
- @Test
- public void testNewKeywordQuoted() {
- Object result = instance.executeStatement( "new 'java:java.lang.String'( 'My String' );", context );
- assertThat( result instanceof DynamicObject ).isEqualTo( true );
- assertThat( ( ( DynamicObject ) result ).getTargetInstance() ).isEqualTo( "My String" );
-
- instance.executeSource(
- """
- classNameToCreate = 'java:java.lang.String';
- result = new "#classNameToCreate#"( 'My String' );
- """,
- context );
- assertThat( variables.get( resultKey ) instanceof DynamicObject ).isEqualTo( true );
- assertThat( ( ( DynamicObject ) result ).getTargetInstance() ).isEqualTo( "My String" );
-
- }
- /*
- * @DisplayName( "create keyword prefix" )
- *
- * @Test
- * public void testCreateKeywordPrefix() {
- * Object result = instance.executeStatement( "create java:java.lang.System", context );
- * assertThat( result instanceof DynamicObject ).isEqualTo( true );
- * assertThat( ( ( DynamicObject ) result ).getTargetClass().getName() ).isEqualTo( "java.lang.System" );
- * }
- *
- * @DisplayName( "create keyword no prefix" )
- *
- * @Test
- * public void testCreateKeywordNoPrefix() {
- * Object result = instance.executeStatement( "create java.lang.System", context );
- * assertThat( result instanceof DynamicObject ).isEqualTo( true );
- * assertThat( ( ( DynamicObject ) result ).getTargetClass().getName() ).isEqualTo( "java.lang.System" );
- * }
- *
- * @DisplayName( "create keyword quoted" )
- *
- * @Test
- * public void testCreateKeywordQuoted() {
- * Object result = instance.executeStatement( "create 'java:java.lang.System';", context );
- * assertThat( result instanceof DynamicObject ).isEqualTo( true );
- * assertThat( ( ( DynamicObject ) result ).getTargetClass().getName() ).isEqualTo( "java.lang.System" );
- *
- * instance.executeSource(
- * """
- * classNameToCreate = 'java:java.lang.System';
- * result = create "#classNameToCreate#";
- * """,
- * context );
- * assertThat( variables.get( resultKey ) instanceof DynamicObject ).isEqualTo( true );
- * assertThat( ( ( DynamicObject ) variables.get( resultKey ) ).getTargetClass().getName() ).isEqualTo( "java.lang.System" );
- * }
- *
- * @DisplayName( "create keyword static method call one-liner" )
- *
- * @Test
- * public void testCreateKeywordstaticMethodCallOneLiner() {
- * instance.executeStatement( "(create java.lang.System).out.println( 2+3 )", context );
- * instance.executeSource(
- * """
- * (create java.lang.System).out.println( 2+3 )
- * """,
- * context );
- *
- * }
- */
-
- @DisplayName( "imports prefix" )
- @Test
- public void testImportsPrefix() {
- instance.executeSource(
- """
- import java:java.lang.String;
- result = new java:String( 'My String' );
- """,
- context );
-
- assertThat( variables.get( resultKey ) instanceof DynamicObject ).isEqualTo( true );
- assertThat( ( ( DynamicObject ) variables.get( resultKey ) ).getTargetInstance() ).isEqualTo( "My String" );
- }
-
- @DisplayName( "imports no prefix" )
- @Test
- public void testImportsNoPrefix() {
- instance.executeSource(
- """
- import java.lang.String;
- result = new String( 'My String' );
- """,
- context );
-
- assertThat( variables.get( resultKey ) instanceof DynamicObject ).isEqualTo( true );
- assertThat( ( ( DynamicObject ) variables.get( resultKey ) ).getTargetInstance() ).isEqualTo( "My String" );
- }
-
- @DisplayName( "imports as" )
- @Test
- public void testImportsAs() {
- instance.executeSource(
- """
- import java.lang.String as jString;
- result = new jString( 'My String' );
- """,
- context );
-
- assertThat( variables.get( resultKey ) instanceof DynamicObject ).isEqualTo( true );
- assertThat( ( ( DynamicObject ) variables.get( resultKey ) ).getTargetInstance() ).isEqualTo( "My String" );
-
- }
-
-}
diff --git a/src/test/java/TestCases/asm/phase1/ObjectReferenceAssignmentTest.java b/src/test/java/TestCases/asm/phase1/ObjectReferenceAssignmentTest.java
deleted file mode 100644
index 336307727..000000000
--- a/src/test/java/TestCases/asm/phase1/ObjectReferenceAssignmentTest.java
+++ /dev/null
@@ -1,396 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.phase1;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-import java.util.Map;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.FunctionBoxContext;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.LocalScope;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-import ortus.boxlang.runtime.types.Argument;
-import ortus.boxlang.runtime.types.Function.Access;
-import ortus.boxlang.runtime.types.IStruct;
-import ortus.boxlang.runtime.types.SampleUDF;
-import ortus.boxlang.runtime.types.exceptions.BoxLangException;
-
-public class ObjectReferenceAssignmentTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "scope assignment" )
- @Test
- public void testScopeAssignment() {
- instance.executeSource(
- """
- variables.result = "brad";
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "brad" );
-
- instance.executeSource(
- """
- keyName = "result";
- variables[keyName] = "wood";
-
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "wood" );
-
- instance.executeSource(
- """
- variables['result'] = "luis";
-
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "luis" );
-
- }
-
- @DisplayName( "unscoped assignment" )
- @Test
- public void testUnscopedAssignment() {
- instance.executeSource(
- """
- result = "brad";
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "brad" );
-
- }
-
- @DisplayName( "invaid assignment" )
- @Test
- public void testInvalidAssignment() {
-
- // These are invalid because they are trying to assign directly to an expression that can't be assigned
- assertThrows( BoxLangException.class, () -> instance.executeSource(
- """
- foo() = "brad";
- """,
- context ) );
-
- assertThrows( BoxLangException.class, () -> instance.executeSource(
- """
- obj.foo() = "brad";
- """,
- context ) );
-
- // These are all a BoxAccess, but the "var" keyword can only come before an INITIAL identifier or BoxAccess
- assertThrows( BoxLangException.class, () -> instance.executeSource(
- """
- var foo().key = "brad";
- """,
- context ) );
-
- assertThrows( BoxLangException.class, () -> instance.executeSource(
- """
- var obj.foo().key = "brad";
- """,
- context ) );
-
- assertThrows( BoxLangException.class, () -> instance.executeSource(
- """
- var "foo".key = "brad";
- """,
- context ) );
-
- }
-
- @DisplayName( "dereference scope key" )
- @Test
- public void testDereferenceScopeKey() {
- instance.executeSource(
- """
- variables.foo = "luis";
- result = variables.foo;
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "luis" );
-
- instance.executeSource(
- """
- variables.foo = "gavin";
- result = variables['foo'];
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "gavin" );
-
- }
-
- @DisplayName( "dereference key" )
- @Test
- public void testDereferenceKey() {
- instance.executeSource(
- """
- import java:ortus.boxlang.runtime.scopes.Key;
- str = new java:ortus.boxlang.runtime.types.Struct();
- str.assign( GetBoxContext(), Key.of("name"), "Brad" );
- result = str.name;
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( "Brad" );
-
- }
-
- @DisplayName( "dereference headless" )
- @Test
- public void testDereferenceHeadless() {
- instance.executeSource(
- """
- variables.foo = 5;
- result = foo;
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( 5 );
-
- }
-
- @DisplayName( "dereference invoke key" )
- @Test
- public void testDereferenceInvokeKey() {
- instance.executeSource(
- """
- ctx = new java:ortus.boxlang.runtime.context.ScriptingRequestBoxContext();
- result = variables.ctx.getDefaultAssignmentScope()
- """,
- context );
- assertThat( variables.get( result ) instanceof IScope ).isTrue();
-
- }
-
- @DisplayName( "dereference invoke headless" )
- @Test
- public void testDereferenceInvokeHeadless() {
- instance.executeSource(
- """
- ctx = new java:ortus.boxlang.runtime.context.ScriptingRequestBoxContext();
- result = ctx.getDefaultAssignmentScope()
- """,
- context );
- assertThat( variables.get( result ) instanceof IScope ).isTrue();
- }
-
- @DisplayName( "safe navigation" )
- @Test
- public void testSafeNavigation() {
- instance.executeSource(
- """
- result = variables?.foo?.bar?.baz;
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( null );
-
- Object theResult = instance.executeStatement( "variables?.foo?.bar?.baz", context );
- assertThat( theResult ).isEqualTo( null );
-
- }
-
- @DisplayName( "var keyword for local" )
- @Test
- public void testVarKeywordForLocal() {
- FunctionBoxContext functionBoxContext = new FunctionBoxContext( context,
- new SampleUDF( Access.PUBLIC, Key.of( "func" ), "any", new Argument[] {}, "" ) );
- instance.executeSource(
- """
- var foo = 5;
- local.bar = 6;
- println(local.asString())
- """,
- functionBoxContext );
-
- IScope localScope = functionBoxContext.getScopeNearby( LocalScope.name );
- assertThat( localScope.get( Key.of( "foo" ) ) ).isEqualTo( 5 );
- assertThat( localScope.get( Key.of( "bar" ) ) ).isEqualTo( 6 );
-
- }
-
- @DisplayName( "var keyword for local Deep" )
- @Test
- public void testVarKeywordForLocalDeep() {
- FunctionBoxContext functionBoxContext = new FunctionBoxContext( context,
- new SampleUDF( Access.PUBLIC, Key.of( "func" ), "any", new Argument[] {}, "" ) );
- IScope localScope = functionBoxContext.getScopeNearby( LocalScope.name );
- instance.executeSource(
- """
- var foo.bar = 5;
- """,
- functionBoxContext );
- assertThat( localScope.get( Key.of( "foo" ) ) instanceof IStruct ).isTrue();
- IStruct foo = ( IStruct ) localScope.get( Key.of( "foo" ) );
- assertThat( foo.get( Key.of( "bar" ) ) ).isEqualTo( 5 );
-
- }
-
- @DisplayName( "var keyword for scope" )
- @Test
- public void testVarKeywordForLocalForScope() {
- FunctionBoxContext functionBoxContext = new FunctionBoxContext( context,
- new SampleUDF( Access.PUBLIC, Key.of( "func" ), "any", new Argument[] {}, "" ) );
- IScope localScope = functionBoxContext.getScopeNearby( LocalScope.name );
- instance.executeSource(
- """
- var variables = 5;
- """,
- functionBoxContext );
- assertThat( localScope.get( Key.of( "variables" ) ) ).isEqualTo( 5 );
-
- }
-
- @DisplayName( "var keyword for scope deep" )
- @Test
- public void testVarKeywordForLocalForScopeDeep() {
- FunctionBoxContext functionBoxContext = new FunctionBoxContext( context,
- new SampleUDF( Access.PUBLIC, Key.of( "func" ), "any", new Argument[] {}, "" ) );
- IScope localScope = functionBoxContext.getScopeNearby( LocalScope.name );
- instance.executeSource(
- """
- var variables.bar = 5;
- """,
- functionBoxContext );
- assertThat( localScope.get( Key.of( "variables" ) ) instanceof IStruct ).isTrue();
- IStruct variables = ( IStruct ) localScope.get( Key.of( "variables" ) );
- assertThat( variables.get( Key.of( "bar" ) ) ).isEqualTo( 5 );
-
- }
-
- @DisplayName( "deep assignment" )
- @Test
- public void testDeepAssignment() {
- instance.executeSource(
- """
- variables.foo.bar.baz="brad"
- """,
- context );
- assertThat( variables.containsKey( Key.of( "foo" ) ) ).isEqualTo( true );
- Object foo = variables.get( Key.of( "foo" ) );
- assertThat( foo instanceof Map ).isEqualTo( true );
- assertThat( ( ( Map ) foo ).containsKey( Key.of( "bar" ) ) ).isEqualTo( true );
- Object bar = ( ( Map ) foo ).get( Key.of( "bar" ) );
- assertThat( bar instanceof Map ).isEqualTo( true );
- Object baz = ( ( Map ) bar ).get( Key.of( "baz" ) );
- assertThat( baz instanceof String ).isEqualTo( true );
- }
-
- @DisplayName( "assignment returns value" )
- @Test
- public void testAssignmentReturnsValue() {
- instance.executeSource(
- """
- foo = bar = brad = "wood"
- """,
- context );
-
- assertThat( variables.get( Key.of( "foo" ) ) ).isEqualTo( "wood" );
- assertThat( variables.get( Key.of( "bar" ) ) ).isEqualTo( "wood" );
- assertThat( variables.get( Key.of( "brad" ) ) ).isEqualTo( "wood" );
- }
-
- @DisplayName( "scoped assignment returns value" )
- @Test
- public void testScopedAssignmentReturnsValue() {
- instance.executeSource(
- """
- variables.foo2 = variables.bar2 = variables.brad2 = "wood2"
- """,
- context );
-
- assertThat( variables.get( Key.of( "foo2" ) ) ).isEqualTo( "wood2" );
- assertThat( variables.get( Key.of( "bar2" ) ) ).isEqualTo( "wood2" );
- assertThat( variables.get( Key.of( "brad2" ) ) ).isEqualTo( "wood2" );
- }
-
- @DisplayName( "call method on object" )
- @Test
- public void testCallMethodOnObject() {
- instance.executeSource(
- """
- system = createObject('java', 'java.lang.System');
- system.out.println("Hello World");
- system["out"]["println"]("Hello World");
- """,
- context );
-
- }
-
- @DisplayName( "static method call on imported class" )
- @Test
- public void testStaticMethodCallOnImportedClass() {
- instance.executeSource(
- """
- import java:java.lang.System;
-
- system.out.println( 2+3 )
- """,
- context );
-
- }
-
- @DisplayName( "null keyword" )
- @Test
- public void testNullKeyword() {
- instance.executeSource(
- """
- nothing = null;
- result = nothing == null;
- """,
- context );
- assertThat( variables.get( result ) ).isEqualTo( true );
-
- }
-
-}
diff --git a/src/test/java/TestCases/asm/phase1/OperatorsTest.java b/src/test/java/TestCases/asm/phase1/OperatorsTest.java
deleted file mode 100644
index efbb97cbf..000000000
--- a/src/test/java/TestCases/asm/phase1/OperatorsTest.java
+++ /dev/null
@@ -1,967 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.phase1;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.compiler.parser.BoxSourceType;
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-import ortus.boxlang.runtime.types.exceptions.ExpressionException;
-import ortus.boxlang.runtime.types.exceptions.KeyNotFoundException;
-
-public class OperatorsTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key resultKey = new Key( "result" );
- static Key tmpKey = new Key( "tmp" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "string concat" )
- @Test
- public void testStringConcat() {
- Object result = instance.executeStatement( "'brad' & 'wood'", context );
- assertThat( result ).isEqualTo( "bradwood" );
- }
-
- @DisplayName( "multi string concat" )
- @Test
- public void testMutliStringConcat() {
- Object result = instance.executeStatement( "'foo' & 'bar' & 'baz' & 'bum'", context );
- assertThat( result ).isEqualTo( "foobarbazbum" );
- }
-
- @DisplayName( "concat and eq" )
- @Test
- public void testConcatAndEQ() {
- Object result = instance.executeStatement( "'$' & 'foo' == '$foo'", context );
- assertThat( result ).isEqualTo( true );
- }
-
- @DisplayName( "string contains" )
- @Test
- public void testStringContains() {
- Object result = instance.executeStatement( "\"Brad Wood\" contains \"Wood\"", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "\"Brad Wood\" contains \"luis\"", context );
- assertThat( result ).isEqualTo( false );
-
- result = instance.executeStatement( "\"Brad Wood\" DOES NOT CONTAIN \"Luis\"", context );
- assertThat( result ).isEqualTo( true );
- }
-
- @DisplayName( "math addition" )
- @Test
- public void testMathAddition() {
- Object result = instance.executeStatement( "+5", context );
- assertThat( result ).isEqualTo( 5 );
-
- result = instance.executeStatement( "5+5", context );
- assertThat( result ).isEqualTo( 10 );
-
- result = instance.executeStatement( "'5'+'2'", context );
- assertThat( result ).isEqualTo( 7 );
- }
-
- @DisplayName( "math subtraction" )
- @Test
- public void testMathSubtraction() {
- Object result = instance.executeStatement( "6-5", context );
- assertThat( result ).isEqualTo( 1 );
- }
-
- @DisplayName( "math negation" )
- @Test
- public void testMathNegation() {
- Object result = instance.executeStatement( "-5", context );
- assertThat( result ).isEqualTo( -5 );
-
- result = instance.executeStatement( "-(5+5)", context );
- assertThat( result ).isEqualTo( -10 );
-
- result = instance.executeStatement( "-5+5", context );
- assertThat( result ).isEqualTo( 0 );
- }
-
- @DisplayName( "math addition var" )
- @Test
- public void testMathAdditionVar() {
- Object result = instance.executeStatement( "foo=5; +foo", context );
- assertThat( result ).isEqualTo( 5 );
- }
-
- @DisplayName( "math negation var" )
- @Test
- public void testMathNegationVar() {
- Object result = instance.executeStatement( "foo=5; -foo", context );
- assertThat( result ).isEqualTo( -5 );
- }
-
- @DisplayName( "math division" )
- @Test
- public void testMathDivision() {
- Number result = ( Number ) instance.executeStatement( "10/5", context );
- assertThat( result.doubleValue() ).isEqualTo( 2 );
- }
-
- @DisplayName( "math int divison" )
- @Test
- public void testMathIntDivision() {
- Number result = ( Number ) instance.executeStatement( "10\\3", context );
- assertThat( result.doubleValue() ).isEqualTo( 3 );
- }
-
- @DisplayName( "math multiplication" )
- @Test
- public void testMathMultiplication() {
- Number result = ( Number ) instance.executeStatement( "10*5", context );
- assertThat( result.doubleValue() ).isEqualTo( 50 );
- }
-
- @DisplayName( "math power" )
- @Test
- public void testMathPower() {
- Number result = ( Number ) instance.executeStatement( "2^3", context );
- assertThat( result.doubleValue() ).isEqualTo( 8 );
- }
-
- @DisplayName( "math plus plus literals" )
- @Test
- public void testMathPlusPlusLiterals() {
- Object result = instance.executeStatement( "5++", context );
- assertThat( result ).isEqualTo( 5 );
-
- result = instance.executeStatement( "++5", context );
- assertThat( result ).isEqualTo( 6 );
-
- result = instance.executeStatement( "result=5++", context );
- assertThat( result ).isEqualTo( 5 );
- assertThat( variables.get( resultKey ) ).isEqualTo( 5 );
-
- result = instance.executeStatement( "result=++5", context );
- assertThat( result ).isEqualTo( 6 );
- assertThat( variables.get( resultKey ) ).isEqualTo( 6 );
-
- }
-
- @DisplayName( "math plus plus parenthetical" )
- @Test
- public void testMathPlusPlusParenthetical() {
- Object result = instance.executeStatement( "(5)++", context );
- assertThat( result ).isEqualTo( 5 );
-
- result = instance.executeStatement( "++(5)", context );
- assertThat( result ).isEqualTo( 6 );
-
- result = instance.executeStatement( "result=(5)++", context );
- assertThat( result ).isEqualTo( 5 );
- assertThat( variables.get( resultKey ) ).isEqualTo( 5 );
-
- result = instance.executeStatement( "result=++(5)", context );
- assertThat( result ).isEqualTo( 6 );
- assertThat( variables.get( resultKey ) ).isEqualTo( 6 );
-
- instance.executeSource( """
- myvar = 5;
- result = ++(myvar);
- """, context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 6 );
- assertThat( variables.get( Key.of( "myvar" ) ) ).isEqualTo( 6 );
-
- instance.executeSource( """
- myvar = 5;
- result = (myvar)++;
- """, context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 5 );
- assertThat( variables.get( Key.of( "myvar" ) ) ).isEqualTo( 6 );
-
- }
-
- @DisplayName( "math plus plus other" )
- @Test
- public void testMathPlusPlusOther() {
-
- instance.executeSource( """
- function num() {
- return 5;
- }
- result = ++num();
- """, context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 6 );
-
- instance.executeSource( """
- function num() {
- return 5;
- }
- result = num()++;
- """, context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 5 );
-
- }
-
- @DisplayName( "math plus plus scoped" )
- @Test
- public void testMathPlusPlusScoped() {
- instance.executeSource(
- """
- tmp = 5;
- result = variables.tmp++;
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 5 );
- assertThat( variables.get( tmpKey ) ).isEqualTo( 6 );
-
- instance.executeSource(
- """
- tmp = 5;
- result = ++variables.tmp;
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 6 );
- assertThat( variables.get( tmpKey ) ).isEqualTo( 6 );
- }
-
- @DisplayName( "math plus plus invalid" )
- @Test
- public void testMathPlusPlusInvalid() {
-
- assertThrows( ExpressionException.class, () -> instance.executeSource( "variables++", context ) );
-
- }
-
- @DisplayName( "math plus plus unscoped" )
- @Test
- public void testMathPlusPlusUnScoped() {
- instance.executeSource(
- """
- tmp = 5;
- result = tmp++;
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 5 );
- assertThat( variables.get( tmpKey ) ).isEqualTo( 6 );
-
- instance.executeSource(
- """
- tmp = 5;
- result = ++tmp;
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 6 );
- assertThat( variables.get( tmpKey ) ).isEqualTo( 6 );
-
- instance.executeSource(
- """
- foo.bar.baz = 5;
- result = foo.bar.baz++;
- tmp = foo.bar.baz;
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 5 );
- assertThat( variables.get( tmpKey ) ).isEqualTo( 6 );
-
- instance.executeSource(
- """
- foo.bar.baz = 5;
- result = ++foo.bar.baz;
- tmp = foo.bar.baz;
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 6 );
- assertThat( variables.get( tmpKey ) ).isEqualTo( 6 );
- }
-
- @DisplayName( "math minus minus literals" )
- @Test
- public void testMathMinusMinusLiterals() {
- Object result = instance.executeStatement( "5--", context );
- assertThat( result ).isEqualTo( 5 );
-
- result = instance.executeStatement( "--5", context );
- assertThat( result ).isEqualTo( 4 );
-
- result = instance.executeStatement( "result=5--", context );
- assertThat( result ).isEqualTo( 5 );
- assertThat( variables.get( resultKey ) ).isEqualTo( 5 );
-
- result = instance.executeStatement( "result=--5", context );
- assertThat( result ).isEqualTo( 4 );
- assertThat( variables.get( resultKey ) ).isEqualTo( 4 );
-
- }
-
- @DisplayName( "math minus minus parenthetical" )
- @Test
- public void testMathMinusMinusParenthetical() {
- Object result = instance.executeStatement( "(5)--", context );
- assertThat( result ).isEqualTo( 5 );
-
- result = instance.executeStatement( "--(5)", context );
- assertThat( result ).isEqualTo( 4 );
-
- result = instance.executeStatement( "result=(5)--", context );
- assertThat( result ).isEqualTo( 5 );
- assertThat( variables.get( resultKey ) ).isEqualTo( 5 );
-
- result = instance.executeStatement( "result=--(5)", context );
- assertThat( result ).isEqualTo( 4 );
- assertThat( variables.get( resultKey ) ).isEqualTo( 4 );
-
- instance.executeSource( """
- myvar = 5;
- result = --(myvar);
- """, context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 4 );
- assertThat( variables.get( Key.of( "myvar" ) ) ).isEqualTo( 4 );
-
- instance.executeSource( """
- myvar = 5;
- result = (myvar)--;
- """, context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 5 );
- assertThat( variables.get( Key.of( "myvar" ) ) ).isEqualTo( 4 );
-
- }
-
- @DisplayName( "math minus minus scoped" )
- @Test
- public void testMathMinusMinusScoped() {
- instance.executeSource(
- """
- tmp = 5;
- result = variables.tmp--;
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 5 );
- assertThat( variables.get( tmpKey ) ).isEqualTo( 4 );
-
- instance.executeSource(
- """
- tmp = 5;
- result = --variables.tmp;
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 4 );
- assertThat( variables.get( tmpKey ) ).isEqualTo( 4 );
- }
-
- @DisplayName( "math minus minus unscoped" )
- @Test
- public void testMathMinusMinusUnScoped() {
- instance.executeSource(
- """
- tmp = 5;
- result = tmp--;
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 5 );
- assertThat( variables.get( tmpKey ) ).isEqualTo( 4 );
-
- instance.executeSource(
- """
- tmp = 5;
- result = --tmp;
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 4 );
- assertThat( variables.get( tmpKey ) ).isEqualTo( 4 );
-
- instance.executeSource(
- """
- foo.bar.baz = 5;
- result = foo.bar.baz--;
- tmp = foo.bar.baz;
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 5 );
- assertThat( variables.get( tmpKey ) ).isEqualTo( 4 );
-
- instance.executeSource(
- """
- foo.bar.baz= 5;
- result = --foo.bar.baz;
- tmp = foo.bar.baz;
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 4 );
- assertThat( variables.get( tmpKey ) ).isEqualTo( 4 );
- }
-
- @DisplayName( "compound operator plus" )
- @Test
- public void compoundOperatorPlus() {
- instance.executeSource(
- """
- result = 5;
- result += 5;
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 10 );
-
- instance.executeSource(
- """
- function foo(){
- local.result = 5;
- local.result += 5;
- return result;
- }
- result = foo();
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 10 );
-
- instance.executeSource(
- """
- result = 5;
- variables.result += 5;
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 10 );
- }
-
- @DisplayName( "compound operators minus" )
- @Test
- public void compoundOperatorMinus() {
- instance.executeSource(
- """
- result = 5;
- result -= 4;
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( 1 );
- }
-
- @DisplayName( "compound operator multiply" )
- @Test
- public void compoundOperatorMultiply() {
- instance.executeSource(
- """
- result = 5;
- result *= 5;
- """,
- context );
- assertThat( variables.getAsNumber( resultKey ).doubleValue() ).isEqualTo( 25 );
- }
-
- @DisplayName( "compound operator divide" )
- @Test
- public void compoundOperatorDivide() {
- instance.executeSource(
- """
- result = 20;
- result /= 5;
- """,
- context );
- assertThat( variables.getAsNumber( resultKey ).doubleValue() ).isEqualTo( 4 );
- }
-
- @DisplayName( "compound operator modulus" )
- @Test
- public void compoundOperatorModulus() {
- instance.executeSource(
- """
- result = 5;
- result %= 4;
- """,
- context );
- assertThat( variables.getAsNumber( resultKey ).doubleValue() ).isEqualTo( 1 );
- }
-
- @DisplayName( "modulus precedence" )
- @Test
- public void modulusPrecedence() {
- instance.executeSource(
- """
- result = 1 + 1 mod 2;
- result2 = 1 + 1 % 2;
- """,
- context );
- assertThat( variables.getAsNumber( resultKey ).doubleValue() ).isEqualTo( 2 );
- assertThat( variables.getAsNumber( Key.of( "result2" ) ).doubleValue() ).isEqualTo( 2 );
- }
-
- @DisplayName( "compound operator concat" )
- @Test
- public void compoundOperatorConcat() {
- instance.executeSource(
- """
- result = "brad";
- result &= "wood";
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( "bradwood" );
- }
-
- @DisplayName( "compound operator with var" )
- @Test
- public void compoundOperatorWithVar() {
- /*
- * I personally think this should be invalid code, but Adobe and Lucee both allow it. Adobe turns all access to the variable into the local scope
- * somehow, presumably some sort of variable hoisting. Lucee just straight up ignores the "var" keyword and modifies the variable in whatever scope
- * it's already in. I've chosen Lucee's behavior for now because it's the least amount of work and this is an edge case.
- */
- instance.executeSource(
- """
- result = "brad";
- var result &= "wood";
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( "bradwood" );
- }
-
- @DisplayName( "logical and" )
- @Test
- public void testLogicalAnd() {
- Object result = instance.executeStatement( "true and true", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "true && true", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "true and false", context );
- assertThat( result ).isEqualTo( false );
-
- result = instance.executeStatement( "true && false", context );
- assertThat( result ).isEqualTo( false );
- }
-
- @DisplayName( "logical or" )
- @Test
- public void testLogicalOr() {
- Object result = instance.executeStatement( "true or true", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "true || true", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "true or false", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "true || false", context );
- assertThat( result ).isEqualTo( true );
- }
-
- @DisplayName( "logical not" )
- @Test
- public void testLogicalNot() {
- Object result = instance.executeStatement( "!true", context );
- assertThat( result ).isEqualTo( false );
-
- result = instance.executeStatement( "!false", context );
- assertThat( result ).isEqualTo( true );
- }
-
- @DisplayName( "logical xor" )
- @Test
- public void testLogicalXOR() {
- Object result = instance.executeStatement( "true xor false", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "true xor true", context );
- assertThat( result ).isEqualTo( false );
-
- result = instance.executeStatement( "false xor false", context );
- assertThat( result ).isEqualTo( false );
- }
-
- @DisplayName( "elvis" )
- @Test
- public void testElvis() {
-
- instance.executeSource(
- """
- tmp = "brad"
- result = tmp ?: 'default'
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( "brad" );
-
- Object result = instance.executeStatement( "null ?: 'default'", context );
- assertThat( result ).isEqualTo( "default" );
-
- result = instance.executeStatement( "foo ?: 'default'", context );
- assertThat( result ).isEqualTo( "default" );
-
- result = instance.executeStatement( "foo.bar ?: 'default'", context );
- assertThat( result ).isEqualTo( "default" );
-
- result = instance.executeStatement( "foo['bar'] ?: 'default'", context );
- assertThat( result ).isEqualTo( "default" );
-
- result = instance.executeStatement( "foo['bar'].baz ?: 'default'", context );
- assertThat( result ).isEqualTo( "default" );
-
- result = instance.executeStatement( "foo.bar() ?: 'default'", context );
- assertThat( result ).isEqualTo( "default" );
-
- }
-
- @DisplayName( "ternary" )
- @Test
- public void testTernary() {
-
- Object result = instance.executeStatement( "true ? 'itwastrue' : 'itwasfalse'", context );
- assertThat( result ).isEqualTo( "itwastrue" );
-
- result = instance.executeStatement( "FALSE ? 'itwastrue' : 'itwasfalse'", context );
- assertThat( result ).isEqualTo( "itwasfalse" );
-
- instance.executeSource(
- """
- tmp = true;
- result = tmp ? 'itwastrue' : 'itwasfalse'
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( "itwastrue" );
-
- }
-
- @DisplayName( "It should lazily evaluate its true branche" )
- @Test
- public void testTernaryTrueLazyEvaluation() {
-
- Object result = instance.executeStatement( """
- "false" castas "boolean" ? "a" castas "boolean" : "0" castas "boolean";
- """, context );
- assertThat( result ).isEqualTo( false );
- }
-
- @DisplayName( "It should lazily evaluate its false branche" )
- @Test
- public void testTernaryFalseLazyEvaluation() {
-
- Object result = instance.executeStatement( """
- "true" castas "boolean" ? "false" castas "boolean" : "x" castas "boolean";
- """, context );
- assertThat( result ).isEqualTo( false );
- }
-
- @DisplayName( "It should properly handle comparison operators" )
- @Test
- public void testTernaryWithComparison() {
-
- Object result = instance.executeStatement( "4 < 5 ? 'itwastrue' : 'itwasfalse'", context );
- assertThat( result ).isEqualTo( "itwastrue" );
-
- result = instance.executeStatement( "4 > 5 ? 'itwastrue' : 'itwasfalse'", context );
- assertThat( result ).isEqualTo( "itwasfalse" );
-
- instance.executeSource(
- """
- tmp = true;
- result = tmp == true ? 'itwastrue' : 'itwasfalse'
- """,
- context );
- assertThat( variables.get( resultKey ) ).isEqualTo( "itwastrue" );
-
- }
-
- @DisplayName( "instanceOf" )
- @Test
- public void testInstanceOf() {
-
- Object result = instance.executeStatement( "true instanceOf 'Boolean'", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "'brad' instanceOf 'java.lang.String'", context );
- assertThat( result ).isEqualTo( true );
-
- }
-
- @DisplayName( "castAs" )
- @Test
- public void testCastAs() {
- assertThrows( KeyNotFoundException.class, () -> instance.executeStatement( "5 castAs sdf", context ) );
-
- Object result = instance.executeStatement( "5 castAs 'String'", context );
- assertThat( result ).isEqualTo( "5" );
- assertThat( result.getClass().getName() ).isEqualTo( "java.lang.String" );
- }
-
- @DisplayName( "assert" )
- @Test
- public void testAssert() {
-
- instance.executeStatement( "assert true", context );
- instance.executeStatement( "assert true;", context );
-
- instance.executeStatement( "assert 5==5", context );
- instance.executeStatement( "assert 5==5;", context );
-
- assertThrows( AssertionError.class, () -> instance.executeStatement( "assert 5==6", context ) );
- assertThrows( AssertionError.class, () -> instance.executeStatement( "assert false", context ) );
-
- }
-
- @DisplayName( "comparison equality" )
- @Test
- public void testComparisonEquality() {
-
- Object result = instance.executeStatement( "5==5", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "'5'==5", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "'brad'=='brad'", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "'brad'==5", context );
- assertThat( result ).isEqualTo( false );
-
- }
-
- @DisplayName( "comparison strict equality" )
- @Test
- public void testComparisonStrictEquality() {
-
- Object result = instance.executeStatement( "5===5", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "'5'===5", context );
- assertThat( result ).isEqualTo( false );
-
- result = instance.executeStatement( "'brad'==='brad'", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "'brad'===5", context );
- assertThat( result ).isEqualTo( false );
-
- }
-
- @DisplayName( "comparison greater than" )
- @Test
- public void testGreaterThan() {
-
- Object result = instance.executeStatement( "6 > 5", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "6 GREATER THAN 5", context );
-
- result = instance.executeStatement( "'B' > 'A'", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "'B' greater than 'A'", context );
- assertThat( result ).isEqualTo( true );
- }
-
- @DisplayName( "comparison greater than equal" )
- @Test
- public void testGreaterThanEqual() {
-
- Object result = instance.executeStatement( "10 >= 5", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "10 GTE 5", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "10 GREATER THAN OR EQUAL TO 5", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "10 GE 5", context );
- assertThat( result ).isEqualTo( true );
- }
-
- @DisplayName( "comparison less than" )
- @Test
- public void testLessThan() {
-
- Object result = instance.executeStatement( "5 < 10", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "5 LT 10", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "5 LESS THAN 10", context );
- assertThat( result ).isEqualTo( true );
-
- }
-
- @DisplayName( "comparison less than equal" )
- @Test
- public void testLessThanEqual() {
-
- Object result = instance.executeStatement( "5 <= 10", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "5 LTE 10", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "5 LESS THAN OR EQUAL TO 10", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "5 LE 10", context );
- assertThat( result ).isEqualTo( true );
-
- }
-
- @DisplayName( "parens" )
- @Test
- public void testParens() {
-
- Number result = ( Number ) instance.executeStatement( "1 + ( 2 * 3 )", context );
- assertThat( result.doubleValue() ).isEqualTo( 7 );
-
- result = ( Number ) instance.executeStatement( "( 1 + 2 ) * 3", context );
- assertThat( result.doubleValue() ).isEqualTo( 9 );
-
- result = ( Number ) instance.executeStatement( "( 1 + 2 * 3 )", context );
- assertThat( result.doubleValue() ).isEqualTo( 7 );
-
- }
-
- @DisplayName( "Order of operations" )
- @Test
- public void testOrderOfOps() {
-
- Number result = ( Number ) instance.executeStatement( "1+2-3*4^5", context );
- assertThat( result.doubleValue() ).isEqualTo( -3069 );
-
- result = ( Number ) instance.executeStatement( "2+3*4", context );
- assertThat( result.doubleValue() ).isEqualTo( 14 );
-
- result = ( Number ) instance.executeStatement( "2-3+4", context );
- assertThat( result.doubleValue() ).isEqualTo( 3 );
-
- result = ( Number ) instance.executeStatement( "2+3/4", context );
- assertThat( result.doubleValue() ).isEqualTo( 2.75 );
-
- result = ( Number ) instance.executeStatement( "2-3/4", context );
- assertThat( result.doubleValue() ).isEqualTo( 1.25 );
-
- result = ( Number ) instance.executeStatement( "2*2%3", context );
- assertThat( result.doubleValue() ).isEqualTo( 1 );
-
- result = ( Number ) instance.executeStatement( "++5^--6", context );
- assertThat( result.doubleValue() ).isEqualTo( 7776 );
-
- }
-
- @DisplayName( "It should handle equivalence" )
- @Test
- public void testEQVOperator() {
-
- Object result = instance.executeStatement( "true EQV true", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "false EQV false", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "false EQV true", context );
- assertThat( result ).isEqualTo( false );
-
- result = instance.executeStatement( "true EQV false", context );
- assertThat( result ).isEqualTo( false );
-
- result = instance.executeStatement( "1 EQV 0", context );
- assertThat( result ).isEqualTo( false );
-
- }
-
- @DisplayName( "It should handle the implies operator" )
- @Test
- public void testIMPOperator() {
-
- Object result = instance.executeStatement( "true IMP false", context );
- assertThat( result ).isEqualTo( false );
-
- result = instance.executeStatement( "false IMP false", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "false IMP true", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "true IMP true", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "1 IMP 0", context );
- assertThat( result ).isEqualTo( false );
-
- }
-
- @DisplayName( "comparison strict not equality" )
- @Test
- public void testComparisonStrictNotEquality() {
-
- Object result = instance.executeStatement( "5!==5", context );
- assertThat( result ).isEqualTo( false );
-
- result = instance.executeStatement( "'5'!==5", context );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "'brad'!=='brad'", context );
- assertThat( result ).isEqualTo( false );
-
- result = instance.executeStatement( "'brad'!==5", context );
- assertThat( result ).isEqualTo( true );
- }
-
- @DisplayName( "comparison strict not equality CF" )
- @Test
- public void testComparisonStrictNotEqualityCF() {
-
- Object result = instance.executeStatement( "5!==5", context, BoxSourceType.CFSCRIPT );
- assertThat( result ).isEqualTo( false );
-
- result = instance.executeStatement( "'5'!==5", context, BoxSourceType.CFSCRIPT );
- assertThat( result ).isEqualTo( true );
-
- result = instance.executeStatement( "'brad'!=='brad'", context, BoxSourceType.CFSCRIPT );
- assertThat( result ).isEqualTo( false );
-
- result = instance.executeStatement( "'brad'!==5", context, BoxSourceType.CFSCRIPT );
- assertThat( result ).isEqualTo( true );
- }
-
-}
diff --git a/src/test/java/TestCases/asm/phase1/unicode.cfm b/src/test/java/TestCases/asm/phase1/unicode.cfm
deleted file mode 100644
index 908462cfb..000000000
--- a/src/test/java/TestCases/asm/phase1/unicode.cfm
+++ /dev/null
@@ -1,2 +0,0 @@
-
-kōwhai
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/AbstractClass.bx b/src/test/java/TestCases/asm/phase3/AbstractClass.bx
deleted file mode 100644
index af9af4554..000000000
--- a/src/test/java/TestCases/asm/phase3/AbstractClass.bx
+++ /dev/null
@@ -1,9 +0,0 @@
-abstract class {
-
- function normal() {
- return "normal";
- }
-
- abstract function abstractMethod()
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/AbstractClassCF.cfc b/src/test/java/TestCases/asm/phase3/AbstractClassCF.cfc
deleted file mode 100644
index dc3d808e4..000000000
--- a/src/test/java/TestCases/asm/phase3/AbstractClassCF.cfc
+++ /dev/null
@@ -1,9 +0,0 @@
-abstract component {
-
- function normal() {
- return "normal";
- }
-
- abstract function abstractMethod()
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/Animal.cfc b/src/test/java/TestCases/asm/phase3/Animal.cfc
deleted file mode 100644
index 7fc908207..000000000
--- a/src/test/java/TestCases/asm/phase3/Animal.cfc
+++ /dev/null
@@ -1,36 +0,0 @@
-component {
- variables.results = [];
- results.append('animal pseudo ' & getFileFromPath( getCurrentTemplatePath()))
- variables.inAnimal = true;
- variables.inDog = false;
-
- function init() {
- results.append('Animal init ' & getFileFromPath( getCurrentTemplatePath()))
- }
-
- function speak() {
- throw( "speak method not implemented" );
- }
-
- function isWarmBlooded() {
- // this needs to be a reference to the bottom most class
- results.append( "animal this is: " & this.$bx.meta.name )
- // We need to see the variables scope of the bottom most class
- results.append( "animal sees inDog as: " & inDog )
- return true;
- }
-
- function getScientificName() {
- // this needs to be a reference to the bottom most class
- results.append( "super animal sees: " & this.$bx.meta.name )
- // We need to see the variables scope of the bottom most class
- results.append( "super sees inDog as: " & inDog )
-
- return "Animal Kingdom";
- }
-
- function getResults() {
- return results;
- }
-
- }
diff --git a/src/test/java/TestCases/asm/phase3/ApplicationTest.java b/src/test/java/TestCases/asm/phase3/ApplicationTest.java
deleted file mode 100644
index 148cdbcc4..000000000
--- a/src/test/java/TestCases/asm/phase3/ApplicationTest.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.phase3;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import java.nio.file.Path;
-import java.time.Instant;
-import java.time.temporal.ChronoUnit;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.application.Application;
-import ortus.boxlang.runtime.application.BaseApplicationListener;
-import ortus.boxlang.runtime.context.ApplicationBoxContext;
-import ortus.boxlang.runtime.context.BaseBoxContext;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.RequestBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.dynamic.casters.DateTimeCaster;
-import ortus.boxlang.runtime.scopes.ApplicationScope;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.SessionScope;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-import ortus.boxlang.runtime.types.IStruct;
-
-public class ApplicationTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "application basics" )
- @Test
- public void testBasicApplication() {
- // @formatter:off
- instance.executeSource(
- """
- application name="myAppsdfsdfasm" sessionmanagement="true";
-
- result = application;
- result2 = session;
- startTime = ApplicationStartTime()
- """, context );
- // @formatter:on
-
- assertThat( variables.get( result ) ).isInstanceOf( ApplicationScope.class );
- assertThat( variables.get( Key.of( "result2" ) ) ).isInstanceOf( SessionScope.class );
-
- ApplicationBoxContext appContext = context.getParentOfType( ApplicationBoxContext.class );
- Application app = appContext.getApplication();
- Instant actual = DateTimeCaster.cast( variables.get( Key.of( "startTime" ) ) ).getWrapped().toInstant();
- Instant now = Instant.now();
- long differenceInSeconds = ChronoUnit.SECONDS.between( actual, now );
-
- assertThat( app.getName().getName() ).isEqualTo( "myAppsdfsdfasm" );
- assertThat( app.getSessionsCache() ).isNotNull();
- assertThat( app.getApplicationScope() ).isNotNull();
- assertThat( app.getApplicationScope().getName().getName() ).isEqualTo( "application" );
- assertThat( app.getClassLoaders() ).isNotNull();
- assertThat( app.hasStarted() ).isTrue();
- assertThat( differenceInSeconds ).isAtMost( 1L );
- }
-
- @Test
- public void testGetAppMeta() {
- // @formatter:off
- instance.executeSource(
- """
- application name="myAppsdfsdf2asm" sessionmanagement="true";
- result = GetApplicationMetadata();
- """, context );
- // @formatter:on
-
- assertThat( variables.get( result ) ).isInstanceOf( IStruct.class );
- assertThat( variables.getAsStruct( result ).get( "name" ) ).isEqualTo( "myAppsdfsdf2asm" );
- assertThat( variables.getAsStruct( result ).get( "sessionmanagement" ).toString() ).isEqualTo( "true" );
- }
-
- @Test
- public void testGetDefaultAppMeta() {
- // @formatter:off
- instance.executeSource(
- """
- result = GetApplicationMetadata();
- """, context );
- // @formatter:on
-
- assertThat( variables.get( result ) ).isInstanceOf( IStruct.class );
- assertThat( variables.getAsStruct( result ).get( "name" ) ).isEqualTo( "" );
- assertThat( variables.getAsStruct( result ).get( "sessionmanagement" ).toString() ).isEqualTo( "false" );
- }
-
- @DisplayName( "java settings setup" )
- @Test
- public void testJavaSettings() {
- // @formatter:off
- instance.executeSource(
- """
- application name="myJavaApp" javaSettings={
- loadPaths = [ "/src/test/resources/libs" ],
- reloadOnChange = true
- };
-
- import com.github.benmanes.caffeine.cache.Caffeine
- targetInstance = Caffeine.newBuilder()
-
- import org.apache.commons.lang3.ClassUtils
- targetInstance2 = ClassUtils.getClass()
- """, context );
- // @formatter:on
-
- ApplicationBoxContext appContext = context.getParentOfType( ApplicationBoxContext.class );
- Application app = appContext.getApplication();
- assertThat( app.getClassLoaderCount() ).isEqualTo( 1 );
- }
-
- @DisplayName( "Ad-hoc config override" )
- @Test
- public void testAdHocConfigOverride() {
-
- context.injectParentContext( new BaseBoxContext() {
-
- public IStruct getConfig() {
- IStruct config = super.getConfig();
- config.put( "adHocConfig", "adHocConfigValue" );
- return config;
- }
- } );
-
- assertThat( context.getConfigItem( Key.of( "adHocConfig" ) ) ).isEqualTo( "adHocConfigValue" );
- }
-
- @DisplayName( "Can resolve java settings paths with a full jar/class path" )
- @Test
- public void testJavaSettingsPaths() {
- // @formatter:off
- instance.executeSource(
- """
- application name="myJavaApp" javaSettings={
- loadPaths = [ "/src/test/resources/libs/helloworld.jar" ],
- reloadOnChange = true
- };
- """, context );
- // @formatter:on
-
- ApplicationBoxContext appContext = context.getParentOfType( ApplicationBoxContext.class );
- Application app = appContext.getApplication();
- assertThat( app.getClassLoaderCount() ).isEqualTo( 1 );
- }
-
- @DisplayName( "Can resolve java settings paths with a full jar/class path with bad pathing" )
- @Test
- public void testJavaSettingsBadPaths() {
- // @formatter:off
- instance.executeSource(
- """
- application name="myJavaApp" javaSettings={
- loadPaths = [ "\\src\\test\\resources\\libs\\helloworld.jar" ],
- reloadOnChange = true
- };
- """, context );
- // @formatter:on
-
- ApplicationBoxContext appContext = context.getParentOfType( ApplicationBoxContext.class );
- Application app = appContext.getApplication();
-
- assertThat( app.getClassLoaderCount() ).isEqualTo( 1 );
- }
-
- @DisplayName( "Can resolve relative paths" )
- @Test
- public void testJavaSettingsRelativePaths() {
-
- RequestBoxContext requestContext = context.getParentOfType( RequestBoxContext.class );
- BaseApplicationListener listener = requestContext.getApplicationListener();
-
- // Mock the relative path
- listener.getSettings()
- .put( "source", Path.of( "src/test/resources/Application.bx" ).toAbsolutePath().toString() );
-
- // @formatter:off
- instance.executeSource(
- """
- application name="myJavaApp" javaSettings={
- loadPaths = [ "libs/helloworld.jar" ],
- reloadOnChange = true
- };
- """, context );
- // @formatter:on
-
- ApplicationBoxContext appContext = context.getParentOfType( ApplicationBoxContext.class );
- Application app = appContext.getApplication();
- assertThat( app.getClassLoaderCount() ).isEqualTo( 1 );
- }
-
-}
diff --git a/src/test/java/TestCases/asm/phase3/CFImportTest.cfc b/src/test/java/TestCases/asm/phase3/CFImportTest.cfc
deleted file mode 100644
index 1bcae0686..000000000
--- a/src/test/java/TestCases/asm/phase3/CFImportTest.cfc
+++ /dev/null
@@ -1,13 +0,0 @@
-import src.test.java.TestCases.phase3.Stack;
-
-component {
- function init() {
- stack = new Stack();
- }
-
- function doSomething() {
- if (!stack.empty() ) {
- // do stuff
- }
- }
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/CFImportTest2.cfc b/src/test/java/TestCases/asm/phase3/CFImportTest2.cfc
deleted file mode 100644
index 6aff56356..000000000
--- a/src/test/java/TestCases/asm/phase3/CFImportTest2.cfc
+++ /dev/null
@@ -1,13 +0,0 @@
-import "src.test.java.TestCases.phase3.Stack";
-
-component {
- function init() {
- stack = new Stack();
- }
-
- function doSomething() {
- if (!stack.empty() ) {
- // do stuff
- }
- }
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/Chihuahua.cfc b/src/test/java/TestCases/asm/phase3/Chihuahua.cfc
deleted file mode 100644
index f1619b84d..000000000
--- a/src/test/java/TestCases/asm/phase3/Chihuahua.cfc
+++ /dev/null
@@ -1,17 +0,0 @@
-component extends="Dog" {
- results.append('Chihuahua pseudo ' & getFileFromPath( getCurrentTemplatePath()))
-
- function init() {
- super.init();
- results.append('Chihuahua init ' & getFileFromPath( getCurrentTemplatePath()))
- }
-
- function speak() {
- return "Yip Yip!";
- }
-
- function getScientificName() {
- return "barkus annoyus " & super.getScientificName();
- }
-
- }
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/Child.cfc b/src/test/java/TestCases/asm/phase3/Child.cfc
deleted file mode 100644
index ffc8ed46e..000000000
--- a/src/test/java/TestCases/asm/phase3/Child.cfc
+++ /dev/null
@@ -1,12 +0,0 @@
-component extends="Parent" {
-
- function init() {
- return super.init();
- }
-
- private void function setupFrameworkDefaults() {
- request.calls.append( "running child setupFrameworkDefaults()" );
- super.setupFrameworkDefaults();
- }
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/ClassLeadingComment.cfc b/src/test/java/TestCases/asm/phase3/ClassLeadingComment.cfc
deleted file mode 100644
index e624afcaf..000000000
--- a/src/test/java/TestCases/asm/phase3/ClassLeadingComment.cfc
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/ClassTest.java b/src/test/java/TestCases/asm/phase3/ClassTest.java
deleted file mode 100644
index ba3f5d315..000000000
--- a/src/test/java/TestCases/asm/phase3/ClassTest.java
+++ /dev/null
@@ -1,1268 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.phase3;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.compiler.parser.BoxSourceType;
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.interop.DynamicObject;
-import ortus.boxlang.runtime.runnables.IClassRunnable;
-import ortus.boxlang.runtime.runnables.RunnableLoader;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.RequestScope;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-import ortus.boxlang.runtime.types.Array;
-import ortus.boxlang.runtime.types.IStruct;
-import ortus.boxlang.runtime.types.Struct;
-import ortus.boxlang.runtime.types.exceptions.AbstractClassException;
-import ortus.boxlang.runtime.types.exceptions.BoxRuntimeException;
-import ortus.boxlang.runtime.types.meta.ClassMeta;
-
-public class ClassTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
- static Key foo = new Key( "foo" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "Test can create vanilla module config" )
- @Test
- void testVanillaModuleConfig() {
-
- IClassRunnable cfc = ( IClassRunnable ) DynamicObject.of( RunnableLoader.getInstance().loadClass(
- """
- /**
- * This is the module descriptor and entry point for your module in the Runtime.
- * The unique name of the moduel is the name of the directory on the modules folder.
- * A BoxLang Mapping will be created for you with the name of the module.
- *
- * A Module can have the following folders that will be automatically registered:
- * + bifs - Custom BIFs that will be registered into the runtime
- * + interceptors - Custom Interceptors that will be registered into the runtime via the configure() method
- * + libs - Custom Java libraries that your module leverages
- * + tags - Custom tags that will be registered into the runtime
- *
- * Every Module will have it's own ClassLoader that will be used to load the module libs and dependencies.
- */
- component{
-
- /**
- * --------------------------------------------------------------------------
- * Module Properties
- * --------------------------------------------------------------------------
- * Here is where you define the properties of your module that the module service
- * will use to register and activate your module
- */
-
- /**
- * Your module version. Try to use semantic versioning
- * @mandatory
- */
- this.version = "1.0.0";
-
- /**
- * The BoxLang mapping for your module. All BoxLang modules are registered with an internal
- * mapping prefix of : bxModules.{this.mapping}, /bxmodules/{this.mapping}. Ex: bxModules.test, /bxmodules/test
- */
- this.mapping = "test";
-
- /**
- * Who built the module
- */
- this.author = "Luis Majano";
-
- /**
- * The module description
- */
- this.description = "This module does amazing things";
-
- /**
- * The module web URL
- */
- this.webURL = "https://www.ortussolutions.com";
-
- /**
- * This boolean flag tells the module service to skip the module registration/activation process.
- */
- this.disabled = false;
-
- /**
- * --------------------------------------------------------------------------
- * Module Methods
- * --------------------------------------------------------------------------
- */
-
- /**
- * Called by the ModuleService on module registration
- *
- * @moduleRecord - The module record registered in the ModuleService
- * @runtime - The Runtime instance
- */
- function configure( moduleRecord, runtime ){
- /**
- * Every module has a settings configuration object
- */
- settings = {
- loadedOn : now(),
- loadedBy : "Luis Majano"
- };
-
- /**
- * The module interceptors to register into the runtime
- */
- interceptors = [
- // { class="path.to.Interceptor", properties={} }
- { class="bxModules.test.interceptors.Listener", properties={} }
- ];
-
- /**
- * A list of custom interception points to register into the runtime
- */
- customInterceptionPoints = [ "onBxTestModule" ];
- }
-
- /**
- * Called by the ModuleService on module activation
- *
- * @moduleRecord - The module record registered in the ModuleService
- * @runtime - The Runtime instance
- */
- function onLoad( moduleRecord, runtime ){
-
- }
-
- /**
- * Called by the ModuleService on module deactivation
- *
- * @moduleRecord - The module record registered in the ModuleService
- * @runtime - The Runtime instance
- */
- function onUnload( moduleRecord, runtime ){
-
- }
-
- /**
- * --------------------------------------------------------------------------
- * Module Events
- * --------------------------------------------------------------------------
- * You can listen to any Runtime events by creating the methods
- * that match the approved Runtime Interception Points
- */
- }
-
- """, context, BoxSourceType.CFSCRIPT ) )
- .invokeConstructor( context )
- .getTargetInstance();
- }
-
- @DisplayName( "Test a basic boxlang class" )
- @Test
- public void testBasicBLClass() {
-
- // @formatter:off
- IClassRunnable bxClass = ( IClassRunnable ) DynamicObject.of( RunnableLoader.getInstance().loadClass(
- """
- import foo;
- import java.lang.System;
-
- /**
- * This is my class description
- *
- * @brad wood
- * @luis
- */
- @foo "bar"
- class accessors=true singleton gavin="pickin" inject {
-
- property numeric age default=1;
- property numeric test;
- property testAlone;
-
- variables.setup=true;
- System.out.println( "word" );
- request.foo="bar";
- println( request.asString())
- isInitted = false;
- println( "current template is " & getCurrentTemplatePath() );
- printLn( foo() )
-
- function init() {
- isInitted = true;
- }
-
- function foo() {
- return "I work! #bar()# #variables.setup# #setup# #request.foo# #isInitted#";
- }
-
- private function bar() {
- return "whee";
- }
-
- function getThis() {
- return this;
- }
-
- function runThisFoo() {
- return this.foo();
- }
- }
- """, context, BoxSourceType.BOXSCRIPT ) )
- .invokeConstructor( context )
- .getTargetInstance();
- // @formatter:on
-
- // Test shorthand properties work
- assertThat(
- bxClass.dereferenceAndInvoke( context, Key.of( "getAge" ), new Object[] {}, false )
- ).isEqualTo( 1 );
- assertThat(
- bxClass.dereferenceAndInvoke( context, Key.of( "getTest" ), new Object[] {}, false )
- ).isEqualTo( null );
- assertThat(
- bxClass.dereferenceAndInvoke( context, Key.of( "getTestAlone" ), new Object[] {}, false )
- ).isEqualTo( null );
- var mdProperties = bxClass.getMetaData().get( Key.of( "properties" ) );
-
- // execute public method
- Object funcResult = bxClass.dereferenceAndInvoke( context, Key.of( "foo" ), new Object[] {}, false );
-
- // private methods error
- Throwable t = assertThrows( BoxRuntimeException.class,
- () -> bxClass.dereferenceAndInvoke( context, Key.of( "bar" ), new Object[] {}, false ) );
- assertThat( t.getMessage().contains( "bar" ) ).isTrue();
-
- // Can call public method that accesses private method, and variables, and request scope
- assertThat( funcResult ).isEqualTo( "I work! whee true true bar true" );
- assertThat( context.getScope( RequestScope.name ).get( Key.of( "foo" ) ) ).isEqualTo( "bar" );
-
- // This scope is reference to actual CFC instance
- funcResult = bxClass.dereferenceAndInvoke( context, Key.of( "getThis" ), new Object[] {}, false );
- assertThat( funcResult ).isEqualTo( bxClass );
-
- // Can call public methods on this
- funcResult = bxClass.dereferenceAndInvoke( context, Key.of( "runThisFoo" ), new Object[] {}, false );
- assertThat( funcResult ).isEqualTo( "I work! whee true true bar true" );
- }
-
- @DisplayName( "basic class" )
- @Test
- public void testBasicCFClass() {
- // @formatter:off
- IClassRunnable cfc = ( IClassRunnable ) DynamicObject.of( RunnableLoader.getInstance().loadClass(
- """
- /**
- * This is my class description
- *
- * @brad wood
- * @luis
- */
- component singleton gavin="pickin" inject foo="bar" {
-
- variables.setup=true;
- createObject('java','java.lang.System').out.println( "word" );
- request.foo="bar";
- println( request.asString())
- isInitted = false;
- println( "current template is " & getCurrentTemplatePath() );
- printLn( foo() )
-
- function init() {
- isInitted = true;
- }
-
- function foo() {
- return "I work! #bar()# #variables.setup# #setup# #request.foo# #isInitted#";
- }
-
- private function bar() {
- return "whee" ;
- }
-
- function getThis() {
- return this;
- }
-
- function runThisFoo() {
- return this.foo() ;
- }
- }
-
-
- """, context, BoxSourceType.CFSCRIPT ) )
- .invokeConstructor( context )
- .getTargetInstance();
- // @formatter:on
-
- // execute public method
- Object funcResult = cfc.dereferenceAndInvoke( context, Key.of( "foo" ), new Object[] {}, false );
-
- // private methods error
- Throwable t = assertThrows( BoxRuntimeException.class,
- () -> cfc.dereferenceAndInvoke( context, Key.of( "bar" ), new Object[] {}, false ) );
- assertThat( t.getMessage().contains( "bar" ) ).isTrue();
-
- // Can call public method that accesses private method, and variables, and request scope
- assertThat( funcResult ).isEqualTo( "I work! whee true true bar true" );
- assertThat( context.getScope( RequestScope.name ).get( Key.of( "foo" ) ) ).isEqualTo( "bar" );
-
- // This scope is reference to actual CFC instance
- funcResult = cfc.dereferenceAndInvoke( context, Key.of( "getThis" ), new Object[] {}, false );
- assertThat( funcResult ).isEqualTo( cfc );
-
- // Can call public methods on this
- funcResult = cfc.dereferenceAndInvoke( context, Key.of( "runThisFoo" ), new Object[] {}, false );
- assertThat( funcResult ).isEqualTo( "I work! whee true true bar true" );
- }
-
- @DisplayName( "basic class file" )
- @Test
- public void testBasicClassFile() {
- // @formatter:off
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.MyClass();
- // execute public method
- result = cfc.foo();
-
- // private methods error
- try {
- cfc.bar()
- assert false;
- } catch( BoxRuntimeException e ) {
- assert e.message contains "bar";
- }
-
- // Can call public method that accesses private method, and variables, and request scope
- assert result == "I work! whee true true bar true";
- assert request.foo == "bar";
-
- // This scope is reference to actual CFC instance
- assert cfc.$bx.$class.getName() == cfc.getThis().$bx.$class.getName();
-
- // Can call public methods on this
- assert cfc.runThisFoo() == "I work! whee true true bar true";
- """, context );
- // @formatter:on
- }
-
- @DisplayName( "legacy meta" )
- @Test
- public void testlegacyMeta() {
-
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.MyClass();
- """, context );
-
- var cfc = variables.getAsClassRunnable( Key.of( "cfc" ) );
- var meta = cfc.getMetaData();
- assertThat( meta.get( Key.of( "name" ) ) ).isEqualTo( "src.test.java.TestCases.phase3.MyClass" );
- assertThat( meta.get( Key.of( "type" ) ) ).isEqualTo( "Component" );
- assertThat( meta.get( Key.of( "fullname" ) ) ).isEqualTo( "src.test.java.TestCases.phase3.MyClass" );
- assertThat( meta.getAsString( Key.of( "path" ) ).contains( "MyClass.bx" ) ).isTrue();
- // assertThat( meta.get( Key.of( "hashcode" ) ) ).isEqualTo( cfc.hashCode() );
- assertThat( meta.get( Key.of( "properties" ) ) ).isInstanceOf( Array.class );
- assertThat( meta.getAsArray( Key.of( "properties" ) ) ).hasSize( 1 );
- Struct prop = ( Struct ) meta.getAsArray( Key.of( "properties" ) ).get( 0 );
- assertThat( prop ).doesNotContainKey( Key.of( "defaultValue" ) );
-
- assertThat( meta.get( Key.of( "functions" ) ) instanceof Array ).isTrue();
- assertThat( meta.getAsArray( Key.of( "functions" ) ).size() ).isEqualTo( 5 );
- assertThat( meta.get( Key.of( "extends" ) ) ).isNull();
- assertThat( meta.get( Key.of( "output" ) ) ).isEqualTo( false );
- assertThat( meta.get( Key.of( "persisent" ) ) ).isEqualTo( false );
- assertThat( meta.get( Key.of( "accessors" ) ) ).isEqualTo( true );
- }
-
- @DisplayName( "legacy meta CF" )
- @Test
- public void testlegacyMetaCF() {
-
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.MyClassCF();
- """, context );
-
- var cfc = variables.getAsClassRunnable( Key.of( "cfc" ) );
- var meta = cfc.getMetaData();
- assertThat( meta.get( Key.of( "name" ) ) ).isEqualTo( "src.test.java.TestCases.phase3.MyClassCF" );
- assertThat( meta.get( Key.of( "type" ) ) ).isEqualTo( "Component" );
- assertThat( meta.get( Key.of( "fullname" ) ) ).isEqualTo( "src.test.java.TestCases.phase3.MyClassCF" );
- assertThat( meta.getAsString( Key.of( "path" ) ).contains( "MyClassCF.cfc" ) ).isTrue();
- // assertThat( meta.get( Key.of( "hashcode" ) ) ).isEqualTo( cfc.hashCode() );
- assertThat( meta.get( Key.of( "properties" ) ) ).isInstanceOf( Array.class );
- assertThat( meta.get( Key.of( "functions" ) ) instanceof Array ).isTrue();
- assertThat( meta.getAsArray( Key.of( "functions" ) ).size() ).isEqualTo( 5 );
- assertThat( meta.get( Key.of( "extends" ) ) ).isNull();
- assertThat( meta.get( Key.of( "output" ) ) ).isEqualTo( true );
- assertThat( meta.get( Key.of( "persisent" ) ) ).isEqualTo( false );
- assertThat( meta.get( Key.of( "accessors" ) ) ).isEqualTo( false );
- }
-
- @DisplayName( "It should call onMissingMethod with pos args" )
- @Test
- public void testOnMissingMethodPos() {
-
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.OnMissingMethod();
- result = cfc.someFunc( "first", "second" );
- """, context );
-
- String res = variables.getAsString( result );
- assertThat( res ).isEqualTo( "someFuncsecond" );
- }
-
- @DisplayName( "It should call onMissingMethod with named args" )
- @Test
- public void testOnMissingMethodNamed() {
-
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.OnMissingMethod();
- result = cfc.someFunc( foo="first", bar="second" );
- """, context );
-
- String res = variables.getAsString( result );
- assertThat( res ).isEqualTo( "someFuncsecond" );
- }
-
- @DisplayName( "box meta" )
- @Test
- public void testBoxMeta() {
-
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.MyClass();
- """, context );
-
- var cfc = variables.getAsClassRunnable( Key.of( "cfc" ) );
- var boxMeta = ( ClassMeta ) cfc.getBoxMeta();
- var meta = boxMeta.meta;
- assertThat( meta.get( Key.of( "type" ) ) ).isEqualTo( "Component" );
- assertThat( meta.get( Key.of( "fullname" ) ) ).isEqualTo( "src.test.java.TestCases.phase3.MyClass" );
- assertThat( meta.getAsString( Key.of( "path" ) ).contains( "MyClass.bx" ) ).isTrue();
- assertThat( meta.get( Key.of( "hashcode" ) ) ).isEqualTo( cfc.hashCode() );
- assertThat( meta.get( Key.of( "properties" ) ) instanceof Array ).isTrue();
- assertThat( meta.get( Key.of( "functions" ) ) instanceof Array ).isTrue();
-
- assertThat( meta.get( Key.of( "extends" ) ) instanceof IStruct ).isTrue();
-
- assertThat( meta.getAsArray( Key.of( "functions" ) ).size() ).isEqualTo( 5 );
- var fun1 = meta.getAsArray( Key.of( "functions" ) ).get( 0 );
- assertThat( fun1 ).isInstanceOf( Struct.class );
- assertThat( ( ( IStruct ) fun1 ).containsKey( Key.of( "name" ) ) ).isTrue();
- System.out.println( meta.getAsArray( Key.of( "functions" ) ).asString() );
-
- assertThat( meta.get( Key.of( "documentation" ) ) instanceof IStruct ).isTrue();
- var docs = meta.getAsStruct( Key.of( "documentation" ) );
- assertThat( docs.getAsString( Key.of( "brad" ) ).trim() ).isEqualTo( "wood" );
- assertThat( docs.get( Key.of( "luis" ) ) ).isEqualTo( "" );
- assertThat( docs.getAsString( Key.of( "hint" ) ).trim() ).isEqualTo( "This is my class description continued on this line \nand this one as well." );
-
- assertThat( meta.get( Key.of( "annotations" ) ) instanceof IStruct ).isTrue();
- var annos = meta.getAsStruct( Key.of( "annotations" ) );
- assertThat( annos.getAsString( Key.of( "foo" ) ).trim() ).isEqualTo( "bar" );
- // assertThat( annos.getAsString( Key.of( "implements" ) ).trim() ).isEqualTo( "Luis,Jorge" );
- assertThat( annos.getAsString( Key.of( "singleton" ) ).trim() ).isEqualTo( "" );
- assertThat( annos.getAsString( Key.of( "gavin" ) ).trim() ).isEqualTo( "pickin" );
- assertThat( annos.getAsString( Key.of( "inject" ) ).trim() ).isEqualTo( "" );
-
- }
-
- @DisplayName( "properties" )
- @Test
- public void testProperties() {
- // @formatter:off
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.PropertyTest();
- nameGet = cfc.getMyProperty();
- invalidSetErrored=false;
- try {
- // property is typed as string, an array should blow up
- setResult = cfc.setMyProperty( [] );
- } catch( any e ) {
- invalidSetErrored=true;
- }
- setResult = cfc.setMyProperty( "anotherValue" );
- nameGet2 = cfc.getMyProperty();
- test1 = cfc.getShortcutWithDefault()
- test2 = cfc.getTypedShortcutWithDefault()
- """, context );
- // @formatter:on
-
- var cfc = variables.getAsClassRunnable( Key.of( "cfc" ) );
- assertThat( variables.get( Key.of( "nameGet" ) ) ).isEqualTo( "myDefaultValue" );
- assertThat( variables.get( Key.of( "nameGet2" ) ) ).isEqualTo( "anotherValue" );
- assertThat( variables.get( Key.of( "setResult" ) ) ).isEqualTo( cfc );
- assertThat( variables.get( Key.of( "invalidSetErrored" ) ) ).isEqualTo( true );
- assertThat( variables.get( Key.of( "test1" ) ) ).isEqualTo( "myDefaultValue" );
- assertThat( variables.get( Key.of( "test2" ) ) ).isEqualTo( "myDefaultValue2" );
-
- var boxMeta = ( ClassMeta ) cfc.getBoxMeta();
- var meta = boxMeta.meta;
-
- assertThat( meta.getAsArray( Key.of( "properties" ) ).size() ).isEqualTo( 7 );
-
- var prop1 = ( IStruct ) meta.getAsArray( Key.of( "properties" ) ).get( 0 );
- assertThat( prop1.get( "name" ) ).isEqualTo( "myProperty" );
- assertThat( prop1.get( "defaultValue" ) ).isEqualTo( "myDefaultValue" );
- assertThat( prop1.get( "type" ) ).isEqualTo( "string" );
-
- var prop1Annotations = prop1.getAsStruct( Key.of( "annotations" ) );
- assertThat( prop1Annotations.size() ).isEqualTo( 5 );
-
- assertThat( prop1Annotations.containsKey( Key.of( "preAnno" ) ) ).isTrue();
- assertThat( prop1Annotations.get( Key.of( "preAnno" ) ) ).isEqualTo( "" );
-
- assertThat( prop1Annotations.containsKey( Key.of( "inject" ) ) ).isTrue();
- assertThat( prop1Annotations.get( Key.of( "inject" ) ) ).isEqualTo( "" );
-
- var prop2 = ( IStruct ) meta.getAsArray( Key.of( "properties" ) ).get( 1 );
- assertThat( prop2.get( "name" ) ).isEqualTo( "anotherprop" );
- assertThat( prop2.get( "defaultValue" ) ).isEqualTo( null );
- assertThat( prop2.get( "type" ) ).isEqualTo( "string" );
-
- var prop2Annotations = prop2.getAsStruct( Key.of( "annotations" ) );
- assertThat( prop2Annotations.size() ).isEqualTo( 4 );
-
- assertThat( prop2Annotations.containsKey( Key.of( "preAnno" ) ) ).isTrue();
- assertThat( prop2Annotations.get( Key.of( "preAnno" ) ) instanceof Array ).isTrue();
- Array preAnno = prop2Annotations.getAsArray( Key.of( "preAnno" ) );
- assertThat( preAnno.size() ).isEqualTo( 2 );
- assertThat( preAnno.get( 0 ) ).isEqualTo( "myValue" );
- assertThat( preAnno.get( 1 ) ).isEqualTo( "anothervalue" );
-
- var prop3 = ( IStruct ) meta.getAsArray( Key.of( "properties" ) ).get( 2 );
- assertThat( prop3.get( "name" ) ).isEqualTo( "theName" );
- assertThat( prop3.get( "defaultValue" ) ).isEqualTo( null );
- assertThat( prop3.get( "type" ) ).isEqualTo( "any" );
-
- var prop3Annotations = prop3.getAsStruct( Key.of( "annotations" ) );
- assertThat( prop3Annotations.size() ).isEqualTo( 4 );
- assertThat( prop3Annotations.containsKey( Key.of( "ID" ) ) ).isTrue();
- assertThat( prop3Annotations.get( Key.of( "ID" ) ) ).isEqualTo( "" );
-
- var prop4 = ( IStruct ) meta.getAsArray( Key.of( "properties" ) ).get( 3 );
- assertThat( prop4.get( "name" ) ).isEqualTo( "name" );
- assertThat( prop4.get( "defaultValue" ) ).isEqualTo( null );
- assertThat( prop4.get( "type" ) ).isEqualTo( "string" );
-
- var prop2Docs = prop2.getAsStruct( Key.of( "documentation" ) );
- assertThat( prop2Docs.size() ).isEqualTo( 3 );
- assertThat( prop2Docs.getAsString( Key.of( "brad" ) ).trim() ).isEqualTo( "wood" );
- assertThat( prop2Docs.getAsString( Key.of( "luis" ) ).trim() ).isEqualTo( "" );
- assertThat( prop2Docs.getAsString( Key.of( "hint" ) ).trim() ).isEqualTo( "This is my property" );
- }
-
- @DisplayName( "properties" )
- @Test
- public void testPropertiesCF() {
-
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.PropertyTestCF();
- nameGet = cfc.getMyProperty();
- setResult = cfc.SetMyProperty( "anotherValue" );
- nameGet2 = cfc.getMyProperty();
- test1 = cfc.getShortcutWithDefault()
- test2 = cfc.getTypedShortcutWithDefault()
- """, context );
-
- var cfc = variables.getAsClassRunnable( Key.of( "cfc" ) );
-
- assertThat( variables.get( Key.of( "nameGet" ) ) ).isEqualTo( "myDefaultValue" );
- assertThat( variables.get( Key.of( "nameGet2" ) ) ).isEqualTo( "anotherValue" );
- assertThat( variables.get( Key.of( "setResult" ) ) ).isEqualTo( cfc );
- assertThat( variables.get( Key.of( "test1" ) ) ).isEqualTo( "myDefaultValue" );
- assertThat( variables.get( Key.of( "test2" ) ) ).isEqualTo( "myDefaultValue2" );
-
- var boxMeta = ( ClassMeta ) cfc.getBoxMeta();
- var meta = boxMeta.meta;
-
- assertThat( meta.getAsArray( Key.of( "properties" ) ).size() ).isEqualTo( 5 );
-
- var prop1 = ( IStruct ) meta.getAsArray( Key.of( "properties" ) ).get( 0 );
- assertThat( prop1.get( "name" ) ).isEqualTo( "myProperty" );
- assertThat( prop1.get( "defaultValue" ) ).isEqualTo( "myDefaultValue" );
- assertThat( prop1.get( "type" ) ).isEqualTo( "string" );
-
- var prop1Annotations = prop1.getAsStruct( Key.of( "annotations" ) );
- assertThat( prop1Annotations.size() ).isEqualTo( 5 );
-
- assertThat( prop1Annotations.containsKey( Key.of( "preAnno" ) ) ).isTrue();
- assertThat( prop1Annotations.get( Key.of( "preAnno" ) ) ).isEqualTo( "" );
-
- assertThat( prop1Annotations.containsKey( Key.of( "inject" ) ) ).isTrue();
- assertThat( prop1Annotations.get( Key.of( "inject" ) ) ).isEqualTo( "" );
-
- var prop2 = ( IStruct ) meta.getAsArray( Key.of( "properties" ) ).get( 1 );
- assertThat( prop2.get( "name" ) ).isEqualTo( "anotherprop" );
- assertThat( prop2.get( "defaultValue" ) ).isEqualTo( null );
- assertThat( prop2.get( "type" ) ).isEqualTo( "string" );
-
- var prop2Annotations = prop2.getAsStruct( Key.of( "annotations" ) );
- assertThat( prop2Annotations.size() ).isEqualTo( 6 );
-
- assertThat( prop2Annotations.containsKey( Key.of( "preAnno" ) ) ).isTrue();
- assertThat( prop2Annotations.get( Key.of( "preAnno" ) ) instanceof Array ).isTrue();
- Array preAnno = prop2Annotations.getAsArray( Key.of( "preAnno" ) );
- assertThat( preAnno.size() ).isEqualTo( 2 );
- assertThat( preAnno.get( 0 ) ).isEqualTo( "myValue" );
- assertThat( preAnno.get( 1 ) ).isEqualTo( "anothervalue" );
-
- var prop2Docs = prop2.getAsStruct( Key.of( "documentation" ) );
- assertThat( prop2Docs.size() ).isEqualTo( 3 );
- assertThat( prop2Docs.getAsString( Key.of( "brad" ) ).trim() ).isEqualTo( "wood" );
- assertThat( prop2Docs.getAsString( Key.of( "luis" ) ).trim() ).isEqualTo( "" );
- assertThat( prop2Docs.getAsString( Key.of( "hint" ) ).trim() ).isEqualTo( "This is my property" );
-
- }
-
- @DisplayName( "Implicit Constructor named" )
- @Test
- public void testImplicitConstructorNamed() {
-
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.ImplicitConstructorTest( name="brad", age=43, favoriteColor="blue" );
- name = cfc.getName();
- age = cfc.getAge();
- favoriteColor = cfc.getFavoriteColor();
- """, context );
-
- assertThat( variables.get( Key.of( "name" ) ) ).isEqualTo( "brad" );
- assertThat( variables.get( Key.of( "age" ) ) ).isEqualTo( 43 );
- assertThat( variables.get( Key.of( "favoriteColor" ) ) ).isEqualTo( "blue" );
-
- }
-
- @DisplayName( "Implicit Constructor named argumentCollection" )
- @Test
- public void testImplicitConstructorNamedArgumentCollection() {
-
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.ImplicitConstructorTest( argumentCollection={ name="brad", age=43, favoriteColor="blue" } );
- name = cfc.getName();
- age = cfc.getAge();
- favoriteColor = cfc.getFavoriteColor();
- """, context );
-
- assertThat( variables.get( Key.of( "name" ) ) ).isEqualTo( "brad" );
- assertThat( variables.get( Key.of( "age" ) ) ).isEqualTo( 43 );
- assertThat( variables.get( Key.of( "favoriteColor" ) ) ).isEqualTo( "blue" );
-
- }
-
- @DisplayName( "Implicit Constructor positional" )
- @Test
- public void testImplicitConstructorPositional() {
-
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.ImplicitConstructorTest( {name="brad", age=43, favoriteColor="blue" });
- name = cfc.getName();
- age = cfc.getAge();
- favoriteColor = cfc.getFavoriteColor();
- """, context );
-
- assertThat( variables.get( Key.of( "name" ) ) ).isEqualTo( "brad" );
- assertThat( variables.get( Key.of( "age" ) ) ).isEqualTo( 43 );
- assertThat( variables.get( Key.of( "favoriteColor" ) ) ).isEqualTo( "blue" );
-
- }
-
- @DisplayName( "InitMethod Test" )
- @Test
- public void testInitMethod() {
-
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.InitMethodTest( );
-
- result = cfc.getInittedProperly();
- """, context );
-
- assertThat( variables.get( Key.of( "result" ) ) ).isEqualTo( true );
-
- }
-
- @DisplayName( "PseudoConstructor can output" )
- @Test
- public void testPseudoConstructorOutput() {
-
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.PseudoConstructorOutput();
- result = getBoxContext().getBuffer().toString()
-
- """, context );
-
- assertThat( variables.get( Key.of( "result" ) ) ).isEqualTo( "PseudoConstructorOutput" );
-
- }
-
- @DisplayName( "PseudoConstructor will not output" )
- @Test
- public void testPseudoConstructorNoOutput() {
-
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.PseudoConstructorNoOutput();
- result = getBoxContext().getBuffer().toString()
-
- """, context );
-
- assertThat( variables.get( Key.of( "result" ) ) ).isEqualTo( "" );
-
- }
-
- @DisplayName( "can extend" )
- @Test
- public void testCanExtend() {
-
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.Chihuahua();
- result = cfc.speak()
- warm = cfc.isWarmBlooded()
- name = cfc.getScientificName()
- results = cfc.getResults()
- """, context );
-
- // Polymorphism invokes overridden method
- assertThat( variables.get( Key.of( "result" ) ) ).isEqualTo( "Yip Yip!" );
- // inherited method from base class
- assertThat( variables.get( Key.of( "warm" ) ) ).isEqualTo( true );
- // Delegate to super.method() in parent class
- assertThat( variables.get( Key.of( "name" ) ) ).isEqualTo( "barkus annoyus Canis lupus Animal Kingdom" );
-
- // This array represents a specific order of operations that occur during the instantiation of our object hierachy
- // as well as specific values that need to be present to ensure correct behaviors
- assertThat( variables.getAsArray( Key.of( "results" ) ).toArray() ).isEqualTo( new Object[] {
- // top most super class is instantiated first. getCurrentTemplate() shows that file
- "animal pseudo Animal.cfc",
- // Then the next super class is instantiated. getCurrentTemplate() shows that file
- "Dog pseudo Dog.cfc",
- // The variables scope in the Doc pseudo constructor is the "same" variables scope as the Animal pseudo constructor that ran before it
- "dog sees variables.inAnimal as: true",
- // And lastly, the concrete class is instantiated. getCurrentTemplate() shows that file
- "Chihuahua pseudo Chihuahua.cfc",
- // I'm calling super.init() first, so animal inits first. getCurrentTemplate() shows the current class. INCOMPAT WITH CF which returns concrete
- // class!
- "Animal init Animal.cfc",
- // Then dog inits as we work backwards. getCurrentTemplate() shows the current class. INCOMPAT WITH CF which returns concrete class!
- "Dog init Dog.cfc",
- // Then the concrete class inits. getCurrentTemplate() shows the concrete class.
- "Chihuahua init Chihuahua.cfc",
- // A method inherited from a base class, sees "this" as the concrete class.
- "animal this is: src.test.java.TestCases.phase3.Chihuahua",
- // A method inherited from a base class, sees the top level "variables" scope.
- "animal sees inDog as: true",
- // A method delegated to as super.foo() sees "this" as the concrete class.
- "super animal sees: src.test.java.TestCases.phase3.Chihuahua",
- // A method delegated to as super.foo() sees the top level "variables" scope.
- "super sees inDog as: true",
- } );
-
- var cfc = variables.getAsClassRunnable( Key.of( "cfc" ) );
- var boxMeta = ( ClassMeta ) cfc.getBoxMeta();
- var meta = boxMeta.meta;
-
- assertThat( meta.get( Key.of( "name" ) ) ).isEqualTo( "src.test.java.TestCases.phase3.Chihuahua" );
-
- IStruct extendsMeta = meta.getAsStruct( Key.of( "extends" ) );
- assertThat( extendsMeta.getAsString( Key.of( "name" ) ).endsWith( ".Dog" ) ).isTrue();
-
- extendsMeta = extendsMeta.getAsStruct( Key.of( "extends" ) );
- assertThat( extendsMeta.getAsString( Key.of( "name" ) ).endsWith( ".Animal" ) ).isTrue();
-
- extendsMeta = extendsMeta.getAsStruct( Key.of( "extends" ) );
- assertThat( extendsMeta ).hasSize( 0 );
-
- }
-
- @DisplayName( "class as struct" )
- @Test
- public void testClassAsStruct() {
-
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.MyClass();
- result = isStruct( cfc )
- cfc.foo = "bar"
- result2 = structGet( "cfc.foo")
- keyArray = structKeyArray( cfc )
-
- """, context );
-
- assertThat( variables.get( result ) ).isEqualTo( true );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "bar" );
- assertThat( variables.get( Key.of( "keyArray" ) ) ).isInstanceOf( Array.class );
-
- }
-
- @Test
- void testJavaMeta() {
- // @formatter:off
- instance.executeSource(
- """
- jClass = createObject( "java", "java.lang.System" )
- result = jClass.$bx.meta
- clazz = jClass.$bx.$class
- println( clazz )
- """, context );
- // @formatter:on
- assertThat( variables.get( result ) ).isInstanceOf( IStruct.class );
- assertThat( variables.get( Key.of( "clazz" ) ) ).isEqualTo( System.class );
- }
-
- @Test
- public void testFunctionMeta() {
- // @formatter:off
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.FunctionMeta();
- result = cfc.$bx.meta
- println( result )
- """, context );
- // @formatter:on
- assertThat( variables.get( result ) ).isInstanceOf( IStruct.class );
- }
-
- @Test
- public void testSuperHeadlessFunctionInvocationToChild() {
-
- instance.executeSource(
- """
- request.calls = [];
- cfc = new src.test.java.TestCases.phase3.Child();
- result = request.calls;
- """, context );
-
- assertThat( variables.getAsArray( result ) ).hasSize( 2 );
- assertThat( variables.getAsArray( result ).get( 0 ) ).isEqualTo( "running child setupFrameworkDefaults()" );
- assertThat( variables.getAsArray( result ).get( 1 ) ).isEqualTo( "running parent setupFrameworkDefaults()" );
- }
-
- @Test
- public void testClassWrappedInScriptIsland() {
-
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.ClassWrappedInScript();
- """, context );
-
- }
-
- @Test
- public void testClassIgnoreLeadingComment() {
-
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.ClassLeadingComment();
- """, context );
-
- }
-
- @Test
- public void testClassIgnoreTrailingComment() {
-
- instance.executeSource(
- """
- cfc = new src.test.java.TestCases.phase3.ClassTrailingComment();
- """, context );
-
- }
-
- @Test
- public void testCFImport() {
-
- instance.executeSource(
- """
- foo = new src.test.java.TestCases.phase3.CFImportTest();
- foo.doSomething();
- """, context );
-
- }
-
- @Test
- public void testCFImport2() {
- // This version quotes the class being imported
- instance.executeSource(
- """
- foo = new src.test.java.TestCases.phase3.CFImportTest2();
- foo.doSomething();
- """, context );
-
- }
-
- @Test
- public void testInlineJavaImplements() {
- instance.executeSource(
- """
- import java:java.lang.Thread;
- jRunnable = new src.test.java.TestCases.phase3.JavaImplements();
- assert jRunnable instanceof "java.lang.Runnable"
- jThread = new java:Thread( jRunnable );
- jThread.start();
- """, context );
-
- }
-
- // disabling this as it causes a crazy concurrency issue with another test
- @Test
- @Disabled
- public void testInlineJavaExtendsASM() {
- instance.executeSource(
- """
- import java.util.Timer;
- myASMTask = new src.test.java.TestCases.asm.phase3.JavaExtendsAsm();
- assert myASMTask instanceof "java.util.TimerTask"
-
- jtimer = new Timer();
- jtimer.schedule(myASMTask, 1000);
- myASMTask.cancel()
- """, context );
-
- }
-
- @Test
- public void testInlineJavaExtendsField() {
- instance.executeSource(
- """
- myContext = new src.test.java.TestCases.phase3.JavaExtends2();
- assert myContext instanceof "ortus.boxlang.runtime.context.IBoxContext"
-
- println( myContext.getTemplatesYo() )
- """, context );
-
- }
-
- @Test
- public void testInlineJavaExtendsFieldPublic() {
- instance.executeSource(
- """
- myBIF = new src.test.java.TestCases.phase3.JavaExtends3();
- assert myBIF instanceof "ortus.boxlang.runtime.bifs.BIF"
- println( myBIF.__isMemberExecution )
- println( myBIF.runtime )
- myBIF.printStuff()
- """, context );
-
- }
-
- @Test
- public void testImplicitAccessor() {
- instance.executeSource(
- """
- clazz = new src.test.java.TestCases.phase3.ImplicitAccessor();
- clazz.name="brad";
- clazz.age=44;
- name = clazz.name;
- age = clazz.age;
- methodsCalled = clazz.getMethodsCalled();
- """, context );
- assertThat( variables.get( Key.of( "name" ) ) ).isEqualTo( "brad" );
- assertThat( variables.get( Key.of( "age" ) ) ).isEqualTo( 44 );
- assertThat( variables.get( Key.of( "methodsCalled" ) ) ).isEqualTo( "setNamesetAgegetNamegetAge" );
- }
-
- @Test
- public void testImplicitGeneratedAccessor() {
- instance.executeSource(
- """
- clazz = new src.test.java.TestCases.phase3.ImplicitGeneratedAccessor();
- clazz.name="brad";
- clazz.age=44;
- name = clazz.name;
- age = clazz.age;
- // prove they're going in the variable scope, not this scope
- keyExistsName = structKeyExists( clazz, "name")
- keyExistsAge = structKeyExists( clazz, "age")
- """, context );
- assertThat( variables.get( Key.of( "name" ) ) ).isEqualTo( "brad" );
- assertThat( variables.get( Key.of( "age" ) ) ).isEqualTo( 44 );
- assertThat( variables.get( Key.of( "keyExistsName" ) ) ).isEqualTo( false );
- assertThat( variables.get( Key.of( "keyExistsAge" ) ) ).isEqualTo( false );
- }
-
- @Test
- public void testStaticInstance() {
- instance.executeSource(
- """
- clazz = new src.test.java.TestCases.phase3.StaticTestCF();
- result1 = clazz.foo;
- result2 = clazz.myStaticFunc();
- result3 = clazz.myInstanceFunc();
- result4 = clazz.scoped;
- result5 = clazz.unscoped;
- result6 = clazz.again;
- """, context, BoxSourceType.BOXSCRIPT );
- assertThat( variables.get( Key.of( "result1" ) ) ).isEqualTo( 42 );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "static42" );
- assertThat( variables.get( Key.of( "result3" ) ) ).isEqualTo( "instancestatic42" );
- assertThat( variables.get( Key.of( "result4" ) ) ).isEqualTo( "brad" );
- assertThat( variables.get( Key.of( "result5" ) ) ).isEqualTo( "wood" );
- assertThat( variables.get( Key.of( "result6" ) ) ).isEqualTo( "luis" );
- }
-
- @Test
- @Disabled
- public void testStaticStatic() {
- instance.executeSource( """
- result1 = src.test.java.TestCases.phase3.StaticTest::foo;
- result2 = src.test.java.TestCases.phase3.StaticTest::myStaticFunc();
- result4 = src.test.java.TestCases.phase3.StaticTest::scoped;
- result5 = src.test.java.TestCases.phase3.StaticTest::unscoped;
- result6 = src.test.java.TestCases.phase3.StaticTest::again;
- myStaticUDF = src.test.java.TestCases.phase3.StaticTest::sayHello;
- result7 = myStaticUDF();
- result8 = src.test.java.TestCases.phase3.StaticTest::123;
- """, context, BoxSourceType.BOXSCRIPT );
- assertThat( variables.get( Key.of( "result1" ) ) ).isEqualTo( 9000 );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "static9000" );
- assertThat( variables.get( Key.of( "result4" ) ) ).isEqualTo( "brad" );
- assertThat( variables.get( Key.of( "result5" ) ) ).isEqualTo( "wood" );
- assertThat( variables.get( Key.of( "result6" ) ) ).isEqualTo( "luis" );
- assertThat( variables.get( Key.of( "result7" ) ) ).isEqualTo( "Hello" );
- assertThat( variables.get( Key.of( "result8" ) ) ).isEqualTo( 456 );
- }
-
- @Test
- public void testStaticInstanceCF() {
- instance.executeSource(
- """
- clazz = new src.test.java.TestCases.phase3.StaticTestCF();
- result1 = clazz.foo;
- result2 = clazz.myStaticFunc();
- result3 = clazz.myInstanceFunc();
- result4 = clazz.scoped;
- result5 = clazz.unscoped;
- result6 = clazz.again;
- """, context, BoxSourceType.CFSCRIPT );
- assertThat( variables.get( Key.of( "result1" ) ) ).isEqualTo( 42 );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "static42" );
- assertThat( variables.get( Key.of( "result3" ) ) ).isEqualTo( "instancestatic42" );
- assertThat( variables.get( Key.of( "result4" ) ) ).isEqualTo( "brad" );
- assertThat( variables.get( Key.of( "result5" ) ) ).isEqualTo( "wood" );
- assertThat( variables.get( Key.of( "result6" ) ) ).isEqualTo( "luis" );
- }
-
- @Test
- @Disabled
- public void testStaticStaticCF() {
- instance.executeSource(
- """
- result1 = src.test.java.TestCases.phase3.StaticTest::foo;
- result2 = src.test.java.TestCases.phase3.StaticTest::myStaticFunc();
- result4 = src.test.java.TestCases.phase3.StaticTest::scoped;
- result5 = src.test.java.TestCases.phase3.StaticTest::unscoped;
- result6 = src.test.java.TestCases.phase3.StaticTest::again;
- result7 = src.test.java.TestCases.phase3.StaticTest::123;
- """, context, BoxSourceType.CFSCRIPT );
- assertThat( variables.get( Key.of( "result1" ) ) ).isEqualTo( 9000 );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "static9000" );
- assertThat( variables.get( Key.of( "result4" ) ) ).isEqualTo( "brad" );
- assertThat( variables.get( Key.of( "result5" ) ) ).isEqualTo( "wood" );
- assertThat( variables.get( Key.of( "result6" ) ) ).isEqualTo( "luis" );
- assertThat( variables.get( Key.of( "result7" ) ) ).isEqualTo( 456 );
- }
-
- @Test
- @Disabled
- public void testStaticImport() {
- instance.executeSource(
- """
- import src.test.java.TestCases.phase3.StaticTest;
-
- result1 = StaticTest::foo;
- result2 = StaticTest::myStaticFunc();
- result4 = StaticTest::scoped;
- result5 = StaticTest::unscoped;
- result6 = StaticTest::again;
- """, context, BoxSourceType.BOXSCRIPT );
- assertThat( variables.get( Key.of( "result1" ) ) ).isEqualTo( 9000 );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "static9000" );
- assertThat( variables.get( Key.of( "result4" ) ) ).isEqualTo( "brad" );
- assertThat( variables.get( Key.of( "result5" ) ) ).isEqualTo( "wood" );
- assertThat( variables.get( Key.of( "result6" ) ) ).isEqualTo( "luis" );
- }
-
- @Test
- @Disabled
- public void testStaticImportDot() {
- instance.executeSource(
- """
- import src.test.java.TestCases.phase3.StaticTest;
-
- result1 = StaticTest.foo;
- result2 = StaticTest.myStaticFunc();
- result4 = StaticTest.scoped;
- result5 = StaticTest.unscoped;
- result6 = StaticTest.again;
- // instance
- myInstance = new StaticTest();
- result7 = myInstance.foo;
- result8 = StaticTest.foo;
- result9 = myInstance.myInstanceFunc2()
- """, context, BoxSourceType.BOXSCRIPT );
- assertThat( variables.get( Key.of( "result1" ) ) ).isEqualTo( 9000 );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "static9000" );
- assertThat( variables.get( Key.of( "result4" ) ) ).isEqualTo( "brad" );
- assertThat( variables.get( Key.of( "result5" ) ) ).isEqualTo( "wood" );
- assertThat( variables.get( Key.of( "result6" ) ) ).isEqualTo( "luis" );
- assertThat( variables.get( Key.of( "result7" ) ) ).isEqualTo( 42 );
- assertThat( variables.get( Key.of( "result8" ) ) ).isEqualTo( 42 );
- assertThat( variables.get( Key.of( "result9" ) ) ).isInstanceOf( Array.class );
- Array result9 = variables.getAsArray( Key.of( "result9" ) );
- assertThat( result9.size() ).isEqualTo( 3 );
- assertThat( result9.get( 0 ) ).isEqualTo( "brad" );
- assertThat( result9.get( 1 ) ).isEqualTo( "wood" );
- assertThat( result9.get( 2 ) ).isEqualTo( 42 );
- }
-
- @Test
- public void testDotExtends() {
- instance.executeSource(
- """
- clazz = new src.test.java.TestCases.phase3.DotExtends();
- result = clazz.childUDF()
- """, context );
- assertThat( variables.get( result ) ).isEqualTo( "childUDFparent" );
- }
-
- @Test
- public void testRelativeInstantiation() {
- instance.executeSource(
- """
- clazz = new src.test.java.TestCases.phase3.RelativeInstantiation();
- result = clazz.findSibling()
- """, context );
- assertThat( variables.get( result ) ).isEqualTo( "bar" );
- }
-
- @Test
- public void testAbstractClass() {
- Throwable t = assertThrows( AbstractClassException.class, () -> instance.executeSource(
- """
- clazz = new src.test.java.TestCases.phase3.AbstractClass();
- """, context ) );
- assertThat( t.getMessage() ).contains( "Cannot instantiate an abstract class" );
-
- instance.executeSource(
- """
- clazz = new src.test.java.TestCases.phase3.ConcreteClass();
- result1 = clazz.normal()
- result2 = clazz.abstractMethod()
- """, context );
- assertThat( variables.get( Key.of( "result1" ) ) ).isEqualTo( "normal" );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "abstractMethod" );
- }
-
- @Test
- public void testAbstractClassCF() {
- Throwable t = assertThrows( AbstractClassException.class, () -> instance.executeSource(
- """
- clazz = new src.test.java.TestCases.phase3.AbstractClassCF();
- """, context ) );
- assertThat( t.getMessage() ).contains( "Cannot instantiate an abstract class" );
-
- instance.executeSource(
- """
- clazz = new src.test.java.TestCases.phase3.ConcreteClassCF();
- result1 = clazz.normal()
- result2 = clazz.abstractMethod()
- """, context );
- assertThat( variables.get( Key.of( "result1" ) ) ).isEqualTo( "normal" );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "abstractMethod" );
- }
-
- @Test
- public void testCFGetterType() {
- instance.executeSource(
- """
- clazz = new src.test.java.TestCases.phase3.GetterTest();
- result = clazz.getMyDate()
- """, context );
- assertThat( variables.get( result ) ).isEqualTo( "" );
- }
-
- @Test
- public void testGetterOverrideInParent() {
- instance.executeSource(
- """
- clazz = new src.test.java.TestCases.phase3.GeneratedGetterChild();
- result = clazz.getFoo()
- """, context );
- assertThat( variables.get( result ) ).isEqualTo( "overriden" );
- }
-
- @Test
- public void testFinalClass() {
- instance.executeSource(
- """
- clazz = new src.test.java.TestCases.phase3.FinalClass();
- """, context );
- Throwable t = assertThrows( BoxRuntimeException.class,
- () -> instance.executeSource(
- """
- clazz = new src.test.java.TestCases.phase3.IllegalFinalExtends();
- """, context ) );
- assertThat( t.getMessage() ).contains( "Cannot extend final class" );
- }
-
-}
diff --git a/src/test/java/TestCases/asm/phase3/ClassTrailingComment.cfc b/src/test/java/TestCases/asm/phase3/ClassTrailingComment.cfc
deleted file mode 100644
index a7606f5f0..000000000
--- a/src/test/java/TestCases/asm/phase3/ClassTrailingComment.cfc
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/src/test/java/TestCases/asm/phase3/ClassWrappedInScript.cfc b/src/test/java/TestCases/asm/phase3/ClassWrappedInScript.cfc
deleted file mode 100644
index 813fa9c83..000000000
--- a/src/test/java/TestCases/asm/phase3/ClassWrappedInScript.cfc
+++ /dev/null
@@ -1,4 +0,0 @@
-
- component {
- }
-
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/ConcreteClass.bx b/src/test/java/TestCases/asm/phase3/ConcreteClass.bx
deleted file mode 100644
index da881c5b8..000000000
--- a/src/test/java/TestCases/asm/phase3/ConcreteClass.bx
+++ /dev/null
@@ -1,6 +0,0 @@
-class extends="AbstractClass" {
-
- function abstractMethod() {
- return "abstractMethod";
- }
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/ConcreteClassCF.cfc b/src/test/java/TestCases/asm/phase3/ConcreteClassCF.cfc
deleted file mode 100644
index 06b946605..000000000
--- a/src/test/java/TestCases/asm/phase3/ConcreteClassCF.cfc
+++ /dev/null
@@ -1,6 +0,0 @@
-component extends="AbstractClassCF" {
-
- function abstractMethod() {
- return "abstractMethod";
- }
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/Dog.cfc b/src/test/java/TestCases/asm/phase3/Dog.cfc
deleted file mode 100644
index efdc62ab0..000000000
--- a/src/test/java/TestCases/asm/phase3/Dog.cfc
+++ /dev/null
@@ -1,20 +0,0 @@
-component extends="Animal" {
- results.append('Dog pseudo ' & getFileFromPath( getCurrentTemplatePath()))
- variables.inDog = true;
- // Our variables scope contains the variables from the parent component
- results.append( "dog sees variables.inAnimal as: " & variables.inAnimal )
-
- function init() {
- super.init();
- results.append('Dog init ' & getFileFromPath( getCurrentTemplatePath()))
- }
-
- function speak() {
- return "Woof!";
- }
-
- function getScientificName() {
- return "Canis lupus " & super.getScientificName();
- }
-
- }
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/DotExtends.cfc b/src/test/java/TestCases/asm/phase3/DotExtends.cfc
deleted file mode 100644
index 28111cff1..000000000
--- a/src/test/java/TestCases/asm/phase3/DotExtends.cfc
+++ /dev/null
@@ -1,5 +0,0 @@
-component extends="../../TestCases/phase3/DotExtendsParent" {
- function childUDF() {
- return "childUDF" & super.parentUDF();
- }
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/DotExtendsParent.cfc b/src/test/java/TestCases/asm/phase3/DotExtendsParent.cfc
deleted file mode 100644
index 55b42456b..000000000
--- a/src/test/java/TestCases/asm/phase3/DotExtendsParent.cfc
+++ /dev/null
@@ -1,5 +0,0 @@
-component {
- function parentUDF() {
- return "parent";
- }
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/ExceptionTest.java b/src/test/java/TestCases/asm/phase3/ExceptionTest.java
deleted file mode 100644
index 80b28b71b..000000000
--- a/src/test/java/TestCases/asm/phase3/ExceptionTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.phase3;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-
-public class ExceptionTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
- static Key foo = new Key( "foo" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @Test
- public void testBoxMeta() {
-
- instance.executeStatement(
- """
- include "src/test/java/TestCases/phase3/ExceptionThrower.cfs";
- """, context );
-
- assertThat( "" ).isEqualTo( "" );
-
- }
-
-}
diff --git a/src/test/java/TestCases/asm/phase3/ExceptionThrower.cfs b/src/test/java/TestCases/asm/phase3/ExceptionThrower.cfs
deleted file mode 100644
index 9bb637d16..000000000
--- a/src/test/java/TestCases/asm/phase3/ExceptionThrower.cfs
+++ /dev/null
@@ -1,6 +0,0 @@
-try {
- 1/0
-} catch( any e ) {
- e.printStackTrace()
- println( e.tagContext )
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/FinalClass.bx b/src/test/java/TestCases/asm/phase3/FinalClass.bx
deleted file mode 100644
index dc3b92ed8..000000000
--- a/src/test/java/TestCases/asm/phase3/FinalClass.bx
+++ /dev/null
@@ -1,5 +0,0 @@
-final class {
-
- final this.CONSTANT = "constant";
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/FindMe.bx b/src/test/java/TestCases/asm/phase3/FindMe.bx
deleted file mode 100644
index 9394e50f5..000000000
--- a/src/test/java/TestCases/asm/phase3/FindMe.bx
+++ /dev/null
@@ -1,5 +0,0 @@
-class {
- function foo() {
- return "bar";
- }
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/FunctionMeta.cfc b/src/test/java/TestCases/asm/phase3/FunctionMeta.cfc
deleted file mode 100644
index 1376b2f56..000000000
--- a/src/test/java/TestCases/asm/phase3/FunctionMeta.cfc
+++ /dev/null
@@ -1,16 +0,0 @@
-component {
-
- /**
- * The bit that can be used to set all tasks created by this scheduler to always run on one server
- */
- property name="serverFixation" type="boolean";
-
- /**
- * This is my function hint
- * @brad wood
- * @param1.luis majano
- */
- function foo( param1 ) {
-
- }
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/GeneratedGetterChild.bx b/src/test/java/TestCases/asm/phase3/GeneratedGetterChild.bx
deleted file mode 100644
index 015a3cdaa..000000000
--- a/src/test/java/TestCases/asm/phase3/GeneratedGetterChild.bx
+++ /dev/null
@@ -1,2 +0,0 @@
-class accessors=true extends="GeneratedGetterParent" {
-}
diff --git a/src/test/java/TestCases/asm/phase3/GeneratedGetterParent.bx b/src/test/java/TestCases/asm/phase3/GeneratedGetterParent.bx
deleted file mode 100644
index 80852e652..000000000
--- a/src/test/java/TestCases/asm/phase3/GeneratedGetterParent.bx
+++ /dev/null
@@ -1,9 +0,0 @@
-class accessors=true {
-
- property name="foo" type=string default="default value";
-
- // overridden getter
- string function getFoo() {
- return "overriden";
- }
-}
diff --git a/src/test/java/TestCases/asm/phase3/GetterTest.cfc b/src/test/java/TestCases/asm/phase3/GetterTest.cfc
deleted file mode 100644
index b85cf9750..000000000
--- a/src/test/java/TestCases/asm/phase3/GetterTest.cfc
+++ /dev/null
@@ -1,10 +0,0 @@
-component accessors="true" {
-
- property name="myDate" type="date";
-
- function init() {
- variables.myDate = "";
- }
-
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/IBicycle.bx b/src/test/java/TestCases/asm/phase3/IBicycle.bx
deleted file mode 100644
index a67cdd373..000000000
--- a/src/test/java/TestCases/asm/phase3/IBicycle.bx
+++ /dev/null
@@ -1,11 +0,0 @@
-interface {
-
- public String function pedal( required numeric speed=3 );
-
- function pedalLax( speed );
-
- default function hasInnerTube() {
- return true;
- }
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/IChildInterface.bx b/src/test/java/TestCases/asm/phase3/IChildInterface.bx
deleted file mode 100644
index c746358a5..000000000
--- a/src/test/java/TestCases/asm/phase3/IChildInterface.bx
+++ /dev/null
@@ -1,9 +0,0 @@
-interface extends="IParentInterface" {
- default function childDefaultMethod() {
- return "childDefaultMethod";
- }
- default function parentOverrideMe() {
- return "parentOverrideMeChild";
- }
- function childMethod();
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/IMotorcycle.bx b/src/test/java/TestCases/asm/phase3/IMotorcycle.bx
deleted file mode 100644
index a3aa0c08d..000000000
--- a/src/test/java/TestCases/asm/phase3/IMotorcycle.bx
+++ /dev/null
@@ -1,9 +0,0 @@
-interface {
-
- function shift( required numeric gear );
-
- default function needsFuel() {
- return false;
- }
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/IMultiChildInterface.bx b/src/test/java/TestCases/asm/phase3/IMultiChildInterface.bx
deleted file mode 100644
index d73790082..000000000
--- a/src/test/java/TestCases/asm/phase3/IMultiChildInterface.bx
+++ /dev/null
@@ -1,12 +0,0 @@
-interface extends="IParentInterface,IUncleInterface" {
- default function childDefaultMethod() {
- return "childDefaultMethod";
- }
- default function parentOverrideMe() {
- return "parentOverrideMeChild";
- }
- default function uncleOverrideMe() {
- return "uncleOverrideMeChild";
- }
- function childMethod();
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/IParentInterface.bx b/src/test/java/TestCases/asm/phase3/IParentInterface.bx
deleted file mode 100644
index 4f3a973b8..000000000
--- a/src/test/java/TestCases/asm/phase3/IParentInterface.bx
+++ /dev/null
@@ -1,12 +0,0 @@
-interface {
- default function parentDefaultMethod() {
- return "parentDefaultMethod";
- }
- default function parentOverrideMe() {
- return "parentOverrideMeParent";
- }
- default function parentOverrideMe2() {
- return "parentOverrideMeParent2";
- }
- function parentMethod();
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/IUncleInterface.bx b/src/test/java/TestCases/asm/phase3/IUncleInterface.bx
deleted file mode 100644
index c05e1f421..000000000
--- a/src/test/java/TestCases/asm/phase3/IUncleInterface.bx
+++ /dev/null
@@ -1,12 +0,0 @@
-interface {
- default function uncleDefaultMethod() {
- return "uncleDefaultMethod";
- }
- default function uncleOverrideMe() {
- return "uncleOverrideMeUncle";
- }
- default function uncleOverrideMe2() {
- return "uncleOverrideMeUncle2";
- }
- function uncleMethod();
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/IllegalFinalExtends.bx b/src/test/java/TestCases/asm/phase3/IllegalFinalExtends.bx
deleted file mode 100644
index 1442a25b7..000000000
--- a/src/test/java/TestCases/asm/phase3/IllegalFinalExtends.bx
+++ /dev/null
@@ -1,3 +0,0 @@
-class extends=FinalClass {
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/ImplicitAccessor.bx b/src/test/java/TestCases/asm/phase3/ImplicitAccessor.bx
deleted file mode 100644
index fc2af56a6..000000000
--- a/src/test/java/TestCases/asm/phase3/ImplicitAccessor.bx
+++ /dev/null
@@ -1,29 +0,0 @@
-class invokeImplicitAccessor=true {
- property string name;
- property integer age;
-
- methodsCalled = "";
- function getName() {
- methodsCalled &= "getName";
- return variables.name;
- }
-
- function setName(string name) {
- methodsCalled &= "setName";
- variables.name = name;
- }
-
- function getAge() {
- methodsCalled &= "getAge";
- return variables.age;
- }
-
- function setAge(integer age) {
- methodsCalled &= "setAge";
- variables.age = age;
- }
-
- function getMethodsCalled() {
- return methodsCalled;
- }
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/ImplicitConstructorTest.cfc b/src/test/java/TestCases/asm/phase3/ImplicitConstructorTest.cfc
deleted file mode 100644
index 4186eec1b..000000000
--- a/src/test/java/TestCases/asm/phase3/ImplicitConstructorTest.cfc
+++ /dev/null
@@ -1,6 +0,0 @@
-component accessors=true {
- property name="name";
- property name="age";
- property name="favoriteColor";
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/ImplicitGeneratedAccessor.bx b/src/test/java/TestCases/asm/phase3/ImplicitGeneratedAccessor.bx
deleted file mode 100644
index 9e6d5e274..000000000
--- a/src/test/java/TestCases/asm/phase3/ImplicitGeneratedAccessor.bx
+++ /dev/null
@@ -1,5 +0,0 @@
-class invokeImplicitAccessor=true accessors=true {
- property string name;
- property integer age;
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/InitMethodTest.bx b/src/test/java/TestCases/asm/phase3/InitMethodTest.bx
deleted file mode 100644
index 60a656d12..000000000
--- a/src/test/java/TestCases/asm/phase3/InitMethodTest.bx
+++ /dev/null
@@ -1,9 +0,0 @@
-class initMethod=birth accessors=true {
- property inittedProperly default=false;
- function init() {
- throw "you'd better not call me!";
- }
- function birth() {
- inittedProperly=true
- }
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/InterfaceInheritenceTest.bx b/src/test/java/TestCases/asm/phase3/InterfaceInheritenceTest.bx
deleted file mode 100644
index 1abcc38b4..000000000
--- a/src/test/java/TestCases/asm/phase3/InterfaceInheritenceTest.bx
+++ /dev/null
@@ -1,11 +0,0 @@
-class implements="IChildInterface" {
-
- public Any function childMethod() {
- return "childMethod";
- }
-
- public Any function parentMethod() {
- return "parentMethod";
- }
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/InterfaceMultiInheritenceTest.bx b/src/test/java/TestCases/asm/phase3/InterfaceMultiInheritenceTest.bx
deleted file mode 100644
index 74c0dedf9..000000000
--- a/src/test/java/TestCases/asm/phase3/InterfaceMultiInheritenceTest.bx
+++ /dev/null
@@ -1,23 +0,0 @@
-class implements="IMultiChildInterface" {
-
- public Any function childMethod() {
- return "childMethod";
- }
-
- public Any function parentMethod() {
- return "parentMethod";
- }
-
- public Any function uncleMethod() {
- return "uncleMethod";
- }
-
- default function parentOverrideMe2() {
- return "parentOverrideMe2Class";
- }
-
- default function uncleOverrideMe2() {
- return "uncleOverrideMe2Class";
- }
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/InterfaceStatic.bx b/src/test/java/TestCases/asm/phase3/InterfaceStatic.bx
deleted file mode 100644
index 3c9e628e0..000000000
--- a/src/test/java/TestCases/asm/phase3/InterfaceStatic.bx
+++ /dev/null
@@ -1,16 +0,0 @@
-interface {
-
- static {
- static.myVar = "brad";
- yourVar = "luis";
- }
-
- static function foo() {
- return static.myVar;
- }
-
- static function callStatic() {
- return foo();
- }
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/InterfaceTest.java b/src/test/java/TestCases/asm/phase3/InterfaceTest.java
deleted file mode 100644
index 167dd863d..000000000
--- a/src/test/java/TestCases/asm/phase3/InterfaceTest.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/**
- * [BoxLang]
- *
- * Copyright [2023] [Ortus Solutions, Corp]
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package TestCases.asm.phase3;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ortus.boxlang.compiler.parser.BoxSourceType;
-import ortus.boxlang.runtime.BoxRuntime;
-import ortus.boxlang.runtime.context.IBoxContext;
-import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
-import ortus.boxlang.runtime.interop.DynamicObject;
-import ortus.boxlang.runtime.runnables.BoxInterface;
-import ortus.boxlang.runtime.runnables.RunnableLoader;
-import ortus.boxlang.runtime.scopes.IScope;
-import ortus.boxlang.runtime.scopes.Key;
-import ortus.boxlang.runtime.scopes.VariablesScope;
-
-public class InterfaceTest {
-
- static BoxRuntime instance;
- IBoxContext context;
- IScope variables;
- static Key result = new Key( "result" );
- static Key foo = new Key( "foo" );
-
- @BeforeAll
- public static void setUp() {
- instance = BoxRuntime.getInstance( true );
- }
-
- @AfterAll
- public static void teardown() {
-
- }
-
- @BeforeEach
- public void setupEach() {
- context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
- variables = context.getScopeNearby( VariablesScope.name );
- instance.useASMBoxPiler();
- }
-
- @AfterEach
- public void teardownEach() {
- // instance.useJavaBoxpiler();
- }
-
- @DisplayName( "basic CF interface" )
- @Test
- public void testBasicCFInterface() {
-
- BoxInterface inter = ( BoxInterface ) DynamicObject.of( RunnableLoader.getInstance().loadClass(
- """
- /**
- * This is my interface description
- *
- * @brad wood
- * @luis
- */
- interface singleton gavin="pickin" inject foo="bar" {
-
- function init();
-
- function foo();
-
- private function bar();
-
- default function myDefaultMethod() {
- return this.foo();
- }
-
- }
-
- """, context, BoxSourceType.CFSCRIPT ), context ).unWrapBoxLangClass();
-
- assertThat( inter.getMetaData().get( Key.of( "type" ) ) ).isEqualTo( "Interface" );
- assertThat( inter.getMetaData().getAsArray( Key.of( "functions" ) ) ).hasSize( 4 );
-
- }
-
- @DisplayName( "basic interface file CF" )
- @Test
- public void testBasicInterfaceFileCF() {
-
- instance.executeStatement(
- """
- result = createObject( "component", "src.test.java.TestCases.phase3.MyInterfaceCF" );
- """, context );
- assertThat( variables.get( result ) ).isInstanceOf( BoxInterface.class );
- BoxInterface inter = variables.getAsBoxInterface( result );
- assertThat( inter.getMetaData().get( Key.of( "type" ) ) ).isEqualTo( "Interface" );
- assertThat( inter.getMetaData().getAsArray( Key.of( "functions" ) ) ).hasSize( 4 );
-
- }
-
- @DisplayName( "basic interface file BL" )
- @Test
- public void testBasicInterfaceFileBL() {
-
- instance.executeStatement(
- """
- result = createObject( "component", "src.test.java.TestCases.phase3.MyInterfaceBL" );
- """, context );
- assertThat( variables.get( result ) ).isInstanceOf( BoxInterface.class );
- BoxInterface inter = variables.getAsBoxInterface( result );
- assertThat( inter.getMetaData().get( Key.of( "type" ) ) ).isEqualTo( "Interface" );
- assertThat( inter.getMetaData().getAsArray( Key.of( "functions" ) ) ).hasSize( 4 );
-
- }
-
- @DisplayName( "basic interface file CF Tag" )
- @Test
- public void testBasicClassFileCFTag() {
-
- instance.executeStatement(
- """
- result = createObject( "component", "src.test.java.TestCases.phase3.MyInterfaceCFTag" );
- """, context );
- assertThat( variables.get( result ) ).isInstanceOf( BoxInterface.class );
- BoxInterface inter = variables.getAsBoxInterface( result );
- assertThat( inter.getMetaData().get( Key.of( "type" ) ) ).isEqualTo( "Interface" );
- assertThat( inter.getMetaData().getAsArray( Key.of( "functions" ) ) ).hasSize( 4 );
-
- }
-
- @DisplayName( "moped example" )
- @Test
- public void testMopedExample() {
-
- instance.executeStatement(
- """
- boxClass = new src.test.java.TestCases.phase3.Moped();
-
- // implemented method from IBicycle
- result1 = boxClass.pedal( 3 )
- // impelemented method from IMotorcycle
- result2 = boxClass.shift( 4 )
- // Default method from IBicycle
- result3 = boxClass.hasInnerTube()
- // Default method from IMotorcycle but overridden by moped
- result4 = boxClass.needsFuel()
- """, context );
- assertThat( variables.get( Key.of( "result1" ) ) ).isEqualTo( "Pedal speed 3" );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "Shift to gear 4" );
- assertThat( variables.get( Key.of( "result3" ) ) ).isEqualTo( true );
- assertThat( variables.get( Key.of( "result4" ) ) ).isEqualTo( true );
- }
-
- @DisplayName( "onMissingMethod example" )
- @Test
- public void testOnMissingMethod() {
-
- instance.executeStatement(
- """
- boxClass = new src.test.java.TestCases.phase3.WheeledThing();
-
- // implemented method from IBicycle
- result1 = boxClass.pedal( 3 )
- // impelemented method from IMotorcycle
- result2 = boxClass.shift( 4 )
- // Default method from IBicycle
- result3 = boxClass.hasInnerTube()
- // Default method from IMotorcycle but overridden by moped
- result4 = boxClass.needsFuel()
- """, context );
- assertThat( variables.get( Key.of( "result1" ) ) ).isEqualTo( "Pedal speed 3" );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "Shift to gear 4" );
- assertThat( variables.get( Key.of( "result3" ) ) ).isEqualTo( true );
- assertThat( variables.get( Key.of( "result4" ) ) ).isEqualTo( false );
-
- }
-
- @DisplayName( "interface inheritence example" )
- @Test
- public void testInterfaceInheritence() {
-
- instance.executeStatement(
- """
- boxClass = new src.test.java.TestCases.phase3.InterfaceInheritenceTest();
- result1 = boxClass.childMethod()
- result2 = boxClass.parentMethod()
- result3 = boxClass.childDefaultMethod()
- result4 = boxClass.parentDefaultMethod()
- result5 = boxClass.parentOverrideMe()
- assert boxClass instanceof "InterfaceInheritenceTest";
- assert boxClass instanceof "IChildInterface";
- assert boxClass instanceof "IParentInterface";
- """, context );
-
- assertThat( variables.get( Key.of( "result1" ) ) ).isEqualTo( "childMethod" );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "parentMethod" );
- assertThat( variables.get( Key.of( "result3" ) ) ).isEqualTo( "childDefaultMethod" );
- assertThat( variables.get( Key.of( "result4" ) ) ).isEqualTo( "parentDefaultMethod" );
- assertThat( variables.get( Key.of( "result5" ) ) ).isEqualTo( "parentOverrideMeChild" );
- }
-
- @DisplayName( "interface multi-inheritence example" )
- @Test
- public void testInterfaceMultiInheritence() {
-
- instance.executeStatement(
- """
- boxClass = new src.test.java.TestCases.phase3.InterfaceMultiInheritenceTest();
- result1 = boxClass.childMethod()
- result2 = boxClass.parentMethod()
- result3 = boxClass.uncleMethod()
- result4 = boxClass.childDefaultMethod()
- result5 = boxClass.parentDefaultMethod()
- result6 = boxClass.uncleDefaultMethod()
- result7 = boxClass.parentOverrideMe()
- result8 = boxClass.uncleOverrideMe()
- result9 = boxClass.parentOverrideMe2()
- result10 = boxClass.uncleOverrideMe2()
- assert boxClass instanceof "InterfaceMultiInheritenceTest";
- assert boxClass instanceof "IMultiChildInterface";
- assert boxClass instanceof "IParentInterface";
- assert boxClass instanceof "IUncleInterface";
- // println( createOBject("src.test.java.TestCases.phase3.IMultiChildInterface" ).$bx.invokeTargetMethod( getBoxContext(), "getMetaData", [].toArray() ) )
- """,
- context );
-
- assertThat( variables.get( Key.of( "result1" ) ) ).isEqualTo( "childMethod" );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "parentMethod" );
- assertThat( variables.get( Key.of( "result3" ) ) ).isEqualTo( "uncleMethod" );
- assertThat( variables.get( Key.of( "result4" ) ) ).isEqualTo( "childDefaultMethod" );
- assertThat( variables.get( Key.of( "result5" ) ) ).isEqualTo( "parentDefaultMethod" );
- assertThat( variables.get( Key.of( "result6" ) ) ).isEqualTo( "uncleDefaultMethod" );
- assertThat( variables.get( Key.of( "result7" ) ) ).isEqualTo( "parentOverrideMeChild" );
- assertThat( variables.get( Key.of( "result8" ) ) ).isEqualTo( "uncleOverrideMeChild" );
- assertThat( variables.get( Key.of( "result9" ) ) ).isEqualTo( "parentOverrideMe2Class" );
- assertThat( variables.get( Key.of( "result10" ) ) ).isEqualTo( "uncleOverrideMe2Class" );
-
- }
-
- @DisplayName( "interface inheritence static" )
- @Test
- public void testInterfaceStatic() {
-
- instance.executeStatement(
- """
- import src.test.java.TestCases.phase3.InterfaceStatic as ist;
- result1 = ist.foo()
- result2 = ist.myVar;
- result3 = ist.yourVar;
- result4 = ist.callStatic();
- result5 = ist::yourVar;
- result6 = ist::callStatic();
- result7 = src.test.java.TestCases.phase3.InterfaceStatic::yourVar;
- result8 = src.test.java.TestCases.phase3.InterfaceStatic::callStatic();
- """, context );
- assertThat( variables.get( Key.of( "result1" ) ) ).isEqualTo( "brad" );
- assertThat( variables.get( Key.of( "result2" ) ) ).isEqualTo( "brad" );
- assertThat( variables.get( Key.of( "result3" ) ) ).isEqualTo( "luis" );
- assertThat( variables.get( Key.of( "result4" ) ) ).isEqualTo( "brad" );
- assertThat( variables.get( Key.of( "result5" ) ) ).isEqualTo( "luis" );
- assertThat( variables.get( Key.of( "result6" ) ) ).isEqualTo( "brad" );
- assertThat( variables.get( Key.of( "result7" ) ) ).isEqualTo( "luis" );
- assertThat( variables.get( Key.of( "result8" ) ) ).isEqualTo( "brad" );
-
- }
-
-}
diff --git a/src/test/java/TestCases/asm/phase3/JavaExtends2.bx b/src/test/java/TestCases/asm/phase3/JavaExtends2.bx
deleted file mode 100644
index 673799e63..000000000
--- a/src/test/java/TestCases/asm/phase3/JavaExtends2.bx
+++ /dev/null
@@ -1,7 +0,0 @@
-class extends="java:ortus.boxlang.runtime.context.BaseBoxContext" {
-
- function getTemplatesYo() {
- return super.templates;
- }
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/JavaExtends3.bx b/src/test/java/TestCases/asm/phase3/JavaExtends3.bx
deleted file mode 100644
index 2aef9391f..000000000
--- a/src/test/java/TestCases/asm/phase3/JavaExtends3.bx
+++ /dev/null
@@ -1,14 +0,0 @@
-class extends="java:ortus.boxlang.runtime.bifs.BIF" {
-
- @overrideJava
- Object function _invoke(ortus.boxlang.runtime.context.IBoxContext c ,ortus.boxlang.runtime.scopes.ArgumentsScope args) {
-
- }
-
- function printStuff() {
- println( this.__isMemberExecution )
- println( this.runtime )
- println( super.__isMemberExecution )
- println( super.runtime )
- }
-}
diff --git a/src/test/java/TestCases/asm/phase3/JavaExtendsAsm.bx b/src/test/java/TestCases/asm/phase3/JavaExtendsAsm.bx
deleted file mode 100644
index 09ca312d3..000000000
--- a/src/test/java/TestCases/asm/phase3/JavaExtendsAsm.bx
+++ /dev/null
@@ -1,16 +0,0 @@
-class extends="java:java.util.TimerTask" {
-
-
-
- @overrideJava
- void function run() {
- println("Hello from a custom TimerTask!" );
- println( super.scheduledExecutionTime() );
- }
-
- @overrideJava
- public long function scheduledExecutionTime() {
- throw "no, not me!";
- }
-
-}
diff --git a/src/test/java/TestCases/asm/phase3/JavaImplements.bx b/src/test/java/TestCases/asm/phase3/JavaImplements.bx
deleted file mode 100644
index ba69db7f7..000000000
--- a/src/test/java/TestCases/asm/phase3/JavaImplements.bx
+++ /dev/null
@@ -1,7 +0,0 @@
-class implements="java:java.lang.Runnable" {
-
- function run() {
- println("Hello from a thread!");
- }
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/Moped.bx b/src/test/java/TestCases/asm/phase3/Moped.bx
deleted file mode 100644
index 7816cd1f4..000000000
--- a/src/test/java/TestCases/asm/phase3/Moped.bx
+++ /dev/null
@@ -1,20 +0,0 @@
-class implements="IBicycle,IMotorcycle" {
-
- String function pedal( required numeric speed=3 ) {
- return "Pedal speed #speed#"
- }
-
- // This overachieving mehod has more details than the interfaces requires
- Boolean function pedalLax( required numeric speed=3 ) {
- }
-
- public Any function shift(required numeric gear) {
- return "Shift to gear #gear#"
- }
-
- @Override
- default function needsFuel() {
- return true;
- }
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/MyClass.bx b/src/test/java/TestCases/asm/phase3/MyClass.bx
deleted file mode 100644
index 35a26f027..000000000
--- a/src/test/java/TestCases/asm/phase3/MyClass.bx
+++ /dev/null
@@ -1,50 +0,0 @@
-// get foo
-import foo;
-// get system
-import java.lang.System;
-
-/**
- * This is my class description
- * continued on this line
- *
- * and this one
- * as well.
- *
- * @brad wood
- * @luis
- */
-@foo "bar"
-class singleton gavin="pickin" inject {
-
- property name;
-
- variables.setup=true; // ending comment
- System.out.println( "word" );
- request.foo="bar";
- isInitted = false;
- println( "current template is " & getCurrentTemplatePath() );
- printLn( foo() )
-
- // my init func
- function init() {
- isInitted = true;
- }
-
- function foo() {
- /* return this value */
- return "I work! #bar()# #variables.setup# #setup# #request.foo# #isInitted#";
- }
-
- private function bar() {
- return "whee";
- }
-
- function getThis() {
- return this;
- }
-
- function runThisFoo() {
- return this.foo();
- }
-
- }
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/MyClassCF.cfc b/src/test/java/TestCases/asm/phase3/MyClassCF.cfc
deleted file mode 100644
index 7aa68b7bb..000000000
--- a/src/test/java/TestCases/asm/phase3/MyClassCF.cfc
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * This is my class description
- *
- * @brad wood
- * @luis
- */
-component singleton gavin="pickin" inject foo="bar" {
-
- variables.setup=true;
- createObject('java','java.lang.System').out.println( "word" );
- request.foo="bar";
- isInitted = false;
- println( "current template is " & getCurrentTemplatePath() );
- printLn( foo() )
-
- function init() {
- isInitted = true;
- }
-
- function foo() {
- return "I work! #bar()# #variables.setup# #setup# #request.foo# #isInitted#";
- }
-
- private function bar() {
- return "whee";
- }
-
- function getThis() {
- return this;
- }
-
- function runThisFoo() {
- return this.foo();
- }
-
- }
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/MyInterfaceBL.bx b/src/test/java/TestCases/asm/phase3/MyInterfaceBL.bx
deleted file mode 100644
index 411c83543..000000000
--- a/src/test/java/TestCases/asm/phase3/MyInterfaceBL.bx
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
-* This is my interface description
-*
-* @brad wood
-* @luis
-*/
-interface singleton gavin="pickin" inject foo="bar" {
-
- function init();
-
- function foo();
-
- private function bar();
-
- default function myDefaultMethod() {
- return this.foo();
- }
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/MyInterfaceCF.cfc b/src/test/java/TestCases/asm/phase3/MyInterfaceCF.cfc
deleted file mode 100644
index 411c83543..000000000
--- a/src/test/java/TestCases/asm/phase3/MyInterfaceCF.cfc
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
-* This is my interface description
-*
-* @brad wood
-* @luis
-*/
-interface singleton gavin="pickin" inject foo="bar" {
-
- function init();
-
- function foo();
-
- private function bar();
-
- default function myDefaultMethod() {
- return this.foo();
- }
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/MyInterfaceCFTag.cfc b/src/test/java/TestCases/asm/phase3/MyInterfaceCFTag.cfc
deleted file mode 100644
index 255d4cda0..000000000
--- a/src/test/java/TestCases/asm/phase3/MyInterfaceCFTag.cfc
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/OnMissingMethod.cfc b/src/test/java/TestCases/asm/phase3/OnMissingMethod.cfc
deleted file mode 100644
index 73e5af916..000000000
--- a/src/test/java/TestCases/asm/phase3/OnMissingMethod.cfc
+++ /dev/null
@@ -1,5 +0,0 @@
-component {
- public any function onMissingMethod( string missingMethodName, any missingMethodArguments ){
- return missingMethodName & missingMethodArguments[2];
- }
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/Parent.cfc b/src/test/java/TestCases/asm/phase3/Parent.cfc
deleted file mode 100644
index 0e435dab7..000000000
--- a/src/test/java/TestCases/asm/phase3/Parent.cfc
+++ /dev/null
@@ -1,12 +0,0 @@
-component {
-
- function init() {
- setupFrameworkDefaults();
- return this;
- }
-
- private void function setupFrameworkDefaults() {
- request.calls.append( "running parent setupFrameworkDefaults()" );
- }
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/PropertyTest.bx b/src/test/java/TestCases/asm/phase3/PropertyTest.bx
deleted file mode 100644
index e27a9870e..000000000
--- a/src/test/java/TestCases/asm/phase3/PropertyTest.bx
+++ /dev/null
@@ -1,25 +0,0 @@
-class accessors=true {
- @preAnno
- property name="myProperty" default="myDefaultValue" type=string inject;
-
- /**
- * This is my property
- * @brad wood
- * @luis
- */
- @preanno "myValue" "anothervalue"
- property string anotherprop;
-
- @ID
- property theName;
-
- property string name;
-
- property shortcutWithDefault default="myDefaultValue";
-
- property String typedShortcutWithDefault default="myDefaultValue2";
-
- function init() {
- getMyProperty();
- }
-}
diff --git a/src/test/java/TestCases/asm/phase3/PropertyTestCF.cfc b/src/test/java/TestCases/asm/phase3/PropertyTestCF.cfc
deleted file mode 100644
index 420a38801..000000000
--- a/src/test/java/TestCases/asm/phase3/PropertyTestCF.cfc
+++ /dev/null
@@ -1,18 +0,0 @@
-component accessors=true {
- property name="myProperty" default="myDefaultValue" type=string inject preAnno;
-
- /**
- * This is my property
- * @brad wood
- * @luis
- */
- property string anotherprop preanno=["myValue", "anothervalue"];
-
- property shortcutWithDefault default="myDefaultValue";
-
- property String typedShortcutWithDefault default="myDefaultValue2";
-
- function init() {
- getMyProperty();
- }
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/PseudoConstructorNoOutput.cfc b/src/test/java/TestCases/asm/phase3/PseudoConstructorNoOutput.cfc
deleted file mode 100644
index 2c844bad6..000000000
--- a/src/test/java/TestCases/asm/phase3/PseudoConstructorNoOutput.cfc
+++ /dev/null
@@ -1,3 +0,0 @@
-component output=false {
- echo( "PseudoConstructorOutput" );
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/PseudoConstructorOutput.cfc b/src/test/java/TestCases/asm/phase3/PseudoConstructorOutput.cfc
deleted file mode 100644
index fe290b038..000000000
--- a/src/test/java/TestCases/asm/phase3/PseudoConstructorOutput.cfc
+++ /dev/null
@@ -1,3 +0,0 @@
-component output=true {
- echo( "PseudoConstructorOutput" );
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/RelativeInstantiation.bx b/src/test/java/TestCases/asm/phase3/RelativeInstantiation.bx
deleted file mode 100644
index 4e7e792d5..000000000
--- a/src/test/java/TestCases/asm/phase3/RelativeInstantiation.bx
+++ /dev/null
@@ -1,5 +0,0 @@
-class {
- function findSibling() {
- return new FindMe().foo();
- }
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/SeniorVespa.bx b/src/test/java/TestCases/asm/phase3/SeniorVespa.bx
deleted file mode 100644
index 1e1c8036b..000000000
--- a/src/test/java/TestCases/asm/phase3/SeniorVespa.bx
+++ /dev/null
@@ -1,3 +0,0 @@
-class extends="Moped" {
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/Stack.cfc b/src/test/java/TestCases/asm/phase3/Stack.cfc
deleted file mode 100644
index f3f5b33cd..000000000
--- a/src/test/java/TestCases/asm/phase3/Stack.cfc
+++ /dev/null
@@ -1,10 +0,0 @@
-component {
- function init() {
- stack = [];
- return this;
- }
-
- function empty() {
- return stack.len() == 0;
- }
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/StaticTest.bx b/src/test/java/TestCases/asm/phase3/StaticTest.bx
deleted file mode 100644
index 51240db75..000000000
--- a/src/test/java/TestCases/asm/phase3/StaticTest.bx
+++ /dev/null
@@ -1,33 +0,0 @@
- class {
- static {
- static.scoped = "brad";
- unscoped = "wood"
- static foo = 9000;
- '123' = 456;
- }
-
- static.foo = 42;
-
- static {
- static.again = "luis"
- }
-
- static function myStaticFunc() {
- return "static" & static.foo;
- }
-
- function myInstanceFunc() {
- return "instance" & myStaticFunc();
- }
-
- array function myInstanceFunc2() {
- return [static.scoped,
- static.unscoped,
- static.foo];
- }
-
- static function sayHello() {
- return "Hello";
- }
-
- }
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/StaticTestCF.cfc b/src/test/java/TestCases/asm/phase3/StaticTestCF.cfc
deleted file mode 100644
index ebfad9dc3..000000000
--- a/src/test/java/TestCases/asm/phase3/StaticTestCF.cfc
+++ /dev/null
@@ -1,22 +0,0 @@
-component {
- static {
- static.scoped = "brad";
- unscoped = "wood"
- static foo = 9000;
- }
-
- static.foo = 42;
-
- static {
- static.again = "luis"
- }
-
- static function myStaticFunc() {
- return "static" & static.foo;
- }
-
- function myInstanceFunc() {
- return "instance" & myStaticFunc();
- }
-
-}
\ No newline at end of file
diff --git a/src/test/java/TestCases/asm/phase3/WheeledThing.bx b/src/test/java/TestCases/asm/phase3/WheeledThing.bx
deleted file mode 100644
index bbbecf7cc..000000000
--- a/src/test/java/TestCases/asm/phase3/WheeledThing.bx
+++ /dev/null
@@ -1,13 +0,0 @@
-class implements="IBicycle,IMotorcycle" {
-
- function onMissingMethod( name, args ) {
- switch( arguments.name ) {
- case "pedal":
- return "Pedal speed #args[1]#"
- break;
- case "shift":
- return "Shift to gear #args[1]#"
- break;
- }
- }
-}
\ No newline at end of file
From fdfd8022e3fab064e020ba15dd75cf04108ab3e0 Mon Sep 17 00:00:00 2001
From: Brad Wood
Date: Mon, 2 Dec 2024 12:17:47 -0600
Subject: [PATCH 014/193] BL-807
---
.../compiler/javaboxpiler/JavaTranspiler.java | 7 ++---
.../transformer/AbstractTransformer.java | 6 ++--
.../transformer/BoxClassTransformer.java | 4 +--
.../transformer/BoxInterfaceTransformer.java | 4 +--
.../BoxStaticAccessTransformer.java | 5 ++--
.../BoxStaticMethodInvocationTransformer.java | 3 +-
.../BoxStringLiteralTransformer.java | 29 +++++++++++++------
.../BoxArgumentDeclarationTransformer.java | 4 +--
.../statement/BoxScriptTransformer.java | 4 +--
9 files changed, 37 insertions(+), 29 deletions(-)
diff --git a/src/main/java/ortus/boxlang/compiler/javaboxpiler/JavaTranspiler.java b/src/main/java/ortus/boxlang/compiler/javaboxpiler/JavaTranspiler.java
index 3e5289618..36b3d8096 100644
--- a/src/main/java/ortus/boxlang/compiler/javaboxpiler/JavaTranspiler.java
+++ b/src/main/java/ortus/boxlang/compiler/javaboxpiler/JavaTranspiler.java
@@ -41,7 +41,6 @@
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.expr.NameExpr;
import com.github.javaparser.ast.expr.ObjectCreationExpr;
-import com.github.javaparser.ast.expr.StringLiteralExpr;
import com.github.javaparser.ast.stmt.Statement;
import ortus.boxlang.compiler.JavaSourceString;
@@ -436,13 +435,13 @@ public Expression createAbstractMethod( BoxFunctionDeclaration bfd, AbstractTran
.setType( "AbstractFunction" )
.addArgument( transformer.createKey( bfd.getName() ) )
.addArgument( argumentsArray )
- .addArgument( new StringLiteralExpr( returnTypeString ) )
+ .addArgument( BoxStringLiteralTransformer.transform( returnTypeString ) )
.addArgument(
new FieldAccessExpr( new FieldAccessExpr( new NameExpr( "Function" ), "Access" ), access.toString().toUpperCase() ) )
.addArgument( transformer.transformAnnotations( bfd.getAnnotations() ) )
.addArgument( transformer.transformDocumentation( bfd.getDocumentation() ) )
- .addArgument( new StringLiteralExpr( sourceObjectName ) )
- .addArgument( new StringLiteralExpr( sourceObjectType ) )
+ .addArgument( BoxStringLiteralTransformer.transform( sourceObjectName ) )
+ .addArgument( BoxStringLiteralTransformer.transform( sourceObjectType ) )
);
}
diff --git a/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/AbstractTransformer.java b/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/AbstractTransformer.java
index db7e7f2a4..37535a20e 100644
--- a/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/AbstractTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/AbstractTransformer.java
@@ -32,7 +32,6 @@
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.expr.NameExpr;
-import com.github.javaparser.ast.expr.StringLiteralExpr;
import com.github.javaparser.ast.stmt.Statement;
import ortus.boxlang.compiler.ast.BoxExpression;
@@ -57,6 +56,7 @@
import ortus.boxlang.compiler.ast.statement.BoxWhile;
import ortus.boxlang.compiler.ast.statement.component.BoxComponent;
import ortus.boxlang.compiler.javaboxpiler.Transpiler;
+import ortus.boxlang.compiler.javaboxpiler.transformer.expression.BoxStringLiteralTransformer;
import ortus.boxlang.runtime.config.util.PlaceholderHelper;
/**
@@ -253,7 +253,7 @@ public Expression transformAnnotations( List annotations, Boolean
value = ( Expression ) transpiler.transform( thisValue );
} else if ( onlyLiteralValues ) {
// Runtime expressions we just put this place holder text in for
- value = new StringLiteralExpr( "" );
+ value = BoxStringLiteralTransformer.transform( "" );
} else {
value = ( Expression ) transpiler.transform( thisValue );
}
@@ -262,7 +262,7 @@ public Expression transformAnnotations( List annotations, Boolean
value = new BooleanLiteralExpr( true );
} else {
// Annotations in script with no value default to empty string (CF compat)
- value = new StringLiteralExpr( "" );
+ value = BoxStringLiteralTransformer.transform( "" );
}
members.add( value );
} );
diff --git a/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/BoxClassTransformer.java b/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/BoxClassTransformer.java
index 66d432a29..bb1f99047 100644
--- a/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/BoxClassTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/BoxClassTransformer.java
@@ -35,7 +35,6 @@
import com.github.javaparser.ast.expr.LambdaExpr;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.expr.NameExpr;
-import com.github.javaparser.ast.expr.StringLiteralExpr;
import com.github.javaparser.ast.stmt.BlockStmt;
import com.github.javaparser.ast.stmt.EmptyStmt;
import com.github.javaparser.ast.stmt.ReturnStmt;
@@ -61,6 +60,7 @@
import ortus.boxlang.compiler.ast.statement.BoxReturnType;
import ortus.boxlang.compiler.ast.statement.BoxType;
import ortus.boxlang.compiler.javaboxpiler.JavaTranspiler;
+import ortus.boxlang.compiler.javaboxpiler.transformer.expression.BoxStringLiteralTransformer;
import ortus.boxlang.runtime.config.util.PlaceholderHelper;
import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
import ortus.boxlang.runtime.dynamic.casters.BooleanCaster;
@@ -657,7 +657,7 @@ public Node transform( BoxNode node, TransformerContext context ) throws Illegal
for ( Map.Entry entry : transpiler.getKeys().entrySet() ) {
MethodCallExpr methodCallExpr = new MethodCallExpr( new NameExpr( "Key" ), "of" );
if ( entry.getValue() instanceof BoxStringLiteral str ) {
- methodCallExpr.addArgument( new StringLiteralExpr( str.getValue() ) );
+ methodCallExpr.addArgument( BoxStringLiteralTransformer.transform( str.getValue() ) );
} else if ( entry.getValue() instanceof BoxIntegerLiteral id ) {
methodCallExpr.addArgument( new IntegerLiteralExpr( id.getValue() ) );
} else {
diff --git a/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/BoxInterfaceTransformer.java b/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/BoxInterfaceTransformer.java
index bf913cdfb..9ec96b19f 100644
--- a/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/BoxInterfaceTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/BoxInterfaceTransformer.java
@@ -27,7 +27,6 @@
import com.github.javaparser.ast.expr.IntegerLiteralExpr;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.expr.NameExpr;
-import com.github.javaparser.ast.expr.StringLiteralExpr;
import ortus.boxlang.compiler.ast.BoxExpression;
import ortus.boxlang.compiler.ast.BoxInterface;
@@ -41,6 +40,7 @@
import ortus.boxlang.compiler.ast.statement.BoxFunctionDeclaration;
import ortus.boxlang.compiler.ast.statement.BoxImport;
import ortus.boxlang.compiler.javaboxpiler.JavaTranspiler;
+import ortus.boxlang.compiler.javaboxpiler.transformer.expression.BoxStringLiteralTransformer;
import ortus.boxlang.runtime.config.util.PlaceholderHelper;
import ortus.boxlang.runtime.types.exceptions.BoxRuntimeException;
import ortus.boxlang.runtime.types.exceptions.ExpressionException;
@@ -378,7 +378,7 @@ public Node transform( BoxNode node, TransformerContext context ) throws Illegal
for ( Map.Entry entry : transpiler.getKeys().entrySet() ) {
MethodCallExpr methodCallExpr = new MethodCallExpr( new NameExpr( "Key" ), "of" );
if ( entry.getValue() instanceof BoxStringLiteral str ) {
- methodCallExpr.addArgument( new StringLiteralExpr( str.getValue() ) );
+ methodCallExpr.addArgument( BoxStringLiteralTransformer.transform( str.getValue() ) );
} else if ( entry.getValue() instanceof BoxIntegerLiteral id ) {
methodCallExpr.addArgument( new IntegerLiteralExpr( id.getValue() ) );
} else {
diff --git a/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/expression/BoxStaticAccessTransformer.java b/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/expression/BoxStaticAccessTransformer.java
index 28ca377ac..61810d220 100644
--- a/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/expression/BoxStaticAccessTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/expression/BoxStaticAccessTransformer.java
@@ -22,7 +22,6 @@
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.StringLiteralExpr;
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.expression.BoxFQN;
@@ -63,13 +62,13 @@ public Node transform( BoxNode node, TransformerContext context ) throws Illegal
Expression jContext;
if ( objectAccess.getContext() instanceof BoxFQN fqn ) {
- jContext = new StringLiteralExpr( fqn.getValue() );
+ jContext = BoxStringLiteralTransformer.transform( fqn.getValue() );
} else if ( objectAccess.getContext() instanceof BoxIdentifier id ) {
// In BL code, this could be an import, but in CF it's just a string
if ( transpiler.matchesImport( id.getName() ) && transpiler.getProperty( "sourceType" ).toLowerCase().startsWith( "box" ) ) {
jContext = ( Expression ) transpiler.transform( id, context );
} else {
- jContext = new StringLiteralExpr( id.getName() );
+ jContext = BoxStringLiteralTransformer.transform( id.getName() );
}
} else {
// foo.bar()::baz
diff --git a/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/expression/BoxStaticMethodInvocationTransformer.java b/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/expression/BoxStaticMethodInvocationTransformer.java
index 35f18d133..7114c5e24 100644
--- a/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/expression/BoxStaticMethodInvocationTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/expression/BoxStaticMethodInvocationTransformer.java
@@ -22,7 +22,6 @@
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.StringLiteralExpr;
import ortus.boxlang.compiler.ast.BoxExpression;
import ortus.boxlang.compiler.ast.BoxNode;
@@ -47,7 +46,7 @@ public Node transform( BoxNode node, TransformerContext context ) throws Illegal
Expression expr;
if ( baseObject instanceof BoxFQN fqn ) {
- expr = new StringLiteralExpr( fqn.getValue() );
+ expr = BoxStringLiteralTransformer.transform( fqn.getValue() );
} else if ( baseObject instanceof BoxIdentifier id ) {
// TODO: What if we have foo::bar() but foo is the name of a variable AND ALSO the name of an accessible Box Class?
// Do we treat "foo" as a FQN class name or a variable in that case??
diff --git a/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/expression/BoxStringLiteralTransformer.java b/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/expression/BoxStringLiteralTransformer.java
index 50b3aba8d..11e55221d 100644
--- a/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/expression/BoxStringLiteralTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/expression/BoxStringLiteralTransformer.java
@@ -18,7 +18,6 @@
import java.util.List;
import java.util.stream.Collectors;
-import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.MethodCallExpr;
@@ -51,15 +50,26 @@ public BoxStringLiteralTransformer( JavaTranspiler transpiler ) {
* @return generates a Java Parser string Literal or concatenation expression
*/
@Override
- public Node transform( BoxNode node, TransformerContext context ) throws IllegalStateException {
- BoxStringLiteral literal = ( BoxStringLiteral ) node;
- String value = escape( literal.getValue() );
+ public Expression transform( BoxNode node, TransformerContext context ) throws IllegalStateException {
+ BoxStringLiteral literal = ( BoxStringLiteral ) node;
+ return transform( literal.getValue() );
+ }
+
+ /**
+ * Transform just the string portion (reuseable for other purposes)
+ *
+ * @param value The input string.
+ *
+ * @return generates a Java Parser string Literal or concatenation expression
+ */
+ public static Expression transform( String value ) throws IllegalStateException {
+ String escapedVal = escape( value );
- if ( value.length() > MAX_LITERAL_LENGTH ) {
+ if ( escapedVal.length() > MAX_LITERAL_LENGTH ) {
List parts = splitStringIntoParts( value );
return createArrayJoinMethodCall( parts );
} else {
- return new StringLiteralExpr( value );
+ return new StringLiteralExpr( escapedVal );
}
}
@@ -70,7 +80,7 @@ public Node transform( BoxNode node, TransformerContext context ) throws Illegal
*
* @return A list of StringLiteralExpr parts.
**/
- private List splitStringIntoParts( String str ) {
+ private static List splitStringIntoParts( String str ) {
List parts = new ArrayList<>();
int length = str.length();
for ( int i = 0; i < length; i += MAX_LITERAL_LENGTH ) {
@@ -88,9 +98,10 @@ private List splitStringIntoParts( String str ) {
*
* @return A BinaryExpr representing the concatenation of all parts.
**/
- private Expression createArrayJoinMethodCall( List parts ) {
+ private static Expression createArrayJoinMethodCall( List parts ) {
// Create a MethodCallExpr for String.join with an array of strings
var args = parts.stream()
+ // Assumes the parts won't have so many escaped chars to put back over the limit
.map( part -> ( Expression ) new StringLiteralExpr( escape( part ) ) ) // Escape quotes and create StringLiteralExpr
.collect( Collectors.toCollection( NodeList::new ) ); // Collect into NodeList
args.add( 0, new StringLiteralExpr( "" ) ); // Delimiter
@@ -106,7 +117,7 @@ private Expression createArrayJoinMethodCall( List parts ) {
*
* @return The output String.
**/
- private String escape( String s ) {
+ private static String escape( String s ) {
return s.replace( "\\", "\\\\" )
.replace( "\t", "\\t" )
.replace( "\b", "\\b" )
diff --git a/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/statement/BoxArgumentDeclarationTransformer.java b/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/statement/BoxArgumentDeclarationTransformer.java
index 45bcccbca..e0b3e031e 100644
--- a/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/statement/BoxArgumentDeclarationTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/statement/BoxArgumentDeclarationTransformer.java
@@ -27,7 +27,6 @@
import com.github.javaparser.ast.expr.LambdaExpr;
import com.github.javaparser.ast.expr.NullLiteralExpr;
import com.github.javaparser.ast.expr.ObjectCreationExpr;
-import com.github.javaparser.ast.expr.StringLiteralExpr;
import com.github.javaparser.ast.stmt.BlockStmt;
import com.github.javaparser.ast.stmt.ReturnStmt;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
@@ -38,6 +37,7 @@
import ortus.boxlang.compiler.javaboxpiler.JavaTranspiler;
import ortus.boxlang.compiler.javaboxpiler.transformer.AbstractTransformer;
import ortus.boxlang.compiler.javaboxpiler.transformer.TransformerContext;
+import ortus.boxlang.compiler.javaboxpiler.transformer.expression.BoxStringLiteralTransformer;
/**
* Transform a BoxArgumentDeclarationTransformer Node the equivalent Java Parser AST nodes
@@ -85,7 +85,7 @@ public Node transform( BoxNode node, TransformerContext context ) throws Illegal
// Create the argument list
NodeList arguments = new NodeList(
new BooleanLiteralExpr( boxArgument.getRequired() ),
- new StringLiteralExpr( type ),
+ BoxStringLiteralTransformer.transform( type ),
createKey( boxArgument.getName() ),
defaultLiteral,
defaultExpression,
diff --git a/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/statement/BoxScriptTransformer.java b/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/statement/BoxScriptTransformer.java
index 287a6d9f8..a2a0fa82d 100644
--- a/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/statement/BoxScriptTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/javaboxpiler/transformer/statement/BoxScriptTransformer.java
@@ -27,7 +27,6 @@
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.expr.NameExpr;
import com.github.javaparser.ast.expr.NullLiteralExpr;
-import com.github.javaparser.ast.expr.StringLiteralExpr;
import com.github.javaparser.ast.stmt.BlockStmt;
import com.github.javaparser.ast.stmt.EmptyStmt;
import com.github.javaparser.ast.stmt.ExpressionStmt;
@@ -46,6 +45,7 @@
import ortus.boxlang.compiler.javaboxpiler.JavaTranspiler;
import ortus.boxlang.compiler.javaboxpiler.transformer.AbstractTransformer;
import ortus.boxlang.compiler.javaboxpiler.transformer.TransformerContext;
+import ortus.boxlang.compiler.javaboxpiler.transformer.expression.BoxStringLiteralTransformer;
import ortus.boxlang.runtime.config.util.PlaceholderHelper;
import ortus.boxlang.runtime.types.exceptions.BoxRuntimeException;
import ortus.boxlang.runtime.types.exceptions.ExpressionException;
@@ -287,7 +287,7 @@ public Node transform( BoxNode node, TransformerContext context ) throws Illegal
for ( Map.Entry entry : transpiler.getKeys().entrySet() ) {
MethodCallExpr methodCallExpr = new MethodCallExpr( new NameExpr( "Key" ), "of" );
if ( entry.getValue() instanceof BoxStringLiteral str ) {
- methodCallExpr.addArgument( new StringLiteralExpr( str.getValue() ) );
+ methodCallExpr.addArgument( BoxStringLiteralTransformer.transform( str.getValue() ) );
} else if ( entry.getValue() instanceof BoxIntegerLiteral id ) {
methodCallExpr.addArgument( new IntegerLiteralExpr( id.getValue() ) );
} else {
From e3686f36432e3335e11c2625879ee0e755a5d0ab Mon Sep 17 00:00:00 2001
From: Jacob Beers
Date: Mon, 2 Dec 2024 12:36:47 -0600
Subject: [PATCH 015/193] BL-808 fully enable asm tests
---
build.gradle | 2 ++
1 file changed, 2 insertions(+)
diff --git a/build.gradle b/build.gradle
index 9571ddf9f..d7b019f6d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -235,6 +235,8 @@ shadowJar {
}
test {
+ systemProperty 'boxlang.experimental.compiler', System.getProperty('boxlang.experimental.compiler', "java")
+
testLogging {
events "FAILED", "STANDARD_ERROR"
}
From e7490dbac5c66e585063912a8242a0784ca9ac1e Mon Sep 17 00:00:00 2001
From: Brad Wood
Date: Mon, 2 Dec 2024 14:45:39 -0600
Subject: [PATCH 016/193] BL-788
---
.../application/ApplicationClassListener.java | 11 ++++
.../application/BaseApplicationListener.java | 2 +
.../boxlang/runtime/config/Configuration.java | 22 ++++++++
.../runtime/context/RequestBoxContext.java | 13 +++++
.../runtime/loader/resolvers/BoxResolver.java | 54 ++++++++++++++++++-
.../ortus/boxlang/runtime/scopes/Key.java | 2 +
src/main/resources/config/boxlang.json | 4 +-
src/test/java/TestCases/phase3/ClassTest.java | 35 ++++++++++++
8 files changed, 141 insertions(+), 2 deletions(-)
diff --git a/src/main/java/ortus/boxlang/runtime/application/ApplicationClassListener.java b/src/main/java/ortus/boxlang/runtime/application/ApplicationClassListener.java
index 4a12f411f..86b6d7921 100644
--- a/src/main/java/ortus/boxlang/runtime/application/ApplicationClassListener.java
+++ b/src/main/java/ortus/boxlang/runtime/application/ApplicationClassListener.java
@@ -24,11 +24,13 @@
import ortus.boxlang.runtime.dynamic.casters.StringCaster;
import ortus.boxlang.runtime.runnables.IClassRunnable;
import ortus.boxlang.runtime.scopes.Key;
+import ortus.boxlang.runtime.types.Array;
import ortus.boxlang.runtime.types.Function;
import ortus.boxlang.runtime.types.Struct;
import ortus.boxlang.runtime.types.exceptions.AbortException;
import ortus.boxlang.runtime.types.util.BLCollector;
import ortus.boxlang.runtime.util.EncryptionUtil;
+import ortus.boxlang.runtime.util.FileSystemUtil;
/**
* I represent an Application listener that wraps an Application class instance, delegting to it, where possible and providing default
@@ -57,6 +59,15 @@ public ApplicationClassListener( IClassRunnable listener, RequestBoxContext cont
this.settings.put( Key.source, listener.getRunnablePath().absolutePath().toString() );
this.settings.put( Key._CLASS, listener.getRunnablePath().absolutePath().toString() );
+ // Expand classPaths in Application.bx. They will be relative to the Application.bx file if not starting with /
+ Array classPaths = this.settings.getAsArray( Key.classPaths );
+ classPaths = classPaths.stream()
+ .map( String::valueOf )
+ .map( ( cp ) -> {
+ return FileSystemUtil.expandPath( context, cp, listener.getRunnablePath() );
+
+ } ).collect( BLCollector.toArray() );
+
// If there is no application name or if it's empty, make one up.
String appName = StringCaster.cast( this.settings.get( Key._NAME ) );
if ( appName == null || appName.isBlank() ) {
diff --git a/src/main/java/ortus/boxlang/runtime/application/BaseApplicationListener.java b/src/main/java/ortus/boxlang/runtime/application/BaseApplicationListener.java
index 103b6d91c..363e55168 100644
--- a/src/main/java/ortus/boxlang/runtime/application/BaseApplicationListener.java
+++ b/src/main/java/ortus/boxlang/runtime/application/BaseApplicationListener.java
@@ -127,6 +127,8 @@ public abstract class BaseApplicationListener {
"clientStorage", "cookie",
"clientTimeout", 1,
// END: CLIENT
+ "classPaths", new Array(),
+ // TODO: move this logic to compat
"componentPaths", new Array(),
"customTagPaths", new Array(),
"datasource", runtime.getConfiguration().defaultDatasource,
diff --git a/src/main/java/ortus/boxlang/runtime/config/Configuration.java b/src/main/java/ortus/boxlang/runtime/config/Configuration.java
index a0ae2e536..fa7a96edc 100644
--- a/src/main/java/ortus/boxlang/runtime/config/Configuration.java
+++ b/src/main/java/ortus/boxlang/runtime/config/Configuration.java
@@ -187,6 +187,11 @@ public class Configuration implements IConfigSegment {
public List customTagsDirectory = new ArrayList<>(
Arrays.asList( BoxRuntime.getInstance().getRuntimeHome().toString() + "/customTags" ) );
+ /**
+ * An array of directories where box classes are located and loaded from.
+ */
+ public List classPaths = new ArrayList<>();
+
/**
* An array of directories where jar files will be loaded from at runtime.
*/
@@ -421,6 +426,22 @@ public Configuration process( IStruct config ) {
}
}
+ // process classPaths directories
+ if ( config.containsKey( Key.classPaths ) ) {
+ if ( config.get( Key.classPaths ) instanceof List> castedList ) {
+ // iterate and add to the original list if it doesn't exist
+ castedList.forEach( item -> {
+ var resolvedItem = PlaceholderHelper.resolve( item );
+ // Verify or add the path
+ if ( !this.classPaths.contains( resolvedItem ) ) {
+ this.classPaths.add( resolvedItem );
+ }
+ } );
+ } else {
+ logger.warn( "The [classPaths] configuration is not a JSON Array, ignoring it." );
+ }
+ }
+
// Process javaLibraryPaths directories
if ( config.containsKey( Key.javaLibraryPaths ) ) {
if ( config.get( Key.javaLibraryPaths ) instanceof List> castedList ) {
@@ -862,6 +883,7 @@ public IStruct asStruct() {
Key.caches, cachesCopy,
Key.classGenerationDirectory, this.classGenerationDirectory,
Key.customTagsDirectory, Array.fromList( this.customTagsDirectory ),
+ Key.classPaths, Array.fromList( this.classPaths ),
Key.datasources, datsourcesCopy,
Key.debugMode, this.debugMode,
Key.defaultCache, this.defaultCache.toStruct(),
diff --git a/src/main/java/ortus/boxlang/runtime/context/RequestBoxContext.java b/src/main/java/ortus/boxlang/runtime/context/RequestBoxContext.java
index 1311a7615..df81f5467 100644
--- a/src/main/java/ortus/boxlang/runtime/context/RequestBoxContext.java
+++ b/src/main/java/ortus/boxlang/runtime/context/RequestBoxContext.java
@@ -376,6 +376,19 @@ public IStruct getConfig() {
config.getAsArray( Key.customTagsDirectory ).addAll( customTagPaths );
}
+ // Add in classPaths and componentPaths (for CF compat) to the classPaths array
+ Array classPaths = appSettings.getAsArray( Key.classPaths );
+ if ( classPaths != null && !classPaths.isEmpty() ) {
+ // Expand each path in case it's relative
+ config.getAsArray( Key.classPaths ).addAll( classPaths );
+ }
+ // TODO: move componentPaths logic to compat
+ Array componentPaths = appSettings.getAsArray( Key.componentPaths );
+ if ( componentPaths != null && !componentPaths.isEmpty() ) {
+ // Expand each path in case it's relative
+ config.getAsArray( Key.classPaths ).addAll( componentPaths );
+ }
+
// OTHER OVERRIDES go here
// Announce it so modules can do their own overrides and such
diff --git a/src/main/java/ortus/boxlang/runtime/loader/resolvers/BoxResolver.java b/src/main/java/ortus/boxlang/runtime/loader/resolvers/BoxResolver.java
index 480d63ab5..33ebe61ce 100644
--- a/src/main/java/ortus/boxlang/runtime/loader/resolvers/BoxResolver.java
+++ b/src/main/java/ortus/boxlang/runtime/loader/resolvers/BoxResolver.java
@@ -287,8 +287,12 @@ public Optional findFromLocal( IBoxContext context, String fullyQ
// Try to find the class using:
// 1. Relative to the current template
// 2. A mapping
+ // 3. Custom tag directory or component/class path
return findByRelativeLocation( context, finalSlashName, name, imports, loadClass )
- .or( () -> findByMapping( context, finalSlashName, name, imports, loadClass ) );
+ // TODO: both of these method call context.getConfig(), but ideally we just call it once
+ // For classes found in a lookup directory, it will result in getConfig() being called twice.
+ .or( () -> findByMapping( context, finalSlashName, name, imports, loadClass ) )
+ .or( () -> findByLookupDirectory( context, finalSlashName, name, imports, loadClass ) );
}
/**
@@ -433,6 +437,54 @@ private Optional findByRelativeLocation(
return Optional.empty();
}
+ /**
+ * Find a class in lookup directories. This includes custom tag paths and component/class paths
+ *
+ * @param context The current context of execution
+ * @param slashName The name of the class to find using slahes instead of dots
+ * @param name The original dot notation name of the class to find
+ * @param imports The list of imports to use
+ * @param loadClass When false, the class location is returned with informatino about where the class was found, but the class is not loaded and will be null.
+ *
+ * @return An Optional of {@link ClassLocation} if found, {@link Optional#empty()} otherwise
+ */
+ private Optional findByLookupDirectory(
+ IBoxContext context,
+ String slashName,
+ String name,
+ List imports,
+ boolean loadClass ) {
+
+ List lookupPaths = new ArrayList();
+ lookupPaths
+ .addAll( context.getConfig().getAsArray( Key.customTagsDirectory ).stream().map( String::valueOf ).map( Path::of ).toList() );
+ lookupPaths.addAll( context.getConfig().getAsArray( Key.classPaths ).stream().map( String::valueOf ).map( Path::of ).toList() );
+
+ Optional result = lookupPaths
+ .stream()
+ .map( cp -> findExistingPathWithValidExtension( cp, slashName ) )
+ .filter( path -> path != null )
+ .findFirst();
+
+ if ( !result.isPresent() ) {
+ return Optional.empty();
+ }
+ Path foundPath = result.get();
+
+ ResolvedFilePath newResolvedFilePath = ResolvedFilePath.of( "", "", slashName, foundPath );
+
+ return Optional.of( new ClassLocation(
+ newResolvedFilePath.getBoxFQN().getClassName(),
+ foundPath.toAbsolutePath().toString(),
+ newResolvedFilePath.getBoxFQN().getPackageString(),
+ ClassLocator.TYPE_BX,
+ loadClass ? RunnableLoader.getInstance().loadClass( newResolvedFilePath, context ) : null,
+ "",
+ false
+ ) );
+
+ }
+
/**
* Find an existing path with a valid extension
*
diff --git a/src/main/java/ortus/boxlang/runtime/scopes/Key.java b/src/main/java/ortus/boxlang/runtime/scopes/Key.java
index a2f10ff3c..1e13fb66d 100644
--- a/src/main/java/ortus/boxlang/runtime/scopes/Key.java
+++ b/src/main/java/ortus/boxlang/runtime/scopes/Key.java
@@ -165,6 +165,7 @@ public class Key implements Comparable, Serializable {
public static final Key childname = Key.of( "childname" );
public static final Key classGenerationDirectory = Key.of( "classGenerationDirectory" );
public static final Key className = Key.of( "className" );
+ public static final Key classPaths = Key.of( "classPaths" );
public static final Key cli = Key.of( "cli" );
public static final Key clazz = Key.of( "clazz" );
public static final Key clientCert = Key.of( "clientCert" );
@@ -184,6 +185,7 @@ public class Key implements Comparable, Serializable {
public static final Key columnTypeList = Key.of( "columnTypeList" );
public static final Key compiler = Key.of( "compiler" );
public static final Key component = Key.of( "component" );
+ public static final Key componentPaths = Key.of( "componentPaths" );
public static final Key componentService = Key.of( "componentService" );
public static final Key compression = Key.of( "compression" );
public static final Key condition = Key.of( "condition" );
diff --git a/src/main/resources/config/boxlang.json b/src/main/resources/config/boxlang.json
index 77729773b..b35113014 100644
--- a/src/main/resources/config/boxlang.json
+++ b/src/main/resources/config/boxlang.json
@@ -68,6 +68,8 @@
"customTagsDirectory": [
"${boxlang-home}/customTags"
],
+ // A collection of directories to lookup box classes in (.bx files), they must be absolute paths
+ "classPaths": [],
// A collection of directories we will class load all Java *.jar files from
"javaLibraryPaths": [
"${boxlang-home}/lib"
@@ -406,4 +408,4 @@
// }
// }
}
-}
+}
\ No newline at end of file
diff --git a/src/test/java/TestCases/phase3/ClassTest.java b/src/test/java/TestCases/phase3/ClassTest.java
index 70b6979b8..d1a1126c3 100644
--- a/src/test/java/TestCases/phase3/ClassTest.java
+++ b/src/test/java/TestCases/phase3/ClassTest.java
@@ -392,6 +392,41 @@ public void testBasicClassFile() {
// @formatter:on
}
+ @DisplayName( "basic class file via component path" )
+ @Test
+ public void testBasicClassFileViaComponentPath() {
+ // @formatter:off
+ instance.executeSource(
+ """
+ newClassPaths = getApplicationMetadata().classPaths.append( expandPath( "/src/test/java/TestCases/phase3" ) );
+ application classPaths=newClassPaths;
+ cfc = new MyClass();
+ // execute public method
+ result = cfc.foo();
+
+ assert result == "I work! whee true true bar true";
+ """, context );
+ // @formatter:on
+ }
+
+ @DisplayName( "basic class file via component path subdir" )
+ @Test
+ public void testBasicClassFileViaComponentPathSubDir() {
+ // @formatter:off
+ instance.executeSource(
+ """
+ newClassPaths = getApplicationMetadata().classPaths.append( expandPath( "/src/test/java/TestCases" ) );
+ application classPaths=newClassPaths;
+ import phase3.MyClass as bradClass;
+ cfc = new bradClass();
+ // execute public method
+ result = cfc.foo();
+
+ assert result == "I work! whee true true bar true";
+ """, context );
+ // @formatter:on
+ }
+
@DisplayName( "legacy meta" )
@Test
public void testlegacyMeta() {
From 66c7aa6ec3dcbbfe263845dd425c07c95962ab32 Mon Sep 17 00:00:00 2001
From: Luis Majano
Date: Mon, 2 Dec 2024 21:48:19 +0100
Subject: [PATCH 017/193] BL-784 WIP
---
.../java/ortus/boxlang/runtime/util/FQN.java | 34 +--
.../boxlang/runtime/util/RegexBuilder.java | 213 ++++++++++++++++++
2 files changed, 232 insertions(+), 15 deletions(-)
create mode 100644 src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java
diff --git a/src/main/java/ortus/boxlang/runtime/util/FQN.java b/src/main/java/ortus/boxlang/runtime/util/FQN.java
index 434270319..1d3558f90 100644
--- a/src/main/java/ortus/boxlang/runtime/util/FQN.java
+++ b/src/main/java/ortus/boxlang/runtime/util/FQN.java
@@ -22,6 +22,8 @@
import java.util.HashSet;
import java.util.Set;
+import org.apache.commons.lang3.StringUtils;
+
/**
* This class represents a java fully qualified name (FQN) for a class or package.
* It handles all the edge cases of dealing with file paths and package names.
@@ -186,8 +188,11 @@ protected String[] parseParts( String fqn, boolean allPackage ) {
fqn = normalizeDots( fqn );
// Remove any non alpha-numeric chars.
- fqn = fqn.replaceAll( "[^a-zA-Z0-9$\\.]", "__" );
+ fqn = RegexBuilder
+ .of( fqn, RegexBuilder.PACKAGE_NAMES )
+ .replaceAllAndGet( "__" );
+ // Short circuit if empty
if ( fqn.isEmpty() ) {
return new String[] {};
}
@@ -214,7 +219,7 @@ protected String[] parseParts( String fqn, boolean allPackage ) {
// parse fqn into array, loop over array and clean/normalize parts
return Arrays.stream( fqn.split( "\\." ) )
// if starts with number, prefix with _
- .map( s -> s.matches( "^\\d.*" ) ? "_" + s : s )
+ .map( s -> RegexBuilder.of( s, RegexBuilder.STARTS_WITH_DIGIT ).matches() ? "_" + s : s )
.map( s -> {
if ( RESERVED_WORDS.contains( s ) ) {
return "_" + s;
@@ -229,18 +234,20 @@ protected String[] parseParts( String fqn, boolean allPackage ) {
* - Remove any double dots.
* - Trim trailing period.
* - Trim leading period.
- *
+ *
* @param fqn The string to normalize.
- *
+ *
* @return The normalized string.
*/
protected String normalizeDots( String fqn ) {
// Replace .. with .
- fqn = fqn.replaceAll( "\\.\\.", "." );
+ fqn = RegexBuilder.of( fqn, RegexBuilder.TWO_DOTS ).replaceAllAndGet( "." );
+
// trim trailing period
if ( fqn.endsWith( "." ) ) {
fqn = fqn.substring( 0, fqn.length() - 1 );
}
+
// trim leading period
if ( fqn.startsWith( "." ) ) {
fqn = fqn.substring( 1 );
@@ -276,17 +283,14 @@ protected String parseFromFile( Path file ) {
fqn = fqn.substring( 0, fqn.length() - 1 );
}
- // Take out periods in folder names
- fqn = fqn.replaceAll( "\\.", "" );
- // Replace / with .
- fqn = fqn.replaceAll( "/", "." );
- // Remove any : from Windows drives
- fqn = fqn.replaceAll( ":", "_" );
- // Replace \ with .
- fqn = fqn.replaceAll( "\\\\", "." );
-
+ // Replace all periods with an emtpy string in fqn
+ fqn = StringUtils.remove( fqn, "." );
+ // Take out slashes to . and backslashes to .
+ fqn = StringUtils.replace( fqn, "/", "." );
+ fqn = StringUtils.replace( fqn, "\\", "." );
+ // Take out colons to _
+ fqn = StringUtils.replace( fqn, ":", "_" );
return fqn;
-
}
/**
diff --git a/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java b/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java
new file mode 100644
index 000000000..cf5b5be84
--- /dev/null
+++ b/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java
@@ -0,0 +1,213 @@
+/**
+ * [BoxLang]
+ *
+ * Copyright [2023] [Ortus Solutions, Corp]
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ortus.boxlang.runtime.util;
+
+import java.util.Objects;
+import java.util.regex.Pattern;
+
+/**
+ * This class can be used as a utility to handle regular expressions.
+ * Add as many compiled patterns as needed and make sure you give them a meaningful name.
+ */
+public class RegexBuilder {
+
+ /**
+ * Pattern Dictionary
+ * Add as many patterns as needed, but make sure they are in all caps and alphabetically ordered.
+ */
+ public static final Pattern BACKSLASH = Pattern.compile( "\\\\" );
+ public static final Pattern COLON = Pattern.compile( ":" );
+ public static final Pattern PACKAGE_NAMES = Pattern.compile( "[^a-zA-Z0-9$\\.]" );
+ public static final Pattern PERIOD = Pattern.compile( "\\." );
+ public static final Pattern SLASH = Pattern.compile( "/" );
+ public static final Pattern STARTS_WITH_DIGIT = Pattern.compile( "^\\d.*" );
+ public static final Pattern TWO_DOTS = Pattern.compile( "\\.{2}" );
+ public static final Pattern WHITESPACE = Pattern.compile( "\\s" );
+
+ /**
+ * Build a matcher for the given pattern lookup
+ *
+ * @param input The input string to match against
+ *
+ * @return A new matcher instance
+ */
+ public static RegexMatcher of( String input ) {
+ return new RegexMatcher( input );
+ }
+
+ /**
+ * Build a matcher for the given input and string pattern
+ *
+ * @param input The input string to match against
+ * @param pattern The pattern to match against
+ *
+ * @return A new matcher instance
+ */
+ public static RegexMatcher of( String input, String pattern ) {
+ return new RegexMatcher( input ).match( pattern );
+ }
+
+ /**
+ * Build a matcher for the given input and string pattern
+ *
+ * @param input The input string to match against
+ * @param pattern The pattern to match against
+ *
+ * @return A new matcher instance
+ */
+ public static RegexMatcher of( String input, Pattern pattern ) {
+ return new RegexMatcher( input ).match( pattern );
+ }
+
+ /**
+ * The RegexMatcher class is used to match a pattern against an input string
+ * by either using a pre-complied pattern or a string pattern that will be compiled on the fly.
+ */
+ public static class RegexMatcher {
+
+ private Pattern pattern;
+ private String input;
+ private final String original;
+
+ /**
+ * Create a new matcher instance
+ *
+ * @param input The input string to match against
+ */
+ private RegexMatcher( String input ) {
+ this.input = input;
+ this.original = input;
+ }
+
+ /**
+ * Compile the pattern from the given pattern
+ *
+ * @param pattern The pattern to compile
+ *
+ * @return The matcher instance
+ */
+ public RegexMatcher match( Pattern pattern ) {
+ this.pattern = pattern;
+ return this;
+ }
+
+ /**
+ * Compile the pattern from the given string
+ *
+ * @param pattern The pattern to compile
+ *
+ * @return The matcher instance
+ */
+ public RegexMatcher match( String pattern ) {
+ Objects.requireNonNull( pattern, "Pattern cannot be null" );
+ if ( pattern.isEmpty() ) {
+ throw new IllegalArgumentException( "Pattern cannot be empty" );
+ }
+ this.pattern = Pattern.compile( pattern );
+ return this;
+ }
+
+ /**
+ * Check if the input string matches the pattern
+ *
+ * @return True if the input string matches the pattern, false otherwise
+ */
+ public Boolean matches() {
+ return this.pattern.matcher( this.input ).matches();
+ }
+
+ /**
+ * Replace all occurrences of the pattern in the input string with the replacement string
+ *
+ * @param replacement The replacement string
+ *
+ * @return The input string with all occurrences of the pattern replaced with the replacement string
+ */
+ public RegexMatcher replaceAll( String replacement ) {
+ Objects.requireNonNull( replacement, "Replacement cannot be null" );
+ if ( replacement.isEmpty() ) {
+ throw new IllegalArgumentException( "Replacement cannot be empty" );
+ }
+ this.input = this.pattern
+ .matcher( this.input )
+ .replaceAll( replacement );
+
+ return this;
+ }
+
+ /**
+ * Replace all occurrences of the pattern in the input string with the replacement string
+ *
+ * @param pattern The pattern to match against
+ * @param replacement The replacement string
+ *
+ * @return The input string with all occurrences of the pattern replaced with the replacement string
+ */
+ public RegexMatcher replaceAll( Pattern pattern, String replacement ) {
+ Objects.requireNonNull( pattern, "Pattern cannot be null" );
+ Objects.requireNonNull( replacement, "Replacement cannot be null" );
+ this.input = pattern
+ .matcher( this.input )
+ .replaceAll( replacement );
+ return this;
+ }
+
+ /**
+ * Replace all occurrences of the pattern in the input string with the replacement string
+ *
+ * @param replacement The replacement string
+ *
+ * @return The input string with all occurrences of the pattern replaced with the replacement string
+ */
+ public String replaceAllAndGet( String replacement ) {
+ return this.replaceAll( replacement ).get();
+ }
+
+ /**
+ * Replace all occurrences of the pattern in the input string with the replacement string
+ *
+ * @param replacement The replacement string
+ *
+ * @return The input string with all occurrences of the pattern replaced with the replacement string
+ */
+ public String replaceAllAndGet( Pattern pattern, String replacement ) {
+ return this.replaceAll( pattern, replacement ).get();
+ }
+
+ /**
+ * Get's the input string as modified by the matcher
+ *
+ * @return The input string
+ */
+ public String get() {
+ return this.input;
+ }
+
+ /**
+ * Reset the input string to the original value
+ *
+ * @return The matcher instance
+ */
+ public RegexMatcher reset() {
+ this.input = this.original;
+ return this;
+ }
+
+ }
+
+}
From da062b343c0499ca75275c39810784cbb7c46d7e Mon Sep 17 00:00:00 2001
From: Luis Majano
Date: Mon, 2 Dec 2024 21:59:14 +0100
Subject: [PATCH 018/193] BL-784 validation done
---
src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java | 3 +++
src/main/java/ortus/boxlang/runtime/util/ValidationUtil.java | 4 ++--
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java b/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java
index cf5b5be84..684eb4745 100644
--- a/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java
+++ b/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java
@@ -32,6 +32,9 @@ public class RegexBuilder {
*/
public static final Pattern BACKSLASH = Pattern.compile( "\\\\" );
public static final Pattern COLON = Pattern.compile( ":" );
+ // cardNumber contains characters other than digit, space, or underscore
+ public static final Pattern CREDIT_CARD_NUMBERS = Pattern.compile( "[0-9 ,_-]+" );
+ public static final Pattern NO_DIGITS = Pattern.compile( "\\D" );
public static final Pattern PACKAGE_NAMES = Pattern.compile( "[^a-zA-Z0-9$\\.]" );
public static final Pattern PERIOD = Pattern.compile( "\\." );
public static final Pattern SLASH = Pattern.compile( "/" );
diff --git a/src/main/java/ortus/boxlang/runtime/util/ValidationUtil.java b/src/main/java/ortus/boxlang/runtime/util/ValidationUtil.java
index 53561c0d8..0e8f453fa 100644
--- a/src/main/java/ortus/boxlang/runtime/util/ValidationUtil.java
+++ b/src/main/java/ortus/boxlang/runtime/util/ValidationUtil.java
@@ -103,11 +103,11 @@ public class ValidationUtil {
public static boolean isValidCreditCard( String cardNumber ) {
int shortestValidCardLength = 12;
int longestValidCardLength = 19;
- if ( cardNumber == null || !cardNumber.matches( "[0-9 ,_-]+" ) ) {
+ if ( cardNumber == null || !RegexBuilder.of( cardNumber, RegexBuilder.CREDIT_CARD_NUMBERS ).matches() ) {
// cardNumber contains characters other than digit, space, or underscore
return false;
}
- String sanitized = cardNumber.replaceAll( "[^0-9]", "" );
+ String sanitized = RegexBuilder.of( cardNumber, RegexBuilder.NO_DIGITS ).replaceAllAndGet( "" );
if ( sanitized.length() < shortestValidCardLength || sanitized.length() > longestValidCardLength ) {
return false;
}
From 865dd6fdc40f3e9857ecf4590f15b0728abae474 Mon Sep 17 00:00:00 2001
From: Luis Majano
Date: Mon, 2 Dec 2024 22:18:28 +0100
Subject: [PATCH 019/193] BL-784 regex performance tuning on runtime
---
.../boxlang/runtime/modules/ModuleRecord.java | 10 ++++-----
.../runtime/services/FunctionService.java | 5 ++++-
.../ortus/boxlang/runtime/types/Array.java | 9 ++++----
.../ortus/boxlang/runtime/types/Struct.java | 3 ++-
.../runtime/types/StructMapWrapper.java | 3 ++-
.../runtime/types/util/StringUtil.java | 15 ++++++-------
.../boxlang/runtime/util/RegexBuilder.java | 21 ++++++++++---------
7 files changed, 37 insertions(+), 29 deletions(-)
diff --git a/src/main/java/ortus/boxlang/runtime/modules/ModuleRecord.java b/src/main/java/ortus/boxlang/runtime/modules/ModuleRecord.java
index 05b0a6c65..af8d0fbc6 100644
--- a/src/main/java/ortus/boxlang/runtime/modules/ModuleRecord.java
+++ b/src/main/java/ortus/boxlang/runtime/modules/ModuleRecord.java
@@ -57,7 +57,6 @@
import ortus.boxlang.runtime.loader.DynamicClassLoader;
import ortus.boxlang.runtime.runnables.IClassRunnable;
import ortus.boxlang.runtime.runnables.RunnableLoader;
-import ortus.boxlang.runtime.types.Argument;
import ortus.boxlang.runtime.scopes.ArgumentsScope;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.scopes.ThisScope;
@@ -67,6 +66,7 @@
import ortus.boxlang.runtime.services.IService;
import ortus.boxlang.runtime.services.InterceptorService;
import ortus.boxlang.runtime.services.ModuleService;
+import ortus.boxlang.runtime.types.Argument;
import ortus.boxlang.runtime.types.Array;
import ortus.boxlang.runtime.types.BoxLangType;
import ortus.boxlang.runtime.types.DynamicFunction;
@@ -304,7 +304,7 @@ public ModuleRecord loadDescriptor( IBoxContext context ) {
ResolvedFilePath.of(
null,
null,
- packageName.replaceAll( "\\.", Matcher.quoteReplacement( File.separator ) ) + File.separator + ModuleService.MODULE_DESCRIPTOR,
+ packageName.replace( ".", Matcher.quoteReplacement( File.separator ) ) + File.separator + ModuleService.MODULE_DESCRIPTOR,
descriptorPath
),
context
@@ -975,7 +975,7 @@ private Array discoverMemberMethods( IClassRunnable targetBIF, Key className ) {
return Array.of(
Struct.of(
// Default member name for class ArrayFoo with BoxType of Array is just foo()
- Key._NAME, className.getNameNoCase().replaceAll( boxType.getKey().getNameNoCase(), "" ),
+ Key._NAME, className.getNameNoCase().replace( boxType.getKey().getNameNoCase(), "" ),
Key.objectArgument, "",
Key.type, boxType
)
@@ -1009,7 +1009,7 @@ private Array discoverMemberMethods( IClassRunnable targetBIF, Key className ) {
// Prepare the record now
BoxLangType boxType = BoxLangType.valueOf( type.getNameNoCase() );
memberRecord.put( Key.type, boxType );
- memberRecord.computeIfAbsent( Key._NAME, k -> className.getNameNoCase().replaceAll( type.getNameNoCase(), "" )
+ memberRecord.computeIfAbsent( Key._NAME, k -> className.getNameNoCase().replace( type.getNameNoCase(), "" )
);
memberRecord.putIfAbsent( Key.objectArgument, "" );
result.push( memberRecord );
@@ -1075,7 +1075,7 @@ private IClassRunnable loadClassRunnable( File targetFile, String conventionsPat
null,
null,
( this.invocationPath + "." + conventionsPath )
- .replaceAll( "\\.", Matcher.quoteReplacement( File.separator ) )
+ .replace( ".", Matcher.quoteReplacement( File.separator ) )
+ File.separator
+ FilenameUtils.getBaseName( targetFile.getAbsolutePath() ),
targetFile.toPath()
diff --git a/src/main/java/ortus/boxlang/runtime/services/FunctionService.java b/src/main/java/ortus/boxlang/runtime/services/FunctionService.java
index baa593dee..05f976a42 100644
--- a/src/main/java/ortus/boxlang/runtime/services/FunctionService.java
+++ b/src/main/java/ortus/boxlang/runtime/services/FunctionService.java
@@ -24,6 +24,7 @@
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;
+import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -408,7 +409,9 @@ public void processBIFRegistration( Class> BIFClass, BIF function, String modu
Key memberKey;
if ( member.name().equals( "" ) ) {
// Default member name for class ArrayFoo with BoxType of Array is just foo()
- memberKey = Key.of( className.toLowerCase().replaceAll( member.type().name().toLowerCase(), "" ) );
+ memberKey = Key.of(
+ StringUtils.replace( className.toLowerCase(), member.type().name().toLowerCase(), "" )
+ );
} else {
memberKey = Key.of( member.name() );
}
diff --git a/src/main/java/ortus/boxlang/runtime/types/Array.java b/src/main/java/ortus/boxlang/runtime/types/Array.java
index b3f7fe158..384aa6390 100644
--- a/src/main/java/ortus/boxlang/runtime/types/Array.java
+++ b/src/main/java/ortus/boxlang/runtime/types/Array.java
@@ -57,6 +57,7 @@
import ortus.boxlang.runtime.types.meta.IListenable;
import ortus.boxlang.runtime.types.unmodifiable.UnmodifiableArray;
import ortus.boxlang.runtime.types.util.BLCollector;
+import ortus.boxlang.runtime.util.RegexBuilder;
/**
* The primary array class in BoxLang. This class wraps a Java List and provides additional functionality for BoxLang.
@@ -286,7 +287,7 @@ public List
*
* @param ctx the parse tree
- *
+ *
* @return The AST for the parenthesised expression
*/
@Override
@@ -306,7 +307,7 @@ public BoxExpression visitExprIllegalIdentifier( ExprIllegalIdentifierContext ct
*
*
* @param ctx the parse tree
- *
+ *
* @return the AST for a particular accessor operation
*/
@Override
@@ -679,9 +680,9 @@ public BoxExpression visitExprOr( ExprOrContext ctx ) {
* Generate the ELVIS AST node.
*
* @param bermudaTriangle the parse tree
- *
+ *
* @return The binary operation representing Elvis
- *
+ *
* @apiNote Elvis needs boats
*/
@Override
@@ -997,7 +998,7 @@ public BoxExpression visitExprLiterals( ExprLiteralsContext ctx ) {
*
*
* @param ctx the parse tree
- *
+ *
* @return Either a BoxIdentifier or BoxScope AST node
*/
@Override
@@ -1150,14 +1151,14 @@ private void processIfNotNull( List list, Consumer consumer ) {
*
*
* @param ctx the parse tree
- *
+ *
* @return the operation AST node
*/
public BoxComparisonOperator buildRelOp( RelOpsContext ctx ) {
// Convert the context to a string without whitespace. Then we can just have a string
// switch
- var op = ctx.getText().replaceAll( "\\s+", "" ).toUpperCase();
+ var op = RegexBuilder.stripWhitespace( ctx.getText() ).toUpperCase();
return switch ( op ) {
case "GT", ">", "GREATERTHAN" -> BoxComparisonOperator.GreaterThan;
@@ -1180,14 +1181,14 @@ public BoxComparisonOperator buildRelOp( RelOpsContext ctx ) {
*
*
* @param ctx the parse tree
- *
+ *
* @return the operation AST node
*/
public BoxBinaryOperator buildBinOp( BinOpsContext ctx ) {
// Convert the context to a string without whitespace. Then we can just have a string
// switch
- var op = ctx.getText().replaceAll( "\\s+", "" ).toUpperCase();
+ var op = RegexBuilder.stripWhitespace( ctx.getText() ).toUpperCase();
return switch ( op ) {
case "EQV" -> BoxBinaryOperator.Equivalence;
@@ -1202,7 +1203,7 @@ public BoxBinaryOperator buildBinOp( BinOpsContext ctx ) {
* Build the assignment operator from the token
*
* @param token The token to build the operator from
- *
+ *
* @return The BoxAssignmentOperator AST
*/
private BoxAssignmentOperator buildAssignOp( Token token ) {
@@ -1228,11 +1229,11 @@ private BoxAssignmentOperator buildAssignOp( Token token ) {
*
*
* @param prefix The possibly COLON-suffixed string for scope generation.
- *
+ *
* @return The BoxScope AST
*/
private BoxExpression buildScope( Token prefix ) {
- var scope = prefix.getText().replaceAll( "[:]+$", "" ).toUpperCase();
+ var scope = RegexBuilder.of( prefix.getText(), RegexBuilder.END_OF_LINE_COLONS ).replaceAllAndGet( "" ).toUpperCase();
return new BoxScope( scope, tools.getPosition( prefix ), prefix.getText() );
}
@@ -1241,7 +1242,7 @@ private BoxExpression buildScope( Token prefix ) {
* when not in a dot accessor.
*
* @param expr The expression to convert
- *
+ *
* @return The converted expression
*/
private BoxExpression convertDotElement( BoxExpression expr, boolean withScope ) {
@@ -1255,7 +1256,7 @@ private BoxExpression convertDotElement( BoxExpression expr, boolean withScope )
* Builds the correct type for a value key or value in a struct literal.
*
* @param ctx the ParserContext to accept and convert
- *
+ *
* @return the correct BoxType
*/
private BoxExpression buildKey( ExpressionContext ctx ) {
@@ -1275,7 +1276,7 @@ public BoxAssignmentModifier buildAssignmentModifier( AssignmentModifierContext
* a visitor to handle such nodes so that we can call the visitor even when the parser rejected the input
*
* @param node the error node
- *
+ *
* @return a New error node so that AST building can work
*/
@Override
diff --git a/src/main/java/ortus/boxlang/compiler/toolchain/CFExpressionVisitor.java b/src/main/java/ortus/boxlang/compiler/toolchain/CFExpressionVisitor.java
index d7b772f79..44488bd9a 100644
--- a/src/main/java/ortus/boxlang/compiler/toolchain/CFExpressionVisitor.java
+++ b/src/main/java/ortus/boxlang/compiler/toolchain/CFExpressionVisitor.java
@@ -142,6 +142,7 @@
import ortus.boxlang.parser.antlr.CFGrammar.TestExpressionContext;
import ortus.boxlang.parser.antlr.CFGrammarBaseVisitor;
import ortus.boxlang.runtime.types.exceptions.ExpressionException;
+import ortus.boxlang.runtime.util.RegexBuilder;
/**
* This class is responsible for visiting the parse tree and generating the AST for CFScript expressions.
@@ -170,7 +171,7 @@ public CFVisitor getStatementVisitor() {
* This is here simply to allow tests to resolve a single expression without having to walk exprStaments
*
* @param ctx the parse tree
- *
+ *
* @return the expression
*/
public BoxExpression visitTestExpression( TestExpressionContext ctx ) {
@@ -196,7 +197,7 @@ public BoxExpression visitExprStatInvocable( ExprStatInvocableContext ctx ) {
*
*
* @param ctx the parse tree
- *
+ *
* @return The AST for the parenthesised expression
*/
@Override
@@ -302,7 +303,7 @@ public BoxExpression visitExprIllegalIdentifier( ExprIllegalIdentifierContext ct
*
*
* @param ctx the parse tree
- *
+ *
* @return the AST for a particular accessor operation
*/
@Override
@@ -626,9 +627,9 @@ public BoxExpression visitExprOr( ExprOrContext ctx ) {
* Generate the ELVIS AST node.
*
* @param bermudaTriangle the parse tree
- *
+ *
* @return The binary operation representing Elvis
- *
+ *
* @apiNote Elvis needs boats
*/
@Override
@@ -926,7 +927,7 @@ public BoxExpression visitExprLiterals( ExprLiteralsContext ctx ) {
*
*
* @param ctx the parse tree
- *
+ *
* @return Either a BoxIdentifier or BoxScope AST node
*/
@Override
@@ -1088,14 +1089,14 @@ private void processIfNotNull( List list, Consumer consumer ) {
*
*
* @param ctx the parse tree
- *
+ *
* @return the operation AST node
*/
public BoxComparisonOperator buildRelOp( RelOpsContext ctx ) {
// Convert the context to a string without whitespace. Then we can just have a string
// switch
- var op = ctx.getText().replaceAll( "\\s+", "" ).toUpperCase();
+ var op = RegexBuilder.stripWhitespace( ctx.getText() ).toUpperCase();
return switch ( op ) {
case "GT", ">", "GREATERTHAN" -> BoxComparisonOperator.GreaterThan;
@@ -1118,14 +1119,14 @@ public BoxComparisonOperator buildRelOp( RelOpsContext ctx ) {
*
*
* @param ctx the parse tree
- *
+ *
* @return the operation AST node
*/
public BoxBinaryOperator buildBinOp( BinOpsContext ctx ) {
// Convert the context to a string without whitespace. Then we can just have a string
// switch
- var op = ctx.getText().replaceAll( "\\s+", "" ).toUpperCase();
+ var op = RegexBuilder.stripWhitespace( ctx.getText() ).toUpperCase();
return switch ( op ) {
case "EQV" -> BoxBinaryOperator.Equivalence;
@@ -1140,7 +1141,7 @@ public BoxBinaryOperator buildBinOp( BinOpsContext ctx ) {
* Build the assignment operator from the token
*
* @param token The token to build the operator from
- *
+ *
* @return The BoxAssignmentOperator AST
*/
private BoxAssignmentOperator buildAssignOp( Token token ) {
@@ -1166,11 +1167,11 @@ private BoxAssignmentOperator buildAssignOp( Token token ) {
*
*
* @param prefix The possibly COLON-suffixed string for scope generation.
- *
+ *
* @return The BoxScope AST
*/
private BoxExpression buildScope( Token prefix ) {
- var scope = prefix.getText().replaceAll( "[:]+$", "" ).toUpperCase();
+ var scope = RegexBuilder.of( prefix.getText(), RegexBuilder.END_OF_LINE_COLONS ).replaceAllAndGet( "" ).toUpperCase();
return new BoxScope( scope, tools.getPosition( prefix ), prefix.getText() );
}
@@ -1179,7 +1180,7 @@ private BoxExpression buildScope( Token prefix ) {
* when not in a dot accessor.
*
* @param expr The expression to convert
- *
+ *
* @return The converted expression
*/
private BoxExpression convertDotElement( BoxExpression expr, boolean withScope ) {
@@ -1193,7 +1194,7 @@ private BoxExpression convertDotElement( BoxExpression expr, boolean withScope )
* Builds the correct type for a value key or value in a struct literal.
*
* @param ctx the ParserContext to accept and convert
- *
+ *
* @return the correct BoxType
*/
private BoxExpression buildKey( ExpressionContext ctx ) {
@@ -1213,7 +1214,7 @@ public BoxAssignmentModifier buildAssignmentModifier( AssignmentModifierContext
* a visitor to handle such nodes so that we can call the visitor even when the parser rejected the input
*
* @param node the error node
- *
+ *
* @return a New error node so that AST building can work
*/
@Override
diff --git a/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java b/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java
index 9977a1d06..cd4764c92 100644
--- a/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java
+++ b/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java
@@ -35,9 +35,11 @@ public class RegexBuilder {
* Add as many patterns as needed, but make sure they are in all caps and alphabetically ordered.
*/
public static final Pattern BACKSLASH = Pattern.compile( "\\\\" );
- public static final Pattern COLON = Pattern.compile( ":" );
+ public static final Pattern CARRIAGE_RETURN = Pattern.compile( "\\r" );
public static final Pattern CF_SQL = Pattern.compile( "(?i)CF_SQL_" );
+ public static final Pattern COLON = Pattern.compile( ":" );
public static final Pattern CREDIT_CARD_NUMBERS = Pattern.compile( "[0-9 ,_-]+" );
+ public static final Pattern END_OF_LINE_COLONS = Pattern.compile( ":+$" );
public static final Pattern LINE_ENDINGS = Pattern.compile( "\\r?\\n" );
public static final Pattern MULTILINE_START_OF_LINE = Pattern.compile( "(?m)^" );
public static final Pattern MULTIPLE_SPACES = Pattern.compile( "\\s+" );
@@ -55,7 +57,9 @@ public class RegexBuilder {
public static final Pattern SQL_PARENTHESIS_START = Pattern.compile( "\\((\\w|\\'|\"|\\`)" );
public static final Pattern STARTS_WITH_DIGIT = Pattern.compile( "^\\d.*" );
public static final Pattern TWO_DOTS = Pattern.compile( "\\.{2}" );
+ public static final Pattern UPPERCASE_GROUP = Pattern.compile( "([A-Z])" );
public static final Pattern WHITESPACE = Pattern.compile( "\\s" );
+ public static final Pattern VOWELS = Pattern.compile( "^[aeiou].*" );
/**
* Build a matcher for the given pattern lookup
@@ -92,6 +96,17 @@ public static RegexMatcher of( String input, Pattern pattern ) {
return new RegexMatcher( input ).match( pattern );
}
+ /**
+ * Conmmonly used utility to strip whitespace from a string
+ */
+ public static String stripWhitespace( String input ) {
+ return of( input, WHITESPACE ).replaceAllAndGet( "" );
+ }
+
+ public static String stripCarriageReturns( String input ) {
+ return of( input, CARRIAGE_RETURN ).replaceAllAndGet( "" );
+ }
+
/**
* The RegexMatcher class is used to match a pattern against an input string
* by either using a pre-complied pattern or a string pattern that will be compiled on the fly.
From c1b8a3535c6aaf1f73d39d7b37081673e920b046 Mon Sep 17 00:00:00 2001
From: Eric Peterson
Date: Wed, 4 Dec 2024 15:24:23 -0600
Subject: [PATCH 045/193] Fix for potentially null expand var
---
src/main/resources/dump/html/Array.bxm | 2 +-
src/main/resources/dump/html/Struct.bxm | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/main/resources/dump/html/Array.bxm b/src/main/resources/dump/html/Array.bxm
index 16ba18747..1d0055226 100644
--- a/src/main/resources/dump/html/Array.bxm
+++ b/src/main/resources/dump/html/Array.bxm
@@ -50,7 +50,7 @@
diff --git a/src/main/resources/dump/html/Struct.bxm b/src/main/resources/dump/html/Struct.bxm
index c37566130..aaf59d8f2 100644
--- a/src/main/resources/dump/html/Struct.bxm
+++ b/src/main/resources/dump/html/Struct.bxm
@@ -86,10 +86,10 @@
tabindex="0"
>
#encodeForHTML( key )#
-
+
-
+
From 54cc6f31c73c85176b11f9e1b91ba3dba93471d1 Mon Sep 17 00:00:00 2001
From: Eric Peterson
Date: Wed, 4 Dec 2024 16:06:40 -0600
Subject: [PATCH 046/193] Fix for an array of args being passed to invoke and
then onMissingMethod
---
.../ortus/boxlang/runtime/util/ArgumentUtil.java | 6 ++++++
src/test/java/TestCases/phase3/ClassTest.java | 13 +++++++++++++
2 files changed, 19 insertions(+)
diff --git a/src/main/java/ortus/boxlang/runtime/util/ArgumentUtil.java b/src/main/java/ortus/boxlang/runtime/util/ArgumentUtil.java
index d911f8e54..5b885d1e9 100644
--- a/src/main/java/ortus/boxlang/runtime/util/ArgumentUtil.java
+++ b/src/main/java/ortus/boxlang/runtime/util/ArgumentUtil.java
@@ -29,6 +29,7 @@
import ortus.boxlang.runtime.scopes.IntKey;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.types.Argument;
+import ortus.boxlang.runtime.types.Array;
import ortus.boxlang.runtime.types.Function;
import ortus.boxlang.runtime.types.IStruct;
import ortus.boxlang.runtime.types.NullValue;
@@ -211,6 +212,11 @@ public static ArgumentsScope createArgumentsScope( IBoxContext context, Map
Date: Wed, 4 Dec 2024 16:08:42 -0600
Subject: [PATCH 047/193] Handle arguments coming in as an array
---
.../boxlang/runtime/interop/DynamicInteropService.java | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/main/java/ortus/boxlang/runtime/interop/DynamicInteropService.java b/src/main/java/ortus/boxlang/runtime/interop/DynamicInteropService.java
index 76baed54f..2a8805169 100644
--- a/src/main/java/ortus/boxlang/runtime/interop/DynamicInteropService.java
+++ b/src/main/java/ortus/boxlang/runtime/interop/DynamicInteropService.java
@@ -508,6 +508,13 @@ private static T bootstrapBLClass( IBoxContext context, IClassRunnable boxCl
}
}
namedArgs.remove( Key.argumentCollection );
+ } else if ( namedArgs.containsKey( Key.argumentCollection ) && namedArgs.get( Key.argumentCollection ) instanceof Array argArray ) {
+ // Create copy of named args, merge in argCollection without overwriting, and delete arg collection key from copy of namedargs
+ namedArgs = new HashMap<>( namedArgs );
+ for ( int i = 0; i < argArray.size(); i++ ) {
+ namedArgs.put( Key.of( i + 1 ), argArray.get( i ) );
+ }
+ namedArgs.remove( Key.argumentCollection );
}
// loop over args and invoke setter methods for each
for ( Map.Entry entry : namedArgs.entrySet() ) {
From f3bf112a550e2b5dfc15105e052b344a237afe7d Mon Sep 17 00:00:00 2001
From: Jacob Beers
Date: Wed, 4 Dec 2024 17:25:33 -0600
Subject: [PATCH 048/193] BL-806 ASM fixes
---
.../expression/BoxBreakTransformer.java | 6 ---
.../expression/BoxSwitchTransformer.java | 35 ++++++++++----
.../statement/BoxWhileTransformer.java | 18 ++++---
.../ortus/boxlang/compiler/CompileIssue1.cfc | 18 +++++++
.../boxlang/compiler/FileTesterTest.java | 47 +++++++++++++++++++
5 files changed, 104 insertions(+), 20 deletions(-)
create mode 100644 src/test/java/ortus/boxlang/compiler/CompileIssue1.cfc
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxBreakTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxBreakTransformer.java
index f2c790965..4f7ed2870 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxBreakTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxBreakTransformer.java
@@ -63,12 +63,6 @@ public List transform( BoxNode node, TransformerContext contex
labelTarget = getTargetAncestor( breakNode );
}
- int intermediateCount = countIntermediateLoops( labelTarget, breakNode );
-
- for ( int i = 0; i < intermediateCount; i++ ) {
- nodes.add( new InsnNode( Opcodes.POP ) );
- }
-
if ( returnContext.nullable
|| exitsAllowed.equals( ExitsAllowed.FUNCTION ) ) {
nodes.add( new InsnNode( Opcodes.ACONST_NULL ) );
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxSwitchTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxSwitchTransformer.java
index e8e86c337..d08ed7b52 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxSwitchTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/expression/BoxSwitchTransformer.java
@@ -25,8 +25,10 @@
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.VarInsnNode;
import ortus.boxlang.compiler.asmboxpiler.AsmHelper;
+import ortus.boxlang.compiler.asmboxpiler.MethodContextTracker;
import ortus.boxlang.compiler.asmboxpiler.Transpiler;
import ortus.boxlang.compiler.asmboxpiler.transformer.AbstractTransformer;
import ortus.boxlang.compiler.asmboxpiler.transformer.ReturnValueContext;
@@ -50,14 +52,19 @@ public List transform( BoxNode node, TransformerContext contex
List condition = transpiler.transform( boxSwitch.getCondition(), TransformerContext.NONE, ReturnValueContext.VALUE );
List nodes = new ArrayList<>();
+ MethodContextTracker tracker = transpiler.getCurrentMethodContextTracker().get();
AsmHelper.addDebugLabel( nodes, "BoxSwitch" );
nodes.addAll( condition );
+ var switchConditionVarStore = tracker.storeNewVariable( Opcodes.ASTORE );
+ nodes.addAll( switchConditionVarStore.nodes() );
nodes.add( new LdcInsnNode( 0 ) );
+ var switchVarStore = tracker.storeNewVariable( Opcodes.ISTORE );
+ nodes.addAll( switchVarStore.nodes() );
LabelNode endLabel = new LabelNode();
LabelNode breakTarget = new LabelNode();
- transpiler.getCurrentMethodContextTracker().ifPresent( t -> t.setBreak( boxSwitch, endLabel ) );
+ tracker.setBreak( boxSwitch, breakTarget );
boxSwitch.getCases().forEach( c -> {
if ( c.getCondition() == null ) {
@@ -66,9 +73,11 @@ public List transform( BoxNode node, TransformerContext contex
AsmHelper.addDebugLabel( nodes, "BoxSwitch - case start" );
LabelNode startOfCase = new LabelNode(), endOfCase = new LabelNode(), endOfAll = new LabelNode();
+ nodes.add( new VarInsnNode( Opcodes.ILOAD, switchVarStore.index() ) );
nodes.add( new JumpInsnNode( Opcodes.IFNE, startOfCase ) );
// this dupes the condition
- nodes.add( new InsnNode( Opcodes.DUP ) );
+ // nodes.add( new InsnNode( Opcodes.DUP ) );
+ nodes.add( new VarInsnNode( Opcodes.ALOAD, switchConditionVarStore.index() ) );
if ( c.getDelimiter() == null ) {
nodes.addAll( transpiler.transform( c.getCondition(), TransformerContext.NONE, ReturnValueContext.VALUE ) );
@@ -110,12 +119,18 @@ public List transform( BoxNode node, TransformerContext contex
nodes.add( new JumpInsnNode( Opcodes.IFEQ, endOfCase ) );
nodes.add( startOfCase );
- c.getBody().forEach( stmt -> nodes.addAll( transpiler.transform( stmt, TransformerContext.NONE ) ) );
+ c.getBody().forEach( stmt -> nodes.addAll( transpiler.transform( stmt, TransformerContext.NONE, ReturnValueContext.EMPTY_UNLESS_JUMPING ) ) );
nodes.add( new LdcInsnNode( 1 ) );
+ nodes.addAll( switchVarStore.nodes() );
+ AsmHelper.addDebugLabel( nodes, "BoxSwitch - goto endOfAll" );
nodes.add( new JumpInsnNode( Opcodes.GOTO, endOfAll ) );
+ AsmHelper.addDebugLabel( nodes, "BoxSwitch - endOfCase" );
nodes.add( endOfCase );
nodes.add( new LdcInsnNode( 0 ) );
+ nodes.addAll( switchVarStore.nodes() );
+
+ AsmHelper.addDebugLabel( nodes, "BoxSwitch - endOfAll" );
nodes.add( endOfAll );
AsmHelper.addDebugLabel( nodes, "BoxSwitch - case end" );
} );
@@ -131,23 +146,27 @@ public List transform( BoxNode node, TransformerContext contex
hasDefault = true;
// pop the initial 0 constant in case we didn't match any cases
- nodes.add( new InsnNode( Opcodes.POP ) );
+ // nodes.add( new InsnNode( Opcodes.POP ) );
// pop the condition off the stack
// nodes.add( new InsnNode( Opcodes.POP ) );
- c.getBody().forEach( stmt -> nodes.addAll( transpiler.transform( stmt, TransformerContext.NONE ) ) );
+ c.getBody().forEach( stmt -> nodes.addAll( transpiler.transform( stmt, TransformerContext.NONE, ReturnValueContext.EMPTY_UNLESS_JUMPING ) ) );
+ AsmHelper.addDebugLabel( nodes, "BoxSwitch - goto Endlabel" );
nodes.add( new JumpInsnNode( Opcodes.GOTO, endLabel ) );
}
}
-
+ nodes.add( new JumpInsnNode( Opcodes.GOTO, endLabel ) );
// pop the initial 0 constant in case we didn't match any cases
+ AsmHelper.addDebugLabel( nodes, "BoxSwitch - breakTarget" );
+ nodes.add( breakTarget );
nodes.add( new InsnNode( Opcodes.POP ) );
+
+ AsmHelper.addDebugLabel( nodes, "BoxSwitch - endLabel" );
nodes.add( endLabel );
// pop the condition off the stack
- nodes.add( new InsnNode( Opcodes.POP ) );
- // nodes.add( breakTarget );
+ // nodes.add( new InsnNode( Opcodes.POP ) );
if ( !returnContext.empty ) {
nodes.add( new InsnNode( Opcodes.ACONST_NULL ) );
diff --git a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxWhileTransformer.java b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxWhileTransformer.java
index 3ab60d6bf..fab598025 100644
--- a/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxWhileTransformer.java
+++ b/src/main/java/ortus/boxlang/compiler/asmboxpiler/transformer/statement/BoxWhileTransformer.java
@@ -24,6 +24,7 @@
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.VarInsnNode;
import ortus.boxlang.compiler.asmboxpiler.AsmHelper;
import ortus.boxlang.compiler.asmboxpiler.MethodContextTracker;
@@ -62,15 +63,18 @@ public List transform( BoxNode node, TransformerContext contex
// this is to allow the statement to return an expression in the case of a BoxScript execution
// if ( returnContext == ReturnValueContext.VALUE_OR_NULL ) {
nodes.add( new InsnNode( Opcodes.ACONST_NULL ) );
- nodes.add( new InsnNode( Opcodes.ACONST_NULL ) );
+ // nodes.add( new InsnNode( Opcodes.ACONST_NULL ) );
+ var varStore = tracker.storeNewVariable( Opcodes.ASTORE );
+
// }
+ AsmHelper.addDebugLabel( nodes, "BoxWhile - start label" );
nodes.add( start );
-
+ nodes.addAll( varStore.nodes() );
// every iteration we will swap the values and pop in order to remove the older value
// if ( returnContext == ReturnValueContext.VALUE_OR_NULL ) {
- nodes.add( new InsnNode( Opcodes.SWAP ) );
- nodes.add( new InsnNode( Opcodes.POP ) );
+ // nodes.add( new InsnNode( Opcodes.SWAP ) );
+ // nodes.add( new InsnNode( Opcodes.POP ) );
// }
nodes.addAll( transpiler.transform( boxWhile.getCondition(), TransformerContext.RIGHT, ReturnValueContext.VALUE ) );
@@ -89,18 +93,20 @@ public List transform( BoxNode node, TransformerContext contex
nodes.add( new JumpInsnNode( Opcodes.IFEQ, end ) );
nodes.addAll( transpiler.transform( boxWhile.getBody(), TransformerContext.NONE, ReturnValueContext.VALUE_OR_NULL ) );
+
AsmHelper.addDebugLabel( nodes, "BoxWhile - jump start" );
nodes.add( new JumpInsnNode( Opcodes.GOTO, start ) );
AsmHelper.addDebugLabel( nodes, "BoxWhile - breakTarget" );
nodes.add( breakTarget );
- nodes.add( new InsnNode( Opcodes.SWAP ) );
- nodes.add( new InsnNode( Opcodes.POP ) );
+ nodes.addAll( varStore.nodes() );
AsmHelper.addDebugLabel( nodes, "BoxWhile - end label" );
nodes.add( end );
+ nodes.add( new VarInsnNode( Opcodes.ALOAD, varStore.index() ) );
+
// every iteration we will swap the values and pop in order to remove the older value
if ( returnContext == ReturnValueContext.EMPTY || returnContext == ReturnValueContext.EMPTY_UNLESS_JUMPING ) {
nodes.add( new InsnNode( Opcodes.POP ) );
diff --git a/src/test/java/ortus/boxlang/compiler/CompileIssue1.cfc b/src/test/java/ortus/boxlang/compiler/CompileIssue1.cfc
new file mode 100644
index 000000000..905c4149f
--- /dev/null
+++ b/src/test/java/ortus/boxlang/compiler/CompileIssue1.cfc
@@ -0,0 +1,18 @@
+
+ component {
+
+
+
+ function serializeReferenceEntity(){
+ switch( "test" ){
+ case "x":
+ try{
+
+ } catch( any e ){
+
+ }
+ }
+
+ }
+
+}
diff --git a/src/test/java/ortus/boxlang/compiler/FileTesterTest.java b/src/test/java/ortus/boxlang/compiler/FileTesterTest.java
index b19e47cf7..6cf129c1a 100644
--- a/src/test/java/ortus/boxlang/compiler/FileTesterTest.java
+++ b/src/test/java/ortus/boxlang/compiler/FileTesterTest.java
@@ -160,6 +160,53 @@ function foo() {
""",
context );
+ @DisplayName( "Test valueList() to queryColumnData().toList()" )
+ @Test
+ public void testCompileIssue1() {
+ // instance.useJavaBoxpiler();
+ instance.executeSource(
+ """
+ a = new src.test.java.ortus.boxlang.compiler.CompileIssue1();
+ """,
+ context );
+ }
+
+ @DisplayName( "Test valueList() to queryColumnData().toList()" )
+ @Test
+ public void zzz() {
+ // instance.useJavaBoxpiler();
+ instance.executeSource(
+ """
+ a = 0
+ while( a < 5 ){
+ try{
+
+
+ }
+ catch( any e ){
+
+ }
+ a++;
+ }
+ """,
+ context );
+ }
+
+ @DisplayName( "Test valueList() to queryColumnData().toList()" )
+ @Test
+ public void switchBreak() {
+ // instance.useJavaBoxpiler();
+ // @formatter:off
+ instance.executeSource("""
+ a = 1;
+ while(a < 10) {
+ if(true) {
+ break;
+ }
+ }
+ """,
+ context );
+ // @formatter:on
}
}
From 732c48c3b3bd00187a4a9f8f5fa495fa62ef4619 Mon Sep 17 00:00:00 2001
From: Jacob Beers
Date: Wed, 4 Dec 2024 17:49:44 -0600
Subject: [PATCH 049/193] Missing curly brace
---
src/test/java/ortus/boxlang/compiler/FileTesterTest.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/test/java/ortus/boxlang/compiler/FileTesterTest.java b/src/test/java/ortus/boxlang/compiler/FileTesterTest.java
index 6cf129c1a..885408a26 100644
--- a/src/test/java/ortus/boxlang/compiler/FileTesterTest.java
+++ b/src/test/java/ortus/boxlang/compiler/FileTesterTest.java
@@ -159,6 +159,7 @@ function foo() {
}
""",
context );
+ }
@DisplayName( "Test valueList() to queryColumnData().toList()" )
@Test
From 5d55a35cdfbc4db22f164d31e4bb24f9f75b76b2 Mon Sep 17 00:00:00 2001
From: Brad Wood
Date: Wed, 4 Dec 2024 18:01:05 -0600
Subject: [PATCH 050/193] BL-813
---
.../runtime/context/ThreadBoxContext.java | 5 +++
.../runtime/components/async/ThreadTest.java | 38 +++++++++++++++----
2 files changed, 35 insertions(+), 8 deletions(-)
diff --git a/src/main/java/ortus/boxlang/runtime/context/ThreadBoxContext.java b/src/main/java/ortus/boxlang/runtime/context/ThreadBoxContext.java
index ce80ba91d..99c976cc2 100644
--- a/src/main/java/ortus/boxlang/runtime/context/ThreadBoxContext.java
+++ b/src/main/java/ortus/boxlang/runtime/context/ThreadBoxContext.java
@@ -157,6 +157,11 @@ public IStruct getVisibleScopes( IStruct scopes, boolean nearby, boolean shallow
@Override
public ScopeSearchResult scopeFindNearby( Key key, IScope defaultScope, boolean shallow ) {
+ // Look in the local scope first
+ if ( key.equals( localScope.getName() ) ) {
+ return new ScopeSearchResult( localScope, localScope, key, true );
+ }
+
Object result = localScope.getRaw( key );
// Null means not found
if ( isDefined( result ) ) {
diff --git a/src/test/java/ortus/boxlang/runtime/components/async/ThreadTest.java b/src/test/java/ortus/boxlang/runtime/components/async/ThreadTest.java
index 807fef5db..5f50d3cab 100644
--- a/src/test/java/ortus/boxlang/runtime/components/async/ThreadTest.java
+++ b/src/test/java/ortus/boxlang/runtime/components/async/ThreadTest.java
@@ -178,18 +178,40 @@ public void testHasTheadScope() {
public void testCanJoinThreadNoTimeout() {
// @formatter:off
instance.executeSource(
- """
- thread name="myThread" {
- sleep( 2000 )
- }
- thread name="myThread" action="join";
- result = myThread;
- """,
- context, BoxSourceType.CFSCRIPT );
+ """
+ thread name="myThread" {
+ sleep( 2000 )
+ }
+ thread name="myThread" action="join";
+ result = myThread;
+ """,
+ context, BoxSourceType.CFSCRIPT );
// @formatter:on
assertThat( variables.getAsStruct( result ).get( Key.status ) ).isEqualTo( "COMPLETED" );
}
+ @DisplayName( "It can use local scope" )
+ @Test
+ public void testCanUseLocalScope() {
+ // @formatter:off
+ instance.executeSource(
+ """
+ thread name="myThread" {
+ local.foo = "bar";
+ variables.result = local.foo;
+ variables.threadContext = getBoxContext();
+ }
+ thread name="myThread" action="join";
+
+ """,
+ context, BoxSourceType.CFSCRIPT );
+ // @formatter:on
+ assertThat( variables.get( Key.of( "result" ) ) ).isEqualTo( "bar" );
+ // ensure variables scope doesn't have local key
+ assertThat( variables ).doesNotContainKey( Key.of( "local" ) );
+ assertThat( ( ( IBoxContext ) variables.get( Key.of( "threadContext" ) ) ).getScopeNearby( Key.of( "local" ) ) ).doesNotContainKey( Key.of( "local" ) );
+ }
+
@DisplayName( "It can join thread zero timeout" )
@Test
public void testCanJoinThreadZeroTimeout() {
From 534e2d922614d532a137ebb1890f6068649da10d Mon Sep 17 00:00:00 2001
From: Luis Majano
Date: Wed, 4 Dec 2024 16:10:34 -0600
Subject: [PATCH 051/193] BL-784 #resolve migration to smart regex builders
---
.../boxlang/debugger/BoxLangDebugger.java | 4 +-
.../runtime/bifs/global/list/ListQualify.java | 19 +++---
.../runtime/bifs/global/string/ReEscape.java | 2 -
.../runtime/bifs/global/string/ReFind.java | 4 +-
.../runtime/bifs/global/string/ReMatch.java | 17 ++---
.../runtime/bifs/global/string/ReReplace.java | 8 +--
.../dynamic/ExpressionInterpreter.java | 3 +-
.../dynamic/casters/DateTimeCaster.java | 3 +-
.../loader/resolvers/JavaResolver.java | 10 ++-
.../boxlang/runtime/modules/ModuleRecord.java | 5 +-
.../runtime/types/util/DateTimeHelper.java | 5 +-
.../boxlang/runtime/util/RegexBuilder.java | 49 ++++++++++++-
.../boxlang/runtime/util/ValidationUtil.java | 68 +++----------------
.../bifs/global/string/ReMatchNoCaseTest.java | 7 --
14 files changed, 97 insertions(+), 107 deletions(-)
diff --git a/src/main/java/ortus/boxlang/debugger/BoxLangDebugger.java b/src/main/java/ortus/boxlang/debugger/BoxLangDebugger.java
index c4341f801..11de5ea42 100644
--- a/src/main/java/ortus/boxlang/debugger/BoxLangDebugger.java
+++ b/src/main/java/ortus/boxlang/debugger/BoxLangDebugger.java
@@ -34,6 +34,8 @@
import java.util.regex.Pattern;
import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+
import com.sun.jdi.AbsentInformationException;
import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.ClassType;
@@ -589,7 +591,7 @@ private void handleThreadDeathEvent( EventSet eventSet, ThreadDeathEvent event )
}
private boolean isBoxlangThread( ThreadReference threadRef ) {
- return threadRef.name().matches( "BL-Thread" );
+ return StringUtils.containsIgnoreCase( threadRef.name(), "BL-Thread" );
}
private void handleExceptionEvent( EventSet eventSet, ExceptionEvent exceptionEvent ) {
diff --git a/src/main/java/ortus/boxlang/runtime/bifs/global/list/ListQualify.java b/src/main/java/ortus/boxlang/runtime/bifs/global/list/ListQualify.java
index a90ff8773..adb13edd8 100644
--- a/src/main/java/ortus/boxlang/runtime/bifs/global/list/ListQualify.java
+++ b/src/main/java/ortus/boxlang/runtime/bifs/global/list/ListQualify.java
@@ -1,4 +1,3 @@
-
/**
* [BoxLang]
*
@@ -16,7 +15,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package ortus.boxlang.runtime.bifs.global.list;
import ortus.boxlang.runtime.bifs.BIF;
@@ -30,13 +28,14 @@
import ortus.boxlang.runtime.types.Argument;
import ortus.boxlang.runtime.types.BoxLangType;
import ortus.boxlang.runtime.types.util.ListUtil;
+import ortus.boxlang.runtime.util.RegexBuilder;
@BoxBIF
@BoxMember( type = BoxLangType.STRING, name = "ListQualify" )
public class ListQualify extends BIF {
- private final String elementsChar = "char";
+ private static final String ELEMENTS_CHAR = "char";
/**
* Constructor
@@ -59,17 +58,16 @@ public ListQualify() {
* @param arguments Argument scope for the BIF.
*
* @argument.list The list to qualify.
- *
+ *
* @argument.qualifier The string to insert at the beginning and end of each element.
- *
+ *
* @argument.delimiter The delimiter used in the list.
- *
+ *
* @argument.elements The elements to qualify. If set to "char", only elements that are all alphabetic characters will be qualified.
- *
+ *
* @argument.includeEmptyFields If true, empty fields will be qualified.
*/
public Object _invoke( IBoxContext context, ArgumentsScope arguments ) {
-
String elements = arguments.getAsString( Key.elements );
String qualifier = arguments.getAsString( Key.qualifier );
@@ -81,8 +79,9 @@ public Object _invoke( IBoxContext context, ArgumentsScope arguments ) {
arguments.getAsBoolean( Key.includeEmptyFields ),
true
).stream().map( item -> {
- if ( elements.equals( elementsChar ) ? StringCaster.cast( item ).matches( "^[a-zA-Z]*$" ) : true ) {
- return qualifier + item + qualifier;
+
+ if ( elements.equals( ELEMENTS_CHAR ) ? RegexBuilder.of( StringCaster.cast( item ), RegexBuilder.ALPHA ).matches() : true ) {
+ return new StringBuilder( qualifier ).append( item ).append( qualifier ).toString();
} else {
return item;
}
diff --git a/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReEscape.java b/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReEscape.java
index f34df7965..e930dc2a0 100644
--- a/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReEscape.java
+++ b/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReEscape.java
@@ -35,12 +35,10 @@ public ReEscape() {
}
/**
- *
* Escapes regular expression control characters within a string.
* If a string is "foo.bar" and you want to escape it for use in a regular expression, you would use this BIF.
* Escaped Pattern will be "foo\\.bar"
*
- *
* @param context The context in which the BIF is being invoked.
* @param arguments Argument scope for the BIF.
*
diff --git a/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReFind.java b/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReFind.java
index cdce31df5..f7aef11cc 100644
--- a/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReFind.java
+++ b/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReFind.java
@@ -16,7 +16,6 @@
import java.util.Set;
import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import ortus.boxlang.runtime.bifs.BIF;
import ortus.boxlang.runtime.bifs.BoxBIF;
@@ -29,6 +28,7 @@
import ortus.boxlang.runtime.types.BoxLangType;
import ortus.boxlang.runtime.types.Struct;
import ortus.boxlang.runtime.types.util.RegexUtil;
+import ortus.boxlang.runtime.util.RegexBuilder;
import ortus.boxlang.runtime.validation.Validator;
@BoxBIF
@@ -93,7 +93,7 @@ public Object _invoke( IBoxContext context, ArgumentsScope arguments ) {
start = 1;
}
// Find the first occurrence of the substring from the specified start position
- Matcher matcher = java.util.regex.Pattern.compile( reg_expression, noCase ? Pattern.CASE_INSENSITIVE : 0 ).matcher( string );
+ Matcher matcher = RegexBuilder.of( string, reg_expression, noCase ).matcher();
if ( start > 1 ) {
matcher.region( start - 1, string.length() );
}
diff --git a/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReMatch.java b/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReMatch.java
index c3d4f95d4..b639cbbf3 100644
--- a/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReMatch.java
+++ b/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReMatch.java
@@ -26,6 +26,7 @@
import ortus.boxlang.runtime.types.Array;
import ortus.boxlang.runtime.types.BoxLangType;
import ortus.boxlang.runtime.types.util.RegexUtil;
+import ortus.boxlang.runtime.util.RegexBuilder;
@BoxBIF
@BoxBIF( alias = "reMatchNoCase" )
@@ -47,16 +48,16 @@ public ReMatch() {
}
/**
- *
+ *
* Uses a regular expression (RE) to search a string for a pattern, starting from a specified position.
- *
+ *
* @param context The context in which the BIF is being invoked.
* @param arguments Argument scope for the BIF.
- *
+ *
* @argument.reg_expression The regular expression to search for
- *
+ *
* @argument.string The string to serach in
- *
+ *
*/
public Object _invoke( IBoxContext context, ArgumentsScope arguments ) {
String reg_expression = arguments.getAsString( Key.reg_expression );
@@ -67,16 +68,12 @@ public Object _invoke( IBoxContext context, ArgumentsScope arguments ) {
return new Array();
}
- if ( noCase ) {
- reg_expression = "(?i)" + reg_expression;
- }
-
// Posix replacement for character classes
reg_expression = RegexUtil.posixReplace( reg_expression, noCase );
// Ignore non-quantifier curly braces like PERL
reg_expression = RegexUtil.replaceNonQuantiferCurlyBraces( reg_expression );
- Matcher matcher = java.util.regex.Pattern.compile( reg_expression ).matcher( string );
+ Matcher matcher = RegexBuilder.of( string, reg_expression, noCase ).matcher();
Array result = new Array();
while ( matcher.find() ) {
diff --git a/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReReplace.java b/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReReplace.java
index b596b3ec4..97847c88e 100644
--- a/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReReplace.java
+++ b/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReReplace.java
@@ -16,7 +16,6 @@
import java.util.Set;
import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import ortus.boxlang.runtime.bifs.BIF;
import ortus.boxlang.runtime.bifs.BoxBIF;
@@ -27,6 +26,7 @@
import ortus.boxlang.runtime.types.Argument;
import ortus.boxlang.runtime.types.BoxLangType;
import ortus.boxlang.runtime.types.util.RegexUtil;
+import ortus.boxlang.runtime.util.RegexBuilder;
import ortus.boxlang.runtime.validation.Validator;
@BoxBIF
@@ -73,10 +73,6 @@ public Object _invoke( IBoxContext context, ArgumentsScope arguments ) {
String scope = arguments.getAsString( Key.scope ).toLowerCase();
boolean noCase = arguments.get( BIF.__functionName ).equals( reFindNoCase );
- if ( noCase ) {
- regex = "(?i)" + regex;
- }
-
// Default string if null
if ( string == null ) {
string = "";
@@ -94,7 +90,7 @@ public Object _invoke( IBoxContext context, ArgumentsScope arguments ) {
regex = RegexUtil.replaceNonQuantiferCurlyBraces( regex );
StringBuffer result = new StringBuffer();
- Matcher matcher = Pattern.compile( regex ).matcher( string );
+ Matcher matcher = RegexBuilder.of( string, regex, noCase ).matcher();
boolean upperCase = false;
boolean lowerCase = false;
diff --git a/src/main/java/ortus/boxlang/runtime/dynamic/ExpressionInterpreter.java b/src/main/java/ortus/boxlang/runtime/dynamic/ExpressionInterpreter.java
index 07adade4c..4cd20680d 100644
--- a/src/main/java/ortus/boxlang/runtime/dynamic/ExpressionInterpreter.java
+++ b/src/main/java/ortus/boxlang/runtime/dynamic/ExpressionInterpreter.java
@@ -33,6 +33,7 @@
import ortus.boxlang.runtime.types.exceptions.ExpressionException;
import ortus.boxlang.runtime.types.exceptions.KeyNotFoundException;
import ortus.boxlang.runtime.types.exceptions.ScopeNotFoundException;
+import ortus.boxlang.runtime.util.RegexBuilder;
/**
* I handle interpreting expressions
@@ -68,7 +69,7 @@ public static Object getVariable( IBoxContext context, String expression, boolea
return expression.substring( 1, expression.length() - 1 ).replace( "''", "'" );
}
// If expression is a number, return it directly
- if ( expression.matches( "^-?\\d+(\\.\\d+)?$" ) ) {
+ if ( RegexBuilder.of( expression, RegexBuilder.NUMBERS ).matches() ) {
return NumberCaster.cast( expression );
}
// Check for true/false
diff --git a/src/main/java/ortus/boxlang/runtime/dynamic/casters/DateTimeCaster.java b/src/main/java/ortus/boxlang/runtime/dynamic/casters/DateTimeCaster.java
index 2239d8d95..6a465042f 100644
--- a/src/main/java/ortus/boxlang/runtime/dynamic/casters/DateTimeCaster.java
+++ b/src/main/java/ortus/boxlang/runtime/dynamic/casters/DateTimeCaster.java
@@ -27,6 +27,7 @@
import ortus.boxlang.runtime.interop.DynamicObject;
import ortus.boxlang.runtime.types.DateTime;
import ortus.boxlang.runtime.types.exceptions.BoxCastException;
+import ortus.boxlang.runtime.util.RegexBuilder;
/**
* I cast to DateTime objects
@@ -220,7 +221,7 @@ public static DateTime cast( Object object, Boolean fail, ZoneId timezone, Boole
try {
// Timestamp string "^\{ts ([^\}])*\}" - {ts 2023-01-01 12:00:00}
- if ( targetString.matches( "^\\{ts ([^\\}]*)\\}" ) ) {
+ if ( RegexBuilder.of( targetString, RegexBuilder.TIMESTAMP ).matches() ) {
return new DateTime(
LocalDateTime.parse(
targetString.trim(),
diff --git a/src/main/java/ortus/boxlang/runtime/loader/resolvers/JavaResolver.java b/src/main/java/ortus/boxlang/runtime/loader/resolvers/JavaResolver.java
index ff3c346e9..4b9165fb1 100644
--- a/src/main/java/ortus/boxlang/runtime/loader/resolvers/JavaResolver.java
+++ b/src/main/java/ortus/boxlang/runtime/loader/resolvers/JavaResolver.java
@@ -36,6 +36,7 @@
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.services.ModuleService;
import ortus.boxlang.runtime.types.exceptions.BoxRuntimeException;
+import ortus.boxlang.runtime.util.RegexBuilder;
/**
* This resolver deals with Java classes only.
@@ -295,9 +296,10 @@ protected boolean importHas( IBoxContext context, ImportDefinition thisImport, S
@Override
protected boolean importHasMulti( IBoxContext context, ImportDefinition thisImport, String className ) {
// We can't interrogate the JDK due to limitations in the JDK itself
- if ( thisImport.className().matches( "(?i)(java|javax)\\..*" ) ) {
+ if ( RegexBuilder.of( thisImport.className(), RegexBuilder.JAVA_PACKAGE ).matches() ) {
- logger.debug( "Checking if [{}] is a JDK class", thisImport.getFullyQualifiedClass( className ) );
+ if ( logger.isDebugEnabled() )
+ logger.debug( "Checking if [{}] is a JDK class", thisImport.getFullyQualifiedClass( className ) );
// Do we have it in the cache?
if ( jdkClassImportCache.contains( thisImport.getFullyQualifiedClass( className ) ) ) {
@@ -307,7 +309,9 @@ protected boolean importHasMulti( IBoxContext context, ImportDefinition thisImpo
try {
Class.forName( thisImport.getFullyQualifiedClass( className ), false, getSystemClassLoader() );
jdkClassImportCache.add( thisImport.getFullyQualifiedClass( className ) );
- logger.debug( "Found JDK Class [{}] and added to jdk import cache", thisImport.getFullyQualifiedClass( className ) );
+
+ if ( logger.isDebugEnabled() )
+ logger.debug( "Found JDK Class [{}] and added to jdk import cache", thisImport.getFullyQualifiedClass( className ) );
return true;
} catch ( ClassNotFoundException e ) {
diff --git a/src/main/java/ortus/boxlang/runtime/modules/ModuleRecord.java b/src/main/java/ortus/boxlang/runtime/modules/ModuleRecord.java
index af8d0fbc6..a9a687b0f 100644
--- a/src/main/java/ortus/boxlang/runtime/modules/ModuleRecord.java
+++ b/src/main/java/ortus/boxlang/runtime/modules/ModuleRecord.java
@@ -76,6 +76,7 @@
import ortus.boxlang.runtime.types.util.StructUtil;
import ortus.boxlang.runtime.util.DataNavigator;
import ortus.boxlang.runtime.util.EncryptionUtil;
+import ortus.boxlang.runtime.util.RegexBuilder;
import ortus.boxlang.runtime.util.ResolvedFilePath;
/**
@@ -765,7 +766,7 @@ private ModuleRecord registerComponent( File targetFile, IBoxContext context ) {
// Skip directories and non CFC/BX files
// We are not doing recursive registration for the moment.
- if ( targetFile.isDirectory() || !targetFile.getName().matches( "^.*\\.(cfc|bx)$" ) ) {
+ if ( targetFile.isDirectory() || !RegexBuilder.of( targetFile.getName(), RegexBuilder.CFC_OR_BX_FILE ).matches() ) {
return this;
}
@@ -860,7 +861,7 @@ private ModuleRecord registerBIF( File targetFile, IBoxContext context ) {
// Skip directories and non CFC/BX files
// We are not doing recursive registration for the moment.
- if ( targetFile.isDirectory() || !targetFile.getName().matches( "^.*\\.(cfc|bx)$" ) ) {
+ if ( targetFile.isDirectory() || !RegexBuilder.of( targetFile.getName(), RegexBuilder.CFC_OR_BX_FILE ).matches() ) {
return this;
}
diff --git a/src/main/java/ortus/boxlang/runtime/types/util/DateTimeHelper.java b/src/main/java/ortus/boxlang/runtime/types/util/DateTimeHelper.java
index 0204831f8..5ddbdf5b8 100644
--- a/src/main/java/ortus/boxlang/runtime/types/util/DateTimeHelper.java
+++ b/src/main/java/ortus/boxlang/runtime/types/util/DateTimeHelper.java
@@ -32,6 +32,8 @@
import javax.management.InvalidAttributeValueException;
+import ortus.boxlang.runtime.util.RegexBuilder;
+
/**
* We represent a static date/time helper class that assists with time units on date/time conversions
* It doesn't hold any date/time information.
@@ -416,7 +418,8 @@ public static LocalDateTime getLastBusinessDayOfTheMonth() {
* @throws InvalidAttributeValueException
*/
public static String validateTime( String time ) throws InvalidAttributeValueException {
- if ( !time.matches( "^([0-1][0-9]|[2][0-3]):[0-5][0-9]$" ) ) {
+
+ if ( !RegexBuilder.of( time, RegexBuilder.TWENTY_FOUR_HOUR_TIME ).matches() ) {
// Do we have only hours?
if ( time.contains( ":" ) ) {
diff --git a/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java b/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java
index cd4764c92..564da1236 100644
--- a/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java
+++ b/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java
@@ -34,17 +34,23 @@ public class RegexBuilder {
* Pattern Dictionary
* Add as many patterns as needed, but make sure they are in all caps and alphabetically ordered.
*/
+ public static final Pattern ALPHA = Pattern.compile( "^[a-zA-Z]*$" );
+ public static final Pattern CFC_OR_BX_FILE = Pattern.compile( ".*\\.(cfc|bx)$" );
public static final Pattern BACKSLASH = Pattern.compile( "\\\\" );
public static final Pattern CARRIAGE_RETURN = Pattern.compile( "\\r" );
public static final Pattern CF_SQL = Pattern.compile( "(?i)CF_SQL_" );
public static final Pattern COLON = Pattern.compile( ":" );
public static final Pattern CREDIT_CARD_NUMBERS = Pattern.compile( "[0-9 ,_-]+" );
+ public static final Pattern EMAIL = Pattern.compile( "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" );
public static final Pattern END_OF_LINE_COLONS = Pattern.compile( ":+$" );
+ public static final Pattern JAVA_PACKAGE = Pattern.compile( "(?i)(java|javax)\\\\..*" );
public static final Pattern LINE_ENDINGS = Pattern.compile( "\\r?\\n" );
public static final Pattern MULTILINE_START_OF_LINE = Pattern.compile( "(?m)^" );
public static final Pattern MULTIPLE_SPACES = Pattern.compile( "\\s+" );
public static final Pattern NO_DIGITS = Pattern.compile( "\\D" );
+ public static final Pattern NON_ALPHA = Pattern.compile( "[^a-zA-Z]" );
public static final Pattern NON_ALPHANUMERIC = Pattern.compile( "[^a-zA-Z0-9]" );
+ public static final Pattern NUMBERS = Pattern.compile( "^-?\\d+(\\.\\d+)?$" );
public static final Pattern PACKAGE_NAMES = Pattern.compile( "[^a-zA-Z0-9$\\.]" );
public static final Pattern PERIOD = Pattern.compile( "\\." );
public static final Pattern REGEX_META = Pattern.compile( "([\\\\$])" );
@@ -56,10 +62,22 @@ public class RegexBuilder {
public static final Pattern SQL_PARENTHESIS_END = Pattern.compile( "(\\w|\\'|\"|\\`)\\)" );
public static final Pattern SQL_PARENTHESIS_START = Pattern.compile( "\\((\\w|\\'|\"|\\`)" );
public static final Pattern STARTS_WITH_DIGIT = Pattern.compile( "^\\d.*" );
+ public static final Pattern SSN = Pattern.compile( "^(?!219099999|078051120)(?!666|000|9\\d{2})\\d{3}(?!00)\\d{2}(?!0{4})\\d{4}$" );
+ public static final Pattern TIMESTAMP = Pattern.compile( "^\\{ts ([^\\}]*)\\}" );
+ public static final Pattern TELEPHONE = Pattern.compile(
+ "^(?:(?:\\+?1\\s*(?:[.-]\\s*)?)?(?:\\(\\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\\s*\\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\\s*(?:[.-]\\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\\s*(?:[.-]\\s*)?([0-9]{4})(?:\\s*(?:#|x\\.?|ext\\.?|extension)\\s*(\\d+))?$" );
public static final Pattern TWO_DOTS = Pattern.compile( "\\.{2}" );
+ public static final Pattern TWENTY_FOUR_HOUR_TIME = Pattern.compile( "^([0-1][\\d]|2[0-3]):[0-5][\\d]$" );
+ public static final Pattern URL = Pattern.compile( "^(https?|ftp|file)://([A-Za-z0-90.]*)/?([-a-zA-Z0-9.+&@#/]+)?(\\??[^\\s]*)$" );
public static final Pattern UPPERCASE_GROUP = Pattern.compile( "([A-Z])" );
- public static final Pattern WHITESPACE = Pattern.compile( "\\s" );
+ public static final Pattern UUID_V4 = Pattern
+ .compile( "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[89abAB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}" );
+ public static final Pattern UUID_PATTERN = Pattern
+ .compile( "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[89abAB][a-fA-F0-9]{3}[a-fA-F0-9]{12}" );
public static final Pattern VOWELS = Pattern.compile( "^[aeiou].*" );
+ public static final Pattern VALID_VARIABLENAME = Pattern.compile( "^[a-zA-Z_][a-zA-Z0-9_]*$" );
+ public static final Pattern WHITESPACE = Pattern.compile( "\\s" );
+ public static final Pattern ZIPCODE = Pattern.compile( "\\d{5}([ -]?\\d{4})?" );
/**
* Build a matcher for the given pattern lookup
@@ -72,6 +90,19 @@ public static RegexMatcher of( String input ) {
return new RegexMatcher( input );
}
+ /**
+ * Build a matcher for the given input and string pattern
+ *
+ * @param input The input string to match against
+ * @param pattern The pattern to match against
+ * @param noCase Whether the pattern should be case insensitive or not
+ *
+ * @return A new matcher instance
+ */
+ public static RegexMatcher of( String input, String pattern, Boolean noCase ) {
+ return new RegexMatcher( input ).match( pattern, noCase );
+ }
+
/**
* Build a matcher for the given input and string pattern
*
@@ -140,13 +171,25 @@ public RegexMatcher match( Pattern pattern ) {
}
/**
- * Compile the pattern from the given string
+ * Compile the pattern from the given string with case sensitivity
*
* @param pattern The pattern to compile
*
* @return The matcher instance
*/
public RegexMatcher match( String pattern ) {
+ return this.match( pattern, false );
+ }
+
+ /**
+ * Compile the pattern from the given string
+ *
+ * @param pattern The pattern to compile
+ * @param noCase Whether the pattern should be case insensitive or not
+ *
+ * @return The matcher instance
+ */
+ public RegexMatcher match( String pattern, Boolean noCase ) {
Objects.requireNonNull( pattern, "Pattern cannot be null" );
if ( pattern.isEmpty() ) {
throw new IllegalArgumentException( "Pattern cannot be empty" );
@@ -157,7 +200,7 @@ public RegexMatcher match( String pattern ) {
this.pattern = ( Pattern ) BoxRuntime.getInstance()
.getCacheService()
.getCache( Key.bxRegex )
- .getOrSet( cacheKey, () -> Pattern.compile( pattern ) );
+ .getOrSet( cacheKey, () -> Pattern.compile( pattern, noCase ? Pattern.CASE_INSENSITIVE : 0 ) );
return this;
}
diff --git a/src/main/java/ortus/boxlang/runtime/util/ValidationUtil.java b/src/main/java/ortus/boxlang/runtime/util/ValidationUtil.java
index 0e8f453fa..07543e1b7 100644
--- a/src/main/java/ortus/boxlang/runtime/util/ValidationUtil.java
+++ b/src/main/java/ortus/boxlang/runtime/util/ValidationUtil.java
@@ -14,8 +14,6 @@
*/
package ortus.boxlang.runtime.util;
-import java.util.regex.Pattern;
-
import org.apache.commons.lang3.math.NumberUtils;
import ortus.boxlang.runtime.dynamic.casters.CastAttempt;
@@ -36,50 +34,6 @@
*/
public class ValidationUtil {
- /**
- * Regular expression Pattern to match a URL with a `http`, `https`, `ftp`, or `file` scheme.
- *
- * @see https://regex101.com/r/kWhB1u/1
- */
- public static final Pattern URL = Pattern.compile( "^(https?|ftp|file)://([A-Za-z0-90.]*)/?([-a-zA-Z0-9.+&@#/]+)?(\\??[^\\s]*)$" );
-
- /**
- * Regular expression Pattern to match a North American Numbering Plan (NANP) telephone number. This does not support international numbers.
- */
- public static final Pattern TELEPHONE = Pattern.compile(
- "^(?:(?:\\+?1\\s*(?:[.-]\\s*)?)?(?:\\(\\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\\s*\\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\\s*(?:[.-]\\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\\s*(?:[.-]\\s*)?([0-9]{4})(?:\\s*(?:#|x\\.?|ext\\.?|extension)\\s*(\\d+))?$" );
-
- /**
- * Regular expression Pattern to match a United States Postal Service (USPS) ZIP Code.
- */
- public static final Pattern ZIPCODE = Pattern.compile( "\\d{5}([ -]?\\d{4})?" );
-
- /**
- * Regular expression Pattern to match a Social Security Number (SSN).
- */
- public static final Pattern SSN = Pattern.compile( "^(?!219099999|078051120)(?!666|000|9\\d{2})\\d{3}(?!00)\\d{2}(?!0{4})\\d{4}$" );
-
- /**
- * Regular expression to match a Version 4 Universally Unique Identifier (UUID), in a
- * case-insensitive fashion.
- *
- * @see https://gitlab.com/jamietanna/uuid/-/blob/v0.2.0/uuid-core/src/main/java/me/jvt/uuid/Patterns.java
- */
- public static final Pattern UUID_V4 = Pattern
- .compile( "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[89abAB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}" );
-
- /**
- * Regular expression to match a Version 4 Universally Unique Identifier (UUID), in a
- * case-insensitive fashion.
- */
- public static final Pattern UUID_PATTERN = Pattern
- .compile( "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[89abAB][a-fA-F0-9]{3}[a-fA-F0-9]{12}" );
-
- /**
- * Regular expression to match a valid variable name.
- */
- public static final String VALID_VARIABLE_REGEX = "^[a-zA-Z_][a-zA-Z0-9_]*$";
-
/**
* Perform the Lunh algorithm to validate a credit card number.
*
@@ -159,7 +113,7 @@ public static boolean isValidNumeric( Object value ) {
* @return Boolean indicating whether the given string is a valid compatible UUID.
*/
public static boolean isValidGUID( String uuid ) {
- return UUID_V4.matcher( uuid ).matches();
+ return RegexBuilder.of( uuid, RegexBuilder.UUID_V4 ).matches();
}
/**
@@ -172,7 +126,7 @@ public static boolean isValidGUID( String uuid ) {
* @return Boolean indicating whether the given string is a valid compatible UUID.
*/
public static boolean isValidUUID( String uuid ) {
- return UUID_PATTERN.matcher( uuid ).matches();
+ return RegexBuilder.of( uuid, RegexBuilder.UUID_PATTERN ).matches();
}
/**
@@ -186,9 +140,7 @@ public static boolean isValidUUID( String uuid ) {
* @return Boolean indicating whether the given string is a valid SSN.
*/
public static boolean isValidSSN( String ssn ) {
- return SSN.matcher(
- ssn.replace( "-", "" ).replace( " ", "" )
- ).matches();
+ return RegexBuilder.of( ssn.replace( "-", "" ).replace( " ", "" ), RegexBuilder.SSN ).matches();
}
/**
@@ -199,7 +151,7 @@ public static boolean isValidSSN( String ssn ) {
* @return Boolean indicating whether the given string is a valid US or North American telephone number.
*/
public static boolean isValidTelephone( String phone ) {
- return TELEPHONE.matcher( phone ).matches();
+ return RegexBuilder.of( phone, RegexBuilder.TELEPHONE ).matches();
}
/**
@@ -210,7 +162,7 @@ public static boolean isValidTelephone( String phone ) {
* @return Boolean indicating whether the given string is a valid URL.
*/
public static boolean isValidURL( String url ) {
- return URL.matcher( url ).matches();
+ return RegexBuilder.of( url, RegexBuilder.URL ).matches();
}
/**
@@ -226,7 +178,7 @@ public static boolean isValidURL( String url ) {
* @return Boolean indicating whether the given string is a valid zip code.
*/
public static boolean isValidZipCode( String zipCode ) {
- return ZIPCODE.matcher( zipCode ).matches();
+ return RegexBuilder.of( zipCode, RegexBuilder.ZIPCODE ).matches();
}
/**
@@ -239,7 +191,7 @@ public static boolean isValidZipCode( String zipCode ) {
* @return Boolean indicating whether the given string is a valid variable name.
*/
public static boolean isValidVariableName( String variableName ) {
- return variableName.matches( VALID_VARIABLE_REGEX );
+ return RegexBuilder.of( variableName, RegexBuilder.VALID_VARIABLENAME ).matches();
}
/**
@@ -352,7 +304,7 @@ public static boolean isValidRange( Object value, Number min, Number max ) {
* @return Boolean indicating if the value matches the regex
*/
public static boolean isValidMatch( String value, String regex ) {
- return value.matches( regex );
+ return RegexBuilder.of( value, regex ).matches();
}
/**
@@ -374,7 +326,7 @@ public static boolean isValidMatchNoCase( String value, String regex ) {
* @param email The email address to validate
*/
public static boolean isValidEmail( String email ) {
- return email.matches( "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" );
+ return RegexBuilder.of( email, RegexBuilder.EMAIL ).matches();
}
/**
@@ -385,7 +337,7 @@ public static boolean isValidEmail( String email ) {
* @param pattern The regex pattern to match
*/
public static boolean isValidPattern( String value, String pattern ) {
- return value.matches( pattern );
+ return RegexBuilder.of( value, pattern ).matches();
}
}
diff --git a/src/test/java/ortus/boxlang/runtime/bifs/global/string/ReMatchNoCaseTest.java b/src/test/java/ortus/boxlang/runtime/bifs/global/string/ReMatchNoCaseTest.java
index 5c0f50655..737ff3784 100644
--- a/src/test/java/ortus/boxlang/runtime/bifs/global/string/ReMatchNoCaseTest.java
+++ b/src/test/java/ortus/boxlang/runtime/bifs/global/string/ReMatchNoCaseTest.java
@@ -15,12 +15,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package ortus.boxlang.runtime.bifs.global.string;
import static com.google.common.truth.Truth.assertThat;
-import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -45,11 +43,6 @@ public static void setUp() {
instance = BoxRuntime.getInstance( true );
}
- @AfterAll
- public static void teardown() {
-
- }
-
@BeforeEach
public void setupEach() {
context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
From b6998c7503d02713e86400d61c69b981632f3709 Mon Sep 17 00:00:00 2001
From: Luis Majano
Date: Wed, 4 Dec 2024 18:02:03 -0600
Subject: [PATCH 052/193] BL-784 #resolved
---
.../ortus/boxlang/runtime/bifs/global/string/ReReplace.java | 1 -
src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java | 4 ++--
.../boxlang/runtime/bifs/global/string/ReMatchTest.java | 6 ------
3 files changed, 2 insertions(+), 9 deletions(-)
diff --git a/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReReplace.java b/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReReplace.java
index 97847c88e..0f65e991f 100644
--- a/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReReplace.java
+++ b/src/main/java/ortus/boxlang/runtime/bifs/global/string/ReReplace.java
@@ -91,7 +91,6 @@ public Object _invoke( IBoxContext context, ArgumentsScope arguments ) {
StringBuffer result = new StringBuffer();
Matcher matcher = RegexBuilder.of( string, regex, noCase ).matcher();
-
boolean upperCase = false;
boolean lowerCase = false;
diff --git a/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java b/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java
index 564da1236..ba5e57b7e 100644
--- a/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java
+++ b/src/main/java/ortus/boxlang/runtime/util/RegexBuilder.java
@@ -43,7 +43,7 @@ public class RegexBuilder {
public static final Pattern CREDIT_CARD_NUMBERS = Pattern.compile( "[0-9 ,_-]+" );
public static final Pattern EMAIL = Pattern.compile( "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" );
public static final Pattern END_OF_LINE_COLONS = Pattern.compile( ":+$" );
- public static final Pattern JAVA_PACKAGE = Pattern.compile( "(?i)(java|javax)\\\\..*" );
+ public static final Pattern JAVA_PACKAGE = Pattern.compile( "(?i)(java|javax)\\..*" );
public static final Pattern LINE_ENDINGS = Pattern.compile( "\\r?\\n" );
public static final Pattern MULTILINE_START_OF_LINE = Pattern.compile( "(?m)^" );
public static final Pattern MULTIPLE_SPACES = Pattern.compile( "\\s+" );
@@ -196,7 +196,7 @@ public RegexMatcher match( String pattern, Boolean noCase ) {
}
// Lookup or compile the pattern into the regex cache
- String cacheKey = EncryptionUtil.hash( pattern );
+ String cacheKey = EncryptionUtil.hash( pattern + noCase );
this.pattern = ( Pattern ) BoxRuntime.getInstance()
.getCacheService()
.getCache( Key.bxRegex )
diff --git a/src/test/java/ortus/boxlang/runtime/bifs/global/string/ReMatchTest.java b/src/test/java/ortus/boxlang/runtime/bifs/global/string/ReMatchTest.java
index eb2caf22d..5fe61dba0 100644
--- a/src/test/java/ortus/boxlang/runtime/bifs/global/string/ReMatchTest.java
+++ b/src/test/java/ortus/boxlang/runtime/bifs/global/string/ReMatchTest.java
@@ -20,7 +20,6 @@
import static com.google.common.truth.Truth.assertThat;
-import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -45,11 +44,6 @@ public static void setUp() {
instance = BoxRuntime.getInstance( true );
}
- @AfterAll
- public static void teardown() {
-
- }
-
@BeforeEach
public void setupEach() {
context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
From bbcc0a160e113d6509c08b532a7308840b328f82 Mon Sep 17 00:00:00 2001
From: Luis Majano
Date: Wed, 4 Dec 2024 18:22:56 -0600
Subject: [PATCH 053/193] BL-791 #resolve Support `enabled` in the boxlang.json
for modules so they can be enabled or disabled and remove `disabled` double
negative
---
.../runtime/config/segments/ModuleConfig.java | 16 ++++++----------
.../boxlang/runtime/modules/ModuleRecord.java | 18 +++++++++---------
.../runtime/services/ModuleService.java | 4 ++--
src/main/resources/config/boxlang.json | 4 ++--
src/modules/test/src/main/bx/ModuleConfig.bx | 2 +-
.../runtime/modules/ModuleRecordTest.java | 7 +++----
6 files changed, 23 insertions(+), 28 deletions(-)
diff --git a/src/main/java/ortus/boxlang/runtime/config/segments/ModuleConfig.java b/src/main/java/ortus/boxlang/runtime/config/segments/ModuleConfig.java
index 4532f7549..e747bc5dc 100644
--- a/src/main/java/ortus/boxlang/runtime/config/segments/ModuleConfig.java
+++ b/src/main/java/ortus/boxlang/runtime/config/segments/ModuleConfig.java
@@ -18,6 +18,7 @@
package ortus.boxlang.runtime.config.segments;
import ortus.boxlang.runtime.config.util.PlaceholderHelper;
+import ortus.boxlang.runtime.config.util.PropertyHelper;
import ortus.boxlang.runtime.dynamic.casters.BooleanCaster;
import ortus.boxlang.runtime.dynamic.casters.StructCaster;
import ortus.boxlang.runtime.scopes.Key;
@@ -40,9 +41,9 @@ public class ModuleConfig implements IConfigSegment {
public String name;
/**
- * Whether the module is disabled or not
+ * Whether the module is enabled or not
*/
- public Boolean disabled = false;
+ public Boolean enabled = true;
/**
* The settings for the module as a struct
@@ -70,13 +71,8 @@ public ModuleConfig( String name ) {
* @return Return itself for chaining
*/
public ModuleConfig process( IStruct config ) {
- // Check if the module is enabled
- if ( config.containsKey( "disabled" ) ) {
- this.disabled = BooleanCaster.cast( PlaceholderHelper.resolve( config.getOrDefault( "disabled", false ) ) );
- }
-
- // Store the settings
- this.settings = StructCaster.cast( config.getOrDefault( Key.settings, new Struct() ) );
+ this.enabled = BooleanCaster.cast( PropertyHelper.processString( config, Key.enabled, "true" ) );
+ this.settings = StructCaster.cast( config.getOrDefault( Key.settings, new Struct() ) );
// Process placeholders
this.settings.forEach( ( key, value ) -> {
if ( value instanceof String ) {
@@ -97,7 +93,7 @@ public ModuleConfig process( IStruct config ) {
public IStruct asStruct() {
return Struct.of(
Key._NAME, this.name,
- Key.disabled, this.disabled,
+ Key.enabled, this.enabled,
Key.settings, new Struct( this.settings )
);
}
diff --git a/src/main/java/ortus/boxlang/runtime/modules/ModuleRecord.java b/src/main/java/ortus/boxlang/runtime/modules/ModuleRecord.java
index a9a687b0f..eac37380e 100644
--- a/src/main/java/ortus/boxlang/runtime/modules/ModuleRecord.java
+++ b/src/main/java/ortus/boxlang/runtime/modules/ModuleRecord.java
@@ -122,9 +122,9 @@ public class ModuleRecord {
public String mapping;
/**
- * If the module is disabled for activation, defaults to false
+ * If the module is enabled for activation, defaults to false
*/
- public boolean disabled = false;
+ public boolean enabled = true;
/**
* Flag to indicate if the module has been activated or not yet
@@ -322,12 +322,12 @@ public ModuleRecord loadDescriptor( IBoxContext context ) {
this.author = ( String ) thisScope.getOrDefault( Key.author, "" );
this.description = ( String ) thisScope.getOrDefault( Key.description, "" );
this.webURL = ( String ) thisScope.getOrDefault( Key.webURL, "" );
- this.disabled = ( Boolean ) thisScope.getOrDefault( Key.disabled, false );
+ this.enabled = ( Boolean ) thisScope.getOrDefault( Key.enabled, true );
// Verify if we disabled the loading of the module in the runtime config
if ( runtime.getConfiguration().modules.containsKey( this.name ) ) {
ModuleConfig config = ( ModuleConfig ) runtime.getConfiguration().modules.get( this.name );
- this.disabled = config.disabled;
+ this.enabled = config.enabled;
}
// Do we have a custom mapping to override?
@@ -695,12 +695,12 @@ public void execute( IBoxContext context, String[] args ) {
*/
/**
- * If the module is disabled for activation
+ * If the module is enabled for activation
*
- * @return {@code true} if the module is disabled for activation, {@code false} otherwise
+ * @return {@code true} if the module is enabled for activation, {@code false} otherwise
*/
- public boolean isDisabled() {
- return disabled;
+ public boolean isEnabled() {
+ return enabled;
}
/**
@@ -732,7 +732,7 @@ public IStruct asStruct() {
"author", author,
"customInterceptionPoints", Array.copyOf( customInterceptionPoints ),
"description", description,
- "disabled", disabled,
+ "enabled", enabled,
"Id", id,
"interceptors", Array.copyOf( interceptors ),
"invocationPath", invocationPath,
diff --git a/src/main/java/ortus/boxlang/runtime/services/ModuleService.java b/src/main/java/ortus/boxlang/runtime/services/ModuleService.java
index 5458c3271..7a2481c48 100644
--- a/src/main/java/ortus/boxlang/runtime/services/ModuleService.java
+++ b/src/main/java/ortus/boxlang/runtime/services/ModuleService.java
@@ -250,7 +250,7 @@ void register( Key name ) {
moduleRecord.loadDescriptor( runtimeContext );
// Check if the module is disabled, if so, skip it
- if ( moduleRecord.isDisabled() ) {
+ if ( moduleRecord.isEnabled() ) {
logger.warn(
"+ Module Service: Module [{}] is disabled, skipping registration",
moduleRecord.name
@@ -342,7 +342,7 @@ void activate( Key name ) {
}
// Check if the module is disabled
- if ( this.registry.get( name ).isDisabled() ) {
+ if ( this.registry.get( name ).isEnabled() ) {
logger.debug(
"+ Module Service: Module [{}] is disabled, skipping activation",
name
diff --git a/src/main/resources/config/boxlang.json b/src/main/resources/config/boxlang.json
index c219a3f04..a772e1ea4 100644
--- a/src/main/resources/config/boxlang.json
+++ b/src/main/resources/config/boxlang.json
@@ -413,13 +413,13 @@
/**
* The BoxLang module settings
* The key is the module name and the value is a struct of settings for that specific module
- * The `disabled` property is a boolean that determines if the module should be enabled or not
+ * The `enabled` property is a boolean that determines if the module should be enabled or not. Default is true
* The `settings` property is a struct of settings that are specific to the module and will be override the module settings
*/
"modules": {
// The Compat Module
// "compat": {
- // "disabled": false,
+ // "enabled": true,
// "settings": {
// "isLucee": true,
// "isAdobe": true
diff --git a/src/modules/test/src/main/bx/ModuleConfig.bx b/src/modules/test/src/main/bx/ModuleConfig.bx
index f81d0e6c8..bd19531ac 100644
--- a/src/modules/test/src/main/bx/ModuleConfig.bx
+++ b/src/modules/test/src/main/bx/ModuleConfig.bx
@@ -56,7 +56,7 @@ class{
/**
* This boolean flag tells the module service to skip the module registration/activation process.
*/
- this.disabled = false;
+ this.enabled = true;
/**
* --------------------------------------------------------------------------
diff --git a/src/test/java/ortus/boxlang/runtime/modules/ModuleRecordTest.java b/src/test/java/ortus/boxlang/runtime/modules/ModuleRecordTest.java
index ccd94ea74..8f6a4a5a5 100644
--- a/src/test/java/ortus/boxlang/runtime/modules/ModuleRecordTest.java
+++ b/src/test/java/ortus/boxlang/runtime/modules/ModuleRecordTest.java
@@ -23,7 +23,6 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
-import java.util.Arrays;
import java.util.List;
import java.util.Optional;
@@ -113,7 +112,7 @@ void testModuleRecordAsStruct() {
assertThat( structRepresentation.get( "activatedOn" ) ).isNull();
assertThat( structRepresentation.get( "author" ) ).isEqualTo( "" );
assertThat( structRepresentation.get( "description" ) ).isEqualTo( "" );
- assertThat( structRepresentation.getAsBoolean( Key.of( "disabled" ) ) ).isFalse();
+ assertThat( structRepresentation.getAsBoolean( Key.of( "enabled" ) ) ).isTrue();
assertThat( structRepresentation.get( "id" ) ).isNotNull();
assertThat( structRepresentation.getAsArray( Key.of( "interceptors" ) ).size() ).isEqualTo( 0 );
assertThat( structRepresentation.get( "invocationPath" ) ).isEqualTo( "bxModules.TestModule" );
@@ -138,7 +137,7 @@ void testCanLoadModuleDescriptor() {
assertThat( moduleRecord.author ).isEqualTo( "Luis Majano" );
assertThat( moduleRecord.description ).isEqualTo( "This module does amazing things" );
assertThat( moduleRecord.webURL ).isEqualTo( "https://www.ortussolutions.com" );
- assertThat( moduleRecord.disabled ).isEqualTo( false );
+ assertThat( moduleRecord.enabled ).isEqualTo( false );
assertThat( moduleRecord.mapping ).isEqualTo( ModuleService.MODULE_MAPPING_PREFIX + "test" );
assertThat( moduleRecord.invocationPath ).isEqualTo( ModuleService.MODULE_MAPPING_INVOCATION_PREFIX + moduleRecord.name.getName() );
}
@@ -179,7 +178,7 @@ void testCanConfigureModuleDescriptor() {
assertThat( moduleRecord.author ).isEqualTo( "Luis Majano" );
assertThat( moduleRecord.description ).isEqualTo( "This module does amazing things" );
assertThat( moduleRecord.webURL ).isEqualTo( "https://www.ortussolutions.com" );
- assertThat( moduleRecord.disabled ).isEqualTo( false );
+ assertThat( moduleRecord.enabled ).isEqualTo( true );
assertThat( moduleRecord.mapping ).isEqualTo( ModuleService.MODULE_MAPPING_PREFIX + "test" );
assertThat( moduleRecord.invocationPath ).isEqualTo( ModuleService.MODULE_MAPPING_INVOCATION_PREFIX + moduleRecord.name.getName() );
assertThat( moduleRecord.settings.getAsStruct( Key.of( "nested" ) ).get( Key.of( "SLA" ) ) ).isEqualTo( "24 hours" );
From 4685a406dff98faf39a83ed56ea42a08e5b22e5e Mon Sep 17 00:00:00 2001
From: Luis Majano
Date: Wed, 4 Dec 2024 18:35:04 -0600
Subject: [PATCH 054/193] fixed tests
---
.../java/ortus/boxlang/runtime/modules/ModuleRecordTest.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/test/java/ortus/boxlang/runtime/modules/ModuleRecordTest.java b/src/test/java/ortus/boxlang/runtime/modules/ModuleRecordTest.java
index 8f6a4a5a5..d200fa627 100644
--- a/src/test/java/ortus/boxlang/runtime/modules/ModuleRecordTest.java
+++ b/src/test/java/ortus/boxlang/runtime/modules/ModuleRecordTest.java
@@ -137,7 +137,7 @@ void testCanLoadModuleDescriptor() {
assertThat( moduleRecord.author ).isEqualTo( "Luis Majano" );
assertThat( moduleRecord.description ).isEqualTo( "This module does amazing things" );
assertThat( moduleRecord.webURL ).isEqualTo( "https://www.ortussolutions.com" );
- assertThat( moduleRecord.enabled ).isEqualTo( false );
+ assertThat( moduleRecord.enabled ).isEqualTo( true );
assertThat( moduleRecord.mapping ).isEqualTo( ModuleService.MODULE_MAPPING_PREFIX + "test" );
assertThat( moduleRecord.invocationPath ).isEqualTo( ModuleService.MODULE_MAPPING_INVOCATION_PREFIX + moduleRecord.name.getName() );
}
From f1c920ba7588f2f5ff849b7e62d591cebd67e8cd Mon Sep 17 00:00:00 2001
From: Luis Majano
Date: Wed, 4 Dec 2024 18:47:12 -0600
Subject: [PATCH 055/193] more refactoring
---
modules/bx-derby/ModuleConfig.bx | 2 +-
src/test/java/TestCases/phase3/ClassTest.java | 2 +-
src/test/resources/modules/anotherModule/ModuleConfig.bx | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/modules/bx-derby/ModuleConfig.bx b/modules/bx-derby/ModuleConfig.bx
index 1b986b205..db1a1d64e 100644
--- a/modules/bx-derby/ModuleConfig.bx
+++ b/modules/bx-derby/ModuleConfig.bx
@@ -51,7 +51,7 @@ class{
/**
* This boolean flag tells the module service to skip the module registration/activation process.
*/
- this.disabled = false;
+ this.enabled = true;
/**
* --------------------------------------------------------------------------
diff --git a/src/test/java/TestCases/phase3/ClassTest.java b/src/test/java/TestCases/phase3/ClassTest.java
index b7d38f9a6..d24377f4a 100644
--- a/src/test/java/TestCases/phase3/ClassTest.java
+++ b/src/test/java/TestCases/phase3/ClassTest.java
@@ -129,7 +129,7 @@ void testVanillaModuleConfig() {
/**
* This boolean flag tells the module service to skip the module registration/activation process.
*/
- this.disabled = false;
+ this.enabled = true;
/**
* --------------------------------------------------------------------------
diff --git a/src/test/resources/modules/anotherModule/ModuleConfig.bx b/src/test/resources/modules/anotherModule/ModuleConfig.bx
index 003269615..b01ecd361 100644
--- a/src/test/resources/modules/anotherModule/ModuleConfig.bx
+++ b/src/test/resources/modules/anotherModule/ModuleConfig.bx
@@ -51,7 +51,7 @@ class {
/**
* This boolean flag tells the module service to skip the module registration/activation process.
*/
- this.disabled = false;
+ this.enabled = true;
/**
* --------------------------------------------------------------------------
From f1f246e8e8123c0c1de8973a49d81a11079ba7af Mon Sep 17 00:00:00 2001
From: Luis Majano
Date: Wed, 4 Dec 2024 18:49:09 -0600
Subject: [PATCH 056/193] return the task record as a struct
---
.../runtime/async/tasks/TaskRecord.java | 23 +++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/src/main/java/ortus/boxlang/runtime/async/tasks/TaskRecord.java b/src/main/java/ortus/boxlang/runtime/async/tasks/TaskRecord.java
index c34d5c6dc..b101bbf55 100644
--- a/src/main/java/ortus/boxlang/runtime/async/tasks/TaskRecord.java
+++ b/src/main/java/ortus/boxlang/runtime/async/tasks/TaskRecord.java
@@ -20,6 +20,9 @@
import java.time.LocalDateTime;
import java.util.concurrent.ScheduledFuture;
+import ortus.boxlang.runtime.types.IStruct;
+import ortus.boxlang.runtime.types.Struct;
+
/**
* The task record holds all the information of a living task in the scheduler.
*/
@@ -87,4 +90,24 @@ public TaskRecord( String name, String group, ScheduledTask task ) {
this.task = task;
this.registeredAt = LocalDateTime.now( task.getTimezone() );
}
+
+ /**
+ * Return the record as a struct
+ */
+ public IStruct asStruct() {
+ return Struct.of(
+ "name", name,
+ "group", group,
+ "task", task,
+ "future", future,
+ "scheduledAt", scheduledAt,
+ "registeredAt", registeredAt,
+ "disabled", disabled,
+ "error", error,
+ "errorMessage", errorMessage,
+ "stacktrace", stacktrace,
+ "inetHost", inetHost,
+ "localIp", localIp
+ );
+ }
}
From 05b21f4a5107e93920968168e94edf2f034638b3 Mon Sep 17 00:00:00 2001
From: Luis Majano
Date: Wed, 4 Dec 2024 18:57:52 -0600
Subject: [PATCH 057/193] BL-699 Schedulers now have a startupTask( task ) to
dynamically startup a task by name or task object
---
.../runtime/async/tasks/BaseScheduler.java | 37 ++++++++++++++++---
1 file changed, 31 insertions(+), 6 deletions(-)
diff --git a/src/main/java/ortus/boxlang/runtime/async/tasks/BaseScheduler.java b/src/main/java/ortus/boxlang/runtime/async/tasks/BaseScheduler.java
index f21196bc5..42c6c0c8e 100644
--- a/src/main/java/ortus/boxlang/runtime/async/tasks/BaseScheduler.java
+++ b/src/main/java/ortus/boxlang/runtime/async/tasks/BaseScheduler.java
@@ -236,7 +236,7 @@ public synchronized BaseScheduler startup() {
// Iterate over tasks and send them off for scheduling
this.tasks.entrySet()
.parallelStream()
- .forEachOrdered( entry -> startupTask( entry.getKey(), entry.getValue() ) );
+ .forEachOrdered( entry -> startupTask( entry.getKey() ) );
// Mark scheduler as started
this.started = true;
@@ -284,13 +284,27 @@ public synchronized BaseScheduler clearTasks() {
return this;
}
+ /**
+ * Startup manullay the passed in task
+ *
+ * @param task The task to startup
+ *
+ * @return The task record
+ */
+ public TaskRecord startupTask( ScheduledTask task ) {
+ return startupTask( task.getName() );
+ }
+
/**
* Startup a specific task by name
*
- * @param taskName The name of the task
- * @param taskRecord The task record object
+ * @param taskName The name of the task
+ *
+ * @return The task record
*/
- private void startupTask( String taskName, TaskRecord taskRecord ) {
+ public TaskRecord startupTask( String taskName ) {
+ // Get the task record
+ var taskRecord = getTaskRecord( taskName );
// Verify we can start it up the task or not
if ( taskRecord.task.isDisabled() ) {
taskRecord.disabled = true;
@@ -299,8 +313,7 @@ private void startupTask( String taskName, TaskRecord taskRecord ) {
this.name,
taskName
);
- // Continue iteration
- return;
+ return taskRecord;
} else {
// Log scheduling startup
logger.info(
@@ -310,6 +323,16 @@ private void startupTask( String taskName, TaskRecord taskRecord ) {
);
}
+ // Verify that the task record: scheduledAt is null
+ if ( taskRecord.scheduledAt != null ) {
+ logger.warn(
+ "- Scheduler ({}) skipping task ({}) as it has already been scheduled.",
+ this.name,
+ taskName
+ );
+ return taskRecord;
+ }
+
// Send it off for scheduling
try {
taskRecord.future = taskRecord.task.start();
@@ -330,6 +353,8 @@ private void startupTask( String taskName, TaskRecord taskRecord ) {
taskRecord.errorMessage = e.getMessage();
taskRecord.stacktrace = Arrays.toString( e.getStackTrace() );
}
+
+ return taskRecord;
}
/**
From 65499fa73628a5161fa43a49d6d438a5dc4c0bd7 Mon Sep 17 00:00:00 2001
From: Luis Majano
Date: Wed, 4 Dec 2024 19:02:49 -0600
Subject: [PATCH 058/193] regression modules loading
---
.../java/ortus/boxlang/runtime/services/ModuleService.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main/java/ortus/boxlang/runtime/services/ModuleService.java b/src/main/java/ortus/boxlang/runtime/services/ModuleService.java
index 7a2481c48..d2cd46391 100644
--- a/src/main/java/ortus/boxlang/runtime/services/ModuleService.java
+++ b/src/main/java/ortus/boxlang/runtime/services/ModuleService.java
@@ -250,7 +250,7 @@ void register( Key name ) {
moduleRecord.loadDescriptor( runtimeContext );
// Check if the module is disabled, if so, skip it
- if ( moduleRecord.isEnabled() ) {
+ if ( !moduleRecord.isEnabled() ) {
logger.warn(
"+ Module Service: Module [{}] is disabled, skipping registration",
moduleRecord.name
@@ -342,7 +342,7 @@ void activate( Key name ) {
}
// Check if the module is disabled
- if ( this.registry.get( name ).isEnabled() ) {
+ if ( !this.registry.get( name ).isEnabled() ) {
logger.debug(
"+ Module Service: Module [{}] is disabled, skipping activation",
name
From c65b6b7c36c44a1da2addc2c489e9b64723ccaba Mon Sep 17 00:00:00 2001
From: Luis Majano
Date: Wed, 4 Dec 2024 21:31:29 -0600
Subject: [PATCH 059/193] leverage the new getLogger( name) method
---
.../runtime/logging/LoggingService.java | 68 ++++++-------------
1 file changed, 20 insertions(+), 48 deletions(-)
diff --git a/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java b/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java
index 0eabfb666..38fb4bd6f 100644
--- a/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java
+++ b/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java
@@ -409,30 +409,9 @@ public LoggingService logMessage(
if ( logger.isEmpty() ) {
logger = DEFAULT_LOG_FILE;
}
- // Verify the log file ends in `.log` and if not, append it
- if ( !logger.toLowerCase().endsWith( ".log" ) ) {
- logger += ".log";
- }
- // If the file is an absolute path, use it, otherwise use the logs directory as the base
- // All logger names should be lowercase
- String loggerFilePath = Path.of( logger ).isAbsolute()
- ? Path.of( logger ).normalize().toString()
- : Paths.get( getLogsDirectory(), "/", logger.toLowerCase() ).normalize().toString();
- String loggerName = FilenameUtils.getBaseName( loggerFilePath.toLowerCase() );
-
- // Get the logger and set the level
- LoggerContext targetContext = getLoggerContext();
- Logger oLogger = targetContext.getLogger( loggerName );
- oLogger.setLevel( Level.TRACE );
- FileAppender appender = getOrBuildAppender( loggerFilePath, targetContext );
-
- // Create or compute the file appender requested
- // This provides locking also and caching so we don't have to keep creating them
- // Shutdown will stop the appenders
- if ( !oLogger.isAttached( appender ) ) {
- oLogger.addAppender( appender );
- }
+ // Compute and get the logger
+ Logger oLogger = getLogger( logger );
// Log according to the level
switch ( targetLogLevel.getNameNoCase() ) {
@@ -454,40 +433,33 @@ public LoggingService logMessage(
* If the logger doesn't exist, it will auto-register it and load it
* using the name as the file name in the logs directory.
*
- * @param loggerName The name of the logger
+ * @param logger The name of the logger to retrieve.
*
* @return The logger requested
*/
- public Logger getLogger( Key loggerName ) {
- // Is it regsitered already?
- if ( this.loggersMap.containsKey( loggerName ) ) {
- return ( Logger ) this.loggersMap.get( loggerName );
+ public Logger getLogger( String logger ) {
+ // The incoming logger can be:
+ // 1. A named logger: "scheduler", "application", "orm", etc
+ // 2. A relative path: "scheduler.log", "application.log", "orm.log"
+ // 3. An absolute path: "/var/log/boxlang/scheduler.log"
+
+ // Make sure it ends in .log
+ if ( !logger.endsWith( ".log" ) ) {
+ logger = logger + ".log";
}
- // Compute it
- return getLogger(
- loggerName,
- Paths.get( getLogsDirectory(), "/", loggerName.getNameNoCase() ).normalize().toString()
- );
- }
+ // If the file is an absolute path, use it, otherwise use the logs directory as the base
+ String loggerFilePath = Path.of( logger ).normalize().isAbsolute()
+ ? Path.of( logger ).normalize().toString()
+ : Paths.get( getLogsDirectory(), logger.toLowerCase() ).normalize().toString();
+ Key loggerKey = Key.of( FilenameUtils.getBaseName( loggerFilePath.toLowerCase() ) );
- /**
- * Get a logger by registered name.
- * If the logger doesn't exist, it will auto-register it and load it
- * using the name as the file name in the logs directory.
- *
- * @param loggerName The name of the logger
- * @param filePath The file path to the logger. If any, this can be null
- *
- * @return The logger requested
- */
- public Logger getLogger( Key loggerName, String filePath ) {
- // Comput if absent and return the logger
- return ( Logger ) this.loggersMap.computeIfAbsent( loggerName, key -> {
+ // Compute it or return it
+ return ( Logger ) this.loggersMap.computeIfAbsent( loggerKey, key -> {
LoggerContext targetContext = getLoggerContext();
Logger oLogger = targetContext.getLogger( key.getNameNoCase() );
oLogger.setLevel( Level.TRACE );
- oLogger.addAppender( getOrBuildAppender( filePath, targetContext ) );
+ oLogger.addAppender( getOrBuildAppender( loggerFilePath, targetContext ) );
oLogger.setAdditive( true );
return oLogger;
} );
From d2cbe603693067fefef4ef1497d5c8c684f0c439 Mon Sep 17 00:00:00 2001
From: Luis Majano
Date: Wed, 4 Dec 2024 21:34:34 -0600
Subject: [PATCH 060/193] more refactoring to use getLogger()
---
.../runtime/logging/LoggingService.java | 26 +++++++++++++------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java b/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java
index 38fb4bd6f..bdabfe750 100644
--- a/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java
+++ b/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java
@@ -455,14 +455,24 @@ public Logger getLogger( String logger ) {
Key loggerKey = Key.of( FilenameUtils.getBaseName( loggerFilePath.toLowerCase() ) );
// Compute it or return it
- return ( Logger ) this.loggersMap.computeIfAbsent( loggerKey, key -> {
- LoggerContext targetContext = getLoggerContext();
- Logger oLogger = targetContext.getLogger( key.getNameNoCase() );
- oLogger.setLevel( Level.TRACE );
- oLogger.addAppender( getOrBuildAppender( loggerFilePath, targetContext ) );
- oLogger.setAdditive( true );
- return oLogger;
- } );
+ return ( Logger ) this.loggersMap.computeIfAbsent( loggerKey, key -> createLogger( loggerKey, loggerFilePath ) );
+ }
+
+ /**
+ * Build a logger with the specified name and file path
+ *
+ * @param loggerKey The key of the logger to build
+ * @param loggerFilePath The file path to log to
+ *
+ * @return The logger requested
+ */
+ private Logger createLogger( Key loggerKey, String loggerFilePath ) {
+ LoggerContext targetContext = getLoggerContext();
+ Logger oLogger = targetContext.getLogger( loggerKey.getNameNoCase() );
+ oLogger.setLevel( Level.TRACE );
+ oLogger.setAdditive( true );
+ oLogger.addAppender( getOrBuildAppender( loggerFilePath, targetContext ) );
+ return oLogger;
}
/**
From e3050c646810bcc0f51a844d600bf1d42e3a8554 Mon Sep 17 00:00:00 2001
From: Luis Majano
Date: Wed, 4 Dec 2024 21:55:37 -0600
Subject: [PATCH 061/193] dynamic loggers now created
---
.../runtime/config/segments/LoggerConfig.java | 12 +++++-
.../runtime/logging/LoggingService.java | 43 +++++++++++--------
2 files changed, 37 insertions(+), 18 deletions(-)
diff --git a/src/main/java/ortus/boxlang/runtime/config/segments/LoggerConfig.java b/src/main/java/ortus/boxlang/runtime/config/segments/LoggerConfig.java
index a85188357..1949ce72f 100644
--- a/src/main/java/ortus/boxlang/runtime/config/segments/LoggerConfig.java
+++ b/src/main/java/ortus/boxlang/runtime/config/segments/LoggerConfig.java
@@ -81,7 +81,17 @@ public class LoggerConfig implements IConfigSegment {
* @param loggingConfig The logging configuration
*/
public LoggerConfig( String name, LoggingConfig loggingConfig ) {
- this.name = new Key( name );
+ this( new Key( name ), loggingConfig );
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name The name of the logger
+ * @param loggingConfig The logging configuration
+ */
+ public LoggerConfig( Key name, LoggingConfig loggingConfig ) {
+ this.name = name;
this.loggingConfig = loggingConfig;
}
diff --git a/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java b/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java
index bdabfe750..c0bb4e04c 100644
--- a/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java
+++ b/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java
@@ -44,6 +44,7 @@
import ch.qos.logback.core.util.FileSize;
import ch.qos.logback.core.util.StatusPrinter;
import ortus.boxlang.runtime.BoxRuntime;
+import ortus.boxlang.runtime.config.segments.LoggerConfig;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.types.IStruct;
import ortus.boxlang.runtime.types.Struct;
@@ -458,23 +459,6 @@ public Logger getLogger( String logger ) {
return ( Logger ) this.loggersMap.computeIfAbsent( loggerKey, key -> createLogger( loggerKey, loggerFilePath ) );
}
- /**
- * Build a logger with the specified name and file path
- *
- * @param loggerKey The key of the logger to build
- * @param loggerFilePath The file path to log to
- *
- * @return The logger requested
- */
- private Logger createLogger( Key loggerKey, String loggerFilePath ) {
- LoggerContext targetContext = getLoggerContext();
- Logger oLogger = targetContext.getLogger( loggerKey.getNameNoCase() );
- oLogger.setLevel( Level.TRACE );
- oLogger.setAdditive( true );
- oLogger.addAppender( getOrBuildAppender( loggerFilePath, targetContext ) );
- return oLogger;
- }
-
/**
* Verify if a logger with the specified name exists
*
@@ -653,4 +637,29 @@ private JsonEncoder buildJsonEncoder() {
return targetEncoder;
}
+ /**
+ * Build a logger with the specified name and file path
+ *
+ * @param loggerKey The key of the logger to build
+ * @param loggerFilePath The file path to log to
+ *
+ * @return The logger requested
+ */
+ private Logger createLogger( Key loggerKey, String loggerFilePath ) {
+ LoggerContext targetContext = getLoggerContext();
+ Logger oLogger = targetContext.getLogger( loggerKey.getNameNoCase() );
+
+ // Check if we have the logger configuration or else build a vanilla one
+ LoggerConfig loggerConfig = ( LoggerConfig ) this.runtime
+ .getConfiguration().logging.loggers
+ .computeIfAbsent( loggerKey, key -> new LoggerConfig( key.getNameNoCase(), this.runtime.getConfiguration().logging ) );
+
+ Level targetLevel = Level.toLevel( LogLevel.valueOf( loggerConfig.level.getName(), false ).getName() );
+
+ oLogger.setLevel( targetLevel );
+ oLogger.setAdditive( loggerConfig.additive );
+ oLogger.addAppender( getOrBuildAppender( loggerFilePath, targetContext ) );
+ return oLogger;
+ }
+
}
From 7fafa028faa0b126af487d572ce1489db31ffce0 Mon Sep 17 00:00:00 2001
From: Luis Majano
Date: Wed, 4 Dec 2024 21:56:52 -0600
Subject: [PATCH 062/193] more wip on config based appenders
---
.../ortus/boxlang/runtime/logging/LoggingService.java | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java b/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java
index c0bb4e04c..61b29a853 100644
--- a/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java
+++ b/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java
@@ -524,13 +524,13 @@ public boolean removeLogger( Key loggerName ) {
/**
* Get the requested file appender according to log location
*
- * @param filePath The file path to get the appender for
- * @param logContext The logger context requested for the appender
- * @param logger The logger to add the appender to
+ * @param filePath The file path to get the appender for
+ * @param logContext The logger context requested for the appender
+ * @param loggerConfig The logger configuration
*
* @return The file appender, computed or from cache
*/
- public FileAppender getOrBuildAppender( String filePath, LoggerContext logContext ) {
+ public FileAppender getOrBuildAppender( String filePath, LoggerContext logContext, LoggerConfig loggerConfig ) {
return ( FileAppender ) this.appendersMap.computeIfAbsent( filePath.toLowerCase(), key -> {
var appender = new RollingFileAppender();
String fileName = FilenameUtils.getBaseName( filePath );
@@ -658,7 +658,7 @@ private Logger createLogger( Key loggerKey, String loggerFilePath ) {
oLogger.setLevel( targetLevel );
oLogger.setAdditive( loggerConfig.additive );
- oLogger.addAppender( getOrBuildAppender( loggerFilePath, targetContext ) );
+ oLogger.addAppender( getOrBuildAppender( loggerFilePath, targetContext, loggerConfig ) );
return oLogger;
}
From 5d1a1b6994316d5a552e734eae68cbf614971b4a Mon Sep 17 00:00:00 2001
From: lmajano
Date: Thu, 5 Dec 2024 03:57:50 +0000
Subject: [PATCH 063/193] Apply cfformat changes
---
src/main/java/ortus/boxlang/runtime/logging/LoggingService.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java b/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java
index 61b29a853..54d5a2d2a 100644
--- a/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java
+++ b/src/main/java/ortus/boxlang/runtime/logging/LoggingService.java
@@ -652,7 +652,7 @@ private Logger createLogger( Key loggerKey, String loggerFilePath ) {
// Check if we have the logger configuration or else build a vanilla one
LoggerConfig loggerConfig = ( LoggerConfig ) this.runtime
.getConfiguration().logging.loggers
- .computeIfAbsent( loggerKey, key -> new LoggerConfig( key.getNameNoCase(), this.runtime.getConfiguration().logging ) );
+ .computeIfAbsent( loggerKey, key -> new LoggerConfig( key.getNameNoCase(), this.runtime.getConfiguration().logging ) );
Level targetLevel = Level.toLevel( LogLevel.valueOf( loggerConfig.level.getName(), false ).getName() );
From 4f4f1443c5394242e6fc149de9faddeab7c0c6a3 Mon Sep 17 00:00:00 2001
From: Eric Peterson
Date: Wed, 4 Dec 2024 22:02:49 -0600
Subject: [PATCH 064/193] Add two more keys for client scope
---
src/main/java/ortus/boxlang/runtime/scopes/Key.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/main/java/ortus/boxlang/runtime/scopes/Key.java b/src/main/java/ortus/boxlang/runtime/scopes/Key.java
index ba62aa89f..732d6d0e5 100644
--- a/src/main/java/ortus/boxlang/runtime/scopes/Key.java
+++ b/src/main/java/ortus/boxlang/runtime/scopes/Key.java
@@ -429,6 +429,7 @@ public class Key implements Comparable, Serializable {
public static final Key limit = Key.of( "limit" );
public static final Key line = Key.of( "line" );
public static final Key list = Key.of( "list" );
+ public static final Key listener = Key.of( "listener" );
public static final Key listInfo = Key.of( "listInfo" );
public static final Key listToJSON = Key.of( "listToJSON" );
public static final Key lJustify = Key.of( "lJustify" );
@@ -806,6 +807,7 @@ public class Key implements Comparable, Serializable {
public static final Key cacheKey = Key.of( "cacheKey" );
public static final Key cacheRegion = Key.of( "cacheRegion" );
public static final Key clientInfo = Key.of( "clientInfo" );
+ public static final Key clientManagement = Key.of( "clientManagement" );
public static final Key connectionString = Key.of( "connectionString" );
public static final Key database = Key.of( "database" );
public static final Key dbtype = Key.of( "dbtype" );
From d59742ae41f10747f323b25d8ae2fdda5fe63a62 Mon Sep 17 00:00:00 2001
From: Eric Peterson
Date: Wed, 4 Dec 2024 23:21:18 -0600
Subject: [PATCH 065/193] Only set values with param when needed
---
.../runtime/components/system/Param.java | 5 ++--
.../runtime/components/system/ParamTest.java | 24 +++++++++++++++++++
2 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/src/main/java/ortus/boxlang/runtime/components/system/Param.java b/src/main/java/ortus/boxlang/runtime/components/system/Param.java
index 70f10a4aa..ea3001747 100644
--- a/src/main/java/ortus/boxlang/runtime/components/system/Param.java
+++ b/src/main/java/ortus/boxlang/runtime/components/system/Param.java
@@ -22,11 +22,11 @@
import ortus.boxlang.runtime.components.Attribute;
import ortus.boxlang.runtime.components.BoxComponent;
import ortus.boxlang.runtime.components.Component;
-import ortus.boxlang.runtime.validation.Validator;
import ortus.boxlang.runtime.context.IBoxContext;
import ortus.boxlang.runtime.dynamic.ExpressionInterpreter;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.types.IStruct;
+import ortus.boxlang.runtime.validation.Validator;
@BoxComponent
public class Param extends Component {
@@ -75,14 +75,13 @@ public BodyResult _invoke( IBoxContext context, IStruct attributes, ComponentBod
Object defaultValue = attributes.get( Key._DEFAULT );
Object existingValue = ExpressionInterpreter.getVariable( context, varName, defaultValue != null );
if ( existingValue == null && defaultValue != null ) {
- existingValue = defaultValue;
+ ExpressionInterpreter.setVariable( context, varName, defaultValue );
}
// TODO: Enforce validation here
// BL types can be passed to GenericCaster
// Other type delegate to isValid()
- ExpressionInterpreter.setVariable( context, varName, existingValue );
return DEFAULT_RETURN;
}
}
diff --git a/src/test/java/ortus/boxlang/runtime/components/system/ParamTest.java b/src/test/java/ortus/boxlang/runtime/components/system/ParamTest.java
index 69bc052c4..b81b2b6c5 100644
--- a/src/test/java/ortus/boxlang/runtime/components/system/ParamTest.java
+++ b/src/test/java/ortus/boxlang/runtime/components/system/ParamTest.java
@@ -33,6 +33,7 @@
import ortus.boxlang.runtime.scopes.IScope;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.scopes.VariablesScope;
+import ortus.boxlang.runtime.types.Struct;
public class ParamTest {
@@ -179,4 +180,27 @@ public void testCanParamScriptShortcutWithTypeOnly() {
assertThat( variables.getAsString( result ) ).isEqualTo( "foo" );
}
+ @DisplayName( "It can param a struct to a default value" )
+ @Test
+ public void testParamStructOnMissing() {
+ instance.executeSource(
+ """
+ param variables.result = {};
+ """,
+ context );
+ assertThat( variables.getAsStruct( result ) ).isEqualTo( Struct.of() );
+ }
+
+ @DisplayName( "It skips paraming a struct with values" )
+ @Test
+ public void testParamStructWithValues() {
+ instance.executeSource(
+ """
+ variables.result = { "foo": "bar" };
+ param variables.result = {};
+ """,
+ context );
+ assertThat( variables.getAsStruct( result ) ).isEqualTo( Struct.of( "foo", "bar" ) );
+ }
+
}
From e6af6881cbcad790eb2b41f64d60f486cc420417 Mon Sep 17 00:00:00 2001
From: Eric Peterson
Date: Wed, 4 Dec 2024 23:21:35 -0600
Subject: [PATCH 066/193] Shortcut setting a scope equal to itself
---
src/main/java/ortus/boxlang/runtime/dynamic/Referencer.java | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/main/java/ortus/boxlang/runtime/dynamic/Referencer.java b/src/main/java/ortus/boxlang/runtime/dynamic/Referencer.java
index 4bdc3e1b3..ba4684e40 100644
--- a/src/main/java/ortus/boxlang/runtime/dynamic/Referencer.java
+++ b/src/main/java/ortus/boxlang/runtime/dynamic/Referencer.java
@@ -206,6 +206,11 @@ public static Object setDeep( IBoxContext context, boolean isFinal, Key mustBeSc
// Catch the case where we're assigning an actual scope
// arguments = someStruct
if ( object instanceof IScope os && keys.length == 0 ) {
+ // if we are setting a scope equal to itself, just return it.
+ if ( os == value ) {
+ return value;
+ }
+
CastAttempt castedStruct = StructCaster.attempt( value );
if ( castedStruct.wasSuccessful() ) {
os.clear();
From e7cc6b9795f454f389234593144d870011f8e1b0 Mon Sep 17 00:00:00 2001
From: Brad Wood
Date: Thu, 5 Dec 2024 01:09:19 -0600
Subject: [PATCH 067/193] BL-239 WIP
---
src/main/antlr/SQLGrammar.g4 | 28 +-
src/main/antlr/SQLLexer.g4 | 3 +-
.../compiler/ast/sql/SQLStatement.java | 2 +-
.../compiler/ast/sql/select/SQLJoin.java | 18 +-
.../ast/sql/select/SQLResultColumn.java | 72 +-
.../compiler/ast/sql/select/SQLSelect.java | 106 ++-
.../ast/sql/select/SQLSelectStatement.java | 52 +-
.../compiler/ast/sql/select/SQLTable.java | 48 +-
.../ast/sql/select/expression/SQLColumn.java | 40 +-
.../select/expression/SQLCountFunction.java | 23 +-
.../sql/select/expression/SQLExpression.java | 22 +-
.../sql/select/expression/SQLFunction.java | 31 +-
.../ast/sql/select/expression/SQLOrderBy.java | 16 +-
.../sql/select/expression/SQLParenthesis.java | 29 +-
.../select/expression/SQLStarExpression.java | 25 +-
.../expression/literal/SQLBooleanLiteral.java | 21 +-
.../expression/literal/SQLNullLiteral.java | 20 +-
.../expression/literal/SQLNumberLiteral.java | 29 +-
.../expression/literal/SQLStringLiteral.java | 29 +-
.../operation/SQLBetweenOperation.java | 24 +-
.../operation/SQLBinaryOperation.java | 50 +-
.../expression/operation/SQLInOperation.java | 23 +-
.../operation/SQLUnaryOperation.java | 37 +-
.../compiler/parser/AbstractParser.java | 9 +-
.../boxlang/compiler/parser/SQLParser.java | 30 +-
.../compiler/toolchain/SQLVisitor.java | 287 ++++++-
.../bifs/global/jdbc/QueryExecute.java | 35 +-
.../runtime/components/jdbc/Query.java | 21 +-
.../boxlang/runtime/jdbc/ExecutedQuery.java | 13 +-
.../boxlang/runtime/jdbc/PendingQuery.java | 1 -
.../boxlang/runtime/jdbc/QueryOptions.java | 27 +-
.../runtime/jdbc/qoq/QoQConnection.java | 262 ++++++
.../runtime/jdbc/qoq/QoQResultSet.java | 800 ++++++++++++++++++
.../boxlang/runtime/jdbc/qoq/QoQService.java | 166 ++++
.../runtime/jdbc/qoq/QoQStatement.java | 217 +++++
.../runtime/types/QueryColumnType.java | 11 +
.../ortus/boxlang/compiler/QoQParseTest.java | 96 +++
37 files changed, 2610 insertions(+), 113 deletions(-)
create mode 100644 src/main/java/ortus/boxlang/runtime/jdbc/qoq/QoQConnection.java
create mode 100644 src/main/java/ortus/boxlang/runtime/jdbc/qoq/QoQResultSet.java
create mode 100644 src/main/java/ortus/boxlang/runtime/jdbc/qoq/QoQService.java
create mode 100644 src/main/java/ortus/boxlang/runtime/jdbc/qoq/QoQStatement.java
create mode 100644 src/test/java/ortus/boxlang/compiler/QoQParseTest.java
diff --git a/src/main/antlr/SQLGrammar.g4 b/src/main/antlr/SQLGrammar.g4
index 632486f81..fef3f3d91 100644
--- a/src/main/antlr/SQLGrammar.g4
+++ b/src/main/antlr/SQLGrammar.g4
@@ -340,25 +340,33 @@ reindex_stmt:
//select_stmt: common_table_stmt? select_core (compound_operator select_core)* order_by_stmt? limit_stmt?;
select_stmt:
- select_core (UNION_ ALL_? select_core)* order_by_stmt? limit_stmt?
+ select_core (union)* order_by_stmt? limit_stmt?
+;
+
+union:
+ UNION_ ALL_? select_core
;
join_clause:
table (join_operator table join_constraint?)*
;
-select_core: (
- SELECT_ (DISTINCT_ /*| ALL_*/)? result_column (COMMA result_column)* (
- FROM_ (table (COMMA table)* | join_clause)
- )? (WHERE_ whereExpr = expr)? (
- GROUP_ BY_ groupByExpr += expr (COMMA groupByExpr += expr)* (
- HAVING_ havingExpr = expr
- )?
- )? //(WINDOW_ window_name AS_ window_defn ( COMMA window_name AS_ window_defn)*)?
- )
+select_core:
+ SELECT_ top? (DISTINCT_ /*| ALL_*/)? result_column (COMMA result_column)* (
+ FROM_ (table (COMMA table)* | join_clause)
+ )? (WHERE_ whereExpr = expr)? (
+ GROUP_ BY_ groupByExpr += expr (COMMA groupByExpr += expr)* (
+ HAVING_ havingExpr = expr
+ )?
+ )? limit_stmt?
+ //(WINDOW_ window_name AS_ window_defn ( COMMA window_name AS_ window_defn)*)?
// | values_clause
;
+top:
+ TOP NUMERIC_LITERAL
+;
+
factored_select_stmt:
select_stmt
;
diff --git a/src/main/antlr/SQLLexer.g4 b/src/main/antlr/SQLLexer.g4
index f58aa3c77..74ef24c58 100644
--- a/src/main/antlr/SQLLexer.g4
+++ b/src/main/antlr/SQLLexer.g4
@@ -149,6 +149,7 @@ TEMP_: 'TEMP';
TEMPORARY_: 'TEMPORARY';
THEN_: 'THEN';
TO_: 'TO';
+TOP: 'TOP';
TRANSACTION_: 'TRANSACTION';
TRIGGER_: 'TRIGGER';
UNION_: 'UNION';
@@ -207,7 +208,7 @@ IDENTIFIER:
NUMERIC_LITERAL: ((DIGIT+ ('.' DIGIT*)?) | ('.' DIGIT+)) ('E' [-+]? DIGIT+)? | '0x' HEX_DIGIT+;
-BIND_PARAMETER: '?' DIGIT* | [:@$] IDENTIFIER;
+BIND_PARAMETER: '?' | ':' IDENTIFIER;
STRING_LITERAL: '\'' ( ~'\'' | '\'\'')* '\'';
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/SQLStatement.java b/src/main/java/ortus/boxlang/compiler/ast/sql/SQLStatement.java
index 873d75a0e..7ea0fb740 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/SQLStatement.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/SQLStatement.java
@@ -28,7 +28,7 @@ public abstract class SQLStatement extends SQLNode {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLStatement( Position position, String sourceText ) {
+ public SQLStatement( Position position, String sourceText ) {
super( position, sourceText );
}
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLJoin.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLJoin.java
index b89c85107..8eed69023 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLJoin.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLJoin.java
@@ -14,6 +14,8 @@
*/
package ortus.boxlang.compiler.ast.sql.select;
+import java.util.Map;
+
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
import ortus.boxlang.compiler.ast.sql.SQLNode;
@@ -39,7 +41,7 @@ public class SQLJoin extends SQLNode {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLJoin( SQLJoinType type, SQLTable table, SQLExpression on, Position position, String sourceText ) {
+ public SQLJoin( SQLJoinType type, SQLTable table, SQLExpression on, Position position, String sourceText ) {
super( position, sourceText );
}
@@ -103,4 +105,18 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ map.put( "type", enumToMap( type ) );
+ map.put( "table", table.toMap() );
+ if ( on != null ) {
+ map.put( "on", on.toMap() );
+ } else {
+ map.put( "on", null );
+ }
+ return map;
+ }
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLResultColumn.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLResultColumn.java
index f2f986ca5..4e5e4c1b6 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLResultColumn.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLResultColumn.java
@@ -14,20 +14,28 @@
*/
package ortus.boxlang.compiler.ast.sql.select;
+import java.util.Map;
+
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
import ortus.boxlang.compiler.ast.sql.SQLNode;
+import ortus.boxlang.compiler.ast.sql.select.expression.SQLColumn;
+import ortus.boxlang.compiler.ast.sql.select.expression.SQLExpression;
+import ortus.boxlang.compiler.ast.sql.select.expression.SQLStarExpression;
import ortus.boxlang.compiler.ast.visitor.ReplacingBoxVisitor;
import ortus.boxlang.compiler.ast.visitor.VoidBoxVisitor;
+import ortus.boxlang.runtime.scopes.Key;
/**
* Abstract Node class representing SQL result column declaration
*/
public class SQLResultColumn extends SQLNode {
- private SQLNode expression;
+ private SQLExpression expression;
+
+ private Key alias;
- private String alias;
+ private int ordinalPosition;
/**
* Constructor
@@ -35,23 +43,24 @@ public class SQLResultColumn extends SQLNode {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLResultColumn( SQLNode expression, String alias, Position position, String sourceText ) {
+ public SQLResultColumn( SQLExpression expression, String alias, int ordinalPosition, Position position, String sourceText ) {
super( position, sourceText );
setExpression( expression );
setAlias( alias );
+ setOrdinalPosition( ordinalPosition );
}
/**
* Get the expression
*/
- public SQLNode getExpression() {
+ public SQLExpression getExpression() {
return expression;
}
/**
* Set the expression
*/
- public void setExpression( SQLNode expression ) {
+ public void setExpression( SQLExpression expression ) {
replaceChildren( this.expression, expression );
this.expression = expression;
this.expression.setParent( this );
@@ -60,7 +69,7 @@ public void setExpression( SQLNode expression ) {
/**
* Get the table alias
*/
- public String getAlias() {
+ public Key getAlias() {
return alias;
}
@@ -68,7 +77,42 @@ public String getAlias() {
* Set the table alias
*/
public void setAlias( String alias ) {
- this.alias = alias;
+ this.alias = ( alias == null ) ? null : Key.of( alias );
+ }
+
+ /**
+ * Get the ordinal position
+ */
+ public int getOrdinalPosition() {
+ return ordinalPosition;
+ }
+
+ /**
+ * Set the ordinal position
+ */
+ public void setOrdinalPosition( int ordinalPosition ) {
+ this.ordinalPosition = ordinalPosition;
+ }
+
+ /**
+ * The name this result column will have in the final result set. This is either the alias or the column name.
+ * If it's any other expression, we name it column_0, column_1, column_2, etc based on the ordinal position in the overall result set.
+ */
+ public Key getResultColumnName() {
+ if ( alias != null ) {
+ return alias;
+ } else if ( expression instanceof SQLColumn c ) {
+ return c.getName();
+ } else {
+ return Key.of( "column_" + ( ordinalPosition - 1 ) );
+ }
+ }
+
+ /**
+ * Is this column a star column?
+ */
+ public boolean isStarExpression() {
+ return expression instanceof SQLStarExpression;
}
@Override
@@ -82,4 +126,18 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ map.put( "expression", expression.toMap() );
+ if ( alias != null ) {
+ map.put( "alias", alias );
+ } else {
+ map.put( "alias", null );
+ }
+ return map;
+ }
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLSelect.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLSelect.java
index 82fe54f13..89c12fa38 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLSelect.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLSelect.java
@@ -15,11 +15,13 @@
package ortus.boxlang.compiler.ast.sql.select;
import java.util.List;
+import java.util.Map;
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
import ortus.boxlang.compiler.ast.sql.SQLNode;
import ortus.boxlang.compiler.ast.sql.select.expression.SQLExpression;
+import ortus.boxlang.compiler.ast.sql.select.expression.literal.SQLNumberLiteral;
import ortus.boxlang.compiler.ast.visitor.ReplacingBoxVisitor;
import ortus.boxlang.compiler.ast.visitor.VoidBoxVisitor;
import ortus.boxlang.runtime.types.exceptions.BoxRuntimeException;
@@ -43,15 +45,16 @@ public class SQLSelect extends SQLNode {
private SQLExpression having;
+ private SQLNumberLiteral limit;
+
/**
* Constructor
*
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLSelect( boolean distinct, List resultColumns, SQLTable table, List joins, SQLExpression where,
- List groupBys,
- SQLExpression having, Position position, String sourceText ) {
+ public SQLSelect( boolean distinct, List resultColumns, SQLTable table, List joins, SQLExpression where,
+ List groupBys, SQLExpression having, SQLNumberLiteral limit, Position position, String sourceText ) {
super( position, sourceText );
setDistinct( distinct );
setResultColumns( resultColumns );
@@ -60,6 +63,7 @@ protected SQLSelect( boolean distinct, List resultColumns, SQLT
setWhere( where );
setGroupBys( groupBys );
setHaving( having );
+ setLimit( limit );
}
/**
@@ -75,7 +79,13 @@ public void setDistinct( boolean distinct ) {
public void setResultColumns( List resultColumns ) {
replaceChildren( this.resultColumns, resultColumns );
this.resultColumns = resultColumns;
- resultColumns.forEach( c -> c.setParent( this ) );
+ if ( resultColumns != null ) {
+ for ( int i = 0; i < resultColumns.size(); i++ ) {
+ SQLResultColumn column = resultColumns.get( i );
+ column.setParent( this );
+ column.setOrdinalPosition( i + 1 );
+ }
+ }
}
/**
@@ -84,7 +94,9 @@ public void setResultColumns( List resultColumns ) {
public void setTable( SQLTable table ) {
replaceChildren( this.table, table );
this.table = table;
- table.setParent( this );
+ if ( table != null ) {
+ table.setParent( this );
+ }
}
/**
@@ -93,19 +105,23 @@ public void setTable( SQLTable table ) {
public void setJoins( List joins ) {
replaceChildren( this.joins, joins );
this.joins = joins;
- joins.forEach( j -> j.setParent( this ) );
+ if ( joins != null ) {
+ joins.forEach( j -> j.setParent( this ) );
+ }
}
/**
* Set the WHERE node
*/
public void setWhere( SQLExpression where ) {
- if ( !where.isBoolean() ) {
+ if ( where != null && !where.isBoolean() ) {
throw new BoxRuntimeException( "WHERE clause must be a boolean expression" );
}
replaceChildren( this.where, where );
this.where = where;
- where.setParent( this );
+ if ( where != null ) {
+ where.setParent( this );
+ }
}
/**
@@ -114,19 +130,23 @@ public void setWhere( SQLExpression where ) {
public void setGroupBys( List groupBys ) {
replaceChildren( this.groupBys, groupBys );
this.groupBys = groupBys;
- groupBys.forEach( g -> g.setParent( this ) );
+ if ( groupBys != null ) {
+ groupBys.forEach( g -> g.setParent( this ) );
+ }
}
/**
* Set the HAVING node
*/
public void setHaving( SQLExpression having ) {
- if ( !having.isBoolean() ) {
+ if ( having != null && !having.isBoolean() ) {
throw new BoxRuntimeException( "HAVING clause must be a boolean expression" );
}
replaceChildren( this.having, having );
this.having = having;
- having.setParent( this );
+ if ( having != null ) {
+ having.setParent( this );
+ }
}
/**
@@ -178,6 +198,24 @@ public SQLExpression getHaving() {
return having;
}
+ /**
+ * Set the LIMIT node
+ */
+ public void setLimit( SQLNumberLiteral limit ) {
+ replaceChildren( this.limit, limit );
+ this.limit = limit;
+ if ( limit != null ) {
+ limit.setParent( this );
+ }
+ }
+
+ /**
+ * Get the LIMIT node
+ */
+ public SQLNumberLiteral getLimit() {
+ return limit;
+ }
+
@Override
public void accept( VoidBoxVisitor v ) {
// TODO Auto-generated method stub
@@ -189,4 +227,50 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ if ( distinct ) {
+ map.put( "distinct", distinct );
+ } else {
+ map.put( "distinct", null );
+ }
+
+ map.put( "resultColumns", resultColumns.stream().map( SQLResultColumn::toMap ).toList() );
+ if ( table != null ) {
+ map.put( "table", table.toMap() );
+ } else {
+ map.put( "table", null );
+ }
+ if ( joins != null ) {
+ map.put( "joins", joins.stream().map( SQLJoin::toMap ).toList() );
+ } else {
+ map.put( "joins", null );
+ }
+ if ( where != null ) {
+ map.put( "where", where.toMap() );
+ } else {
+ map.put( "where", null );
+ }
+ if ( groupBys != null ) {
+ map.put( "groupBys", groupBys.stream().map( SQLExpression::toMap ).toList() );
+ } else {
+ map.put( "groupBys", null );
+ }
+ if ( having != null ) {
+ map.put( "having", having.toMap() );
+ } else {
+ map.put( "having", null );
+ }
+ if ( limit != null ) {
+ map.put( "limit", limit.toMap() );
+ } else {
+ map.put( "limit", null );
+ }
+
+ return map;
+ }
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLSelectStatement.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLSelectStatement.java
index 89735a1cc..684172035 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLSelectStatement.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLSelectStatement.java
@@ -15,6 +15,7 @@
package ortus.boxlang.compiler.ast.sql.select;
import java.util.List;
+import java.util.Map;
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
@@ -41,7 +42,7 @@ public class SQLSelectStatement extends SQLStatement {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLSelectStatement( SQLSelect select, List unions, List orderBys, SQLNumberLiteral limit, Position position,
+ public SQLSelectStatement( SQLSelect select, List unions, List orderBys, SQLNumberLiteral limit, Position position,
String sourceText ) {
super( position, sourceText );
setSelect( select );
@@ -56,7 +57,9 @@ protected SQLSelectStatement( SQLSelect select, List unions, List unions ) {
replaceChildren( this.unions, unions );
this.unions = unions;
- unions.forEach( u -> u.setParent( this ) );
+ if ( unions != null ) {
+ unions.forEach( u -> u.setParent( this ) );
+ }
}
/**
@@ -88,14 +93,9 @@ public List getUnions() {
public void setOrderBys( List orderBys ) {
replaceChildren( this.orderBys, orderBys );
this.orderBys = orderBys;
- orderBys.forEach( o -> o.setParent( this ) );
- }
-
- /**
- * Get the ORDER BY nodes
- */
- public List getOrderBys() {
- return orderBys;
+ if ( orderBys != null ) {
+ orderBys.forEach( o -> o.setParent( this ) );
+ }
}
/**
@@ -104,7 +104,9 @@ public List getOrderBys() {
public void setLimit( SQLNumberLiteral limit ) {
replaceChildren( this.limit, limit );
this.limit = limit;
- limit.setParent( this );
+ if ( limit != null ) {
+ limit.setParent( this );
+ }
}
/**
@@ -114,6 +116,13 @@ public SQLNumberLiteral getLimit() {
return limit;
}
+ /**
+ * Get the ORDER BY nodes
+ */
+ public List getOrderBys() {
+ return orderBys;
+ }
+
@Override
public void accept( VoidBoxVisitor v ) {
// TODO Auto-generated method stub
@@ -125,4 +134,23 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ map.put( "select", select.toMap() );
+ if ( unions != null ) {
+ map.put( "unions", unions.stream().map( SQLSelect::toMap ).toList() );
+ } else {
+ map.put( "unions", null );
+ }
+ if ( orderBys != null ) {
+ map.put( "orderBys", orderBys.stream().map( SQLOrderBy::toMap ).toList() );
+ } else {
+ map.put( "orderBys", null );
+ }
+ return map;
+ }
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLTable.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLTable.java
index bbd4af586..1fa3f0acd 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLTable.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/SQLTable.java
@@ -14,11 +14,14 @@
*/
package ortus.boxlang.compiler.ast.sql.select;
+import java.util.Map;
+
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
import ortus.boxlang.compiler.ast.sql.SQLNode;
import ortus.boxlang.compiler.ast.visitor.ReplacingBoxVisitor;
import ortus.boxlang.compiler.ast.visitor.VoidBoxVisitor;
+import ortus.boxlang.runtime.scopes.Key;
/**
* Abstract Node class representing SQL table declaration
@@ -27,9 +30,9 @@ public class SQLTable extends SQLNode {
private String schema;
- private String name;
+ private Key name;
- private String alias;
+ private Key alias;
/**
* Constructor
@@ -37,7 +40,7 @@ public class SQLTable extends SQLNode {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLTable( String schema, String name, String alias, Position position, String sourceText ) {
+ public SQLTable( String schema, String name, String alias, Position position, String sourceText ) {
super( position, sourceText );
setSchema( schema );
setName( name );
@@ -61,7 +64,7 @@ public void setSchema( String schema ) {
/**
* Get the table name
*/
- public String getName() {
+ public Key getName() {
return name;
}
@@ -69,13 +72,13 @@ public String getName() {
* Set the table name
*/
public void setName( String name ) {
- this.name = name;
+ this.name = Key.of( name );
}
/**
* Get the table alias
*/
- public String getAlias() {
+ public Key getAlias() {
return alias;
}
@@ -83,7 +86,19 @@ public String getAlias() {
* Set the table alias
*/
public void setAlias( String alias ) {
- this.alias = alias;
+ this.alias = ( alias == null ) ? null : Key.of( alias );
+ }
+
+ public boolean isCalled( Key name ) {
+ return this.name.equals( name ) || ( alias != null && alias.equals( name ) );
+ }
+
+ public String getVariableName() {
+ if ( schema != null ) {
+ return schema + "." + name.getName();
+ } else {
+ return name.getName();
+ }
}
@Override
@@ -97,4 +112,23 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ if ( schema != null ) {
+ map.put( "schema", schema );
+ } else {
+ map.put( "schema", null );
+ }
+ map.put( "name", name.getName() );
+ if ( alias != null ) {
+ map.put( "alias", alias.getName() );
+ } else {
+ map.put( "alias", null );
+ }
+ return map;
+ }
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLColumn.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLColumn.java
index a7f46a34f..d1645d412 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLColumn.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLColumn.java
@@ -14,11 +14,16 @@
*/
package ortus.boxlang.compiler.ast.sql.select.expression;
+import java.util.Map;
+
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
import ortus.boxlang.compiler.ast.sql.select.SQLTable;
import ortus.boxlang.compiler.ast.visitor.ReplacingBoxVisitor;
import ortus.boxlang.compiler.ast.visitor.VoidBoxVisitor;
+import ortus.boxlang.runtime.scopes.Key;
+import ortus.boxlang.runtime.types.Query;
+import ortus.boxlang.runtime.types.QueryColumnType;
/**
* Abstract Node class representing SQL column reference
@@ -27,7 +32,7 @@ public class SQLColumn extends SQLExpression {
private SQLTable table;
- private String name;
+ private Key name;
/**
* Constructor
@@ -35,7 +40,7 @@ public class SQLColumn extends SQLExpression {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLColumn( SQLTable table, String name, Position position, String sourceText ) {
+ public SQLColumn( SQLTable table, String name, Position position, String sourceText ) {
super( position, sourceText );
setName( name );
setTable( table );
@@ -46,7 +51,7 @@ protected SQLColumn( SQLTable table, String name, Position position, String sour
*
* @return the name of the function
*/
- public String getName() {
+ public Key getName() {
return name;
}
@@ -56,7 +61,7 @@ public String getName() {
* @param name the name of the function
*/
public void setName( String name ) {
- this.name = name;
+ this.name = Key.of( name );
}
/**
@@ -74,6 +79,20 @@ public void setTable( SQLTable table ) {
this.table = table;
}
+ /**
+ * What type does this expression evaluate to
+ */
+ public QueryColumnType getType( Map tableLookup ) {
+ return tableLookup.get( table ).getColumns().get( name ).getType();
+ }
+
+ /**
+ * Evaluate the expression
+ */
+ public Object evaluate( Map tableLookup, int i ) {
+ return tableLookup.get( table ).getCell( name, i - 1 );
+ }
+
@Override
public void accept( VoidBoxVisitor v ) {
// TODO Auto-generated method stub
@@ -86,4 +105,17 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ map.put( "name", name.getName() );
+ if ( table != null ) {
+ map.put( "table", table.toMap() );
+ } else {
+ map.put( "table", null );
+ }
+ return map;
+ }
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLCountFunction.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLCountFunction.java
index c29f40ebc..cd5e7f7db 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLCountFunction.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLCountFunction.java
@@ -15,11 +15,15 @@
package ortus.boxlang.compiler.ast.sql.select.expression;
import java.util.List;
+import java.util.Map;
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
+import ortus.boxlang.compiler.ast.sql.select.SQLTable;
import ortus.boxlang.compiler.ast.visitor.ReplacingBoxVisitor;
import ortus.boxlang.compiler.ast.visitor.VoidBoxVisitor;
+import ortus.boxlang.runtime.types.Query;
+import ortus.boxlang.runtime.types.QueryColumnType;
/**
* Abstract Node class representing SQL count() function call
@@ -34,7 +38,7 @@ public class SQLCountFunction extends SQLFunction {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLCountFunction( String name, List arguments, boolean distinct, Position position, String sourceText ) {
+ public SQLCountFunction( String name, List arguments, boolean distinct, Position position, String sourceText ) {
super( name, arguments, position, sourceText );
setDistinct( distinct );
}
@@ -53,6 +57,13 @@ public boolean isDistinct() {
return distinct;
}
+ /**
+ * What type does this expression evaluate to
+ */
+ public QueryColumnType getType( Map tableLookup ) {
+ return QueryColumnType.INTEGER;
+ }
+
@Override
public void accept( VoidBoxVisitor v ) {
// TODO Auto-generated method stub
@@ -65,4 +76,14 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ map.put( "distinct", isDistinct() );
+ map.put( "name", getName() );
+ map.put( "arguments", getArguments().stream().map( BoxNode::toMap ).toList() );
+ return map;
+ }
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLExpression.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLExpression.java
index 3937b25e2..d4ad6647d 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLExpression.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLExpression.java
@@ -14,8 +14,13 @@
*/
package ortus.boxlang.compiler.ast.sql.select.expression;
+import java.util.Map;
+
import ortus.boxlang.compiler.ast.Position;
import ortus.boxlang.compiler.ast.sql.SQLNode;
+import ortus.boxlang.compiler.ast.sql.select.SQLTable;
+import ortus.boxlang.runtime.types.Query;
+import ortus.boxlang.runtime.types.QueryColumnType;
/**
* Abstract Node class representing SQL expression
@@ -28,7 +33,7 @@ public abstract class SQLExpression extends SQLNode {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLExpression( Position position, String sourceText ) {
+ public SQLExpression( Position position, String sourceText ) {
super( position, sourceText );
}
@@ -46,4 +51,19 @@ public boolean isBoolean() {
return false;
}
+ /**
+ * What type does this expression evaluate to
+ */
+ public QueryColumnType getType( Map tableLookup ) {
+ if ( isBoolean() ) {
+ return QueryColumnType.BIT;
+ }
+ return QueryColumnType.OBJECT;
+ }
+
+ /**
+ * Evaluate the expression
+ */
+ public abstract Object evaluate( Map tableLookup, int i );
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLFunction.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLFunction.java
index cc79d29d5..f06e6e1ef 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLFunction.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLFunction.java
@@ -15,11 +15,16 @@
package ortus.boxlang.compiler.ast.sql.select.expression;
import java.util.List;
+import java.util.Map;
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
+import ortus.boxlang.compiler.ast.sql.select.SQLTable;
import ortus.boxlang.compiler.ast.visitor.ReplacingBoxVisitor;
import ortus.boxlang.compiler.ast.visitor.VoidBoxVisitor;
+import ortus.boxlang.runtime.types.Query;
+import ortus.boxlang.runtime.types.QueryColumnType;
+import ortus.boxlang.runtime.types.exceptions.BoxRuntimeException;
/**
* Abstract Node class representing SQL function call
@@ -36,7 +41,7 @@ public class SQLFunction extends SQLExpression {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLFunction( String name, List arguments, Position position, String sourceText ) {
+ public SQLFunction( String name, List arguments, Position position, String sourceText ) {
super( position, sourceText );
setName( name );
setArguments( arguments );
@@ -88,6 +93,21 @@ public boolean isBoolean() {
return false;
}
+ /**
+ * What type does this expression evaluate to
+ */
+ public QueryColumnType getType( Map tableLookup ) {
+ // TODO: actually return proper type based on the function in question
+ return QueryColumnType.OBJECT;
+ }
+
+ /**
+ * Evaluate the expression
+ */
+ public Object evaluate( Map tableLookup, int i ) {
+ throw new BoxRuntimeException( "not implemented" );
+ }
+
@Override
public void accept( VoidBoxVisitor v ) {
// TODO Auto-generated method stub
@@ -100,4 +120,13 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ map.put( "name", getName() );
+ map.put( "arguments", getArguments().stream().map( BoxNode::toMap ).toList() );
+ return map;
+ }
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLOrderBy.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLOrderBy.java
index 6db36e988..1248af906 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLOrderBy.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLOrderBy.java
@@ -14,15 +14,18 @@
*/
package ortus.boxlang.compiler.ast.sql.select.expression;
+import java.util.Map;
+
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
+import ortus.boxlang.compiler.ast.sql.SQLNode;
import ortus.boxlang.compiler.ast.visitor.ReplacingBoxVisitor;
import ortus.boxlang.compiler.ast.visitor.VoidBoxVisitor;
/**
* Abstract Node class representing SQL Order By item
*/
-public class SQLOrderBy extends SQLExpression {
+public class SQLOrderBy extends SQLNode {
private SQLExpression expression;
@@ -34,7 +37,7 @@ public class SQLOrderBy extends SQLExpression {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLOrderBy( SQLExpression expression, boolean ascending, Position position, String sourceText ) {
+ public SQLOrderBy( SQLExpression expression, boolean ascending, Position position, String sourceText ) {
super( position, sourceText );
setExpression( expression );
setAscending( ascending );
@@ -82,4 +85,13 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ map.put( "expression", expression.toMap() );
+ map.put( "ascending", ascending );
+ return map;
+ }
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLParenthesis.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLParenthesis.java
index 17ef09d12..72c46cad9 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLParenthesis.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLParenthesis.java
@@ -14,10 +14,15 @@
*/
package ortus.boxlang.compiler.ast.sql.select.expression;
+import java.util.Map;
+
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
+import ortus.boxlang.compiler.ast.sql.select.SQLTable;
import ortus.boxlang.compiler.ast.visitor.ReplacingBoxVisitor;
import ortus.boxlang.compiler.ast.visitor.VoidBoxVisitor;
+import ortus.boxlang.runtime.types.Query;
+import ortus.boxlang.runtime.types.QueryColumnType;
/**
* Abstract Node class representing SQL parenthetical expression
@@ -32,7 +37,7 @@ public class SQLParenthesis extends SQLExpression {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLParenthesis( SQLExpression expression, Position position, String sourceText ) {
+ public SQLParenthesis( SQLExpression expression, Position position, String sourceText ) {
super( position, sourceText );
setExpression( expression );
}
@@ -60,6 +65,20 @@ public boolean isBoolean() {
return expression.isBoolean();
}
+ /**
+ * What type does this expression evaluate to
+ */
+ public QueryColumnType getType( Map tableLookup ) {
+ return expression.getType( tableLookup );
+ }
+
+ /**
+ * Evaluate the expression
+ */
+ public Object evaluate( Map tableLookup, int i ) {
+ return expression.evaluate( tableLookup, i );
+ }
+
@Override
public void accept( VoidBoxVisitor v ) {
// TODO Auto-generated method stub
@@ -72,4 +91,12 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ map.put( "expression", expression.toMap() );
+ return map;
+ }
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLStarExpression.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLStarExpression.java
index a6ec7aa10..cde8d7f4c 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLStarExpression.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/SQLStarExpression.java
@@ -14,11 +14,15 @@
*/
package ortus.boxlang.compiler.ast.sql.select.expression;
+import java.util.Map;
+
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
import ortus.boxlang.compiler.ast.sql.select.SQLTable;
import ortus.boxlang.compiler.ast.visitor.ReplacingBoxVisitor;
import ortus.boxlang.compiler.ast.visitor.VoidBoxVisitor;
+import ortus.boxlang.runtime.types.Query;
+import ortus.boxlang.runtime.types.exceptions.BoxRuntimeException;
/**
* Abstract Node class representing SQL * expression
@@ -33,7 +37,7 @@ public class SQLStarExpression extends SQLExpression {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLStarExpression( SQLTable table, Position position, String sourceText ) {
+ public SQLStarExpression( SQLTable table, Position position, String sourceText ) {
super( position, sourceText );
setTable( table );
}
@@ -53,6 +57,13 @@ public void setTable( SQLTable table ) {
this.table = table;
}
+ /**
+ * Evaluate the expression
+ */
+ public Object evaluate( Map tableLookup, int i ) {
+ throw new BoxRuntimeException( "Cannot evaluate a * expression" );
+ }
+
@Override
public void accept( VoidBoxVisitor v ) {
// TODO Auto-generated method stub
@@ -65,4 +76,16 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ if ( table != null ) {
+ map.put( "table", table.toMap() );
+ } else {
+ map.put( "table", null );
+ }
+ return map;
+ }
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/literal/SQLBooleanLiteral.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/literal/SQLBooleanLiteral.java
index 5372cfe50..4d2c870bc 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/literal/SQLBooleanLiteral.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/literal/SQLBooleanLiteral.java
@@ -14,11 +14,15 @@
*/
package ortus.boxlang.compiler.ast.sql.select.expression.literal;
+import java.util.Map;
+
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
+import ortus.boxlang.compiler.ast.sql.select.SQLTable;
import ortus.boxlang.compiler.ast.sql.select.expression.SQLExpression;
import ortus.boxlang.compiler.ast.visitor.ReplacingBoxVisitor;
import ortus.boxlang.compiler.ast.visitor.VoidBoxVisitor;
+import ortus.boxlang.runtime.types.Query;
/**
* Abstract Node class representing SQL boolean
@@ -33,7 +37,7 @@ public class SQLBooleanLiteral extends SQLExpression {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLBooleanLiteral( boolean value, Position position, String sourceText ) {
+ public SQLBooleanLiteral( boolean value, Position position, String sourceText ) {
super( position, sourceText );
setValue( value );
}
@@ -65,6 +69,13 @@ public boolean isBoolean() {
return true;
}
+ /**
+ * Evaluate the expression
+ */
+ public Object evaluate( Map tableLookup, int i ) {
+ return value;
+ }
+
@Override
public void accept( VoidBoxVisitor v ) {
// TODO Auto-generated method stub
@@ -77,4 +88,12 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ map.put( "value", value );
+ return map;
+ }
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/literal/SQLNullLiteral.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/literal/SQLNullLiteral.java
index 45514b3fd..51f8f09e6 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/literal/SQLNullLiteral.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/literal/SQLNullLiteral.java
@@ -14,11 +14,15 @@
*/
package ortus.boxlang.compiler.ast.sql.select.expression.literal;
+import java.util.Map;
+
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
+import ortus.boxlang.compiler.ast.sql.select.SQLTable;
import ortus.boxlang.compiler.ast.sql.select.expression.SQLExpression;
import ortus.boxlang.compiler.ast.visitor.ReplacingBoxVisitor;
import ortus.boxlang.compiler.ast.visitor.VoidBoxVisitor;
+import ortus.boxlang.runtime.types.Query;
/**
* Abstract Node class representing SQL null
@@ -31,7 +35,7 @@ public class SQLNullLiteral extends SQLExpression {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLNullLiteral( Position position, String sourceText ) {
+ public SQLNullLiteral( Position position, String sourceText ) {
super( position, sourceText );
}
@@ -42,6 +46,13 @@ public boolean isLiteral() {
return true;
}
+ /**
+ * Evaluate the expression
+ */
+ public Object evaluate( Map tableLookup, int i ) {
+ return null;
+ }
+
@Override
public void accept( VoidBoxVisitor v ) {
// TODO Auto-generated method stub
@@ -54,4 +65,11 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ return map;
+ }
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/literal/SQLNumberLiteral.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/literal/SQLNumberLiteral.java
index 9e318f7b2..69a90e524 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/literal/SQLNumberLiteral.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/literal/SQLNumberLiteral.java
@@ -14,11 +14,16 @@
*/
package ortus.boxlang.compiler.ast.sql.select.expression.literal;
+import java.util.Map;
+
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
+import ortus.boxlang.compiler.ast.sql.select.SQLTable;
import ortus.boxlang.compiler.ast.sql.select.expression.SQLExpression;
import ortus.boxlang.compiler.ast.visitor.ReplacingBoxVisitor;
import ortus.boxlang.compiler.ast.visitor.VoidBoxVisitor;
+import ortus.boxlang.runtime.types.Query;
+import ortus.boxlang.runtime.types.QueryColumnType;
/**
* Abstract Node class representing SQL number literal
@@ -33,7 +38,7 @@ public class SQLNumberLiteral extends SQLExpression {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLNumberLiteral( Number value, Position position, String sourceText ) {
+ public SQLNumberLiteral( Number value, Position position, String sourceText ) {
super( position, sourceText );
setValue( value );
}
@@ -58,6 +63,20 @@ public boolean isLiteral() {
return true;
}
+ /**
+ * What type does this expression evaluate to
+ */
+ public QueryColumnType getType( Map tableLookup ) {
+ return QueryColumnType.DOUBLE;
+ }
+
+ /**
+ * Evaluate the expression
+ */
+ public Object evaluate( Map tableLookup, int i ) {
+ return value;
+ }
+
@Override
public void accept( VoidBoxVisitor v ) {
// TODO Auto-generated method stub
@@ -70,4 +89,12 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ map.put( "value", value );
+ return map;
+ }
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/literal/SQLStringLiteral.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/literal/SQLStringLiteral.java
index 6d9d91f0c..0a5773a14 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/literal/SQLStringLiteral.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/literal/SQLStringLiteral.java
@@ -14,11 +14,16 @@
*/
package ortus.boxlang.compiler.ast.sql.select.expression.literal;
+import java.util.Map;
+
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
+import ortus.boxlang.compiler.ast.sql.select.SQLTable;
import ortus.boxlang.compiler.ast.sql.select.expression.SQLExpression;
import ortus.boxlang.compiler.ast.visitor.ReplacingBoxVisitor;
import ortus.boxlang.compiler.ast.visitor.VoidBoxVisitor;
+import ortus.boxlang.runtime.types.Query;
+import ortus.boxlang.runtime.types.QueryColumnType;
/**
* Abstract Node class representing SQL string literal
@@ -33,7 +38,7 @@ public class SQLStringLiteral extends SQLExpression {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLStringLiteral( String value, Position position, String sourceText ) {
+ public SQLStringLiteral( String value, Position position, String sourceText ) {
super( position, sourceText );
setValue( value );
}
@@ -58,6 +63,20 @@ public boolean isLiteral() {
return true;
}
+ /**
+ * What type does this expression evaluate to
+ */
+ public QueryColumnType getType( Map tableLookup ) {
+ return QueryColumnType.VARCHAR;
+ }
+
+ /**
+ * Evaluate the expression
+ */
+ public Object evaluate( Map tableLookup, int i ) {
+ return value;
+ }
+
@Override
public void accept( VoidBoxVisitor v ) {
// TODO Auto-generated method stub
@@ -70,4 +89,12 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ map.put( "value", value );
+ return map;
+ }
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/operation/SQLBetweenOperation.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/operation/SQLBetweenOperation.java
index 8fec19759..a330fb630 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/operation/SQLBetweenOperation.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/operation/SQLBetweenOperation.java
@@ -14,11 +14,16 @@
*/
package ortus.boxlang.compiler.ast.sql.select.expression.operation;
+import java.util.Map;
+
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
+import ortus.boxlang.compiler.ast.sql.select.SQLTable;
import ortus.boxlang.compiler.ast.sql.select.expression.SQLExpression;
import ortus.boxlang.compiler.ast.visitor.ReplacingBoxVisitor;
import ortus.boxlang.compiler.ast.visitor.VoidBoxVisitor;
+import ortus.boxlang.runtime.types.Query;
+import ortus.boxlang.runtime.types.exceptions.BoxRuntimeException;
/**
* Abstract Node class representing SQL BETWEEN operation
@@ -37,7 +42,7 @@ public class SQLBetweenOperation extends SQLExpression {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLBetweenOperation( SQLExpression expression, SQLExpression left, SQLExpression right, Position position, String sourceText ) {
+ public SQLBetweenOperation( SQLExpression expression, SQLExpression left, SQLExpression right, Position position, String sourceText ) {
super( position, sourceText );
setExpression( expression );
setLeft( left );
@@ -99,6 +104,13 @@ public boolean isBoolean() {
return true;
}
+ /**
+ * Evaluate the expression
+ */
+ public Object evaluate( Map tableLookup, int i ) {
+ throw new BoxRuntimeException( "not implemented" );
+ }
+
@Override
public void accept( VoidBoxVisitor v ) {
// TODO Auto-generated method stub
@@ -111,4 +123,14 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ map.put( "expression", expression.toMap() );
+ map.put( "left", left.toMap() );
+ map.put( "right", right.toMap() );
+ return map;
+ }
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/operation/SQLBinaryOperation.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/operation/SQLBinaryOperation.java
index 1ca4d6656..1390b7cd7 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/operation/SQLBinaryOperation.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/operation/SQLBinaryOperation.java
@@ -14,13 +14,18 @@
*/
package ortus.boxlang.compiler.ast.sql.select.expression.operation;
+import java.util.Map;
import java.util.Set;
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
+import ortus.boxlang.compiler.ast.sql.select.SQLTable;
import ortus.boxlang.compiler.ast.sql.select.expression.SQLExpression;
import ortus.boxlang.compiler.ast.visitor.ReplacingBoxVisitor;
import ortus.boxlang.compiler.ast.visitor.VoidBoxVisitor;
+import ortus.boxlang.runtime.types.Query;
+import ortus.boxlang.runtime.types.QueryColumnType;
+import ortus.boxlang.runtime.types.exceptions.BoxRuntimeException;
/**
* Abstract Node class representing SQL binary operation
@@ -31,6 +36,9 @@ public class SQLBinaryOperation extends SQLExpression {
private static final Set booleanOperators = Set.of( SQLBinaryOperator.EQUAL, SQLBinaryOperator.NOTEQUAL, SQLBinaryOperator.LESSTHAN,
SQLBinaryOperator.LESSTHANOREQUAL, SQLBinaryOperator.GREATERTHAN, SQLBinaryOperator.GREATERTHANOREQUAL, SQLBinaryOperator.AND, SQLBinaryOperator.OR );
+ private static Set mathOperators = Set.of( SQLBinaryOperator.MINUS, SQLBinaryOperator.MULTIPLY, SQLBinaryOperator.DIVIDE,
+ SQLBinaryOperator.MODULO );
+
private SQLExpression left;
private SQLExpression right;
@@ -43,7 +51,7 @@ public class SQLBinaryOperation extends SQLExpression {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLBinaryOperation( SQLExpression left, SQLExpression right, SQLBinaryOperator operator, Position position, String sourceText ) {
+ public SQLBinaryOperation( SQLExpression left, SQLExpression right, SQLBinaryOperator operator, Position position, String sourceText ) {
super( position, sourceText );
setLeft( left );
setRight( right );
@@ -103,6 +111,34 @@ public boolean isBoolean() {
return booleanOperators.contains( operator );
}
+ /**
+ * What type does this expression evaluate to
+ */
+ public QueryColumnType getType( Map tableLookup ) {
+ // If this is a boolean operation, then we're a bit
+ if ( isBoolean() ) {
+ return QueryColumnType.BIT;
+ }
+ // All math operators but + return a number
+ if ( mathOperators.contains( operator ) ) {
+ return QueryColumnType.DOUBLE;
+ }
+ // Plus returns a string if the left and right operand were a string, otherwise it's a math operation.
+ if ( operator == SQLBinaryOperator.PLUS ) {
+ return QueryColumnType.isStringType( left.getType( tableLookup ) ) && QueryColumnType.isStringType( right.getType( tableLookup ) )
+ ? QueryColumnType.VARCHAR
+ : QueryColumnType.DOUBLE;
+ }
+ return QueryColumnType.OBJECT;
+ }
+
+ /**
+ * Evaluate the expression
+ */
+ public Object evaluate( Map tableLookup, int i ) {
+ throw new BoxRuntimeException( "not implemented" );
+ }
+
@Override
public void accept( VoidBoxVisitor v ) {
// TODO Auto-generated method stub
@@ -115,4 +151,14 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
-}
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ map.put( "left", left.toMap() );
+ map.put( "right", right.toMap() );
+ map.put( "operator", enumToMap( operator ) );
+ return map;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/operation/SQLInOperation.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/operation/SQLInOperation.java
index 7f2a2c234..306a5822f 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/operation/SQLInOperation.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/operation/SQLInOperation.java
@@ -15,12 +15,16 @@
package ortus.boxlang.compiler.ast.sql.select.expression.operation;
import java.util.List;
+import java.util.Map;
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
+import ortus.boxlang.compiler.ast.sql.select.SQLTable;
import ortus.boxlang.compiler.ast.sql.select.expression.SQLExpression;
import ortus.boxlang.compiler.ast.visitor.ReplacingBoxVisitor;
import ortus.boxlang.compiler.ast.visitor.VoidBoxVisitor;
+import ortus.boxlang.runtime.types.Query;
+import ortus.boxlang.runtime.types.exceptions.BoxRuntimeException;
/**
* Abstract Node class representing SQL IN operation
@@ -39,7 +43,7 @@ public class SQLInOperation extends SQLExpression {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLInOperation( boolean not, SQLExpression expression, List values, Position position, String sourceText ) {
+ public SQLInOperation( boolean not, SQLExpression expression, List values, Position position, String sourceText ) {
super( position, sourceText );
setExpression( expression );
setValues( values );
@@ -99,6 +103,13 @@ public boolean isBoolean() {
return true;
}
+ /**
+ * Evaluate the expression
+ */
+ public Object evaluate( Map tableLookup, int i ) {
+ throw new BoxRuntimeException( "not implemented" );
+ }
+
@Override
public void accept( VoidBoxVisitor v ) {
// TODO Auto-generated method stub
@@ -111,4 +122,14 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ map.put( "not", not );
+ map.put( "expression", expression.toMap() );
+ map.put( "values", values.stream().map( SQLExpression::toMap ).toList() );
+ return map;
+ }
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/operation/SQLUnaryOperation.java b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/operation/SQLUnaryOperation.java
index 2b4a1c48d..ddf94d696 100644
--- a/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/operation/SQLUnaryOperation.java
+++ b/src/main/java/ortus/boxlang/compiler/ast/sql/select/expression/operation/SQLUnaryOperation.java
@@ -14,13 +14,18 @@
*/
package ortus.boxlang.compiler.ast.sql.select.expression.operation;
+import java.util.Map;
import java.util.Set;
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.ast.Position;
+import ortus.boxlang.compiler.ast.sql.select.SQLTable;
import ortus.boxlang.compiler.ast.sql.select.expression.SQLExpression;
import ortus.boxlang.compiler.ast.visitor.ReplacingBoxVisitor;
import ortus.boxlang.compiler.ast.visitor.VoidBoxVisitor;
+import ortus.boxlang.runtime.types.Query;
+import ortus.boxlang.runtime.types.QueryColumnType;
+import ortus.boxlang.runtime.types.exceptions.BoxRuntimeException;
/**
* Abstract Node class representing SQL unary operation
@@ -40,7 +45,7 @@ public class SQLUnaryOperation extends SQLExpression {
* @param position position of the statement in the source code
* @param sourceText source code of the statement
*/
- protected SQLUnaryOperation( SQLExpression expression, SQLUnaryOperator operator, Position position, String sourceText ) {
+ public SQLUnaryOperation( SQLExpression expression, SQLUnaryOperator operator, Position position, String sourceText ) {
super( position, sourceText );
setExpression( expression );
setOperator( operator );
@@ -83,6 +88,27 @@ public boolean isBoolean() {
return booleanOperators.contains( operator );
}
+ /**
+ * What type does this expression evaluate to
+ */
+ public QueryColumnType getType( Map tableLookup ) {
+ // If this is a boolean operation, then we're a bit
+ if ( isBoolean() ) {
+ return QueryColumnType.BIT;
+ }
+ if ( operator == SQLUnaryOperator.PLUS || operator == SQLUnaryOperator.MINUS ) {
+ return QueryColumnType.DOUBLE;
+ }
+ return QueryColumnType.OBJECT;
+ }
+
+ /**
+ * Evaluate the expression
+ */
+ public Object evaluate( Map tableLookup, int i ) {
+ throw new BoxRuntimeException( "not implemented" );
+ }
+
@Override
public void accept( VoidBoxVisitor v ) {
// TODO Auto-generated method stub
@@ -95,4 +121,13 @@ public BoxNode accept( ReplacingBoxVisitor v ) {
throw new UnsupportedOperationException( "Unimplemented method 'accept'" );
}
+ @Override
+ public Map toMap() {
+ Map map = super.toMap();
+
+ map.put( "expression", expression.toMap() );
+ map.put( "operator", enumToMap( operator ) );
+ return map;
+ }
+
}
diff --git a/src/main/java/ortus/boxlang/compiler/parser/AbstractParser.java b/src/main/java/ortus/boxlang/compiler/parser/AbstractParser.java
index 14a5d3198..49350f679 100644
--- a/src/main/java/ortus/boxlang/compiler/parser/AbstractParser.java
+++ b/src/main/java/ortus/boxlang/compiler/parser/AbstractParser.java
@@ -39,6 +39,7 @@
import ortus.boxlang.compiler.ast.Position;
import ortus.boxlang.compiler.ast.Source;
import ortus.boxlang.compiler.ast.comment.BoxComment;
+import ortus.boxlang.runtime.types.exceptions.BoxIOException;
/**
* Parser abstract class
@@ -91,8 +92,12 @@ public AbstractParser( int startLine, int startColumn ) {
*
* @throws IOException
*/
- protected BOMInputStream getInputStream( File file ) throws IOException {
- return BOMInputStream.builder().setFile( file ).setByteOrderMarks( ByteOrderMark.UTF_8 ).setInclude( false ).get();
+ protected BOMInputStream getInputStream( File file ) {
+ try {
+ return BOMInputStream.builder().setFile( file ).setByteOrderMarks( ByteOrderMark.UTF_8 ).setInclude( false ).get();
+ } catch ( IOException e ) {
+ throw new BoxIOException( e );
+ }
}
/**
diff --git a/src/main/java/ortus/boxlang/compiler/parser/SQLParser.java b/src/main/java/ortus/boxlang/compiler/parser/SQLParser.java
index 9fb4d6c86..62aadb961 100644
--- a/src/main/java/ortus/boxlang/compiler/parser/SQLParser.java
+++ b/src/main/java/ortus/boxlang/compiler/parser/SQLParser.java
@@ -37,6 +37,7 @@
import ortus.boxlang.compiler.toolchain.SQLVisitor;
import ortus.boxlang.parser.antlr.SQLGrammar;
import ortus.boxlang.parser.antlr.SQLLexer;
+import ortus.boxlang.runtime.types.exceptions.BoxIOException;
/**
* Parser for QoQ scripts
@@ -63,11 +64,11 @@ public SQLParser( int startLine, int startColumn ) {
*
* @return a ParsingResult containing the AST with a BoxScript as root and the list of errors (if any)
*
- * @throws IOException if the input stream is in error
+ * @ if the input stream is in error
*
* @see ParsingResult
*/
- public ParsingResult parse( File file, boolean isScript ) throws IOException {
+ public ParsingResult parse( File file, boolean isScript ) {
this.file = file;
setSource( new SourceFile( file ) );
BOMInputStream inputStream = getInputStream( file );
@@ -84,16 +85,16 @@ public ParsingResult parse( File file, boolean isScript ) throws IOException {
*
* @return a ParsingResult containing the AST with a BoxScript as root and the list of errors (if any)
*
- * @throws IOException if the input stream is in error
+ * @ if the input stream is in error
*
* @see BoxScript
* @see ParsingResult
*/
- public ParsingResult parse( String code, boolean isScript ) throws IOException {
+ public ParsingResult parse( String code, boolean isScript ) {
return parse( code, false, isScript );
}
- public ParsingResult parse( String code ) throws IOException {
+ public ParsingResult parse( String code ) {
return parse( code, false, true );
}
@@ -104,13 +105,13 @@ public ParsingResult parse( String code ) throws IOException {
*
* @return a ParsingResult containing the AST with a BoxScript as root and the list of errors (if any)
*
- * @throws IOException if the input stream is in error
+ * @ if the input stream is in error
*
* @see BoxScript
* @see ParsingResult
*/
@Override
- public ParsingResult parse( String code, boolean classOrInterface, boolean isScript ) throws IOException {
+ public ParsingResult parse( String code, boolean classOrInterface, boolean isScript ) {
this.sourceCode = code;
setSource( new SourceCode( code ) );
InputStream inputStream = IOUtils.toInputStream( code, StandardCharsets.UTF_8 );
@@ -126,13 +127,18 @@ public ParsingResult parse( String code, boolean classOrInterface, boolean isScr
*
* @return the ANTLR ParserRule representing the parse tree of the code
*
- * @throws IOException io error
+ * @ io error
*/
@Override
- protected BoxNode parserFirstStage( InputStream stream, boolean classOrInterface, boolean isScript ) throws IOException {
+ protected BoxNode parserFirstStage( InputStream stream, boolean classOrInterface, boolean isScript ) {
- SQLLexerCustom lexer = new SQLLexerCustom( CharStreams.fromStream( stream, StandardCharsets.UTF_8 ), errorListener, this );
- SQLGrammar parser = new SQLGrammar( new CommonTokenStream( lexer ) );
+ SQLLexerCustom lexer;
+ try {
+ lexer = new SQLLexerCustom( CharStreams.fromStream( stream, StandardCharsets.UTF_8 ), errorListener, this );
+ } catch ( IOException e ) {
+ throw new BoxIOException( e );
+ }
+ SQLGrammar parser = new SQLGrammar( new CommonTokenStream( lexer ) );
// DEBUG: Will print a trace of all parser rules visited:
// boxParser.setTrace( true );
@@ -205,7 +211,7 @@ private void validateParse( SQLLexerCustom lexer ) {
}
}
- private void extractComments( SQLLexerCustom lexer ) throws IOException {
+ private void extractComments( SQLLexerCustom lexer ) {
lexer.reset();
Token token = lexer.nextToken();
while ( token.getType() != Token.EOF ) {
diff --git a/src/main/java/ortus/boxlang/compiler/toolchain/SQLVisitor.java b/src/main/java/ortus/boxlang/compiler/toolchain/SQLVisitor.java
index cd4ef6993..0f9c60c41 100644
--- a/src/main/java/ortus/boxlang/compiler/toolchain/SQLVisitor.java
+++ b/src/main/java/ortus/boxlang/compiler/toolchain/SQLVisitor.java
@@ -2,13 +2,35 @@
import java.util.List;
+import org.antlr.v4.runtime.tree.TerminalNode;
+
import ortus.boxlang.compiler.ast.BoxNode;
+import ortus.boxlang.compiler.ast.sql.select.SQLJoin;
+import ortus.boxlang.compiler.ast.sql.select.SQLResultColumn;
+import ortus.boxlang.compiler.ast.sql.select.SQLSelect;
+import ortus.boxlang.compiler.ast.sql.select.SQLSelectStatement;
+import ortus.boxlang.compiler.ast.sql.select.SQLTable;
+import ortus.boxlang.compiler.ast.sql.select.expression.SQLColumn;
+import ortus.boxlang.compiler.ast.sql.select.expression.SQLExpression;
+import ortus.boxlang.compiler.ast.sql.select.expression.SQLOrderBy;
+import ortus.boxlang.compiler.ast.sql.select.expression.SQLStarExpression;
+import ortus.boxlang.compiler.ast.sql.select.expression.literal.SQLBooleanLiteral;
+import ortus.boxlang.compiler.ast.sql.select.expression.literal.SQLNullLiteral;
+import ortus.boxlang.compiler.ast.sql.select.expression.literal.SQLNumberLiteral;
+import ortus.boxlang.compiler.ast.sql.select.expression.literal.SQLStringLiteral;
import ortus.boxlang.compiler.parser.SQLParser;
+import ortus.boxlang.parser.antlr.SQLGrammar.ExprContext;
+import ortus.boxlang.parser.antlr.SQLGrammar.Literal_valueContext;
+import ortus.boxlang.parser.antlr.SQLGrammar.Ordering_termContext;
import ortus.boxlang.parser.antlr.SQLGrammar.ParseContext;
+import ortus.boxlang.parser.antlr.SQLGrammar.Result_columnContext;
+import ortus.boxlang.parser.antlr.SQLGrammar.Select_coreContext;
import ortus.boxlang.parser.antlr.SQLGrammar.Select_stmtContext;
import ortus.boxlang.parser.antlr.SQLGrammar.Sql_stmtContext;
import ortus.boxlang.parser.antlr.SQLGrammar.Sql_stmt_listContext;
+import ortus.boxlang.parser.antlr.SQLGrammar.TableContext;
import ortus.boxlang.parser.antlr.SQLGrammarBaseVisitor;
+import ortus.boxlang.runtime.scopes.Key;
/**
* This class is responsible for creating the SQL AST from the ANTLR generated parse tree.
@@ -82,8 +104,271 @@ public BoxNode visitSql_stmt_list( Sql_stmt_listContext ctx ) {
*/
@Override
public BoxNode visitSelect_stmt( Select_stmtContext ctx ) {
- var pos = tools.getPosition( ctx );
+ var pos = tools.getPosition( ctx );
+ var src = tools.getSourceText( ctx );
+
+ SQLSelect select = null;
+ List unions = null;
+ List orderBys = null;
+ SQLNumberLiteral limit = null;
+
+ select = ( SQLSelect ) visit( ctx.select_core() );
+ final SQLSelect finalSelect = select;
+
+ if ( ctx.order_by_stmt() != null ) {
+ orderBys = ctx.order_by_stmt().ordering_term().stream().map( term -> visitOrdering_term( term, finalSelect.getTable(), finalSelect.getJoins() ) )
+ .toList();
+ }
+
+ // Limit after the order by, applies to all unions
+ if ( ctx.limit_stmt() != null ) {
+ limit = NUMERIC_LITERAL( ctx.limit_stmt().NUMERIC_LITERAL() );
+ }
+
+ // TODO: handle unions
+
+ return new SQLSelectStatement( select, unions, orderBys, limit, pos, src );
+ }
+
+ /**
+ * Visit the class or interface context to generate the AST node for the
+ * top level node
+ *
+ * @param ctx the parse tree
+ *
+ * @return the AST node representing the class or interface
+ */
+ @Override
+ public SQLSelect visitSelect_core( Select_coreContext ctx ) {
+ var pos = tools.getPosition( ctx );
+ var src = tools.getSourceText( ctx );
+
+ boolean distinct = ctx.DISTINCT_() != null;
+ SQLNumberLiteral limit = null;
+ List resultColumns = null;
+ SQLTable table = null;
+ List joins = null;
+ SQLExpression where = null;
+ List groupBys = null;
+ SQLExpression having = null;
+
+ // limit before order by, can have one per unioned table
+ if ( ctx.limit_stmt() != null ) {
+ limit = NUMERIC_LITERAL( ctx.limit_stmt().NUMERIC_LITERAL() );
+ }
+ // each
+ if ( ctx.top() != null ) {
+ limit = NUMERIC_LITERAL( ctx.top().NUMERIC_LITERAL() );
+ }
+
+ if ( !ctx.table().isEmpty() ) {
+ var firstTable = ctx.table().get( 0 );
+ table = ( SQLTable ) visit( firstTable );
+ }
+
+ if ( ctx.whereExpr != null ) {
+ where = visitExpr( ctx.whereExpr, table, joins );
+ }
+
+ // TODO: group by
+
+ // TODO: having
+ // TODO: handle additional tables as joins
+
+ // TODO: handle joins
+
+ // Do this after all joins above so we know the tables available to us
+ final SQLTable finalTable = table;
+ final List finalJoins = joins;
+ resultColumns = ctx.result_column().stream().map( col -> visitResult_column( col, finalTable, finalJoins ) ).toList();
+
+ var result = new SQLSelect( distinct, resultColumns, table, joins, where, groupBys, having, limit, pos, src );
+ var cols = result.getDescendantsOfType( SQLColumn.class, c -> c.getTable() == null );
+ if ( cols.size() > 0 ) {
+ if ( joins != null && !joins.isEmpty() ) {
+ tools.reportError( "Column reference must have table prefix to disambiguate.", pos );
+ } else {
+ if ( table == null ) {
+ tools.reportError( "This QoQ has column references, but there is no table!", pos );
+ } else {
+ cols.forEach( c -> c.setTable( finalTable ) );
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Visit the class or interface context to generate the AST node for the
+ * top level node
+ *
+ * @param ctx the parse tree
+ *
+ * @return the AST node representing the class or interface
+ */
+ @Override
+ public SQLTable visitTable( TableContext ctx ) {
+ var pos = tools.getPosition( ctx );
+ var src = tools.getSourceText( ctx );
+ String schema = null;
+ String name = ctx.table_name().getText();
+ String alias = null;
+
+ if ( ctx.schema_name() != null ) {
+ schema = ctx.schema_name().getText();
+ }
+
+ if ( ctx.table_alias() != null ) {
+ alias = ctx.table_alias().getText();
+ }
+
+ return new SQLTable( schema, name, alias, pos, src );
+ }
+
+ /**
+ * Visit the class or interface context to generate the AST node for the
+ * top level node
+ *
+ * @param ctx the parse tree
+ *
+ * @return the AST node representing the class or interface
+ */
+ public SQLResultColumn visitResult_column( Result_columnContext ctx, SQLTable table, List joins ) {
+ var pos = tools.getPosition( ctx );
+ var src = tools.getSourceText( ctx );
+ String alias = null;
+ SQLExpression expression;
+
+ if ( ctx.column_alias() != null ) {
+ alias = ctx.column_alias().getText();
+ }
+
+ if ( ctx.STAR() != null ) {
+ SQLTable tableRef = null;
+ // if we have tableName.* or tAlias.* then we need to find the table reference
+ if ( ctx.table_name() != null ) {
+ String tableName = ctx.table_name().getText();
+ tableRef = findTableRef( table, joins, tableName );
+ // If we didn't find the table reference then error
+ if ( tableRef == null ) {
+ tools.reportError( "Table reference not found for " + src, pos );
+ }
+ }
+ expression = new SQLStarExpression( tableRef, pos, src );
+ } else {
+ expression = visitExpr( ctx.expr(), table, joins );
+ }
+
+ return new SQLResultColumn( expression, alias, 0, pos, src );
+ }
+
+ /**
+ * Visit the class or interface context to generate the AST node for the
+ * top level node
+ *
+ * @param ctx the parse tree
+ *
+ * @return the AST node representing the class or interface
+ */
+ public SQLOrderBy visitOrdering_term( Ordering_termContext ctx, SQLTable table, List joins ) {
+ var pos = tools.getPosition( ctx );
+ var src = tools.getSourceText( ctx );
+ boolean ascending = true;
+
+ if ( ctx.asc_desc() != null ) {
+ ascending = ctx.asc_desc().DESC_() != null;
+ }
+
+ return new SQLOrderBy( visitExpr( ctx.expr(), table, joins ), ascending, pos, src );
+ }
+
+ /**
+ * Visit the class or interface context to generate the AST node for the
+ * top level node
+ *
+ * @param ctx the parse tree
+ *
+ * @return the AST node representing the class or interface
+ */
+ public SQLExpression visitExpr( ExprContext ctx, SQLTable table, List joins ) {
+ var pos = tools.getPosition( ctx );
+ var src = tools.getSourceText( ctx );
+
+ if ( ctx.column_name() != null ) {
+ SQLTable tableRef = null;
+ // if we have tableName.* or tAlias.* then we need to find the table reference
+ if ( ctx.table_name() != null ) {
+ String tableName = ctx.table_name().getText();
+ tableRef = findTableRef( table, joins, tableName );
+ // If we didn't find the table reference then error
+ if ( tableRef == null ) {
+ tools.reportError( "Table reference not found for " + src, pos );
+ }
+ }
+ return new SQLColumn( tableRef, ctx.column_name().getText(), pos, src );
+ } else if ( ctx.literal_value() != null ) {
+ return ( SQLExpression ) visit( ctx.literal_value() );
+ } else {
+ throw new UnsupportedOperationException( "Unimplemented expression: " + src );
+ }
+ }
+
+ /**
+ * Visit the class or interface context to generate the AST node for the
+ * top level node
+ *
+ * @param ctx the parse tree
+ *
+ * @return the AST node representing the class or interface
+ */
+ @Override
+ public SQLExpression visitLiteral_value( Literal_valueContext ctx ) {
+ var pos = tools.getPosition( ctx );
+ var src = tools.getSourceText( ctx );
+
+ if ( ctx.NULL_() != null ) {
+ return new SQLNullLiteral( pos, src );
+ } else if ( ctx.NUMERIC_LITERAL() != null ) {
+ return NUMERIC_LITERAL( ctx.NUMERIC_LITERAL() );
+ } else if ( ctx.TRUE_() != null ) {
+ return new SQLBooleanLiteral( true, pos, src );
+ } else if ( ctx.FALSE_() != null ) {
+ return new SQLBooleanLiteral( false, pos, src );
+ } else if ( ctx.STRING_LITERAL() != null ) {
+ return new SQLStringLiteral( ctx.STRING_LITERAL().getText(), pos, src );
+ } else {
+ throw new UnsupportedOperationException( "Unimplemented literal expression: " + src );
+ }
+ }
+
+ /**
+ * Visit the class or interface context to generate the AST node for the
+ * top level node
+ *
+ * @param ctx the parse tree
+ *
+ * @return the AST node representing the class or interface
+ */
+ public SQLNumberLiteral NUMERIC_LITERAL( TerminalNode ctx ) {
+ var pos = tools.getPosition( ctx );
+ var src = ctx.getText();
+
+ // TODO: handle different types (int, long, double, bigdecimal)
+ return new SQLNumberLiteral( Double.parseDouble( src ), pos, src );
+ }
+
+ private SQLTable findTableRef( SQLTable table, List joins, String tableName ) {
+ Key tableNameKey = Key.of( tableName );
+ if ( table.isCalled( tableNameKey ) ) {
+ return table;
+ } else if ( joins != null ) {
+ for ( SQLJoin join : joins ) {
+ if ( join.getTable().isCalled( tableNameKey ) ) {
+ return join.getTable();
+ }
+ }
+ }
return null;
}
diff --git a/src/main/java/ortus/boxlang/runtime/bifs/global/jdbc/QueryExecute.java b/src/main/java/ortus/boxlang/runtime/bifs/global/jdbc/QueryExecute.java
index 2bd9be6f5..fb2644e09 100644
--- a/src/main/java/ortus/boxlang/runtime/bifs/global/jdbc/QueryExecute.java
+++ b/src/main/java/ortus/boxlang/runtime/bifs/global/jdbc/QueryExecute.java
@@ -14,6 +14,7 @@
*/
package ortus.boxlang.runtime.bifs.global.jdbc;
+import java.sql.Connection;
import java.util.Set;
import ortus.boxlang.runtime.bifs.BIF;
@@ -21,12 +22,11 @@
import ortus.boxlang.runtime.context.IBoxContext;
import ortus.boxlang.runtime.context.IJDBCCapableContext;
import ortus.boxlang.runtime.dynamic.ExpressionInterpreter;
-import ortus.boxlang.runtime.dynamic.casters.CastAttempt;
-import ortus.boxlang.runtime.dynamic.casters.StructCaster;
import ortus.boxlang.runtime.jdbc.ConnectionManager;
import ortus.boxlang.runtime.jdbc.ExecutedQuery;
import ortus.boxlang.runtime.jdbc.PendingQuery;
import ortus.boxlang.runtime.jdbc.QueryOptions;
+import ortus.boxlang.runtime.jdbc.qoq.QoQConnection;
import ortus.boxlang.runtime.scopes.ArgumentsScope;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.types.Argument;
@@ -57,21 +57,34 @@ public QueryExecute() {
* @param arguments Argument scope for the BIF.
*
* @argument.sql The SQL to execute
- *
+ *
* @argument.params An array of binding parameters or a struct of named binding parameters
*
* @argument.options A struct of query options
*
*/
public Object _invoke( IBoxContext context, ArgumentsScope arguments ) {
- IJDBCCapableContext jdbcContext = context.getParentOfType( IJDBCCapableContext.class );
- ConnectionManager connectionManager = jdbcContext.getConnectionManager();
- CastAttempt optionsAsStruct = StructCaster.attempt( arguments.get( Key.options ) );
- QueryOptions options = new QueryOptions( optionsAsStruct.getOrDefault( new Struct() ) );
- String sql = arguments.getAsString( Key.sql );
- Object bindings = arguments.get( Key.params );
- PendingQuery pendingQuery = new PendingQuery( sql, bindings, options );
- ExecutedQuery executedQuery = pendingQuery.execute( connectionManager );
+ IStruct optionsAsStruct = arguments.getAsStruct( Key.options );
+ if ( optionsAsStruct == null ) {
+ optionsAsStruct = new Struct();
+ }
+ String sql = arguments.getAsString( Key.sql );
+ Object bindings = arguments.get( Key.params );
+
+ QueryOptions options = new QueryOptions( optionsAsStruct );
+ PendingQuery pendingQuery = new PendingQuery( sql, bindings, options );
+
+ ExecutedQuery executedQuery;
+ // QoQ uses a special QoQ connection
+ if ( options.isQoQ() ) {
+ Connection connection = new QoQConnection( context );
+ executedQuery = pendingQuery.execute( connection );
+ } else {
+ // whereas normal queries use the JDBC connection manager
+ IJDBCCapableContext jdbcContext = context.getParentOfType( IJDBCCapableContext.class );
+ ConnectionManager connectionManager = jdbcContext.getConnectionManager();
+ executedQuery = pendingQuery.execute( connectionManager );
+ }
if ( options.wantsResultStruct() ) {
assert options.resultVariableName != null;
diff --git a/src/main/java/ortus/boxlang/runtime/components/jdbc/Query.java b/src/main/java/ortus/boxlang/runtime/components/jdbc/Query.java
index 3dd8cefd1..7a8c12afc 100644
--- a/src/main/java/ortus/boxlang/runtime/components/jdbc/Query.java
+++ b/src/main/java/ortus/boxlang/runtime/components/jdbc/Query.java
@@ -17,6 +17,7 @@
*/
package ortus.boxlang.runtime.components.jdbc;
+import java.sql.Connection;
import java.util.Set;
import ortus.boxlang.runtime.components.Attribute;
@@ -30,6 +31,7 @@
import ortus.boxlang.runtime.jdbc.ExecutedQuery;
import ortus.boxlang.runtime.jdbc.PendingQuery;
import ortus.boxlang.runtime.jdbc.QueryOptions;
+import ortus.boxlang.runtime.jdbc.qoq.QoQConnection;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.types.Array;
import ortus.boxlang.runtime.types.IStruct;
@@ -70,7 +72,7 @@ public Query() {
Validator.NOT_IMPLEMENTED
) ),
new Attribute( Key.dbtype, "string", Set.of(
- Validator.NOT_IMPLEMENTED
+ Validator.NON_EMPTY, Validator.valueOneOf( "query", "hql" )
) ),
new Attribute( Key.username, "string", Set.of(
Validator.NOT_IMPLEMENTED
@@ -102,9 +104,7 @@ public Query() {
}
public BodyResult _invoke( IBoxContext context, IStruct attributes, ComponentBody body, IStruct executionState ) {
- IJDBCCapableContext jdbcContext = context.getParentOfType( IJDBCCapableContext.class );
- ConnectionManager connectionManager = jdbcContext.getConnectionManager();
- QueryOptions options = new QueryOptions( attributes );
+ QueryOptions options = new QueryOptions( attributes );
executionState.put( Key.queryParams, new Array() );
@@ -129,7 +129,18 @@ public BodyResult _invoke( IBoxContext context, IStruct attributes, ComponentBod
String sql = buffer.toString();
Array bindings = executionState.getAsArray( Key.queryParams );
PendingQuery pendingQuery = new PendingQuery( sql, bindings, options );
- ExecutedQuery executedQuery = pendingQuery.execute( connectionManager );
+
+ ExecutedQuery executedQuery;
+ // QoQ uses a special QoQ connection
+ if ( options.isQoQ() ) {
+ Connection connection = new QoQConnection( context );
+ executedQuery = pendingQuery.execute( connection );
+ } else {
+ // whereas normal queries use the JDBC connection manager
+ IJDBCCapableContext jdbcContext = context.getParentOfType( IJDBCCapableContext.class );
+ ConnectionManager connectionManager = jdbcContext.getConnectionManager();
+ executedQuery = pendingQuery.execute( connectionManager );
+ }
if ( options.wantsResultStruct() ) {
assert options.resultVariableName != null;
diff --git a/src/main/java/ortus/boxlang/runtime/jdbc/ExecutedQuery.java b/src/main/java/ortus/boxlang/runtime/jdbc/ExecutedQuery.java
index 081726d1a..5048d9d6d 100644
--- a/src/main/java/ortus/boxlang/runtime/jdbc/ExecutedQuery.java
+++ b/src/main/java/ortus/boxlang/runtime/jdbc/ExecutedQuery.java
@@ -32,6 +32,7 @@
import ortus.boxlang.runtime.BoxRuntime;
import ortus.boxlang.runtime.events.BoxEvent;
+import ortus.boxlang.runtime.jdbc.qoq.QoQStatement;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.services.InterceptorService;
import ortus.boxlang.runtime.types.Array;
@@ -93,10 +94,14 @@ public static ExecutedQuery fromPendingQuery( @Nonnull PendingQuery pendingQuery
Object generatedKey = null;
Query results = null;
- try ( ResultSet rs = statement.getResultSet() ) {
- results = Query.fromResultSet( rs );
- } catch ( SQLException e ) {
- throw new DatabaseException( e.getMessage(), e );
+ if ( statement instanceof QoQStatement qs ) {
+ results = qs.getQueryResult();
+ } else {
+ try ( ResultSet rs = statement.getResultSet() ) {
+ results = Query.fromResultSet( rs );
+ } catch ( SQLException e ) {
+ throw new DatabaseException( e.getMessage(), e );
+ }
}
// Capture generated keys, if any.
diff --git a/src/main/java/ortus/boxlang/runtime/jdbc/PendingQuery.java b/src/main/java/ortus/boxlang/runtime/jdbc/PendingQuery.java
index c2f787148..ccbacb5b8 100644
--- a/src/main/java/ortus/boxlang/runtime/jdbc/PendingQuery.java
+++ b/src/main/java/ortus/boxlang/runtime/jdbc/PendingQuery.java
@@ -474,7 +474,6 @@ private void applyStatementOptions( Statement statement ) throws SQLException {
/**
* TODO: Implement the following options:
* ormoptions
- * dbtype : query of queries (In progress)
* username and password : To evaluate later due to security concerns of overriding datasources, not going to implement unless requested
* clientInfo : Part of the connection: get/setClientInfo()
*/
diff --git a/src/main/java/ortus/boxlang/runtime/jdbc/QueryOptions.java b/src/main/java/ortus/boxlang/runtime/jdbc/QueryOptions.java
index eace219fc..a93c24deb 100644
--- a/src/main/java/ortus/boxlang/runtime/jdbc/QueryOptions.java
+++ b/src/main/java/ortus/boxlang/runtime/jdbc/QueryOptions.java
@@ -43,6 +43,7 @@
*