The following presentation is provided under DHMB license
(Do Not Hurt My Brain).
Lecturer is not responsible for the financial and moral
damages resulting from taking too seriously the content of
the presentation.
Including permanent damage to neurons, reduction of
neurotransmitter activity at the molecular level and group
dismissal.
Patterns for JVM
languages
Jarosław Pałka
about me
work://chief_architect@lumesse
owner://symentis.pl
twitter://j_palka
blog://geekyprimitives.wordpress.com
scm:bitbucket://kcrimson
scm:github://kcrimson
Pet project
Because having pet projects is like solving crosswords
everyday
Or going to a gym
Helps your brain to stay in shape
Patterns for JVM languages - Geecon 2014
Patterns for JVM languages - Geecon 2014
JVM
is
the
new
assembler
Translator
source code
↓
target language source code
↓
machine code || interpreter
Interpreter
source code
↓
execution results
Compiler
source code
↓
machine code
So how does it all work?
Diving into the stream
source code
↓lexer
token stream
↓parser
IR
Intermediate Representation
visitor
listener
tree
Syntax tree
local y = 1
x = 1 + y
Patterns for JVM languages - Geecon 2014
Patterns for JVM languages - Geecon 2014
Patterns for JVM languages - Geecon 2014
fragment
DIGIT
:
[0-9]
;
fragment
LETTER
:
[a-zA-Z]
;
String
:
''' .*? '''
| '"' .*? '"'
;
Number
:
DIGIT+
;
Name
:
(
'_'
| LETTER
)
(
'_'
| LETTER
| DIGIT
)*
;
COMMENT
:
'--' .*? 'n' -> skip
;
NL
:
'r'? 'n' -> skip
;
WS
:
[ tf]+ -> skip
;
[@0,[0..1)='x',<49>]
[@1,[2..3)='=',<36>]
[@2,[4..5)='1',<48>]
[@3,[6..7)='+',<33>]
[@4,[8..15)='"Hello"',<47>]
[@5,[15..16)=';',<37>]
[@6,[17..17)='',<-1=EOF>]
varlist returns [Varlist result]
:
var
{$result = createVarlist($var.result);}
(
',' var
{$result = createVarlist($result,$var.result);}
)*
;
//
var returns [Var result]
:
Name
{ $result = createVariableName($Name.text); }
| prefixexp '[' exp ']'
| prefixexp '.' Name
;
beware of left recursion
translator
interpreter
compiler
Interpreter pattern
Non terminal nodes
Terminal nodes
Patterns for JVM languages - Geecon 2014
package pl.symentis.lua.grammar;
import pl.symentis.lua.runtime.Context;
public interface Statement {
void execute(Context context);
}
package pl.symentis.lua.grammar;
Import pl.symentis.lua.runtime.Context;
public interface Expression<T> {
T evaluate(Context ctx);
}
package pl.symentis.lua.runtime;
public interface Context {
VariableRef resolveVariable(String name);
Scope enterScope();
Scope exitScope();
}
package pl.symentis.lua.runtime;
public interface Scope {
Scope getOuterScope();
VariableRef resolveVariable(String name);
void bindVariable(String name, Object value);
}
Into the forest of syntax tree
x = 1
public class Literal implements ExpressionNode {
public final LuaType value;
public Literal(LuaType value) {
super();
this.value = value;
}
@Override
public void accept(ExpressionVisitor visitor) {
visitor.visit(this);
}
}
public class VariableName extends Var {
public final String name;
public VariableName(String name) {
this.name = name;
}
@Override
public void accept(ExpressionVisitor visitor) {
visitor.visit(this);
}
}
public class Assignment implements StatementNode {
public final Varlist varlist;
public final Explist explist;
public Assignment(Varlist varlist, Explist explist) {
super();
this.varlist = varlist;
this.explist = explist;
}
@Override
public void accept(StatementVisitor visitor) {
visitor.visit(this);
}
}
public void visit(Assignment assignment) {
InterpreterExpressionVisitor varlist = createExpressionVisitor();
assignment.varlist.accept(varlist);
InterpreterExpressionVisitor explist = createExpressionVisitor();
assignment.explist.accept(explist);
Iterator<ExpressionNode> iterator = ((List<ExpressionNode>) explist.result()).iterator();
List<VariableRef> vars = (List<VariableRef>) varlist.result();
for (VariableRef variableRef : vars) {
if (iterator.hasNext()) {
ExpressionNode node = iterator.next();
InterpreterExpressionVisitor exp = createExpressionVisitor();
node.accept(exp);
variableRef.set(exp.result());
} else {
variableRef.set(LuaNil.Nil);
}
}
}
public void visit(Literal literal) {
result = literal.value;
}
public void visit(VariableName variableName) {
result = context.resolveVariable(variableName.name);
}
public void visit(Varlist varlist) {
List<VariableRef> refs = new ArrayList<>();
for (Var var : varlist.vars) {
var.accept(this);
refs.add((VariableRef) result());
}
result = refs;
}
translator
interpreter
compiler
compiler → byte code
org.ow2.asm:asm:jar
me.qmx.jitescript:jitescript:jar
JiteClass jiteClass = new JiteClass(classname, new String[] { p(Script.class) });
jiteClass.defineDefaultConstructor();
CodeBlock codeBlock = newCodeBlock();
// bind context into current runtime
codeBlock.aload(1);
codeBlock.invokestatic(p(RuntimeContext.class), "enterContext", sig(void.class, Context.class));
// parse file and start to walk through AST visitor
StatementNode chunk = parseScript(readFileToString(script));
// generate byte code
chunk.accept(new CompilerStatementVisitor(codeBlock, new HashSymbolTable()));
codeBlock.voidreturn();
jiteClass.defineMethod("execute", JiteClass.ACC_PUBLIC, sig(void.class, new Class[]
{ Context.class }),
codeBlock);
return jiteClass.toBytes(JDKVersion.V1_8);
}
JiteClass jiteClass = new JiteClass(classname, new String[] { p(Script.class) });
jiteClass.defineDefaultConstructor();
CodeBlock codeBlock = newCodeBlock();
// bind context into current runtime
codeBlock.aload(1);
codeBlock.invokestatic(p(RuntimeContext.class), "enterContext", sig(void.class, Context.class));
// parse file and start to walk through AST visitor
StatementNode chunk = parseScript(readFileToString(script));
// generate byte code
chunk.accept(new CompilerStatementVisitor(codeBlock, new HashSymbolTable()));
codeBlock.voidreturn();
jiteClass.defineMethod("execute", JiteClass.ACC_PUBLIC, sig(void.class, new Class[]
{ Context.class }),
codeBlock);
return jiteClass.toBytes(JDKVersion.V1_8);
}
JiteClass jiteClass = new JiteClass(classname, new String[] { p(Script.class) });
jiteClass.defineDefaultConstructor();
CodeBlock codeBlock = newCodeBlock();
// bind context into current runtime
codeBlock.aload(1);
codeBlock.invokestatic(p(RuntimeContext.class), "enterContext", sig(void.class, Context.class));
// parse file and start to walk through AST visitor
StatementNode chunk = parseScript(readFileToString(script));
// generate byte code
chunk.accept(new CompilerStatementVisitor(codeBlock, new HashSymbolTable()));
codeBlock.voidreturn();
jiteClass.defineMethod("execute", JiteClass.ACC_PUBLIC, sig(void.class, new Class[]
{ Context.class }),
codeBlock);
return jiteClass.toBytes(JDKVersion.V1_8);
}
x = 1
public void visit(Assignment assignment) {
Explist explist = assignment.explist;
Varlist varlist = assignment.varlist;
Iterator<Var> vars = varlist.vars.iterator();
for (ExpressionNode exp : explist.expressions) {
exp.accept(new CompilerExpressionVisitor(codeBlock, symbolTable));
CompilerExpressionVisitor visitor = new CompilerExpressionVisitor(
codeBlock, symbolTable);
vars.next().accept(visitor);
String varName = (String) visitor.result();
codeBlock.astore(symbolTable.index(varName));
}
}
public void visit(Literal literal) {
Object object = literal.value.asObject();
codeBlock.ldc(object);
// box object into Lua type
if (object instanceof Integer) {
codeBlock.invokestatic(p(Integer.class), "valueOf", sig(Integer.class, int.class));
} else if (object instanceof Double) {
codeBlock.invokestatic(p(Double.class), "valueOf", sig(Double.class,
double.class));
}
codeBlock.invokestatic(p(LuaTypes.class), "valueOf", sig(LuaType.class, Object.class));
}
public void visit(VariableName variableName) {
result = variableName.name;
}
When writing bytecode compiler it helps to think about Java code
But at the end you need to think like stack machine :)
.method public execute : (Lpl/symentis/lua4j/runtime/Context;)V
; method code size: 21 bytes
.limit stack 2
.limit locals 3
aload_1
invokestatic pl/symentis/lua4j/compiler/RuntimeContext
enterContext (Lpl/symentis/lua4j/runtime/Context;)V
ldc2_w 1.0
invokestatic java/lang/Double valueOf (D)Ljava/lang/Double;
invokestatic pl/symentis/lua4j/types/LuaTypes valueOf [_28]
astore_2
aload_2
return
.end method
Symbol table
maps variable local to its symbolic name
0xBA
invokedynamic
print("Welcome","to","Geecon",2014)
Var var = functionCall.var;
CompilerExpressionVisitor visitor = new CompilerExpressionVisitor(codeBlock,
symbolTable);
var.accept(visitor);
String functionName = (String) visitor.result();
Args args = functionCall.args;
visitor = new CompilerExpressionVisitor(codeBlock, symbolTable);
args.accept(visitor);
Integer argNumber = (Integer) visitor.result();
Class<?>[] paramTypeArr = new Class[argNumber];
fill(paramTypeArr, LuaType.class);
codeBlock.invokedynamic(functionName, sig(void.class, paramTypeArr),
Lua4JDynamicBootstrap.HANDLE,
new Object[] {});
static final Handle HANDLE = new Handle(
CodeBlock.H_INVOKESTATIC,
p(Lua4JDynamicBootstrap.class),
"bootstrap",
sig(CallSite.class, MethodHandles.Lookup.class, String.class,
MethodType.class));
public static CallSite bootstrap(
MethodHandles.Lookup lookup,
String name,
MethodType type) throws Throwable {
Context context = currentContext();
MethodHandle target=lookup.findStatic(BasicFunctions.class,name,
methodType(
LuaType.class,
Context.class,
LuaType[].class));
target = MethodHandles.insertArguments(handler, 0, context)
.asCollector(LuaType[].class, type.parameterCount());
return new ConstantCallSite(target.asType(type));
}
https://github.com/headius/invokebinder
A Java DSL for binding method handles forward,
rather than backward
https://github.com/projectodd/rephract
Another Java DSL for invokedynamic
What's next?
graal + truffle
dynamic compiler + AST interpreter
Thanks,
stay cool,
dynamically linked
and...
Let the eternal stream of bytecode
flow through your body
Q&A

