Skip to content

Commit

Permalink
Merge pull request #30 from kindlich/master
Browse files Browse the repository at this point in the history
Continue statement | Array<->List cast | ReturnsSelf
  • Loading branch information
kindlich authored Aug 30, 2019
2 parents 2406f97 + fb8bac7 commit b88317d
Show file tree
Hide file tree
Showing 10 changed files with 245 additions and 44 deletions.
2 changes: 2 additions & 0 deletions src/main/java/stanhebben/zenscript/ZenTokener.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public class ZenTokener extends TokenStream {
public static final int T_VAL = 127;
public static final int T_WHILE = 128;
public static final int T_BREAK = 129;
public static final int T_CONTINUE = 130;
public static final int T_NULL = 140;
public static final int T_TRUE = 141;
public static final int T_FALSE = 142;
Expand Down Expand Up @@ -127,6 +128,7 @@ public class ZenTokener extends TokenStream {
KEYWORDS.put("instanceof", T_INSTANCEOF);
KEYWORDS.put("while", T_WHILE);
KEYWORDS.put("break", T_BREAK);
KEYWORDS.put("continue", T_CONTINUE);

KEYWORDS.put("null", T_NULL);
KEYWORDS.put("true", T_TRUE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,10 @@ public void compile(boolean result, IEnvironmentMethod environment) {
}

method.invokeVirtual(environment.getOutput());
if(method.getReturnType() != ZenType.VOID && !result) {
if(!result && method.getReturnType() != ZenType.VOID) {
environment.getOutput().pop(method.getReturnType().isLarge());
}

if(method instanceof JavaMethod && ((JavaMethod) method).returnsSelf)
} else if(method instanceof JavaMethod && ((JavaMethod) method).returnsSelf) {
environment.getOutput().checkCast(receiver.getType().toASMType().getInternalName());
}
}
}
5 changes: 5 additions & 0 deletions src/main/java/stanhebben/zenscript/statements/Statement.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ public static Statement read(ZenTokener parser, IEnvironmentGlobal environment,
parser.required(T_SEMICOLON, "; expected");
return new StatementBreak(next.getPosition());
}
case T_CONTINUE: {
parser.next();
parser.required(T_SEMICOLON, "; expected");
return new StatementContinue(next.getPosition());
}
}

ZenPosition position = parser.peek().getPosition();
Expand Down
52 changes: 26 additions & 26 deletions src/main/java/stanhebben/zenscript/statements/StatementBreak.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
package stanhebben.zenscript.statements;

import org.objectweb.asm.Label;
import stanhebben.zenscript.compiler.IEnvironmentMethod;
import stanhebben.zenscript.util.ZenPosition;

public class StatementBreak extends Statement {

private Label exit;

public StatementBreak(ZenPosition position) {
super(position);
}

public void setExit(Label exit) {
this.exit = exit;
}

@Override
public void compile(IEnvironmentMethod environment) {
if(exit != null)
environment.getOutput().goTo(exit);
else
environment.error(getPosition(), "Skipping break statement as it has no proper label. Only use breaks in loops!");
}
}
package stanhebben.zenscript.statements;

import org.objectweb.asm.Label;
import stanhebben.zenscript.compiler.IEnvironmentMethod;
import stanhebben.zenscript.util.ZenPosition;

