Moved TranspilerState to its own file.

This commit is contained in:
JesseBrault0709 2024-05-25 14:31:35 +02:00
parent 3f45609236
commit dd92d99afd
10 changed files with 168 additions and 162 deletions

View File

@ -1,7 +1,6 @@
package groowt.view.component.web.transpile; package groowt.view.component.web.transpile;
import groowt.view.component.web.ast.node.BodyChildNode; import groowt.view.component.web.ast.node.BodyChildNode;
import groowt.view.component.web.transpile.TranspilerUtil.TranspilerState;
import org.codehaus.groovy.ast.expr.Expression; import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.stmt.Statement; import org.codehaus.groovy.ast.stmt.Statement;

View File

@ -2,7 +2,6 @@ package groowt.view.component.web.transpile;
import groowt.view.component.web.ast.node.BodyChildNode; import groowt.view.component.web.ast.node.BodyChildNode;
import groowt.view.component.web.ast.node.BodyNode; import groowt.view.component.web.ast.node.BodyNode;
import groowt.view.component.web.transpile.TranspilerUtil.TranspilerState;
import org.codehaus.groovy.ast.expr.Expression; import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.stmt.BlockStatement; import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.codehaus.groovy.ast.stmt.Statement; import org.codehaus.groovy.ast.stmt.Statement;

View File

@ -1,7 +1,6 @@
package groowt.view.component.web.transpile; package groowt.view.component.web.transpile;
import groowt.view.component.web.ast.node.ComponentNode; import groowt.view.component.web.ast.node.ComponentNode;
import groowt.view.component.web.transpile.TranspilerUtil.TranspilerState;
import org.codehaus.groovy.ast.stmt.Statement; import org.codehaus.groovy.ast.stmt.Statement;
import java.util.List; import java.util.List;

View File

@ -2,7 +2,6 @@ package groowt.view.component.web.transpile;
import groovy.lang.Tuple2; import groovy.lang.Tuple2;
import groowt.view.component.web.ast.node.BodyChildNode; import groowt.view.component.web.ast.node.BodyChildNode;
import groowt.view.component.web.transpile.TranspilerUtil.TranspilerState;
import org.codehaus.groovy.ast.expr.*; import org.codehaus.groovy.ast.expr.*;
import org.codehaus.groovy.ast.stmt.ExpressionStatement; import org.codehaus.groovy.ast.stmt.ExpressionStatement;
import org.codehaus.groovy.ast.stmt.Statement; import org.codehaus.groovy.ast.stmt.Statement;

View File

@ -2,7 +2,6 @@ package groowt.view.component.web.transpile;
import groowt.view.component.web.WebViewComponentBugError; import groowt.view.component.web.WebViewComponentBugError;
import groowt.view.component.web.ast.node.*; import groowt.view.component.web.ast.node.*;
import groowt.view.component.web.transpile.TranspilerUtil.TranspilerState;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import org.codehaus.groovy.ast.expr.GStringExpression; import org.codehaus.groovy.ast.expr.GStringExpression;
import org.codehaus.groovy.ast.stmt.BlockStatement; import org.codehaus.groovy.ast.stmt.BlockStatement;

View File

@ -2,7 +2,6 @@ package groowt.view.component.web.transpile;
import groowt.view.component.web.WebViewComponentBugError; import groowt.view.component.web.WebViewComponentBugError;
import groowt.view.component.web.ast.node.*; import groowt.view.component.web.ast.node.*;
import groowt.view.component.web.transpile.TranspilerUtil.TranspilerState;
import groowt.view.component.web.transpile.groovy.GroovyUtil; import groowt.view.component.web.transpile.groovy.GroovyUtil;
import groowt.view.component.web.transpile.groovy.GroovyUtil.ConvertResult; import groowt.view.component.web.transpile.groovy.GroovyUtil.ConvertResult;
import org.codehaus.groovy.ast.Parameter; import org.codehaus.groovy.ast.Parameter;

View File

