# Thesis notes
I came with several ideas to how implement the problem
1. generate bytes in the straight way
2. use library that can generate classes
https://github.com/raphw/byte-buddy/blob/master/README.md
http://jni4net.com - call java methods from C#
https://androidpaksquestions.blogspot.com/2016/04/step-by-step-java-jar-to-c-binding.html
https://docs.microsoft.com/en-us/xamarin/android/platform/binding-java-library/
https://www.baeldung.com/java-asm - Guide to Java Bytecode manipulation with ASM
https://asm.ow2.io/asm4-guide.pdf - ASM documentation and tutorials [pdf]
https://github.com/saroff - the guy that previously made a thesis with similar topic
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-3.html - some oracel documentation that might be useful
https://stackoverflow.com/questions/29404600/java-bytecode-generation - question of the guy
https://bytebuddy.net/#/ - another library for code generation Byte Buddy
https://dzone.com/articles/generating-bytecode
http://www.egtry.com/java/bytecode/asm/Hello - Hello World ASM tutorial
http://www.egtry.com/java/index.html - куча примеров с ASM
http://web.cs.ucla.edu/~msb/cs239-tutorial/ - еще туториал и объяснение ASM
https://www.tiobe.com/tiobe-index/ - language rating
I always use shadow types
## Add two integers
### Slang
``` Scala
AddTwoIntegers(a: Integer, b: Integer): Integer do
c is Integer
c := a + b
return c
end
```
### Opcodes
```
iload_0
iload_1
iadd
istore_2
iload_2
ireturn
```
### Java ASM
``` Java
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "addTwoIntegers", "(Ljava/lang/Integer;Ljava/lang/Integer;)java/lang/Integer", null, null);
mv.visitCode();
mv.visitVarInsn(ILOAD, 0);
mv.visitVarInsn(ILOAD, 1);
mv.visitInsn(IADD);
mv.visitVarInsn(ISTORE, 2);
mv.visitVarInsn(ILOAD, 2);
mv.visitInsn(IRETURN);
mv.visitMaxs(3, 3);
mv.visitEnd();
```
### Java generated code
``` Java
public static Long addTwoIntegers(Integer var0, Integer var1) {
Object var2 = var0 + var1;
return (Integer)var2;
}
```
<!--
## Subtract two integers
### Slang
``` Scala
SubtractTwoIntegers(a: Integer, b: Integer): Integer do
c is Integer
c := a - b
return c
end
```
### Opcodes
```
iload_0
iload_1
isub
istore_2
iload_2
ireturn
```
### Java ASM
``` Java
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "subtractTwoIntegers", "(Ljava/lang/Integer;Ljava/lang/Integer;)java/lang/Integer", null, null);
mv.visitCode();
mv.visitVarInsn(ILOAD, 0);
mv.visitVarInsn(ILOAD, 1);
mv.visitInsn(ISUB);
mv.visitVarInsn(ISTORE, 2);
mv.visitVarInsn(ILOAD, 2);
mv.visitInsn(IRETURN);
mv.visitMaxs(3, 3);
mv.visitEnd();
```
### Java generated code
``` Java
public static Integer addTwoIntegers(Integer var0, Integer var1) {
Object var2 = var0 - var1;
return (Integer)var2;
}
```
## Add two Reals
For real in Slang - Double in Java
### Slang
``` Scala
AddTwoReals(a: Real, b: Real): Real do
c is Real
c := a + b
return c
end
```
### Opcodes
```
dload_0
dload_1
dadd
dstore_2
dload_2
dreturn
```
### Java ASM
``` Java
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "addTwoReals", "(Ljava/lang/Double;Ljava/lang/Double;)java/lang/Double", null, null);
mv.visitCode();
mv.visitVarInsn(DLOAD, 0);
mv.visitVarInsn(DLOAD, 1);
mv.visitInsn(DADD);
mv.visitVarInsn(DSTORE, 2);
mv.visitVarInsn(DLOAD, 2);
mv.visitInsn(DRETURN);
mv.visitMaxs(3, 3);
mv.visitEnd();
```
### Java generated code
``` Java
public static Double addTwoReals(Double var0, Double var1) {
Object var2 = var0 + var1;
return (Double)var2;
}
```
## Subtract two Reals
``` Scala
SubtractTwoReals(a: Real, b: Real): Real do
c is Real
c := a - b
return c
end
```
### Opcodes
```
dload_0
dload_1
dsub
dstore_2
dload_2
dreturn
```
### Java ASM
``` Java
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "subtractTwoReals", "(Ljava/lang/Double;Ljava/lang/Double;)java/lang/Double", null, null);
mv.visitCode();
mv.visitVarInsn(DLOAD, 0);
mv.visitVarInsn(DLOAD, 1);
mv.visitInsn(DSUB);
mv.visitVarInsn(DSTORE, 2);
mv.visitVarInsn(DLOAD, 2);
mv.visitInsn(DRETURN);
mv.visitMaxs(3, 3);
mv.visitEnd();
```
### Java generated code
``` Java
public static Double subtractTwoReals(Double var0, Double var1) {
Object var2 = var0 - var1;
return (Double)var2;
}
```
-->
## Simple Unit declaration
### Slang
``` Scala
unit SimpleObject
value: Integer
init(value: Integer) do
this.value = value
end
end
```
### Opcode
TODO
```
aload_0
iload_1
putfield
return
```
### Java ASM
``` Java
ClassWriter cw = new ClassWriter(0);
cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, "gen/SimpleObject", null, "java/lang/Object", null);
cw.visitField(ACC_PUBLIC, "value", "Ljava/lang/Integer;", null, null).visitEnd();
//default constructor
{
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(Ljava/lang/Integer;)V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ILOAD, 1);
mv.visitFieldInsn(PUTFIELD, "gen/SimpleObject", "value", "Ljava/lang/Integer;");
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
cw.visitEnd();
```
### Java generated code
``` Java
package gen;
public class SimpleObject {
public Integer value;
public SimpleObject(Integer var1) {
this.value = var1;
}
}
```
## Working with several units
### Slang
``` Scala
AddTwoObjects(a: SimpleObject, b: SimpleObject): SimpleObject do
c is SimpleObject
cTemp is Integer
cTemp := a.value + b.value
c := SimpleObject(cTemp)
return c
end
```
### Opcode
```
aload_1
getfield
isore_3
aload_2
getfield
istore_4
iload_3
iload_4
iadd
istore_5
new
dup
iload_5
invokespecial
areturn
```
### Java ASM
``` Java
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "AddTwoObjects", "(Lgen/SimpleObject;Lgen/SimpleObject;)gen/SimpleObject", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 1);
mv.visitFieldInsn(GETFIELD, "gen/SimpleObject", "value", "Ljava/lang/Integer;");
mv.visitVarInsn(ISTORE, 3);
mv.visitVarInsn(ALOAD, 2);
mv.visitFieldInsn(GETFIELD, "gen/SimpleObject", "value", "Ljava/lang/Integer;");
mv.visitVarInsn(ISTORE, 4);
mv.visitVarInsn(ILOAD, 3);
mv.visitVarInsn(ILOAD, 4);
mv.visitInsn(IADD);
mv.visitVarInsn(ISTORE, 5);
mv.visitTypeInsn(NEW, "Lgen/SimpleObject;");
mv.visitInsn(DUP);
mv.visitVarInsn(ILOAD,5);
mv.visitMethodInsn(INVOKESPECIAL, "gen/SimpleObject", "<init>", "(Ljava/lang/Integer;)V");
mv.visitInsn(ARETURN);
mv.visitEnd();
```
### Java generated code
``` Java
public SimpleObject AddTwoObjects(SimpleObject var1, SimpleObject var2) {
Integer var3 = var1.value;
Integer var4 = var2.value;
Object var5 = var3 + var4;
return new SimpleObject((Integer)var5);
}
```
## Boolean check
### Slang
``` Scala
a is Integer
b is Integer
c is Boolean
a := 1
b := a + 2
c := a == b
```
### Opcode
```
TODO
iconst_1
invokestatic
astore_1
iconst_2
aload_1
invokevirtual
iadd
invokestatic
astore_2
aload_1
aload_2
//label 3
if_acmpne label3
iconst_1
//label 4
goto label4
//visit label 3
f_append//CHECK
iconst_0
//visit label 4
invokestatic
asstore_3
return
```
### Java ASM
``` Java
methodVisitor.visitInsn(ICONST_1);
methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
methodVisitor.visitVarInsn(ASTORE, 1);
methodVisitor.visitInsn(ICONST_2);
methodVisitor.visitVarInsn(ALOAD, 1);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
methodVisitor.visitInsn(IADD);
methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
methodVisitor.visitVarInsn(ASTORE, 2);
methodVisitor.visitVarInsn(ALOAD, 1);
methodVisitor.visitVarInsn(ALOAD, 2);
Label label3 = new Label();
methodVisitor.visitJumpInsn(IF_ACMPNE, label3);
methodVisitor.visitInsn(ICONST_1);
Label label4 = new Label();
methodVisitor.visitJumpInsn(GOTO, label4);
methodVisitor.visitLabel(label3);
methodVisitor.visitFrame(Opcodes.F_APPEND, 2, new Object[]{"java/lang/Integer", "java/lang/Integer"}, 0, null);
methodVisitor.visitInsn(ICONST_0);
methodVisitor.visitLabel(label4);
methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
methodVisitor.visitVarInsn(ASTORE, 3);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(2, 4);
methodVisitor.visitEnd();
```
### Java generated code
``` Java
Integer var1 = 1;
Integer var2 = 2 + var1;
Boolean var3 = var1 == var2;
```
## Loop
## IfElse
# Complex Cases
## Fibonacci
### Slang
``` Scala
fib_recursive(n: Integer): Integer do
if n < 2 do
return n
else
return recursive(n - 1) + recursive(n - 2)
end
end
// optimized speed, but increased memory consumption
fib_recursive_memo(n: Integer): Integer do
inner(prvprv: Integer, prv: Integer, c Integer): Integer do
if c < 1 do
return prvprv
else do
return inner(prv, prvprv + prv, c - 1)
end
end
return inner(0, 1, n)
end
fib_iterative(n: Integer): Integer do
current is 0
next is 1
temp: Integer
require n > 0 do
n = n - 1
temp = current + next
current = next
next = temp
end
return next
end
```
### Opcode
```
//fib_recursive
```
### Java ASM
``` Java
{ //fib_recursive
methodVisitor = classWriter.visitMethod(0, "fib_recursive", "(Ljava/lang/Integer;)Ljava/lang/Integer;", null, null);
methodVisitor.visitCode();
Label label0 = new Label();
methodVisitor.visitLabel(label0);
methodVisitor.visitLineNumber(6, label0);
methodVisitor.visitVarInsn(ALOAD, 1);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
methodVisitor.visitInsn(ICONST_2);
Label label1 = new Label();
methodVisitor.visitJumpInsn(IF_ICMPGE, label1);
Label label2 = new Label();
methodVisitor.visitLabel(label2);
methodVisitor.visitLineNumber(7, label2);
methodVisitor.visitVarInsn(ALOAD, 1);
methodVisitor.visitInsn(ARETURN);
methodVisitor.visitLabel(label1);
methodVisitor.visitLineNumber(9, label1);
methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
methodVisitor.visitVarInsn(ALOAD, 0);
methodVisitor.visitVarInsn(ALOAD, 1);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
methodVisitor.visitInsn(ICONST_1);
methodVisitor.visitInsn(ISUB);
methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "gen/Fibonacci", "fib_recursive", "(Ljava/lang/Integer;)Ljava/lang/Integer;", false);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
methodVisitor.visitVarInsn(ALOAD, 0);
methodVisitor.visitVarInsn(ALOAD, 1);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
methodVisitor.visitInsn(ICONST_2);
methodVisitor.visitInsn(ISUB);
methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "gen/Fibonacci", "fib_recursive", "(Ljava/lang/Integer;)Ljava/lang/Integer;", false);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
methodVisitor.visitInsn(IADD);
methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
methodVisitor.visitInsn(ARETURN);
Label label3 = new Label();
methodVisitor.visitLabel(label3);
methodVisitor.visitLocalVariable("this", "Lgen/Fibonacci;", null, label0, label3, 0);
methodVisitor.visitLocalVariable("n", "Ljava/lang/Integer;", null, label0, label3, 1);
methodVisitor.visitMaxs(4, 2);
methodVisitor.visitEnd();
}
{
methodVisitor = classWriter.visitMethod(ACC_PRIVATE, "inner", "(Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer;", null, null);
methodVisitor.visitCode();
Label label0 = new Label();
methodVisitor.visitLabel(label0);
methodVisitor.visitLineNumber(13, label0);
methodVisitor.visitVarInsn(ALOAD, 3);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
methodVisitor.visitInsn(ICONST_1);
Label label1 = new Label();
methodVisitor.visitJumpInsn(IF_ICMPGE, label1);
Label label2 = new Label();
methodVisitor.visitLabel(label2);
methodVisitor.visitLineNumber(14, label2);
methodVisitor.visitVarInsn(ALOAD, 1);
methodVisitor.visitInsn(ARETURN);
methodVisitor.visitLabel(label1);
methodVisitor.visitLineNumber(16, label1);
methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
methodVisitor.visitVarInsn(ALOAD, 0);
methodVisitor.visitVarInsn(ALOAD, 2);
methodVisitor.visitVarInsn(ALOAD, 1);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
methodVisitor.visitVarInsn(ALOAD, 2);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
methodVisitor.visitInsn(IADD);
methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
methodVisitor.visitVarInsn(ALOAD, 3);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
methodVisitor.visitInsn(ICONST_1);
methodVisitor.visitInsn(ISUB);
methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
methodVisitor.visitMethodInsn(INVOKESPECIAL, "gen/Fibonacci", "inner", "(Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer;", false);
methodVisitor.visitInsn(ARETURN);
Label label3 = new Label();
methodVisitor.visitLabel(label3);
methodVisitor.visitLocalVariable("this", "Lgen/Fibonacci;", null, label0, label3, 0);
methodVisitor.visitLocalVariable("prvprv", "Ljava/lang/Integer;", null, label0, label3, 1);
methodVisitor.visitLocalVariable("prv", "Ljava/lang/Integer;", null, label0, label3, 2);
methodVisitor.visitLocalVariable("c", "Ljava/lang/Integer;", null, label0, label3, 3);
methodVisitor.visitMaxs(5, 4);
methodVisitor.visitEnd();
}
{
methodVisitor = classWriter.visitMethod(0, "fib_recursive_memo", "(Ljava/lang/Integer;)Ljava/lang/Integer;", null, null);
methodVisitor.visitCode();
Label label0 = new Label();
methodVisitor.visitLabel(label0);
methodVisitor.visitLineNumber(20, label0);
methodVisitor.visitVarInsn(ALOAD, 0);
methodVisitor.visitInsn(ICONST_0);
methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
methodVisitor.visitInsn(ICONST_1);
methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
methodVisitor.visitVarInsn(ALOAD, 1);
methodVisitor.visitMethodInsn(INVOKESPECIAL, "gen/Fibonacci", "inner", "(Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer;", false);
methodVisitor.visitInsn(ARETURN);
Label label1 = new Label();
methodVisitor.visitLabel(label1);
methodVisitor.visitLocalVariable("this", "Lgen/Fibonacci;", null, label0, label1, 0);
methodVisitor.visitLocalVariable("n", "Ljava/lang/Integer;", null, label0, label1, 1);
methodVisitor.visitMaxs(4, 2);
methodVisitor.visitEnd();
}
{
methodVisitor = classWriter.visitMethod(0, "fib_iterative", "(Ljava/lang/Integer;)Ljava/lang/Integer;", null, null);
methodVisitor.visitCode();
Label label0 = new Label();
methodVisitor.visitLabel(label0);
methodVisitor.visitLineNumber(24, label0);
methodVisitor.visitInsn(ICONST_0);
methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
methodVisitor.visitVarInsn(ASTORE, 2);
Label label1 = new Label();
methodVisitor.visitLabel(label1);
methodVisitor.visitLineNumber(25, label1);
methodVisitor.visitInsn(ICONST_1);
methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
methodVisitor.visitVarInsn(ASTORE, 3);
Label label2 = new Label();
methodVisitor.visitLabel(label2);
methodVisitor.visitLineNumber(26, label2);
methodVisitor.visitInsn(ACONST_NULL);
methodVisitor.visitVarInsn(ASTORE, 4);
Label label3 = new Label();
methodVisitor.visitLabel(label3);
methodVisitor.visitLineNumber(28, label3);
methodVisitor.visitFrame(Opcodes.F_APPEND,3, new Object[] {"java/lang/Integer", "java/lang/Integer", "java/lang/Integer"}, 0, null);
methodVisitor.visitVarInsn(ALOAD, 1);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
Label label4 = new Label();
methodVisitor.visitJumpInsn(IFLE, label4);
Label label5 = new Label();
methodVisitor.visitLabel(label5);
methodVisitor.visitLineNumber(29, label5);
methodVisitor.visitVarInsn(ALOAD, 1);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
methodVisitor.visitInsn(ICONST_1);
methodVisitor.visitInsn(ISUB);
methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
methodVisitor.visitVarInsn(ASTORE, 1);
Label label6 = new Label();
methodVisitor.visitLabel(label6);
methodVisitor.visitLineNumber(30, label6);
methodVisitor.visitVarInsn(ALOAD, 2);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
methodVisitor.visitVarInsn(ALOAD, 3);
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
methodVisitor.visitInsn(IADD);
methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
methodVisitor.visitVarInsn(ASTORE, 4);
Label label7 = new Label();
methodVisitor.visitLabel(label7);
methodVisitor.visitLineNumber(31, label7);
methodVisitor.visitVarInsn(ALOAD, 3);
methodVisitor.visitVarInsn(ASTORE, 2);
Label label8 = new Label();
methodVisitor.visitLabel(label8);
methodVisitor.visitLineNumber(32, label8);
methodVisitor.visitVarInsn(ALOAD, 4);
methodVisitor.visitVarInsn(ASTORE, 3);
methodVisitor.visitJumpInsn(GOTO, label3);
methodVisitor.visitLabel(label4);
methodVisitor.visitLineNumber(35, label4);
methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
methodVisitor.visitVarInsn(ALOAD, 3);
methodVisitor.visitInsn(ARETURN);
Label label9 = new Label();
methodVisitor.visitLabel(label9);
methodVisitor.visitLocalVariable("this", "Lgen/Fibonacci;", null, label0, label9, 0);
methodVisitor.visitLocalVariable("n", "Ljava/lang/Integer;", null, label0, label9, 1);
methodVisitor.visitLocalVariable("current", "Ljava/lang/Integer;", null, label1, label9, 2);
methodVisitor.visitLocalVariable("next", "Ljava/lang/Integer;", null, label2, label9, 3);
methodVisitor.visitLocalVariable("temp", "Ljava/lang/Integer;", null, label3, label9, 4);
methodVisitor.visitMaxs(2, 5);
methodVisitor.visitEnd();
}
```
##