summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2026-11-06 15:25:33 +0000
committerMichael Williamson <mike@zwobble.org>2026-11-06 15:25:33 +0000
commit5a7995056e6e8aa2db573c7ab5ce4f86e4267d73 (patch)
tree1d185901f5e5856a22d3fec9dd6faa1b9478ab66 /src
parenta1d3da9e2c2e0526a2d004cda035e761626b2f85 (diff)
Parse equals operation
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedBinaryOperationNode.java58
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedBinaryOperator.java13
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedExpressionNode.java2
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/parser/OperatorPrecedence.java1
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java45
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java3
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedBinaryOperationNodeMatcher.java59
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserBinaryOperationTests.java26
8 files changed, 206 insertions, 1 deletions
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedBinaryOperationNode.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedBinaryOperationNode.java
new file mode 100644
index 0000000..226e88e
--- /dev/null
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedBinaryOperationNode.java
@@ -0,0 +1,58 @@
+// Generated by hobgoblin.
+
+package org.zwobble.hobgoblin.compiler.ast.untyped;
+
+// Custom area start: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode imports
+// Custom area end: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode imports
+
+public record UntypedBinaryOperationNode(
+ org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperator operator,
+ org.zwobble.hobgoblin.compiler.ast.untyped.UntypedExpressionNode left,
+ org.zwobble.hobgoblin.compiler.ast.untyped.UntypedExpressionNode right,
+ org.zwobble.hobgoblin.compiler.sources.Source source
+) implements org.zwobble.hobgoblin.compiler.ast.untyped.UntypedExpressionNode {
+ public static org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode.Builder arbitrary() {
+ return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode.Builder(org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperator.EQUALS, org.zwobble.hobgoblin.compiler.ast.untyped.UntypedReferenceNode.arbitrary().build(), org.zwobble.hobgoblin.compiler.ast.untyped.UntypedReferenceNode.arbitrary().build(), org.zwobble.hobgoblin.compiler.sources.HobgoblinNativeSources.arbitrarySource());
+ }
+
+ public record Builder(
+ org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperator operator,
+ org.zwobble.hobgoblin.compiler.ast.untyped.UntypedExpressionNode left,
+ org.zwobble.hobgoblin.compiler.ast.untyped.UntypedExpressionNode right,
+ org.zwobble.hobgoblin.compiler.sources.Source source
+ ) implements org.zwobble.hobgoblin.compiler.ast.untyped.UntypedExpressionNode.Builder {
+ public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode build() {
+ return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode(operator, left, right, source);
+ }
+
+ public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode.Builder withOperator(org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperator operator) {
+ return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode.Builder(operator, left, right, source);
+ }
+
+ public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode.Builder withLeft(org.zwobble.hobgoblin.compiler.ast.untyped.UntypedExpressionNode left) {
+ return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode.Builder(operator, left, right, source);
+ }
+
+ public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode.Builder withLeft(org.zwobble.hobgoblin.compiler.ast.untyped.UntypedExpressionNode.Builder left) {
+ return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode.Builder(operator, left.build(), right, source);
+ }
+
+ public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode.Builder withRight(org.zwobble.hobgoblin.compiler.ast.untyped.UntypedExpressionNode right) {
+ return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode.Builder(operator, left, right, source);
+ }
+
+ public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode.Builder withRight(org.zwobble.hobgoblin.compiler.ast.untyped.UntypedExpressionNode.Builder right) {
+ return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode.Builder(operator, left, right.build(), source);
+ }
+
+ public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode.Builder withSource(org.zwobble.hobgoblin.compiler.sources.Source source) {
+ return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode.Builder(operator, left, right, source);
+ }
+
+ // Custom area start: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode.Builder body
+ // Custom area end: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode.Builder body
+ }
+
+ // Custom area start: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode body
+ // Custom area end: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode body
+}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedBinaryOperator.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedBinaryOperator.java
new file mode 100644
index 0000000..b479e9b
--- /dev/null
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedBinaryOperator.java
@@ -0,0 +1,13 @@
+// Generated by hobgoblin.
+
+package org.zwobble.hobgoblin.compiler.ast.untyped;
+
+// Custom area start: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperator imports
+// Custom area end: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperator imports
+
+public enum UntypedBinaryOperator {
+ EQUALS
+
+ // Custom area start: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperator body
+ // Custom area end: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperator body
+}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedExpressionNode.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedExpressionNode.java
index a5c54a0..98a8d6c 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedExpressionNode.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedExpressionNode.java
@@ -5,7 +5,7 @@ package org.zwobble.hobgoblin.compiler.ast.untyped;
// Custom area start: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedExpressionNode imports
// Custom area end: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedExpressionNode imports
-public sealed interface UntypedExpressionNode permits org.zwobble.hobgoblin.compiler.ast.untyped.UntypedCallNode, org.zwobble.hobgoblin.compiler.ast.untyped.UntypedFunctionExpressionNode, org.zwobble.hobgoblin.compiler.ast.untyped.UntypedMemberAccessNode, org.zwobble.hobgoblin.compiler.ast.untyped.UntypedReferenceNode {
+public sealed interface UntypedExpressionNode permits org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode, org.zwobble.hobgoblin.compiler.ast.untyped.UntypedCallNode, org.zwobble.hobgoblin.compiler.ast.untyped.UntypedFunctionExpressionNode, org.zwobble.hobgoblin.compiler.ast.untyped.UntypedMemberAccessNode, org.zwobble.hobgoblin.compiler.ast.untyped.UntypedReferenceNode {
public interface Builder {
public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedExpressionNode build();
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/parser/OperatorPrecedence.java b/src/main/java/org/zwobble/hobgoblin/compiler/parser/OperatorPrecedence.java
index b63ca86..13c38db 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/parser/OperatorPrecedence.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/parser/OperatorPrecedence.java
@@ -2,4 +2,5 @@ package org.zwobble.hobgoblin.compiler.parser;
enum OperatorPrecedence {
CALL,
+ COMPARE,
}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java b/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java
index 508ab70..7403d1b 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java
@@ -605,6 +605,44 @@ public class Parser {
return new UntypedReferenceNode(name, source);
}
+ private static class BinaryOperationParser implements OperationParser<OperatorPrecedence, UntypedExpressionNode> {
+ private final UntypedBinaryOperator operator;
+ private final OperatorPrecedence precedence;
+ private final TokenType operatorTokenType;
+
+ public BinaryOperationParser(
+ UntypedBinaryOperator operator,
+ OperatorPrecedence precedence,
+ TokenType operatorTokenType
+ ) {
+ this.operator = operator;
+ this.precedence = precedence;
+ this.operatorTokenType = operatorTokenType;
+ }
+
+ @Override
+ public OperatorPrecedence precedence() {
+ return precedence;
+ }
+
+ @Override
+ public List<TokenType> operatorTokenTypes() {
+ return List.of(operatorTokenType);
+ }
+
+ @Override
+ public UntypedExpressionNode parse(SourcePosition start, UntypedExpressionNode left, TokenIterator tokens) {
+ tokens.skip(operatorTokenType);
+
+ var right = parseExpression(tokens, Optional.of(precedence));
+
+ var end = tokens.endPosition();
+ var source = createSource(start, end);
+
+ return new UntypedBinaryOperationNode(operator, left, right, source);
+ }
+ }
+
private static final OperationParser<OperatorPrecedence, UntypedExpressionNode> CALL_PARSER = new OperationParser<>() {
@Override
public OperatorPrecedence precedence() {
@@ -666,8 +704,15 @@ public class Parser {
}
};
+ private static final BinaryOperationParser EQUALS_OPERATION_PARSER = new BinaryOperationParser(
+ UntypedBinaryOperator.EQUALS,
+ OperatorPrecedence.COMPARE,
+ TokenType.SYMBOL_EQUALS_EQUALS
+ );
+
private static final Map<TokenType, OperationParser<OperatorPrecedence, UntypedExpressionNode>> OPERATION_PARSERS = Stream.of(
CALL_PARSER,
+ EQUALS_OPERATION_PARSER,
MEMBER_ACCESS_PARSER
)
.flatMap(parser ->
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java
index 68e078c..29bd917 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java
@@ -705,6 +705,9 @@ public class TypeChecker {
TypeCheckerNamespaceContext context
) {
switch (expression) {
+ case UntypedBinaryOperationNode _ -> {
+ throw new UnsupportedOperationException("TODO");
+ }
case UntypedCallNode _ -> {
throw new UnsupportedOperationException("TODO");
}
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedBinaryOperationNodeMatcher.java b/src/test/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedBinaryOperationNodeMatcher.java
new file mode 100644
index 0000000..63cf1d8
--- /dev/null
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedBinaryOperationNodeMatcher.java
@@ -0,0 +1,59 @@
+// Generated by hobgoblin.
+
+package org.zwobble.hobgoblin.compiler.ast.untyped;
+
+// Custom area start: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNodeMatcher imports
+// Custom area end: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNodeMatcher imports
+
+public final class UntypedBinaryOperationNodeMatcher implements org.zwobble.precisely.Matcher<java.lang.Object> {
+ public static org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNodeMatcher isUntypedBinaryOperationNode() {
+ return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNodeMatcher(java.util.List.of());
+ }
+
+ private final java.util.List<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode>> submatchers;
+
+ private UntypedBinaryOperationNodeMatcher(
+ java.util.List<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode>> submatchers
+ ) {
+ this.submatchers = submatchers;
+ }
+
+ public org.zwobble.precisely.MatchResult match(java.lang.Object actual) {
+ return this.toMatcher().match(actual);
+ }
+
+ public org.zwobble.precisely.TextTree describe() {
+ return this.toMatcher().describe();
+ }
+
+ private org.zwobble.precisely.Matcher<java.lang.Object> toMatcher() {
+ return org.zwobble.precisely.Matchers.instanceOf(org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode.class, this.submatchers);
+ }
+
+ public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNodeMatcher withOperator(org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperator> operator) {
+ var submatchers = new java.util.ArrayList<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode>>(this.submatchers);
+ submatchers.add(org.zwobble.precisely.Matchers.has("operator", org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode::operator, (org.zwobble.precisely.Matcher) operator));
+ return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNodeMatcher(submatchers);
+ }
+
+ public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNodeMatcher withLeft(org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.ast.untyped.UntypedExpressionNode> left) {
+ var submatchers = new java.util.ArrayList<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode>>(this.submatchers);
+ submatchers.add(org.zwobble.precisely.Matchers.has("left", org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode::left, (org.zwobble.precisely.Matcher) left));
+ return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNodeMatcher(submatchers);
+ }
+
+ public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNodeMatcher withRight(org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.ast.untyped.UntypedExpressionNode> right) {
+ var submatchers = new java.util.ArrayList<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode>>(this.submatchers);
+ submatchers.add(org.zwobble.precisely.Matchers.has("right", org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode::right, (org.zwobble.precisely.Matcher) right));
+ return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNodeMatcher(submatchers);
+ }
+
+ public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNodeMatcher withSource(org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.sources.Source> source) {
+ var submatchers = new java.util.ArrayList<org.zwobble.precisely.Matcher<? super org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode>>(this.submatchers);
+ submatchers.add(org.zwobble.precisely.Matchers.has("source", org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNode::source, (org.zwobble.precisely.Matcher) source));
+ return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNodeMatcher(submatchers);
+ }
+
+ // Custom area start: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNodeMatcher body
+ // Custom area end: org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNodeMatcher body
+}
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserBinaryOperationTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserBinaryOperationTests.java
new file mode 100644
index 0000000..ea2f673
--- /dev/null
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserBinaryOperationTests.java
@@ -0,0 +1,26 @@
+package org.zwobble.hobgoblin.compiler.parser;
+
+import org.junit.jupiter.api.Test;
+import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperator;
+
+import static org.zwobble.hobgoblin.compiler.ast.untyped.UntypedBinaryOperationNodeMatcher.isUntypedBinaryOperationNode;
+import static org.zwobble.hobgoblin.compiler.ast.untyped.UntypedReferenceNodeMatcher.isUntypedReferenceNode;
+import static org.zwobble.hobgoblin.compiler.parser.ParserTesting.parseString;
+import static org.zwobble.precisely.AssertThat.assertThat;
+import static org.zwobble.precisely.Matchers.equalTo;
+
+public class ParserBinaryOperationTests {
+ @Test
+ public void canParseEquality() {
+ var source = "a == b";
+
+ var node = parseString(source, Parser::parseTopLevelExpression);
+
+ assertThat(node, isUntypedBinaryOperationNode()
+ .withOperator(equalTo(UntypedBinaryOperator.EQUALS))
+ .withLeft(isUntypedReferenceNode().withName(equalTo("a")))
+ .withRight(isUntypedReferenceNode().withName(equalTo("b")))
+ );
+ }
+}
+