Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/development' into development
Browse files Browse the repository at this point in the history
# Conflicts:
#	compiler/src/test/java/TestStatements.java
  • Loading branch information
mctaverna committed Sep 7, 2023
2 parents 5c7066f + f99191a commit 1d11910
Show file tree
Hide file tree
Showing 93 changed files with 1,002 additions and 736 deletions.
Original file line number Diff line number Diff line change
@@ -1,35 +1,40 @@
package ourtus.boxlang.transpiler.transformer.expression;

import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.expr.Expression;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.expr.Expression;

import ourtus.boxlang.ast.BoxNode;
import ourtus.boxlang.ast.expression.BoxMethodInvocation;
import ourtus.boxlang.transpiler.BoxLangTranspiler;
import ourtus.boxlang.transpiler.transformer.AbstractTransformer;
import ourtus.boxlang.transpiler.transformer.TransformerContext;

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class BoxMethodInvocationTransformer extends AbstractTransformer {

Logger logger = LoggerFactory.getLogger( BoxScopeTransformer.class );

@Override
public Node transform( BoxNode node, TransformerContext context ) throws IllegalStateException {
BoxMethodInvocation invocation = ( BoxMethodInvocation ) node;
String side = context == TransformerContext.NONE ? "" : "(" + context.toString() + ") ";

BoxMethodInvocation invocation = ( BoxMethodInvocation ) node;
String side = context == TransformerContext.NONE ? "" : "(" + context.toString() + ") ";

Expression expr = ( Expression ) BoxLangTranspiler.transform( invocation.getObj(), TransformerContext.RIGHT );
Expression expr = ( Expression ) BoxLangTranspiler.transform( invocation.getObj(),
TransformerContext.RIGHT );

String args = invocation.getArguments().stream().map( it -> BoxLangTranspiler.transform( it ).toString() )
.collect( Collectors.joining( ", " ) );
String args = invocation.getArguments().stream()
.map( it -> BoxLangTranspiler.transform( it ).toString() )
.collect( Collectors.joining( ", " ) );

Map<String, String> values = new HashMap<>();
Map<String, String> values = new HashMap<>();

String target = BoxBuiltinRegistry.getInstance().getRegistry().get( invocation.getName().getName() );
String target = BoxBuiltinRegistry.getInstance().getRegistry().get( invocation.getName().getName() );

values.put( "expr", expr.toString() );
values.put( "args", args );
Expand All @@ -41,16 +46,17 @@ public Node transform( BoxNode node, TransformerContext context ) throws Illegal
} else {
values.put( "method", invocation.getName().getName().toString() );
template = """
Referencer.getAndInvoke(
${expr},
Key.of( "${method}" ),
new Object[] { ${args} },
false
)
""";
Referencer.getAndInvoke(
context,
${expr},
Key.of( "${method}" ),
new Object[] { ${args} },
false
)
""";
}
Node javaExpr = parseExpression( template, values );
logger.info(side + node.getSourceText() + " -> " + javaExpr);
logger.info( side + node.getSourceText() + " -> " + javaExpr );
return javaExpr;
}
}
144 changes: 76 additions & 68 deletions compiler/src/test/java/TestStatements.java
Original file line number Diff line number Diff line change
@@ -1,106 +1,114 @@
import static org.junit.Assert.assertEquals;

import java.io.IOException;

import org.junit.Test;

import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.stmt.BlockStmt;
import org.junit.Test;

import ourtus.boxlang.parser.BoxFileType;
import ourtus.boxlang.parser.BoxLangParser;
import ourtus.boxlang.parser.ParsingResult;
import ourtus.boxlang.transpiler.BoxLangTranspiler;

import java.io.IOException;

import static org.junit.Assert.assertEquals;

public class TestStatements extends TestBase {

@Test
public void invokeMethod() throws IOException {
String expression = """
myObject.myMethod( obj1, "foo", 42 )
""";
String expression = """
myObject.myMethod( obj1, "foo", 42 )
""";

BoxLangParser parser = new BoxLangParser();
ParsingResult result = parser.parseStatement( expression );
Node javaAST = BoxLangTranspiler.transform( result.getRoot() );
BoxLangParser parser = new BoxLangParser();
ParsingResult result = parser.parseStatement( expression );
Node javaAST = BoxLangTranspiler.transform( result.getRoot() );

assertEqualsNoWhiteSpaces( """
Referencer.getAndInvoke(
myObject,
Key.of( "myMethod" ),
new Object[] { obj1, "foo", 42 },
false
);
""", javaAST.toString() );
} @Test
public void invokeMethodWithKnownScope() throws IOException {
String expression = """
variables.system.out.println(
"hello world"
)
""";

BoxLangParser parser = new BoxLangParser();
ParsingResult result = parser.parseStatement( expression );
Node javaAST = BoxLangTranspiler.transform( result.getRoot() );

assertEqualsNoWhiteSpaces( "Referencer.getAndInvoke(Referencer.get(variablesScope.get(Key.of(\"system\")).get(Key.of(\"out\")),false),Key.of(\"println\"),newObject[]{\"helloworld\"},false);", javaAST.toString() );
Referencer.getAndInvoke(
context,
myObject,
Key.of( "myMethod" ),
new Object[] { obj1, "foo", 42 },
false
);
""", javaAST.toString() );
}