@ -0,0 +1,161 @@
package groowt.view.component.web.transpile;
import groowt.view.component.compiler.ComponentTemplateCompileException;
import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.Variable;
import org.codehaus.groovy.ast.VariableScope;
import org.codehaus.groovy.ast.expr.VariableExpression;
import org.jetbrains.annotations.TestOnly;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
public final class TranspilerState {
public static TranspilerState withRootScope(
Parameter componentContext,
Parameter writer,
Variable renderContext
) {
final VariableScope rootScope = new VariableScope();
rootScope.putDeclaredVariable(componentContext);
rootScope.putDeclaredVariable(writer);
rootScope.putDeclaredVariable(renderContext);
return new TranspilerState(rootScope);
}
@TestOnly
public static TranspilerState withDefaultRootScope() {
final VariableScope rootScope = new VariableScope();
rootScope.putDeclaredVariable(new Parameter(
TranspilerUtil.COMPONENT_CONTEXT_TYPE,
TranspilerUtil.COMPONENT_CONTEXT_NAME
));
rootScope.putDeclaredVariable(new Parameter(
TranspilerUtil.COMPONENT_WRITER_TYPE,
TranspilerUtil.COMPONENT_WRITER_NAME
));
rootScope.putDeclaredVariable(new VariableExpression(
TranspilerUtil.RENDER_CONTEXT_NAME,
TranspilerUtil.WEB_VIEW_COMPONENT_RENDER_CONTEXT_TYPE
));
return new TranspilerState(rootScope);
}
private final AtomicInteger componentNumberCounter = new AtomicInteger();
private final Deque<VariableScope> scopeStack = new LinkedList<>();
private final Deque<VariableExpression> componentStack = new LinkedList<>();
private final Deque<VariableExpression> resolvedStack = new LinkedList<>();
private final Deque<Parameter> childListStack = new LinkedList<>();
private final List<ComponentTemplateCompileException> errors = new ArrayList<>();
private int lastComponentNumber;
private TranspilerState(VariableScope rootScope) {
this.scopeStack.push(rootScope);
}
public int getCurrentComponentNumber() {
return this.lastComponentNumber;
}
public int newComponentNumber() {
this.lastComponentNumber = this.componentNumberCounter.getAndIncrement();
return this.lastComponentNumber;
}
public VariableScope pushScope() {
final VariableScope parent = this.scopeStack.peek();
final VariableScope result = new VariableScope(parent);
this.scopeStack.push(result);
return result;
}
public void popScope() {
this.scopeStack.pop();
}
public VariableScope getCurrentScope() {
return Objects.requireNonNull(this.scopeStack.peek());
}
private Variable getDeclaredVariable(String name) {
VariableScope scope = this.getCurrentScope();
while (scope != null) {
final Variable potential = scope.getDeclaredVariable(name);
if (potential != null) {
return potential;
} else {
scope = scope.getParent();
}
}
throw new NullPointerException("Cannot find variable: " + name);
}
public VariableExpression getWriter() {
return new VariableExpression(this.getDeclaredVariable(TranspilerUtil.COMPONENT_WRITER_NAME));
}
public VariableExpression getRenderContext() {
return (VariableExpression) this.getDeclaredVariable(TranspilerUtil.RENDER_CONTEXT_NAME);
}
public void pushComponent(VariableExpression componentVariable) {
this.componentStack.push(componentVariable);
}
public void popComponent() {
this.componentStack.pop();
}
public VariableExpression getCurrentComponent() {
return Objects.requireNonNull(this.componentStack.peek());
}
public void pushResolved(VariableExpression resolvedVariable) {
this.resolvedStack.push(resolvedVariable);
}
public void popResolved() {
this.resolvedStack.pop();
}
public VariableExpression getCurrentResolved() {
return Objects.requireNonNull(this.resolvedStack.peek());
}
public void pushChildList(Parameter childCollector) {
this.childListStack.push(childCollector);
}
public void popChildList() {
this.childListStack.pop();
}
public VariableExpression getCurrentChildList() {
final Parameter childCollectorParam = Objects.requireNonNull(this.childListStack.peek());
return new VariableExpression(childCollectorParam);
}
public boolean hasCurrentChildList() {
return this.childListStack.peek() != null;
}
public void addError(ComponentTemplateCompileException error) {
this.errors.add(error);
}
public void addErrors(Collection<? extends ComponentTemplateCompileException> errors) {
this.errors.addAll(errors);
}
public boolean hasErrors() {
return !this.errors.isEmpty();
}
public List<ComponentTemplateCompileException> getErrors() {
return new ArrayList<>(this.errors);
}
}

View File

