Skip to content

Commit

Permalink
Merge pull request #96 from ortus-boxlang/development
Browse files Browse the repository at this point in the history
1.0.0-Beta10
  • Loading branch information
lmajano authored Aug 16, 2024
2 parents 4453241 + 259e78c commit 07a1218
Show file tree
Hide file tree
Showing 159 changed files with 15,469 additions and 347 deletions.
8 changes: 6 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ dependencies {
// https://mvnrepository.com/artifact/com.github.javaparser/javaparser-symbol-solver-core
implementation 'com.github.javaparser:javaparser-symbol-solver-core:3.26.1'
// https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
implementation 'org.apache.commons:commons-lang3:3.15.0'
implementation 'org.apache.commons:commons-lang3:3.16.0'
// https://mvnrepository.com/artifact/org.apache.commons/commons-text
// Many of these classes ( e.g. StringEscapeUtils ) are currently deprecated in commons-lang and others will be moved in the future
implementation 'org.apache.commons:commons-text:1.12.0'
Expand All @@ -120,11 +120,15 @@ dependencies {
// https://mvnrepository.com/artifact/com.fasterxml.jackson.jr/jackson-jr-annotation-support
implementation 'com.fasterxml.jackson.jr:jackson-jr-annotation-support:2.17.2'
// https://mvnrepository.com/artifact/org.slf4j/slf4j-api
implementation 'org.slf4j:slf4j-api:2.0.13'
implementation 'org.slf4j:slf4j-api:2.0.16'
// https://mvnrepository.com/artifact/ch.qos.logback/logback-classic
implementation 'ch.qos.logback:logback-classic:1.5.6'
// https://mvnrepository.com/artifact/com.zaxxer/HikariCP
implementation 'com.zaxxer:HikariCP:5.1.0'
// https://mvnrepository.com/artifact/org.ow2.asm/asm-tree
implementation 'org.ow2.asm:asm-tree:9.7'
// https://mvnrepository.com/artifact/org.ow2.asm/asm-util
implementation 'org.ow2.asm:asm-util:9.7'
}

/**
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 Aug 02 15:59:15 UTC 2024
#Fri Aug 09 14:28:54 UTC 2024
antlrVersion=4.13.1
jdkVersion=21
version=1.0.0-beta9
version=1.0.0-beta10
11 changes: 3 additions & 8 deletions src/main/java/ortus/boxlang/compiler/IBoxpiler.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
package ortus.boxlang.compiler;

import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.io.PrintStream;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.parser.BoxSourceType;
import ortus.boxlang.compiler.parser.ParsingResult;
import ortus.boxlang.runtime.context.IBoxContext;
Expand Down Expand Up @@ -166,8 +162,7 @@ static String getClassName( File file ) {

ParsingResult validateParse( ParsingResult result, String source );

@SuppressWarnings( "unused" )
String generateJavaSource( BoxNode node, ClassInfo classInfo );
void printTranspiledCode( ParsingResult result, ClassInfo classInfo, PrintStream target );

SourceMap getSourceMapFromFQN( String FQN );

Expand Down
100 changes: 71 additions & 29 deletions src/main/java/ortus/boxlang/compiler/asmboxpiler/ASMBoxpiler.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
package ortus.boxlang.compiler.asmboxpiler;

import java.io.File;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.List;
import java.util.function.BiConsumer;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.util.CheckClassAdapter;
import org.objectweb.asm.util.TraceClassVisitor;

import ortus.boxlang.compiler.Boxpiler;
import ortus.boxlang.compiler.ClassInfo;
import ortus.boxlang.compiler.ast.BoxClass;
import ortus.boxlang.compiler.ast.BoxNode;
import ortus.boxlang.compiler.parser.BoxSourceType;
import ortus.boxlang.compiler.ast.BoxScript;
import ortus.boxlang.compiler.ast.visitor.QueryEscapeSingleQuoteVisitor;
import ortus.boxlang.compiler.parser.ParsingResult;
import ortus.boxlang.runtime.runnables.IBoxRunnable;
import ortus.boxlang.runtime.types.exceptions.BoxRuntimeException;
import ortus.boxlang.runtime.util.ResolvedFilePath;

Expand Down Expand Up @@ -50,42 +60,77 @@ public static synchronized ASMBoxpiler getInstance() {
}

@Override
public Class<IBoxRunnable> compileStatement( String source, BoxSourceType type ) {
ClassInfo classInfo = ClassInfo.forStatement( source, type, this );
var classPool = getClassPool( classInfo.classPoolName() );
classPool.putIfAbsent( classInfo.FQN(), classInfo );
classInfo = classPool.get( classInfo.FQN() );

return classInfo.getDiskClass();

}
public void printTranspiledCode( ParsingResult result, ClassInfo classInfo, PrintStream target ) {
try ( PrintWriter writer = new PrintWriter( target ) ) {
doCompileClassInfo( transpiler( classInfo ), classInfo, parseClassInfo( classInfo ).getRoot(),
( fqn, node ) -> node.accept( new TraceClassVisitor( null, new PrintWriter( target ) ) ) );
}

@Override
public String generateJavaSource( BoxNode node, ClassInfo classInfo ) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException( "Unimplemented method 'generateJavaSource'" );
}

@Override
public void compileClassInfo( String classPoolName, String FQN ) {
var classPool = getClassPool( classPoolName );
ClassInfo classInfo = classPool.get( FQN );
ClassInfo classInfo = getClassPool( classPoolName ).get( FQN );
if ( classInfo == null ) {
throw new BoxRuntimeException( "ClassInfo not found for " + FQN );
}

// This is the entry point for generating bytecode before this function returns it should generate a class file

// This result holds the AST we want to convert to bytecode
ParsingResult result = parseClassInfo( classInfo );
if ( classInfo.resolvedFilePath() != null ) {
File sourceFile = classInfo.resolvedFilePath().absolutePath().toFile();
// Check if the source file contains Java bytecode by reading the first few bytes
if ( diskClassUtil.isJavaBytecode( sourceFile ) ) {
System.out.println( "Loading bytecode direct from pre-compiled source file for " + FQN );
classInfo.getClassLoader().defineClasses( FQN, sourceFile );
return;
}
ParsingResult result = parseOrFail( sourceFile );
doWriteClassInfo( result.getRoot(), classInfo );
} else if ( classInfo.source() != null ) {
ParsingResult result = parseOrFail( classInfo.source(), classInfo.sourceType(), classInfo.isClass() );
doWriteClassInfo( result.getRoot(), classInfo );
} else if ( classInfo.interfaceProxyDefinition() != null ) {
throw new UnsupportedOperationException();
} else {
throw new BoxRuntimeException( "Unknown class info type: " + classInfo.toString() );
}
}

// Generate the bytes...
byte[] bytes = new byte[ 256 ];
private void doWriteClassInfo( BoxNode node, ClassInfo classInfo ) {
node.accept( new QueryEscapeSingleQuoteVisitor() );
doCompileClassInfo( transpiler( classInfo ), classInfo, node, ( fqn, classNode ) -> {
ClassWriter classWriter = new ClassWriter( ClassWriter.COMPUTE_FRAMES );
classNode.accept( new CheckClassAdapter( new TraceClassVisitor( classWriter, new PrintWriter( System.out ) ) ) );
// classNode.accept( classWriter );
byte[] bytes = classWriter.toByteArray();
diskClassUtil.writeBytes( classInfo.classPoolName(), fqn, "class", bytes );
} );
}

// use diskClassUtil to write your class files to the appropriate location
diskClassUtil.writeBytes( classPoolName, classInfo.FQN(), ".class", bytes );
private static Transpiler transpiler( ClassInfo classInfo ) {
Transpiler transpiler = Transpiler.getTranspiler();
transpiler.setProperty( "classname", classInfo.className() );
transpiler.setProperty( "packageName", classInfo.packageName().toString() );
transpiler.setProperty( "boxPackageName", classInfo.boxPackageName().toString() );
transpiler.setProperty( "baseclass", classInfo.baseclass() );
transpiler.setProperty( "returnType", classInfo.returnType() );
transpiler.setProperty( "sourceType", classInfo.sourceType().name() );
transpiler.setProperty( "mappingName", classInfo.resolvedFilePath() == null ? null : classInfo.resolvedFilePath().mappingName() );
transpiler.setProperty( "mappingPath", classInfo.resolvedFilePath() == null ? null : classInfo.resolvedFilePath().mappingPath() );
transpiler.setProperty( "relativePath", classInfo.resolvedFilePath() == null ? null : classInfo.resolvedFilePath().relativePath() );
return transpiler;
}

throw new UnsupportedOperationException( "Unimplemented method 'generateJavaSource'" );
private void doCompileClassInfo( Transpiler transpiler, ClassInfo classInfo, BoxNode node, BiConsumer<String, ClassNode> consumer ) {
ClassNode classNode;
if ( node instanceof BoxScript boxScript ) {
classNode = transpiler.transpile( boxScript );
} else if ( node instanceof BoxClass boxClass ) {
classNode = transpiler.transpile( boxClass );
} else {
throw new IllegalStateException( "Unexpected root type: " + node );
}
transpiler.getAuxiliary().forEach( consumer );
consumer.accept( classInfo.FQN(), classNode );
}

private ParsingResult parseClassInfo( ClassInfo info ) {
Expand All @@ -94,14 +139,11 @@ private ParsingResult parseClassInfo( ClassInfo info ) {
} else if ( info.source() != null ) {
return parseOrFail( info.source(), info.sourceType(), info.isClass() );
}

return null;
}

@Override
public List<byte[]> compileTemplateBytes( ResolvedFilePath resolvedFilePath ) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException( "Unimplemented method 'compileTemplateBytes'" );
}

}
Loading

0 comments on commit 07a1218

Please sign in to comment.