From 792b6efd127af6f8a0fdc906fc3afcf990dbb902 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 31 Dec 2020 02:30:41 -0700 Subject: [PATCH] allow data to be returned --- .../terra/api/structures/parser/Parser.java | 10 ++--- .../api/structures/parser/ParserUtil.java | 3 ++ .../api/structures/parser/lang/Block.java | 30 ++++++++++--- .../lang/functions/def/DefinedFunction.java | 34 ++++++++++++++ .../lang/functions/def/FunctionBlock.java | 44 +++++++++++++++++++ .../keywords/{ => flow}/BreakKeyword.java | 2 +- .../keywords/{ => flow}/ContinueKeyword.java | 2 +- .../lang/keywords/{ => flow}/FailKeyword.java | 2 +- .../keywords/{ => flow}/ReturnKeyword.java | 2 +- .../lang/keywords/looplike/ForKeyword.java | 12 ++--- .../lang/keywords/looplike/IfKeyword.java | 6 +-- .../lang/keywords/looplike/WhileKeyword.java | 12 ++--- .../structures/script/StructureScript.java | 8 ++-- 13 files changed, 133 insertions(+), 34 deletions(-) create mode 100644 common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/def/DefinedFunction.java create mode 100644 common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/def/FunctionBlock.java rename common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/{ => flow}/BreakKeyword.java (92%) rename common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/{ => flow}/ContinueKeyword.java (92%) rename common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/{ => flow}/FailKeyword.java (92%) rename common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/{ => flow}/ReturnKeyword.java (92%) diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java index 341915b08..5d4509aa5 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java @@ -14,10 +14,10 @@ import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.api.structures.parser.lang.functions.builtin.AbsFunction; import com.dfsek.terra.api.structures.parser.lang.functions.builtin.PowFunction; import com.dfsek.terra.api.structures.parser.lang.functions.builtin.SqrtFunction; -import com.dfsek.terra.api.structures.parser.lang.keywords.BreakKeyword; -import com.dfsek.terra.api.structures.parser.lang.keywords.ContinueKeyword; -import com.dfsek.terra.api.structures.parser.lang.keywords.FailKeyword; -import com.dfsek.terra.api.structures.parser.lang.keywords.ReturnKeyword; +import com.dfsek.terra.api.structures.parser.lang.keywords.flow.BreakKeyword; +import com.dfsek.terra.api.structures.parser.lang.keywords.flow.ContinueKeyword; +import com.dfsek.terra.api.structures.parser.lang.keywords.flow.FailKeyword; +import com.dfsek.terra.api.structures.parser.lang.keywords.flow.ReturnKeyword; import com.dfsek.terra.api.structures.parser.lang.keywords.looplike.ForKeyword; import com.dfsek.terra.api.structures.parser.lang.keywords.looplike.IfKeyword; import com.dfsek.terra.api.structures.parser.lang.keywords.looplike.WhileKeyword; @@ -188,7 +188,7 @@ public class Parser { } private ForKeyword parseForLoop(TokenHolder tokens, Map> old, Position start) throws ParseException { - Map> variableMap = new HashMap<>(old); + Map> variableMap = new HashMap<>(old); // New scope Token f = tokens.get(); ParserUtil.checkType(f, Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.IDENTIFIER); Item initializer; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/ParserUtil.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/ParserUtil.java index e42349ac1..0462d630c 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/ParserUtil.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/ParserUtil.java @@ -13,6 +13,7 @@ public class ParserUtil { private static final Map> PRECEDENCE = new HashMap<>(); private static final List ARITHMETIC = Arrays.asList(Token.Type.ADDITION_OPERATOR, Token.Type.SUBTRACTION_OPERATOR, Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR); + private static final List COMPARISON = Arrays.asList(Token.Type.EQUALS_OPERATOR, Token.Type.NOT_EQUALS_OPERATOR, Token.Type.LESS_THAN_OPERATOR, Token.Type.LESS_THAN_OR_EQUALS_OPERATOR, Token.Type.GREATER_THAN_OPERATOR, Token.Type.GREATER_THAN_OR_EQUALS_OPERATOR); static { // Setup precedence PRECEDENCE.put(Token.Type.ADDITION_OPERATOR, Arrays.asList(Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR)); @@ -23,6 +24,8 @@ public class ParserUtil { PRECEDENCE.put(Token.Type.GREATER_THAN_OR_EQUALS_OPERATOR, ARITHMETIC); PRECEDENCE.put(Token.Type.LESS_THAN_OPERATOR, ARITHMETIC); PRECEDENCE.put(Token.Type.LESS_THAN_OR_EQUALS_OPERATOR, ARITHMETIC); + PRECEDENCE.put(Token.Type.BOOLEAN_AND, COMPARISON); + PRECEDENCE.put(Token.Type.BOOLEAN_OR, COMPARISON); } public static void checkType(Token token, Token.Type... expected) throws ParseException { diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Block.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Block.java index de890168e..3bddbbd3b 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Block.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Block.java @@ -7,7 +7,7 @@ import com.dfsek.terra.api.structures.tokenizer.Position; import java.util.List; import java.util.Random; -public class Block implements Item { +public class Block implements Item> { private final List> items; private final Position position; @@ -21,15 +21,15 @@ public class Block implements Item { } @Override - public synchronized ReturnLevel apply(Buffer buffer, Rotation rotation, Random random, int recursions) { + public synchronized ReturnInfo apply(Buffer buffer, Rotation rotation, Random random, int recursions) { for(Item item : items) { Object result = item.apply(buffer, rotation, random, recursions); - if(result instanceof ReturnLevel) { - ReturnLevel level = (ReturnLevel) result; - if(!level.equals(ReturnLevel.NONE)) return level; + if(result instanceof ReturnInfo) { + ReturnInfo level = (ReturnInfo) result; + if(!level.getLevel().equals(ReturnLevel.NONE)) return level; } } - return ReturnLevel.NONE; + return new ReturnInfo<>(ReturnLevel.NONE, null); } @Override @@ -37,6 +37,24 @@ public class Block implements Item { return position; } + public static class ReturnInfo { + private final ReturnLevel level; + private final T data; + + public ReturnInfo(ReturnLevel level, T data) { + this.level = level; + this.data = data; + } + + public ReturnLevel getLevel() { + return level; + } + + public T getData() { + return data; + } + } + public enum ReturnLevel { NONE(false), BREAK(false), CONTINUE(false), RETURN(true), FAIL(true); diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/def/DefinedFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/def/DefinedFunction.java new file mode 100644 index 000000000..a34084104 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/def/DefinedFunction.java @@ -0,0 +1,34 @@ +package com.dfsek.terra.api.structures.parser.lang.functions.def; + +import com.dfsek.terra.api.structures.parser.lang.Block; +import com.dfsek.terra.api.structures.parser.lang.functions.Function; +import com.dfsek.terra.api.structures.structure.Rotation; +import com.dfsek.terra.api.structures.structure.buffer.Buffer; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.Random; + +public abstract class DefinedFunction implements Function { + private final Block block; + private final String name; + + protected DefinedFunction(Block block, String name) { + this.block = block; + this.name = name; + } + + @Override + public String name() { + return name; + } + + @Override + public T apply(Buffer buffer, Rotation rotation, Random random, int recursions) { + return null; + } + + @Override + public Position getPosition() { + return null; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/def/FunctionBlock.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/def/FunctionBlock.java new file mode 100644 index 000000000..e374d5d71 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/def/FunctionBlock.java @@ -0,0 +1,44 @@ +package com.dfsek.terra.api.structures.parser.lang.functions.def; + +import com.dfsek.terra.api.structures.parser.lang.Block; +import com.dfsek.terra.api.structures.parser.lang.Item; +import com.dfsek.terra.api.structures.structure.Rotation; +import com.dfsek.terra.api.structures.structure.buffer.Buffer; +import com.dfsek.terra.api.structures.tokenizer.Position; + +import java.util.List; +import java.util.Random; + +public class FunctionBlock implements Item> { + private final List> items; + private final Position position; + private final T defaultVal; + + public FunctionBlock(List> items, T defaultVal, Position position) { + this.items = items; + this.position = position; + this.defaultVal = defaultVal; + } + + public List> getItems() { + return items; + } + + @SuppressWarnings("unchecked") + @Override + public synchronized Block.ReturnInfo apply(Buffer buffer, Rotation rotation, Random random, int recursions) { + for(Item item : items) { + Object result = item.apply(buffer, rotation, random, recursions); + if(result instanceof Block.ReturnInfo) { + Block.ReturnInfo level = (Block.ReturnInfo) result; + if(!level.getLevel().equals(Block.ReturnLevel.NONE)) return level; + } + } + return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, defaultVal); + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/BreakKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/BreakKeyword.java similarity index 92% rename from common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/BreakKeyword.java rename to common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/BreakKeyword.java index 6d205dbf3..0887fb995 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/BreakKeyword.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/BreakKeyword.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.api.structures.parser.lang.keywords; +package com.dfsek.terra.api.structures.parser.lang.keywords.flow; import com.dfsek.terra.api.structures.parser.lang.Block; import com.dfsek.terra.api.structures.parser.lang.Keyword; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/ContinueKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ContinueKeyword.java similarity index 92% rename from common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/ContinueKeyword.java rename to common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ContinueKeyword.java index 72b2cfa73..5460598f8 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/ContinueKeyword.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ContinueKeyword.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.api.structures.parser.lang.keywords; +package com.dfsek.terra.api.structures.parser.lang.keywords.flow; import com.dfsek.terra.api.structures.parser.lang.Block; import com.dfsek.terra.api.structures.parser.lang.Keyword; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/FailKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/FailKeyword.java similarity index 92% rename from common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/FailKeyword.java rename to common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/FailKeyword.java index 1277946a0..0f52b19f2 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/FailKeyword.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/FailKeyword.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.api.structures.parser.lang.keywords; +package com.dfsek.terra.api.structures.parser.lang.keywords.flow; import com.dfsek.terra.api.structures.parser.lang.Block; import com.dfsek.terra.api.structures.parser.lang.Keyword; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/ReturnKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ReturnKeyword.java similarity index 92% rename from common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/ReturnKeyword.java rename to common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ReturnKeyword.java index 27df59d2b..239110439 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/ReturnKeyword.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ReturnKeyword.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.api.structures.parser.lang.keywords; +package com.dfsek.terra.api.structures.parser.lang.keywords.flow; import com.dfsek.terra.api.structures.parser.lang.Block; import com.dfsek.terra.api.structures.parser.lang.Keyword; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/ForKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/ForKeyword.java index 6cdd7845c..5f9eb4c89 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/ForKeyword.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/ForKeyword.java @@ -10,7 +10,7 @@ import com.dfsek.terra.api.structures.tokenizer.Position; import java.util.Random; -public class ForKeyword implements Keyword { +public class ForKeyword implements Keyword> { private final Block conditional; private final Item initializer; private final Returnable statement; @@ -26,13 +26,13 @@ public class ForKeyword implements Keyword { } @Override - public Block.ReturnLevel apply(Buffer buffer, Rotation rotation, Random random, int recursions) { + public Block.ReturnInfo apply(Buffer buffer, Rotation rotation, Random random, int recursions) { for(initializer.apply(buffer, rotation, random, recursions); statement.apply(buffer, rotation, random, recursions); incrementer.apply(buffer, rotation, random, recursions)) { - Block.ReturnLevel level = conditional.apply(buffer, rotation, random, recursions); - if(level.equals(Block.ReturnLevel.BREAK)) break; - if(level.isReturnFast()) return level; + Block.ReturnInfo level = conditional.apply(buffer, rotation, random, recursions); + if(level.getLevel().equals(Block.ReturnLevel.BREAK)) break; + if(level.getLevel().isReturnFast()) return level; } - return Block.ReturnLevel.NONE; + return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null); } @Override diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/IfKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/IfKeyword.java index 7a5f4ee88..683bca13c 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/IfKeyword.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/IfKeyword.java @@ -11,7 +11,7 @@ import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Random; -public class IfKeyword implements Keyword { +public class IfKeyword implements Keyword> { private final Block conditional; private final Returnable statement; private final Position position; @@ -27,7 +27,7 @@ public class IfKeyword implements Keyword { } @Override - public Block.ReturnLevel apply(Buffer buffer, Rotation rotation, Random random, int recursions) { + public Block.ReturnInfo apply(Buffer buffer, Rotation rotation, Random random, int recursions) { if(statement.apply(buffer, rotation, random, recursions)) return conditional.apply(buffer, rotation, random, recursions); else { for(Pair, Block> pair : elseIf) { @@ -37,7 +37,7 @@ public class IfKeyword implements Keyword { } if(elseBlock != null) return elseBlock.apply(buffer, rotation, random, recursions); } - return Block.ReturnLevel.NONE; + return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null); } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/WhileKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/WhileKeyword.java index 014542d45..c08c0d51f 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/WhileKeyword.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/WhileKeyword.java @@ -9,7 +9,7 @@ import com.dfsek.terra.api.structures.tokenizer.Position; import java.util.Random; -public class WhileKeyword implements Keyword { +public class WhileKeyword implements Keyword> { private final Block conditional; private final Returnable statement; private final Position position; @@ -21,13 +21,13 @@ public class WhileKeyword implements Keyword { } @Override - public Block.ReturnLevel apply(Buffer buffer, Rotation rotation, Random random, int recursions) { + public Block.ReturnInfo apply(Buffer buffer, Rotation rotation, Random random, int recursions) { while(statement.apply(buffer, rotation, random, recursions)) { - Block.ReturnLevel level = conditional.apply(buffer, rotation, random, recursions); - if(level.equals(Block.ReturnLevel.BREAK)) break; - if(level.isReturnFast()) return level; + Block.ReturnInfo level = conditional.apply(buffer, rotation, random, recursions); + if(level.getLevel().equals(Block.ReturnLevel.BREAK)) break; + if(level.getLevel().isReturnFast()) return level; } - return Block.ReturnLevel.NONE; + return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null); } @Override diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java b/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java index 4c7c83098..6306b01a7 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java @@ -71,16 +71,16 @@ public class StructureScript { */ public boolean execute(Location location, Random random, Rotation rotation) { StructureBuffer buffer = new StructureBuffer(location); - Block.ReturnLevel level = block.apply(buffer, rotation, random, 0); + Block.ReturnInfo level = block.apply(buffer, rotation, random, 0); buffer.paste(); - return !level.equals(Block.ReturnLevel.FAIL); + return !level.getLevel().equals(Block.ReturnLevel.FAIL); } public boolean execute(Location location, Chunk chunk, Random random, Rotation rotation) { StructureBuffer buffer = cache.computeIfAbsent(location, loc -> { StructureBuffer buf = new StructureBuffer(loc); - Block.ReturnLevel level = block.apply(buf, rotation, random, 0); - buf.setSucceeded(!level.equals(Block.ReturnLevel.FAIL)); + Block.ReturnInfo level = block.apply(buf, rotation, random, 0); + buf.setSucceeded(!level.getLevel().equals(Block.ReturnLevel.FAIL)); return buf; }); buffer.paste(chunk);