More Related Content

PPTX
Javascript best practices
PDF
Secrets of JavaScript Libraries
ZIP
Fundamental JavaScript [In Control 2009]
PDF
Javascript Best Practices
PPT
Javascript and Jquery Best practices
PDF
JavaScript Basics and Best Practices - CC FE & UX
PDF
Performance Optimization and JavaScript Best Practices
PDF
Ten useful JavaScript tips & best practices
Javascript best practices
Secrets of JavaScript Libraries
Fundamental JavaScript [In Control 2009]
Javascript Best Practices
Javascript and Jquery Best practices
JavaScript Basics and Best Practices - CC FE & UX
Performance Optimization and JavaScript Best Practices
Ten useful JavaScript tips & best practices

What's hot (20)

PPTX
Javascript basics for automation testing
PPTX
5 Tips for Better JavaScript
PDF
Fundamental JavaScript [UTC, March 2014]
ODP
Javascript
PDF
JavaScript Best Pratices
PDF
JavaScript - From Birth To Closure
PDF
JavaScript 101
PDF
Scalable JavaScript Design Patterns
PDF
Javascript Design Patterns
PDF
Java Script Best Practices
PPT
JavaScript Basics
PPT
A Deeper look into Javascript Basics
PPTX
Intro to Javascript
PPTX
JavaScript Fundamentals & JQuery
PDF
Design patterns in java script, jquery, angularjs
PPT
Java script
PDF
Javascript basics
PDF
How AngularJS Embraced Traditional Design Patterns
PPTX
Javascript Common Design Patterns
Javascript basics for automation testing
5 Tips for Better JavaScript
Fundamental JavaScript [UTC, March 2014]
Javascript
JavaScript Best Pratices
JavaScript - From Birth To Closure
JavaScript 101
Scalable JavaScript Design Patterns
Javascript Design Patterns
Java Script Best Practices
JavaScript Basics
A Deeper look into Javascript Basics
Intro to Javascript
JavaScript Fundamentals & JQuery
Design patterns in java script, jquery, angularjs
Java script
Javascript basics
How AngularJS Embraced Traditional Design Patterns
Javascript Common Design Patterns
Ad