@ -2,21 +2,16 @@ package groowt.view.component.web.transpile;
import groovy.lang.Tuple2; import groovy.lang.Tuple2;
import groowt.view.component.ComponentTemplate; import groowt.view.component.ComponentTemplate;
import groowt.view.component.compiler.ComponentTemplateCompileException;
import groowt.view.component.context.ComponentContext; import groowt.view.component.context.ComponentContext;
import groowt.view.component.runtime.ComponentWriter; import groowt.view.component.runtime.ComponentWriter;
import groowt.view.component.web.runtime.DefaultWebViewRenderContext; import groowt.view.component.web.runtime.DefaultWebViewRenderContext;
import groowt.view.component.web.runtime.WebViewComponentRenderContext; import groowt.view.component.web.runtime.WebViewComponentRenderContext;
import groowt.view.component.web.util.SourcePosition; import groowt.view.component.web.util.SourcePosition;
import org.codehaus.groovy.ast.*; import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.expr.ConstantExpression; import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.syntax.Token; import org.codehaus.groovy.syntax.Token;
import org.codehaus.groovy.syntax.Types; import org.codehaus.groovy.syntax.Types;
import org.jetbrains.annotations.TestOnly;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
public final class TranspilerUtil { public final class TranspilerUtil {
@ -57,149 +52,6 @@ public final class TranspilerUtil {
return new Token(Types.LEFT_SHIFT, "<<", -1, -1); return new Token(Types.LEFT_SHIFT, "<<", -1, -1);
} }
public static final class TranspilerState {
public static TranspilerState withRootScope(
Parameter componentContext,
Parameter writer,
Variable renderContext
) {
final VariableScope rootScope = new VariableScope();
rootScope.putDeclaredVariable(componentContext);
rootScope.putDeclaredVariable(writer);
rootScope.putDeclaredVariable(renderContext);
return new TranspilerState(rootScope);
}
@TestOnly
public static TranspilerState withDefaultRootScope() {
final VariableScope rootScope = new VariableScope();
rootScope.putDeclaredVariable(new Parameter(COMPONENT_CONTEXT_TYPE, COMPONENT_CONTEXT_NAME));
rootScope.putDeclaredVariable(new Parameter(COMPONENT_WRITER_TYPE, COMPONENT_WRITER_NAME));
rootScope.putDeclaredVariable(new VariableExpression(RENDER_CONTEXT_NAME,
WEB_VIEW_COMPONENT_RENDER_CONTEXT_TYPE
));
return new TranspilerState(rootScope);
}
private final AtomicInteger componentNumberCounter = new AtomicInteger();
private final Deque<VariableScope> scopeStack = new LinkedList<>();
private final Deque<VariableExpression> componentStack = new LinkedList<>();
private final Deque<VariableExpression> resolvedStack = new LinkedList<>();
private final Deque<Parameter> childListStack = new LinkedList<>();
private final List<ComponentTemplateCompileException> errors = new ArrayList<>();
private int lastComponentNumber;
private TranspilerState(VariableScope rootScope) {
this.scopeStack.push(rootScope);
}
public int getCurrentComponentNumber() {
return this.lastComponentNumber;
}
public int newComponentNumber() {
this.lastComponentNumber = this.componentNumberCounter.getAndIncrement();
return this.lastComponentNumber;
}
public VariableScope pushScope() {
final VariableScope parent = this.scopeStack.peek();
final VariableScope result = new VariableScope(parent);
this.scopeStack.push(result);
return result;
}
public void popScope() {
this.scopeStack.pop();
}
public VariableScope getCurrentScope() {
return Objects.requireNonNull(this.scopeStack.peek());
}
private Variable getDeclaredVariable(String name) {
VariableScope scope = this.getCurrentScope();
while (scope != null) {
final Variable potential = scope.getDeclaredVariable(name);
if (potential != null) {
return potential;
} else {
scope = scope.getParent();
}
}
throw new NullPointerException("Cannot find variable: " + name);
}
public VariableExpression getWriter() {
return new VariableExpression(this.getDeclaredVariable(COMPONENT_WRITER_NAME));
}
public VariableExpression getRenderContext() {
return (VariableExpression) this.getDeclaredVariable(RENDER_CONTEXT_NAME);
}
public void pushComponent(VariableExpression componentVariable) {
this.componentStack.push(componentVariable);
}
public void popComponent() {
this.componentStack.pop();
}
public VariableExpression getCurrentComponent() {
return Objects.requireNonNull(this.componentStack.peek());
}
public void pushResolved(VariableExpression resolvedVariable) {
this.resolvedStack.push(resolvedVariable);
}
public void popResolved() {
this.resolvedStack.pop();
}
public VariableExpression getCurrentResolved() {
return Objects.requireNonNull(this.resolvedStack.peek());
}
public void pushChildList(Parameter childCollector) {
this.childListStack.push(childCollector);
}
public void popChildList() {
this.childListStack.pop();
}
public VariableExpression getCurrentChildList() {
final Parameter childCollectorParam = Objects.requireNonNull(this.childListStack.peek());
return new VariableExpression(childCollectorParam);
}
public boolean hasCurrentChildList() {
return this.childListStack.peek() != null;
}
public void addError(ComponentTemplateCompileException error) {
this.errors.add(error);
}
public void addErrors(Collection<? extends ComponentTemplateCompileException> errors) {
this.errors.addAll(errors);
}
public boolean hasErrors() {
return !this.errors.isEmpty();
}
public List<ComponentTemplateCompileException> getErrors() {
return new ArrayList<>(this.errors);
}
}
private TranspilerUtil() {} private TranspilerUtil() {}
} }

