better patterns: assign variable values

This commit is contained in:
ProgramSnail 2025-06-14 13:44:16 +03:00
parent 41a86c1314
commit 1068d95010
16 changed files with 156 additions and 35 deletions

View file

@ -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);
}
}

View file

@ -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<PatternMatch> 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);
}
}

View file

@ -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<PatternMatch> match(Object object) {
return optionalOfBoolean(object instanceof LamaArray);
}
}

View file

@ -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<PatternMatch> match(Object object) {
return optionalOfBoolean(object instanceof TruffleString || object instanceof LamaArrayLike); // includes array and sexp
}
}

View file

@ -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<PatternMatch> match(Object object) {
return optionalOfBoolean(object instanceof FunctionObject); // TODO: check
}
}

View file

@ -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<PatternMatch> match(Object object) {
return optionalOfBoolean((object instanceof Integer other) && other == value);
}
}

View file

@ -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<PatternMatch> match(Object object) {
return Optional.of(new PatternMatch(id, object));
}
}

View file

@ -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<PatternMatch> match(Object object);
protected static Optional<PatternMatch> optionalOfBoolean(boolean value) {
return value ? Optional.of(new PatternMatch()) : Optional.empty();
}
}

View file

@ -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<PatternMatch> 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);
}
}

View file

@ -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<PatternMatch> match(Object object) {
return optionalOfBoolean(object instanceof LamaSexp);
}
}

View file

@ -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<PatternMatch> match(Object object) {
return optionalOfBoolean((object instanceof TruffleString other) && other == value);
}
}

View file

@ -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<PatternMatch> match(Object object) {
return optionalOfBoolean(object instanceof TruffleString);
}
}

View file

@ -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<PatternMatch> match(Object object) {
return optionalOfBoolean(object instanceof Integer); // TODO: does work with int ??
}
}

View file

@ -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<PatternMatch> match(Object object) {
return optionalOfBoolean(true);
}
}

View file

@ -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<MatchElem> matches;
public PatternMatch() {
this.matches = new ArrayList<>();
}
public PatternMatch(Integer id, Object object) {
this.matches = new ArrayList<>();
addMatch(id, object);
}
public PatternMatch(List<MatchElem> 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);
}
}
}

View file

@ -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;
}