Similar to Patterns for JVM languages - Geecon 2014 (20)

PDF
Patterns for JVM languages JokerConf
ODP
Ast transformations
PDF
Interpreter Case Study - Design Patterns
PDF
TypeScript Introduction
ODP
AST Transformations
PDF
Activator and Reactive at Play NYC meetup
ODP
Groovy Ast Transformations (greach)
PDF
FalsyValues. Dmitry Soshnikov - ECMAScript 6
PDF
Decoupling with Design Patterns and Symfony2 DIC
PDF
JNI - Java & C in the same project
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
PDF
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
PDF
So various polymorphism in Scala
PDF
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
PDF
​"Delegates, Delegates everywhere" Владимир Миронов
PPTX
JavaFX 2.0 With Alternative Languages - JavaOne 2011
PDF
Kotlin Austin Droids April 14 2016
Patterns for JVM languages JokerConf
Ast transformations
Interpreter Case Study - Design Patterns
TypeScript Introduction
AST Transformations
Activator and Reactive at Play NYC meetup
Groovy Ast Transformations (greach)
FalsyValues. Dmitry Soshnikov - ECMAScript 6
Decoupling with Design Patterns and Symfony2 DIC
JNI - Java & C in the same project
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
So various polymorphism in Scala
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
​"Delegates, Delegates everywhere" Владимир Миронов
JavaFX 2.0 With Alternative Languages - JavaOne 2011
Kotlin Austin Droids April 14 2016
Ad

