diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/controlflow/LamaCaseNode.java b/src/main/java/org/programsnail/truffle_lama/nodes/controlflow/LamaCaseNode.java index 3245cde..bed34f8 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/controlflow/LamaCaseNode.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/controlflow/LamaCaseNode.java @@ -31,7 +31,9 @@ public final class LamaCaseNode extends LamaExpressionNode { public Object executeGeneric(VirtualFrame frame) throws UnexpectedResultException { Object value = this.valueNode.executeGeneric(frame); for (int i = 0; i < this.patterns.length; ++i) { - if (this.patterns[i].match(value)) { // TODO: special case for name binding ?? + var patternMatch = this.patterns[i].match(value); + if (patternMatch.isPresent()) { + patternMatch.get().assignVariablesIn(frame); return this.exprNodes[i].executeGeneric(frame); } } diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaArrayPattern.java b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaArrayPattern.java index 99c31be..b1d9cbf 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaArrayPattern.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaArrayPattern.java @@ -2,6 +2,8 @@ package org.programsnail.truffle_lama.nodes.pattern; import org.programsnail.truffle_lama.runtime.LamaArray; +import java.util.Optional; + public final class LamaArrayPattern extends LamaPattern { private final LamaPattern[] elements; @@ -10,18 +12,19 @@ public final class LamaArrayPattern extends LamaPattern { } @Override - public boolean match(Object object) { - if (!(object instanceof LamaArray array)) { - return false; - } - if (elements.length != array.getLength()) { - return false; + public Optional match(Object object) { + if (!(object instanceof LamaArray array) || elements.length != array.getLength()) { + return Optional.empty(); } + + PatternMatch patternMatch = new PatternMatch(); for (int i = 0; i < elements.length; ++i) { - if (!elements[i].match(array.readAt(i))) { - return false; + var currentMatch = elements[i].match(array.readAt(i)); + if (currentMatch.isEmpty()) { + return Optional.empty(); } + patternMatch.extendWith(currentMatch.get()); } - return true; + return Optional.of(patternMatch); } } diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaArrayTagPattern.java b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaArrayTagPattern.java index af86664..1c1c9d0 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaArrayTagPattern.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaArrayTagPattern.java @@ -2,9 +2,11 @@ package org.programsnail.truffle_lama.nodes.pattern; import org.programsnail.truffle_lama.runtime.LamaArray; +import java.util.Optional; + public final class LamaArrayTagPattern extends LamaPattern { @Override - public boolean match(Object object) { - return object instanceof LamaArray; + public Optional match(Object object) { + return optionalOfBoolean(object instanceof LamaArray); } } diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaBoxedPattern.java b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaBoxedPattern.java index e8852b2..6283cc2 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaBoxedPattern.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaBoxedPattern.java @@ -4,9 +4,11 @@ import com.oracle.truffle.api.strings.TruffleString; import org.programsnail.truffle_lama.runtime.LamaArrayLike; import org.programsnail.truffle_lama.runtime.LamaSexp; +import java.util.Optional; + public final class LamaBoxedPattern extends LamaPattern { @Override - public boolean match(Object object) { - return object instanceof TruffleString || object instanceof LamaArrayLike; // includes array and sexp + public Optional match(Object object) { + return optionalOfBoolean(object instanceof TruffleString || object instanceof LamaArrayLike); // includes array and sexp } } diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaClosureTagPattern.java b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaClosureTagPattern.java index b034ae1..70dc6e9 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaClosureTagPattern.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaClosureTagPattern.java @@ -2,9 +2,11 @@ package org.programsnail.truffle_lama.nodes.pattern; import org.programsnail.truffle_lama.FunctionObject; +import java.util.Optional; + public final class LamaClosureTagPattern extends LamaPattern { @Override - public boolean match(Object object) { - return object instanceof FunctionObject; // TODO: check + public Optional match(Object object) { + return optionalOfBoolean(object instanceof FunctionObject); // TODO: check } } diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaConstPattern.java b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaConstPattern.java index 846a016..91bf33c 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaConstPattern.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaConstPattern.java @@ -2,6 +2,8 @@ package org.programsnail.truffle_lama.nodes.pattern; import org.programsnail.truffle_lama.runtime.LamaArray; +import java.util.Optional; + public final class LamaConstPattern extends LamaPattern { private final long value; @@ -10,7 +12,7 @@ public final class LamaConstPattern extends LamaPattern { } @Override - public boolean match(Object object) { - return (object instanceof Integer other) && other == value; + public Optional match(Object object) { + return optionalOfBoolean((object instanceof Integer other) && other == value); } } diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaNamedPattern.java b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaNamedPattern.java index 12f1156..2f0ff95 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaNamedPattern.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaNamedPattern.java @@ -1,5 +1,18 @@ package org.programsnail.truffle_lama.nodes.pattern; +import com.oracle.truffle.api.frame.VirtualFrame; + +import java.util.Optional; + public final class LamaNamedPattern extends LamaPattern { - // TODO: return var assignment in som way + private final int id; + + public LamaNamedPattern(int id, VirtualFrame frame) { + this.id = id; + } + + @Override + public Optional match(Object object) { + return Optional.of(new PatternMatch(id, object)); + } } diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaPattern.java b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaPattern.java index 3dff45b..b369d10 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaPattern.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaPattern.java @@ -1,5 +1,11 @@ package org.programsnail.truffle_lama.nodes.pattern; +import java.util.Optional; + public abstract class LamaPattern { - public abstract boolean match(Object object); + public abstract Optional match(Object object); + + protected static Optional optionalOfBoolean(boolean value) { + return value ? Optional.of(new PatternMatch()) : Optional.empty(); + } } diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaSexpPattern.java b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaSexpPattern.java index 6ca2ca5..2b89bf9 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaSexpPattern.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaSexpPattern.java @@ -1,4 +1,33 @@ package org.programsnail.truffle_lama.nodes.pattern; +import com.oracle.truffle.api.strings.TruffleString; +import org.programsnail.truffle_lama.runtime.LamaSexp; + +import java.util.Optional; + public final class LamaSexpPattern extends LamaPattern { + private final TruffleString tag; + private final LamaPattern[] elements; + + public LamaSexpPattern(TruffleString tag, LamaPattern[] elements) { + this.tag = tag; + this.elements = elements; + } + + @Override + public Optional match(Object object) { + if (!(object instanceof LamaSexp sexp) || tag != sexp.getTag() || elements.length != sexp.getLength()) { + return Optional.empty(); + } + + PatternMatch patternMatch = new PatternMatch(); + for (int i = 0; i < elements.length; ++i) { + var currentMatch = elements[i].match(sexp.readAt(i)); + if (currentMatch.isEmpty()) { + return Optional.empty(); + } + patternMatch.extendWith(currentMatch.get()); + } + return Optional.of(patternMatch); + } } diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaSexpTagPattern.java b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaSexpTagPattern.java index c2c9954..39f15c1 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaSexpTagPattern.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaSexpTagPattern.java @@ -2,9 +2,11 @@ package org.programsnail.truffle_lama.nodes.pattern; import org.programsnail.truffle_lama.runtime.LamaSexp; +import java.util.Optional; + public final class LamaSexpTagPattern extends LamaPattern { @Override - public boolean match(Object object) { - return object instanceof LamaSexp; + public Optional match(Object object) { + return optionalOfBoolean(object instanceof LamaSexp); } } diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaStringPattern.java b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaStringPattern.java index 4ec4244..c6161cf 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaStringPattern.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaStringPattern.java @@ -2,6 +2,8 @@ package org.programsnail.truffle_lama.nodes.pattern; import com.oracle.truffle.api.strings.TruffleString; +import java.util.Optional; + public final class LamaStringPattern extends LamaPattern { private final TruffleString value; @@ -10,7 +12,7 @@ public final class LamaStringPattern extends LamaPattern { } @Override - public boolean match(Object object) { - return (object instanceof TruffleString other) && other == value; + public Optional match(Object object) { + return optionalOfBoolean((object instanceof TruffleString other) && other == value); } } diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaStringTagPattern.java b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaStringTagPattern.java index bc2947b..e50ee08 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaStringTagPattern.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaStringTagPattern.java @@ -2,9 +2,11 @@ package org.programsnail.truffle_lama.nodes.pattern; import com.oracle.truffle.api.strings.TruffleString; +import java.util.Optional; + public final class LamaStringTagPattern extends LamaPattern { @Override - public boolean match(Object object) { - return object instanceof TruffleString; + public Optional match(Object object) { + return optionalOfBoolean(object instanceof TruffleString); } } diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaUnBoxedPattern.java b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaUnBoxedPattern.java index 2b051e5..49cbaba 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaUnBoxedPattern.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaUnBoxedPattern.java @@ -1,8 +1,10 @@ package org.programsnail.truffle_lama.nodes.pattern; +import java.util.Optional; + public final class LamaUnBoxedPattern extends LamaPattern { @Override - public boolean match(Object object) { - return object instanceof Integer; // TODO: does work with int ?? + public Optional match(Object object) { + return optionalOfBoolean(object instanceof Integer); // TODO: does work with int ?? } } diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaWildcardPattern.java b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaWildcardPattern.java index 0be5a26..55b95d2 100644 --- a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaWildcardPattern.java +++ b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/LamaWildcardPattern.java @@ -1,8 +1,10 @@ package org.programsnail.truffle_lama.nodes.pattern; +import java.util.Optional; + public final class LamaWildcardPattern extends LamaPattern { @Override - public boolean match(Object object) { - return true; + public Optional match(Object object) { + return optionalOfBoolean(true); } } diff --git a/src/main/java/org/programsnail/truffle_lama/nodes/pattern/PatternMatch.java b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/PatternMatch.java new file mode 100644 index 0000000..c7900ab --- /dev/null +++ b/src/main/java/org/programsnail/truffle_lama/nodes/pattern/PatternMatch.java @@ -0,0 +1,48 @@ +package org.programsnail.truffle_lama.nodes.pattern; + +import com.oracle.truffle.api.frame.VirtualFrame; +import org.antlr.v4.runtime.misc.Pair; + +import java.util.ArrayList; +import java.util.List; + +public final class PatternMatch { + public static final class MatchElem { + public final int id; + public final Object object; + + public MatchElem(int id, Object object) { + this.id = id; + this.object = object; + } + } + + private final List matches; + + public PatternMatch() { + this.matches = new ArrayList<>(); + } + + public PatternMatch(Integer id, Object object) { + this.matches = new ArrayList<>(); + addMatch(id, object); + } + + public PatternMatch(List matches) { + this.matches = matches; + } + + public void addMatch(Integer id, Object object) { + this.matches.addLast(new MatchElem(id, object)); + } + + public void extendWith(PatternMatch other) { + matches.addAll(other.matches); + } + + public void assignVariablesIn(VirtualFrame frame) { + for (var match : matches) { + frame.setObject(match.id, match.object); + } + } +} diff --git a/src/main/java/org/programsnail/truffle_lama/runtime/LamaSexp.java b/src/main/java/org/programsnail/truffle_lama/runtime/LamaSexp.java index c169e32..6dc897a 100644 --- a/src/main/java/org/programsnail/truffle_lama/runtime/LamaSexp.java +++ b/src/main/java/org/programsnail/truffle_lama/runtime/LamaSexp.java @@ -1,18 +1,20 @@ package org.programsnail.truffle_lama.runtime; -public final class LamaSexp extends LamaArrayLike { - private String tag; +import com.oracle.truffle.api.strings.TruffleString; - public String getTag() { +public final class LamaSexp extends LamaArrayLike { + private TruffleString tag; + + public TruffleString getTag() { return tag; } - public LamaSexp(String tag, Object[] elements) { + public LamaSexp(TruffleString tag, Object[] elements) { super(elements); this.tag = tag; } - LamaSexp(String tag, int length) { + LamaSexp(TruffleString tag, int length) { super(length); this.tag = tag; }