@Test
public void invokeMethodWithKnownScope() throws IOException {
String expression = """
variables.system.out.println(
"hello world"
)
""";

BoxLangParser parser = new BoxLangParser();
ParsingResult result = parser.parseStatement( expression );
Node javaAST = BoxLangTranspiler.transform( result.getRoot() );

assertEqualsNoWhiteSpaces(
"Referencer.getAndInvoke(context,Referencer.get(variablesScope.get(Key.of(\"system\")).get(Key.of(\"out\")),false),Key.of(\"println\"),newObject[]{\"helloworld\"},false);",
javaAST.toString() );
}

@Test
public void assigment() throws IOException {
String expression = """
variables["system"] = "Hello"
""";
String expression = """
variables["system"] = "Hello"
""";

BoxLangParser parser = new BoxLangParser();
ParsingResult result = parser.parseStatement( expression );
BoxLangParser parser = new BoxLangParser();
ParsingResult result = parser.parseStatement( expression );

Node javaAST = BoxLangTranspiler.transform( result.getRoot() );
Node javaAST = BoxLangTranspiler.transform( result.getRoot() );

assertEquals( "variablesScope.put(Key.of(\"system\"), \"Hello\");", javaAST.toString() );

}

@Test
public void var() throws IOException {
String expression = """
var a = b = 1/0;
""";
String expression = """
var a = b = 1/0;
""";

BoxLangParser parser = new BoxLangParser();
ParsingResult result = parser.parseStatement( expression );

BlockStmt javaAST = (BlockStmt)BoxLangTranspiler.transform( result.getRoot() );
assertEquals( "context.getScopeNearby(Key.of(LocalScope.name)).put(Key.of(\"a\"), Divide.invoke(1, 0));", javaAST.getStatements().get(0).toString() );
assertEquals( "context.getScopeNearby(Key.of(LocalScope.name)).put(Key.of(\"b\"), Divide.invoke(1, 0));", javaAST.getStatements().get(1).toString() );
BoxLangParser parser = new BoxLangParser();
ParsingResult result = parser.parseStatement( expression );

BlockStmt javaAST = ( BlockStmt ) BoxLangTranspiler.transform( result.getRoot() );
assertEquals( "context.getScopeNearby(Key.of(LocalScope.name)).put(Key.of(\"a\"), Divide.invoke(1, 0));",
javaAST.getStatements().get( 0 ).toString() );
assertEquals( "context.getScopeNearby(Key.of(LocalScope.name)).put(Key.of(\"b\"), Divide.invoke(1, 0));",
javaAST.getStatements().get( 1 ).toString() );

}