More from Jaroslaw Palka (7)

PDF
We are crowd, we are anonymous
PDF
Czterej jeźdźcy apokalipsy gdy Armagedon w JVM nadchodzi
ODP
Systematyczny architekt na drodze ku planowanemu postarzaniu
PDF
Systematyczny architekt na drodze ku planowanemu postarzaniu
PDF
Patterns for organic architecture
ODP
I ty też możesz mieć swoje dane w cache
PPTX
Programming and architecture of NOSQL web at 33degree
We are crowd, we are anonymous
Czterej jeźdźcy apokalipsy gdy Armagedon w JVM nadchodzi
Systematyczny architekt na drodze ku planowanemu postarzaniu
Systematyczny architekt na drodze ku planowanemu postarzaniu
Patterns for organic architecture
I ty też możesz mieć swoje dane w cache
Programming and architecture of NOSQL web at 33degree

Recently uploaded (20)

PDF
AI Guide for Business Growth - Arna Softech
PDF
AI-Powered Threat Modeling: The Future of Cybersecurity by Arun Kumar Elengov...
PPTX
Monitoring Stack: Grafana, Loki & Promtail
PDF
EaseUS PDF Editor Pro 6.2.0.2 Crack with License Key 2025
PPTX
Patient Appointment Booking in Odoo with online payment
PDF
CCleaner 6.39.11548 Crack 2025 License Key
PDF
DuckDuckGo Private Browser Premium APK for Android Crack Latest 2025
PPTX
GSA Content Generator Crack (2025 Latest)
PPTX
Weekly report ppt - harsh dattuprasad patel.pptx
PDF
MCP Security Tutorial - Beginner to Advanced
PDF
How to Make Money in the Metaverse_ Top Strategies for Beginners.pdf
PDF
Autodesk AutoCAD Crack Free Download 2025
PPTX
Introduction to Windows Operating System
PPTX
"Secure File Sharing Solutions on AWS".pptx
PDF
Visual explanation of Dijkstra's Algorithm using Python
PDF
AI/ML Infra Meetup | Beyond S3's Basics: Architecting for AI-Native Data Access
PDF
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
PDF
Time Tracking Features That Teams and Organizations Actually Need
DOCX
Modern SharePoint Intranet Templates That Boost Employee Engagement in 2025.docx
PDF
Website Design Services for Small Businesses.pdf
AI Guide for Business Growth - Arna Softech
AI-Powered Threat Modeling: The Future of Cybersecurity by Arun Kumar Elengov...
Monitoring Stack: Grafana, Loki & Promtail
EaseUS PDF Editor Pro 6.2.0.2 Crack with License Key 2025
Patient Appointment Booking in Odoo with online payment
CCleaner 6.39.11548 Crack 2025 License Key
DuckDuckGo Private Browser Premium APK for Android Crack Latest 2025
GSA Content Generator Crack (2025 Latest)
Weekly report ppt - harsh dattuprasad patel.pptx
MCP Security Tutorial - Beginner to Advanced
How to Make Money in the Metaverse_ Top Strategies for Beginners.pdf
Autodesk AutoCAD Crack Free Download 2025
Introduction to Windows Operating System
"Secure File Sharing Solutions on AWS".pptx
Visual explanation of Dijkstra's Algorithm using Python
AI/ML Infra Meetup | Beyond S3's Basics: Architecting for AI-Native Data Access
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
Time Tracking Features That Teams and Organizations Actually Need
Modern SharePoint Intranet Templates That Boost Employee Engagement in 2025.docx
Website Design Services for Small Businesses.pdf