View File

@ -1,7 +1,6 @@
package groowt.view.component.web.transpile; package groowt.view.component.web.transpile;
import groowt.view.component.web.ast.node.ValueNode; import groowt.view.component.web.ast.node.ValueNode;
import groowt.view.component.web.transpile.TranspilerUtil.TranspilerState;
import org.codehaus.groovy.ast.expr.Expression; import org.codehaus.groovy.ast.expr.Expression;
public interface ValueNodeTranspiler { public interface ValueNodeTranspiler {

View File

@ -8,7 +8,7 @@ import groowt.view.component.web.ast.node.BodyNode;
import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit; import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit;
import groowt.view.component.web.transpile.BodyTranspiler; import groowt.view.component.web.transpile.BodyTranspiler;
import groowt.view.component.web.transpile.TranspilerConfiguration; import groowt.view.component.web.transpile.TranspilerConfiguration;
import groowt.view.component.web.transpile.TranspilerUtil; import groowt.view.component.web.transpile.TranspilerState;
import org.codehaus.groovy.ast.ModuleNode; import org.codehaus.groovy.ast.ModuleNode;
import org.codehaus.groovy.ast.expr.ConstantExpression; import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.MethodCallExpression; import org.codehaus.groovy.ast.expr.MethodCallExpression;
@ -67,12 +67,12 @@ public abstract class BodyTranspilerTests {
final var buildResult = this.build(source); final var buildResult = this.build(source);
final var configuration = this.getConfiguration(compileUnit, moduleNode); final var configuration = this.getConfiguration(compileUnit, moduleNode);
final var transpiler = this.getBodyTranspiler(configuration); final var transpiler = this.getBodyTranspiler(configuration);
final var state = TranspilerUtil.TranspilerState.withDefaultRootScope(); final var state = TranspilerState.withDefaultRootScope();
final var addOrAppend = configuration.getAppendOrAddStatementFactory(); final var addOrAppend = configuration.getAppendOrAddStatementFactory();
final BlockStatement blockStatement = transpiler.transpileBody( final BlockStatement blockStatement = transpiler.transpileBody(
buildResult.bodyNode(), buildResult.bodyNode(),
(node, expression) -> addOrAppend.addOrAppend(node, state, ignored -> expression), (node, expression) -> addOrAppend.addOrAppend(node, state, ignored -> expression),
TranspilerUtil.TranspilerState.withDefaultRootScope() TranspilerState.withDefaultRootScope()
); );
assertEquals(1, blockStatement.getStatements().size()); assertEquals(1, blockStatement.getStatements().size());
} }
@ -86,12 +86,12 @@ public abstract class BodyTranspilerTests {
final var buildResult = this.build(source); final var buildResult = this.build(source);
final var configuration = this.getConfiguration(compileUnit, moduleNode); final var configuration = this.getConfiguration(compileUnit, moduleNode);
final var transpiler = this.getBodyTranspiler(configuration); final var transpiler = this.getBodyTranspiler(configuration);
final var state = TranspilerUtil.TranspilerState.withDefaultRootScope(); final var state = TranspilerState.withDefaultRootScope();
final var addOrAppend = configuration.getAppendOrAddStatementFactory(); final var addOrAppend = configuration.getAppendOrAddStatementFactory();
final BlockStatement blockStatement = transpiler.transpileBody( final BlockStatement blockStatement = transpiler.transpileBody(
buildResult.bodyNode(), buildResult.bodyNode(),
(node, expression) -> addOrAppend.addOrAppend(node, state, ignored -> expression), (node, expression) -> addOrAppend.addOrAppend(node, state, ignored -> expression),
TranspilerUtil.TranspilerState.withDefaultRootScope() TranspilerState.withDefaultRootScope()
); );
assertEquals(1, blockStatement.getStatements().size()); assertEquals(1, blockStatement.getStatements().size());
final var s0 = (ExpressionStatement) blockStatement.getStatements().getFirst(); final var s0 = (ExpressionStatement) blockStatement.getStatements().getFirst();