public class StatementBreak extends Statement {

private Label exit;

public StatementBreak(ZenPosition position) {
super(position);
}

public void setExit(Label exit) {
this.exit = exit;
}

@Override
public void compile(IEnvironmentMethod environment) {
if(exit != null)
environment.getOutput().goTo(exit);
else
environment.error(getPosition(), "Skipping break statement as it has no proper label. Only use breaks in loops!");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package stanhebben.zenscript.statements;

import org.objectweb.asm.Label;
import stanhebben.zenscript.compiler.IEnvironmentMethod;
import stanhebben.zenscript.util.ZenPosition;

public class StatementContinue extends Statement {

private Label exit;

public StatementContinue(ZenPosition position) {
super(position);
}

public void setExit(Label exit) {
this.exit = exit;
}

@Override
public void compile(IEnvironmentMethod environment) {
if(exit != null)
environment.getOutput().goTo(exit);
else
environment.error(getPosition(), "Skipping continue statement as it has no proper label. Only use them in loops!");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,20 @@ public void compile(IEnvironmentMethod environment) {

Label repeat = new Label();
Label exit = new Label();
Label postIterate = new Label();

//Allows for break statements, sets the exit label!
for (Statement statement : body.getSubStatements()) {
if (statement instanceof StatementBreak)
((StatementBreak) statement).setExit(exit);
else if (statement instanceof StatementContinue)
((StatementContinue) statement).setExit(postIterate);
}

methodOutput.label(repeat);
iterator.compilePreIterate(localVariables, exit);
body.compile(local);
methodOutput.label(postIterate);
iterator.compilePostIterate(localVariables, exit, repeat);
methodOutput.label(exit);
iterator.compileEnd();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

import org.objectweb.asm.Label;
import stanhebben.zenscript.compiler.IEnvironmentMethod;
import stanhebben.zenscript.type.*;
import stanhebben.zenscript.type.ZenType;
import stanhebben.zenscript.type.ZenTypeArrayBasic;
import stanhebben.zenscript.type.ZenTypeArrayList;
import stanhebben.zenscript.util.MethodOutput;

import java.util.*;
import java.util.Collection;
import java.util.List;

/**
* @author Stan
Expand All @@ -24,7 +27,13 @@ public CastingRuleListArray(ICastingRule base, ZenTypeArrayList from, ZenTypeArr

@Override
public void compile(IEnvironmentMethod method) {
if (base == null)
compileNoConversion(method.getOutput());
else
compileWithConversion(method);
}

private void compileWithConversion(IEnvironmentMethod method) {
final MethodOutput methodOutput = method.getOutput();
methodOutput.iConst0();
final int localCounter = methodOutput.local(int.class);
Expand All @@ -49,8 +58,8 @@ public void compile(IEnvironmentMethod method) {
methodOutput.loadInt(localCounter);

methodOutput.invokeInterface(List.class, "get", Object.class, int.class);
if(base != null)
base.compile(method);
methodOutput.checkCast(from.getBaseType().toASMType().getInternalName());
base.compile(method);
methodOutput.loadObject(localArray);
methodOutput.swap();
methodOutput.loadInt(localCounter);
Expand All @@ -60,9 +69,21 @@ public void compile(IEnvironmentMethod method) {
methodOutput.iinc(localCounter);
methodOutput.goTo(start);
methodOutput.label(end);

methodOutput.pop();
methodOutput.pop();
methodOutput.loadObject(localArray);
}


private void compileNoConversion(MethodOutput methodOutput) {
methodOutput.iConst0();
methodOutput.newArray(to.getBaseType().toASMType());

methodOutput.invokeInterface(Collection.class, "toArray", Object[].class, Object[].class);
methodOutput.checkCast(to.toJavaClass());
}

@Override
public ZenType getInputType() {
return from;
Expand Down
10 changes: 9 additions & 1 deletion src/test/java/stanhebben/zenscript/TestHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@

@SuppressWarnings("WeakerAccess")
public class TestHelper {


/**Should log the print statements to console?*/
private static final boolean debug = false;

public static List<String> prints = new LinkedList<>();
public static GenericRegistry registry;
public static TestErrorLogger logger;
Expand All @@ -31,9 +34,14 @@ public static void setupEnvironment() {
logger = new TestErrorLogger();
registry = new GenericRegistry(compileEnvironment, logger);
registry.registerGlobal("print", registry.getStaticFunction(TestHelper.class, "print", String.class));

//Generic Environment does not check for types when it checks names, hence importing the type root
registry.registerGlobal("root", registry.getRoot());
}

public static void print(String s) {
if(debug)
System.out.println("[Print] " + s);
prints.add(s);
}

Expand Down
109 changes: 100 additions & 9 deletions src/test/java/stanhebben/zenscript/tests/TestArrayCasts.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,60 +5,151 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import stanhebben.zenscript.TestHelper;
import stanhebben.zenscript.annotations.ZenCaster;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenConstructor;

import static stanhebben.zenscript.TestAssertions.assertMany;

public class TestArrayCasts {

@BeforeAll
public static void setupEnvironment() {
TestHelper.setupEnvironment();
TestHelper.registry.registerNativeClass(A.class);
TestHelper.registry.registerNativeClass(B.class);
}

@BeforeEach
public void beforeEach() {
TestHelper.beforeEach();
}

@Test
public void testCastAtDeclaration() {
TestHelper.run("var x = [1.0f, 2.0f, 3.0f] as double[]; for i in x print(i);");
assertMany("1.0", "2.0", "3.0");
}

@Test
public void testCastAtDeclaration2() {
TestHelper.run("var x = [0x001, 0x002, 0x003] as double[]; for i in x print(i);");
assertMany("1.0", "2.0", "3.0");
}

@Test
public void testCastAfterDeclaration() {
TestHelper.run("var x = [1.0f, 2.0f, 3.0f] as float[]; var y = x as double[]; for i in y print(i);");
assertMany("1.0", "2.0", "3.0");
}

@Test
public void testCastAfterDeclaration_nonLarge_large() {
TestHelper.run("var x = [0x001, 0x002, 0x003] as int[]; var y = x as double[]; for i in y print(i);");
assertMany("1.0", "2.0", "3.0");
}

@Test
public void testCastAfterDeclaration_nonLarge_nonLarge() {
TestHelper.run("var x = [0x001, 0x002, 0x003] as int[]; var y = x as float[]; for i in y print(i);");
assertMany("1.0", "2.0", "3.0");
}

@Test
public void testCastAfterDeclaration_large_nonLarge() {
TestHelper.run("var x = [1.0D, 2.0D, 3.0D] as double[]; var y = x as int[]; for i in y print(i);");
assertMany("1", "2", "3");
}

@Test
public void testCastAfterDeclaration_large_large() {
TestHelper.run("var x = [1.0D, 2.0D, 3.0D] as double[]; var y = x as long[]; for i in y print(i);");
assertMany("1", "2", "3");
}

@Test
public void testCastArrayArray_B_A() {
TestHelper.run("import root.tests.B; import root.tests.A; var x = [B('1'), B('2'), B('3')] as B[]; var y = x as A[]; for i in y print(i);");
assertMany("1", "2", "3");
}

@Test
public void testCastArray2List() {
TestHelper.run("var x = ['1', '2', '3'] as string[]; var y = x as [string]; for i in y print(i);");
assertMany("1", "2", "3");
}

@Test
public void testCastList2Array() {
TestHelper.run("var x = ['1', '2', '3'] as [string]; var y = x as string[]; for i in y print(i);");
assertMany("1", "2", "3");
}

@Test
public void testCastArray2List_A_String() {
TestHelper.run("import root.tests.B; var x = [B('1'), B('2'), B('3')] as B[]; var y = x as [string]; for i in y print(i);");
assertMany("1", "2", "3");
}

@Test
public void testCastArray2List_A_B() {
TestHelper.run("import root.tests.B; import root.tests.A; var x = [B('1'), B('2'), B('3')] as B[]; var y = x as [A]; for i in y print(i);");
assertMany("1", "2", "3");
}

@Test
public void testCastListList_B_A() {
TestHelper.run("import root.tests.B; import root.tests.A; var x = [B('1'), B('2'), B('3')] as [B]; var y = x as [A]; for i in y print(i);");
assertMany("1", "2", "3");
}

@Test
public void testCastListArray_B_A() {
TestHelper.run("import root.tests.B; import root.tests.A; var x = [B('1'), B('2'), B('3')] as [B]; var y = x as A[]; for i in y print(i);");
assertMany("1", "2", "3");
}


@ZenClass("tests.A")
public static class A {
private final String s;

@ZenConstructor
public A(String s) {
this.s = s;
}

@Override
@ZenCaster()
public String toString() {
return s;
}

@ZenCaster
public B asB() {
return new B(s);
}
}

@ZenClass("tests.B")
public static class B {
final String s;

@ZenConstructor
public B(String s) {
this.s = s;
}

@Override
@ZenCaster()
public String toString() {
return s;
}

@ZenCaster
public A asA() {
return new A(s);
}
}

}
Loading

0 comments on commit b88317d

Please sign in to comment.