Patterns for JVM languages - Geecon 2014

  • 1. The following presentation is provided under DHMB license (Do Not Hurt My Brain). Lecturer is not responsible for the financial and moral damages resulting from taking too seriously the content of the presentation. Including permanent damage to neurons, reduction of neurotransmitter activity at the molecular level and group dismissal.
  • 5. Because having pet projects is like solving crosswords everyday Or going to a gym Helps your brain to stay in shape
  • 10. source code ↓ target language source code ↓ machine code || interpreter
  • 15. So how does it all work?
  • 16. Diving into the stream
  • 20. local y = 1 x = 1 + y
  • 24. fragment DIGIT : [0-9] ; fragment LETTER : [a-zA-Z] ; String : ''' .*? ''' | '"' .*? '"' ; Number : DIGIT+ ; Name : ( '_' | LETTER ) ( '_' | LETTER | DIGIT )* ; COMMENT : '--' .*? 'n' -> skip ; NL : 'r'? 'n' -> skip ; WS : [ tf]+ -> skip ;
  • 26. varlist returns [Varlist result] : var {$result = createVarlist($var.result);} ( ',' var {$result = createVarlist($result,$var.result);} )* ; // var returns [Var result] : Name { $result = createVariableName($Name.text); } | prefixexp '[' exp ']' | prefixexp '.' Name ;
  • 27. beware of left recursion
  • 29. Interpreter pattern Non terminal nodes Terminal nodes
  • 31. package pl.symentis.lua.grammar; import pl.symentis.lua.runtime.Context; public interface Statement { void execute(Context context); }
  • 32. package pl.symentis.lua.grammar; Import pl.symentis.lua.runtime.Context; public interface Expression<T> { T evaluate(Context ctx); }
  • 33. package pl.symentis.lua.runtime; public interface Context { VariableRef resolveVariable(String name); Scope enterScope(); Scope exitScope(); }
  • 34. package pl.symentis.lua.runtime; public interface Scope { Scope getOuterScope(); VariableRef resolveVariable(String name); void bindVariable(String name, Object value); }
  • 35. Into the forest of syntax tree
  • 36. x = 1
  • 37. public class Literal implements ExpressionNode { public final LuaType value; public Literal(LuaType value) { super(); this.value = value; } @Override public void accept(ExpressionVisitor visitor) { visitor.visit(this); } }
  • 38. public class VariableName extends Var { public final String name; public VariableName(String name) { this.name = name; } @Override public void accept(ExpressionVisitor visitor) { visitor.visit(this); } }
  • 39. public class Assignment implements StatementNode { public final Varlist varlist; public final Explist explist; public Assignment(Varlist varlist, Explist explist) { super(); this.varlist = varlist; this.explist = explist; } @Override public void accept(StatementVisitor visitor) { visitor.visit(this); } }
  • 40. public void visit(Assignment assignment) { InterpreterExpressionVisitor varlist = createExpressionVisitor(); assignment.varlist.accept(varlist); InterpreterExpressionVisitor explist = createExpressionVisitor(); assignment.explist.accept(explist); Iterator<ExpressionNode> iterator = ((List<ExpressionNode>) explist.result()).iterator(); List<VariableRef> vars = (List<VariableRef>) varlist.result(); for (VariableRef variableRef : vars) { if (iterator.hasNext()) { ExpressionNode node = iterator.next(); InterpreterExpressionVisitor exp = createExpressionVisitor(); node.accept(exp); variableRef.set(exp.result()); } else { variableRef.set(LuaNil.Nil); } } }
  • 41. public void visit(Literal literal) { result = literal.value; } public void visit(VariableName variableName) { result = context.resolveVariable(variableName.name); } public void visit(Varlist varlist) { List<VariableRef> refs = new ArrayList<>(); for (Var var : varlist.vars) { var.accept(this); refs.add((VariableRef) result()); } result = refs; }
  • 43. compiler → byte code org.ow2.asm:asm:jar me.qmx.jitescript:jitescript:jar
  • 44. JiteClass jiteClass = new JiteClass(classname, new String[] { p(Script.class) }); jiteClass.defineDefaultConstructor(); CodeBlock codeBlock = newCodeBlock(); // bind context into current runtime codeBlock.aload(1); codeBlock.invokestatic(p(RuntimeContext.class), "enterContext", sig(void.class, Context.class)); // parse file and start to walk through AST visitor StatementNode chunk = parseScript(readFileToString(script)); // generate byte code chunk.accept(new CompilerStatementVisitor(codeBlock, new HashSymbolTable())); codeBlock.voidreturn(); jiteClass.defineMethod("execute", JiteClass.ACC_PUBLIC, sig(void.class, new Class[] { Context.class }), codeBlock); return jiteClass.toBytes(JDKVersion.V1_8); }
  • 45. JiteClass jiteClass = new JiteClass(classname, new String[] { p(Script.class) }); jiteClass.defineDefaultConstructor(); CodeBlock codeBlock = newCodeBlock(); // bind context into current runtime codeBlock.aload(1); codeBlock.invokestatic(p(RuntimeContext.class), "enterContext", sig(void.class, Context.class)); // parse file and start to walk through AST visitor StatementNode chunk = parseScript(readFileToString(script)); // generate byte code chunk.accept(new CompilerStatementVisitor(codeBlock, new HashSymbolTable())); codeBlock.voidreturn(); jiteClass.defineMethod("execute", JiteClass.ACC_PUBLIC, sig(void.class, new Class[] { Context.class }), codeBlock); return jiteClass.toBytes(JDKVersion.V1_8); }
  • 46. JiteClass jiteClass = new JiteClass(classname, new String[] { p(Script.class) }); jiteClass.defineDefaultConstructor(); CodeBlock codeBlock = newCodeBlock(); // bind context into current runtime codeBlock.aload(1); codeBlock.invokestatic(p(RuntimeContext.class), "enterContext", sig(void.class, Context.class)); // parse file and start to walk through AST visitor StatementNode chunk = parseScript(readFileToString(script)); // generate byte code chunk.accept(new CompilerStatementVisitor(codeBlock, new HashSymbolTable())); codeBlock.voidreturn(); jiteClass.defineMethod("execute", JiteClass.ACC_PUBLIC, sig(void.class, new Class[] { Context.class }), codeBlock); return jiteClass.toBytes(JDKVersion.V1_8); }
  • 47. x = 1
  • 48. public void visit(Assignment assignment) { Explist explist = assignment.explist; Varlist varlist = assignment.varlist; Iterator<Var> vars = varlist.vars.iterator(); for (ExpressionNode exp : explist.expressions) { exp.accept(new CompilerExpressionVisitor(codeBlock, symbolTable)); CompilerExpressionVisitor visitor = new CompilerExpressionVisitor( codeBlock, symbolTable); vars.next().accept(visitor); String varName = (String) visitor.result(); codeBlock.astore(symbolTable.index(varName)); } }
  • 49. public void visit(Literal literal) { Object object = literal.value.asObject(); codeBlock.ldc(object); // box object into Lua type if (object instanceof Integer) { codeBlock.invokestatic(p(Integer.class), "valueOf", sig(Integer.class, int.class)); } else if (object instanceof Double) { codeBlock.invokestatic(p(Double.class), "valueOf", sig(Double.class, double.class)); } codeBlock.invokestatic(p(LuaTypes.class), "valueOf", sig(LuaType.class, Object.class)); } public void visit(VariableName variableName) { result = variableName.name; }
  • 50. When writing bytecode compiler it helps to think about Java code But at the end you need to think like stack machine :)
  • 51. .method public execute : (Lpl/symentis/lua4j/runtime/Context;)V ; method code size: 21 bytes .limit stack 2 .limit locals 3 aload_1 invokestatic pl/symentis/lua4j/compiler/RuntimeContext enterContext (Lpl/symentis/lua4j/runtime/Context;)V ldc2_w 1.0 invokestatic java/lang/Double valueOf (D)Ljava/lang/Double; invokestatic pl/symentis/lua4j/types/LuaTypes valueOf [_28] astore_2 aload_2 return .end method
  • 52. Symbol table maps variable local to its symbolic name
  • 55. Var var = functionCall.var; CompilerExpressionVisitor visitor = new CompilerExpressionVisitor(codeBlock, symbolTable); var.accept(visitor); String functionName = (String) visitor.result(); Args args = functionCall.args; visitor = new CompilerExpressionVisitor(codeBlock, symbolTable); args.accept(visitor); Integer argNumber = (Integer) visitor.result(); Class<?>[] paramTypeArr = new Class[argNumber]; fill(paramTypeArr, LuaType.class); codeBlock.invokedynamic(functionName, sig(void.class, paramTypeArr), Lua4JDynamicBootstrap.HANDLE, new Object[] {});
  • 56. static final Handle HANDLE = new Handle( CodeBlock.H_INVOKESTATIC, p(Lua4JDynamicBootstrap.class), "bootstrap", sig(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class));
  • 57. public static CallSite bootstrap( MethodHandles.Lookup lookup, String name, MethodType type) throws Throwable { Context context = currentContext(); MethodHandle target=lookup.findStatic(BasicFunctions.class,name, methodType( LuaType.class, Context.class, LuaType[].class)); target = MethodHandles.insertArguments(handler, 0, context) .asCollector(LuaType[].class, type.parameterCount()); return new ConstantCallSite(target.asType(type)); }
  • 58. https://github.com/headius/invokebinder A Java DSL for binding method handles forward, rather than backward https://github.com/projectodd/rephract Another Java DSL for invokedynamic
  • 59. What's next? graal + truffle dynamic compiler + AST interpreter
  • 61. Let the eternal stream of bytecode flow through your body
  • 62. Q&A