Skip to content

Commit

Permalink
Merge pull request #142 from ortus-boxlang/development
Browse files Browse the repository at this point in the history
version bump
  • Loading branch information
lmajano authored Dec 2, 2024
2 parents 1d5a178 + 420b1d4 commit 74981a8
Show file tree
Hide file tree
Showing 38 changed files with 1,845 additions and 450 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ dependencies {

// Implementation Dependencies
// https://mvnrepository.com/artifact/commons-io/commons-io
implementation "commons-io:commons-io:2.17.0"
implementation "commons-io:commons-io:2.18.0"
// https://mvnrepository.com/artifact/com.github.javaparser/javaparser-symbol-solver-core
implementation 'com.github.javaparser:javaparser-symbol-solver-core:3.26.2'
// https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
Expand Down
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#Fri Nov 15 22:11:50 UTC 2024
#Sat Nov 23 12:24:04 UTC 2024
antlrVersion=4.13.1
jdkVersion=21
version=1.0.0-beta23
version=1.0.0-beta24
2 changes: 2 additions & 0 deletions src/main/antlr/BoxTemplateLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,8 @@ mode POSSIBLE_COMPONENT;
PREFIX: 'bx:' -> pushMode(COMPONENT_NAME_MODE);
SLASH_PREFIX: '/bx:' -> pushMode(END_COMPONENT);
COMPONENT_OPEN2: '<' -> type(COMPONENT_OPEN);
ICHAR7:
'#' {_modeStack.contains(OUTPUT_MODE)}? -> type(ICHAR), popMode, pushMode(EXPRESSION_MODE_STRING
);
Expand Down
33 changes: 28 additions & 5 deletions src/main/antlr/CFLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ options {
private int parenCount = 0;
private int braceCount = 0;
private int bracketCount = 0;
private boolean isQuery = false;
private int countModes(int mode) {
int count = 0;
Expand Down Expand Up @@ -151,6 +152,12 @@ COMPONENT_CLOSE99:
popMode, popMode
;

// We have to capture this scenario and break it apart in our lexer super class into two tokens. If we don't capture this here, the >= rule below will match it and
// fail to end the component for us, causing an invalid parse
COMPONENT_CLOSE_EQUAL:
'>=' {isExpressionComplete() && _modeStack.contains(TEMPLATE_EXPRESSION_MODE_COMPONENT)}? -> popMode, popMode, popMode, popMode, popMode
;

// Comments can live inside script expressions, if we're inside a component/tag (CF/Lucee compat only)
COMMENT_START10:
'<!---' {_modeStack.contains(TEMPLATE_COMPONENT_MODE)}? -> pushMode(TEMPLATE_COMMENT_QUIET), channel(HIDDEN), type(COMMENT_START)
Expand Down Expand Up @@ -481,6 +488,10 @@ TEMPLATE_COMPONENT : 'component' -> pushMode( TEMPLATE_COMPONENT_MODE );
TEMPLATE_INTERFACE : 'interface' -> pushMode( TEMPLATE_COMPONENT_MODE );
TEMPLATE_FUNCTION : 'function' -> pushMode( TEMPLATE_COMPONENT_MODE );
TEMPLATE_ARGUMENT : 'argument' -> pushMode( TEMPLATE_COMPONENT_MODE );
// cfquery doesn't have a dedicated AST node, but we need to pretend we're in a cfoutput when we enter a cfquery.
TEMPLATE_QUERY:
'query' {isQuery=true;} -> type(COMPONENT_NAME), pushMode( TEMPLATE_COMPONENT_MODE )
;
// return may or may not have an expression, so eat any leading whitespace now so it doesn't give us an expression part that's just a space
TEMPLATE_RETURN:
Expand Down Expand Up @@ -534,6 +545,10 @@ COMMENT_START1:
'<!---' -> pushMode(TEMPLATE_COMMENT_QUIET), channel(HIDDEN), type(COMMENT_START)
;
COMPONENT_CLOSE4:
{isQuery}? '>' -> popMode, popMode, popMode, pushMode(TEMPLATE_OUTPUT_MODE), pushMode(DEFAULT_TEMPLATE_MODE), type(COMPONENT_CLOSE)
;
COMPONENT_CLOSE: '>' -> popMode, popMode, popMode;
COMPONENT_SLASH_CLOSE: '/>' -> popMode, popMode, popMode;
Expand Down Expand Up @@ -576,6 +591,9 @@ mode TEMPLATE_END_COMPONENT;
TEMPLATE_IF2 : 'if' -> type(TEMPLATE_IF);
TEMPLATE_COMPONENT2 : 'component' -> type(TEMPLATE_COMPONENT);
TEMPLATE_FUNCTION2 : 'function' -> type(TEMPLATE_FUNCTION);
// If we're ending a cfquery, we need to use the special exit below with the extra pop out of output mode
TEMPLATE_QUERY2: 'query' {isQuery=true;} -> type(COMPONENT_NAME);
// popping back to: POSSIBLE_COMPONENT -> DEFAULT_MODE -> OUTPUT_MODE -> COMPONENT -> POSSIBLE_COMPONENT -> DEFAULT_MODE
OUTPUT_END:
'output' COMPONENT_WHITESPACE_OUTPUT3* '>' -> popMode, popMode, popMode, popMode, popMode, popMode
Expand All @@ -598,8 +616,11 @@ TEMPLATE_DEFAULTCASE2 : 'defaultcase' -> type(TEMPLATE_DEFAULTCASE);
COMPONENT_WHITESPACE_OUTPUT3: [ \t\r\n] -> skip;
COMPONENT_NAME2 : COMPONENT_NameStartChar COMPONENT_NameChar* -> type(COMPONENT_NAME);
COMPONENT_CLOSE2 : '>' -> popMode, popMode, type(COMPONENT_CLOSE);
COMPONENT_NAME2: COMPONENT_NameStartChar COMPONENT_NameChar* -> type(COMPONENT_NAME);
// If we're coming out of a cfquery, then pop 2 extra times to get out of the output mode and additional default template mode
COMPONENT_CLOSE2: '>' {isQuery}? -> popMode, popMode, popMode, popMode, type(COMPONENT_CLOSE);
// all other ending tags
COMPONENT_CLOSE23: '>' -> popMode, popMode, type(COMPONENT_CLOSE);
// *********************************************************************************************************************
mode TEMPLATE_ATTVALUE;
Expand Down Expand Up @@ -672,11 +693,13 @@ DUMMY2: .;
// *********************************************************************************************************************
mode TEMPLATE_POSSIBLE_COMPONENT;

PREFIX : 'cf' -> pushMode(TEMPLATE_COMPONENT_NAME_MODE);
SLASH_PREFIX : '/cf' -> pushMode(TEMPLATE_END_COMPONENT);
PREFIX : 'cf' {isQuery=false;} -> pushMode(TEMPLATE_COMPONENT_NAME_MODE);
SLASH_PREFIX : '/cf' {isQuery=false;} -> pushMode(TEMPLATE_END_COMPONENT);

COMPONENT_OPEN2: '<' -> type(COMPONENT_OPEN);

TEMPLATE_ICHAR7:
'#' {_modeStack.contains(TEMPLATE_OUTPUT_MODE)}? -> type(ICHAR), popMode, pushMode( DEFAULT_SCRIPT_MODE )
'#' {_modeStack.contains(TEMPLATE_OUTPUT_MODE)}? -> type(ICHAR), popMode, pushMode(hashMode), pushMode( DEFAULT_SCRIPT_MODE )
;

TEMPLATE_ANY: . -> type(CONTENT_TEXT), popMode;
260 changes: 259 additions & 1 deletion src/main/java/ortus/boxlang/compiler/asmboxpiler/AsmTranspiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MultiANewArrayInsnNode;
import org.objectweb.asm.tree.TypeInsnNode;

import ortus.boxlang.compiler.asmboxpiler.transformer.ReturnValueContext;
Expand Down Expand Up @@ -161,6 +163,211 @@

public class AsmTranspiler extends Transpiler {

private static final int[] STACK_SIZE_DELTA = {
0, // nop = 0 (0x0)
1, // aconst_null = 1 (0x1)
1, // iconst_m1 = 2 (0x2)
1, // iconst_0 = 3 (0x3)
1, // iconst_1 = 4 (0x4)
1, // iconst_2 = 5 (0x5)
1, // iconst_3 = 6 (0x6)
1, // iconst_4 = 7 (0x7)
1, // iconst_5 = 8 (0x8)
2, // lconst_0 = 9 (0x9)
2, // lconst_1 = 10 (0xa)
1, // fconst_0 = 11 (0xb)
1, // fconst_1 = 12 (0xc)
1, // fconst_2 = 13 (0xd)
2, // dconst_0 = 14 (0xe)
2, // dconst_1 = 15 (0xf)
1, // bipush = 16 (0x10)
1, // sipush = 17 (0x11)
Integer.MIN_VALUE, // ldc = 18 (0x12)
Integer.MIN_VALUE, // ldc_w = 19 (0x13)
Integer.MIN_VALUE, // ldc2_w = 20 (0x14)
1, // iload = 21 (0x15)
2, // lload = 22 (0x16)
1, // fload = 23 (0x17)
2, // dload = 24 (0x18)
1, // aload = 25 (0x19)
1, // iload_0 = 26 (0x1a)
1, // iload_1 = 27 (0x1b)
1, // iload_2 = 28 (0x1c)
1, // iload_3 = 29 (0x1d)
2, // lload_0 = 30 (0x1e)
2, // lload_1 = 31 (0x1f)
2, // lload_2 = 32 (0x20)
2, // lload_3 = 33 (0x21)
1, // fload_0 = 34 (0x22)
1, // fload_1 = 35 (0x23)
1, // fload_2 = 36 (0x24)
1, // fload_3 = 37 (0x25)
2, // dload_0 = 38 (0x26)
2, // dload_1 = 39 (0x27)
2, // dload_2 = 40 (0x28)
2, // dload_3 = 41 (0x29)
1, // aload_0 = 42 (0x2a)
1, // aload_1 = 43 (0x2b)
1, // aload_2 = 44 (0x2c)
1, // aload_3 = 45 (0x2d)
-1, // iaload = 46 (0x2e)
0, // laload = 47 (0x2f)
-1, // faload = 48 (0x30)
0, // daload = 49 (0x31)
-1, // aaload = 50 (0x32)
-1, // baload = 51 (0x33)
-1, // caload = 52 (0x34)
-1, // saload = 53 (0x35)
-1, // istore = 54 (0x36)
-2, // lstore = 55 (0x37)
-1, // fstore = 56 (0x38)
-2, // dstore = 57 (0x39)
-1, // astore = 58 (0x3a)
-1, // istore_0 = 59 (0x3b)
-1, // istore_1 = 60 (0x3c)
-1, // istore_2 = 61 (0x3d)
-1, // istore_3 = 62 (0x3e)
-2, // lstore_0 = 63 (0x3f)
-2, // lstore_1 = 64 (0x40)
-2, // lstore_2 = 65 (0x41)
-2, // lstore_3 = 66 (0x42)
-1, // fstore_0 = 67 (0x43)
-1, // fstore_1 = 68 (0x44)
-1, // fstore_2 = 69 (0x45)
-1, // fstore_3 = 70 (0x46)
-2, // dstore_0 = 71 (0x47)
-2, // dstore_1 = 72 (0x48)
-2, // dstore_2 = 73 (0x49)
-2, // dstore_3 = 74 (0x4a)
-1, // astore_0 = 75 (0x4b)
-1, // astore_1 = 76 (0x4c)
-1, // astore_2 = 77 (0x4d)
-1, // astore_3 = 78 (0x4e)
-3, // iastore = 79 (0x4f)
-4, // lastore = 80 (0x50)
-3, // fastore = 81 (0x51)
-4, // dastore = 82 (0x52)
-3, // aastore = 83 (0x53)
-3, // bastore = 84 (0x54)
-3, // castore = 85 (0x55)
-3, // sastore = 86 (0x56)
-1, // pop = 87 (0x57)
-2, // pop2 = 88 (0x58)
1, // dup = 89 (0x59)
1, // dup_x1 = 90 (0x5a)
1, // dup_x2 = 91 (0x5b)
2, // dup2 = 92 (0x5c)
2, // dup2_x1 = 93 (0x5d)
2, // dup2_x2 = 94 (0x5e)
0, // swap = 95 (0x5f)
-1, // iadd = 96 (0x60)
-2, // ladd = 97 (0x61)
-1, // fadd = 98 (0x62)
-2, // dadd = 99 (0x63)
-1, // isub = 100 (0x64)
-2, // lsub = 101 (0x65)
-1, // fsub = 102 (0x66)
-2, // dsub = 103 (0x67)
-1, // imul = 104 (0x68)
-2, // lmul = 105 (0x69)
-1, // fmul = 106 (0x6a)
-2, // dmul = 107 (0x6b)
-1, // idiv = 108 (0x6c)
-2, // ldiv = 109 (0x6d)
-1, // fdiv = 110 (0x6e)
-2, // ddiv = 111 (0x6f)
-1, // irem = 112 (0x70)
-2, // lrem = 113 (0x71)
-1, // frem = 114 (0x72)
-2, // drem = 115 (0x73)
0, // ineg = 116 (0x74)
0, // lneg = 117 (0x75)
0, // fneg = 118 (0x76)
0, // dneg = 119 (0x77)
-1, // ishl = 120 (0x78)
-1, // lshl = 121 (0x79)
-1, // ishr = 122 (0x7a)
-1, // lshr = 123 (0x7b)
-1, // iushr = 124 (0x7c)
-1, // lushr = 125 (0x7d)
-1, // iand = 126 (0x7e)
-2, // land = 127 (0x7f)
-1, // ior = 128 (0x80)
-2, // lor = 129 (0x81)
-1, // ixor = 130 (0x82)
-2, // lxor = 131 (0x83)
0, // iinc = 132 (0x84)
1, // i2l = 133 (0x85)
0, // i2f = 134 (0x86)
1, // i2d = 135 (0x87)
-1, // l2i = 136 (0x88)
-1, // l2f = 137 (0x89)
0, // l2d = 138 (0x8a)
0, // f2i = 139 (0x8b)
1, // f2l = 140 (0x8c)
1, // f2d = 141 (0x8d)
-1, // d2i = 142 (0x8e)
0, // d2l = 143 (0x8f)
-1, // d2f = 144 (0x90)
0, // i2b = 145 (0x91)
0, // i2c = 146 (0x92)
0, // i2s = 147 (0x93)
-3, // lcmp = 148 (0x94)
-1, // fcmpl = 149 (0x95)
-1, // fcmpg = 150 (0x96)
-3, // dcmpl = 151 (0x97)
-3, // dcmpg = 152 (0x98)
-1, // ifeq = 153 (0x99)
-1, // ifne = 154 (0x9a)
-1, // iflt = 155 (0x9b)
-1, // ifge = 156 (0x9c)
-1, // ifgt = 157 (0x9d)
-1, // ifle = 158 (0x9e)
-2, // if_icmpeq = 159 (0x9f)
-2, // if_icmpne = 160 (0xa0)
-2, // if_icmplt = 161 (0xa1)
-2, // if_icmpge = 162 (0xa2)
-2, // if_icmpgt = 163 (0xa3)
-2, // if_icmple = 164 (0xa4)
-2, // if_acmpeq = 165 (0xa5)
-2, // if_acmpne = 166 (0xa6)
0, // goto = 167 (0xa7)
1, // jsr = 168 (0xa8)
0, // ret = 169 (0xa9)
-1, // tableswitch = 170 (0xaa)
-1, // lookupswitch = 171 (0xab)
-1, // ireturn = 172 (0xac)
-2, // lreturn = 173 (0xad)
-1, // freturn = 174 (0xae)
-2, // dreturn = 175 (0xaf)
-1, // areturn = 176 (0xb0)
0, // return = 177 (0xb1)
Integer.MIN_VALUE, // getstatic = 178 (0xb2)
Integer.MIN_VALUE, // putstatic = 179 (0xb3)
Integer.MIN_VALUE, // getfield = 180 (0xb4)
Integer.MIN_VALUE, // putfield = 181 (0xb5)
Integer.MIN_VALUE, // invokevirtual = 182 (0xb6)
Integer.MIN_VALUE, // invokespecial = 183 (0xb7)
Integer.MIN_VALUE, // invokestatic = 184 (0xb8)
Integer.MIN_VALUE, // invokeinterface = 185 (0xb9)
Integer.MIN_VALUE, // invokedynamic = 186 (0xba)
1, // new = 187 (0xbb)
0, // newarray = 188 (0xbc)
0, // anewarray = 189 (0xbd)
0, // arraylength = 190 (0xbe)
-1, // athrow = 191 (0xbf)
0, // checkcast = 192 (0xc0)
0, // instanceof = 193 (0xc1)
-1, // monitorenter = 194 (0xc2)
-1, // monitorexit = 195 (0xc3)
Integer.MIN_VALUE, // wide = 196 (0xc4)
Integer.MIN_VALUE, // multianewarray = 197 (0xc5)
-1, // ifnull = 198 (0xc6)
-1, // ifnonnull = 199 (0xc7)
Integer.MIN_VALUE, // goto_w = 200 (0xc8)
Integer.MIN_VALUE // jsr_w = 201 (0xc9)
};

private static HashMap<Class<?>, Transformer> registry = new HashMap<>();
private static final String EXTENDS_ANNOTATION_MARKER = "overrideJava";

Expand Down Expand Up @@ -362,7 +569,58 @@ public ClassNode transpile( BoxInterface boxClass ) throws BoxRuntimeException {
public List<AbstractInsnNode> transform( BoxNode node, TransformerContext context, ReturnValueContext returnValueContext ) {
Transformer transformer = registry.get( node.getClass() );
if ( transformer != null ) {
return transformer.transform( node, context, returnValueContext );
List<AbstractInsnNode> nodes = transformer.transform( node, context, returnValueContext );
if ( ASMBoxpiler.DEBUG ) {
int delta = 0;
for ( AbstractInsnNode value : nodes ) {
if ( value.getOpcode() == -1 ) {
continue;
} else if ( value instanceof FieldInsnNode fieldInsnNode ) {
Type type = Type.getType( fieldInsnNode.desc );
delta += switch ( fieldInsnNode.getOpcode() ) {
case Opcodes.GETSTATIC -> type.getSize();
case Opcodes.PUTSTATIC -> -type.getSize();
case Opcodes.GETFIELD -> type.getSize() - 1;
case Opcodes.PUTFIELD -> -type.getSize() - 1;
default -> throw new IllegalStateException();
};
} else if ( value instanceof MethodInsnNode methodInsnNode ) {
Type type = Type.getMethodType( methodInsnNode.desc );
for ( Type argument : type.getArgumentTypes() ) {
delta -= argument.getSize();
}
delta += type.getReturnType().getSize();
delta += switch ( methodInsnNode.getOpcode() ) {
case Opcodes.INVOKESTATIC -> 0;
case Opcodes.INVOKEVIRTUAL, Opcodes.INVOKEINTERFACE, Opcodes.INVOKESPECIAL -> -1;
default -> throw new IllegalStateException();
};
} else if ( value instanceof InvokeDynamicInsnNode invokeDynamicInsnNode ) {
Type type = Type.getMethodType( invokeDynamicInsnNode.desc );
for ( Type argument : type.getArgumentTypes() ) {
delta -= argument.getSize();
}
delta += type.getReturnType().getSize();
} else if ( value instanceof LdcInsnNode ldcInsnNode ) {
delta += ldcInsnNode.cst instanceof Double || ldcInsnNode.cst instanceof Long ? 2 : 1;
} else if ( value instanceof MultiANewArrayInsnNode multiANewArrayInsnNode ) {
delta -= multiANewArrayInsnNode.dims + 1;
} else {
if ( STACK_SIZE_DELTA[ value.getOpcode() ] == Integer.MIN_VALUE ) {
throw new IllegalStateException();
}
delta += STACK_SIZE_DELTA[ value.getOpcode() ];
}
}
int expectation = switch ( returnValueContext ) {
case EMPTY, EMPTY_UNLESS_JUMPING -> 0;
case VALUE, VALUE_OR_NULL -> 1;
};
if ( expectation != delta ) {
throw new IllegalStateException( node.getClass() + " with " + returnValueContext + " yielded a stack delta of " + delta );
}
}
return nodes;
}
throw new IllegalStateException( "unsupported: " + node.getClass().getSimpleName() + " : " + node.getSourceText() );
}
Expand Down
Loading

0 comments on commit 74981a8

Please sign in to comment.