@Test
public void ifElse() throws IOException {
String expression = """
var a = 1 + 2 * 3;
var b = "0";
if( variables.a == "0" && variables.b == "0" ) {
variables.a = a & "1";
} else if( !foo ) {
variables.a = a & "2";
}
""";

BoxLangParser parser = new BoxLangParser();
ParsingResult result = parser.parse( expression , BoxFileType.CF);

Node javaAST = new BoxLangTranspiler().transpile( result.getRoot() );

MethodDeclaration invokeMethod = javaAST.findCompilationUnit().orElseThrow()
.getClassByName("TestClass").orElseThrow()
.getMethodsByName("invoke").get(0);

System.out.println(invokeMethod.toString());
assertEquals("/**\n * Each template must implement the invoke() method which executes the template\n *\n * @param context The execution context requesting the execution\n */\npublic void invoke(IBoxContext context) throws Throwable {\n // Reference to the variables scope\n IScope variablesScope = context.getScopeNearby(Key.of(\"variables\"));\n ClassLocator JavaLoader = ClassLocator.getInstance();\n context.getScopeNearby(Key.of(LocalScope.name)).put(Key.of(\"a\"), 0);\n if (BooleanCaster.cast(EqualsEquals.invoke(variablesScope.get(Key.of(\"a\")), 0))) {\n variablesScope.put(Key.of(\"a\"), Plus.invoke(context.scopeFindNearby(Key.of(\"a\")), 1));\n } else {\n if (BooleanCaster.cast(Negate.invoke(foo))) {\n }\n }\n}", invokeMethod.toString() );

String expression = """
var a = "0";
if( variables.a == "0" ) {
variables.a = a & "1";
} else if( !foo ) {
variables.a = a & "2";
}
""";

BoxLangParser parser = new BoxLangParser();
ParsingResult result = parser.parse( expression, BoxFileType.CF );

Node javaAST = new BoxLangTranspiler().transpile( result.getRoot() );

MethodDeclaration invokeMethod = javaAST.findCompilationUnit().orElseThrow()
.getClassByName( "TestClass" ).orElseThrow()
.getMethodsByName( "invoke" ).get( 0 );

System.out.println( invokeMethod.toString() );
assertEquals(
"/**\n * Each template must implement the invoke() method which executes the template\n *\n * @param context The execution context requesting the execution\n */\npublic void invoke(IBoxContext context) throws Throwable {\n // Reference to the variables scope\n IScope variablesScope = context.getScopeNearby(Key.of(\"variables\"));\n ClassLocator JavaLoader = ClassLocator.getInstance();\n context.getScopeNearby(Key.of(LocalScope.name)).put(Key.of(\"a\"), 0);\n if (BooleanCaster.cast(EqualsEquals.invoke(variablesScope.get(Key.of(\"a\")), 0))) {\n variablesScope.put(Key.of(\"a\"), Plus.invoke(context.scopeFindNearby(Key.of(\"a\")), 1));\n } else {\n if (BooleanCaster.cast(Negate.invoke(foo))) {\n }\n }\n}",
invokeMethod.toString() );

}
}
2 changes: 1 addition & 1 deletion examples/cf_to_java/HelloWorld/HelloWorld.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public void invoke( ExecutionContext context ) throws Throwable {
if ( EqualsEquals.invoke( context, variablesScope.get( Key.of( "GREETING" ) ), "Hello" ) ) {

Referencer.getAndInvoke(

context,
// Object
Referencer.get( variablesScope.get( Key.of( "SYSTEM" ) ), Key.of( "OUT" ) ),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,10 @@

import java.util.Map;

import ortus.boxlang.runtime.context.IBoxContext.ScopeSearchResult;
import ortus.boxlang.runtime.dynamic.BaseTemplate;
import ortus.boxlang.runtime.scopes.*;
import ortus.boxlang.runtime.scopes.IScope;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.types.Function;
import ortus.boxlang.runtime.types.Struct;
import ortus.boxlang.runtime.types.UDF;
import ortus.boxlang.runtime.types.exceptions.KeyNotFoundException;
import ortus.boxlang.runtime.types.exceptions.ScopeNotFoundException;

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
package ortus.boxlang.runtime.context;

import java.util.Map;

import ortus.boxlang.runtime.scopes.ArgumentsScope;
import ortus.boxlang.runtime.scopes.IScope;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.scopes.LocalScope;
import ortus.boxlang.runtime.scopes.ScopeWrapper;
import ortus.boxlang.runtime.scopes.VariablesScope;
import ortus.boxlang.runtime.types.Struct;
import ortus.boxlang.runtime.types.exceptions.KeyNotFoundException;
import ortus.boxlang.runtime.types.exceptions.ScopeNotFoundException;
Expand Down Expand Up @@ -53,14 +49,27 @@ public ScopeSearchResult scopeFindNearby( Key key, IScope defaultScope ) {
return new ScopeSearchResult( argumentsScope, Struct.unWrapNull( result ) );
}

return scopeFind( key, defaultScope );
if ( parent != null ) {
// A UDF is "transparent" and can see everything in the parent scope as a "local" observer
return parent.scopeFindNearby( key, defaultScope );
}

// Default scope requested for missing keys
if ( defaultScope != null ) {
return new ScopeSearchResult( defaultScope, null );
}
// Not found anywhere
throw new KeyNotFoundException(
String.format( "The requested key [%s] was not located in any scope or it's undefined", key.getName() )
);
}

public ScopeSearchResult scopeFind( Key key, IScope defaultScope ) {

// The FunctionBoxContext has no "global" scopes, so just defer to parent

if ( parent != null ) {
// A UDF is "transparent" and can see everything in the parent scope as a "local" observer
return parent.scopeFind( key, defaultScope );
}

Expand Down Expand Up @@ -97,7 +106,15 @@ public IScope getScopeNearby( Key name ) throws ScopeNotFoundException {
return argumentsScope;
}

return getScope( name );
// The FunctionBoxContext has no "global" scopes, so just defer to parent
if ( parent != null ) {
return parent.getScopeNearby( name );
}

// Not found anywhere
throw new ScopeNotFoundException(
String.format( "The requested scope name [%s] was not located in any context", name.getName() )
);

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@

import java.util.Map;

import ortus.boxlang.runtime.scopes.*;
import ortus.boxlang.runtime.types.Function;
import ortus.boxlang.runtime.scopes.IScope;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.types.UDF;
import ortus.boxlang.runtime.types.exceptions.KeyNotFoundException;
import ortus.boxlang.runtime.types.exceptions.ScopeNotFoundException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
package ortus.boxlang.runtime.context;

import ortus.boxlang.runtime.dynamic.BaseTemplate;
import ortus.boxlang.runtime.scopes.*;
import ortus.boxlang.runtime.types.Function;
import ortus.boxlang.runtime.scopes.IScope;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.scopes.VariablesScope;
import ortus.boxlang.runtime.types.Struct;
import ortus.boxlang.runtime.types.UDF;
import ortus.boxlang.runtime.types.exceptions.KeyNotFoundException;
Expand Down
Loading

0 comments on commit 1d11910

Please sign in to comment.