aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-09-27 11:30:36 +0100
committerMichael Williamson <mike@zwobble.org>2023-09-27 11:30:36 +0100
commit217cef25875d3ef04f055bed64752db9b2fbb21e (patch)
tree65a5e599b61d5aaba998a02a96cded0f7558f0fe /src
parent537aefec06307139899e3f2f2cd74842a3af6345 (diff)
Support ignore target
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/shedlang/compiler/ast/typed/TypedTargetNode.java1
-rw-r--r--src/main/java/org/shedlang/compiler/ast/untyped/UntypedTargetNode.java1
-rw-r--r--src/main/java/org/shedlang/compiler/parser/Parser.java11
-rw-r--r--src/main/java/org/shedlang/compiler/parser/TokenType.java1
-rw-r--r--src/main/java/org/shedlang/compiler/parser/Tokeniser.java3
-rw-r--r--src/main/java/org/shedlang/compiler/stackir/StackCompiler.java4
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/DeclaredVariables.java3
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java4
-rw-r--r--src/test/java/org/shedlang/compiler/ast/typed/Typed.java4
-rw-r--r--src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java4
-rw-r--r--src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java4
-rw-r--r--src/test/java/org/shedlang/compiler/ast/untyped/UntypedNodeMatchers.java4
-rw-r--r--src/test/java/org/shedlang/compiler/parser/ParserAssignTests.java12
-rw-r--r--src/test/java/org/shedlang/compiler/stackir/StackCompilerAssignTests.java17
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerAssignTests.java16
15 files changed, 87 insertions, 2 deletions
diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedTargetNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedTargetNode.java
index 61ead210..1b469175 100644
--- a/src/main/java/org/shedlang/compiler/ast/typed/TypedTargetNode.java
+++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedTargetNode.java
@@ -5,6 +5,7 @@ import org.shedlang.compiler.sources.Source;
import java.util.List;
public sealed interface TypedTargetNode extends TypedNode {
+ record Ignore(Source source) implements TypedTargetNode {}
record Reassign(String name, Source source) implements TypedTargetNode {}
record Tuple(List<TypedTargetNode> elements, Source source) implements TypedTargetNode {}
record Val(String name, Source source) implements TypedTargetNode {}
diff --git a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedTargetNode.java b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedTargetNode.java
index 3cea8c2d..1d4cbe7e 100644
--- a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedTargetNode.java
+++ b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedTargetNode.java
@@ -5,6 +5,7 @@ import org.shedlang.compiler.sources.Source;
import java.util.List;
public sealed interface UntypedTargetNode extends UntypedNode {
+ record Ignore(Source source) implements UntypedTargetNode {}
record Reassign(String name, Source source) implements UntypedTargetNode {}
record Tuple(List<UntypedTargetNode> elements, Source source) implements UntypedTargetNode {}
record Val(String name, Source source) implements UntypedTargetNode, UntypedVariableDeclarationNode {}
diff --git a/src/main/java/org/shedlang/compiler/parser/Parser.java b/src/main/java/org/shedlang/compiler/parser/Parser.java
index 44c132e7..eef01d28 100644
--- a/src/main/java/org/shedlang/compiler/parser/Parser.java
+++ b/src/main/java/org/shedlang/compiler/parser/Parser.java
@@ -301,7 +301,7 @@ public class Parser {
static UntypedFunctionStatementNode parseFunctionStatement(TokenIterator<TokenType> tokens) {
return switch (tokens.peek().tokenType()) {
- case KEYWORD_ASSIGN, KEYWORD_VAL, KEYWORD_VAR ->
+ case KEYWORD_ASSIGN, KEYWORD_VAL, KEYWORD_VAR, SYMBOL_UNDERSCORE ->
parseAssign(tokens);
case KEYWORD_RETURN ->
@@ -633,6 +633,15 @@ public class Parser {
yield new UntypedTargetNode.Tuple(elements, source);
}
+ case SYMBOL_UNDERSCORE -> {
+ tokens.skip(TokenType.SYMBOL_UNDERSCORE);
+
+ var end = tokens.position();
+ var source = start.to(end);
+
+ yield new UntypedTargetNode.Ignore(source);
+ }
+
default ->
throw new UnexpectedTokenException("target", tokens.peek());
};
diff --git a/src/main/java/org/shedlang/compiler/parser/TokenType.java b/src/main/java/org/shedlang/compiler/parser/TokenType.java
index d9cd95aa..53a7877a 100644
--- a/src/main/java/org/shedlang/compiler/parser/TokenType.java
+++ b/src/main/java/org/shedlang/compiler/parser/TokenType.java
@@ -37,4 +37,5 @@ public enum TokenType {
SYMBOL_PLUS,
SYMBOL_SEMICOLON,
SYMBOL_THIN_ARROW,
+ SYMBOL_UNDERSCORE,
}
diff --git a/src/main/java/org/shedlang/compiler/parser/Tokeniser.java b/src/main/java/org/shedlang/compiler/parser/Tokeniser.java
index 3793417a..bfa75a8e 100644
--- a/src/main/java/org/shedlang/compiler/parser/Tokeniser.java
+++ b/src/main/java/org/shedlang/compiler/parser/Tokeniser.java
@@ -51,7 +51,8 @@ public class Tokeniser {
RegexTokeniser.rule(TokenType.SYMBOL_PAREN_OPEN, "\\("),
RegexTokeniser.rule(TokenType.SYMBOL_PAREN_CLOSE, "\\)"),
RegexTokeniser.rule(TokenType.SYMBOL_PLUS, "\\+"),
- RegexTokeniser.rule(TokenType.SYMBOL_SEMICOLON, ";")
+ RegexTokeniser.rule(TokenType.SYMBOL_SEMICOLON, ";"),
+ RegexTokeniser.rule(TokenType.SYMBOL_UNDERSCORE, "_")
)
);
diff --git a/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java b/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java
index d036eebe..07180669 100644
--- a/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java
+++ b/src/main/java/org/shedlang/compiler/stackir/StackCompiler.java
@@ -372,6 +372,10 @@ public class StackCompiler {
Context context
) {
return switch (target) {
+ case TypedTargetNode.Ignore ignore -> {
+ yield context.addInstruction(new DiscardInstruction(ignore.source()));
+ }
+
case TypedTargetNode.Reassign reassign -> {
context = context.addInstruction(
new VarStoreInstruction(
diff --git a/src/main/java/org/shedlang/compiler/typechecker/DeclaredVariables.java b/src/main/java/org/shedlang/compiler/typechecker/DeclaredVariables.java
index 43a087b5..7175f51c 100644
--- a/src/main/java/org/shedlang/compiler/typechecker/DeclaredVariables.java
+++ b/src/main/java/org/shedlang/compiler/typechecker/DeclaredVariables.java
@@ -102,6 +102,9 @@ class DeclaredVariables {
VariableType.VAL,
val.source()
));
+
+ case UntypedTargetNode.Ignore ignore ->
+ variables;
};
}
}
diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
index 8f0d363a..2d426428 100644
--- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
+++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
@@ -864,6 +864,10 @@ public class TypeChecker {
TypeCheckerContext context
) {
return switch (target) {
+ case UntypedTargetNode.Ignore ignore -> {
+ yield context.toResult(new TypedTargetNode.Ignore(target.source()));
+ }
+
case UntypedTargetNode.Reassign reassign -> {
var targetVariableResult = runtimeLookup(
reassign.name(),
diff --git a/src/test/java/org/shedlang/compiler/ast/typed/Typed.java b/src/test/java/org/shedlang/compiler/ast/typed/Typed.java
index 0d48711c..42a46859 100644
--- a/src/test/java/org/shedlang/compiler/ast/typed/Typed.java
+++ b/src/test/java/org/shedlang/compiler/ast/typed/Typed.java
@@ -182,6 +182,10 @@ public class Typed {
);
}
+ public static TypedTargetNode targetIgnore() {
+ return new TypedTargetNode.Ignore(Sources.NULL);
+ }
+
public static TypedTargetNode targetReassign(String name) {
return new TypedTargetNode.Reassign(name, Sources.NULL);
}
diff --git a/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java b/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java
index c8b0501d..52d91cdf 100644
--- a/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java
+++ b/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java
@@ -221,6 +221,10 @@ public class TypedNodeMatchers {
);
}
+ public static Matcher<TypedTargetNode> isTypedTargetIgnore() {
+ return instanceOf(TypedTargetNode.Ignore.class);
+ }
+
public static Matcher<TypedTargetNode> isTypedTargetReassign(String name) {
return instanceOf(
TypedTargetNode.Reassign.class,
diff --git a/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java b/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java
index 36668a8b..a87b1c48 100644
--- a/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java
+++ b/src/test/java/org/shedlang/compiler/ast/untyped/Untyped.java
@@ -150,6 +150,10 @@ public class Untyped {
);
}
+ public static UntypedTargetNode targetIgnore() {
+ return new UntypedTargetNode.Ignore(Sources.NULL);
+ }
+
public static UntypedTargetNode targetReassign(String name) {
return new UntypedTargetNode.Reassign(name, Sources.NULL);
}
diff --git a/src/test/java/org/shedlang/compiler/ast/untyped/UntypedNodeMatchers.java b/src/test/java/org/shedlang/compiler/ast/untyped/UntypedNodeMatchers.java
index 37d432e8..7d80b4ab 100644
--- a/src/test/java/org/shedlang/compiler/ast/untyped/UntypedNodeMatchers.java
+++ b/src/test/java/org/shedlang/compiler/ast/untyped/UntypedNodeMatchers.java
@@ -190,6 +190,10 @@ public class UntypedNodeMatchers {
return isUntypedBinaryOperationNode(UntypedBinaryOperator.SUB, left, right);
}
+ public static Matcher<UntypedTargetNode> isUntypedTargetIgnoreNode() {
+ return instanceOf(UntypedTargetNode.Ignore.class);
+ }
+
public static Matcher<UntypedTargetNode> isUntypedTargetReassignNode(String name) {
return instanceOf(
UntypedTargetNode.Reassign.class,
diff --git a/src/test/java/org/shedlang/compiler/parser/ParserAssignTests.java b/src/test/java/org/shedlang/compiler/parser/ParserAssignTests.java
index 9c29d328..7dc07722 100644
--- a/src/test/java/org/shedlang/compiler/parser/ParserAssignTests.java
+++ b/src/test/java/org/shedlang/compiler/parser/ParserAssignTests.java
@@ -34,4 +34,16 @@ public class ParserAssignTests {
isUntypedReferenceNode("z")
));
}
+
+ @Test
+ public void canParseIgnoreTarget() {
+ var source = "_ = x;";
+
+ var node = parseString(source, Parser::parseFunctionStatement);
+
+ assertThat(node, isUntypedAssignNode(
+ isUntypedTargetIgnoreNode(),
+ isUntypedReferenceNode("x")
+ ));
+ }
}
diff --git a/src/test/java/org/shedlang/compiler/stackir/StackCompilerAssignTests.java b/src/test/java/org/shedlang/compiler/stackir/StackCompilerAssignTests.java
index b717648a..7c49af0a 100644
--- a/src/test/java/org/shedlang/compiler/stackir/StackCompilerAssignTests.java
+++ b/src/test/java/org/shedlang/compiler/stackir/StackCompilerAssignTests.java
@@ -11,6 +11,23 @@ import static org.zwobble.precisely.Matchers.isSequence;
public class StackCompilerAssignTests {
@Test
+ public void targetIgnoreIsCompiledToDiscard() {
+ var node = Typed.assign(
+ Typed.targetIgnore(),
+ Typed.reference("x")
+ );
+ var context = StackCompiler.Context.EMPTY
+ .addShedVariable("x");
+
+ var result = StackCompiler.compileFunctionStatement(node, context);
+
+ assertThat(result.instructions(), isSequence(
+ isLocalLoadInstruction("x__0"),
+ isDiscardInstruction()
+ ));
+ }
+
+ @Test
public void whenTargetIsReassignThenExpressionIsEvaluatedAndStoredAsVar() {
var node = Typed.assign(
Typed.targetReassign("x"),
diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerAssignTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerAssignTests.java
index eb2a2db1..9bd07ffd 100644
--- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerAssignTests.java
+++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerAssignTests.java
@@ -24,6 +24,22 @@ import static org.zwobble.precisely.Matchers.*;
public class TypeCheckerAssignTests {
@Test
+ public void canTypeCheckTargetIgnore() {
+ var untyped = Untyped.assign(Untyped.targetIgnore(), Untyped.stringLiteral("hello"));
+ var context = TypeCheckerContext.EMPTY
+ .enterNamespace(P.map(
+ Map.entry("x", Variable.defined(Types.STRING, VariableType.VAR))
+ ));
+
+ var typed = typeCheckFunctionStatement(untyped, context);
+
+ assertThat(typed.value(), isTypedAssignNode(
+ isTypedTargetIgnore(),
+ isTypedStringLiteralNode("hello")
+ ));
+ }
+
+ @Test
public void canTypeCheckReassign() {
var untyped = Untyped.assign(Untyped.targetReassign("x"), Untyped.stringLiteral("hello"));
var context = TypeCheckerContext.EMPTY