diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-09-27 11:30:36 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-09-27 11:30:36 +0100 |
| commit | 217cef25875d3ef04f055bed64752db9b2fbb21e (patch) | |
| tree | 65a5e599b61d5aaba998a02a96cded0f7558f0fe /src | |
| parent | 537aefec06307139899e3f2f2cd74842a3af6345 (diff) | |
Support ignore target
Diffstat (limited to 'src')
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 |
